11cb0ef41Sopenharmony_ci// jscs:disable requireUseStrict
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_civar test = require('tape');
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_civar functionBind = require('../implementation');
61cb0ef41Sopenharmony_civar getCurrentContext = function () { return this; };
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_citest('functionBind is a function', function (t) {
91cb0ef41Sopenharmony_ci    t.equal(typeof functionBind, 'function');
101cb0ef41Sopenharmony_ci    t.end();
111cb0ef41Sopenharmony_ci});
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_citest('non-functions', function (t) {
141cb0ef41Sopenharmony_ci    var nonFunctions = [true, false, [], {}, 42, 'foo', NaN, /a/g];
151cb0ef41Sopenharmony_ci    t.plan(nonFunctions.length);
161cb0ef41Sopenharmony_ci    for (var i = 0; i < nonFunctions.length; ++i) {
171cb0ef41Sopenharmony_ci        try { functionBind.call(nonFunctions[i]); } catch (ex) {
181cb0ef41Sopenharmony_ci            t.ok(ex instanceof TypeError, 'throws when given ' + String(nonFunctions[i]));
191cb0ef41Sopenharmony_ci        }
201cb0ef41Sopenharmony_ci    }
211cb0ef41Sopenharmony_ci    t.end();
221cb0ef41Sopenharmony_ci});
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_citest('without a context', function (t) {
251cb0ef41Sopenharmony_ci    t.test('binds properly', function (st) {
261cb0ef41Sopenharmony_ci        var args, context;
271cb0ef41Sopenharmony_ci        var namespace = {
281cb0ef41Sopenharmony_ci            func: functionBind.call(function () {
291cb0ef41Sopenharmony_ci                args = Array.prototype.slice.call(arguments);
301cb0ef41Sopenharmony_ci                context = this;
311cb0ef41Sopenharmony_ci            })
321cb0ef41Sopenharmony_ci        };
331cb0ef41Sopenharmony_ci        namespace.func(1, 2, 3);
341cb0ef41Sopenharmony_ci        st.deepEqual(args, [1, 2, 3]);
351cb0ef41Sopenharmony_ci        st.equal(context, getCurrentContext.call());
361cb0ef41Sopenharmony_ci        st.end();
371cb0ef41Sopenharmony_ci    });
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci    t.test('binds properly, and still supplies bound arguments', function (st) {
401cb0ef41Sopenharmony_ci        var args, context;
411cb0ef41Sopenharmony_ci        var namespace = {
421cb0ef41Sopenharmony_ci            func: functionBind.call(function () {
431cb0ef41Sopenharmony_ci                args = Array.prototype.slice.call(arguments);
441cb0ef41Sopenharmony_ci                context = this;
451cb0ef41Sopenharmony_ci            }, undefined, 1, 2, 3)
461cb0ef41Sopenharmony_ci        };
471cb0ef41Sopenharmony_ci        namespace.func(4, 5, 6);
481cb0ef41Sopenharmony_ci        st.deepEqual(args, [1, 2, 3, 4, 5, 6]);
491cb0ef41Sopenharmony_ci        st.equal(context, getCurrentContext.call());
501cb0ef41Sopenharmony_ci        st.end();
511cb0ef41Sopenharmony_ci    });
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci    t.test('returns properly', function (st) {
541cb0ef41Sopenharmony_ci        var args;
551cb0ef41Sopenharmony_ci        var namespace = {
561cb0ef41Sopenharmony_ci            func: functionBind.call(function () {
571cb0ef41Sopenharmony_ci                args = Array.prototype.slice.call(arguments);
581cb0ef41Sopenharmony_ci                return this;
591cb0ef41Sopenharmony_ci            }, null)
601cb0ef41Sopenharmony_ci        };
611cb0ef41Sopenharmony_ci        var context = namespace.func(1, 2, 3);
621cb0ef41Sopenharmony_ci        st.equal(context, getCurrentContext.call(), 'returned context is namespaced context');
631cb0ef41Sopenharmony_ci        st.deepEqual(args, [1, 2, 3], 'passed arguments are correct');
641cb0ef41Sopenharmony_ci        st.end();
651cb0ef41Sopenharmony_ci    });
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci    t.test('returns properly with bound arguments', function (st) {
681cb0ef41Sopenharmony_ci        var args;
691cb0ef41Sopenharmony_ci        var namespace = {
701cb0ef41Sopenharmony_ci            func: functionBind.call(function () {
711cb0ef41Sopenharmony_ci                args = Array.prototype.slice.call(arguments);
721cb0ef41Sopenharmony_ci                return this;
731cb0ef41Sopenharmony_ci            }, null, 1, 2, 3)
741cb0ef41Sopenharmony_ci        };
751cb0ef41Sopenharmony_ci        var context = namespace.func(4, 5, 6);
761cb0ef41Sopenharmony_ci        st.equal(context, getCurrentContext.call(), 'returned context is namespaced context');
771cb0ef41Sopenharmony_ci        st.deepEqual(args, [1, 2, 3, 4, 5, 6], 'passed arguments are correct');
781cb0ef41Sopenharmony_ci        st.end();
791cb0ef41Sopenharmony_ci    });
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci    t.test('called as a constructor', function (st) {
821cb0ef41Sopenharmony_ci        var thunkify = function (value) {
831cb0ef41Sopenharmony_ci            return function () { return value; };
841cb0ef41Sopenharmony_ci        };
851cb0ef41Sopenharmony_ci        st.test('returns object value', function (sst) {
861cb0ef41Sopenharmony_ci            var expectedReturnValue = [1, 2, 3];
871cb0ef41Sopenharmony_ci            var Constructor = functionBind.call(thunkify(expectedReturnValue), null);
881cb0ef41Sopenharmony_ci            var result = new Constructor();
891cb0ef41Sopenharmony_ci            sst.equal(result, expectedReturnValue);
901cb0ef41Sopenharmony_ci            sst.end();
911cb0ef41Sopenharmony_ci        });
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci        st.test('does not return primitive value', function (sst) {
941cb0ef41Sopenharmony_ci            var Constructor = functionBind.call(thunkify(42), null);
951cb0ef41Sopenharmony_ci            var result = new Constructor();
961cb0ef41Sopenharmony_ci            sst.notEqual(result, 42);
971cb0ef41Sopenharmony_ci            sst.end();
981cb0ef41Sopenharmony_ci        });
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci        st.test('object from bound constructor is instance of original and bound constructor', function (sst) {
1011cb0ef41Sopenharmony_ci            var A = function (x) {
1021cb0ef41Sopenharmony_ci                this.name = x || 'A';
1031cb0ef41Sopenharmony_ci            };
1041cb0ef41Sopenharmony_ci            var B = functionBind.call(A, null, 'B');
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci            var result = new B();
1071cb0ef41Sopenharmony_ci            sst.ok(result instanceof B, 'result is instance of bound constructor');
1081cb0ef41Sopenharmony_ci            sst.ok(result instanceof A, 'result is instance of original constructor');
1091cb0ef41Sopenharmony_ci            sst.end();
1101cb0ef41Sopenharmony_ci        });
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci        st.end();
1131cb0ef41Sopenharmony_ci    });
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci    t.end();
1161cb0ef41Sopenharmony_ci});
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_citest('with a context', function (t) {
1191cb0ef41Sopenharmony_ci    t.test('with no bound arguments', function (st) {
1201cb0ef41Sopenharmony_ci        var args, context;
1211cb0ef41Sopenharmony_ci        var boundContext = {};
1221cb0ef41Sopenharmony_ci        var namespace = {
1231cb0ef41Sopenharmony_ci            func: functionBind.call(function () {
1241cb0ef41Sopenharmony_ci                args = Array.prototype.slice.call(arguments);
1251cb0ef41Sopenharmony_ci                context = this;
1261cb0ef41Sopenharmony_ci            }, boundContext)
1271cb0ef41Sopenharmony_ci        };
1281cb0ef41Sopenharmony_ci        namespace.func(1, 2, 3);
1291cb0ef41Sopenharmony_ci        st.equal(context, boundContext, 'binds a context properly');
1301cb0ef41Sopenharmony_ci        st.deepEqual(args, [1, 2, 3], 'supplies passed arguments');
1311cb0ef41Sopenharmony_ci        st.end();
1321cb0ef41Sopenharmony_ci    });
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci    t.test('with bound arguments', function (st) {
1351cb0ef41Sopenharmony_ci        var args, context;
1361cb0ef41Sopenharmony_ci        var boundContext = {};
1371cb0ef41Sopenharmony_ci        var namespace = {
1381cb0ef41Sopenharmony_ci            func: functionBind.call(function () {
1391cb0ef41Sopenharmony_ci                args = Array.prototype.slice.call(arguments);
1401cb0ef41Sopenharmony_ci                context = this;
1411cb0ef41Sopenharmony_ci            }, boundContext, 1, 2, 3)
1421cb0ef41Sopenharmony_ci        };
1431cb0ef41Sopenharmony_ci        namespace.func(4, 5, 6);
1441cb0ef41Sopenharmony_ci        st.equal(context, boundContext, 'binds a context properly');
1451cb0ef41Sopenharmony_ci        st.deepEqual(args, [1, 2, 3, 4, 5, 6], 'supplies bound and passed arguments');
1461cb0ef41Sopenharmony_ci        st.end();
1471cb0ef41Sopenharmony_ci    });
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci    t.test('returns properly', function (st) {
1501cb0ef41Sopenharmony_ci        var boundContext = {};
1511cb0ef41Sopenharmony_ci        var args;
1521cb0ef41Sopenharmony_ci        var namespace = {
1531cb0ef41Sopenharmony_ci            func: functionBind.call(function () {
1541cb0ef41Sopenharmony_ci                args = Array.prototype.slice.call(arguments);
1551cb0ef41Sopenharmony_ci                return this;
1561cb0ef41Sopenharmony_ci            }, boundContext)
1571cb0ef41Sopenharmony_ci        };
1581cb0ef41Sopenharmony_ci        var context = namespace.func(1, 2, 3);
1591cb0ef41Sopenharmony_ci        st.equal(context, boundContext, 'returned context is bound context');
1601cb0ef41Sopenharmony_ci        st.notEqual(context, getCurrentContext.call(), 'returned context is not lexical context');
1611cb0ef41Sopenharmony_ci        st.deepEqual(args, [1, 2, 3], 'passed arguments are correct');
1621cb0ef41Sopenharmony_ci        st.end();
1631cb0ef41Sopenharmony_ci    });
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci    t.test('returns properly with bound arguments', function (st) {
1661cb0ef41Sopenharmony_ci        var boundContext = {};
1671cb0ef41Sopenharmony_ci        var args;
1681cb0ef41Sopenharmony_ci        var namespace = {
1691cb0ef41Sopenharmony_ci            func: functionBind.call(function () {
1701cb0ef41Sopenharmony_ci                args = Array.prototype.slice.call(arguments);
1711cb0ef41Sopenharmony_ci                return this;
1721cb0ef41Sopenharmony_ci            }, boundContext, 1, 2, 3)
1731cb0ef41Sopenharmony_ci        };
1741cb0ef41Sopenharmony_ci        var context = namespace.func(4, 5, 6);
1751cb0ef41Sopenharmony_ci        st.equal(context, boundContext, 'returned context is bound context');
1761cb0ef41Sopenharmony_ci        st.notEqual(context, getCurrentContext.call(), 'returned context is not lexical context');
1771cb0ef41Sopenharmony_ci        st.deepEqual(args, [1, 2, 3, 4, 5, 6], 'passed arguments are correct');
1781cb0ef41Sopenharmony_ci        st.end();
1791cb0ef41Sopenharmony_ci    });
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_ci    t.test('passes the correct arguments when called as a constructor', function (st) {
1821cb0ef41Sopenharmony_ci        var expected = { name: 'Correct' };
1831cb0ef41Sopenharmony_ci        var namespace = {
1841cb0ef41Sopenharmony_ci            Func: functionBind.call(function (arg) {
1851cb0ef41Sopenharmony_ci                return arg;
1861cb0ef41Sopenharmony_ci            }, { name: 'Incorrect' })
1871cb0ef41Sopenharmony_ci        };
1881cb0ef41Sopenharmony_ci        var returned = new namespace.Func(expected);
1891cb0ef41Sopenharmony_ci        st.equal(returned, expected, 'returns the right arg when called as a constructor');
1901cb0ef41Sopenharmony_ci        st.end();
1911cb0ef41Sopenharmony_ci    });
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ci    t.test('has the new instance\'s context when called as a constructor', function (st) {
1941cb0ef41Sopenharmony_ci        var actualContext;
1951cb0ef41Sopenharmony_ci        var expectedContext = { foo: 'bar' };
1961cb0ef41Sopenharmony_ci        var namespace = {
1971cb0ef41Sopenharmony_ci            Func: functionBind.call(function () {
1981cb0ef41Sopenharmony_ci                actualContext = this;
1991cb0ef41Sopenharmony_ci            }, expectedContext)
2001cb0ef41Sopenharmony_ci        };
2011cb0ef41Sopenharmony_ci        var result = new namespace.Func();
2021cb0ef41Sopenharmony_ci        st.equal(result instanceof namespace.Func, true);
2031cb0ef41Sopenharmony_ci        st.notEqual(actualContext, expectedContext);
2041cb0ef41Sopenharmony_ci        st.end();
2051cb0ef41Sopenharmony_ci    });
2061cb0ef41Sopenharmony_ci
2071cb0ef41Sopenharmony_ci    t.end();
2081cb0ef41Sopenharmony_ci});
2091cb0ef41Sopenharmony_ci
2101cb0ef41Sopenharmony_citest('bound function length', function (t) {
2111cb0ef41Sopenharmony_ci    t.test('sets a correct length without thisArg', function (st) {
2121cb0ef41Sopenharmony_ci        var subject = functionBind.call(function (a, b, c) { return a + b + c; });
2131cb0ef41Sopenharmony_ci        st.equal(subject.length, 3);
2141cb0ef41Sopenharmony_ci        st.equal(subject(1, 2, 3), 6);
2151cb0ef41Sopenharmony_ci        st.end();
2161cb0ef41Sopenharmony_ci    });
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ci    t.test('sets a correct length with thisArg', function (st) {
2191cb0ef41Sopenharmony_ci        var subject = functionBind.call(function (a, b, c) { return a + b + c; }, {});
2201cb0ef41Sopenharmony_ci        st.equal(subject.length, 3);
2211cb0ef41Sopenharmony_ci        st.equal(subject(1, 2, 3), 6);
2221cb0ef41Sopenharmony_ci        st.end();
2231cb0ef41Sopenharmony_ci    });
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ci    t.test('sets a correct length without thisArg and first argument', function (st) {
2261cb0ef41Sopenharmony_ci        var subject = functionBind.call(function (a, b, c) { return a + b + c; }, undefined, 1);
2271cb0ef41Sopenharmony_ci        st.equal(subject.length, 2);
2281cb0ef41Sopenharmony_ci        st.equal(subject(2, 3), 6);
2291cb0ef41Sopenharmony_ci        st.end();
2301cb0ef41Sopenharmony_ci    });
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_ci    t.test('sets a correct length with thisArg and first argument', function (st) {
2331cb0ef41Sopenharmony_ci        var subject = functionBind.call(function (a, b, c) { return a + b + c; }, {}, 1);
2341cb0ef41Sopenharmony_ci        st.equal(subject.length, 2);
2351cb0ef41Sopenharmony_ci        st.equal(subject(2, 3), 6);
2361cb0ef41Sopenharmony_ci        st.end();
2371cb0ef41Sopenharmony_ci    });
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci    t.test('sets a correct length without thisArg and too many arguments', function (st) {
2401cb0ef41Sopenharmony_ci        var subject = functionBind.call(function (a, b, c) { return a + b + c; }, undefined, 1, 2, 3, 4);
2411cb0ef41Sopenharmony_ci        st.equal(subject.length, 0);
2421cb0ef41Sopenharmony_ci        st.equal(subject(), 6);
2431cb0ef41Sopenharmony_ci        st.end();
2441cb0ef41Sopenharmony_ci    });
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_ci    t.test('sets a correct length with thisArg and too many arguments', function (st) {
2471cb0ef41Sopenharmony_ci        var subject = functionBind.call(function (a, b, c) { return a + b + c; }, {}, 1, 2, 3, 4);
2481cb0ef41Sopenharmony_ci        st.equal(subject.length, 0);
2491cb0ef41Sopenharmony_ci        st.equal(subject(), 6);
2501cb0ef41Sopenharmony_ci        st.end();
2511cb0ef41Sopenharmony_ci    });
2521cb0ef41Sopenharmony_ci});
253