| // Copyright 2015 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| |
| (function TestClass() { |
| 'use strict'; |
| |
| var calls = 0; |
| class Base { |
| constructor(_) { |
| assertEquals(Base, new.target); |
| calls++; |
| } |
| } |
| assertInstanceof(new Base(1), Base); |
| assertInstanceof(new Base(1, 2), Base); |
| assertInstanceof(new Base(), Base); |
| assertEquals(3, calls); |
| })(); |
| |
| |
| (function TestDerivedClass() { |
| 'use strict'; |
| |
| var calls = 0; |
| class Base { |
| constructor(expected) { |
| assertEquals(expected, new.target); |
| } |
| } |
| class Derived extends Base { |
| constructor(expected) { |
| super(expected); |
| assertEquals(expected, new.target); |
| calls++; |
| } |
| } |
| new Derived(Derived, 'extra'); |
| new Derived(Derived); |
| assertEquals(2, calls); |
| |
| class Derived2 extends Derived {} |
| calls = 0; |
| new Derived2(Derived2); |
| new Derived2(Derived2, 'extra'); |
| assertEquals(2, calls); |
| })(); |
| |
| |
| (function TestFunctionCall() { |
| var calls; |
| function f(expected) { |
| calls++; |
| assertEquals(expected, new.target); |
| } |
| |
| calls = 0; |
| f(undefined); |
| f(undefined, 'extra'); |
| f(); |
| assertEquals(3, calls); |
| |
| calls = 0; |
| f.call({}, undefined); |
| f.call({}, undefined, 'extra'); |
| f.call({}); |
| assertEquals(3, calls); |
| |
| calls = 0; |
| f.apply({}, [undefined]); |
| f.apply({}, [undefined, 'extra']); |
| f.apply({}, []); |
| assertEquals(3, calls); |
| })(); |
| |
| |
| (function TestFunctionConstruct() { |
| var calls; |
| function f(expected) { |
| calls++; |
| assertEquals(expected, new.target); |
| } |
| |
| calls = 0; |
| new f(f); |
| new f(f, 'extra'); |
| assertEquals(2, calls); |
| })(); |
| |
| |
| (function TestClassExtendsFunction() { |
| 'use strict'; |
| |
| var calls = 0; |
| function f(expected) { |
| assertEquals(expected, new.target); |
| } |
| class Derived extends f { |
| constructor(expected) { |
| super(expected); |
| assertEquals(expected, new.target); |
| calls++; |
| } |
| } |
| |
| new Derived(Derived); |
| new Derived(Derived, 'extra'); |
| assertEquals(2, calls); |
| })(); |
| |
| |
| (function TestFunctionReturnObject() { |
| function f(expected) { |
| assertEquals(expected, new.target); |
| return /abc/; |
| } |
| |
| assertInstanceof(new f(f), RegExp); |
| assertInstanceof(new f(f, 'extra'), RegExp); |
| |
| assertInstanceof(f(undefined), RegExp); |
| assertInstanceof(f(), RegExp); |
| assertInstanceof(f(undefined, 'extra'), RegExp); |
| })(); |
| |
| |
| (function TestClassReturnObject() { |
| 'use strict'; |
| |
| class Base { |
| constructor(expected) { |
| assertEquals(expected, new.target); |
| return /abc/; |
| } |
| } |
| |
| assertInstanceof(new Base(Base), RegExp); |
| assertInstanceof(new Base(Base, 'extra'), RegExp); |
| |
| class Derived extends Base {} |
| assertInstanceof(new Derived(Derived), RegExp); |
| assertInstanceof(new Derived(Derived, 'extra'), RegExp); |
| |
| class Derived2 extends Base { |
| constructor(expected) { |
| super(expected); |
| assertInstanceof(this, RegExp); |
| } |
| } |
| assertInstanceof(new Derived2(Derived2), RegExp); |
| assertInstanceof(new Derived2(Derived2, 'extra'), RegExp); |
| })(); |
| |
| |
| (function TestReflectConstruct() { |
| var calls = 0; |
| function f(expected) { |
| calls++; |
| assertEquals(expected, new.target); |
| } |
| |
| var o = Reflect.construct(f, [f]); |
| assertEquals(Object.getPrototypeOf(o), f.prototype); |
| o = Reflect.construct(f, [f, 'extra']); |
| assertEquals(Object.getPrototypeOf(o), f.prototype); |
| assertEquals(2, calls); |
| |
| calls = 0; |
| o = Reflect.construct(f, [f], f); |
| assertEquals(Object.getPrototypeOf(o), f.prototype); |
| o = Reflect.construct(f, [f, 'extra'], f); |
| assertEquals(Object.getPrototypeOf(o), f.prototype); |
| assertEquals(2, calls); |
| |
| |
| function g() {} |
| calls = 0; |
| o = Reflect.construct(f, [g], g); |
| assertEquals(Object.getPrototypeOf(o), g.prototype); |
| o = Reflect.construct(f, [g, 'extra'], g); |
| assertEquals(Object.getPrototypeOf(o), g.prototype); |
| assertEquals(2, calls); |
| })(); |
| |
| |
| (function TestRestParametersFunction() { |
| function f(...rest) { |
| assertEquals(rest[0], new.target); |
| } |
| |
| assertInstanceof(new f(f), f); |
| assertInstanceof(new f(f, 'extra'), f); |
| })(); |
| |
| |
| (function TestRestParametersClass() { |
| 'use strict'; |
| |
| class Base { |
| constructor(...rest) { |
| assertEquals(rest[0], new.target); |
| } |
| } |
| |
| assertInstanceof(new Base(Base), Base); |
| assertInstanceof(new Base(Base, 'extra'), Base); |
| |
| class Derived extends Base {} |
| |
| assertInstanceof(new Derived(Derived), Derived); |
| assertInstanceof(new Derived(Derived, 'extra'), Derived); |
| })(); |
| |
| |
| (function TestArrowFunction() { |
| function f(expected) { |
| (() => { |
| assertEquals(expected, new.target); |
| })(); |
| } |
| |
| assertInstanceof(new f(f), f); |
| assertInstanceof(new f(f, 'extra'), f); |
| })(); |
| |
| |
| (function TestRestParametersClass() { |
| 'use strict'; |
| |
| class Base { |
| constructor(expected) { |
| (() => { |
| assertEquals(expected, new.target); |
| })(); |
| } |
| } |
| |
| assertInstanceof(new Base(Base), Base); |
| assertInstanceof(new Base(Base, 'extra'), Base); |
| |
| class Derived extends Base {} |
| |
| assertInstanceof(new Derived(Derived), Derived); |
| assertInstanceof(new Derived(Derived, 'extra'), Derived); |
| })(); |
| |
| |
| (function TestSloppyArguments() { |
| var length, a0, a1, a2, nt; |
| function f(x) { |
| assertEquals(length, arguments.length); |
| assertEquals(a0, arguments[0]); |
| assertEquals(a1, arguments[1]); |
| assertEquals(a2, arguments[2]); |
| assertEquals(nt, new.target); |
| |
| if (length > 0) { |
| x = 42; |
| assertEquals(42, x); |
| assertEquals(42, arguments[0]); |
| |
| arguments[0] = 33; |
| assertEquals(33, x); |
| assertEquals(33, arguments[0]); |
| } |
| } |
| |
| nt = f; |
| length = 0; |
| new f(); |
| |
| length = 1; |
| a0 = 1; |
| new f(1); |
| |
| length = 2; |
| a0 = 1; |
| a1 = 2; |
| new f(1, 2); |
| |
| length = 3; |
| a0 = 1; |
| a1 = 2; |
| a2 = 3; |
| new f(1, 2, 3); |
| |
| nt = undefined; |
| a0 = a1 = a2 = undefined; |
| length = 0; |
| f(); |
| |
| length = 1; |
| a0 = 1; |
| f(1); |
| |
| length = 2; |
| a0 = 1; |
| a1 = 2; |
| f(1, 2); |
| |
| length = 3; |
| a0 = 1; |
| a1 = 2; |
| a2 = 3; |
| f(1, 2, 3); |
| })(); |
| |
| |
| (function TestStrictArguments() { |
| var length, a0, a1, a2, nt; |
| function f(x) { |
| 'use strict'; |
| assertEquals(length, arguments.length); |
| assertEquals(a0, arguments[0]); |
| assertEquals(a1, arguments[1]); |
| assertEquals(a2, arguments[2]); |
| assertEquals(nt, new.target); |
| |
| if (length > 0) { |
| x = 42; |
| assertEquals(a0, arguments[0]); |
| |
| arguments[0] = 33; |
| assertEquals(33, arguments[0]); |
| } |
| } |
| |
| nt = f; |
| length = 0; |
| new f(); |
| |
| length = 1; |
| a0 = 1; |
| new f(1); |
| |
| length = 2; |
| a0 = 1; |
| a1 = 2; |
| new f(1, 2); |
| |
| length = 3; |
| a0 = 1; |
| a1 = 2; |
| a2 = 3; |
| new f(1, 2, 3); |
| |
| nt = undefined; |
| a0 = a1 = a2 = undefined; |
| length = 0; |
| f(); |
| |
| length = 1; |
| a0 = 1; |
| f(1); |
| |
| length = 2; |
| a0 = 1; |
| a1 = 2; |
| f(1, 2); |
| |
| length = 3; |
| a0 = 1; |
| a1 = 2; |
| a2 = 3; |
| f(1, 2, 3); |
| })(); |
| |
| |
| (function TestOtherScopes() { |
| function f1() { return eval("'use strict'; new.target") } |
| assertSame(f1, new f1); |
| function f2() { with ({}) return new.target } |
| assertSame(f2, new f2); |
| function f3({a}) { return new.target } |
| assertSame(f3, new f3({})); |
| function f4(...a) { return new.target } |
| assertSame(f4, new f4); |
| function f5() { 'use strict'; { let x; return new.target } } |
| assertSame(f5, new f5); |
| function f6() { with ({'new.target': 42}) return new.target } |
| assertSame(f6, new f6); |
| })(); |
| |
| |
| // Has to be top-level to be inlined. |
| function get_new_target() { return new.target; } |
| (function TestInlining() { |
| "use strict"; |
| new function() { assertEquals(undefined, get_new_target()); } |
| new function() { assertEquals(get_new_target, new get_new_target()); } |
| |
| class A extends get_new_target { |
| constructor() { |
| var new_target = super(); |
| this.new_target = new_target; |
| } |
| } |
| assertEquals(A, new A().new_target); |
| })(); |
| |
| |
| (function TestEarlyErrors() { |
| assertThrows(function() { Function("new.target = 42"); }, ReferenceError); |
| assertThrows(function() { Function("var foo = 1; new.target = foo = 42"); }, ReferenceError); |
| assertThrows(function() { Function("var foo = 1; foo = new.target = 42"); }, ReferenceError); |
| assertThrows(function() { Function("new.target--"); }, ReferenceError); |
| assertThrows(function() { Function("--new.target"); }, ReferenceError); |
| assertThrows(function() { Function("(new.target)++"); }, ReferenceError); |
| assertThrows(function() { Function("++(new.target)"); }, ReferenceError); |
| assertThrows(function() { Function("for (new.target of {});"); }, SyntaxError); |
| })(); |
| |
| (function TestOperatorPrecedence() { |
| function A() {} |
| function constructNewTargetDotProp() { return new new.target.Prop } |
| constructNewTargetDotProp.Prop = A; |
| assertInstanceof(new constructNewTargetDotProp, A); |
| |
| function constructNewTargetBracketProp() { return new new.target['Prop'] } |
| constructNewTargetBracketProp.Prop = A; |
| assertInstanceof(new constructNewTargetBracketProp, A); |
| |
| function refNewTargetDotProp() { return new.target.Prop; } |
| function B() {} |
| refNewTargetDotProp.Prop = B; |
| assertEquals(new refNewTargetDotProp, B); |
| |
| function refNewTargetBracketProp() { return new.target['Prop']; } |
| refNewTargetBracketProp.Prop = B; |
| assertEquals(new refNewTargetBracketProp, B); |
| |
| var calls = 0; |
| function constructNewTargetArgsDotProp(safe) { |
| this.Prop = ++calls; |
| return safe ? Object(new new.target().Prop) : this; |
| } |
| assertInstanceof(new constructNewTargetArgsDotProp, |
| constructNewTargetArgsDotProp); |
| assertEquals(3, new constructNewTargetArgsDotProp(true) | 0); |
| |
| function constructNewTargetArgsBracketProp(safe) { |
| this.Prop = ++calls; |
| return safe ? Object(new new.target()['Prop']) : this; |
| } |
| assertInstanceof(new constructNewTargetArgsBracketProp, |
| constructNewTargetArgsBracketProp); |
| assertEquals(6, new constructNewTargetArgsBracketProp(true) | 0); |
| |
| function callNewTargetArgsDotProp(safe) { |
| this.Prop = ++calls; |
| return safe ? Object(new.target().Prop) : this; |
| } |
| assertInstanceof(new callNewTargetArgsDotProp(), callNewTargetArgsDotProp); |
| assertEquals(new callNewTargetArgsDotProp(true) | 0, 9); |
| |
| function callNewTargetArgsBracketProp(safe) { |
| this.Prop = ++calls; |
| return safe ? Object(new.target()['Prop']) : this; |
| } |
| assertInstanceof(new callNewTargetArgsBracketProp(), |
| callNewTargetArgsBracketProp); |
| assertEquals(new callNewTargetArgsBracketProp(true) | 0, 12); |
| |
| function tagNewTarget(callSite, ...subs) { |
| return callSite ? subs : new.target`${new.target.name}`; |
| } |
| assertEquals(new tagNewTarget, ["tagNewTarget"]); |
| |
| function C(callSite, ...subs) { return subs; } |
| function tagNewTargetProp() { return new.target.Prop`${new.target.name}`; } |
| tagNewTargetProp.Prop = C; |
| assertEquals(new tagNewTargetProp, ["tagNewTargetProp"]); |
| })(); |
| |
| (function testDeleteSloppy() { |
| assertTrue(delete new.target); |
| })(); |
| |
| (function testDeleteStrict() { |
| "use strict"; |
| assertTrue(delete new.target); |
| })(); |