util: refactor to use more primordials

PR-URL: https://github.com/nodejs/node/pull/36265
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
This commit is contained in:
Antoine du Hamel 2020-11-16 16:39:28 +01:00 committed by Node.js GitHub Bot
parent d146b25928
commit ecdff81684
6 changed files with 162 additions and 97 deletions

View File

@ -3,8 +3,11 @@
const {
ArrayFrom,
ArrayIsArray,
ArrayPrototypePop,
ArrayPrototypePush,
ArrayPrototypeSlice,
ArrayPrototypeSort,
Error,
Map,
ObjectCreate,
ObjectDefineProperties,
ObjectDefineProperty,
@ -13,8 +16,14 @@ const {
ObjectGetPrototypeOf,
ObjectSetPrototypeOf,
Promise,
ReflectApply,
ReflectConstruct,
Set,
RegExpPrototypeTest,
SafeMap,
SafeSet,
StringPrototypeReplace,
StringPrototypeToLowerCase,
StringPrototypeToUpperCase,
Symbol,
SymbolFor,
} = primordials;
@ -40,12 +49,12 @@ const { isNativeError } = internalBinding('types');
const noCrypto = !process.versions.openssl;
const experimentalWarnings = new Set();
const experimentalWarnings = new SafeSet();
const colorRegExp = /\u001b\[\d\d?m/g; // eslint-disable-line no-control-regex
function removeColors(str) {
return str.replace(colorRegExp, '');
return StringPrototypeReplace(str, colorRegExp, '');
}
function isError(e) {
@ -57,7 +66,7 @@ function isError(e) {
// Keep a list of deprecation codes that have been warned on so we only warn on
// each one once.
const codesWarned = new Set();
const codesWarned = new SafeSet();
// Mark that a method should not be used.
// Returns a modified function which warns once by default.
@ -86,7 +95,7 @@ function deprecate(fn, msg, code) {
if (new.target) {
return ReflectConstruct(fn, args, new.target);
}
return fn.apply(this, args);
return ReflectApply(fn, this, args);
}
// The wrapper will keep the same prototype as fn to maintain prototype chain
@ -132,12 +141,13 @@ function slowCases(enc) {
case 4:
if (enc === 'UTF8') return 'utf8';
if (enc === 'ucs2' || enc === 'UCS2') return 'utf16le';
enc = `${enc}`.toLowerCase();
enc = StringPrototypeToLowerCase(`${enc}`);
if (enc === 'utf8') return 'utf8';
if (enc === 'ucs2') return 'utf16le';
break;
case 3:
if (enc === 'hex' || enc === 'HEX' || `${enc}`.toLowerCase() === 'hex')
if (enc === 'hex' || enc === 'HEX' ||
StringPrototypeToLowerCase(`${enc}`) === 'hex')
return 'hex';
break;
case 5:
@ -146,7 +156,7 @@ function slowCases(enc) {
if (enc === 'UTF-8') return 'utf8';
if (enc === 'ASCII') return 'ascii';
if (enc === 'UCS-2') return 'utf16le';
enc = `${enc}`.toLowerCase();
enc = StringPrototypeToLowerCase(`${enc}`);
if (enc === 'utf-8') return 'utf8';
if (enc === 'ascii') return 'ascii';
if (enc === 'ucs-2') return 'utf16le';
@ -156,18 +166,18 @@ function slowCases(enc) {
if (enc === 'latin1' || enc === 'binary') return 'latin1';
if (enc === 'BASE64') return 'base64';
if (enc === 'LATIN1' || enc === 'BINARY') return 'latin1';
enc = `${enc}`.toLowerCase();
enc = StringPrototypeToLowerCase(`${enc}`);
if (enc === 'base64') return 'base64';
if (enc === 'latin1' || enc === 'binary') return 'latin1';
break;
case 7:
if (enc === 'utf16le' || enc === 'UTF16LE' ||
`${enc}`.toLowerCase() === 'utf16le')
StringPrototypeToLowerCase(`${enc}`) === 'utf16le')
return 'utf16le';
break;
case 8:
if (enc === 'utf-16le' || enc === 'UTF-16LE' ||
`${enc}`.toLowerCase() === 'utf-16le')
StringPrototypeToLowerCase(`${enc}`) === 'utf-16le')
return 'utf16le';
break;
default:
@ -184,17 +194,17 @@ function emitExperimentalWarning(feature) {
}
function filterDuplicateStrings(items, low) {
const map = new Map();
const map = new SafeMap();
for (let i = 0; i < items.length; i++) {
const item = items[i];
const key = item.toLowerCase();
const key = StringPrototypeToLowerCase(item);
if (low) {
map.set(key, key);
} else {
map.set(key, item);
}
}
return ArrayFrom(map.values()).sort();
return ArrayPrototypeSort(ArrayFrom(map.values()));
}
function cachedResult(fn) {
@ -202,7 +212,7 @@ function cachedResult(fn) {
return () => {
if (result === undefined)
result = fn();
return result.slice();
return ArrayPrototypeSlice(result);
};
}
@ -244,7 +254,7 @@ function convertToValidSignal(signal) {
return signal;
if (typeof signal === 'string') {
const signalName = signals[signal.toUpperCase()];
const signalName = signals[StringPrototypeToUpperCase(signal)];
if (signalName) return signalName;
}
@ -294,7 +304,7 @@ function promisify(original) {
function fn(...args) {
return new Promise((resolve, reject) => {
original.call(this, ...args, (err, ...values) => {
ArrayPrototypePush(args, (err, ...values) => {
if (err) {
return reject(err);
}
@ -307,6 +317,7 @@ function promisify(original) {
resolve(values[0]);
}
});
ReflectApply(original, this, args);
});
}
@ -343,7 +354,7 @@ function join(output, separator) {
function spliceOne(list, index) {
for (; index + 1 < list.length; index++)
list[index] = list[index + 1];
list.pop();
ArrayPrototypePop(list);
}
const kNodeModulesRE = /^(.*)[\\/]node_modules[\\/]/;
@ -376,9 +387,9 @@ function isInsideNodeModules() {
const filename = frame.getFileName();
// If a filename does not start with / or contain \,
// it's likely from Node.js core.
if (!/^\/|\\/.test(filename))
if (!RegExpPrototypeTest(/^\/|\\/, filename))
continue;
return kNodeModulesRE.test(filename);
return RegExpPrototypeTest(kNodeModulesRE, filename);
}
}
return false;
@ -389,7 +400,7 @@ function once(callback) {
return function(...args) {
if (called) return;
called = true;
callback.apply(this, args);
ReflectApply(callback, this, args);
};
}

View File

@ -2,11 +2,12 @@
const {
ArrayIsArray,
ArrayPrototypeFilter,
ArrayPrototypePush,
BigIntPrototypeValueOf,
BooleanPrototypeValueOf,
DatePrototypeGetTime,
Error,
Map,
NumberIsNaN,
NumberPrototypeValueOf,
ObjectGetOwnPropertySymbols,
@ -16,10 +17,11 @@ const {
ObjectPrototypeHasOwnProperty,
ObjectPrototypePropertyIsEnumerable,
ObjectPrototypeToString,
Set,
SafeMap,
SafeSet,
StringPrototypeValueOf,
SymbolPrototypeValueOf,
SymbolToStringTag,
TypedArrayPrototypeGetSymbolToStringTag,
Uint8Array,
} = primordials;
@ -126,7 +128,7 @@ function isEqualBoxedPrimitive(val1, val2) {
function isIdenticalTypedArrayType(a, b) {
// Fast path to reduce type checks in the common case.
const check = types[`is${a[SymbolToStringTag]}`];
const check = types[`is${TypedArrayPrototypeGetSymbolToStringTag(a)}`];
if (check !== undefined && check(a)) {
return check(b);
}
@ -150,8 +152,9 @@ function isIdenticalTypedArrayType(a, b) {
}
/* c8 ignore next 4 */
assert.fail(
`Unknown TypedArray type checking ${a[SymbolToStringTag]} ${a}\n` +
`and ${b[SymbolToStringTag]} ${b}`
'Unknown TypedArray type checking ' +
`${TypedArrayPrototypeGetSymbolToStringTag(a)} ${a}\n` +
`and ${TypedArrayPrototypeGetSymbolToStringTag(b)} ${b}`
);
}
@ -291,7 +294,10 @@ function innerDeepEqual(val1, val2, strict, memos) {
}
function getEnumerables(val, keys) {
return keys.filter((k) => ObjectPrototypePropertyIsEnumerable(val, k));
return ArrayPrototypeFilter(
keys,
(k) => ObjectPrototypePropertyIsEnumerable(val, k)
);
}
function keyCheck(val1, val2, strict, memos, iterationType, aKeys) {
@ -330,7 +336,7 @@ function keyCheck(val1, val2, strict, memos, iterationType, aKeys) {
if (!ObjectPrototypePropertyIsEnumerable(val2, key)) {
return false;
}
aKeys.push(key);
ArrayPrototypePush(aKeys, key);
count++;
} else if (ObjectPrototypePropertyIsEnumerable(val2, key)) {
return false;
@ -360,8 +366,8 @@ function keyCheck(val1, val2, strict, memos, iterationType, aKeys) {
// Use memos to handle cycles.
if (memos === undefined) {
memos = {
val1: new Map(),
val2: new Map(),
val1: new SafeMap(),
val2: new SafeMap(),
position: 0
};
} else {
@ -458,7 +464,7 @@ function setEquiv(a, b, strict, memo) {
// to check this improves the worst case scenario instead.
if (typeof val === 'object' && val !== null) {
if (set === null) {
set = new Set();
set = new SafeSet();
}
// If the specified value doesn't exist in the second set its an not null
// object (or non strict only: a not matching primitive) we'll need to go
@ -475,7 +481,7 @@ function setEquiv(a, b, strict, memo) {
}
if (set === null) {
set = new Set();
set = new SafeSet();
}
set.add(val);
}
@ -521,7 +527,7 @@ function mapEquiv(a, b, strict, memo) {
for (const [key, item1] of a) {
if (typeof key === 'object' && key !== null) {
if (set === null) {
set = new Set();
set = new SafeSet();
}
set.add(key);
} else {
@ -537,7 +543,7 @@ function mapEquiv(a, b, strict, memo) {
if (!mapMightHaveLoosePrim(a, b, key, item1, memo))
return false;
if (set === null) {
set = new Set();
set = new SafeSet();
}
set.add(key);
}

View File

@ -1,13 +1,15 @@
'use strict';
const {
FunctionPrototype,
FunctionPrototypeBind,
ObjectCreate,
ObjectDefineProperty,
RegExp,
RegExpPrototypeTest,
SafeArrayIterator,
StringPrototypeToUpperCase
StringPrototypeToLowerCase,
StringPrototypeToUpperCase,
} = primordials;
const { inspect, format, formatWithOptions } = require('internal/util/inspect');
@ -37,13 +39,13 @@ function initializeDebugEnv(debugEnv) {
function emitWarningIfNeeded(set) {
if ('HTTP' === set || 'HTTP2' === set) {
process.emitWarning('Setting the NODE_DEBUG environment variable ' +
'to \'' + set.toLowerCase() + '\' can expose sensitive ' +
'to \'' + StringPrototypeToLowerCase(set) + '\' can expose sensitive ' +
'data (such as passwords, tokens and authentication headers) ' +
'in the resulting log.');
}
}
function noop() {}
const noop = FunctionPrototype;
function debuglogImpl(enabled, set) {
if (debugImpls[set] === undefined) {

View File

@ -3,6 +3,10 @@
const {
Array,
ArrayIsArray,
ArrayPrototypeFilter,
ArrayPrototypePush,
ArrayPrototypeSort,
ArrayPrototypeUnshift,
BigIntPrototypeValueOf,
BooleanPrototypeValueOf,
DatePrototypeGetTime,
@ -12,7 +16,6 @@ const {
FunctionPrototypeCall,
FunctionPrototypeToString,
JSONStringify,
Map,
MapPrototypeGetSize,
MapPrototypeEntries,
MathFloor,
@ -39,14 +42,27 @@ const {
ObjectPrototypePropertyIsEnumerable,
ObjectSeal,
ObjectSetPrototypeOf,
ReflectApply,
RegExp,
RegExpPrototypeTest,
RegExpPrototypeToString,
SafeStringIterator,
Set,
SafeMap,
SafeSet,
SetPrototypeGetSize,
SetPrototypeValues,
String,
StringPrototypeCharCodeAt,
StringPrototypeCodePointAt,
StringPrototypeIncludes,
StringPrototypeNormalize,
StringPrototypePadEnd,
StringPrototypePadStart,
StringPrototypeRepeat,
StringPrototypeReplace,
StringPrototypeSlice,
StringPrototypeSplit,
StringPrototypeToLowerCase,
StringPrototypeTrim,
StringPrototypeValueOf,
SymbolPrototypeToString,
SymbolPrototypeValueOf,
@ -120,8 +136,11 @@ const { NativeModule } = require('internal/bootstrap/loaders');
let hexSlice;
const builtInObjects = new Set(
ObjectGetOwnPropertyNames(global).filter((e) => /^[A-Z][a-zA-Z0-9]+$/.test(e))
const builtInObjects = new SafeSet(
ArrayPrototypeFilter(
ObjectGetOwnPropertyNames(global),
(e) => RegExpPrototypeTest(/^[A-Z][a-zA-Z0-9]+$/, e)
)
);
// https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot
@ -430,7 +449,7 @@ function addQuotes(str, quotes) {
return `'${str}'`;
}
const escapeFn = (str) => meta[str.charCodeAt(0)];
const escapeFn = (str) => meta[StringPrototypeCharCodeAt(str)];
// Escape control characters, single quotes and the backslash.
// This is similar to JSON stringify escaping.
@ -458,10 +477,10 @@ function strEscape(str) {
}
// Some magic numbers that worked out fine while benchmarking with v8 6.0
if (str.length < 5000 && !escapeTest.test(str))
if (str.length < 5000 && !RegExpPrototypeTest(escapeTest, str))
return addQuotes(str, singleQuote);
if (str.length > 100) {
str = str.replace(escapeReplace, escapeFn);
str = StringPrototypeReplace(str, escapeReplace, escapeFn);
return addQuotes(str, singleQuote);
}
@ -477,14 +496,14 @@ function strEscape(str) {
if (last === i) {
result += meta[point];
} else {
result += `${str.slice(last, i)}${meta[point]}`;
result += `${StringPrototypeSlice(str, last, i)}${meta[point]}`;
}
last = i + 1;
}
}
if (last !== lastIndex) {
result += str.slice(last);
result += StringPrototypeSlice(str, last);
}
return addQuotes(result, singleQuote);
}
@ -588,7 +607,7 @@ function addPrototypeProperties(ctx, main, obj, recurseTimes, output) {
}
if (depth === 0) {
keySet = new Set();
keySet = new SafeSet();
} else {
keys.forEach((key) => keySet.add(key));
}
@ -661,7 +680,7 @@ function getKeys(value, showHidden) {
}
if (symbols.length !== 0) {
const filter = (key) => ObjectPrototypePropertyIsEnumerable(value, key);
keys.push(...symbols.filter(filter));
ArrayPrototypePush(keys, ...ArrayPrototypeFilter(symbols, filter));
}
}
return keys;
@ -751,7 +770,8 @@ function formatValue(ctx, value, recurseTimes, typedArray) {
if (ctx.seen.includes(value)) {
let index = 1;
if (ctx.circular === undefined) {
ctx.circular = new Map([[value, index]]);
ctx.circular = new SafeMap();
ctx.circular.set(value, index);
} else {
index = ctx.circular.get(value);
if (index === undefined) {
@ -924,11 +944,11 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
`{ byteLength: ${formatNumber(ctx.stylize, value.byteLength)} }`;
}
braces[0] = `${prefix}{`;
keys.unshift('byteLength');
ArrayPrototypeUnshift(keys, 'byteLength');
} else if (isDataView(value)) {
braces[0] = `${getPrefix(constructor, tag, 'DataView')}{`;
// .buffer goes last, it's not a primitive like the others.
keys.unshift('byteLength', 'byteOffset', 'buffer');
ArrayPrototypeUnshift(keys, 'byteLength', 'byteOffset', 'buffer');
} else if (isPromise(value)) {
braces[0] = `${getPrefix(constructor, tag, 'Promise')}{`;
formatter = formatPromise;
@ -1072,7 +1092,7 @@ function getBoxedBase(value, ctx, keys, constructor, tag) {
}
if (keys.length !== 0 || ctx.stylize === stylizeNoColor)
return base;
return ctx.stylize(base, type.toLowerCase());
return ctx.stylize(base, StringPrototypeToLowerCase(type));
}
function getClassBase(value, constructor, tag) {
@ -1287,11 +1307,11 @@ function groupArrayElements(ctx, output, value) {
lineMaxLength += separatorSpace;
maxLineLength[i] = lineMaxLength;
}
let order = 'padStart';
let order = StringPrototypePadStart;
if (value !== undefined) {
for (let i = 0; i < output.length; i++) {
if (typeof value[i] !== 'number' && typeof value[i] !== 'bigint') {
order = 'padEnd';
order = StringPrototypePadEnd;
break;
}
}
@ -1307,21 +1327,21 @@ function groupArrayElements(ctx, output, value) {
// done line by line as some lines might contain more colors than
// others.
const padding = maxLineLength[j - i] + output[j].length - dataLen[j];
str += `${output[j]}, `[order](padding, ' ');
str += order(`${output[j]}, `, padding, ' ');
}
if (order === 'padStart') {
if (order === StringPrototypePadStart) {
const padding = maxLineLength[j - i] +
output[j].length -
dataLen[j] -
separatorSpace;
str += output[j].padStart(padding, ' ');
str += StringPrototypePadStart(output[j], padding, ' ');
} else {
str += output[j];
}
tmp.push(str);
ArrayPrototypePush(tmp, str);
}
if (ctx.maxArrayLength < output.length) {
tmp.push(output[outputLength]);
ArrayPrototypePush(tmp, output[outputLength]);
}
output = tmp;
}
@ -1458,8 +1478,9 @@ function formatArrayBuffer(ctx, value) {
}
if (hexSlice === undefined)
hexSlice = uncurryThis(require('buffer').Buffer.prototype.hexSlice);
let str = hexSlice(buffer, 0, MathMin(ctx.maxArrayLength, buffer.length))
.replace(/(.{2})/g, '$1 ').trim();
let str = StringPrototypeTrim(StringPrototypeReplace(
hexSlice(buffer, 0, MathMin(ctx.maxArrayLength, buffer.length)),
/(.{2})/g, '$1 '));
const remaining = buffer.length - ctx.maxArrayLength;
if (remaining > 0)
str += ` ... ${remaining} more byte${remaining > 1 ? 's' : ''}`;
@ -1508,7 +1529,7 @@ function formatTypedArray(value, length, ctx, ignored, recurseTimes) {
'buffer'
]) {
const str = formatValue(ctx, value[key], recurseTimes, true);
output.push(`[${key}]: ${str}`);
ArrayPrototypePush(output, `[${key}]: ${str}`);
}
ctx.indentationLvl -= 2;
}
@ -1519,7 +1540,7 @@ function formatSet(value, ctx, ignored, recurseTimes) {
const output = [];
ctx.indentationLvl += 2;
for (const v of value) {
output.push(formatValue(ctx, v, recurseTimes));
ArrayPrototypePush(output, formatValue(ctx, v, recurseTimes));
}
ctx.indentationLvl -= 2;
return output;
@ -1539,7 +1560,7 @@ function formatMap(value, ctx, ignored, recurseTimes) {
function formatSetIterInner(ctx, recurseTimes, entries, state) {
const maxArrayLength = MathMax(ctx.maxArrayLength, 0);
const maxLength = MathMin(maxArrayLength, entries.length);
let output = new Array(maxLength);
const output = new Array(maxLength);
ctx.indentationLvl += 2;
for (let i = 0; i < maxLength; i++) {
output[i] = formatValue(ctx, entries[i], recurseTimes);
@ -1549,11 +1570,12 @@ function formatSetIterInner(ctx, recurseTimes, entries, state) {
// Sort all entries to have a halfway reliable output (if more entries than
// retrieved ones exist, we can not reliably return the same output) if the
// output is not sorted anyway.
output = output.sort();
ArrayPrototypeSort(output);
}
const remaining = entries.length - maxLength;
if (remaining > 0) {
output.push(`... ${remaining} more item${remaining > 1 ? 's' : ''}`);
ArrayPrototypePush(output,
`... ${remaining} more item${remaining > 1 ? 's' : ''}`);
}
return output;
}
@ -1661,7 +1683,7 @@ function formatProperty(ctx, value, recurseTimes, key, type, desc,
(ctx.getters === 'get' && desc.set === undefined) ||
(ctx.getters === 'set' && desc.set !== undefined))) {
try {
const tmp = ReflectApply(desc.get, original, []);
const tmp = FunctionPrototypeCall(desc.get, original);
ctx.indentationLvl += 2;
if (tmp === null) {
str = `${s(`[${label}:`, sp)} ${s('null', 'null')}${s(']', sp)}`;
@ -1688,11 +1710,16 @@ function formatProperty(ctx, value, recurseTimes, key, type, desc,
return str;
}
if (typeof key === 'symbol') {
const tmp = key.toString().replace(strEscapeSequencesReplacer, escapeFn);
const tmp = StringPrototypeReplace(
SymbolPrototypeToString(key),
strEscapeSequencesReplacer, escapeFn
);
name = `[${ctx.stylize(tmp, 'symbol')}]`;
} else if (desc.enumerable === false) {
name = `[${key.replace(strEscapeSequencesReplacer, escapeFn)}]`;
} else if (keyStrRegExp.test(key)) {
const tmp = StringPrototypeReplace(key,
strEscapeSequencesReplacer, escapeFn);
name = `[${tmp}]`;
} else if (RegExpPrototypeTest(keyStrRegExp, key)) {
name = ctx.stylize(key, 'name');
} else {
name = ctx.stylize(strEscape(key), 'string');
@ -1721,7 +1748,7 @@ function isBelowBreakLength(ctx, output, start, base) {
}
}
// Do not line up properties on the same line if `base` contains line breaks.
return base === '' || !base.includes('\n');
return base === '' || !StringPrototypeIncludes(base, '\n');
}
function reduceToSingleString(
@ -1764,7 +1791,7 @@ function reduceToSingleString(
}
}
// Line up each entry on an individual line.
const indentation = `\n${' '.repeat(ctx.indentationLvl)}`;
const indentation = `\n${StringPrototypeRepeat(' ', ctx.indentationLvl)}`;
return `${base ? `${base} ` : ''}${braces[0]}${indentation} ` +
`${join(output, `,${indentation} `)}${indentation}${braces[1]}`;
}
@ -1774,7 +1801,7 @@ function reduceToSingleString(
return `${braces[0]}${base ? ` ${base}` : ''} ${join(output, ', ')} ` +
braces[1];
}
const indentation = ' '.repeat(ctx.indentationLvl);
const indentation = StringPrototypeRepeat(' ', ctx.indentationLvl);
// If the opening "brace" is too large, like in the case of "Set {",
// we need to force the first item to be on the next line or the
// items will not line up correctly.
@ -1816,7 +1843,8 @@ function hasBuiltInToString(value) {
builtInObjects.has(descriptor.value.name);
}
const firstErrorLine = (error) => error.message.split('\n')[0];
const firstErrorLine = (error) =>
StringPrototypeSplit(error.message, '\n', 1)[0];
let CIRCULAR_ERROR_MESSAGE;
function tryStringify(arg) {
try {
@ -1864,8 +1892,8 @@ function formatWithOptionsInternal(inspectOptions, ...args) {
let lastPos = 0;
for (let i = 0; i < first.length - 1; i++) {
if (first.charCodeAt(i) === 37) { // '%'
const nextChar = first.charCodeAt(++i);
if (StringPrototypeCharCodeAt(first, i) === 37) { // '%'
const nextChar = StringPrototypeCharCodeAt(first, ++i);
if (a + 1 !== args.length) {
switch (nextChar) {
case 115: // 's'
@ -1936,19 +1964,19 @@ function formatWithOptionsInternal(inspectOptions, ...args) {
tempStr = '';
break;
case 37: // '%'
str += first.slice(lastPos, i);
str += StringPrototypeSlice(first, lastPos, i);
lastPos = i + 1;
continue;
default: // Any other character is not a correct placeholder
continue;
}
if (lastPos !== i - 1) {
str += first.slice(lastPos, i - 1);
str += StringPrototypeSlice(first, lastPos, i - 1);
}
str += tempStr;
lastPos = i + 1;
} else if (nextChar === 37) {
str += first.slice(lastPos, i);
str += StringPrototypeSlice(first, lastPos, i);
lastPos = i + 1;
}
}
@ -1957,7 +1985,7 @@ function formatWithOptionsInternal(inspectOptions, ...args) {
a++;
join = ' ';
if (lastPos < first.length) {
str += first.slice(lastPos);
str += StringPrototypeSlice(first, lastPos);
}
}
}
@ -2005,9 +2033,9 @@ if (internalBinding('config').hasIntl) {
if (removeControlChars)
str = stripVTControlCharacters(str);
str = str.normalize('NFC');
str = StringPrototypeNormalize(str, 'NFC');
for (const char of new SafeStringIterator(str)) {
const code = char.codePointAt(0);
const code = StringPrototypeCodePointAt(char, 0);
if (isFullWidthCodePoint(code)) {
width += 2;
} else if (!isZeroWidthCodePoint(code)) {

View File

@ -1,6 +1,8 @@
'use strict';
const {
ArrayPrototypeConcat,
FunctionPrototypeBind,
ObjectDefineProperty,
ObjectKeys,
} = primordials;
@ -27,8 +29,10 @@ function installConsoleExtensions(commandLineApi) {
const { makeRequireFunction } = require('internal/modules/cjs/helpers');
const consoleAPIModule = new CJSModule('<inspector console>');
const cwd = tryGetCwd();
consoleAPIModule.paths =
CJSModule._nodeModulePaths(cwd).concat(CJSModule.globalPaths);
consoleAPIModule.paths = ArrayPrototypeConcat(
CJSModule._nodeModulePaths(cwd),
CJSModule.globalPaths
);
commandLineApi.require = makeRequireFunction(consoleAPIModule);
}
@ -40,9 +44,12 @@ function wrapConsole(consoleFromNode, consoleFromVM) {
// then wrap these two methods into one. Native wrapper will preserve
// the original stack.
if (consoleFromNode.hasOwnProperty(key)) {
consoleFromNode[key] = consoleCall.bind(consoleFromNode,
consoleFromVM[key],
consoleFromNode[key]);
consoleFromNode[key] = FunctionPrototypeBind(
consoleCall,
consoleFromNode,
consoleFromVM[key],
consoleFromNode[key]
);
ObjectDefineProperty(consoleFromNode[key], 'name', {
value: key
});

View File

@ -23,8 +23,16 @@
const {
ArrayIsArray,
ArrayPrototypeJoin,
ArrayPrototypePop,
Date,
DatePrototypeGetDate,
DatePrototypeGetHours,
DatePrototypeGetMinutes,
DatePrototypeGetMonth,
DatePrototypeGetSeconds,
Error,
FunctionPrototypeBind,
NumberIsSafeInteger,
ObjectDefineProperties,
ObjectDefineProperty,
@ -33,6 +41,7 @@ const {
ObjectPrototypeToString,
ObjectSetPrototypeOf,
ReflectApply,
StringPrototypePadStart,
} = primordials;
const {
@ -110,7 +119,7 @@ function isPrimitive(arg) {
}
function pad(n) {
return n.toString().padStart(2, '0');
return StringPrototypePadStart(n.toString(), 2, '0');
}
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
@ -119,10 +128,12 @@ const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
// 26 Feb 16:19:34
function timestamp() {
const d = new Date();
const time = [pad(d.getHours()),
pad(d.getMinutes()),
pad(d.getSeconds())].join(':');
return [d.getDate(), months[d.getMonth()], time].join(' ');
const t = ArrayPrototypeJoin([
pad(DatePrototypeGetHours(d)),
pad(DatePrototypeGetMinutes(d)),
pad(DatePrototypeGetSeconds(d)),
], ':');
return `${DatePrototypeGetDate(d)} ${months[DatePrototypeGetMonth(d)]} ${t}`;
}
let console;
@ -201,11 +212,11 @@ function callbackify(original) {
// 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 = args.pop();
const maybeCb = ArrayPrototypePop(args);
if (typeof maybeCb !== 'function') {
throw new ERR_INVALID_ARG_TYPE('last argument', 'Function', maybeCb);
}
const cb = (...args) => { ReflectApply(maybeCb, this, args); };
const cb = FunctionPrototypeBind(maybeCb, this);
// In true node style we process the callback on `nextTick` with all the
// implications (stack, `uncaughtException`, `async_hooks`)
ReflectApply(original, this, args)