1'use strict';
2
3var bind = require('function-bind');
4var GetIntrinsic = require('get-intrinsic');
5
6var $apply = GetIntrinsic('%Function.prototype.apply%');
7var $call = GetIntrinsic('%Function.prototype.call%');
8var $reflectApply = GetIntrinsic('%Reflect.apply%', true) || bind.call($call, $apply);
9
10var $gOPD = GetIntrinsic('%Object.getOwnPropertyDescriptor%', true);
11var $defineProperty = GetIntrinsic('%Object.defineProperty%', true);
12var $max = GetIntrinsic('%Math.max%');
13
14if ($defineProperty) {
15	try {
16		$defineProperty({}, 'a', { value: 1 });
17	} catch (e) {
18		// IE 8 has a broken defineProperty
19		$defineProperty = null;
20	}
21}
22
23module.exports = function callBind(originalFunction) {
24	var func = $reflectApply(bind, $call, arguments);
25	if ($gOPD && $defineProperty) {
26		var desc = $gOPD(func, 'length');
27		if (desc.configurable) {
28			// original length, plus the receiver, minus any additional arguments (after the receiver)
29			$defineProperty(
30				func,
31				'length',
32				{ value: 1 + $max(0, originalFunction.length - (arguments.length - 1)) }
33			);
34		}
35	}
36	return func;
37};
38
39var applyBind = function applyBind() {
40	return $reflectApply(bind, $apply, arguments);
41};
42
43if ($defineProperty) {
44	$defineProperty(module.exports, 'apply', { value: applyBind });
45} else {
46	module.exports.apply = applyBind;
47}
48