@@ -19,10 +19,36 @@ const {
19
19
// `uncurryThis` is equivalent to `func => Function.prototype.call.bind(func)`.
20
20
// It is using `bind.bind(call)` to avoid using `Function.prototype.bind`
21
21
// 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 ;
23
23
const uncurryThis = bind . bind ( call ) ;
24
24
primordials . uncurryThis = uncurryThis ;
25
25
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
+
26
52
function getNewKey ( key ) {
27
53
return typeof key === 'symbol' ?
28
54
`Symbol${ key . description [ 7 ] . toUpperCase ( ) } ${ key . description . slice ( 8 ) } ` :
@@ -49,7 +75,13 @@ function copyPropsRenamed(src, dest, prefix) {
49
75
if ( 'get' in desc ) {
50
76
copyAccessor ( dest , prefix , newKey , desc ) ;
51
77
} 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
+ }
53
85
}
54
86
}
55
87
}
@@ -61,10 +93,18 @@ function copyPropsRenamedBound(src, dest, prefix) {
61
93
if ( 'get' in desc ) {
62
94
copyAccessor ( dest , prefix , newKey , desc ) ;
63
95
} 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
+ } ) ;
66
107
}
67
- ReflectDefineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
68
108
}
69
109
}
70
110
}
@@ -76,10 +116,18 @@ function copyPrototype(src, dest, prefix) {
76
116
if ( 'get' in desc ) {
77
117
copyAccessor ( dest , prefix , newKey , desc ) ;
78
118
} 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
+ } ) ;
81
130
}
82
- ReflectDefineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
83
131
}
84
132
}
85
133
}
0 commit comments