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