@@ -21,10 +21,36 @@ const {
21
21
// `uncurryThis` is equivalent to `func => Function.prototype.call.bind(func)`.
22
22
// It is using `bind.bind(call)` to avoid using `Function.prototype.bind`
23
23
// 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 ;
25
25
const uncurryThis = bind . bind ( call ) ;
26
26
primordials . uncurryThis = uncurryThis ;
27
27
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
+
28
54
function getNewKey ( key ) {
29
55
return typeof key === 'symbol' ?
30
56
`Symbol${ key . description [ 7 ] . toUpperCase ( ) } ${ key . description . slice ( 8 ) } ` :
@@ -51,7 +77,13 @@ function copyPropsRenamed(src, dest, prefix) {
51
77
if ( 'get' in desc ) {
52
78
copyAccessor ( dest , prefix , newKey , desc ) ;
53
79
} 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
+ }
55
87
}
56
88
}
57
89
}
@@ -63,10 +95,18 @@ function copyPropsRenamedBound(src, dest, prefix) {
63
95
if ( 'get' in desc ) {
64
96
copyAccessor ( dest , prefix , newKey , desc ) ;
65
97
} 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
+ } ) ;
68
109
}
69
- ReflectDefineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
70
110
}
71
111
}
72
112
}
@@ -78,10 +118,18 @@ function copyPrototype(src, dest, prefix) {
78
118
if ( 'get' in desc ) {
79
119
copyAccessor ( dest , prefix , newKey , desc ) ;
80
120
} 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
+ } ) ;
83
132
}
84
- ReflectDefineProperty ( dest , `${ prefix } ${ newKey } ` , desc ) ;
85
133
}
86
134
}
87
135
}
0 commit comments