Index: test/webkit/class-syntax-name.js |
diff --git a/test/webkit/class-syntax-name.js b/test/webkit/class-syntax-name.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..09faa3a54aed5fe6d09c08e51506409afea3c0e6 |
--- /dev/null |
+++ b/test/webkit/class-syntax-name.js |
@@ -0,0 +1,115 @@ |
+// Copyright 2015 the V8 project authors. All rights reserved. |
+// Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. |
+// |
+// Redistribution and use in source and binary forms, with or without |
+// modification, are permitted provided that the following conditions |
+// are met: |
+// 1. Redistributions of source code must retain the above copyright |
+// notice, this list of conditions and the following disclaimer. |
+// 2. Redistributions in binary form must reproduce the above copyright |
+// notice, this list of conditions and the following disclaimer in the |
+// documentation and/or other materials provided with the distribution. |
+// |
+// THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY |
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
+// DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
+// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ |
+// Flags: --harmony-sloppy |
+ |
+description('Tests for ES6 class name semantics in class statements and expressions'); |
+ |
+function runTestShouldBe(statement, result) { |
+ shouldBe(statement, result); |
+ shouldBe("'use strict'; " + statement, result); |
+} |
+ |
+function runTestShouldBeTrue(statement) { |
+ shouldBeTrue(statement); |
+ shouldBeTrue("'use strict'; " + statement); |
+} |
+ |
+function runTestShouldThrow(statement) { |
+ shouldThrow(statement); |
+ shouldThrow("'use strict'; " + statement); |
+} |
+ |
+function runTestShouldNotThrow(statement) { |
+ shouldNotThrow(statement); |
+ shouldNotThrow("'use strict'; " + statement); |
+} |
+ |
+// Class statement. Class name added to global scope. Class name is available inside class scope and in global scope. |
+debug('Class statement'); |
+runTestShouldThrow("A"); |
+runTestShouldThrow("class {}"); |
+runTestShouldThrow("class { constructor() {} }"); |
+runTestShouldNotThrow("class A { constructor() {} }"); |
+runTestShouldBe("class A { constructor() {} }; A.toString()", "'class A { constructor() {} }'"); |
+runTestShouldBeTrue("class A { constructor() {} }; (new A) instanceof A"); |
+runTestShouldBe("class A { constructor() { this.base = A; } }; (new A).base.toString()", "'class A { constructor() { this.base = A; } }'"); |
+runTestShouldNotThrow("class A { constructor() {} }; class B extends A {};"); |
+runTestShouldBe("class A { constructor() {} }; class B extends A { constructor() {} }; B.toString()", "'class B extends A { constructor() {} }'"); |
+runTestShouldBeTrue("class A { constructor() {} }; class B extends A {}; (new B) instanceof A"); |
+runTestShouldBeTrue("class A { constructor() {} }; class B extends A {}; (new B) instanceof B"); |
+runTestShouldBe("class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).base.toString()", "'class A { constructor() {} }'"); |
+runTestShouldBe("class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).derived.toString()", "'class B extends A { constructor() { super(); this.base = A; this.derived = B; } }'"); |
+ |
+// Class expression. Class name not added to scope. Class name is available inside class scope. |
+debug(''); debug('Class expression'); |
+runTestShouldThrow("A"); |
+runTestShouldNotThrow("(class {})"); |
+runTestShouldNotThrow("(class { constructor(){} })"); |
+runTestShouldBe("typeof (class {})", '"function"'); |
+runTestShouldNotThrow("(class A {})"); |
+runTestShouldBe("typeof (class A {})", '"function"'); |
+runTestShouldThrow("(class A {}); A"); |
+runTestShouldNotThrow("new (class A {})"); |
+runTestShouldBe("typeof (new (class A {}))", '"object"'); |
+runTestShouldNotThrow("(new (class A { constructor() { this.base = A; } })).base"); |
+runTestShouldBe("(new (class A { constructor() { this.base = A; } })).base.toString()", '"class A { constructor() { this.base = A; } }"'); |
+runTestShouldNotThrow("class A {}; (class B extends A {})"); |
+runTestShouldThrow("class A {}; (class B extends A {}); B"); |
+runTestShouldNotThrow("class A {}; new (class B extends A {})"); |
+runTestShouldNotThrow("class A {}; new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })"); |
+runTestShouldBeTrue("class A {}; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })) instanceof A"); |
+runTestShouldBe("class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).base.toString()", "'class A { constructor() {} }'"); |
+runTestShouldBe("class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).derived.toString()", "'class B extends A { constructor() { super(); this.base = A; this.derived = B; } }'"); |
+ |
+// Assignment of a class expression to a variable. Variable name available in scope, class name is not. Class name is available inside class scope. |
+debug(''); debug('Class expression assignment to variable'); |
+runTestShouldThrow("A"); |
+runTestShouldNotThrow("var VarA = class {}"); |
+runTestShouldBe("var VarA = class { constructor() {} }; VarA.toString()", "'class { constructor() {} }'"); |
+runTestShouldThrow("VarA"); |
+runTestShouldNotThrow("var VarA = class A { constructor() {} }"); |
+runTestShouldBe("var VarA = class A { constructor() {} }; VarA.toString()", "'class A { constructor() {} }'"); |
+runTestShouldThrow("var VarA = class A { constructor() {} }; A.toString()"); |
+runTestShouldBeTrue("var VarA = class A { constructor() {} }; (new VarA) instanceof VarA"); |
+runTestShouldBe("var VarA = class A { constructor() { this.base = A; } }; (new VarA).base.toString()", "'class A { constructor() { this.base = A; } }'"); |
+runTestShouldNotThrow("var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} };"); |
+runTestShouldThrow("var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; B"); |
+runTestShouldBe("var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; VarB.toString()", "'class B extends VarA { constructor() {} }'"); |
+runTestShouldBeTrue("var VarA = class A { constructor() {} }; var VarB = class B extends VarA { }; (new VarB) instanceof VarA"); |
+runTestShouldBeTrue("var VarA = class A { constructor() {} }; var VarB = class B extends VarA { }; (new VarB) instanceof VarB"); |
+runTestShouldBeTrue("var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() { super(); this.base = VarA; this.derived = B; this.derivedVar = VarB; } }; (new VarB).base === VarA"); |
+runTestShouldBeTrue("var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() { super(); this.base = VarA; this.derived = B; this.derivedVar = VarB; } }; (new VarB).derived === VarB"); |
+runTestShouldBeTrue("var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() { super(); this.base = VarA; this.derived = B; this.derivedVar = VarB; } }; (new VarB).derivedVar === VarB"); |
+ |
+// FIXME: Class statement binding should be like `let`, not `var`. |
+debug(''); debug('Class statement binding in other circumstances'); |
+runTestShouldThrow("var result = A; result"); |
+runTestShouldThrow("var result = A; class A {}; result"); |
+runTestShouldThrow("class A { constructor() { A = 1; } }; new A"); |
+runTestShouldBe("class A { constructor() { } }; A = 1; A", "1"); |
+runTestShouldNotThrow("class A {}; var result = A; result"); |
+shouldBe("eval('var Foo = 10'); Foo", "10"); |
+shouldThrow("'use strict'; eval('var Foo = 10'); Foo"); |
+shouldBe("eval('class Bar { constructor() {} }'); Bar.toString()", "'class Bar { constructor() {} }'"); |
+shouldThrow("'use strict'; eval('class Bar { constructor() {} }'); Bar.toString()"); |