Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib: enforce use of Array from primordials #30635

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/.eslintrc.yaml
Original file line number Diff line number Diff line change
@@ -9,6 +9,8 @@ rules:
- groups: [[ "&&", "||" ]]
no-restricted-globals:
- error
- name: Array
message: "Use `const { Array } = primordials;` instead of the global."
- name: JSON
message: "Use `const { JSON } = primordials;` instead of the global."
- name: Math
3 changes: 2 additions & 1 deletion lib/_http_client.js
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
'use strict';

const {
ArrayIsArray,
ObjectAssign,
ObjectKeys,
ObjectSetPrototypeOf,
@@ -217,7 +218,7 @@ function ClientRequest(input, options, cb) {
}
}

const headersArray = Array.isArray(options.headers);
const headersArray = ArrayIsArray(options.headers);
if (!headersArray) {
if (options.headers) {
const keys = ObjectKeys(options.headers);
7 changes: 4 additions & 3 deletions lib/_http_outgoing.js
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
'use strict';

const {
ArrayIsArray,
ObjectCreate,
ObjectDefineProperty,
ObjectKeys,
@@ -359,7 +360,7 @@ function _storeHeader(firstLine, headers) {
const entry = headers[key];
processHeader(this, state, entry[0], entry[1], false);
}
} else if (Array.isArray(headers)) {
} else if (ArrayIsArray(headers)) {
for (const entry of headers) {
processHeader(this, state, entry[0], entry[1], true);
}
@@ -453,7 +454,7 @@ function _storeHeader(firstLine, headers) {
function processHeader(self, state, key, value, validate) {
if (validate)
validateHeaderName(key);
if (Array.isArray(value)) {
if (ArrayIsArray(value)) {
if (value.length < 2 || !isCookieField(key)) {
for (var i = 0; i < value.length; i++)
storeHeader(self, state, key, value[i], validate);
@@ -695,7 +696,7 @@ function connectionCorkNT(conn) {
OutgoingMessage.prototype.addTrailers = function addTrailers(headers) {
this._trailer = '';
const keys = ObjectKeys(headers);
const isArray = Array.isArray(headers);
const isArray = ArrayIsArray(headers);
var field, value;
for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i];
3 changes: 2 additions & 1 deletion lib/_stream_readable.js
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
'use strict';

const {
ArrayIsArray,
ObjectDefineProperty,
ObjectSetPrototypeOf,
} = primordials;
@@ -70,7 +71,7 @@ function prependListener(emitter, event, fn) {
// the prependListener() method. The goal is to eventually remove this hack.
if (!emitter._events || !emitter._events[event])
emitter.on(event, fn);
else if (Array.isArray(emitter._events[event]))
else if (ArrayIsArray(emitter._events[event]))
emitter._events[event].unshift(fn);
else
emitter._events[event] = [fn, emitter._events[event]];
1 change: 1 addition & 0 deletions lib/_stream_writable.js
Original file line number Diff line number Diff line change
@@ -26,6 +26,7 @@
'use strict';

const {
Array,
ObjectDefineProperty,
ObjectSetPrototypeOf,
} = primordials;
11 changes: 6 additions & 5 deletions lib/_tls_common.js
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
'use strict';

const {
ArrayIsArray,
ObjectCreate,
} = primordials;

@@ -105,7 +106,7 @@ exports.createSecureContext = function createSecureContext(options) {
// Add CA before the cert to be able to load cert's issuer in C++ code.
const { ca } = options;
if (ca) {
if (Array.isArray(ca)) {
if (ArrayIsArray(ca)) {
for (i = 0; i < ca.length; ++i) {
val = ca[i];
validateKeyOrCertOption('ca', val);
@@ -121,7 +122,7 @@ exports.createSecureContext = function createSecureContext(options) {

const { cert } = options;
if (cert) {
if (Array.isArray(cert)) {
if (ArrayIsArray(cert)) {
for (i = 0; i < cert.length; ++i) {
val = cert[i];
validateKeyOrCertOption('cert', val);
@@ -140,7 +141,7 @@ exports.createSecureContext = function createSecureContext(options) {
const key = options.key;
const passphrase = options.passphrase;
if (key) {
if (Array.isArray(key)) {
if (ArrayIsArray(key)) {
for (i = 0; i < key.length; ++i) {
val = key[i];
// eslint-disable-next-line eqeqeq
@@ -240,7 +241,7 @@ exports.createSecureContext = function createSecureContext(options) {
}

if (options.crl) {
if (Array.isArray(options.crl)) {
if (ArrayIsArray(options.crl)) {
for (i = 0; i < options.crl.length; i++) {
c.context.addCRL(options.crl[i]);
}
@@ -257,7 +258,7 @@ exports.createSecureContext = function createSecureContext(options) {
if (!toBuf)
toBuf = require('internal/crypto/util').toBuf;

if (Array.isArray(options.pfx)) {
if (ArrayIsArray(options.pfx)) {
for (i = 0; i < options.pfx.length; i++) {
const pfx = options.pfx[i];
const raw = pfx.buf ? pfx.buf : pfx;
6 changes: 4 additions & 2 deletions lib/buffer.js
Original file line number Diff line number Diff line change
@@ -22,6 +22,8 @@
'use strict';

const {
Array,
ArrayIsArray,
MathFloor,
MathMin,
MathTrunc,
@@ -483,7 +485,7 @@ function fromObject(obj) {
return fromArrayLike(obj);
}

if (obj.type === 'Buffer' && Array.isArray(obj.data)) {
if (obj.type === 'Buffer' && ArrayIsArray(obj.data)) {
return fromArrayLike(obj.data);
}
}
@@ -518,7 +520,7 @@ Buffer[kIsEncodingSymbol] = Buffer.isEncoding;

Buffer.concat = function concat(list, length) {
let i;
if (!Array.isArray(list)) {
if (!ArrayIsArray(list)) {
throw new ERR_INVALID_ARG_TYPE('list', 'Array', list);
}

9 changes: 5 additions & 4 deletions lib/child_process.js
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
'use strict';

const {
ArrayIsArray,
ObjectAssign,
ObjectDefineProperty,
ObjectPrototypeHasOwnProperty,
@@ -63,7 +64,7 @@ function fork(modulePath /* , args, options */) {
let options = {};
let args = [];
let pos = 1;
if (pos < arguments.length && Array.isArray(arguments[pos])) {
if (pos < arguments.length && ArrayIsArray(arguments[pos])) {
args = arguments[pos++];
}

@@ -96,7 +97,7 @@ function fork(modulePath /* , args, options */) {

if (typeof options.stdio === 'string') {
options.stdio = stdioStringToArray(options.stdio, 'ipc');
} else if (!Array.isArray(options.stdio)) {
} else if (!ArrayIsArray(options.stdio)) {
// Use a separate fd=3 for the IPC channel. Inherit stdin, stdout,
// and stderr from the parent if silent isn't set.
options.stdio = stdioStringToArray(
@@ -186,7 +187,7 @@ function execFile(file /* , args, options, callback */) {

// Parse the optional positional parameters.
let pos = 1;
if (pos < arguments.length && Array.isArray(arguments[pos])) {
if (pos < arguments.length && ArrayIsArray(arguments[pos])) {
args = arguments[pos++];
} else if (pos < arguments.length && arguments[pos] == null) {
pos++;
@@ -404,7 +405,7 @@ function normalizeSpawnArguments(file, args, options) {
if (file.length === 0)
throw new ERR_INVALID_ARG_VALUE('file', file, 'cannot be empty');

if (Array.isArray(args)) {
if (ArrayIsArray(args)) {
args = args.slice(0);
} else if (args == null) {
args = [];
4 changes: 3 additions & 1 deletion lib/dgram.js
Original file line number Diff line number Diff line change
@@ -22,6 +22,8 @@
'use strict';

const {
Array,
ArrayIsArray,
ObjectDefineProperty,
ObjectSetPrototypeOf,
} = primordials;
@@ -592,7 +594,7 @@ Socket.prototype.send = function(buffer,
throw new ERR_SOCKET_DGRAM_IS_CONNECTED();
}

if (!Array.isArray(buffer)) {
if (!ArrayIsArray(buffer)) {
if (typeof buffer === 'string') {
list = [ Buffer.from(buffer) ];
} else if (!isUint8Array(buffer)) {
1 change: 1 addition & 0 deletions lib/domain.js
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@
// unless they address existing, critical bugs.

const {
Array,
ObjectDefineProperty,
ReflectApply,
} = primordials;
1 change: 1 addition & 0 deletions lib/events.js
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
'use strict';

const {
Array,
MathMin,
ObjectCreate,
ObjectDefineProperty,
9 changes: 5 additions & 4 deletions lib/internal/child_process.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const {
ArrayIsArray,
ObjectDefineProperty,
ObjectSetPrototypeOf,
} = primordials;
@@ -357,7 +358,7 @@ ChildProcess.prototype.spawn = function(options) {
// Let child process know about opened IPC channel
if (options.envPairs === undefined)
options.envPairs = [];
else if (!Array.isArray(options.envPairs)) {
else if (!ArrayIsArray(options.envPairs)) {
throw new ERR_INVALID_ARG_TYPE('options.envPairs',
'Array',
options.envPairs);
@@ -370,7 +371,7 @@ ChildProcess.prototype.spawn = function(options) {
validateString(options.file, 'options.file');
this.spawnfile = options.file;

if (Array.isArray(options.args))
if (ArrayIsArray(options.args))
this.spawnargs = options.args;
else if (options.args === undefined)
this.spawnargs = [];
@@ -613,7 +614,7 @@ function setupChannel(target, channel, serializationMode) {
}
}

assert(Array.isArray(target._handleQueue));
assert(ArrayIsArray(target._handleQueue));
const queue = target._handleQueue;
target._handleQueue = null;

@@ -912,7 +913,7 @@ function getValidStdio(stdio, sync) {
// Replace shortcut with an array
if (typeof stdio === 'string') {
stdio = stdioStringToArray(stdio);
} else if (!Array.isArray(stdio)) {
} else if (!ArrayIsArray(stdio)) {
throw new ERR_INVALID_OPT_VALUE('stdio', inspect(stdio));
}

7 changes: 2 additions & 5 deletions lib/internal/console/constructor.js
Original file line number Diff line number Diff line change
@@ -4,6 +4,8 @@
// console. It's exported for backwards compatibility.

const {
ArrayFrom,
ArrayIsArray,
MathFloor,
ObjectDefineProperties,
ObjectDefineProperty,
@@ -44,11 +46,6 @@ const kSecond = 1000;
const kMinute = 60 * kSecond;
const kHour = 60 * kMinute;

const {
isArray: ArrayIsArray,
from: ArrayFrom,
} = Array;

// Lazy loaded for startup performance.
let cliTable;

7 changes: 6 additions & 1 deletion lib/internal/dns/utils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
'use strict';

const {
ArrayIsArray,
} = primordials;

const errors = require('internal/errors');
const { isIP } = require('internal/net');
const {
@@ -38,7 +43,7 @@ class Resolver {
}

setServers(servers) {
if (!Array.isArray(servers)) {
if (!ArrayIsArray(servers)) {
throw new ERR_INVALID_ARG_TYPE('servers', 'Array', servers);
}

3 changes: 2 additions & 1 deletion lib/internal/errors.js
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@
// message may change, the code should not.

const {
ArrayIsArray,
MathAbs,
ObjectDefineProperty,
ObjectKeys,
@@ -608,7 +609,7 @@ function isStackOverflowError(err) {

function oneOf(expected, thing) {
assert(typeof thing === 'string', '`thing` has to be of type string');
if (Array.isArray(expected)) {
if (ArrayIsArray(expected)) {
const len = expected.length;
assert(len > 0,
'At least one expected value needs to be specified');
4 changes: 4 additions & 0 deletions lib/internal/fixed_queue.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
'use strict';

const {
Array,
} = primordials;

// Currently optimal queue size, tested on V8 6.0 - 6.6. Must be power of two.
const kSize = 2048;
const kMask = kSize - 1;
1 change: 1 addition & 0 deletions lib/internal/fs/streams.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const {
Array,
MathMin,
ObjectDefineProperty,
ObjectSetPrototypeOf,
3 changes: 2 additions & 1 deletion lib/internal/fs/utils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const {
ArrayIsArray,
ObjectSetPrototypeOf,
ReflectOwnKeys,
} = primordials;
@@ -541,7 +542,7 @@ const getValidatedPath = hideStackFrames((fileURLOrPath, propName = 'path') => {
});

const validateBufferArray = hideStackFrames((buffers, propName = 'buffers') => {
if (!Array.isArray(buffers))
if (!ArrayIsArray(buffers))
throw new ERR_INVALID_ARG_TYPE(propName, 'ArrayBufferView[]', buffers);

for (let i = 0; i < buffers.length; i++) {
3 changes: 2 additions & 1 deletion lib/internal/http2/compat.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const {
ArrayIsArray,
ObjectAssign,
ObjectCreate,
ObjectKeys,
@@ -617,7 +618,7 @@ class Http2ServerResponse extends Stream {
headers = statusMessage;

let i;
if (Array.isArray(headers)) {
if (ArrayIsArray(headers)) {
for (i = 0; i < headers.length; i++) {
const header = headers[i];
this[kSetHeader](header[0], header[1]);
6 changes: 4 additions & 2 deletions lib/internal/http2/core.js
Original file line number Diff line number Diff line change
@@ -3,6 +3,8 @@
/* eslint-disable no-use-before-define */

const {
ArrayFrom,
ArrayIsArray,
MathMin,
ObjectAssign,
ObjectCreate,
@@ -948,7 +950,7 @@ function setupHandle(socket, type, options) {
this.settings(settings);

if (type === NGHTTP2_SESSION_SERVER &&
Array.isArray(options.origins)) {
ArrayIsArray(options.origins)) {
this.origin(...options.origins);
}

@@ -1105,7 +1107,7 @@ class Http2Session extends EventEmitter {
get originSet() {
if (!this.encrypted || this.destroyed)
return undefined;
return Array.from(initOriginSet(this));
return ArrayFrom(initOriginSet(this));
}

// True if the Http2Session is still waiting for the socket to connect
5 changes: 3 additions & 2 deletions lib/internal/http2/util.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const {
ArrayIsArray,
MathMax,
ObjectCreate,
ObjectKeys,
@@ -449,7 +450,7 @@ function mapToHeaders(map,
continue;
key = key.toLowerCase();
isSingleValueHeader = kSingleValueHeaders.has(key);
isArray = Array.isArray(value);
isArray = ArrayIsArray(value);
if (isArray) {
switch (value.length) {
case 0:
@@ -513,7 +514,7 @@ const assertIsObject = hideStackFrames((value, name, types) => {
if (value !== undefined &&
(value === null ||
typeof value !== 'object' ||
Array.isArray(value))) {
ArrayIsArray(value))) {
throw new ERR_INVALID_ARG_TYPE(name, types || 'Object', value);
}
});
11 changes: 6 additions & 5 deletions lib/internal/modules/cjs/loader.js
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
'use strict';

const {
ArrayIsArray,
JSONParse,
ObjectCreate,
ObjectDefineProperty,
@@ -464,7 +465,7 @@ function trySelf(paths, exts, isMain, trailingSlash, request) {
function isConditionalDotExportSugar(exports, basePath) {
if (typeof exports === 'string')
return true;
if (Array.isArray(exports))
if (ArrayIsArray(exports))
return true;
if (typeof exports !== 'object')
return false;
@@ -572,9 +573,9 @@ function resolveExportsTarget(pkgPath, target, subpath, basePath, mappingKey) {
}
}
}
} else if (Array.isArray(target)) {
} else if (ArrayIsArray(target)) {
for (const targetValue of target) {
if (Array.isArray(targetValue)) continue;
if (ArrayIsArray(targetValue)) continue;
try {
return resolveExportsTarget(pkgPath, targetValue, subpath, basePath,
mappingKey);
@@ -967,7 +968,7 @@ Module._resolveFilename = function(request, parent, isMain, options) {
let paths;

if (typeof options === 'object' && options !== null) {
if (Array.isArray(options.paths)) {
if (ArrayIsArray(options.paths)) {
const isRelative = request.startsWith('./') ||
request.startsWith('../') ||
((isWindows && request.startsWith('.\\')) ||
@@ -1330,7 +1331,7 @@ Module._initPaths = function() {
};

Module._preloadModules = function(requests) {
if (!Array.isArray(requests))
if (!ArrayIsArray(requests))
return;

// Preloaded modules have a dummy parent module which is deemed to exist
9 changes: 1 addition & 8 deletions lib/internal/per_context/primordials.js
Original file line number Diff line number Diff line change
@@ -13,7 +13,6 @@
// by the native module compiler.

const ReflectApply = Reflect.apply;
const ReflectConstruct = Reflect.construct;

// This function is borrowed from the function with the same name on V8 Extras'
// `utils` object. V8 implements Reflect.apply very efficiently in conjunction
@@ -120,13 +119,7 @@ primordials.SafePromise = makeSafe(
'WeakSet',
].forEach((name) => {
const original = global[name];
primordials[name] = Object.setPrototypeOf({
[name]: function(...args) {
return new.target ?
ReflectConstruct(original, args, new.target) :
ReflectApply(original, this, args);
}
}[name], null);
Copy link
Member Author

@targos targos Nov 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is necessary, for two reasons:

  • Some of the arrays we create are returned to the user
  • Without it I'd also have to change calls to array methods

Also, It's probably better not to wrap the primordial functions for performance reasons, especially when we migrate String() and Number() calls in the future.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, wait, but why is Object.setPrototypeOf(..., null) removed here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because if we stop wrapping the functions, it becomes useless, as there is nothing left to set the prototype of (we can't do that directly on the original functions).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. To me making the Array namespace less mutable takes precedence over keeping these functions away from prototype poisoning, so LGTM.

primordials[name] = original;
copyPropsRenamed(original, primordials, name);
copyPrototype(original.prototype, primordials, `${name}Prototype`);
});
3 changes: 2 additions & 1 deletion lib/internal/policy/manifest.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const {
ArrayIsArray,
Map,
MapPrototypeSet,
ObjectEntries,
@@ -137,7 +138,7 @@ class Manifest {
if (dependencyMap === null || dependencyMap === undefined) {
dependencyMap = {};
}
if (typeof dependencyMap === 'object' && !Array.isArray(dependencyMap)) {
if (typeof dependencyMap === 'object' && !ArrayIsArray(dependencyMap)) {
/**
* @returns {true | URL}
*/
4 changes: 4 additions & 0 deletions lib/internal/priority_queue.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
'use strict';

const {
Array,
} = primordials;

const kCompare = Symbol('compare');
const kHeap = Symbol('heap');
const kSetPosition = Symbol('setPosition');
6 changes: 5 additions & 1 deletion lib/internal/process/main_thread_only.js
Original file line number Diff line number Diff line change
@@ -3,6 +3,10 @@
// This file contains process bootstrappers that can only be
// run in the main thread

const {
ArrayIsArray,
} = primordials;

const {
errnoException,
codes: {
@@ -74,7 +78,7 @@ function wrapPosixCredentialSetters(credentials) {
}

function setgroups(groups) {
if (!Array.isArray(groups)) {
if (!ArrayIsArray(groups)) {
throw new ERR_INVALID_ARG_TYPE('groups', 'Array', groups);
}
for (let i = 0; i < groups.length; i++) {
3 changes: 2 additions & 1 deletion lib/internal/process/per_thread.js
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
// thread and the worker threads.

const {
ArrayIsArray,
ObjectDefineProperties,
ObjectDefineProperty,
ObjectFreeze,
@@ -114,7 +115,7 @@ function wrapProcessMethods(binding) {
_hrtime(hrValues);

if (time !== undefined) {
if (!Array.isArray(time)) {
if (!ArrayIsArray(time)) {
throw new ERR_INVALID_ARG_TYPE('time', 'Array', time);
}
if (time.length !== 2) {
1 change: 1 addition & 0 deletions lib/internal/process/task_queues.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const {
Array,
FunctionPrototypeBind,
} = primordials;

6 changes: 5 additions & 1 deletion lib/internal/process/warning.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
'use strict';

const {
ArrayIsArray,
} = primordials;

const { ERR_INVALID_ARG_TYPE } = require('internal/errors').codes;

// Lazily loaded
@@ -84,7 +88,7 @@ function onWarning(warning) {
// process.emitWarning(str[, options])
function emitWarning(warning, type, code, ctor, now) {
let detail;
if (type !== null && typeof type === 'object' && !Array.isArray(type)) {
if (type !== null && typeof type === 'object' && !ArrayIsArray(type)) {
ctor = type.ctor;
code = type.code;
if (typeof type.detail === 'string')
4 changes: 4 additions & 0 deletions lib/internal/querystring.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
'use strict';

const {
Array,
} = primordials;

const { ERR_INVALID_URI } = require('internal/errors').codes;

const hexTable = new Array(256);
4 changes: 4 additions & 0 deletions lib/internal/stream_base_commons.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
'use strict';

const {
Array,
} = primordials;

const { Buffer } = require('buffer');
const { FastBuffer } = require('internal/buffer');
const {
6 changes: 5 additions & 1 deletion lib/internal/streams/pipeline.js
Original file line number Diff line number Diff line change
@@ -3,6 +3,10 @@

'use strict';

const {
ArrayIsArray,
} = primordials;

let eos;

const { once } = require('internal/util');
@@ -65,7 +69,7 @@ function popCallback(streams) {
function pipeline(...streams) {
const callback = popCallback(streams);

if (Array.isArray(streams[0])) streams = streams[0];
if (ArrayIsArray(streams[0])) streams = streams[0];

if (streams.length < 2) {
throw new ERR_MISSING_ARGS('streams');
3 changes: 2 additions & 1 deletion lib/internal/tls.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const {
ArrayIsArray,
ObjectCreate,
} = primordials;

@@ -15,7 +16,7 @@ function parseCertString(s) {
const key = parts[i].slice(0, sepIndex);
const value = parts[i].slice(sepIndex + 1);
if (key in out) {
if (!Array.isArray(out[key])) {
if (!ArrayIsArray(out[key])) {
out[key] = [out[key]];
}
out[key].push(value);
1 change: 1 addition & 0 deletions lib/internal/url.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const {
Array,
ObjectCreate,
ObjectDefineProperties,
ObjectDefineProperty,
6 changes: 4 additions & 2 deletions lib/internal/util.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
'use strict';

const {
ArrayFrom,
ArrayIsArray,
ObjectCreate,
ObjectDefineProperties,
ObjectDefineProperty,
@@ -184,7 +186,7 @@ function filterDuplicateStrings(items, low) {
map.set(key, item);
}
}
return Array.from(map.values()).sort();
return ArrayFrom(map.values()).sort();
}

function cachedResult(fn) {
@@ -361,7 +363,7 @@ function isInsideNodeModules() {

// Iterate over all stack frames and look for the first one not coming
// from inside Node.js itself:
if (Array.isArray(stack)) {
if (ArrayIsArray(stack)) {
for (const frame of stack) {
const filename = frame.getFileName();
// If a filename does not start with / or contain \,
3 changes: 2 additions & 1 deletion lib/internal/util/comparisons.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const {
ArrayIsArray,
BigIntPrototypeValueOf,
BooleanPrototypeValueOf,
DatePrototypeGetTime,
@@ -163,7 +164,7 @@ function innerDeepEqual(val1, val2, strict, memos) {
if (val1Tag !== val2Tag) {
return false;
}
if (Array.isArray(val1)) {
if (ArrayIsArray(val1)) {
// Check for sparse arrays and general fast path
if (val1.length !== val2.length) {
return false;
1 change: 1 addition & 0 deletions lib/internal/util/inspect.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const {
Array,
ArrayIsArray,
BigIntPrototypeValueOf,
BooleanPrototypeValueOf,
3 changes: 2 additions & 1 deletion lib/internal/vm/module.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const {
ArrayIsArray,
ObjectCreate,
ObjectDefineProperty,
Symbol,
@@ -350,7 +351,7 @@ class SourceTextModule extends Module {

class SyntheticModule extends Module {
constructor(exportNames, evaluateCallback, options = {}) {
if (!Array.isArray(exportNames) ||
if (!ArrayIsArray(exportNames) ||
exportNames.some((e) => typeof e !== 'string')) {
throw new ERR_INVALID_ARG_TYPE('exportNames', 'Array of strings',
exportNames);
3 changes: 2 additions & 1 deletion lib/internal/worker.js
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
/* global SharedArrayBuffer */

const {
ArrayIsArray,
MathMax,
ObjectCreate,
ObjectEntries,
@@ -79,7 +80,7 @@ class Worker extends EventEmitter {
super();
debug(`[${threadId}] create new worker`, filename, options);
validateString(filename, 'filename');
if (options.execArgv && !Array.isArray(options.execArgv)) {
if (options.execArgv && !ArrayIsArray(options.execArgv)) {
throw new ERR_INVALID_ARG_TYPE('options.execArgv',
'array',
options.execArgv);
5 changes: 3 additions & 2 deletions lib/net.js
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
'use strict';

const {
ArrayIsArray,
ObjectDefineProperty,
ObjectSetPrototypeOf,
} = primordials;
@@ -809,7 +810,7 @@ protoGetter('bytesWritten', function bytesWritten() {
bytes += Buffer.byteLength(el.chunk, el.encoding);
});

if (Array.isArray(data)) {
if (ArrayIsArray(data)) {
// Was a writev, iterate over chunks to get total length
for (let i = 0; i < data.length; i++) {
const chunk = data[i];
@@ -920,7 +921,7 @@ Socket.prototype.connect = function(...args) {
// already been normalized (so we don't normalize more than once). This has
// been solved before in https://github.com/nodejs/node/pull/12342, but was
// reverted as it had unintended side effects.
if (Array.isArray(args[0]) && args[0][normalizedArgsSymbol]) {
if (ArrayIsArray(args[0]) && args[0][normalizedArgsSymbol]) {
normalized = args[0];
} else {
normalized = normalizeArgs(args);
3 changes: 2 additions & 1 deletion lib/perf_hooks.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const {
ArrayIsArray,
ObjectDefineProperties,
ObjectDefineProperty,
ObjectKeys,
@@ -335,7 +336,7 @@ class PerformanceObserver extends AsyncResource {
if (typeof options !== 'object' || options === null) {
throw new ERR_INVALID_ARG_TYPE('options', 'Object', options);
}
if (!Array.isArray(options.entryTypes)) {
if (!ArrayIsArray(options.entryTypes)) {
throw new ERR_INVALID_OPT_VALUE('entryTypes', options);
}
const entryTypes = options.entryTypes.filter(filterTypes).map(mapTypes);
4 changes: 3 additions & 1 deletion lib/querystring.js
Original file line number Diff line number Diff line change
@@ -24,6 +24,8 @@
'use strict';

const {
Array,
ArrayIsArray,
ObjectCreate,
ObjectKeys,
} = primordials;
@@ -180,7 +182,7 @@ function stringify(obj, sep, eq, options) {
let ks = encode(stringifyPrimitive(k));
ks += eq;

if (Array.isArray(v)) {
if (ArrayIsArray(v)) {
const vlen = v.length;
if (vlen === 0) continue;
const vlast = vlen - 1;
5 changes: 3 additions & 2 deletions lib/repl.js
Original file line number Diff line number Diff line change
@@ -43,6 +43,7 @@
'use strict';

const {
ArrayIsArray,
MathMax,
ObjectAssign,
ObjectCreate,
@@ -1250,9 +1251,9 @@ function complete(line, callback) {
completionGroupsLoaded();
} else {
this.eval('.scope', this.context, 'repl', function ev(err, globals) {
if (err || !Array.isArray(globals)) {
if (err || !ArrayIsArray(globals)) {
if (filter !== '') addCommonWords(completionGroups);
} else if (Array.isArray(globals[0])) {
} else if (ArrayIsArray(globals[0])) {
// Add grouped globals
for (let n = 0; n < globals.length; n++)
completionGroups.push(globals[n]);
6 changes: 4 additions & 2 deletions lib/tls.js
Original file line number Diff line number Diff line change
@@ -22,6 +22,8 @@
'use strict';

const {
Array,
ArrayIsArray,
ObjectDefineProperty,
ObjectFreeze,
} = primordials;
@@ -124,7 +126,7 @@ function convertProtocols(protocols) {

exports.convertALPNProtocols = function convertALPNProtocols(protocols, out) {
// If protocols is Array - translate it into buffer
if (Array.isArray(protocols)) {
if (ArrayIsArray(protocols)) {
out.ALPNProtocols = convertProtocols(protocols);
} else if (isArrayBufferView(protocols)) {
// Copy new buffer not to be modified by user.
@@ -261,7 +263,7 @@ exports.checkServerIdentity = function checkServerIdentity(hostname, cert) {
if (dnsNames.length === 0 && ips.length === 0 && uriNames.length === 0) {
const cn = subject.CN;

if (Array.isArray(cn))
if (ArrayIsArray(cn))
valid = cn.some(wildcard);
else if (cn)
valid = wildcard(cn);
6 changes: 5 additions & 1 deletion lib/trace_events.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
'use strict';

const {
ArrayIsArray,
} = primordials;

const { hasTracing } = internalBinding('config');
const kHandle = Symbol('handle');
const kEnabled = Symbol('enabled');
@@ -76,7 +80,7 @@ function createTracing(options) {
if (typeof options !== 'object' || options === null)
throw new ERR_INVALID_ARG_TYPE('options', 'object', options);

if (!Array.isArray(options.categories)) {
if (!ArrayIsArray(options.categories)) {
throw new ERR_INVALID_ARG_TYPE('options.categories', 'string[]',
options.categories);
}
1 change: 1 addition & 0 deletions lib/tty.js
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
'use strict';

const {
Array,
ObjectSetPrototypeOf,
} = primordials;

3 changes: 2 additions & 1 deletion lib/util.js
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
'use strict';

const {
ArrayIsArray,
ObjectDefineProperties,
ObjectDefineProperty,
ObjectGetOwnPropertyDescriptors,
@@ -243,7 +244,7 @@ module.exports = {
getSystemErrorName,
inherits,
inspect,
isArray: Array.isArray,
isArray: ArrayIsArray,
isBoolean,
isBuffer,
isDeepStrictEqual(a, b) {
1 change: 1 addition & 0 deletions lib/v8.js
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
'use strict';

const {
Array,
ObjectPrototypeToString,
} = primordials;