| function assert(cond, msg = "") { |
| if (!cond) |
| throw new Error(msg); |
| } |
| noInline(assert); |
| |
| function shouldThrow(func) { |
| var hadError = false; |
| try { |
| func() |
| } catch (e) { |
| hadError = true; |
| } |
| assert(hadError, "Did not throw"); |
| } |
| noInline(shouldThrow); |
| |
| function shouldThrowSyntaxError(str) { |
| var hadError = false; |
| try { |
| eval(str); |
| } catch (e) { |
| if (e instanceof SyntaxError) |
| hadError = true; |
| } |
| assert(hadError, "Did not throw syntax error"); |
| } |
| noInline(shouldThrowSyntaxError); |
| |
| function shouldThrowTDZ(func) { |
| var hasThrown = false; |
| try { |
| func(); |
| } catch(e) { |
| if (e.name.indexOf("ReferenceError") !== -1) |
| hasThrown = true; |
| } |
| assert(hasThrown); |
| } |
| noInline(shouldThrowTDZ); |
| |
| function basic(x, y=x) { |
| assert(y === x, "basics don't work.") |
| } |
| basic(20); |
| basic("hello"); |
| basic({foo: 20}); |
| basic(undefined); |
| |
| ;(function(){ |
| var scopeVariable = {hello: "world"}; |
| function basicScope(x = scopeVariable) { |
| assert(x === scopeVariable); |
| } |
| basicScope(); |
| })(); |
| |
| function basicFunctionCaptureInDefault(theArg = 20, y = function() {return theArg}) { |
| assert(theArg === y(), "y should return x."); |
| theArg = {}; |
| assert(theArg === y(), "y should return x."); |
| } |
| basicFunctionCaptureInDefault() |
| basicFunctionCaptureInDefault(undefined) |
| |
| function basicCaptured(x = 20, y = x) { |
| assert(x === y, "y should equal x"); |
| function mutate() { x = "mutation"; } |
| mutate() |
| assert(x !== y, "y should not equal x"); |
| } |
| basicCaptured() |
| basicCaptured(undefined) |
| |
| function tricky(globalX = (globalX = "x"), y = (globalX = 20)) { |
| assert(globalX === 20); |
| assert(globalX === y); |
| } |
| shouldThrow(tricky); |
| |
| function strict(x, y = x) { |
| assert(x === y); |
| } |
| strict(20); |
| strict(undefined); |
| |
| function playground(x = "foo", y = "bar") { |
| return {x, y} |
| } |
| assert(playground().x === "foo") |
| assert(playground(undefined).x === "foo") |
| assert(playground(undefined, 20).x === "foo") |
| assert(playground(null).x === null) |
| assert(playground().y === "bar") |
| assert(playground(undefined, undefined).y === "bar") |
| assert(playground("hello", undefined).y === "bar") |
| assert(playground("bar").x === playground(undefined, undefined).y) |
| assert(playground(10).x === 10) |
| assert(playground(undefined, 20).y === 20) |
| assert(playground(undefined, null).y === null) |
| |
| function scoping(f = function() { return local;}) { |
| shouldThrow(f); |
| var local = 10; |
| shouldThrow(f); |
| } |
| scoping(); |
| |
| function augmentsArguments1(x = 20) { |
| assert(x === 20); |
| |
| arguments[0] = 10; |
| assert(x === 20); |
| |
| x = 15; |
| assert(x === 15); |
| assert(arguments[0] === 10); |
| } |
| augmentsArguments1(undefined); |
| |
| function augmentsArguments2(x = 20) { |
| assert(x === 20); |
| |
| arguments[0] = 10; |
| assert(x === 20); |
| assert(arguments[0] === 10); |
| |
| x = 15; |
| assert(x === 15); |
| assert(arguments[0] === 10); |
| |
| function augment() { x = 40 } |
| augment() |
| assert(x === 40); |
| assert(arguments[0] === 10); |
| } |
| augmentsArguments2(undefined); |
| |
| function augmentsArguments3(x = 10) { |
| assert(x === 10); |
| |
| assert(arguments[0] === undefined); |
| x = 20; |
| assert(arguments[0] === undefined); |
| } |
| augmentsArguments3(); |
| |
| function augmentsArguments4(x) { |
| "use strict"; |
| function inner(x = 10) { |
| assert(x === 10); |
| |
| assert(arguments[0] === undefined); |
| x = 20; |
| assert(arguments[0] === undefined); |
| } |
| inner(x); |
| } |
| augmentsArguments4(); |
| augmentsArguments4(undefined); |
| |
| function augmentsArguments5(x) { |
| "use strict"; |
| function inner(x = 10) { |
| assert(x === 20); |
| |
| assert(arguments[0] === 20); |
| x = 20; |
| assert(arguments[0] === 20); |
| } |
| inner(x); |
| } |
| augmentsArguments5(20); |
| |
| ;(function () { |
| var outer = "outer"; |
| function foo(a = outer, b = function() { return a; }, c = function(v) { a = v; }) { |
| var a; |
| assert(a === "outer"); |
| a = 20; |
| assert(a === 20); |
| assert(b() === "outer"); |
| c("hello"); |
| assert(b() === "hello"); |
| } |
| |
| function bar(a = outer, b = function() { return a; }, c = function(v) { a = v; }) { |
| with({}) { |
| var a; |
| assert(a === "outer"); |
| a = 20; |
| assert(a === 20); |
| assert(b() === "outer"); |
| c("hello"); |
| assert(b() === "hello"); |
| } |
| } |
| |
| function baz(x = function() { return y; }, y = "y") { |
| assert(x() === "y"); |
| assert(x() === y); |
| assert(y === y); |
| } |
| |
| function jaz(x = function() { return y; }, y = "y") { |
| return x; |
| } |
| |
| function taz(x = 10, y = eval("x + 1")) { |
| assert(y === 11); |
| } |
| |
| for (var i = 0; i < 1000; i++) { |
| foo(); |
| bar(); |
| baz(); |
| assert(jaz(undefined, 20)() === 20); |
| assert(jaz(undefined, undefined)() === "y"); |
| assert(jaz(undefined, {x: "x"})().x === "x"); |
| taz(); |
| } |
| })(); |
| |
| // Length |
| |
| function named1(a){}; |
| function named2(a=1){}; |
| function named3(a,b){}; |
| function named4(a,b=1){}; |
| function named5(a=1,b=1){}; |
| function named6(a,b,c){}; |
| function named7(a=1,b,c){}; |
| function named8(a,b=1,c){}; |
| function named9(a,b,c=1){}; |
| function named10(a,...b){}; |
| function named11(a=1,...b){}; |
| function named12(a=10,b,c=20,...r){}; |
| |
| assert( named1.length === 1 ); |
| assert( named2.length === 0 ); |
| assert( named3.length === 2 ); |
| assert( named4.length === 1 ); |
| assert( named5.length === 0 ); |
| assert( named6.length === 3 ); |
| assert( named7.length === 0 ); |
| assert( named8.length === 1 ); |
| assert( named9.length === 2 ); |
| assert( named10.length === 1 ); |
| assert( named11.length === 0 ); |
| assert( named12.length === 0 ); |
| |
| assert( (function(a){}).length === 1 ); |
| assert( (function(a=1){}).length === 0 ); |
| assert( (function(a,b){}).length === 2 ); |
| assert( (function(a,b=1){}).length === 1 ); |
| assert( (function(a=1,b=1){}).length === 0 ); |
| assert( (function(a,b,c){}).length === 3 ); |
| assert( (function(a=1,b,c){}).length === 0 ); |
| assert( (function(a,b=1,c){}).length === 1 ); |
| assert( (function(a,b,c=1){}).length === 2 ); |
| assert( (function(a,...b){}).length === 1 ); |
| assert( (function(a=1,...b){}).length === 0 ); |
| assert( (function(a=10,b,c=20,...r){}).length === 0 ); |
| |
| assert( (function*(a){}).length === 1 ); |
| assert( (function*(a=1){}).length === 0 ); |
| assert( (function*(a,b){}).length === 2 ); |
| assert( (function*(a,b=1){}).length === 1 ); |
| assert( (function*(a=1,b=1){}).length === 0 ); |
| assert( (function*(a,b,c){}).length === 3 ); |
| assert( (function*(a=1,b,c){}).length === 0 ); |
| assert( (function*(a,b=1,c){}).length === 1 ); |
| assert( (function*(a,b,c=1){}).length === 2 ); |
| assert( (function*(a,...b){}).length === 1 ); |
| assert( (function*(a=1,...b){}).length === 0 ); |
| assert( (function*(a=10,b,c=20,...r){}).length === 0 ); |
| |
| assert( ((a)=>{}).length === 1 ); |
| assert( ((a=1)=>{}).length === 0 ); |
| assert( ((a,b)=>{}).length === 2 ); |
| assert( ((a,b=1)=>{}).length === 1 ); |
| assert( ((a=1,b=1)=>{}).length === 0 ); |
| assert( ((a,b,c)=>{}).length === 3 ); |
| assert( ((a=1,b,c)=>{}).length === 0 ); |
| assert( ((a,b=1,c)=>{}).length === 1 ); |
| assert( ((a,b,c=1)=>{}).length === 2 ); |
| assert( ((a,...b)=>{}).length === 1 ); |
| assert( ((a=1,...b)=>{}).length === 0 ); |
| assert( ((a=10,b,c=20,...r)=>{}).length === 0 ); |
| |
| assert( Object.getOwnPropertyDescriptor({set setter(a){}}, "setter").set.length === 1 ); |
| assert( Object.getOwnPropertyDescriptor({set setter(a=1){}}, "setter").set.length === 0 ); |
| |
| assert( ({method(a){}}).method.length === 1 ); |
| assert( ({method(a=1){}}).method.length === 0 ); |
| assert( ({method(a,b){}}).method.length === 2 ); |
| assert( ({method(a,b=1){}}).method.length === 1 ); |
| assert( ({method(a=1,b=1){}}).method.length === 0 ); |
| assert( ({method(a,b,c){}}).method.length === 3 ); |
| assert( ({method(a=1,b,c){}}).method.length === 0 ); |
| assert( ({method(a,b=1,c){}}).method.length === 1 ); |
| assert( ({method(a,b,c=1){}}).method.length === 2 ); |
| assert( ({method(a,...b){}}).method.length === 1 ); |
| assert( ({method(a=1,...b){}}).method.length === 0 ); |
| assert( ({method(a=10,b,c=20,...r){}}).method.length === 0 ); |
| |
| assert( ({*method(a){}}).method.length === 1 ); |
| assert( ({*method(a=1){}}).method.length === 0 ); |
| assert( ({*method(a,b){}}).method.length === 2 ); |
| assert( ({*method(a,b=1){}}).method.length === 1 ); |
| assert( ({*method(a=1,b=1){}}).method.length === 0 ); |
| assert( ({*method(a,b,c){}}).method.length === 3 ); |
| assert( ({*method(a=1,b,c){}}).method.length === 0 ); |
| assert( ({*method(a,b=1,c){}}).method.length === 1 ); |
| assert( ({*method(a,b,c=1){}}).method.length === 2 ); |
| assert( ({*method(a,...b){}}).method.length === 1 ); |
| assert( ({*method(a=1,...b){}}).method.length === 0 ); |
| assert( ({*method(a=10,b,c=20,...r){}}).method.length === 0 ); |
| |
| assert( (class {static method(a){}}).method.length === 1 ); |
| assert( (class {static method(a=1){}}).method.length === 0 ); |
| assert( (class {static method(a,b){}}).method.length === 2 ); |
| assert( (class {static method(a,b=1){}}).method.length === 1 ); |
| assert( (class {static method(a=1,b=1){}}).method.length === 0 ); |
| assert( (class {static method(a,b,c){}}).method.length === 3 ); |
| assert( (class {static method(a=1,b,c){}}).method.length === 0 ); |
| assert( (class {static method(a,b=1,c){}}).method.length === 1 ); |
| assert( (class {static method(a,b,c=1){}}).method.length === 2 ); |
| assert( (class {static method(a,...b){}}).method.length === 1 ); |
| assert( (class {static method(a=1,...b){}}).method.length === 0 ); |
| assert( (class {static method(a=10,b,c=20,...r){}}).method.length === 0 ); |
| |
| // TDZ errors. |
| ;(function() { |
| function basicError(x = y, y) { } |
| function basicError2(x = x) { } |
| function baz(z = {p: x}, x = z) {} |
| function bar(x = {p: [x]}) {} |
| function jaz(x = eval("y"), y) { } |
| function kaz(x = eval(";(function() { return y})();"), y) { } |
| for (var i = 0; i < 1000; i++) { |
| shouldThrowTDZ(basicError); |
| shouldThrowTDZ(basicError2); |
| shouldThrowTDZ(baz); |
| shouldThrowTDZ(bar); |
| shouldThrowTDZ(jaz); |
| shouldThrowTDZ(kaz); |
| } |
| })(); |
| |
| |
| // Test proper variable binding. |
| ;(function() { |
| function foo(a = function() { return b; }, {b}) { |
| assert(a() === 34); |
| assert(b === 34); |
| b = 50; |
| assert(a() === 50); |
| assert(b === 50); |
| } |
| function bar(a = function(x) { b = x; }, {b}) { |
| assert(b === 34); |
| a(50); |
| assert(b === 50); |
| } |
| function baz(f1 = function(x) { b = x; }, f2 = function() { return b; }, {b}) { |
| var b; |
| assert(b === 34); |
| assert(f2() === 34); |
| f1(50); |
| assert(b === 34); |
| assert(f2() === 50); |
| } |
| noInline(foo); |
| noInline(bar); |
| noInline(baz); |
| for (let i = 0; i < 1000; i++) { |
| foo(undefined, {b: 34}); |
| bar(undefined, {b: 34}); |
| baz(undefined, undefined, {b: 34}); |
| } |
| })(); |
| |
| |
| // Syntax errors. |
| shouldThrowSyntaxError("function b(a = 20, a = 40) {}"); |
| shouldThrowSyntaxError("function b(aaaaa = 20,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v, aaaaa = 40) {}"); |
| shouldThrowSyntaxError("function b(a = 20, {a}) {}"); |
| shouldThrowSyntaxError("function b(a = 20, a) {}"); |
| shouldThrowSyntaxError("function b(a, a = 20) {}"); |
| shouldThrowSyntaxError("function b(a, a, b = 20) {}"); |
| shouldThrowSyntaxError("function b({a, a} = 20) {}"); |
| shouldThrowSyntaxError("function b({a, a} = 20) {}"); |