lib: add bound apply variants of varargs primordials

Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com>

PR-URL: https://github.com/nodejs/node/pull/37005
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
This commit is contained in:
ExE BossandAntoine du Hamel authored and Antoine du Hamel committed 2021-01-28 18:45:43 +01:00
1 parent 029d1fd797
commit 728fee22e9
3 files changed
+60 -10

No files matched your search

+56 -8
View File
@@ -21,10 +21,36 @@ const {
// `uncurryThis` is equivalent to `func => Function.prototype.call.bind(func)`.
// It is using `bind.bind(call)` to avoid using `Function.prototype.bind`
// and `Function.prototype.call` after it may have been mutated by users.
const { bind, call } = Function.prototype;
const { apply, bind, call } = Function.prototype;
const uncurryThis = bind.bind(call);
primordials.uncurryThis = uncurryThis;
// `applyBind` is equivalent to `func => Function.prototype.apply.bind(func)`.
// It is using `bind.bind(apply)` to avoid using `Function.prototype.bind`
// and `Function.prototype.apply` after it may have been mutated by users.
const applyBind = bind.bind(apply);
primordials.applyBind = applyBind;
// Methods that accept a variable number of arguments, and thus it's useful to
// also create `${prefix}${key}Apply`, which uses `Function.prototype.apply`,
// instead of `Function.prototype.call`, and thus doesn't require iterator
// destructuring.
const varargsMethods = [
// 'ArrayPrototypeConcat' is omitted, because it performs the spread
// on its own for arrays and array-likes with a truthy
// @@isConcatSpreadable symbol property.
'ArrayOf',
'ArrayPrototypePush',
'ArrayPrototypeUnshift',
// 'FunctionPrototypeCall' is omitted, since there's 'ReflectApply'
// and 'FunctionPrototypeApply'.
'MathHypot',
'MathMax',
'MathMin',
'StringPrototypeConcat',
'TypedArrayOf',
];
function getNewKey(key) {
return typeof key === 'symbol' ?
`Symbol${key.description[7].toUpperCase()}${key.description.slice(8)}` :
@@ -51,7 +77,13 @@ function copyPropsRenamed(src, dest, prefix) {
if ('get' in desc) {
copyAccessor(dest, prefix, newKey, desc);
} else {
ReflectDefineProperty(dest, `${prefix}${newKey}`, desc);
const name = `${prefix}${newKey}`;
ReflectDefineProperty(dest, name, desc);
if (varargsMethods.includes(name)) {
ReflectDefineProperty(dest, `${name}Apply`, {
value: applyBind(desc.value, src),
});
}
}
}
}
@@ -63,10 +95,18 @@ function copyPropsRenamedBound(src, dest, prefix) {
if ('get' in desc) {
copyAccessor(dest, prefix, newKey, desc);
} else {
if (typeof desc.value === 'function') {
desc.value = desc.value.bind(src);
const { value } = desc;
if (typeof value === 'function') {
desc.value = value.bind(src);
}
const name = `${prefix}${newKey}`;
ReflectDefineProperty(dest, name, desc);
if (varargsMethods.includes(name)) {
ReflectDefineProperty(dest, `${name}Apply`, {
value: applyBind(value, src),
});
}
ReflectDefineProperty(dest, `${prefix}${newKey}`, desc);
}
}
}
@@ -78,10 +118,18 @@ function copyPrototype(src, dest, prefix) {
if ('get' in desc) {
copyAccessor(dest, prefix, newKey, desc);
} else {
if (typeof desc.value === 'function') {
desc.value = uncurryThis(desc.value);
const { value } = desc;
if (typeof value === 'function') {
desc.value = uncurryThis(value);
}
const name = `${prefix}${newKey}`;
ReflectDefineProperty(dest, name, desc);
if (varargsMethods.includes(name)) {
ReflectDefineProperty(dest, `${name}Apply`, {
value: applyBind(value),
});
}
ReflectDefineProperty(dest, `${prefix}${newKey}`, desc);
}
}
}
+3 -2
View File
@@ -6,6 +6,7 @@ const {
ArrayPrototypeFilter,
ArrayPrototypeForEach,
ArrayPrototypePush,
ArrayPrototypePushApply,
ArrayPrototypeSort,
ArrayPrototypeUnshift,
BigIntPrototypeValueOf,
@@ -665,7 +666,7 @@ function getKeys(value, showHidden) {
if (showHidden) {
keys = ObjectGetOwnPropertyNames(value);
if (symbols.length !== 0)
ArrayPrototypePush(keys, ...symbols);
ArrayPrototypePushApply(keys, symbols);
} else {
// This might throw if `value` is a Module Namespace Object from an
// unevaluated module, but we don't want to perform the actual type
@@ -681,7 +682,7 @@ function getKeys(value, showHidden) {
}
if (symbols.length !== 0) {
const filter = (key) => ObjectPrototypePropertyIsEnumerable(value, key);
ArrayPrototypePush(keys, ...ArrayPrototypeFilter(symbols, filter));
ArrayPrototypePushApply(keys, ArrayPrototypeFilter(symbols, filter));
}
}
return keys;
+1
View File
@@ -1313,6 +1313,7 @@ function complete(line, callback) {
if (!this.useGlobal) {
// When the context is not `global`, builtins are not own
// properties of it.
// `globalBuiltins` is a `SafeSet`, not an Array-like.
ArrayPrototypePush(contextOwnNames, ...globalBuiltins);
}
ArrayPrototypePush(completionGroups, contextOwnNames);