Skip to content

Commit

Permalink
lib: add bound apply variants of varargs primordials
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
ExE-Boss authored and targos committed Sep 1, 2021
1 parent 7cdff9a commit b24b34e
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 10 deletions.
64 changes: 56 additions & 8 deletions lib/internal/per_context/primordials.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,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)}` :
Expand All @@ -49,7 +75,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),
});
}
}
}
}
Expand All @@ -61,10 +93,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);
}
}
}
Expand All @@ -76,10 +116,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);
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions lib/internal/util/inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const {
Array,
ArrayIsArray,
ArrayPrototypeFilter,
ArrayPrototypePushApply,
BigIntPrototypeValueOf,
BooleanPrototypeValueOf,
DatePrototypeGetTime,
Expand Down Expand Up @@ -653,7 +654,7 @@ function getKeys(value, showHidden) {
if (showHidden) {
keys = ObjectGetOwnPropertyNames(value);
if (symbols.length !== 0)
keys.push(...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
Expand All @@ -669,7 +670,7 @@ function getKeys(value, showHidden) {
}
if (symbols.length !== 0) {
const filter = (key) => ObjectPrototypePropertyIsEnumerable(value, key);
keys.push(...symbols.filter(filter));
ArrayPrototypePushApply(keys, ArrayPrototypeFilter(symbols, filter));
}
}
return keys;
Expand Down
1 change: 1 addition & 0 deletions lib/repl.js
Original file line number Diff line number Diff line change
Expand Up @@ -1343,6 +1343,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);
Expand Down

0 comments on commit b24b34e

Please sign in to comment.