Skip to content

Commit b24b34e

Browse files
ExE-Bosstargos
authored andcommitted
lib: add bound apply variants of varargs primordials
Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com> PR-URL: #37005 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
1 parent 7cdff9a commit b24b34e

File tree

3 files changed

+60
-10
lines changed

3 files changed

+60
-10
lines changed

lib/internal/per_context/primordials.js

+56-8
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,36 @@ const {
1919
// `uncurryThis` is equivalent to `func => Function.prototype.call.bind(func)`.
2020
// It is using `bind.bind(call)` to avoid using `Function.prototype.bind`
2121
// and `Function.prototype.call` after it may have been mutated by users.
22-
const { bind, call } = Function.prototype;
22+
const { apply, bind, call } = Function.prototype;
2323
const uncurryThis = bind.bind(call);
2424
primordials.uncurryThis = uncurryThis;
2525

26+
// `applyBind` is equivalent to `func => Function.prototype.apply.bind(func)`.
27+
// It is using `bind.bind(apply)` to avoid using `Function.prototype.bind`
28+
// and `Function.prototype.apply` after it may have been mutated by users.
29+
const applyBind = bind.bind(apply);
30+
primordials.applyBind = applyBind;
31+
32+
// Methods that accept a variable number of arguments, and thus it's useful to
33+
// also create `${prefix}${key}Apply`, which uses `Function.prototype.apply`,
34+
// instead of `Function.prototype.call`, and thus doesn't require iterator
35+
// destructuring.
36+
const varargsMethods = [
37+
// 'ArrayPrototypeConcat' is omitted, because it performs the spread
38+
// on its own for arrays and array-likes with a truthy
39+
// @@isConcatSpreadable symbol property.
40+
'ArrayOf',
41+
'ArrayPrototypePush',
42+
'ArrayPrototypeUnshift',
43+
// 'FunctionPrototypeCall' is omitted, since there's 'ReflectApply'
44+
// and 'FunctionPrototypeApply'.
45+
'MathHypot',
46+
'MathMax',
47+
'MathMin',
48+
'StringPrototypeConcat',
49+
'TypedArrayOf',
50+
];
51+
2652
function getNewKey(key) {
2753
return typeof key === 'symbol' ?
2854
`Symbol${key.description[7].toUpperCase()}${key.description.slice(8)}` :
@@ -49,7 +75,13 @@ function copyPropsRenamed(src, dest, prefix) {
4975
if ('get' in desc) {
5076
copyAccessor(dest, prefix, newKey, desc);
5177
} else {
52-
ReflectDefineProperty(dest, `${prefix}${newKey}`, desc);
78+
const name = `${prefix}${newKey}`;
79+
ReflectDefineProperty(dest, name, desc);
80+
if (varargsMethods.includes(name)) {
81+
ReflectDefineProperty(dest, `${name}Apply`, {
82+
value: applyBind(desc.value, src),
83+
});
84+
}
5385
}
5486
}
5587
}
@@ -61,10 +93,18 @@ function copyPropsRenamedBound(src, dest, prefix) {
6193
if ('get' in desc) {
6294
copyAccessor(dest, prefix, newKey, desc);
6395
} else {
64-
if (typeof desc.value === 'function') {
65-
desc.value = desc.value.bind(src);
96+
const { value } = desc;
97+
if (typeof value === 'function') {
98+
desc.value = value.bind(src);
99+
}
100+
101+
const name = `${prefix}${newKey}`;
102+
ReflectDefineProperty(dest, name, desc);
103+
if (varargsMethods.includes(name)) {
104+
ReflectDefineProperty(dest, `${name}Apply`, {
105+
value: applyBind(value, src),
106+
});
66107
}
67-
ReflectDefineProperty(dest, `${prefix}${newKey}`, desc);
68108
}
69109
}
70110
}
@@ -76,10 +116,18 @@ function copyPrototype(src, dest, prefix) {
76116
if ('get' in desc) {
77117
copyAccessor(dest, prefix, newKey, desc);
78118
} else {
79-
if (typeof desc.value === 'function') {
80-
desc.value = uncurryThis(desc.value);
119+
const { value } = desc;
120+
if (typeof value === 'function') {
121+
desc.value = uncurryThis(value);
122+
}
123+
124+
const name = `${prefix}${newKey}`;
125+
ReflectDefineProperty(dest, name, desc);
126+
if (varargsMethods.includes(name)) {
127+
ReflectDefineProperty(dest, `${name}Apply`, {
128+
value: applyBind(value),
129+
});
81130
}
82-
ReflectDefineProperty(dest, `${prefix}${newKey}`, desc);
83131
}
84132
}
85133
}

lib/internal/util/inspect.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const {
44
Array,
55
ArrayIsArray,
66
ArrayPrototypeFilter,
7+
ArrayPrototypePushApply,
78
BigIntPrototypeValueOf,
89
BooleanPrototypeValueOf,
910
DatePrototypeGetTime,
@@ -653,7 +654,7 @@ function getKeys(value, showHidden) {
653654
if (showHidden) {
654655
keys = ObjectGetOwnPropertyNames(value);
655656
if (symbols.length !== 0)
656-
keys.push(...symbols);
657+
ArrayPrototypePushApply(keys, symbols);
657658
} else {
658659
// This might throw if `value` is a Module Namespace Object from an
659660
// unevaluated module, but we don't want to perform the actual type
@@ -669,7 +670,7 @@ function getKeys(value, showHidden) {
669670
}
670671
if (symbols.length !== 0) {
671672
const filter = (key) => ObjectPrototypePropertyIsEnumerable(value, key);
672-
keys.push(...symbols.filter(filter));
673+
ArrayPrototypePushApply(keys, ArrayPrototypeFilter(symbols, filter));
673674
}
674675
}
675676
return keys;

lib/repl.js

+1
Original file line numberDiff line numberDiff line change
@@ -1343,6 +1343,7 @@ function complete(line, callback) {
13431343
if (!this.useGlobal) {
13441344
// When the context is not `global`, builtins are not own
13451345
// properties of it.
1346+
// `globalBuiltins` is a `SafeSet`, not an Array-like.
13461347
ArrayPrototypePush(contextOwnNames, ...globalBuiltins);
13471348
}
13481349
ArrayPrototypePush(completionGroups, contextOwnNames);

0 commit comments

Comments
 (0)