@@ -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 ;
2323const uncurryThis = bind . bind ( call ) ;
2424primordials . 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+
2652function 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}
0 commit comments