From 1a3c1cab7b5a042905899aa2449915bebe3082fd Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Thu, 6 Jan 2022 14:53:54 +0700 Subject: [PATCH] avoid internal usage of third-party `.bind` polyfills, close #1034 --- packages/core-js/internals/function-apply.js | 5 +++-- packages/core-js/internals/function-bind-context.js | 3 ++- packages/core-js/internals/function-bind-native.js | 7 +++++++ packages/core-js/internals/function-bind.js | 10 +++------- packages/core-js/internals/function-call.js | 4 +++- packages/core-js/internals/function-uncurry-this.js | 6 ++++-- tests/compat/tests.js | 5 +++-- 7 files changed, 25 insertions(+), 15 deletions(-) create mode 100644 packages/core-js/internals/function-bind-native.js diff --git a/packages/core-js/internals/function-apply.js b/packages/core-js/internals/function-apply.js index 6524ffd7cb38..d9051329420d 100644 --- a/packages/core-js/internals/function-apply.js +++ b/packages/core-js/internals/function-apply.js @@ -1,9 +1,10 @@ +var NATIVE_BIND = require('../internals/function-bind-native'); + var FunctionPrototype = Function.prototype; var apply = FunctionPrototype.apply; -var bind = FunctionPrototype.bind; var call = FunctionPrototype.call; // eslint-disable-next-line es/no-reflect -- safe -module.exports = typeof Reflect == 'object' && Reflect.apply || (bind ? call.bind(apply) : function () { +module.exports = typeof Reflect == 'object' && Reflect.apply || (NATIVE_BIND ? call.bind(apply) : function () { return call.apply(apply, arguments); }); diff --git a/packages/core-js/internals/function-bind-context.js b/packages/core-js/internals/function-bind-context.js index 91b6bdec1eab..4409ae0da26c 100644 --- a/packages/core-js/internals/function-bind-context.js +++ b/packages/core-js/internals/function-bind-context.js @@ -1,12 +1,13 @@ var uncurryThis = require('../internals/function-uncurry-this'); var aCallable = require('../internals/a-callable'); +var NATIVE_BIND = require('../internals/function-bind-native'); var bind = uncurryThis(uncurryThis.bind); // optional / simple context binding module.exports = function (fn, that) { aCallable(fn); - return that === undefined ? fn : bind ? bind(fn, that) : function (/* ...args */) { + return that === undefined ? fn : NATIVE_BIND ? bind(fn, that) : function (/* ...args */) { return fn.apply(that, arguments); }; }; diff --git a/packages/core-js/internals/function-bind-native.js b/packages/core-js/internals/function-bind-native.js new file mode 100644 index 000000000000..3b03405a7e43 --- /dev/null +++ b/packages/core-js/internals/function-bind-native.js @@ -0,0 +1,7 @@ +var fails = require('../internals/fails'); + +module.exports = !fails(function () { + var test = (function () { /* empty */ }).bind(); + // eslint-disable-next-line no-prototype-builtins -- safe + return typeof test != 'function' || test.hasOwnProperty('prototype'); +}); diff --git a/packages/core-js/internals/function-bind.js b/packages/core-js/internals/function-bind.js index 18a09308becd..d0a4d660825b 100644 --- a/packages/core-js/internals/function-bind.js +++ b/packages/core-js/internals/function-bind.js @@ -1,11 +1,11 @@ 'use strict'; var global = require('../internals/global'); var uncurryThis = require('../internals/function-uncurry-this'); -var fails = require('../internals/fails'); var aCallable = require('../internals/a-callable'); var isObject = require('../internals/is-object'); var hasOwn = require('../internals/has-own-property'); var arraySlice = require('../internals/array-slice'); +var NATIVE_BIND = require('../internals/function-bind-native'); var Function = global.Function; var concat = uncurryThis([].concat); @@ -21,11 +21,7 @@ var construct = function (C, argsLength, args) { // `Function.prototype.bind` method implementation // https://tc39.es/ecma262/#sec-function.prototype.bind -module.exports = fails(function () { - // detect broken third-party polyfills - var Test = function () { /* empty */ }; - return !(new (Test.bind())() instanceof Test) || (function (a, b) { return this + a + b; }).bind(1, 2)(3) !== 6; -}) ? function bind(that /* , ...args */) { +module.exports = NATIVE_BIND ? Function.bind : function bind(that /* , ...args */) { var F = aCallable(this); var Prototype = F.prototype; var partArgs = arraySlice(arguments, 1); @@ -35,4 +31,4 @@ module.exports = fails(function () { }; if (isObject(Prototype)) boundFunction.prototype = Prototype; return boundFunction; -} : Function.bind; +}; diff --git a/packages/core-js/internals/function-call.js b/packages/core-js/internals/function-call.js index 25ac8dadab40..7ef02adb12cc 100644 --- a/packages/core-js/internals/function-call.js +++ b/packages/core-js/internals/function-call.js @@ -1,5 +1,7 @@ +var NATIVE_BIND = require('../internals/function-bind-native'); + var call = Function.prototype.call; -module.exports = call.bind ? call.bind(call) : function () { +module.exports = NATIVE_BIND ? call.bind(call) : function () { return call.apply(call, arguments); }; diff --git a/packages/core-js/internals/function-uncurry-this.js b/packages/core-js/internals/function-uncurry-this.js index 2b88d2a53389..4e6de173264f 100644 --- a/packages/core-js/internals/function-uncurry-this.js +++ b/packages/core-js/internals/function-uncurry-this.js @@ -1,9 +1,11 @@ +var NATIVE_BIND = require('../internals/function-bind-native'); + var FunctionPrototype = Function.prototype; var bind = FunctionPrototype.bind; var call = FunctionPrototype.call; -var uncurryThis = bind && bind.bind(call, call); +var uncurryThis = NATIVE_BIND && bind.bind(call, call); -module.exports = bind ? function (fn) { +module.exports = NATIVE_BIND ? function (fn) { return fn && uncurryThis(fn); } : function (fn) { return fn && function () { diff --git a/tests/compat/tests.js b/tests/compat/tests.js index 46558231c06f..f424819a6c46 100644 --- a/tests/compat/tests.js +++ b/tests/compat/tests.js @@ -528,8 +528,9 @@ GLOBAL.tests = { return escape; }, 'es.function.bind': function () { - var Test = function () { /* empty */ }; - return (new (Test.bind())() instanceof Test) && (function (a, b) { return this + a + b; }).bind(1, 2)(3) === 6; + var test = (function () { /* empty */ }).bind(); + // eslint-disable-next-line no-prototype-builtins -- safe + return typeof test == 'function' && !test.hasOwnProperty('prototype'); }, 'es.function.has-instance': [SYMBOLS_SUPPORT, function () { return Symbol.hasInstance in Function.prototype;