More node tests passing (#16269)

This commit is contained in:
pfg
2025-01-10 19:51:30 -08:00
committed by GitHub
parent d9ed436321
commit 1e67665d33
11 changed files with 1075 additions and 29 deletions

View File

@@ -2607,14 +2607,18 @@ function getStringWidth(str, removeControlChars = true) {
}
// Regex used for ansi escape code splitting
// Adopted from https://github.com/chalk/ansi-regex/blob/HEAD/index.js
// License: MIT, authors: @sindresorhus, Qix-, arjunmehta and LitoMore
// Ref: https://github.com/chalk/ansi-regex/blob/f338e1814144efb950276aac84135ff86b72dc8e/index.js
// License: MIT by Sindre Sorhus <sindresorhus@gmail.com>
// Matches all ansi escape code sequences in a string
const ansiPattern =
const ansiPattern = new RegExp(
"[\\u001B\\u009B][[\\]()#;?]*" +
"(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*" +
"|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)" +
"|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))";
"(?:(?:(?:(?:;[-a-zA-Z\\d\\/\\#&.:=?%@~_]+)*" +
"|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/\\#&.:=?%@~_]*)*)?" +
"(?:\\u0007|\\u001B\\u005C|\\u009C))" +
"|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?" +
"[\\dA-PR-TZcf-nq-uy=><~]))",
"g",
);
const ansi = new RegExp(ansiPattern, "g");
/** Remove all VT control characters. Use to estimate displayed string width. */
function stripVTControlCharacters(str) {

View File

@@ -31,10 +31,12 @@ const formatWithOptions = utl.formatWithOptions;
const format = utl.format;
const stripVTControlCharacters = utl.stripVTControlCharacters;
const codesWarned = new Set();
function deprecate(fn, msg, code) {
if (process.noDeprecation === true) {
return fn;
}
if (code !== undefined) validateString(code, "code");
var warned = false;
function deprecated() {
@@ -46,7 +48,15 @@ function deprecate(fn, msg, code) {
} else if (process.traceDeprecation) {
console.trace(msg);
} else {
console.error(msg);
if (code !== undefined) {
// only warn for each code once
if (codesWarned.has(code)) {
process.emitWarning(msg, "DeprecationWarning", code);
}
codesWarned.add(code);
} else {
process.emitWarning(msg, "DeprecationWarning");
}
}
warned = true;
}
@@ -149,7 +159,13 @@ var inherits = function inherits(ctor, superCtor) {
if (superCtor.prototype === undefined) {
throw $ERR_INVALID_ARG_TYPE("superCtor.prototype", "object", superCtor.prototype);
}
ctor.super_ = superCtor;
Object.defineProperty(ctor, "super_", {
// @ts-ignore
__proto__: null,
value: superCtor,
writable: true,
configurable: true,
});
Object.setPrototypeOf(ctor.prototype, superCtor.prototype);
};
var _extend = function (origin, add) {
@@ -172,30 +188,40 @@ function callbackifyOnRejected(reason, cb) {
return cb(reason);
}
function callbackify(original) {
if (typeof original !== "function") {
throw new TypeError('The "original" argument must be of type Function');
}
function callbackified() {
var args = Array.prototype.slice.$call(arguments);
var maybeCb = args.pop();
if (typeof maybeCb !== "function") {
throw new TypeError("The last argument must be of type Function");
}
var self = this;
var cb = function () {
return maybeCb.$apply(self, arguments);
};
const { validateFunction } = require("internal/validators");
validateFunction(original, "original");
// We DO NOT return the promise as it gives the user a false sense that
// the promise is actually somehow related to the callback's execution
// and that the callback throwing will reject the promise.
function callbackified(...args) {
const maybeCb = Array.prototype.pop.$call(args);
validateFunction(maybeCb, "last argument");
const cb = Function.prototype.bind.$call(maybeCb, this);
// In true node style we process the callback on `nextTick` with all the
// implications (stack, `uncaughtException`, `async_hooks`)
original.$apply(this, args).then(
function (ret) {
process.nextTick(cb, null, ret);
},
function (rej) {
process.nextTick(callbackifyOnRejected, rej, cb);
},
ret => process.nextTick(cb, null, ret),
rej => process.nextTick(callbackifyOnRejected, rej, cb),
);
}
Object.setPrototypeOf(callbackified, Object.getPrototypeOf(original));
Object.defineProperties(callbackified, getOwnPropertyDescriptors(original));
const descriptors = Object.getOwnPropertyDescriptors(original);
// It is possible to manipulate a functions `length` or `name` property. This
// guards against the manipulation.
if (typeof descriptors.length.value === "number") {
descriptors.length.value++;
}
if (typeof descriptors.name.value === "string") {
descriptors.name.value += "Callbackified";
}
const propertiesValues = Object.values(descriptors);
for (let i = 0; i < propertiesValues.length; i++) {
// We want to use null-prototype objects to not rely on globally mutable
// %Object.prototype%.
Object.setPrototypeOf(propertiesValues[i], null);
}
Object.defineProperties(callbackified, descriptors);
return callbackified;
}
var toUSVString = input => {

View File

@@ -0,0 +1,296 @@
'use strict';
const common = require('../common');
// This test checks that the semantics of `util.callbackify` are as described in
// the API docs
const assert = require('assert');
const { callbackify } = require('util');
const { execFile } = require('child_process');
const fixtures = require('../common/fixtures');
const values = [
'hello world',
null,
undefined,
false,
0,
{},
{ key: 'value' },
Symbol('I am a symbol'),
function ok() {},
['array', 'with', 4, 'values'],
new Error('boo'),
];
{
// Test that the resolution value is passed as second argument to callback
for (const value of values) {
// Test and `async function`
async function asyncFn() {
return value;
}
const cbAsyncFn = callbackify(asyncFn);
cbAsyncFn(common.mustSucceed((ret) => {
assert.strictEqual(ret, value);
}));
// Test Promise factory
function promiseFn() {
return Promise.resolve(value);
}
const cbPromiseFn = callbackify(promiseFn);
cbPromiseFn(common.mustSucceed((ret) => {
assert.strictEqual(ret, value);
}));
// Test Thenable
function thenableFn() {
return {
then(onRes, onRej) {
onRes(value);
}
};
}
const cbThenableFn = callbackify(thenableFn);
cbThenableFn(common.mustSucceed((ret) => {
assert.strictEqual(ret, value);
}));
}
}
{
// Test that rejection reason is passed as first argument to callback
for (const value of values) {
// Test an `async function`
async function asyncFn() {
return Promise.reject(value);
}
const cbAsyncFn = callbackify(asyncFn);
assert.strictEqual(cbAsyncFn.length, 1);
assert.strictEqual(cbAsyncFn.name, 'asyncFnCallbackified');
cbAsyncFn(common.mustCall((err, ret) => {
assert.strictEqual(ret, undefined);
if (err instanceof Error) {
if ('reason' in err) {
assert(!value);
assert.strictEqual(err.code, 'ERR_FALSY_VALUE_REJECTION');
assert.strictEqual(err.reason, value);
} else {
assert.strictEqual(String(value).endsWith(err.message), true);
}
} else {
assert.strictEqual(err, value);
}
}));
// Test a Promise factory
function promiseFn() {
return Promise.reject(value);
}
const obj = {};
Object.defineProperty(promiseFn, 'name', {
value: obj,
writable: false,
enumerable: false,
configurable: true
});
const cbPromiseFn = callbackify(promiseFn);
assert.strictEqual(promiseFn.name, obj);
cbPromiseFn(common.mustCall((err, ret) => {
assert.strictEqual(ret, undefined);
if (err instanceof Error) {
if ('reason' in err) {
assert(!value);
assert.strictEqual(err.code, 'ERR_FALSY_VALUE_REJECTION');
assert.strictEqual(err.reason, value);
} else {
assert.strictEqual(String(value).endsWith(err.message), true);
}
} else {
assert.strictEqual(err, value);
}
}));
// Test Thenable
function thenableFn() {
return {
then(onRes, onRej) {
onRej(value);
}
};
}
const cbThenableFn = callbackify(thenableFn);
cbThenableFn(common.mustCall((err, ret) => {
assert.strictEqual(ret, undefined);
if (err instanceof Error) {
if ('reason' in err) {
assert(!value);
assert.strictEqual(err.code, 'ERR_FALSY_VALUE_REJECTION');
assert.strictEqual(err.reason, value);
} else {
assert.strictEqual(String(value).endsWith(err.message), true);
}
} else {
assert.strictEqual(err, value);
}
}));
}
}
{
// Test that arguments passed to callbackified function are passed to original
for (const value of values) {
async function asyncFn(arg) {
assert.strictEqual(arg, value);
return arg;
}
const cbAsyncFn = callbackify(asyncFn);
assert.strictEqual(cbAsyncFn.length, 2);
assert.notStrictEqual(
Object.getPrototypeOf(cbAsyncFn),
Object.getPrototypeOf(asyncFn)
);
assert.strictEqual(Object.getPrototypeOf(cbAsyncFn), Function.prototype);
cbAsyncFn(value, common.mustSucceed((ret) => {
assert.strictEqual(ret, value);
}));
function promiseFn(arg) {
assert.strictEqual(arg, value);
return Promise.resolve(arg);
}
const obj = {};
Object.defineProperty(promiseFn, 'length', {
value: obj,
writable: false,
enumerable: false,
configurable: true
});
const cbPromiseFn = callbackify(promiseFn);
assert.strictEqual(promiseFn.length, obj);
cbPromiseFn(value, common.mustSucceed((ret) => {
assert.strictEqual(ret, value);
}));
}
}
{
// Test that `this` binding is the same for callbackified and original
for (const value of values) {
const iAmThis = {
fn(arg) {
assert.strictEqual(this, iAmThis);
return Promise.resolve(arg);
},
};
iAmThis.cbFn = callbackify(iAmThis.fn);
iAmThis.cbFn(value, common.mustSucceed(function(ret) {
assert.strictEqual(ret, value);
assert.strictEqual(this, iAmThis);
}));
const iAmThat = {
async fn(arg) {
assert.strictEqual(this, iAmThat);
return arg;
},
};
iAmThat.cbFn = callbackify(iAmThat.fn);
iAmThat.cbFn(value, common.mustSucceed(function(ret) {
assert.strictEqual(ret, value);
assert.strictEqual(this, iAmThat);
}));
}
}
{
// Test that callback that throws emits an `uncaughtException` event
const fixture = fixtures.path('uncaught-exceptions', 'callbackify1.js');
execFile(
process.execPath,
[fixture],
common.mustCall((err, stdout, stderr) => {
assert.strictEqual(err.code, 1);
assert.strictEqual(Object.getPrototypeOf(err).name, 'Error');
assert.strictEqual(stdout, '');
const errLines = stderr.trim().split(/[\r\n]+/);
const errLine = errLines.find((l) => /^error/.exec(l));
assert.strictEqual(errLine, `error: ${fixture}`);
})
);
}
{
// Test that handled `uncaughtException` works and passes rejection reason
const fixture = fixtures.path('uncaught-exceptions', 'callbackify2.js');
execFile(
process.execPath,
[fixture],
common.mustSucceed((stdout, stderr) => {
assert.strictEqual(
stdout.trim(),
`ifError got unwanted exception: ${fixture}`);
assert.strictEqual(stderr, '');
})
);
}
{
// Verify that non-function inputs throw.
['foo', null, undefined, false, 0, {}, Symbol(), []].forEach((value) => {
assert.throws(() => {
callbackify(value);
}, {
code: 'ERR_INVALID_ARG_TYPE',
name: 'TypeError',
message: 'The "original" argument must be of type function.' +
common.invalidArgTypeHelper(value)
});
});
}
{
async function asyncFn() {
return 42;
}
const cb = callbackify(asyncFn);
const args = [];
// Verify that the last argument to the callbackified function is a function.
['foo', null, undefined, false, 0, {}, Symbol(), []].forEach((value) => {
args.push(value);
assert.throws(() => {
cb(...args);
}, {
code: 'ERR_INVALID_ARG_TYPE',
name: 'TypeError',
});
});
}
{
// Test Promise factory
function promiseFn(value) {
return Promise.reject(value);
}
const cbPromiseFn = callbackify(promiseFn);
cbPromiseFn(null, (err) => {
assert.strictEqual(err.code, 'ERR_FALSY_VALUE_REJECTION');
assert.strictEqual(err.reason, null);
// skipped, bun doesn't hide callbackifyOnRejected from the stack trace
// const stack = err.stack.split(/[\r\n]+/);
// assert.match(stack[1], /at process\.processTicksAndRejections/);
});
}

View File

@@ -0,0 +1,14 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const util = require('util');
[1, true, false, null, {}].forEach((notString) => {
assert.throws(() => util.deprecate(() => {}, 'message', notString), {
code: 'ERR_INVALID_ARG_TYPE',
name: 'TypeError',
message: 'The "code" argument must be of type string.' +
common.invalidArgTypeHelper(notString)
});
});

View File

@@ -0,0 +1,57 @@
'use strict';
require('../common');
// Tests basic functionality of util.deprecate().
const assert = require('assert');
const util = require('util');
const expectedWarnings = new Map();
// Emits deprecation only once if same function is called.
{
const msg = 'fhqwhgads';
const fn = util.deprecate(() => {}, msg);
expectedWarnings.set(msg, { code: undefined, count: 1 });
fn();
fn();
}
// Emits deprecation twice for different functions.
{
const msg = 'sterrance';
const fn1 = util.deprecate(() => {}, msg);
const fn2 = util.deprecate(() => {}, msg);
expectedWarnings.set(msg, { code: undefined, count: 2 });
fn1();
fn2();
}
// Emits deprecation only once if optional code is the same, even for different
// functions.
{
const msg = 'cannonmouth';
const code = 'deprecatesque';
const fn1 = util.deprecate(() => {}, msg, code);
const fn2 = util.deprecate(() => {}, msg, code);
expectedWarnings.set(msg, { code, count: 1 });
fn1();
fn2();
fn1();
fn2();
}
process.on('warning', (warning) => {
assert.strictEqual(warning.name, 'DeprecationWarning');
assert.ok(expectedWarnings.has(warning.message));
const expected = expectedWarnings.get(warning.message);
assert.strictEqual(warning.code, expected.code);
expected.count = expected.count - 1;
if (expected.count === 0)
expectedWarnings.delete(warning.message);
});
process.on('exit', () => {
assert.deepStrictEqual(expectedWarnings, new Map());
});

View File

@@ -0,0 +1,19 @@
'use strict';
// emitExperimentalWarning is a node internal not used by bun, so this test is skipped
// // Flags: --expose-internals
// const common = require('../common');
// const assert = require('assert');
// const { emitExperimentalWarning } = require('internal/util');
// This test ensures that the emitExperimentalWarning in internal/util emits a
// warning when passed an unsupported feature and that it simply returns
// when passed the same feature multiple times.
// process.on('warning', common.mustCall((warning) => {
// assert.match(warning.message, /is an experimental feature/);
// }, 2));
// emitExperimentalWarning('feature1');
// emitExperimentalWarning('feature1'); // should not warn
// emitExperimentalWarning('feature2');

View File

@@ -0,0 +1,105 @@
'use strict';
require('../common');
const assert = require('assert');
const { inherits } = require('util');
// Super constructor
function A() {
this._a = 'a';
}
A.prototype.a = function() { return this._a; };
// One level of inheritance
function B(value) {
A.call(this);
this._b = value;
}
inherits(B, A);
B.prototype.b = function() { return this._b; };
assert.deepStrictEqual(
Object.getOwnPropertyDescriptor(B, 'super_'),
{
value: A,
enumerable: false,
configurable: true,
writable: true
}
);
const b = new B('b');
assert.strictEqual(b.a(), 'a');
assert.strictEqual(b.b(), 'b');
assert.strictEqual(b.constructor, B);
// Two levels of inheritance
function C() {
B.call(this, 'b');
this._c = 'c';
}
inherits(C, B);
C.prototype.c = function() { return this._c; };
C.prototype.getValue = function() { return this.a() + this.b() + this.c(); };
assert.strictEqual(C.super_, B);
const c = new C();
assert.strictEqual(c.getValue(), 'abc');
assert.strictEqual(c.constructor, C);
// Inherits can be called after setting prototype properties
function D() {
C.call(this);
this._d = 'd';
}
D.prototype.d = function() { return this._d; };
inherits(D, C);
assert.strictEqual(D.super_, C);
const d = new D();
assert.strictEqual(d.c(), 'c');
assert.strictEqual(d.d(), 'd');
assert.strictEqual(d.constructor, D);
// ES6 classes can inherit from a constructor function
class E {
constructor() {
D.call(this);
this._e = 'e';
}
e() { return this._e; }
}
inherits(E, D);
assert.strictEqual(E.super_, D);
const e = new E();
assert.strictEqual(e.getValue(), 'abc');
assert.strictEqual(e.d(), 'd');
assert.strictEqual(e.e(), 'e');
assert.strictEqual(e.constructor, E);
// Should throw with invalid arguments
assert.throws(() => {
inherits(A, {});
}, {
code: 'ERR_INVALID_ARG_TYPE',
name: 'TypeError',
});
assert.throws(() => {
inherits(A, null);
}, {
code: 'ERR_INVALID_ARG_TYPE',
name: 'TypeError',
});
assert.throws(() => {
inherits(null, A);
}, {
code: 'ERR_INVALID_ARG_TYPE',
name: 'TypeError',
});

View File

@@ -0,0 +1,20 @@
'use strict';
require('../common');
// Test that huge objects don't crash due to exceeding the maximum heap size.
const util = require('util');
// Create a difficult to stringify object. Without the artificial limitation
// this would crash or throw an maximum string size error.
let last = {};
const obj = last;
for (let i = 0; i < 1000; i++) {
last.next = { circular: obj, last, obj: { a: 1, b: 2, c: true } };
last = last.next;
obj[i] = last;
}
util.inspect(obj, { depth: Infinity });

View File

@@ -0,0 +1,183 @@
// Flags: --expose-internals
'use strict';
// tests testing proxy internals are skipped, as getProxyDetails is not available in bun
require('../common');
const assert = require('assert');
const util = require('util');
// const { internalBinding } = require('internal/test/binding');
// const processUtil = internalBinding('util');
const opts = { showProxy: true };
let proxyObj;
let called = false;
const target = {
[util.inspect.custom](depth, { showProxy }) {
if (showProxy === false) {
called = true;
if (proxyObj !== this) {
throw new Error('Failed');
}
}
return [1, 2, 3];
}
};
const handler = {
getPrototypeOf() { throw new Error('getPrototypeOf'); },
setPrototypeOf() { throw new Error('setPrototypeOf'); },
isExtensible() { throw new Error('isExtensible'); },
preventExtensions() { throw new Error('preventExtensions'); },
getOwnPropertyDescriptor() { throw new Error('getOwnPropertyDescriptor'); },
defineProperty() { throw new Error('defineProperty'); },
has() { throw new Error('has'); },
get() { throw new Error('get'); },
set() { throw new Error('set'); },
deleteProperty() { throw new Error('deleteProperty'); },
ownKeys() { throw new Error('ownKeys'); },
apply() { throw new Error('apply'); },
construct() { throw new Error('construct'); }
};
proxyObj = new Proxy(target, handler);
// Inspecting the proxy should not actually walk it's properties
util.inspect(proxyObj, opts);
// Make sure inspecting object does not trigger any proxy traps.
util.format('%s', proxyObj);
// getProxyDetails is an internal method, not intended for public use.
// This is here to test that the internals are working correctly.
// let details = processUtil.getProxyDetails(proxyObj, true);
// assert.strictEqual(target, details[0]);
// assert.strictEqual(handler, details[1]);
// details = processUtil.getProxyDetails(proxyObj);
// assert.strictEqual(target, details[0]);
// assert.strictEqual(handler, details[1]);
// details = processUtil.getProxyDetails(proxyObj, false);
// assert.strictEqual(target, details);
// details = processUtil.getProxyDetails({}, true);
// assert.strictEqual(details, undefined);
const r = Proxy.revocable({}, {});
r.revoke();
// details = processUtil.getProxyDetails(r.proxy, true);
// assert.strictEqual(details[0], null);
// assert.strictEqual(details[1], null);
// details = processUtil.getProxyDetails(r.proxy, false);
// assert.strictEqual(details, null);
assert.strictEqual(util.inspect(r.proxy), '<Revoked Proxy>');
assert.strictEqual(
util.inspect(r, { showProxy: true }),
'{ proxy: <Revoked Proxy>, revoke: [Function (anonymous)] }',
);
assert.strictEqual(util.format('%s', r.proxy), '<Revoked Proxy>');
assert.strictEqual(
util.inspect(proxyObj, opts),
'Proxy [\n' +
' [ 1, 2, 3 ],\n' +
' {\n' +
' getPrototypeOf: [Function: getPrototypeOf],\n' +
' setPrototypeOf: [Function: setPrototypeOf],\n' +
' isExtensible: [Function: isExtensible],\n' +
' preventExtensions: [Function: preventExtensions],\n' +
' getOwnPropertyDescriptor: [Function: getOwnPropertyDescriptor],\n' +
' defineProperty: [Function: defineProperty],\n' +
' has: [Function: has],\n' +
' get: [Function: get],\n' +
' set: [Function: set],\n' +
' deleteProperty: [Function: deleteProperty],\n' +
' ownKeys: [Function: ownKeys],\n' +
' apply: [Function: apply],\n' +
' construct: [Function: construct]\n' +
' }\n' +
']'
);
// // Using getProxyDetails with non-proxy returns undefined
// assert.strictEqual(processUtil.getProxyDetails({}), undefined);
// Inspecting a proxy without the showProxy option set to true should not
// trigger any proxy handlers.
assert.strictEqual(util.inspect(proxyObj), '[ 1, 2, 3 ]');
assert(called);
// Yo dawg, I heard you liked Proxy so I put a Proxy
// inside your Proxy that proxies your Proxy's Proxy.
const proxy1 = new Proxy({}, {});
const proxy2 = new Proxy(proxy1, {});
const proxy3 = new Proxy(proxy2, proxy1);
const proxy4 = new Proxy(proxy1, proxy2);
const proxy5 = new Proxy(proxy3, proxy4);
const proxy6 = new Proxy(proxy5, proxy5);
const expected0 = '{}';
const expected1 = 'Proxy [ {}, {} ]';
const expected2 = 'Proxy [ Proxy [ {}, {} ], {} ]';
const expected3 = 'Proxy [ Proxy [ Proxy [ {}, {} ], {} ], Proxy [ {}, {} ] ]';
const expected4 = 'Proxy [ Proxy [ {}, {} ], Proxy [ Proxy [ {}, {} ], {} ] ]';
const expected5 = 'Proxy [\n ' +
'Proxy [ Proxy [ Proxy [Array], {} ], Proxy [ {}, {} ] ],\n' +
' Proxy [ Proxy [ {}, {} ], Proxy [ Proxy [Array], {} ] ]' +
'\n]';
const expected6 = 'Proxy [\n' +
' Proxy [\n' +
' Proxy [ Proxy [Array], Proxy [Array] ],\n' +
' Proxy [ Proxy [Array], Proxy [Array] ]\n' +
' ],\n' +
' Proxy [\n' +
' Proxy [ Proxy [Array], Proxy [Array] ],\n' +
' Proxy [ Proxy [Array], Proxy [Array] ]\n' +
' ]\n' +
']';
assert.strictEqual(
util.inspect(proxy1, { showProxy: 1, depth: null }),
expected1);
assert.strictEqual(util.inspect(proxy2, opts), expected2);
assert.strictEqual(util.inspect(proxy3, opts), expected3);
assert.strictEqual(util.inspect(proxy4, opts), expected4);
assert.strictEqual(util.inspect(proxy5, opts), expected5);
assert.strictEqual(util.inspect(proxy6, opts), expected6);
assert.strictEqual(util.inspect(proxy1), expected0);
assert.strictEqual(util.inspect(proxy2), expected0);
assert.strictEqual(util.inspect(proxy3), expected0);
assert.strictEqual(util.inspect(proxy4), expected0);
assert.strictEqual(util.inspect(proxy5), expected0);
assert.strictEqual(util.inspect(proxy6), expected0);
// Just for fun, let's create a Proxy using Arrays.
const proxy7 = new Proxy([], []);
const expected7 = 'Proxy [ [], [] ]';
assert.strictEqual(util.inspect(proxy7, opts), expected7);
assert.strictEqual(util.inspect(proxy7), '[]');
// Now we're just getting silly, right?
const proxy8 = new Proxy(Date, []);
const proxy9 = new Proxy(Date, String);
const expected8 = 'Proxy [ [Function: Date], [] ]';
const expected9 = 'Proxy [ [Function: Date], [Function: String] ]';
assert.strictEqual(util.inspect(proxy8, opts), expected8);
assert.strictEqual(util.inspect(proxy9, opts), expected9);
assert.strictEqual(util.inspect(proxy8), '[Function: Date]');
assert.strictEqual(util.inspect(proxy9), '[Function: Date]');
const proxy10 = new Proxy(() => {}, {});
const proxy11 = new Proxy(() => {}, {
get() {
return proxy11;
},
apply() {
return proxy11;
}
});
const expected10 = '[Function (anonymous)]';
const expected11 = '[Function (anonymous)]';
assert.strictEqual(util.inspect(proxy10), expected10);
assert.strictEqual(util.inspect(proxy11), expected11);

View File

@@ -0,0 +1,26 @@
'use strict';
require('../common');
const util = require('util');
const assert = require('node:assert');
// Ref: https://github.com/chalk/ansi-regex/blob/main/test.js
const tests = [
// [before, expected]
['\u001B[0m\u001B[4m\u001B[42m\u001B[31mfoo\u001B[39m\u001B[49m\u001B[24mfoo\u001B[0m', 'foofoo'], // Basic ANSI
['\u001B[0;33;49;3;9;4mbar\u001B[0m', 'bar'], // Advanced colors
['foo\u001B[0gbar', 'foobar'], // Clear tabs
['foo\u001B[Kbar', 'foobar'], // Clear line
['foo\u001B[2Jbar', 'foobar'], // Clear screen
];
for (const ST of ['\u0007', '\u001B\u005C', '\u009C']) {
tests.push(
[`\u001B]8;;mailto:no-replay@mail.com${ST}mail\u001B]8;;${ST}`, 'mail'],
[`\u001B]8;k=v;https://example-a.com/?a_b=1&c=2#tit%20le${ST}click\u001B]8;;${ST}`, 'click'],
);
}
for (const [before, expected] of tests) {
assert.strictEqual(util.stripVTControlCharacters(before), expected);
}

View File

@@ -0,0 +1,296 @@
'use strict';
// JSStream is disabled because it is a node internal
// vm tests are skipped because node:vm Module is not yet implemented
// // Flags: --experimental-vm-modules --expose-internals
const common = require('../common');
const assert = require('assert');
const { types, inspect } = require('util');
const vm = require('vm');
// const { internalBinding } = require('internal/test/binding');
// const { JSStream } = internalBinding('js_stream');
// const external = (new JSStream())._externalStream;
for (const [ value, _method ] of [
// [ external, 'isExternal' ],
[ new Date() ],
[ (function() { return arguments; })(), 'isArgumentsObject' ],
[ new Boolean(), 'isBooleanObject' ],
[ new Number(), 'isNumberObject' ],
[ new String(), 'isStringObject' ],
[ Object(Symbol()), 'isSymbolObject' ],
[ Object(BigInt(0)), 'isBigIntObject' ],
[ new Error(), 'isNativeError' ],
[ new RegExp() ],
[ async function() {}, 'isAsyncFunction' ],
[ function*() {}, 'isGeneratorFunction' ],
[ (function*() {})(), 'isGeneratorObject' ],
[ Promise.resolve() ],
[ new Map() ],
[ new Set() ],
[ (new Map())[Symbol.iterator](), 'isMapIterator' ],
[ (new Set())[Symbol.iterator](), 'isSetIterator' ],
[ new WeakMap() ],
[ new WeakSet() ],
[ new ArrayBuffer() ],
[ new Uint8Array() ],
[ new Uint8ClampedArray() ],
[ new Uint16Array() ],
[ new Uint32Array() ],
[ new Int8Array() ],
[ new Int16Array() ],
[ new Int32Array() ],
[ new Float32Array() ],
[ new Float64Array() ],
[ new BigInt64Array() ],
[ new BigUint64Array() ],
[ Object.defineProperty(new Uint8Array(),
Symbol.toStringTag,
{ value: 'foo' }) ],
[ new DataView(new ArrayBuffer()) ],
[ new SharedArrayBuffer() ],
[ new Proxy({}, {}), 'isProxy' ],
]) {
const method = _method || `is${value.constructor.name}`;
assert(method in types, `Missing ${method} for ${inspect(value)}`);
assert(types[method](value), `Want ${inspect(value)} to match ${method}`);
for (const key of Object.keys(types)) {
if ((types.isArrayBufferView(value) ||
types.isAnyArrayBuffer(value)) && key.includes('Array') ||
key === 'isBoxedPrimitive') {
continue;
}
assert.strictEqual(types[key](value),
key === method,
`${inspect(value)}: ${key}, ` +
`${method}, ${types[key](value)}`);
}
}
// Check boxed primitives.
[
new Boolean(),
new Number(),
new String(),
Object(Symbol()),
Object(BigInt(0)),
].forEach((entry) => assert(types.isBoxedPrimitive(entry)));
{
assert(!types.isUint8Array({ [Symbol.toStringTag]: 'Uint8Array' }));
assert(types.isUint8Array(vm.runInNewContext('new Uint8Array')));
assert(!types.isUint8ClampedArray({
[Symbol.toStringTag]: 'Uint8ClampedArray'
}));
assert(types.isUint8ClampedArray(
vm.runInNewContext('new Uint8ClampedArray')
));
assert(!types.isUint16Array({ [Symbol.toStringTag]: 'Uint16Array' }));
assert(types.isUint16Array(vm.runInNewContext('new Uint16Array')));
assert(!types.isUint32Array({ [Symbol.toStringTag]: 'Uint32Array' }));
assert(types.isUint32Array(vm.runInNewContext('new Uint32Array')));
assert(!types.isInt8Array({ [Symbol.toStringTag]: 'Int8Array' }));
assert(types.isInt8Array(vm.runInNewContext('new Int8Array')));
assert(!types.isInt16Array({ [Symbol.toStringTag]: 'Int16Array' }));
assert(types.isInt16Array(vm.runInNewContext('new Int16Array')));
assert(!types.isInt32Array({ [Symbol.toStringTag]: 'Int32Array' }));
assert(types.isInt32Array(vm.runInNewContext('new Int32Array')));
assert(!types.isFloat32Array({ [Symbol.toStringTag]: 'Float32Array' }));
assert(types.isFloat32Array(vm.runInNewContext('new Float32Array')));
assert(!types.isFloat64Array({ [Symbol.toStringTag]: 'Float64Array' }));
assert(types.isFloat64Array(vm.runInNewContext('new Float64Array')));
assert(!types.isBigInt64Array({ [Symbol.toStringTag]: 'BigInt64Array' }));
assert(types.isBigInt64Array(vm.runInNewContext('new BigInt64Array')));
assert(!types.isBigUint64Array({ [Symbol.toStringTag]: 'BigUint64Array' }));
assert(types.isBigUint64Array(vm.runInNewContext('new BigUint64Array')));
}
{
const primitive = true;
const arrayBuffer = new ArrayBuffer();
const buffer = Buffer.from(arrayBuffer);
const dataView = new DataView(arrayBuffer);
const uint8Array = new Uint8Array(arrayBuffer);
const uint8ClampedArray = new Uint8ClampedArray(arrayBuffer);
const uint16Array = new Uint16Array(arrayBuffer);
const uint32Array = new Uint32Array(arrayBuffer);
const int8Array = new Int8Array(arrayBuffer);
const int16Array = new Int16Array(arrayBuffer);
const int32Array = new Int32Array(arrayBuffer);
const float32Array = new Float32Array(arrayBuffer);
const float64Array = new Float64Array(arrayBuffer);
const bigInt64Array = new BigInt64Array(arrayBuffer);
const bigUint64Array = new BigUint64Array(arrayBuffer);
const fakeBuffer = { __proto__: Buffer.prototype };
const fakeDataView = { __proto__: DataView.prototype };
const fakeUint8Array = { __proto__: Uint8Array.prototype };
const fakeUint8ClampedArray = { __proto__: Uint8ClampedArray.prototype };
const fakeUint16Array = { __proto__: Uint16Array.prototype };
const fakeUint32Array = { __proto__: Uint32Array.prototype };
const fakeInt8Array = { __proto__: Int8Array.prototype };
const fakeInt16Array = { __proto__: Int16Array.prototype };
const fakeInt32Array = { __proto__: Int32Array.prototype };
const fakeFloat32Array = { __proto__: Float32Array.prototype };
const fakeFloat64Array = { __proto__: Float64Array.prototype };
const fakeBigInt64Array = { __proto__: BigInt64Array.prototype };
const fakeBigUint64Array = { __proto__: BigUint64Array.prototype };
const stealthyDataView =
Object.setPrototypeOf(new DataView(arrayBuffer), Uint8Array.prototype);
const stealthyUint8Array =
Object.setPrototypeOf(new Uint8Array(arrayBuffer), ArrayBuffer.prototype);
const stealthyUint8ClampedArray =
Object.setPrototypeOf(
new Uint8ClampedArray(arrayBuffer), ArrayBuffer.prototype
);
const stealthyUint16Array =
Object.setPrototypeOf(new Uint16Array(arrayBuffer), Uint16Array.prototype);
const stealthyUint32Array =
Object.setPrototypeOf(new Uint32Array(arrayBuffer), Uint32Array.prototype);
const stealthyInt8Array =
Object.setPrototypeOf(new Int8Array(arrayBuffer), Int8Array.prototype);
const stealthyInt16Array =
Object.setPrototypeOf(new Int16Array(arrayBuffer), Int16Array.prototype);
const stealthyInt32Array =
Object.setPrototypeOf(new Int32Array(arrayBuffer), Int32Array.prototype);
const stealthyFloat32Array =
Object.setPrototypeOf(
new Float32Array(arrayBuffer), Float32Array.prototype
);
const stealthyFloat64Array =
Object.setPrototypeOf(
new Float64Array(arrayBuffer), Float64Array.prototype
);
const stealthyBigInt64Array =
Object.setPrototypeOf(
new BigInt64Array(arrayBuffer), BigInt64Array.prototype
);
const stealthyBigUint64Array =
Object.setPrototypeOf(
new BigUint64Array(arrayBuffer), BigUint64Array.prototype
);
const all = [
primitive, arrayBuffer, buffer, fakeBuffer,
dataView, fakeDataView, stealthyDataView,
uint8Array, fakeUint8Array, stealthyUint8Array,
uint8ClampedArray, fakeUint8ClampedArray, stealthyUint8ClampedArray,
uint16Array, fakeUint16Array, stealthyUint16Array,
uint32Array, fakeUint32Array, stealthyUint32Array,
int8Array, fakeInt8Array, stealthyInt8Array,
int16Array, fakeInt16Array, stealthyInt16Array,
int32Array, fakeInt32Array, stealthyInt32Array,
float32Array, fakeFloat32Array, stealthyFloat32Array,
float64Array, fakeFloat64Array, stealthyFloat64Array,
bigInt64Array, fakeBigInt64Array, stealthyBigInt64Array,
bigUint64Array, fakeBigUint64Array, stealthyBigUint64Array,
];
const expected = {
isArrayBufferView: [
buffer,
dataView, stealthyDataView,
uint8Array, stealthyUint8Array,
uint8ClampedArray, stealthyUint8ClampedArray,
uint16Array, stealthyUint16Array,
uint32Array, stealthyUint32Array,
int8Array, stealthyInt8Array,
int16Array, stealthyInt16Array,
int32Array, stealthyInt32Array,
float32Array, stealthyFloat32Array,
float64Array, stealthyFloat64Array,
bigInt64Array, stealthyBigInt64Array,
bigUint64Array, stealthyBigUint64Array,
],
isTypedArray: [
buffer,
uint8Array, stealthyUint8Array,
uint8ClampedArray, stealthyUint8ClampedArray,
uint16Array, stealthyUint16Array,
uint32Array, stealthyUint32Array,
int8Array, stealthyInt8Array,
int16Array, stealthyInt16Array,
int32Array, stealthyInt32Array,
float32Array, stealthyFloat32Array,
float64Array, stealthyFloat64Array,
bigInt64Array, stealthyBigInt64Array,
bigUint64Array, stealthyBigUint64Array,
],
isUint8Array: [
buffer, uint8Array, stealthyUint8Array,
],
isUint8ClampedArray: [
uint8ClampedArray, stealthyUint8ClampedArray,
],
isUint16Array: [
uint16Array, stealthyUint16Array,
],
isUint32Array: [
uint32Array, stealthyUint32Array,
],
isInt8Array: [
int8Array, stealthyInt8Array,
],
isInt16Array: [
int16Array, stealthyInt16Array,
],
isInt32Array: [
int32Array, stealthyInt32Array,
],
isFloat32Array: [
float32Array, stealthyFloat32Array,
],
isFloat64Array: [
float64Array, stealthyFloat64Array,
],
isBigInt64Array: [
bigInt64Array, stealthyBigInt64Array,
],
isBigUint64Array: [
bigUint64Array, stealthyBigUint64Array,
]
};
for (const testedFunc of Object.keys(expected)) {
const func = types[testedFunc];
const yup = [];
for (const value of all) {
if (func(value)) {
yup.push(value);
}
}
console.log('Testing', testedFunc);
assert.deepStrictEqual(yup, expected[testedFunc]);
}
}
// (skipped)
// (async () => {
// const m = new vm.SourceTextModule('');
// await m.link(() => 0);
// await m.evaluate();
// assert.ok(types.isModuleNamespaceObject(m.namespace));
// })().then(common.mustCall());
{
// eslint-disable-next-line node-core/crypto-check
if (common.hasCrypto) {
const crypto = require('crypto');
assert.ok(!types.isKeyObject(crypto.createHash('sha1')));
}
assert.ok(!types.isCryptoKey());
assert.ok(!types.isKeyObject());
}