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>
  • Loading branch information
ExE-Boss and aduh95 committed Jan 20, 2021
1 parent e3e054d commit 60dab86
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 12 deletions.
56 changes: 48 additions & 8 deletions lib/internal/per_context/primordials.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,28 @@ 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;

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 = [
'ArrayPrototypePush',
'ArrayPrototypeUnshift',
'ArrayOf',
'MathMax',
'MathMin',
'MathHypot',
'StringPrototypeConcat',
'TypedArrayOf',
];

function getNewKey(key) {
return typeof key === 'symbol' ?
`Symbol${key.description[7].toUpperCase()}${key.description.slice(8)}` :
Expand All @@ -51,7 +69,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 @@ -63,10 +87,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 @@ -78,10 +110,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, src),
});
}
ReflectDefineProperty(dest, `${prefix}${newKey}`, desc);
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion lib/internal/process/per_thread.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const {
ArrayIsArray,
ArrayPrototypeMap,
ArrayPrototypePush,
ArrayPrototypePushApply,
ArrayPrototypeSplice,
BigUint64Array,
Float64Array,
Expand Down Expand Up @@ -274,7 +275,7 @@ function buildAllowedFlags() {
if (recursiveExpansion) {
if (recursiveExpansion[0] === to)
ArrayPrototypeSplice(recursiveExpansion, 0, 1);
ArrayPrototypePush(expansion, ...recursiveExpansion);
ArrayPrototypePushApply(expansion, recursiveExpansion);
continue;
}
isAccepted = options.get(to).envVarSettings === kAllowedInEnvironment;
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 @@ -6,6 +6,7 @@ const {
ArrayPrototypeFilter,
ArrayPrototypeForEach,
ArrayPrototypePush,
ArrayPrototypePushApply,
ArrayPrototypeSort,
ArrayPrototypeUnshift,
BigIntPrototypeValueOf,
Expand Down Expand Up @@ -664,7 +665,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
Expand All @@ -680,7 +681,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;
Expand Down
3 changes: 2 additions & 1 deletion lib/repl.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const {
ArrayPrototypeMap,
ArrayPrototypePop,
ArrayPrototypePush,
ArrayPrototypePushApply,
ArrayPrototypeReverse,
ArrayPrototypeShift,
ArrayPrototypeSort,
Expand Down Expand Up @@ -1310,7 +1311,7 @@ function complete(line, callback) {
if (!this.useGlobal) {
// When the context is not `global`, builtins are not own
// properties of it.
ArrayPrototypePush(contextOwnNames, ...globalBuiltins);
ArrayPrototypePushApply(contextOwnNames, globalBuiltins);
}
ArrayPrototypePush(completionGroups, contextOwnNames);
if (filter !== '') addCommonWords(completionGroups);
Expand Down

0 comments on commit 60dab86

Please sign in to comment.