Compare commits

...

6 Commits

Author SHA1 Message Date
Jarred Sumner
450eb55703 Merge branch 'main' into pfg/node-tests-util 2024-12-12 18:51:46 -08:00
pfg
c93f829b54 test-util-types 2024-12-11 20:41:59 -08:00
pfg
249ef035de test-util 2024-12-11 20:38:31 -08:00
pfg
e4d826b608 test-util-promisify 2024-12-11 20:28:54 -08:00
pfg
3944334f9b test-util-styletext.js 2024-12-11 20:17:29 -08:00
pfg
0d8f0c1dd8 test-util-inherits 2024-12-11 19:13:22 -08:00
9 changed files with 907 additions and 42 deletions

View File

@@ -112,32 +112,6 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionIsNativeError,
if (value.isCell()) {
if (value.inherits<JSC::ErrorInstance>() || value.asCell()->type() == ErrorInstanceType)
return JSValue::encode(jsBoolean(true));
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
JSObject* object = value.toObject(globalObject);
// node util.isError relies on toString
// https://github.com/nodejs/node/blob/cf8c6994e0f764af02da4fa70bc5962142181bf3/doc/api/util.md#L2923
PropertySlot slot(object, PropertySlot::InternalMethodType::VMInquiry, &vm);
if (object->getPropertySlot(globalObject,
vm.propertyNames->toStringTagSymbol, slot)) {
EXCEPTION_ASSERT(!scope.exception());
if (slot.isValue()) {
JSValue value = slot.getValue(globalObject, vm.propertyNames->toStringTagSymbol);
if (value.isString()) {
String tag = asString(value)->value(globalObject);
if (UNLIKELY(scope.exception()))
scope.clearException();
if (tag == "Error"_s)
return JSValue::encode(jsBoolean(true));
}
}
}
JSValue proto = object->getPrototype(vm, globalObject);
if (proto.isCell() && (proto.inherits<JSC::ErrorInstance>() || proto.asCell()->type() == ErrorInstanceType || proto.inherits<JSC::ErrorPrototype>()))
return JSValue::encode(jsBoolean(true));
}
return JSValue::encode(jsBoolean(false));

View File

@@ -21,11 +21,11 @@ function defineCustomPromisifyArgs(target, args) {
}
var promisify = function promisify(original) {
if (typeof original !== "function") throw new TypeError('The "original" argument must be of type Function');
if (typeof original !== "function") throw $ERR_INVALID_ARG_TYPE("original", "function", original);
const custom = original[kCustomPromisifiedSymbol];
if (custom) {
if (typeof custom !== "function") {
throw new TypeError('The "util.promisify.custom" argument must be of type Function');
throw $ERR_INVALID_ARG_TYPE("util.promisify.custom", "function", custom);
}
// ensure that we don't create another promisified function wrapper
return defineCustomPromisify(custom, custom);
@@ -45,10 +45,10 @@ var promisify = function promisify(original) {
if (callbackArgs !== undefined && values.length > 0) {
if (!Array.isArray(callbackArgs)) {
throw new TypeError('The "customPromisifyArgs" argument must be of type Array');
throw $ERR_INVALID_ARG_TYPE("customPromisifyArgs", "callbackArgs", callbackArgs);
}
if (callbackArgs.length !== values.length) {
throw new Error("Mismatched length in promisify callback args");
throw $ERR_INVALID_ARG_TYPE("Mismatched length in promisify callback args", "callbackArgs", callbackArgs);
}
const result = {};
for (let i = 0; i < callbackArgs.length; i++) {

View File

@@ -65,6 +65,17 @@ function validateObject(value, name) {
}
hideFromStack(validateObject);
function validateOneOf(value, name, oneOf) {
if (!Array.prototype.includes.$call(oneOf, value)) {
const allowed = Array.prototype.join.$call(
Array.prototype.map.$call(oneOf, v => (typeof v === "string" ? `'${v}'` : String(v))),
", ",
);
throw $ERR_INVALID_ARG_VALUE(`The argument '${name}' must be one of: ${allowed}.`);
}
}
hideFromStack(validateOneOf);
export default {
validateObject: validateObject,
validateLinkHeaderValue: validateLinkHeaderValue,
@@ -103,4 +114,5 @@ export default {
validateUndefined: $newCppFunction("NodeValidator.cpp", "jsFunction_validateUndefined", 0),
/** `(buffer, name = 'buffer')` */
validateBuffer: $newCppFunction("NodeValidator.cpp", "jsFunction_validateBuffer", 0),
validateOneOf: validateOneOf,
};

View File

@@ -4,6 +4,7 @@ const types = require("node:util/types");
const utl = require("internal/util/inspect");
const { ERR_INVALID_ARG_TYPE, ERR_OUT_OF_RANGE } = require("internal/errors");
const { promisify } = require("internal/promisify");
const { validateString, validateBoolean, validateOneOf } = require("internal/validators");
const internalErrorName = $newZigFunction("node_util_binding.zig", "internalErrorName", 1);
@@ -147,7 +148,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-expect-error
__proto__: null,
value: superCtor,
writable: true,
configurable: true,
});
Object.setPrototypeOf(ctor.prototype, superCtor.prototype);
};
var _extend = function (origin, add) {
@@ -200,21 +207,67 @@ var toUSVString = input => {
return (input + "").toWellFormed();
};
function styleText(format, text) {
if (typeof text !== "string") {
const e = new Error(`The text argument must be of type string. Received type ${typeof text}`);
e.code = "ERR_INVALID_ARG_TYPE";
throw e;
/**
* @param {string | string[]} format
* @param {string} text
* @param {object} [options={}]
* @param {boolean} [options.validateStream=true] - Whether to validate the stream.
* @param {Stream} [options.stream=process.stdout] - The stream used for validation.
* @returns {string}
*/
function styleText(format, text, { validateStream = true, stream = process.stdout } = {}) {
validateString(text, "text");
validateBoolean(validateStream, "options.validateStream");
if (validateStream) {
if (!$isReadableStream(stream) && !$isWritableStream(stream) && !isNodeStream(stream)) {
throw $ERR_INVALID_ARG_TYPE("stream", ["ReadableStream", "WritableStream", "Stream"], stream);
}
}
if (Array.isArray(format)) {
let left = "";
let right = "";
for (const key of format) {
const formatCodes = inspect.colors[key];
if (formatCodes == null) {
validateOneOf(key, "format", Object.keys(inspect.colors));
}
left += `\x1b[${formatCodes[0]}m`;
right = `\x1b[${formatCodes[1]}m${right}`;
}
return `${left}${text}${right}`;
}
const formatCodes = inspect.colors[format];
if (formatCodes == null) {
const e = new Error(
`The value "${typeof format === "symbol" ? format.description : format}" is invalid for argument 'format'. Reason: must be one of: ${Object.keys(inspect.colors).join(", ")}`,
);
e.code = "ERR_INVALID_ARG_VALUE";
throw e;
validateOneOf(format, "format", Object.keys(inspect.colors));
}
return `\u001b[${formatCodes[0]}m${text}\u001b[${formatCodes[1]}m`;
// Check colorize only after validating arg type and value
if (validateStream && (!stream || !shouldColorize(stream))) {
return text;
}
return `\x1b[${formatCodes[0]}m${text}\x1b[${formatCodes[1]}m`;
}
function isNodeStream(obj) {
return (
obj &&
(obj._readableState ||
obj._writableState ||
(typeof obj.write === "function" && typeof obj.on === "function") ||
(typeof obj.pipe === "function" && typeof obj.on === "function"))
);
}
function shouldColorize(stream) {
if (process.env[["FORCE_", "COLOR"].join("")] !== undefined) {
return typeof process.stdout.getColorDepth === "function" ? process.stdout.getColorDepth() > 2 : true;
}
return stream?.isTTY && (typeof stream.getColorDepth === "function" ? stream.getColorDepth() > 2 : true);
}
function getSystemErrorName(err: any) {

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,229 @@
'use strict';
// Flags: --expose-internals
const common = require('../common');
const assert = require('assert');
const fs = require('fs');
const vm = require('vm');
const { promisify } = require('util');
{
const warningHandler = common.mustNotCall();
process.on('warning', warningHandler);
function foo() {}
foo.constructor = (async () => {}).constructor;
promisify(foo);
process.off('warning', warningHandler);
}
// common.expectWarning(
// 'DeprecationWarning',
// 'Calling promisify on a function that returns a Promise is likely a mistake.',
// 'DEP0174');
promisify(async (callback) => { callback(); })().then(common.mustCall(() => {
// We must add the second `expectWarning` call in the `.then` handler, when
// the first warning has already been triggered.
// common.expectWarning(
// 'DeprecationWarning',
// 'Calling promisify on a function that returns a Promise is likely a mistake.',
// 'DEP0174');
promisify(async () => {})().then(common.mustNotCall());
}));
const stat = promisify(fs.stat);
{
const promise = stat(__filename);
assert(promise instanceof Promise);
promise.then(common.mustCall((value) => {
assert.deepStrictEqual(value, fs.statSync(__filename));
}));
}
{
const promise = stat('/dontexist');
promise.catch(common.mustCall((error) => {
assert(error.message.includes('No such file or directory'));
}));
}
{
function fn() {}
function promisifedFn() {}
fn[promisify.custom] = promisifedFn;
assert.strictEqual(promisify(fn), promisifedFn);
assert.strictEqual(promisify(promisify(fn)), promisifedFn);
}
{
function fn() {}
function promisifiedFn() {}
// util.promisify.custom is a shared symbol which can be accessed
// as `Symbol.for("nodejs.util.promisify.custom")`.
const kCustomPromisifiedSymbol = Symbol.for('nodejs.util.promisify.custom');
fn[kCustomPromisifiedSymbol] = promisifiedFn;
assert.strictEqual(kCustomPromisifiedSymbol, promisify.custom);
assert.strictEqual(promisify(fn), promisifiedFn);
assert.strictEqual(promisify(promisify(fn)), promisifiedFn);
}
{
function fn() {}
fn[promisify.custom] = 42;
assert.throws(
() => promisify(fn),
{ code: 'ERR_INVALID_ARG_TYPE', name: 'TypeError' }
);
}
// {
// const firstValue = 5;
// const secondValue = 17;
// function fn(callback) {
// callback(null, firstValue, secondValue);
// }
// fn[customPromisifyArgs] = ['first', 'second'];
// promisify(fn)().then(common.mustCall((obj) => {
// assert.deepStrictEqual(obj, { first: firstValue, second: secondValue });
// }));
// }
{
const fn = vm.runInNewContext('(function() {})');
assert.notStrictEqual(Object.getPrototypeOf(promisify(fn)),
Function.prototype);
}
{
function fn(callback) {
callback(null, 'foo', 'bar');
}
promisify(fn)().then(common.mustCall((value) => {
assert.strictEqual(value, 'foo');
}));
}
{
function fn(callback) {
callback(null);
}
promisify(fn)().then(common.mustCall((value) => {
assert.strictEqual(value, undefined);
}));
}
{
function fn(callback) {
callback();
}
promisify(fn)().then(common.mustCall((value) => {
assert.strictEqual(value, undefined);
}));
}
{
function fn(err, val, callback) {
callback(err, val);
}
promisify(fn)(null, 42).then(common.mustCall((value) => {
assert.strictEqual(value, 42);
}));
}
{
function fn(err, val, callback) {
callback(err, val);
}
promisify(fn)(new Error('oops'), null).catch(common.mustCall((err) => {
assert.strictEqual(err.message, 'oops');
}));
}
{
function fn(err, val, callback) {
callback(err, val);
}
(async () => {
const value = await promisify(fn)(null, 42);
assert.strictEqual(value, 42);
})().then(common.mustCall());
}
{
const o = {};
const fn = promisify(function(cb) {
cb(null, this === o);
});
o.fn = fn;
o.fn().then(common.mustCall((val) => assert(val)));
}
{
const err = new Error('Should not have called the callback with the error.');
const stack = err.stack;
const fn = promisify(function(cb) {
cb(null);
cb(err);
});
(async () => {
await fn();
await Promise.resolve();
return assert.strictEqual(stack, err.stack);
})().then(common.mustCall());
}
{
function c() { }
const a = promisify(function() { });
const b = promisify(a);
assert.notStrictEqual(c, a);
assert.strictEqual(a, b);
}
{
let errToThrow;
const thrower = promisify(function(a, b, c, cb) {
errToThrow = new Error();
throw errToThrow;
});
thrower(1, 2, 3)
.then(assert.fail)
.then(assert.fail, (e) => assert.strictEqual(e, errToThrow));
}
{
const err = new Error();
const a = promisify((cb) => cb(err))();
const b = promisify(() => { throw err; })();
Promise.all([
a.then(assert.fail, function(e) {
assert.strictEqual(err, e);
}),
b.then(assert.fail, function(e) {
assert.strictEqual(err, e);
}),
]);
}
[undefined, null, true, 0, 'str', {}, [], Symbol()].forEach((input) => {
assert.throws(
() => promisify(input),
{
code: 'ERR_INVALID_ARG_TYPE',
name: 'TypeError',
});
});

View File

@@ -0,0 +1,107 @@
'use strict';
delete process.env["FORCE_COLOR"];
const common = require('../common');
const assert = require('node:assert');
const util = require('node:util');
const { WriteStream } = require('node:tty');
const styled = '\u001b[31mtest\u001b[39m';
const noChange = 'test';
[
undefined,
null,
false,
5n,
5,
Symbol(),
() => {},
{},
].forEach((invalidOption) => {
assert.throws(() => {
util.styleText(invalidOption, 'test');
}, {
code: 'ERR_INVALID_ARG_VALUE',
});
assert.throws(() => {
util.styleText('red', invalidOption);
}, {
code: 'ERR_INVALID_ARG_TYPE'
});
});
assert.throws(() => {
util.styleText('invalid', 'text');
}, {
code: 'ERR_INVALID_ARG_VALUE',
});
assert.strictEqual(
util.styleText('red', 'test', { validateStream: false }),
'\u001b[31mtest\u001b[39m',
);
assert.strictEqual(
util.styleText(['bold', 'red'], 'test', { validateStream: false }),
'\u001b[1m\u001b[31mtest\u001b[39m\u001b[22m',
);
assert.strictEqual(
util.styleText(['bold', 'red'], 'test', { validateStream: false }),
util.styleText(
'bold',
util.styleText('red', 'test', { validateStream: false }),
{ validateStream: false },
),
);
assert.throws(() => {
util.styleText(['invalid'], 'text');
}, {
code: 'ERR_INVALID_ARG_VALUE',
});
assert.throws(() => {
util.styleText('red', 'text', { stream: {} });
}, {
code: 'ERR_INVALID_ARG_TYPE',
});
// does not throw
util.styleText('red', 'text', { stream: {}, validateStream: false });
assert.strictEqual(
util.styleText('red', 'test', { validateStream: false }),
styled,
);
const fd = common.getTTYfd();
if (fd !== -1) {
const writeStream = new WriteStream(fd);
const originalEnv = process.env;
[
{ isTTY: true, env: {}, expected: styled },
{ isTTY: false, env: {}, expected: noChange },
{ isTTY: true, env: { NODE_DISABLE_COLORS: '1' }, expected: noChange },
{ isTTY: true, env: { NO_COLOR: '1' }, expected: noChange },
{ isTTY: true, env: { FORCE_COLOR: '1' }, expected: styled },
{ isTTY: true, env: { FORCE_COLOR: '1', NODE_DISABLE_COLORS: '1' }, expected: styled },
{ isTTY: false, env: { FORCE_COLOR: '1', NO_COLOR: '1', NODE_DISABLE_COLORS: '1' }, expected: styled },
{ isTTY: true, env: { FORCE_COLOR: '1', NO_COLOR: '1', NODE_DISABLE_COLORS: '1' }, expected: styled },
].forEach((testCase) => {
writeStream.isTTY = testCase.isTTY;
process.env = {
...process.env,
...testCase.env
};
const output = util.styleText('red', 'test', { stream: writeStream });
console.log(output);
assert.strictEqual(output, testCase.expected);
process.env = originalEnv;
});
} else {
common.skip('Could not create TTY fd');
}

View File

@@ -0,0 +1,297 @@
// Flags: --experimental-vm-modules --expose-internals
'use strict';
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]);
}
}
(async () => {
const m = new vm.SourceTextModule('');
await m.link(() => 0);
await m.evaluate();
assert.ok(types.isModuleNamespaceObject(m.namespace));
})().then(() => {throw new Error("test passes")}).catch(common.mustCall(e => {
if(e.message !== "node:vm Module is not yet implemented in Bun.") throw e;
}));
// TODO: once vm.SourceTextModule is implemented, remove the two lines above and uncomment the line below
// })().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());
}

View File

@@ -0,0 +1,88 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict';
// Flags: --expose-internals
const common = require('../common');
const assert = require('assert');
const util = require('util');
const context = require('vm').runInNewContext;
// isArray
assert.strictEqual(util.isArray([]), true);
assert.strictEqual(util.isArray(Array()), true);
assert.strictEqual(util.isArray(new Array()), true);
assert.strictEqual(util.isArray(new Array(5)), true);
assert.strictEqual(util.isArray(new Array('with', 'some', 'entries')), true);
assert.strictEqual(util.isArray(context('Array')()), true);
assert.strictEqual(util.isArray({}), false);
assert.strictEqual(util.isArray({ push: function() {} }), false);
assert.strictEqual(util.isArray(/regexp/), false);
assert.strictEqual(util.isArray(new Error()), false);
assert.strictEqual(util.isArray({ __proto__: Array.prototype }), false);
// _extend
assert.deepStrictEqual(util._extend({ a: 1 }), { a: 1 });
assert.deepStrictEqual(util._extend({ a: 1 }, []), { a: 1 });
assert.deepStrictEqual(util._extend({ a: 1 }, null), { a: 1 });
assert.deepStrictEqual(util._extend({ a: 1 }, true), { a: 1 });
assert.deepStrictEqual(util._extend({ a: 1 }, false), { a: 1 });
assert.deepStrictEqual(util._extend({ a: 1 }, { b: 2 }), { a: 1, b: 2 });
assert.deepStrictEqual(util._extend({ a: 1, b: 2 }, { b: 3 }), { a: 1, b: 3 });
assert.strictEqual(util.toUSVString('string\ud801'), 'string\ufffd');
{
assert.strictEqual(util.types.isNativeError(new Error()), true);
assert.strictEqual(util.types.isNativeError(new TypeError()), true);
assert.strictEqual(util.types.isNativeError(new SyntaxError()), true);
assert.strictEqual(util.types.isNativeError(new (context('Error'))()), true);
assert.strictEqual(
util.types.isNativeError(new (context('TypeError'))()),
true
);
assert.strictEqual(
util.types.isNativeError(new (context('SyntaxError'))()),
true
);
assert.strictEqual(util.types.isNativeError({}), false);
assert.strictEqual(
util.types.isNativeError({ name: 'Error', message: '' }),
false
);
assert.strictEqual(util.types.isNativeError([]), false);
assert.strictEqual(
util.types.isNativeError({ __proto__: Error.prototype }),
false
);
// assert.strictEqual(
// util.types.isNativeError(new errors.codes.ERR_IPC_CHANNEL_CLOSED()),
// true
// );
}
assert.throws(() => {
util.stripVTControlCharacters({});
}, {
code: 'ERR_INVALID_ARG_TYPE',
message: 'The "str" argument must be of type string.' +
common.invalidArgTypeHelper({})
});