@@ -21,10 +21,36 @@ const {
2121// `uncurryThis` is equivalent to `func => Function.prototype.call.bind(func)`.
2222// It is using `bind.bind(call)` to avoid using `Function.prototype.bind`
2323// and `Function.prototype.call` after it may have been mutated by users.
24- const { bind, call } = Function . prototype ;
24+ const { apply , bind, call } = Function . prototype ;
2525const uncurryThis = bind . bind ( call ) ;
2626primordials . uncurryThis = uncurryThis ;
2727
28+ // `applyBind` is equivalent to `func => Function.prototype.apply.bind(func)`.
29+ // It is using `bind.bind(apply)` to avoid using `Function.prototype.bind`
30+ // and `Function.prototype.apply` after it may have been mutated by users.
31+ const applyBind = bind . bind ( apply ) ;
32+ primordials . applyBind = applyBind ;
33+
34+ // Methods that accept a variable number of arguments, and thus it's useful to
35+ // also create `${prefix}${key}Apply`, which uses `Function.prototype.apply`,
36+ // instead of `Function.prototype.call`, and thus doesn't require iterator
37+ // destructuring.
38+ const varargsMethods = [
39+ // 'ArrayPrototypeConcat' is omitted, because it performs the spread
40+ // on its own for arrays and array-likes with a truthy
41+ // @@isConcatSpreadable symbol property.
42+ 'ArrayOf' ,
43+ 'ArrayPrototypePush' ,
44+ 'ArrayPrototypeUnshift' ,
45+ // 'FunctionPrototypeCall' is omitted, since there's 'ReflectApply'
46+ // and 'FunctionPrototypeApply'.
47+ 'MathHypot' ,
48+ 'MathMax' ,
49+ 'MathMin' ,
50+ 'StringPrototypeConcat' ,
51+ 'TypedArrayOf' ,
52+ ] ;
53+
2854function getNewKey ( key ) {
2955 return typeof key === 'symbol' ?
3056 `Symbol${ key . description [ 7 ] . toUpperCase ( ) } ${ key . description . slice ( 8 ) } ` :
@@ -51,7 +77,13 @@ function copyPropsRenamed(src, dest, prefix) {
5177 if ( 'get' in desc ) {
5278 copyAccessor ( dest , prefix , newKey , desc ) ;
5379 } else {
54- ReflectDefineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
80+ const name = `${ prefix } ${ newKey } ` ;
81+ ReflectDefineProperty ( dest , name , desc ) ;
82+ if ( varargsMethods . includes ( name ) ) {
83+ ReflectDefineProperty ( dest , `${ name } Apply` , {
84+ value : applyBind ( desc . value , src ) ,
85+ } ) ;
86+ }
5587 }
5688 }
5789}
@@ -63,10 +95,18 @@ function copyPropsRenamedBound(src, dest, prefix) {
6395 if ( 'get' in desc ) {
6496 copyAccessor ( dest , prefix , newKey , desc ) ;
6597 } else {
66- if ( typeof desc . value === 'function' ) {
67- desc . value = desc . value . bind ( src ) ;
98+ const { value } = desc ;
99+ if ( typeof value === 'function' ) {
100+ desc . value = value . bind ( src ) ;
101+ }
102+
103+ const name = `${ prefix } ${ newKey } ` ;
104+ ReflectDefineProperty ( dest , name , desc ) ;
105+ if ( varargsMethods . includes ( name ) ) {
106+ ReflectDefineProperty ( dest , `${ name } Apply` , {
107+ value : applyBind ( value , src ) ,
108+ } ) ;
68109 }
69- ReflectDefineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
70110 }
71111 }
72112}
@@ -78,10 +118,18 @@ function copyPrototype(src, dest, prefix) {
78118 if ( 'get' in desc ) {
79119 copyAccessor ( dest , prefix , newKey , desc ) ;
80120 } else {
81- if ( typeof desc . value === 'function' ) {
82- desc . value = uncurryThis ( desc . value ) ;
121+ const { value } = desc ;
122+ if ( typeof value === 'function' ) {
123+ desc . value = uncurryThis ( value ) ;
124+ }
125+
126+ const name = `${ prefix } ${ newKey } ` ;
127+ ReflectDefineProperty ( dest , name , desc ) ;
128+ if ( varargsMethods . includes ( name ) ) {
129+ ReflectDefineProperty ( dest , `${ name } Apply` , {
130+ value : applyBind ( value ) ,
131+ } ) ;
83132 }
84- ReflectDefineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
85133 }
86134 }
87135}
0 commit comments