mirror of
https://github.com/oven-sh/bun
synced 2026-02-03 15:38:46 +00:00
Compare commits
6 Commits
ali/react
...
pfg/node-t
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
450eb55703 | ||
|
|
c93f829b54 | ||
|
|
249ef035de | ||
|
|
e4d826b608 | ||
|
|
3944334f9b | ||
|
|
0d8f0c1dd8 |
@@ -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));
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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) {
|
||||
|
||||
105
test/js/node/test/parallel/test-util-inherits.js
Normal file
105
test/js/node/test/parallel/test-util-inherits.js
Normal 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',
|
||||
});
|
||||
229
test/js/node/test/parallel/test-util-promisify.js
Normal file
229
test/js/node/test/parallel/test-util-promisify.js
Normal 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',
|
||||
});
|
||||
});
|
||||
107
test/js/node/test/parallel/test-util-styletext.js
Normal file
107
test/js/node/test/parallel/test-util-styletext.js
Normal 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');
|
||||
}
|
||||
297
test/js/node/test/parallel/test-util-types.js
Normal file
297
test/js/node/test/parallel/test-util-types.js
Normal 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());
|
||||
}
|
||||
88
test/js/node/test/parallel/test-util.js
Normal file
88
test/js/node/test/parallel/test-util.js
Normal 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({})
|
||||
});
|
||||
Reference in New Issue
Block a user