haikuwebkit/LayoutTests/js/class-syntax-name-expected.txt

127 lines
11 KiB
Plaintext
Raw Permalink Normal View History

ES6: Classes: Program level class statement throws exception in strict mode https://bugs.webkit.org/show_bug.cgi?id=143038 Reviewed by Ryosuke Niwa. Source/JavaScriptCore: Classes expose a name to the current lexical environment. This treats "class X {}" like "var X = class X {}". Ideally it would be "let X = class X {}". Also, improve error messages for class statements where the class is missing a name. * parser/Parser.h: * parser/Parser.cpp: (JSC::Parser<LexerType>::parseClass): Fill name in info parameter if needed. Better error message if name is needed and missing. (JSC::Parser<LexerType>::parseClassDeclaration): Pass info parameter to get name, and expose the name as a variable name. (JSC::Parser<LexerType>::parsePrimaryExpression): Pass info parameter that is ignored. * parser/ParserFunctionInfo.h: Add a parser info for class, to extract the name. LayoutTests: This updates a number of existing tests that were relying on poor behavior. `shouldBe` and friends use eval within a function not at the global scope. This means `shouldBe('class X { ... }')` behaves like `shouldBe('var x = ...')` not `shouldBe('x = ...')`. This means `x` will not be available in the next `shouldBe` call. Add a test specifically to cover the scoping of the class name in regular and strict mode code. Currently we treat it like var with one failing test that would pass when we treat it like let. * js/class-syntax-name.html: Added. * js/script-tests/class-syntax-name.js: Added. (runTestShouldBe): (runTestShouldBeTrue): (runTestShouldThrow): (runTestShouldNotThrow): Test class name scoping. * js/class-syntax-call-expected.txt: * js/class-syntax-declaration-expected.txt: * js/class-syntax-default-constructor-expected.txt: * js/class-syntax-name-expected.txt: Added. * js/script-tests/class-syntax-call.js: * js/script-tests/class-syntax-declaration.js: * js/script-tests/class-syntax-default-constructor.js: Canonical link: https://commits.webkit.org/161082@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@181973 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-03-25 21:33:59 +00:00
Tests for ES6 class name semantics in class statements and expressions
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
Class statement
ES6 class syntax should use block scoping https://bugs.webkit.org/show_bug.cgi?id=142567 Reviewed by Geoffrey Garen. Source/JavaScriptCore: We treat class declarations like we do "let" declarations. The class name is under TDZ until the class declaration statement is evaluated. Class declarations also follow the same rules as "let": No duplicate definitions inside a lexical environment. * parser/ASTBuilder.h: (JSC::ASTBuilder::createClassDeclStatement): * parser/Parser.cpp: (JSC::Parser<LexerType>::parseClassDeclaration): * tests/stress/class-syntax-block-scoping.js: Added. (assert): (truth): (.): * tests/stress/class-syntax-definition-semantics.js: Added. (shouldBeSyntaxError): (shouldNotBeSyntaxError): (truth): * tests/stress/class-syntax-tdz.js: (assert): (shouldThrowTDZ): (truth): (.): LayoutTests: * js/class-constructor-return-expected.txt: * js/class-syntax-call-expected.txt: * js/class-syntax-declaration-expected.txt: * js/class-syntax-default-constructor-expected.txt: * js/class-syntax-extends-expected.txt: * js/class-syntax-name-expected.txt: * js/class-syntax-super-expected.txt: * js/script-tests/class-constructor-return.js: (shouldThrow): (shouldNotThrow): (shouldBeTrue): (shouldBeFalse): * js/script-tests/class-syntax-call.js: (A): (B): (shouldThrow): (shouldNotThrow): * js/script-tests/class-syntax-declaration.js: (shouldThrow): (shouldNotThrow): (shouldBe): * js/script-tests/class-syntax-default-constructor.js: (shouldThrow): (shouldBe): (shouldBeTrue): (assert): (A): (B): * js/script-tests/class-syntax-extends.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (Base): (Base.prototype.baseMethod): * js/script-tests/class-syntax-name.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (runTestShouldBe): * js/script-tests/class-syntax-super.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (shouldBeFalse): Canonical link: https://commits.webkit.org/165577@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@187680 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-07-31 21:05:19 +00:00
PASS A:::ReferenceError: Can't find variable: A
PASS 'use strict'; A:::ReferenceError: Can't find variable: A
PASS class {}:::SyntaxError: Class statements must have a name.
PASS 'use strict'; class {}:::SyntaxError: Class statements must have a name.
PASS class { constructor() {} }:::SyntaxError: Class statements must have a name.
PASS 'use strict'; class { constructor() {} }:::SyntaxError: Class statements must have a name.
PASS class A { constructor() {} }
PASS 'use strict'; class A { constructor() {} }
Implement Function.name and Function#toString for ES6 class. https://bugs.webkit.org/show_bug.cgi?id=155336 Reviewed by Geoffrey Garen. Source/JavaScriptCore: The only thing that the ES6 spec says about toString with regards to class objects is: "The string representation must have the syntax of a FunctionDeclaration, FunctionExpression, GeneratorDeclaration, GeneratorExpression, ClassDeclaration, ClassExpression, ArrowFunction, MethodDefinition, or GeneratorMethod depending upon the actual characteristics of the object." Previously, invoking toString() on a class object will return the function source string of the class' constructor function. This does not conform to the spec in that the toString string for a class does not have the syntax of a ClassDeclaration or ClassExpression. This is now fixed by doing the following: 1. Added "m_classSource" to FunctionExecutable (and correspondingly to UnlinkedFunctionExecutable, FunctionMetadataNode, and ClassExprNode). m_classSource is the SourceCode for the code range "class ... { ... }". Since the class constructor function is the in memory representation of the class object, only class constructor functions will have its m_classSource set. m_classSource will be "null" (by default) for all other functions. This is how we know if a FunctionExecutable is for a class. Note: FunctionExecutable does not have its own m_classSource. It always gets it from its UnlinkedFunctionExecutable. This is ok to do because our CodeCache currently does not cache UnlinkedFunctionExecutables for class constructors. 2. The ClassExprNode now tracks the SourceCode range for the class expression. This is used to set m_classSource in the UnlinkedFunctionExecutable at bytecode generation time, and the FunctionExecutable later at bytecode linking time. 3. Function.prototype.toString() now checks if the function is for a class. If so, it returns the string for the class source instead of just the function source for the class constructor. Note: the class source is static from the time the class was parsed. This can introduces some weirdness at runtime. Consider the following: var v1 = class {} v1.toString(); // yields "class {}". class c2 extends v1 {} c2.__proto__ === v1; // yields true i.e. c2 extends v1. c2.toString(); // yields "class c2 extends v1 {}" which is fine. v1 = {}; // point v1 to something else now. c2.__proto__ === v1; // now yields false i.e. c2 no longer extends v1. // c2 actually extends the class that v1 used to // point to, but ... c2.toString(); // still yields "class c2 extends v1 {}" which is no longer true. It is unclear how we can best implement toString() to avoid this issue. The above behavior is how Chrome (Version 51.0.2671.0 canary (64-bit)) currently implements toString() of a class, and we do the same in this patch. In Firefox (45.0), toString() of a class will yield the function source of it constructor function, which is not better. In this patch, we also added ES6 compliance for Function.name on class objects: 4. The ClassExprNode now has a m_ecmaName string for tracking the inferred name of a class according to the ES6 spec. The ASTBuilder now mirrors its handling of FuncExprNodes to ClassExprNodes in setting the nodes' m_ecmaName where relevant. The m_ecmaName is later used to set the m_ecmaName of the FunctionExecutable of the class constructor, which in turn is used to populate the initial value of the Function.name property. 5. Also renamed some variable names (/m_metadata/metadata/) to be consistent with webkit naming convention. * bytecode/UnlinkedFunctionExecutable.cpp: (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable): * bytecode/UnlinkedFunctionExecutable.h: * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitNewArrowFunctionExpression): (JSC::BytecodeGenerator::emitNewDefaultConstructor): * bytecompiler/BytecodeGenerator.h: * bytecompiler/NodesCodegen.cpp: (JSC::ClassExprNode::emitBytecode): * parser/ASTBuilder.h: (JSC::ASTBuilder::createAssignResolve): (JSC::ASTBuilder::createYield): (JSC::ASTBuilder::createClassExpr): (JSC::ASTBuilder::createFunctionExpr): (JSC::ASTBuilder::createProperty): (JSC::ASTBuilder::makeAssignNode): * parser/NodeConstructors.h: (JSC::FunctionParameters::FunctionParameters): (JSC::BaseFuncExprNode::BaseFuncExprNode): (JSC::FuncExprNode::FuncExprNode): (JSC::FuncDeclNode::FuncDeclNode): (JSC::ArrowFuncExprNode::ArrowFuncExprNode): (JSC::ClassDeclNode::ClassDeclNode): (JSC::ClassExprNode::ClassExprNode): * parser/Nodes.h: (JSC::ExpressionNode::isDestructuringNode): (JSC::ExpressionNode::isFuncExprNode): (JSC::ExpressionNode::isArrowFuncExprNode): (JSC::ExpressionNode::isClassExprNode): (JSC::ExpressionNode::isCommaNode): (JSC::ExpressionNode::isSimpleArray): (JSC::ExpressionNode::isAdd): * parser/Parser.cpp: (JSC::stringForFunctionMode): (JSC::Parser<LexerType>::parseFunctionInfo): (JSC::Parser<LexerType>::parseClass): * parser/ParserFunctionInfo.h: * parser/SyntaxChecker.h: (JSC::SyntaxChecker::createEmptyLetExpression): (JSC::SyntaxChecker::createYield): (JSC::SyntaxChecker::createClassExpr): (JSC::SyntaxChecker::createFunctionExpr): (JSC::SyntaxChecker::createFunctionMetadata): (JSC::SyntaxChecker::createArrowFunctionExpr): * runtime/Executable.cpp: (JSC::FunctionExecutable::FunctionExecutable): (JSC::FunctionExecutable::finishCreation): * runtime/Executable.h: * runtime/FunctionPrototype.cpp: (JSC::functionProtoFuncToString): * tests/es6.yaml: LayoutTests: * js/class-syntax-name-expected.txt: * js/script-tests/class-syntax-name.js: (shouldBe): (shouldBeTrue): - Rebased expected result. * js/function-toString-vs-name.html: * js/script-tests/function-toString-vs-name.js: - Added new tests for class. * platform/mac/inspector/model/remote-object-expected.txt: - Rebased expected result. Canonical link: https://commits.webkit.org/173492@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@198042 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-03-11 21:08:08 +00:00
PASS class A { constructor() {} }; A.toString():::'class A { constructor() {} }'
PASS 'use strict'; class A { constructor() {} }; A.toString():::'class A { constructor() {} }'
ES6 class syntax should use block scoping https://bugs.webkit.org/show_bug.cgi?id=142567 Reviewed by Geoffrey Garen. Source/JavaScriptCore: We treat class declarations like we do "let" declarations. The class name is under TDZ until the class declaration statement is evaluated. Class declarations also follow the same rules as "let": No duplicate definitions inside a lexical environment. * parser/ASTBuilder.h: (JSC::ASTBuilder::createClassDeclStatement): * parser/Parser.cpp: (JSC::Parser<LexerType>::parseClassDeclaration): * tests/stress/class-syntax-block-scoping.js: Added. (assert): (truth): (.): * tests/stress/class-syntax-definition-semantics.js: Added. (shouldBeSyntaxError): (shouldNotBeSyntaxError): (truth): * tests/stress/class-syntax-tdz.js: (assert): (shouldThrowTDZ): (truth): (.): LayoutTests: * js/class-constructor-return-expected.txt: * js/class-syntax-call-expected.txt: * js/class-syntax-declaration-expected.txt: * js/class-syntax-default-constructor-expected.txt: * js/class-syntax-extends-expected.txt: * js/class-syntax-name-expected.txt: * js/class-syntax-super-expected.txt: * js/script-tests/class-constructor-return.js: (shouldThrow): (shouldNotThrow): (shouldBeTrue): (shouldBeFalse): * js/script-tests/class-syntax-call.js: (A): (B): (shouldThrow): (shouldNotThrow): * js/script-tests/class-syntax-declaration.js: (shouldThrow): (shouldNotThrow): (shouldBe): * js/script-tests/class-syntax-default-constructor.js: (shouldThrow): (shouldBe): (shouldBeTrue): (assert): (A): (B): * js/script-tests/class-syntax-extends.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (Base): (Base.prototype.baseMethod): * js/script-tests/class-syntax-name.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (runTestShouldBe): * js/script-tests/class-syntax-super.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (shouldBeFalse): Canonical link: https://commits.webkit.org/165577@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@187680 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-07-31 21:05:19 +00:00
PASS class A { constructor() {} }; (new A) instanceof A
PASS 'use strict'; class A { constructor() {} }; (new A) instanceof A
Implement Function.name and Function#toString for ES6 class. https://bugs.webkit.org/show_bug.cgi?id=155336 Reviewed by Geoffrey Garen. Source/JavaScriptCore: The only thing that the ES6 spec says about toString with regards to class objects is: "The string representation must have the syntax of a FunctionDeclaration, FunctionExpression, GeneratorDeclaration, GeneratorExpression, ClassDeclaration, ClassExpression, ArrowFunction, MethodDefinition, or GeneratorMethod depending upon the actual characteristics of the object." Previously, invoking toString() on a class object will return the function source string of the class' constructor function. This does not conform to the spec in that the toString string for a class does not have the syntax of a ClassDeclaration or ClassExpression. This is now fixed by doing the following: 1. Added "m_classSource" to FunctionExecutable (and correspondingly to UnlinkedFunctionExecutable, FunctionMetadataNode, and ClassExprNode). m_classSource is the SourceCode for the code range "class ... { ... }". Since the class constructor function is the in memory representation of the class object, only class constructor functions will have its m_classSource set. m_classSource will be "null" (by default) for all other functions. This is how we know if a FunctionExecutable is for a class. Note: FunctionExecutable does not have its own m_classSource. It always gets it from its UnlinkedFunctionExecutable. This is ok to do because our CodeCache currently does not cache UnlinkedFunctionExecutables for class constructors. 2. The ClassExprNode now tracks the SourceCode range for the class expression. This is used to set m_classSource in the UnlinkedFunctionExecutable at bytecode generation time, and the FunctionExecutable later at bytecode linking time. 3. Function.prototype.toString() now checks if the function is for a class. If so, it returns the string for the class source instead of just the function source for the class constructor. Note: the class source is static from the time the class was parsed. This can introduces some weirdness at runtime. Consider the following: var v1 = class {} v1.toString(); // yields "class {}". class c2 extends v1 {} c2.__proto__ === v1; // yields true i.e. c2 extends v1. c2.toString(); // yields "class c2 extends v1 {}" which is fine. v1 = {}; // point v1 to something else now. c2.__proto__ === v1; // now yields false i.e. c2 no longer extends v1. // c2 actually extends the class that v1 used to // point to, but ... c2.toString(); // still yields "class c2 extends v1 {}" which is no longer true. It is unclear how we can best implement toString() to avoid this issue. The above behavior is how Chrome (Version 51.0.2671.0 canary (64-bit)) currently implements toString() of a class, and we do the same in this patch. In Firefox (45.0), toString() of a class will yield the function source of it constructor function, which is not better. In this patch, we also added ES6 compliance for Function.name on class objects: 4. The ClassExprNode now has a m_ecmaName string for tracking the inferred name of a class according to the ES6 spec. The ASTBuilder now mirrors its handling of FuncExprNodes to ClassExprNodes in setting the nodes' m_ecmaName where relevant. The m_ecmaName is later used to set the m_ecmaName of the FunctionExecutable of the class constructor, which in turn is used to populate the initial value of the Function.name property. 5. Also renamed some variable names (/m_metadata/metadata/) to be consistent with webkit naming convention. * bytecode/UnlinkedFunctionExecutable.cpp: (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable): * bytecode/UnlinkedFunctionExecutable.h: * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitNewArrowFunctionExpression): (JSC::BytecodeGenerator::emitNewDefaultConstructor): * bytecompiler/BytecodeGenerator.h: * bytecompiler/NodesCodegen.cpp: (JSC::ClassExprNode::emitBytecode): * parser/ASTBuilder.h: (JSC::ASTBuilder::createAssignResolve): (JSC::ASTBuilder::createYield): (JSC::ASTBuilder::createClassExpr): (JSC::ASTBuilder::createFunctionExpr): (JSC::ASTBuilder::createProperty): (JSC::ASTBuilder::makeAssignNode): * parser/NodeConstructors.h: (JSC::FunctionParameters::FunctionParameters): (JSC::BaseFuncExprNode::BaseFuncExprNode): (JSC::FuncExprNode::FuncExprNode): (JSC::FuncDeclNode::FuncDeclNode): (JSC::ArrowFuncExprNode::ArrowFuncExprNode): (JSC::ClassDeclNode::ClassDeclNode): (JSC::ClassExprNode::ClassExprNode): * parser/Nodes.h: (JSC::ExpressionNode::isDestructuringNode): (JSC::ExpressionNode::isFuncExprNode): (JSC::ExpressionNode::isArrowFuncExprNode): (JSC::ExpressionNode::isClassExprNode): (JSC::ExpressionNode::isCommaNode): (JSC::ExpressionNode::isSimpleArray): (JSC::ExpressionNode::isAdd): * parser/Parser.cpp: (JSC::stringForFunctionMode): (JSC::Parser<LexerType>::parseFunctionInfo): (JSC::Parser<LexerType>::parseClass): * parser/ParserFunctionInfo.h: * parser/SyntaxChecker.h: (JSC::SyntaxChecker::createEmptyLetExpression): (JSC::SyntaxChecker::createYield): (JSC::SyntaxChecker::createClassExpr): (JSC::SyntaxChecker::createFunctionExpr): (JSC::SyntaxChecker::createFunctionMetadata): (JSC::SyntaxChecker::createArrowFunctionExpr): * runtime/Executable.cpp: (JSC::FunctionExecutable::FunctionExecutable): (JSC::FunctionExecutable::finishCreation): * runtime/Executable.h: * runtime/FunctionPrototype.cpp: (JSC::functionProtoFuncToString): * tests/es6.yaml: LayoutTests: * js/class-syntax-name-expected.txt: * js/script-tests/class-syntax-name.js: (shouldBe): (shouldBeTrue): - Rebased expected result. * js/function-toString-vs-name.html: * js/script-tests/function-toString-vs-name.js: - Added new tests for class. * platform/mac/inspector/model/remote-object-expected.txt: - Rebased expected result. Canonical link: https://commits.webkit.org/173492@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@198042 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-03-11 21:08:08 +00:00
PASS class A { constructor() { this.base = A; } }; (new A).base.toString():::'class A { constructor() { this.base = A; } }'
PASS 'use strict'; class A { constructor() { this.base = A; } }; (new A).base.toString():::'class A { constructor() { this.base = A; } }'
ES6 class syntax should use block scoping https://bugs.webkit.org/show_bug.cgi?id=142567 Reviewed by Geoffrey Garen. Source/JavaScriptCore: We treat class declarations like we do "let" declarations. The class name is under TDZ until the class declaration statement is evaluated. Class declarations also follow the same rules as "let": No duplicate definitions inside a lexical environment. * parser/ASTBuilder.h: (JSC::ASTBuilder::createClassDeclStatement): * parser/Parser.cpp: (JSC::Parser<LexerType>::parseClassDeclaration): * tests/stress/class-syntax-block-scoping.js: Added. (assert): (truth): (.): * tests/stress/class-syntax-definition-semantics.js: Added. (shouldBeSyntaxError): (shouldNotBeSyntaxError): (truth): * tests/stress/class-syntax-tdz.js: (assert): (shouldThrowTDZ): (truth): (.): LayoutTests: * js/class-constructor-return-expected.txt: * js/class-syntax-call-expected.txt: * js/class-syntax-declaration-expected.txt: * js/class-syntax-default-constructor-expected.txt: * js/class-syntax-extends-expected.txt: * js/class-syntax-name-expected.txt: * js/class-syntax-super-expected.txt: * js/script-tests/class-constructor-return.js: (shouldThrow): (shouldNotThrow): (shouldBeTrue): (shouldBeFalse): * js/script-tests/class-syntax-call.js: (A): (B): (shouldThrow): (shouldNotThrow): * js/script-tests/class-syntax-declaration.js: (shouldThrow): (shouldNotThrow): (shouldBe): * js/script-tests/class-syntax-default-constructor.js: (shouldThrow): (shouldBe): (shouldBeTrue): (assert): (A): (B): * js/script-tests/class-syntax-extends.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (Base): (Base.prototype.baseMethod): * js/script-tests/class-syntax-name.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (runTestShouldBe): * js/script-tests/class-syntax-super.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (shouldBeFalse): Canonical link: https://commits.webkit.org/165577@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@187680 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-07-31 21:05:19 +00:00
PASS class A { constructor() {} }; class B extends A {};
PASS 'use strict'; class A { constructor() {} }; class B extends A {};
Implement Function.name and Function#toString for ES6 class. https://bugs.webkit.org/show_bug.cgi?id=155336 Reviewed by Geoffrey Garen. Source/JavaScriptCore: The only thing that the ES6 spec says about toString with regards to class objects is: "The string representation must have the syntax of a FunctionDeclaration, FunctionExpression, GeneratorDeclaration, GeneratorExpression, ClassDeclaration, ClassExpression, ArrowFunction, MethodDefinition, or GeneratorMethod depending upon the actual characteristics of the object." Previously, invoking toString() on a class object will return the function source string of the class' constructor function. This does not conform to the spec in that the toString string for a class does not have the syntax of a ClassDeclaration or ClassExpression. This is now fixed by doing the following: 1. Added "m_classSource" to FunctionExecutable (and correspondingly to UnlinkedFunctionExecutable, FunctionMetadataNode, and ClassExprNode). m_classSource is the SourceCode for the code range "class ... { ... }". Since the class constructor function is the in memory representation of the class object, only class constructor functions will have its m_classSource set. m_classSource will be "null" (by default) for all other functions. This is how we know if a FunctionExecutable is for a class. Note: FunctionExecutable does not have its own m_classSource. It always gets it from its UnlinkedFunctionExecutable. This is ok to do because our CodeCache currently does not cache UnlinkedFunctionExecutables for class constructors. 2. The ClassExprNode now tracks the SourceCode range for the class expression. This is used to set m_classSource in the UnlinkedFunctionExecutable at bytecode generation time, and the FunctionExecutable later at bytecode linking time. 3. Function.prototype.toString() now checks if the function is for a class. If so, it returns the string for the class source instead of just the function source for the class constructor. Note: the class source is static from the time the class was parsed. This can introduces some weirdness at runtime. Consider the following: var v1 = class {} v1.toString(); // yields "class {}". class c2 extends v1 {} c2.__proto__ === v1; // yields true i.e. c2 extends v1. c2.toString(); // yields "class c2 extends v1 {}" which is fine. v1 = {}; // point v1 to something else now. c2.__proto__ === v1; // now yields false i.e. c2 no longer extends v1. // c2 actually extends the class that v1 used to // point to, but ... c2.toString(); // still yields "class c2 extends v1 {}" which is no longer true. It is unclear how we can best implement toString() to avoid this issue. The above behavior is how Chrome (Version 51.0.2671.0 canary (64-bit)) currently implements toString() of a class, and we do the same in this patch. In Firefox (45.0), toString() of a class will yield the function source of it constructor function, which is not better. In this patch, we also added ES6 compliance for Function.name on class objects: 4. The ClassExprNode now has a m_ecmaName string for tracking the inferred name of a class according to the ES6 spec. The ASTBuilder now mirrors its handling of FuncExprNodes to ClassExprNodes in setting the nodes' m_ecmaName where relevant. The m_ecmaName is later used to set the m_ecmaName of the FunctionExecutable of the class constructor, which in turn is used to populate the initial value of the Function.name property. 5. Also renamed some variable names (/m_metadata/metadata/) to be consistent with webkit naming convention. * bytecode/UnlinkedFunctionExecutable.cpp: (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable): * bytecode/UnlinkedFunctionExecutable.h: * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitNewArrowFunctionExpression): (JSC::BytecodeGenerator::emitNewDefaultConstructor): * bytecompiler/BytecodeGenerator.h: * bytecompiler/NodesCodegen.cpp: (JSC::ClassExprNode::emitBytecode): * parser/ASTBuilder.h: (JSC::ASTBuilder::createAssignResolve): (JSC::ASTBuilder::createYield): (JSC::ASTBuilder::createClassExpr): (JSC::ASTBuilder::createFunctionExpr): (JSC::ASTBuilder::createProperty): (JSC::ASTBuilder::makeAssignNode): * parser/NodeConstructors.h: (JSC::FunctionParameters::FunctionParameters): (JSC::BaseFuncExprNode::BaseFuncExprNode): (JSC::FuncExprNode::FuncExprNode): (JSC::FuncDeclNode::FuncDeclNode): (JSC::ArrowFuncExprNode::ArrowFuncExprNode): (JSC::ClassDeclNode::ClassDeclNode): (JSC::ClassExprNode::ClassExprNode): * parser/Nodes.h: (JSC::ExpressionNode::isDestructuringNode): (JSC::ExpressionNode::isFuncExprNode): (JSC::ExpressionNode::isArrowFuncExprNode): (JSC::ExpressionNode::isClassExprNode): (JSC::ExpressionNode::isCommaNode): (JSC::ExpressionNode::isSimpleArray): (JSC::ExpressionNode::isAdd): * parser/Parser.cpp: (JSC::stringForFunctionMode): (JSC::Parser<LexerType>::parseFunctionInfo): (JSC::Parser<LexerType>::parseClass): * parser/ParserFunctionInfo.h: * parser/SyntaxChecker.h: (JSC::SyntaxChecker::createEmptyLetExpression): (JSC::SyntaxChecker::createYield): (JSC::SyntaxChecker::createClassExpr): (JSC::SyntaxChecker::createFunctionExpr): (JSC::SyntaxChecker::createFunctionMetadata): (JSC::SyntaxChecker::createArrowFunctionExpr): * runtime/Executable.cpp: (JSC::FunctionExecutable::FunctionExecutable): (JSC::FunctionExecutable::finishCreation): * runtime/Executable.h: * runtime/FunctionPrototype.cpp: (JSC::functionProtoFuncToString): * tests/es6.yaml: LayoutTests: * js/class-syntax-name-expected.txt: * js/script-tests/class-syntax-name.js: (shouldBe): (shouldBeTrue): - Rebased expected result. * js/function-toString-vs-name.html: * js/script-tests/function-toString-vs-name.js: - Added new tests for class. * platform/mac/inspector/model/remote-object-expected.txt: - Rebased expected result. Canonical link: https://commits.webkit.org/173492@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@198042 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-03-11 21:08:08 +00:00
PASS class A { constructor() {} }; class B extends A { constructor() {} }; B.toString():::'class B extends A { constructor() {} }'
PASS 'use strict'; class A { constructor() {} }; class B extends A { constructor() {} }; B.toString():::'class B extends A { constructor() {} }'
ES6 class syntax should use block scoping https://bugs.webkit.org/show_bug.cgi?id=142567 Reviewed by Geoffrey Garen. Source/JavaScriptCore: We treat class declarations like we do "let" declarations. The class name is under TDZ until the class declaration statement is evaluated. Class declarations also follow the same rules as "let": No duplicate definitions inside a lexical environment. * parser/ASTBuilder.h: (JSC::ASTBuilder::createClassDeclStatement): * parser/Parser.cpp: (JSC::Parser<LexerType>::parseClassDeclaration): * tests/stress/class-syntax-block-scoping.js: Added. (assert): (truth): (.): * tests/stress/class-syntax-definition-semantics.js: Added. (shouldBeSyntaxError): (shouldNotBeSyntaxError): (truth): * tests/stress/class-syntax-tdz.js: (assert): (shouldThrowTDZ): (truth): (.): LayoutTests: * js/class-constructor-return-expected.txt: * js/class-syntax-call-expected.txt: * js/class-syntax-declaration-expected.txt: * js/class-syntax-default-constructor-expected.txt: * js/class-syntax-extends-expected.txt: * js/class-syntax-name-expected.txt: * js/class-syntax-super-expected.txt: * js/script-tests/class-constructor-return.js: (shouldThrow): (shouldNotThrow): (shouldBeTrue): (shouldBeFalse): * js/script-tests/class-syntax-call.js: (A): (B): (shouldThrow): (shouldNotThrow): * js/script-tests/class-syntax-declaration.js: (shouldThrow): (shouldNotThrow): (shouldBe): * js/script-tests/class-syntax-default-constructor.js: (shouldThrow): (shouldBe): (shouldBeTrue): (assert): (A): (B): * js/script-tests/class-syntax-extends.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (Base): (Base.prototype.baseMethod): * js/script-tests/class-syntax-name.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (runTestShouldBe): * js/script-tests/class-syntax-super.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (shouldBeFalse): Canonical link: https://commits.webkit.org/165577@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@187680 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-07-31 21:05:19 +00:00
PASS class A { constructor() {} }; class B extends A {}; (new B) instanceof A
PASS 'use strict'; class A { constructor() {} }; class B extends A {}; (new B) instanceof A
PASS class A { constructor() {} }; class B extends A {}; (new B) instanceof B
PASS 'use strict'; class A { constructor() {} }; class B extends A {}; (new B) instanceof B
Implement Function.name and Function#toString for ES6 class. https://bugs.webkit.org/show_bug.cgi?id=155336 Reviewed by Geoffrey Garen. Source/JavaScriptCore: The only thing that the ES6 spec says about toString with regards to class objects is: "The string representation must have the syntax of a FunctionDeclaration, FunctionExpression, GeneratorDeclaration, GeneratorExpression, ClassDeclaration, ClassExpression, ArrowFunction, MethodDefinition, or GeneratorMethod depending upon the actual characteristics of the object." Previously, invoking toString() on a class object will return the function source string of the class' constructor function. This does not conform to the spec in that the toString string for a class does not have the syntax of a ClassDeclaration or ClassExpression. This is now fixed by doing the following: 1. Added "m_classSource" to FunctionExecutable (and correspondingly to UnlinkedFunctionExecutable, FunctionMetadataNode, and ClassExprNode). m_classSource is the SourceCode for the code range "class ... { ... }". Since the class constructor function is the in memory representation of the class object, only class constructor functions will have its m_classSource set. m_classSource will be "null" (by default) for all other functions. This is how we know if a FunctionExecutable is for a class. Note: FunctionExecutable does not have its own m_classSource. It always gets it from its UnlinkedFunctionExecutable. This is ok to do because our CodeCache currently does not cache UnlinkedFunctionExecutables for class constructors. 2. The ClassExprNode now tracks the SourceCode range for the class expression. This is used to set m_classSource in the UnlinkedFunctionExecutable at bytecode generation time, and the FunctionExecutable later at bytecode linking time. 3. Function.prototype.toString() now checks if the function is for a class. If so, it returns the string for the class source instead of just the function source for the class constructor. Note: the class source is static from the time the class was parsed. This can introduces some weirdness at runtime. Consider the following: var v1 = class {} v1.toString(); // yields "class {}". class c2 extends v1 {} c2.__proto__ === v1; // yields true i.e. c2 extends v1. c2.toString(); // yields "class c2 extends v1 {}" which is fine. v1 = {}; // point v1 to something else now. c2.__proto__ === v1; // now yields false i.e. c2 no longer extends v1. // c2 actually extends the class that v1 used to // point to, but ... c2.toString(); // still yields "class c2 extends v1 {}" which is no longer true. It is unclear how we can best implement toString() to avoid this issue. The above behavior is how Chrome (Version 51.0.2671.0 canary (64-bit)) currently implements toString() of a class, and we do the same in this patch. In Firefox (45.0), toString() of a class will yield the function source of it constructor function, which is not better. In this patch, we also added ES6 compliance for Function.name on class objects: 4. The ClassExprNode now has a m_ecmaName string for tracking the inferred name of a class according to the ES6 spec. The ASTBuilder now mirrors its handling of FuncExprNodes to ClassExprNodes in setting the nodes' m_ecmaName where relevant. The m_ecmaName is later used to set the m_ecmaName of the FunctionExecutable of the class constructor, which in turn is used to populate the initial value of the Function.name property. 5. Also renamed some variable names (/m_metadata/metadata/) to be consistent with webkit naming convention. * bytecode/UnlinkedFunctionExecutable.cpp: (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable): * bytecode/UnlinkedFunctionExecutable.h: * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitNewArrowFunctionExpression): (JSC::BytecodeGenerator::emitNewDefaultConstructor): * bytecompiler/BytecodeGenerator.h: * bytecompiler/NodesCodegen.cpp: (JSC::ClassExprNode::emitBytecode): * parser/ASTBuilder.h: (JSC::ASTBuilder::createAssignResolve): (JSC::ASTBuilder::createYield): (JSC::ASTBuilder::createClassExpr): (JSC::ASTBuilder::createFunctionExpr): (JSC::ASTBuilder::createProperty): (JSC::ASTBuilder::makeAssignNode): * parser/NodeConstructors.h: (JSC::FunctionParameters::FunctionParameters): (JSC::BaseFuncExprNode::BaseFuncExprNode): (JSC::FuncExprNode::FuncExprNode): (JSC::FuncDeclNode::FuncDeclNode): (JSC::ArrowFuncExprNode::ArrowFuncExprNode): (JSC::ClassDeclNode::ClassDeclNode): (JSC::ClassExprNode::ClassExprNode): * parser/Nodes.h: (JSC::ExpressionNode::isDestructuringNode): (JSC::ExpressionNode::isFuncExprNode): (JSC::ExpressionNode::isArrowFuncExprNode): (JSC::ExpressionNode::isClassExprNode): (JSC::ExpressionNode::isCommaNode): (JSC::ExpressionNode::isSimpleArray): (JSC::ExpressionNode::isAdd): * parser/Parser.cpp: (JSC::stringForFunctionMode): (JSC::Parser<LexerType>::parseFunctionInfo): (JSC::Parser<LexerType>::parseClass): * parser/ParserFunctionInfo.h: * parser/SyntaxChecker.h: (JSC::SyntaxChecker::createEmptyLetExpression): (JSC::SyntaxChecker::createYield): (JSC::SyntaxChecker::createClassExpr): (JSC::SyntaxChecker::createFunctionExpr): (JSC::SyntaxChecker::createFunctionMetadata): (JSC::SyntaxChecker::createArrowFunctionExpr): * runtime/Executable.cpp: (JSC::FunctionExecutable::FunctionExecutable): (JSC::FunctionExecutable::finishCreation): * runtime/Executable.h: * runtime/FunctionPrototype.cpp: (JSC::functionProtoFuncToString): * tests/es6.yaml: LayoutTests: * js/class-syntax-name-expected.txt: * js/script-tests/class-syntax-name.js: (shouldBe): (shouldBeTrue): - Rebased expected result. * js/function-toString-vs-name.html: * js/script-tests/function-toString-vs-name.js: - Added new tests for class. * platform/mac/inspector/model/remote-object-expected.txt: - Rebased expected result. Canonical link: https://commits.webkit.org/173492@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@198042 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-03-11 21:08:08 +00:00
PASS class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).base.toString():::'class A { constructor() {} }'
PASS 'use strict'; class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).base.toString():::'class A { constructor() {} }'
PASS 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; } }'
PASS 'use strict'; 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; } }'
ES6: Classes: Program level class statement throws exception in strict mode https://bugs.webkit.org/show_bug.cgi?id=143038 Reviewed by Ryosuke Niwa. Source/JavaScriptCore: Classes expose a name to the current lexical environment. This treats "class X {}" like "var X = class X {}". Ideally it would be "let X = class X {}". Also, improve error messages for class statements where the class is missing a name. * parser/Parser.h: * parser/Parser.cpp: (JSC::Parser<LexerType>::parseClass): Fill name in info parameter if needed. Better error message if name is needed and missing. (JSC::Parser<LexerType>::parseClassDeclaration): Pass info parameter to get name, and expose the name as a variable name. (JSC::Parser<LexerType>::parsePrimaryExpression): Pass info parameter that is ignored. * parser/ParserFunctionInfo.h: Add a parser info for class, to extract the name. LayoutTests: This updates a number of existing tests that were relying on poor behavior. `shouldBe` and friends use eval within a function not at the global scope. This means `shouldBe('class X { ... }')` behaves like `shouldBe('var x = ...')` not `shouldBe('x = ...')`. This means `x` will not be available in the next `shouldBe` call. Add a test specifically to cover the scoping of the class name in regular and strict mode code. Currently we treat it like var with one failing test that would pass when we treat it like let. * js/class-syntax-name.html: Added. * js/script-tests/class-syntax-name.js: Added. (runTestShouldBe): (runTestShouldBeTrue): (runTestShouldThrow): (runTestShouldNotThrow): Test class name scoping. * js/class-syntax-call-expected.txt: * js/class-syntax-declaration-expected.txt: * js/class-syntax-default-constructor-expected.txt: * js/class-syntax-name-expected.txt: Added. * js/script-tests/class-syntax-call.js: * js/script-tests/class-syntax-declaration.js: * js/script-tests/class-syntax-default-constructor.js: Canonical link: https://commits.webkit.org/161082@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@181973 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-03-25 21:33:59 +00:00
Class expression
ES6 class syntax should use block scoping https://bugs.webkit.org/show_bug.cgi?id=142567 Reviewed by Geoffrey Garen. Source/JavaScriptCore: We treat class declarations like we do "let" declarations. The class name is under TDZ until the class declaration statement is evaluated. Class declarations also follow the same rules as "let": No duplicate definitions inside a lexical environment. * parser/ASTBuilder.h: (JSC::ASTBuilder::createClassDeclStatement): * parser/Parser.cpp: (JSC::Parser<LexerType>::parseClassDeclaration): * tests/stress/class-syntax-block-scoping.js: Added. (assert): (truth): (.): * tests/stress/class-syntax-definition-semantics.js: Added. (shouldBeSyntaxError): (shouldNotBeSyntaxError): (truth): * tests/stress/class-syntax-tdz.js: (assert): (shouldThrowTDZ): (truth): (.): LayoutTests: * js/class-constructor-return-expected.txt: * js/class-syntax-call-expected.txt: * js/class-syntax-declaration-expected.txt: * js/class-syntax-default-constructor-expected.txt: * js/class-syntax-extends-expected.txt: * js/class-syntax-name-expected.txt: * js/class-syntax-super-expected.txt: * js/script-tests/class-constructor-return.js: (shouldThrow): (shouldNotThrow): (shouldBeTrue): (shouldBeFalse): * js/script-tests/class-syntax-call.js: (A): (B): (shouldThrow): (shouldNotThrow): * js/script-tests/class-syntax-declaration.js: (shouldThrow): (shouldNotThrow): (shouldBe): * js/script-tests/class-syntax-default-constructor.js: (shouldThrow): (shouldBe): (shouldBeTrue): (assert): (A): (B): * js/script-tests/class-syntax-extends.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (Base): (Base.prototype.baseMethod): * js/script-tests/class-syntax-name.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (runTestShouldBe): * js/script-tests/class-syntax-super.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (shouldBeFalse): Canonical link: https://commits.webkit.org/165577@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@187680 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-07-31 21:05:19 +00:00
PASS A:::ReferenceError: Can't find variable: A
PASS 'use strict'; A:::ReferenceError: Can't find variable: A
PASS (class {})
PASS 'use strict'; (class {})
PASS (class { constructor(){} })
PASS 'use strict'; (class { constructor(){} })
PASS typeof (class {}):::"function"
PASS 'use strict'; typeof (class {}):::"function"
PASS (class A {})
PASS 'use strict'; (class A {})
PASS typeof (class A {}):::"function"
PASS 'use strict'; typeof (class A {}):::"function"
PASS (class A {}); A:::ReferenceError: Can't find variable: A
PASS 'use strict'; (class A {}); A:::ReferenceError: Can't find variable: A
PASS new (class A {})
PASS 'use strict'; new (class A {})
PASS typeof (new (class A {})):::"object"
PASS 'use strict'; typeof (new (class A {})):::"object"
PASS (new (class A { constructor() { this.base = A; } })).base
PASS 'use strict'; (new (class A { constructor() { this.base = A; } })).base
Implement Function.name and Function#toString for ES6 class. https://bugs.webkit.org/show_bug.cgi?id=155336 Reviewed by Geoffrey Garen. Source/JavaScriptCore: The only thing that the ES6 spec says about toString with regards to class objects is: "The string representation must have the syntax of a FunctionDeclaration, FunctionExpression, GeneratorDeclaration, GeneratorExpression, ClassDeclaration, ClassExpression, ArrowFunction, MethodDefinition, or GeneratorMethod depending upon the actual characteristics of the object." Previously, invoking toString() on a class object will return the function source string of the class' constructor function. This does not conform to the spec in that the toString string for a class does not have the syntax of a ClassDeclaration or ClassExpression. This is now fixed by doing the following: 1. Added "m_classSource" to FunctionExecutable (and correspondingly to UnlinkedFunctionExecutable, FunctionMetadataNode, and ClassExprNode). m_classSource is the SourceCode for the code range "class ... { ... }". Since the class constructor function is the in memory representation of the class object, only class constructor functions will have its m_classSource set. m_classSource will be "null" (by default) for all other functions. This is how we know if a FunctionExecutable is for a class. Note: FunctionExecutable does not have its own m_classSource. It always gets it from its UnlinkedFunctionExecutable. This is ok to do because our CodeCache currently does not cache UnlinkedFunctionExecutables for class constructors. 2. The ClassExprNode now tracks the SourceCode range for the class expression. This is used to set m_classSource in the UnlinkedFunctionExecutable at bytecode generation time, and the FunctionExecutable later at bytecode linking time. 3. Function.prototype.toString() now checks if the function is for a class. If so, it returns the string for the class source instead of just the function source for the class constructor. Note: the class source is static from the time the class was parsed. This can introduces some weirdness at runtime. Consider the following: var v1 = class {} v1.toString(); // yields "class {}". class c2 extends v1 {} c2.__proto__ === v1; // yields true i.e. c2 extends v1. c2.toString(); // yields "class c2 extends v1 {}" which is fine. v1 = {}; // point v1 to something else now. c2.__proto__ === v1; // now yields false i.e. c2 no longer extends v1. // c2 actually extends the class that v1 used to // point to, but ... c2.toString(); // still yields "class c2 extends v1 {}" which is no longer true. It is unclear how we can best implement toString() to avoid this issue. The above behavior is how Chrome (Version 51.0.2671.0 canary (64-bit)) currently implements toString() of a class, and we do the same in this patch. In Firefox (45.0), toString() of a class will yield the function source of it constructor function, which is not better. In this patch, we also added ES6 compliance for Function.name on class objects: 4. The ClassExprNode now has a m_ecmaName string for tracking the inferred name of a class according to the ES6 spec. The ASTBuilder now mirrors its handling of FuncExprNodes to ClassExprNodes in setting the nodes' m_ecmaName where relevant. The m_ecmaName is later used to set the m_ecmaName of the FunctionExecutable of the class constructor, which in turn is used to populate the initial value of the Function.name property. 5. Also renamed some variable names (/m_metadata/metadata/) to be consistent with webkit naming convention. * bytecode/UnlinkedFunctionExecutable.cpp: (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable): * bytecode/UnlinkedFunctionExecutable.h: * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitNewArrowFunctionExpression): (JSC::BytecodeGenerator::emitNewDefaultConstructor): * bytecompiler/BytecodeGenerator.h: * bytecompiler/NodesCodegen.cpp: (JSC::ClassExprNode::emitBytecode): * parser/ASTBuilder.h: (JSC::ASTBuilder::createAssignResolve): (JSC::ASTBuilder::createYield): (JSC::ASTBuilder::createClassExpr): (JSC::ASTBuilder::createFunctionExpr): (JSC::ASTBuilder::createProperty): (JSC::ASTBuilder::makeAssignNode): * parser/NodeConstructors.h: (JSC::FunctionParameters::FunctionParameters): (JSC::BaseFuncExprNode::BaseFuncExprNode): (JSC::FuncExprNode::FuncExprNode): (JSC::FuncDeclNode::FuncDeclNode): (JSC::ArrowFuncExprNode::ArrowFuncExprNode): (JSC::ClassDeclNode::ClassDeclNode): (JSC::ClassExprNode::ClassExprNode): * parser/Nodes.h: (JSC::ExpressionNode::isDestructuringNode): (JSC::ExpressionNode::isFuncExprNode): (JSC::ExpressionNode::isArrowFuncExprNode): (JSC::ExpressionNode::isClassExprNode): (JSC::ExpressionNode::isCommaNode): (JSC::ExpressionNode::isSimpleArray): (JSC::ExpressionNode::isAdd): * parser/Parser.cpp: (JSC::stringForFunctionMode): (JSC::Parser<LexerType>::parseFunctionInfo): (JSC::Parser<LexerType>::parseClass): * parser/ParserFunctionInfo.h: * parser/SyntaxChecker.h: (JSC::SyntaxChecker::createEmptyLetExpression): (JSC::SyntaxChecker::createYield): (JSC::SyntaxChecker::createClassExpr): (JSC::SyntaxChecker::createFunctionExpr): (JSC::SyntaxChecker::createFunctionMetadata): (JSC::SyntaxChecker::createArrowFunctionExpr): * runtime/Executable.cpp: (JSC::FunctionExecutable::FunctionExecutable): (JSC::FunctionExecutable::finishCreation): * runtime/Executable.h: * runtime/FunctionPrototype.cpp: (JSC::functionProtoFuncToString): * tests/es6.yaml: LayoutTests: * js/class-syntax-name-expected.txt: * js/script-tests/class-syntax-name.js: (shouldBe): (shouldBeTrue): - Rebased expected result. * js/function-toString-vs-name.html: * js/script-tests/function-toString-vs-name.js: - Added new tests for class. * platform/mac/inspector/model/remote-object-expected.txt: - Rebased expected result. Canonical link: https://commits.webkit.org/173492@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@198042 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-03-11 21:08:08 +00:00
PASS (new (class A { constructor() { this.base = A; } })).base.toString():::"class A { constructor() { this.base = A; } }"
PASS 'use strict'; (new (class A { constructor() { this.base = A; } })).base.toString():::"class A { constructor() { this.base = A; } }"
ES6 class syntax should use block scoping https://bugs.webkit.org/show_bug.cgi?id=142567 Reviewed by Geoffrey Garen. Source/JavaScriptCore: We treat class declarations like we do "let" declarations. The class name is under TDZ until the class declaration statement is evaluated. Class declarations also follow the same rules as "let": No duplicate definitions inside a lexical environment. * parser/ASTBuilder.h: (JSC::ASTBuilder::createClassDeclStatement): * parser/Parser.cpp: (JSC::Parser<LexerType>::parseClassDeclaration): * tests/stress/class-syntax-block-scoping.js: Added. (assert): (truth): (.): * tests/stress/class-syntax-definition-semantics.js: Added. (shouldBeSyntaxError): (shouldNotBeSyntaxError): (truth): * tests/stress/class-syntax-tdz.js: (assert): (shouldThrowTDZ): (truth): (.): LayoutTests: * js/class-constructor-return-expected.txt: * js/class-syntax-call-expected.txt: * js/class-syntax-declaration-expected.txt: * js/class-syntax-default-constructor-expected.txt: * js/class-syntax-extends-expected.txt: * js/class-syntax-name-expected.txt: * js/class-syntax-super-expected.txt: * js/script-tests/class-constructor-return.js: (shouldThrow): (shouldNotThrow): (shouldBeTrue): (shouldBeFalse): * js/script-tests/class-syntax-call.js: (A): (B): (shouldThrow): (shouldNotThrow): * js/script-tests/class-syntax-declaration.js: (shouldThrow): (shouldNotThrow): (shouldBe): * js/script-tests/class-syntax-default-constructor.js: (shouldThrow): (shouldBe): (shouldBeTrue): (assert): (A): (B): * js/script-tests/class-syntax-extends.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (Base): (Base.prototype.baseMethod): * js/script-tests/class-syntax-name.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (runTestShouldBe): * js/script-tests/class-syntax-super.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (shouldBeFalse): Canonical link: https://commits.webkit.org/165577@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@187680 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-07-31 21:05:19 +00:00
PASS class A {}; (class B extends A {})
PASS 'use strict'; class A {}; (class B extends A {})
PASS class A {}; (class B extends A {}); B:::ReferenceError: Can't find variable: B
PASS 'use strict'; class A {}; (class B extends A {}); B:::ReferenceError: Can't find variable: B
PASS class A {}; new (class B extends A {})
PASS 'use strict'; class A {}; new (class B extends A {})
PASS class A {}; new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })
PASS 'use strict'; class A {}; new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })
PASS class A {}; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })) instanceof A
PASS 'use strict'; class A {}; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })) instanceof A
Implement Function.name and Function#toString for ES6 class. https://bugs.webkit.org/show_bug.cgi?id=155336 Reviewed by Geoffrey Garen. Source/JavaScriptCore: The only thing that the ES6 spec says about toString with regards to class objects is: "The string representation must have the syntax of a FunctionDeclaration, FunctionExpression, GeneratorDeclaration, GeneratorExpression, ClassDeclaration, ClassExpression, ArrowFunction, MethodDefinition, or GeneratorMethod depending upon the actual characteristics of the object." Previously, invoking toString() on a class object will return the function source string of the class' constructor function. This does not conform to the spec in that the toString string for a class does not have the syntax of a ClassDeclaration or ClassExpression. This is now fixed by doing the following: 1. Added "m_classSource" to FunctionExecutable (and correspondingly to UnlinkedFunctionExecutable, FunctionMetadataNode, and ClassExprNode). m_classSource is the SourceCode for the code range "class ... { ... }". Since the class constructor function is the in memory representation of the class object, only class constructor functions will have its m_classSource set. m_classSource will be "null" (by default) for all other functions. This is how we know if a FunctionExecutable is for a class. Note: FunctionExecutable does not have its own m_classSource. It always gets it from its UnlinkedFunctionExecutable. This is ok to do because our CodeCache currently does not cache UnlinkedFunctionExecutables for class constructors. 2. The ClassExprNode now tracks the SourceCode range for the class expression. This is used to set m_classSource in the UnlinkedFunctionExecutable at bytecode generation time, and the FunctionExecutable later at bytecode linking time. 3. Function.prototype.toString() now checks if the function is for a class. If so, it returns the string for the class source instead of just the function source for the class constructor. Note: the class source is static from the time the class was parsed. This can introduces some weirdness at runtime. Consider the following: var v1 = class {} v1.toString(); // yields "class {}". class c2 extends v1 {} c2.__proto__ === v1; // yields true i.e. c2 extends v1. c2.toString(); // yields "class c2 extends v1 {}" which is fine. v1 = {}; // point v1 to something else now. c2.__proto__ === v1; // now yields false i.e. c2 no longer extends v1. // c2 actually extends the class that v1 used to // point to, but ... c2.toString(); // still yields "class c2 extends v1 {}" which is no longer true. It is unclear how we can best implement toString() to avoid this issue. The above behavior is how Chrome (Version 51.0.2671.0 canary (64-bit)) currently implements toString() of a class, and we do the same in this patch. In Firefox (45.0), toString() of a class will yield the function source of it constructor function, which is not better. In this patch, we also added ES6 compliance for Function.name on class objects: 4. The ClassExprNode now has a m_ecmaName string for tracking the inferred name of a class according to the ES6 spec. The ASTBuilder now mirrors its handling of FuncExprNodes to ClassExprNodes in setting the nodes' m_ecmaName where relevant. The m_ecmaName is later used to set the m_ecmaName of the FunctionExecutable of the class constructor, which in turn is used to populate the initial value of the Function.name property. 5. Also renamed some variable names (/m_metadata/metadata/) to be consistent with webkit naming convention. * bytecode/UnlinkedFunctionExecutable.cpp: (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable): * bytecode/UnlinkedFunctionExecutable.h: * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitNewArrowFunctionExpression): (JSC::BytecodeGenerator::emitNewDefaultConstructor): * bytecompiler/BytecodeGenerator.h: * bytecompiler/NodesCodegen.cpp: (JSC::ClassExprNode::emitBytecode): * parser/ASTBuilder.h: (JSC::ASTBuilder::createAssignResolve): (JSC::ASTBuilder::createYield): (JSC::ASTBuilder::createClassExpr): (JSC::ASTBuilder::createFunctionExpr): (JSC::ASTBuilder::createProperty): (JSC::ASTBuilder::makeAssignNode): * parser/NodeConstructors.h: (JSC::FunctionParameters::FunctionParameters): (JSC::BaseFuncExprNode::BaseFuncExprNode): (JSC::FuncExprNode::FuncExprNode): (JSC::FuncDeclNode::FuncDeclNode): (JSC::ArrowFuncExprNode::ArrowFuncExprNode): (JSC::ClassDeclNode::ClassDeclNode): (JSC::ClassExprNode::ClassExprNode): * parser/Nodes.h: (JSC::ExpressionNode::isDestructuringNode): (JSC::ExpressionNode::isFuncExprNode): (JSC::ExpressionNode::isArrowFuncExprNode): (JSC::ExpressionNode::isClassExprNode): (JSC::ExpressionNode::isCommaNode): (JSC::ExpressionNode::isSimpleArray): (JSC::ExpressionNode::isAdd): * parser/Parser.cpp: (JSC::stringForFunctionMode): (JSC::Parser<LexerType>::parseFunctionInfo): (JSC::Parser<LexerType>::parseClass): * parser/ParserFunctionInfo.h: * parser/SyntaxChecker.h: (JSC::SyntaxChecker::createEmptyLetExpression): (JSC::SyntaxChecker::createYield): (JSC::SyntaxChecker::createClassExpr): (JSC::SyntaxChecker::createFunctionExpr): (JSC::SyntaxChecker::createFunctionMetadata): (JSC::SyntaxChecker::createArrowFunctionExpr): * runtime/Executable.cpp: (JSC::FunctionExecutable::FunctionExecutable): (JSC::FunctionExecutable::finishCreation): * runtime/Executable.h: * runtime/FunctionPrototype.cpp: (JSC::functionProtoFuncToString): * tests/es6.yaml: LayoutTests: * js/class-syntax-name-expected.txt: * js/script-tests/class-syntax-name.js: (shouldBe): (shouldBeTrue): - Rebased expected result. * js/function-toString-vs-name.html: * js/script-tests/function-toString-vs-name.js: - Added new tests for class. * platform/mac/inspector/model/remote-object-expected.txt: - Rebased expected result. Canonical link: https://commits.webkit.org/173492@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@198042 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-03-11 21:08:08 +00:00
PASS class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).base.toString():::'class A { constructor() {} }'
PASS 'use strict'; class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).base.toString():::'class A { constructor() {} }'
PASS 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; } }'
PASS 'use strict'; 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; } }'
ES6: Classes: Program level class statement throws exception in strict mode https://bugs.webkit.org/show_bug.cgi?id=143038 Reviewed by Ryosuke Niwa. Source/JavaScriptCore: Classes expose a name to the current lexical environment. This treats "class X {}" like "var X = class X {}". Ideally it would be "let X = class X {}". Also, improve error messages for class statements where the class is missing a name. * parser/Parser.h: * parser/Parser.cpp: (JSC::Parser<LexerType>::parseClass): Fill name in info parameter if needed. Better error message if name is needed and missing. (JSC::Parser<LexerType>::parseClassDeclaration): Pass info parameter to get name, and expose the name as a variable name. (JSC::Parser<LexerType>::parsePrimaryExpression): Pass info parameter that is ignored. * parser/ParserFunctionInfo.h: Add a parser info for class, to extract the name. LayoutTests: This updates a number of existing tests that were relying on poor behavior. `shouldBe` and friends use eval within a function not at the global scope. This means `shouldBe('class X { ... }')` behaves like `shouldBe('var x = ...')` not `shouldBe('x = ...')`. This means `x` will not be available in the next `shouldBe` call. Add a test specifically to cover the scoping of the class name in regular and strict mode code. Currently we treat it like var with one failing test that would pass when we treat it like let. * js/class-syntax-name.html: Added. * js/script-tests/class-syntax-name.js: Added. (runTestShouldBe): (runTestShouldBeTrue): (runTestShouldThrow): (runTestShouldNotThrow): Test class name scoping. * js/class-syntax-call-expected.txt: * js/class-syntax-declaration-expected.txt: * js/class-syntax-default-constructor-expected.txt: * js/class-syntax-name-expected.txt: Added. * js/script-tests/class-syntax-call.js: * js/script-tests/class-syntax-declaration.js: * js/script-tests/class-syntax-default-constructor.js: Canonical link: https://commits.webkit.org/161082@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@181973 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-03-25 21:33:59 +00:00
Class expression assignment to variable
ES6 class syntax should use block scoping https://bugs.webkit.org/show_bug.cgi?id=142567 Reviewed by Geoffrey Garen. Source/JavaScriptCore: We treat class declarations like we do "let" declarations. The class name is under TDZ until the class declaration statement is evaluated. Class declarations also follow the same rules as "let": No duplicate definitions inside a lexical environment. * parser/ASTBuilder.h: (JSC::ASTBuilder::createClassDeclStatement): * parser/Parser.cpp: (JSC::Parser<LexerType>::parseClassDeclaration): * tests/stress/class-syntax-block-scoping.js: Added. (assert): (truth): (.): * tests/stress/class-syntax-definition-semantics.js: Added. (shouldBeSyntaxError): (shouldNotBeSyntaxError): (truth): * tests/stress/class-syntax-tdz.js: (assert): (shouldThrowTDZ): (truth): (.): LayoutTests: * js/class-constructor-return-expected.txt: * js/class-syntax-call-expected.txt: * js/class-syntax-declaration-expected.txt: * js/class-syntax-default-constructor-expected.txt: * js/class-syntax-extends-expected.txt: * js/class-syntax-name-expected.txt: * js/class-syntax-super-expected.txt: * js/script-tests/class-constructor-return.js: (shouldThrow): (shouldNotThrow): (shouldBeTrue): (shouldBeFalse): * js/script-tests/class-syntax-call.js: (A): (B): (shouldThrow): (shouldNotThrow): * js/script-tests/class-syntax-declaration.js: (shouldThrow): (shouldNotThrow): (shouldBe): * js/script-tests/class-syntax-default-constructor.js: (shouldThrow): (shouldBe): (shouldBeTrue): (assert): (A): (B): * js/script-tests/class-syntax-extends.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (Base): (Base.prototype.baseMethod): * js/script-tests/class-syntax-name.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (runTestShouldBe): * js/script-tests/class-syntax-super.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (shouldBeFalse): Canonical link: https://commits.webkit.org/165577@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@187680 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-07-31 21:05:19 +00:00
PASS A:::ReferenceError: Can't find variable: A
PASS 'use strict'; A:::ReferenceError: Can't find variable: A
PASS var VarA = class {}
PASS 'use strict'; var VarA = class {}
Implement Function.name and Function#toString for ES6 class. https://bugs.webkit.org/show_bug.cgi?id=155336 Reviewed by Geoffrey Garen. Source/JavaScriptCore: The only thing that the ES6 spec says about toString with regards to class objects is: "The string representation must have the syntax of a FunctionDeclaration, FunctionExpression, GeneratorDeclaration, GeneratorExpression, ClassDeclaration, ClassExpression, ArrowFunction, MethodDefinition, or GeneratorMethod depending upon the actual characteristics of the object." Previously, invoking toString() on a class object will return the function source string of the class' constructor function. This does not conform to the spec in that the toString string for a class does not have the syntax of a ClassDeclaration or ClassExpression. This is now fixed by doing the following: 1. Added "m_classSource" to FunctionExecutable (and correspondingly to UnlinkedFunctionExecutable, FunctionMetadataNode, and ClassExprNode). m_classSource is the SourceCode for the code range "class ... { ... }". Since the class constructor function is the in memory representation of the class object, only class constructor functions will have its m_classSource set. m_classSource will be "null" (by default) for all other functions. This is how we know if a FunctionExecutable is for a class. Note: FunctionExecutable does not have its own m_classSource. It always gets it from its UnlinkedFunctionExecutable. This is ok to do because our CodeCache currently does not cache UnlinkedFunctionExecutables for class constructors. 2. The ClassExprNode now tracks the SourceCode range for the class expression. This is used to set m_classSource in the UnlinkedFunctionExecutable at bytecode generation time, and the FunctionExecutable later at bytecode linking time. 3. Function.prototype.toString() now checks if the function is for a class. If so, it returns the string for the class source instead of just the function source for the class constructor. Note: the class source is static from the time the class was parsed. This can introduces some weirdness at runtime. Consider the following: var v1 = class {} v1.toString(); // yields "class {}". class c2 extends v1 {} c2.__proto__ === v1; // yields true i.e. c2 extends v1. c2.toString(); // yields "class c2 extends v1 {}" which is fine. v1 = {}; // point v1 to something else now. c2.__proto__ === v1; // now yields false i.e. c2 no longer extends v1. // c2 actually extends the class that v1 used to // point to, but ... c2.toString(); // still yields "class c2 extends v1 {}" which is no longer true. It is unclear how we can best implement toString() to avoid this issue. The above behavior is how Chrome (Version 51.0.2671.0 canary (64-bit)) currently implements toString() of a class, and we do the same in this patch. In Firefox (45.0), toString() of a class will yield the function source of it constructor function, which is not better. In this patch, we also added ES6 compliance for Function.name on class objects: 4. The ClassExprNode now has a m_ecmaName string for tracking the inferred name of a class according to the ES6 spec. The ASTBuilder now mirrors its handling of FuncExprNodes to ClassExprNodes in setting the nodes' m_ecmaName where relevant. The m_ecmaName is later used to set the m_ecmaName of the FunctionExecutable of the class constructor, which in turn is used to populate the initial value of the Function.name property. 5. Also renamed some variable names (/m_metadata/metadata/) to be consistent with webkit naming convention. * bytecode/UnlinkedFunctionExecutable.cpp: (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable): * bytecode/UnlinkedFunctionExecutable.h: * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitNewArrowFunctionExpression): (JSC::BytecodeGenerator::emitNewDefaultConstructor): * bytecompiler/BytecodeGenerator.h: * bytecompiler/NodesCodegen.cpp: (JSC::ClassExprNode::emitBytecode): * parser/ASTBuilder.h: (JSC::ASTBuilder::createAssignResolve): (JSC::ASTBuilder::createYield): (JSC::ASTBuilder::createClassExpr): (JSC::ASTBuilder::createFunctionExpr): (JSC::ASTBuilder::createProperty): (JSC::ASTBuilder::makeAssignNode): * parser/NodeConstructors.h: (JSC::FunctionParameters::FunctionParameters): (JSC::BaseFuncExprNode::BaseFuncExprNode): (JSC::FuncExprNode::FuncExprNode): (JSC::FuncDeclNode::FuncDeclNode): (JSC::ArrowFuncExprNode::ArrowFuncExprNode): (JSC::ClassDeclNode::ClassDeclNode): (JSC::ClassExprNode::ClassExprNode): * parser/Nodes.h: (JSC::ExpressionNode::isDestructuringNode): (JSC::ExpressionNode::isFuncExprNode): (JSC::ExpressionNode::isArrowFuncExprNode): (JSC::ExpressionNode::isClassExprNode): (JSC::ExpressionNode::isCommaNode): (JSC::ExpressionNode::isSimpleArray): (JSC::ExpressionNode::isAdd): * parser/Parser.cpp: (JSC::stringForFunctionMode): (JSC::Parser<LexerType>::parseFunctionInfo): (JSC::Parser<LexerType>::parseClass): * parser/ParserFunctionInfo.h: * parser/SyntaxChecker.h: (JSC::SyntaxChecker::createEmptyLetExpression): (JSC::SyntaxChecker::createYield): (JSC::SyntaxChecker::createClassExpr): (JSC::SyntaxChecker::createFunctionExpr): (JSC::SyntaxChecker::createFunctionMetadata): (JSC::SyntaxChecker::createArrowFunctionExpr): * runtime/Executable.cpp: (JSC::FunctionExecutable::FunctionExecutable): (JSC::FunctionExecutable::finishCreation): * runtime/Executable.h: * runtime/FunctionPrototype.cpp: (JSC::functionProtoFuncToString): * tests/es6.yaml: LayoutTests: * js/class-syntax-name-expected.txt: * js/script-tests/class-syntax-name.js: (shouldBe): (shouldBeTrue): - Rebased expected result. * js/function-toString-vs-name.html: * js/script-tests/function-toString-vs-name.js: - Added new tests for class. * platform/mac/inspector/model/remote-object-expected.txt: - Rebased expected result. Canonical link: https://commits.webkit.org/173492@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@198042 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-03-11 21:08:08 +00:00
PASS var VarA = class { constructor() {} }; VarA.toString():::'class { constructor() {} }'
PASS 'use strict'; var VarA = class { constructor() {} }; VarA.toString():::'class { constructor() {} }'
ES6 class syntax should use block scoping https://bugs.webkit.org/show_bug.cgi?id=142567 Reviewed by Geoffrey Garen. Source/JavaScriptCore: We treat class declarations like we do "let" declarations. The class name is under TDZ until the class declaration statement is evaluated. Class declarations also follow the same rules as "let": No duplicate definitions inside a lexical environment. * parser/ASTBuilder.h: (JSC::ASTBuilder::createClassDeclStatement): * parser/Parser.cpp: (JSC::Parser<LexerType>::parseClassDeclaration): * tests/stress/class-syntax-block-scoping.js: Added. (assert): (truth): (.): * tests/stress/class-syntax-definition-semantics.js: Added. (shouldBeSyntaxError): (shouldNotBeSyntaxError): (truth): * tests/stress/class-syntax-tdz.js: (assert): (shouldThrowTDZ): (truth): (.): LayoutTests: * js/class-constructor-return-expected.txt: * js/class-syntax-call-expected.txt: * js/class-syntax-declaration-expected.txt: * js/class-syntax-default-constructor-expected.txt: * js/class-syntax-extends-expected.txt: * js/class-syntax-name-expected.txt: * js/class-syntax-super-expected.txt: * js/script-tests/class-constructor-return.js: (shouldThrow): (shouldNotThrow): (shouldBeTrue): (shouldBeFalse): * js/script-tests/class-syntax-call.js: (A): (B): (shouldThrow): (shouldNotThrow): * js/script-tests/class-syntax-declaration.js: (shouldThrow): (shouldNotThrow): (shouldBe): * js/script-tests/class-syntax-default-constructor.js: (shouldThrow): (shouldBe): (shouldBeTrue): (assert): (A): (B): * js/script-tests/class-syntax-extends.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (Base): (Base.prototype.baseMethod): * js/script-tests/class-syntax-name.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (runTestShouldBe): * js/script-tests/class-syntax-super.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (shouldBeFalse): Canonical link: https://commits.webkit.org/165577@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@187680 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-07-31 21:05:19 +00:00
PASS VarA:::ReferenceError: Can't find variable: VarA
PASS 'use strict'; VarA:::ReferenceError: Can't find variable: VarA
PASS var VarA = class A { constructor() {} }
PASS 'use strict'; var VarA = class A { constructor() {} }
Implement Function.name and Function#toString for ES6 class. https://bugs.webkit.org/show_bug.cgi?id=155336 Reviewed by Geoffrey Garen. Source/JavaScriptCore: The only thing that the ES6 spec says about toString with regards to class objects is: "The string representation must have the syntax of a FunctionDeclaration, FunctionExpression, GeneratorDeclaration, GeneratorExpression, ClassDeclaration, ClassExpression, ArrowFunction, MethodDefinition, or GeneratorMethod depending upon the actual characteristics of the object." Previously, invoking toString() on a class object will return the function source string of the class' constructor function. This does not conform to the spec in that the toString string for a class does not have the syntax of a ClassDeclaration or ClassExpression. This is now fixed by doing the following: 1. Added "m_classSource" to FunctionExecutable (and correspondingly to UnlinkedFunctionExecutable, FunctionMetadataNode, and ClassExprNode). m_classSource is the SourceCode for the code range "class ... { ... }". Since the class constructor function is the in memory representation of the class object, only class constructor functions will have its m_classSource set. m_classSource will be "null" (by default) for all other functions. This is how we know if a FunctionExecutable is for a class. Note: FunctionExecutable does not have its own m_classSource. It always gets it from its UnlinkedFunctionExecutable. This is ok to do because our CodeCache currently does not cache UnlinkedFunctionExecutables for class constructors. 2. The ClassExprNode now tracks the SourceCode range for the class expression. This is used to set m_classSource in the UnlinkedFunctionExecutable at bytecode generation time, and the FunctionExecutable later at bytecode linking time. 3. Function.prototype.toString() now checks if the function is for a class. If so, it returns the string for the class source instead of just the function source for the class constructor. Note: the class source is static from the time the class was parsed. This can introduces some weirdness at runtime. Consider the following: var v1 = class {} v1.toString(); // yields "class {}". class c2 extends v1 {} c2.__proto__ === v1; // yields true i.e. c2 extends v1. c2.toString(); // yields "class c2 extends v1 {}" which is fine. v1 = {}; // point v1 to something else now. c2.__proto__ === v1; // now yields false i.e. c2 no longer extends v1. // c2 actually extends the class that v1 used to // point to, but ... c2.toString(); // still yields "class c2 extends v1 {}" which is no longer true. It is unclear how we can best implement toString() to avoid this issue. The above behavior is how Chrome (Version 51.0.2671.0 canary (64-bit)) currently implements toString() of a class, and we do the same in this patch. In Firefox (45.0), toString() of a class will yield the function source of it constructor function, which is not better. In this patch, we also added ES6 compliance for Function.name on class objects: 4. The ClassExprNode now has a m_ecmaName string for tracking the inferred name of a class according to the ES6 spec. The ASTBuilder now mirrors its handling of FuncExprNodes to ClassExprNodes in setting the nodes' m_ecmaName where relevant. The m_ecmaName is later used to set the m_ecmaName of the FunctionExecutable of the class constructor, which in turn is used to populate the initial value of the Function.name property. 5. Also renamed some variable names (/m_metadata/metadata/) to be consistent with webkit naming convention. * bytecode/UnlinkedFunctionExecutable.cpp: (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable): * bytecode/UnlinkedFunctionExecutable.h: * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitNewArrowFunctionExpression): (JSC::BytecodeGenerator::emitNewDefaultConstructor): * bytecompiler/BytecodeGenerator.h: * bytecompiler/NodesCodegen.cpp: (JSC::ClassExprNode::emitBytecode): * parser/ASTBuilder.h: (JSC::ASTBuilder::createAssignResolve): (JSC::ASTBuilder::createYield): (JSC::ASTBuilder::createClassExpr): (JSC::ASTBuilder::createFunctionExpr): (JSC::ASTBuilder::createProperty): (JSC::ASTBuilder::makeAssignNode): * parser/NodeConstructors.h: (JSC::FunctionParameters::FunctionParameters): (JSC::BaseFuncExprNode::BaseFuncExprNode): (JSC::FuncExprNode::FuncExprNode): (JSC::FuncDeclNode::FuncDeclNode): (JSC::ArrowFuncExprNode::ArrowFuncExprNode): (JSC::ClassDeclNode::ClassDeclNode): (JSC::ClassExprNode::ClassExprNode): * parser/Nodes.h: (JSC::ExpressionNode::isDestructuringNode): (JSC::ExpressionNode::isFuncExprNode): (JSC::ExpressionNode::isArrowFuncExprNode): (JSC::ExpressionNode::isClassExprNode): (JSC::ExpressionNode::isCommaNode): (JSC::ExpressionNode::isSimpleArray): (JSC::ExpressionNode::isAdd): * parser/Parser.cpp: (JSC::stringForFunctionMode): (JSC::Parser<LexerType>::parseFunctionInfo): (JSC::Parser<LexerType>::parseClass): * parser/ParserFunctionInfo.h: * parser/SyntaxChecker.h: (JSC::SyntaxChecker::createEmptyLetExpression): (JSC::SyntaxChecker::createYield): (JSC::SyntaxChecker::createClassExpr): (JSC::SyntaxChecker::createFunctionExpr): (JSC::SyntaxChecker::createFunctionMetadata): (JSC::SyntaxChecker::createArrowFunctionExpr): * runtime/Executable.cpp: (JSC::FunctionExecutable::FunctionExecutable): (JSC::FunctionExecutable::finishCreation): * runtime/Executable.h: * runtime/FunctionPrototype.cpp: (JSC::functionProtoFuncToString): * tests/es6.yaml: LayoutTests: * js/class-syntax-name-expected.txt: * js/script-tests/class-syntax-name.js: (shouldBe): (shouldBeTrue): - Rebased expected result. * js/function-toString-vs-name.html: * js/script-tests/function-toString-vs-name.js: - Added new tests for class. * platform/mac/inspector/model/remote-object-expected.txt: - Rebased expected result. Canonical link: https://commits.webkit.org/173492@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@198042 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-03-11 21:08:08 +00:00
PASS var VarA = class A { constructor() {} }; VarA.toString():::'class A { constructor() {} }'
PASS 'use strict'; var VarA = class A { constructor() {} }; VarA.toString():::'class A { constructor() {} }'
ES6 class syntax should use block scoping https://bugs.webkit.org/show_bug.cgi?id=142567 Reviewed by Geoffrey Garen. Source/JavaScriptCore: We treat class declarations like we do "let" declarations. The class name is under TDZ until the class declaration statement is evaluated. Class declarations also follow the same rules as "let": No duplicate definitions inside a lexical environment. * parser/ASTBuilder.h: (JSC::ASTBuilder::createClassDeclStatement): * parser/Parser.cpp: (JSC::Parser<LexerType>::parseClassDeclaration): * tests/stress/class-syntax-block-scoping.js: Added. (assert): (truth): (.): * tests/stress/class-syntax-definition-semantics.js: Added. (shouldBeSyntaxError): (shouldNotBeSyntaxError): (truth): * tests/stress/class-syntax-tdz.js: (assert): (shouldThrowTDZ): (truth): (.): LayoutTests: * js/class-constructor-return-expected.txt: * js/class-syntax-call-expected.txt: * js/class-syntax-declaration-expected.txt: * js/class-syntax-default-constructor-expected.txt: * js/class-syntax-extends-expected.txt: * js/class-syntax-name-expected.txt: * js/class-syntax-super-expected.txt: * js/script-tests/class-constructor-return.js: (shouldThrow): (shouldNotThrow): (shouldBeTrue): (shouldBeFalse): * js/script-tests/class-syntax-call.js: (A): (B): (shouldThrow): (shouldNotThrow): * js/script-tests/class-syntax-declaration.js: (shouldThrow): (shouldNotThrow): (shouldBe): * js/script-tests/class-syntax-default-constructor.js: (shouldThrow): (shouldBe): (shouldBeTrue): (assert): (A): (B): * js/script-tests/class-syntax-extends.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (Base): (Base.prototype.baseMethod): * js/script-tests/class-syntax-name.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (runTestShouldBe): * js/script-tests/class-syntax-super.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (shouldBeFalse): Canonical link: https://commits.webkit.org/165577@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@187680 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-07-31 21:05:19 +00:00
PASS var VarA = class A { constructor() {} }; A.toString():::ReferenceError: Can't find variable: A
PASS 'use strict'; var VarA = class A { constructor() {} }; A.toString():::ReferenceError: Can't find variable: A
PASS var VarA = class A { constructor() {} }; (new VarA) instanceof VarA
PASS 'use strict'; var VarA = class A { constructor() {} }; (new VarA) instanceof VarA
Implement Function.name and Function#toString for ES6 class. https://bugs.webkit.org/show_bug.cgi?id=155336 Reviewed by Geoffrey Garen. Source/JavaScriptCore: The only thing that the ES6 spec says about toString with regards to class objects is: "The string representation must have the syntax of a FunctionDeclaration, FunctionExpression, GeneratorDeclaration, GeneratorExpression, ClassDeclaration, ClassExpression, ArrowFunction, MethodDefinition, or GeneratorMethod depending upon the actual characteristics of the object." Previously, invoking toString() on a class object will return the function source string of the class' constructor function. This does not conform to the spec in that the toString string for a class does not have the syntax of a ClassDeclaration or ClassExpression. This is now fixed by doing the following: 1. Added "m_classSource" to FunctionExecutable (and correspondingly to UnlinkedFunctionExecutable, FunctionMetadataNode, and ClassExprNode). m_classSource is the SourceCode for the code range "class ... { ... }". Since the class constructor function is the in memory representation of the class object, only class constructor functions will have its m_classSource set. m_classSource will be "null" (by default) for all other functions. This is how we know if a FunctionExecutable is for a class. Note: FunctionExecutable does not have its own m_classSource. It always gets it from its UnlinkedFunctionExecutable. This is ok to do because our CodeCache currently does not cache UnlinkedFunctionExecutables for class constructors. 2. The ClassExprNode now tracks the SourceCode range for the class expression. This is used to set m_classSource in the UnlinkedFunctionExecutable at bytecode generation time, and the FunctionExecutable later at bytecode linking time. 3. Function.prototype.toString() now checks if the function is for a class. If so, it returns the string for the class source instead of just the function source for the class constructor. Note: the class source is static from the time the class was parsed. This can introduces some weirdness at runtime. Consider the following: var v1 = class {} v1.toString(); // yields "class {}". class c2 extends v1 {} c2.__proto__ === v1; // yields true i.e. c2 extends v1. c2.toString(); // yields "class c2 extends v1 {}" which is fine. v1 = {}; // point v1 to something else now. c2.__proto__ === v1; // now yields false i.e. c2 no longer extends v1. // c2 actually extends the class that v1 used to // point to, but ... c2.toString(); // still yields "class c2 extends v1 {}" which is no longer true. It is unclear how we can best implement toString() to avoid this issue. The above behavior is how Chrome (Version 51.0.2671.0 canary (64-bit)) currently implements toString() of a class, and we do the same in this patch. In Firefox (45.0), toString() of a class will yield the function source of it constructor function, which is not better. In this patch, we also added ES6 compliance for Function.name on class objects: 4. The ClassExprNode now has a m_ecmaName string for tracking the inferred name of a class according to the ES6 spec. The ASTBuilder now mirrors its handling of FuncExprNodes to ClassExprNodes in setting the nodes' m_ecmaName where relevant. The m_ecmaName is later used to set the m_ecmaName of the FunctionExecutable of the class constructor, which in turn is used to populate the initial value of the Function.name property. 5. Also renamed some variable names (/m_metadata/metadata/) to be consistent with webkit naming convention. * bytecode/UnlinkedFunctionExecutable.cpp: (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable): * bytecode/UnlinkedFunctionExecutable.h: * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitNewArrowFunctionExpression): (JSC::BytecodeGenerator::emitNewDefaultConstructor): * bytecompiler/BytecodeGenerator.h: * bytecompiler/NodesCodegen.cpp: (JSC::ClassExprNode::emitBytecode): * parser/ASTBuilder.h: (JSC::ASTBuilder::createAssignResolve): (JSC::ASTBuilder::createYield): (JSC::ASTBuilder::createClassExpr): (JSC::ASTBuilder::createFunctionExpr): (JSC::ASTBuilder::createProperty): (JSC::ASTBuilder::makeAssignNode): * parser/NodeConstructors.h: (JSC::FunctionParameters::FunctionParameters): (JSC::BaseFuncExprNode::BaseFuncExprNode): (JSC::FuncExprNode::FuncExprNode): (JSC::FuncDeclNode::FuncDeclNode): (JSC::ArrowFuncExprNode::ArrowFuncExprNode): (JSC::ClassDeclNode::ClassDeclNode): (JSC::ClassExprNode::ClassExprNode): * parser/Nodes.h: (JSC::ExpressionNode::isDestructuringNode): (JSC::ExpressionNode::isFuncExprNode): (JSC::ExpressionNode::isArrowFuncExprNode): (JSC::ExpressionNode::isClassExprNode): (JSC::ExpressionNode::isCommaNode): (JSC::ExpressionNode::isSimpleArray): (JSC::ExpressionNode::isAdd): * parser/Parser.cpp: (JSC::stringForFunctionMode): (JSC::Parser<LexerType>::parseFunctionInfo): (JSC::Parser<LexerType>::parseClass): * parser/ParserFunctionInfo.h: * parser/SyntaxChecker.h: (JSC::SyntaxChecker::createEmptyLetExpression): (JSC::SyntaxChecker::createYield): (JSC::SyntaxChecker::createClassExpr): (JSC::SyntaxChecker::createFunctionExpr): (JSC::SyntaxChecker::createFunctionMetadata): (JSC::SyntaxChecker::createArrowFunctionExpr): * runtime/Executable.cpp: (JSC::FunctionExecutable::FunctionExecutable): (JSC::FunctionExecutable::finishCreation): * runtime/Executable.h: * runtime/FunctionPrototype.cpp: (JSC::functionProtoFuncToString): * tests/es6.yaml: LayoutTests: * js/class-syntax-name-expected.txt: * js/script-tests/class-syntax-name.js: (shouldBe): (shouldBeTrue): - Rebased expected result. * js/function-toString-vs-name.html: * js/script-tests/function-toString-vs-name.js: - Added new tests for class. * platform/mac/inspector/model/remote-object-expected.txt: - Rebased expected result. Canonical link: https://commits.webkit.org/173492@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@198042 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-03-11 21:08:08 +00:00
PASS var VarA = class A { constructor() { this.base = A; } }; (new VarA).base.toString():::'class A { constructor() { this.base = A; } }'
PASS 'use strict'; var VarA = class A { constructor() { this.base = A; } }; (new VarA).base.toString():::'class A { constructor() { this.base = A; } }'
ES6 class syntax should use block scoping https://bugs.webkit.org/show_bug.cgi?id=142567 Reviewed by Geoffrey Garen. Source/JavaScriptCore: We treat class declarations like we do "let" declarations. The class name is under TDZ until the class declaration statement is evaluated. Class declarations also follow the same rules as "let": No duplicate definitions inside a lexical environment. * parser/ASTBuilder.h: (JSC::ASTBuilder::createClassDeclStatement): * parser/Parser.cpp: (JSC::Parser<LexerType>::parseClassDeclaration): * tests/stress/class-syntax-block-scoping.js: Added. (assert): (truth): (.): * tests/stress/class-syntax-definition-semantics.js: Added. (shouldBeSyntaxError): (shouldNotBeSyntaxError): (truth): * tests/stress/class-syntax-tdz.js: (assert): (shouldThrowTDZ): (truth): (.): LayoutTests: * js/class-constructor-return-expected.txt: * js/class-syntax-call-expected.txt: * js/class-syntax-declaration-expected.txt: * js/class-syntax-default-constructor-expected.txt: * js/class-syntax-extends-expected.txt: * js/class-syntax-name-expected.txt: * js/class-syntax-super-expected.txt: * js/script-tests/class-constructor-return.js: (shouldThrow): (shouldNotThrow): (shouldBeTrue): (shouldBeFalse): * js/script-tests/class-syntax-call.js: (A): (B): (shouldThrow): (shouldNotThrow): * js/script-tests/class-syntax-declaration.js: (shouldThrow): (shouldNotThrow): (shouldBe): * js/script-tests/class-syntax-default-constructor.js: (shouldThrow): (shouldBe): (shouldBeTrue): (assert): (A): (B): * js/script-tests/class-syntax-extends.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (Base): (Base.prototype.baseMethod): * js/script-tests/class-syntax-name.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (runTestShouldBe): * js/script-tests/class-syntax-super.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (shouldBeFalse): Canonical link: https://commits.webkit.org/165577@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@187680 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-07-31 21:05:19 +00:00
PASS var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} };
PASS 'use strict'; var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} };
PASS var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; B:::ReferenceError: Can't find variable: B
PASS 'use strict'; var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; B:::ReferenceError: Can't find variable: B
Implement Function.name and Function#toString for ES6 class. https://bugs.webkit.org/show_bug.cgi?id=155336 Reviewed by Geoffrey Garen. Source/JavaScriptCore: The only thing that the ES6 spec says about toString with regards to class objects is: "The string representation must have the syntax of a FunctionDeclaration, FunctionExpression, GeneratorDeclaration, GeneratorExpression, ClassDeclaration, ClassExpression, ArrowFunction, MethodDefinition, or GeneratorMethod depending upon the actual characteristics of the object." Previously, invoking toString() on a class object will return the function source string of the class' constructor function. This does not conform to the spec in that the toString string for a class does not have the syntax of a ClassDeclaration or ClassExpression. This is now fixed by doing the following: 1. Added "m_classSource" to FunctionExecutable (and correspondingly to UnlinkedFunctionExecutable, FunctionMetadataNode, and ClassExprNode). m_classSource is the SourceCode for the code range "class ... { ... }". Since the class constructor function is the in memory representation of the class object, only class constructor functions will have its m_classSource set. m_classSource will be "null" (by default) for all other functions. This is how we know if a FunctionExecutable is for a class. Note: FunctionExecutable does not have its own m_classSource. It always gets it from its UnlinkedFunctionExecutable. This is ok to do because our CodeCache currently does not cache UnlinkedFunctionExecutables for class constructors. 2. The ClassExprNode now tracks the SourceCode range for the class expression. This is used to set m_classSource in the UnlinkedFunctionExecutable at bytecode generation time, and the FunctionExecutable later at bytecode linking time. 3. Function.prototype.toString() now checks if the function is for a class. If so, it returns the string for the class source instead of just the function source for the class constructor. Note: the class source is static from the time the class was parsed. This can introduces some weirdness at runtime. Consider the following: var v1 = class {} v1.toString(); // yields "class {}". class c2 extends v1 {} c2.__proto__ === v1; // yields true i.e. c2 extends v1. c2.toString(); // yields "class c2 extends v1 {}" which is fine. v1 = {}; // point v1 to something else now. c2.__proto__ === v1; // now yields false i.e. c2 no longer extends v1. // c2 actually extends the class that v1 used to // point to, but ... c2.toString(); // still yields "class c2 extends v1 {}" which is no longer true. It is unclear how we can best implement toString() to avoid this issue. The above behavior is how Chrome (Version 51.0.2671.0 canary (64-bit)) currently implements toString() of a class, and we do the same in this patch. In Firefox (45.0), toString() of a class will yield the function source of it constructor function, which is not better. In this patch, we also added ES6 compliance for Function.name on class objects: 4. The ClassExprNode now has a m_ecmaName string for tracking the inferred name of a class according to the ES6 spec. The ASTBuilder now mirrors its handling of FuncExprNodes to ClassExprNodes in setting the nodes' m_ecmaName where relevant. The m_ecmaName is later used to set the m_ecmaName of the FunctionExecutable of the class constructor, which in turn is used to populate the initial value of the Function.name property. 5. Also renamed some variable names (/m_metadata/metadata/) to be consistent with webkit naming convention. * bytecode/UnlinkedFunctionExecutable.cpp: (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable): * bytecode/UnlinkedFunctionExecutable.h: * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitNewArrowFunctionExpression): (JSC::BytecodeGenerator::emitNewDefaultConstructor): * bytecompiler/BytecodeGenerator.h: * bytecompiler/NodesCodegen.cpp: (JSC::ClassExprNode::emitBytecode): * parser/ASTBuilder.h: (JSC::ASTBuilder::createAssignResolve): (JSC::ASTBuilder::createYield): (JSC::ASTBuilder::createClassExpr): (JSC::ASTBuilder::createFunctionExpr): (JSC::ASTBuilder::createProperty): (JSC::ASTBuilder::makeAssignNode): * parser/NodeConstructors.h: (JSC::FunctionParameters::FunctionParameters): (JSC::BaseFuncExprNode::BaseFuncExprNode): (JSC::FuncExprNode::FuncExprNode): (JSC::FuncDeclNode::FuncDeclNode): (JSC::ArrowFuncExprNode::ArrowFuncExprNode): (JSC::ClassDeclNode::ClassDeclNode): (JSC::ClassExprNode::ClassExprNode): * parser/Nodes.h: (JSC::ExpressionNode::isDestructuringNode): (JSC::ExpressionNode::isFuncExprNode): (JSC::ExpressionNode::isArrowFuncExprNode): (JSC::ExpressionNode::isClassExprNode): (JSC::ExpressionNode::isCommaNode): (JSC::ExpressionNode::isSimpleArray): (JSC::ExpressionNode::isAdd): * parser/Parser.cpp: (JSC::stringForFunctionMode): (JSC::Parser<LexerType>::parseFunctionInfo): (JSC::Parser<LexerType>::parseClass): * parser/ParserFunctionInfo.h: * parser/SyntaxChecker.h: (JSC::SyntaxChecker::createEmptyLetExpression): (JSC::SyntaxChecker::createYield): (JSC::SyntaxChecker::createClassExpr): (JSC::SyntaxChecker::createFunctionExpr): (JSC::SyntaxChecker::createFunctionMetadata): (JSC::SyntaxChecker::createArrowFunctionExpr): * runtime/Executable.cpp: (JSC::FunctionExecutable::FunctionExecutable): (JSC::FunctionExecutable::finishCreation): * runtime/Executable.h: * runtime/FunctionPrototype.cpp: (JSC::functionProtoFuncToString): * tests/es6.yaml: LayoutTests: * js/class-syntax-name-expected.txt: * js/script-tests/class-syntax-name.js: (shouldBe): (shouldBeTrue): - Rebased expected result. * js/function-toString-vs-name.html: * js/script-tests/function-toString-vs-name.js: - Added new tests for class. * platform/mac/inspector/model/remote-object-expected.txt: - Rebased expected result. Canonical link: https://commits.webkit.org/173492@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@198042 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-03-11 21:08:08 +00:00
PASS var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; VarB.toString():::'class B extends VarA { constructor() {} }'
PASS 'use strict'; var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; VarB.toString():::'class B extends VarA { constructor() {} }'
ES6 class syntax should use block scoping https://bugs.webkit.org/show_bug.cgi?id=142567 Reviewed by Geoffrey Garen. Source/JavaScriptCore: We treat class declarations like we do "let" declarations. The class name is under TDZ until the class declaration statement is evaluated. Class declarations also follow the same rules as "let": No duplicate definitions inside a lexical environment. * parser/ASTBuilder.h: (JSC::ASTBuilder::createClassDeclStatement): * parser/Parser.cpp: (JSC::Parser<LexerType>::parseClassDeclaration): * tests/stress/class-syntax-block-scoping.js: Added. (assert): (truth): (.): * tests/stress/class-syntax-definition-semantics.js: Added. (shouldBeSyntaxError): (shouldNotBeSyntaxError): (truth): * tests/stress/class-syntax-tdz.js: (assert): (shouldThrowTDZ): (truth): (.): LayoutTests: * js/class-constructor-return-expected.txt: * js/class-syntax-call-expected.txt: * js/class-syntax-declaration-expected.txt: * js/class-syntax-default-constructor-expected.txt: * js/class-syntax-extends-expected.txt: * js/class-syntax-name-expected.txt: * js/class-syntax-super-expected.txt: * js/script-tests/class-constructor-return.js: (shouldThrow): (shouldNotThrow): (shouldBeTrue): (shouldBeFalse): * js/script-tests/class-syntax-call.js: (A): (B): (shouldThrow): (shouldNotThrow): * js/script-tests/class-syntax-declaration.js: (shouldThrow): (shouldNotThrow): (shouldBe): * js/script-tests/class-syntax-default-constructor.js: (shouldThrow): (shouldBe): (shouldBeTrue): (assert): (A): (B): * js/script-tests/class-syntax-extends.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (Base): (Base.prototype.baseMethod): * js/script-tests/class-syntax-name.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (runTestShouldBe): * js/script-tests/class-syntax-super.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (shouldBeFalse): Canonical link: https://commits.webkit.org/165577@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@187680 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-07-31 21:05:19 +00:00
PASS var VarA = class A { constructor() {} }; var VarB = class B extends VarA { }; (new VarB) instanceof VarA
PASS 'use strict'; var VarA = class A { constructor() {} }; var VarB = class B extends VarA { }; (new VarB) instanceof VarA
PASS var VarA = class A { constructor() {} }; var VarB = class B extends VarA { }; (new VarB) instanceof VarB
PASS 'use strict'; var VarA = class A { constructor() {} }; var VarB = class B extends VarA { }; (new VarB) instanceof VarB
PASS 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
PASS 'use strict'; 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
PASS 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
PASS 'use strict'; 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
PASS 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
PASS 'use strict'; 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
ES6: Classes: Program level class statement throws exception in strict mode https://bugs.webkit.org/show_bug.cgi?id=143038 Reviewed by Ryosuke Niwa. Source/JavaScriptCore: Classes expose a name to the current lexical environment. This treats "class X {}" like "var X = class X {}". Ideally it would be "let X = class X {}". Also, improve error messages for class statements where the class is missing a name. * parser/Parser.h: * parser/Parser.cpp: (JSC::Parser<LexerType>::parseClass): Fill name in info parameter if needed. Better error message if name is needed and missing. (JSC::Parser<LexerType>::parseClassDeclaration): Pass info parameter to get name, and expose the name as a variable name. (JSC::Parser<LexerType>::parsePrimaryExpression): Pass info parameter that is ignored. * parser/ParserFunctionInfo.h: Add a parser info for class, to extract the name. LayoutTests: This updates a number of existing tests that were relying on poor behavior. `shouldBe` and friends use eval within a function not at the global scope. This means `shouldBe('class X { ... }')` behaves like `shouldBe('var x = ...')` not `shouldBe('x = ...')`. This means `x` will not be available in the next `shouldBe` call. Add a test specifically to cover the scoping of the class name in regular and strict mode code. Currently we treat it like var with one failing test that would pass when we treat it like let. * js/class-syntax-name.html: Added. * js/script-tests/class-syntax-name.js: Added. (runTestShouldBe): (runTestShouldBeTrue): (runTestShouldThrow): (runTestShouldNotThrow): Test class name scoping. * js/class-syntax-call-expected.txt: * js/class-syntax-declaration-expected.txt: * js/class-syntax-default-constructor-expected.txt: * js/class-syntax-name-expected.txt: Added. * js/script-tests/class-syntax-call.js: * js/script-tests/class-syntax-declaration.js: * js/script-tests/class-syntax-default-constructor.js: Canonical link: https://commits.webkit.org/161082@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@181973 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-03-25 21:33:59 +00:00
Class statement binding in other circumstances
ES6 class syntax should use block scoping https://bugs.webkit.org/show_bug.cgi?id=142567 Reviewed by Geoffrey Garen. Source/JavaScriptCore: We treat class declarations like we do "let" declarations. The class name is under TDZ until the class declaration statement is evaluated. Class declarations also follow the same rules as "let": No duplicate definitions inside a lexical environment. * parser/ASTBuilder.h: (JSC::ASTBuilder::createClassDeclStatement): * parser/Parser.cpp: (JSC::Parser<LexerType>::parseClassDeclaration): * tests/stress/class-syntax-block-scoping.js: Added. (assert): (truth): (.): * tests/stress/class-syntax-definition-semantics.js: Added. (shouldBeSyntaxError): (shouldNotBeSyntaxError): (truth): * tests/stress/class-syntax-tdz.js: (assert): (shouldThrowTDZ): (truth): (.): LayoutTests: * js/class-constructor-return-expected.txt: * js/class-syntax-call-expected.txt: * js/class-syntax-declaration-expected.txt: * js/class-syntax-default-constructor-expected.txt: * js/class-syntax-extends-expected.txt: * js/class-syntax-name-expected.txt: * js/class-syntax-super-expected.txt: * js/script-tests/class-constructor-return.js: (shouldThrow): (shouldNotThrow): (shouldBeTrue): (shouldBeFalse): * js/script-tests/class-syntax-call.js: (A): (B): (shouldThrow): (shouldNotThrow): * js/script-tests/class-syntax-declaration.js: (shouldThrow): (shouldNotThrow): (shouldBe): * js/script-tests/class-syntax-default-constructor.js: (shouldThrow): (shouldBe): (shouldBeTrue): (assert): (A): (B): * js/script-tests/class-syntax-extends.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (Base): (Base.prototype.baseMethod): * js/script-tests/class-syntax-name.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (runTestShouldBe): * js/script-tests/class-syntax-super.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (shouldBeFalse): Canonical link: https://commits.webkit.org/165577@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@187680 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-07-31 21:05:19 +00:00
PASS var result = A; result:::ReferenceError: Can't find variable: A
PASS 'use strict'; var result = A; result:::ReferenceError: Can't find variable: A
PASS var result = A; class A {}; result:::ReferenceError: Cannot access uninitialized variable.
PASS 'use strict'; var result = A; class A {}; result:::ReferenceError: Cannot access uninitialized variable.
PASS class A { constructor() { A = 1; } }; new A:::TypeError: Attempted to assign to readonly property.
PASS 'use strict'; class A { constructor() { A = 1; } }; new A:::TypeError: Attempted to assign to readonly property.
PASS class A { constructor() { } }; A = 1; A:::1
PASS 'use strict'; class A { constructor() { } }; A = 1; A:::1
PASS class A {}; var result = A; result
PASS 'use strict'; class A {}; var result = A; result
PASS eval('var Foo = 10'); Foo:::10
PASS 'use strict'; eval('var Foo = 10'); Foo:::ReferenceError: Can't find variable: Foo
Implement Function.name and Function#toString for ES6 class. https://bugs.webkit.org/show_bug.cgi?id=155336 Reviewed by Geoffrey Garen. Source/JavaScriptCore: The only thing that the ES6 spec says about toString with regards to class objects is: "The string representation must have the syntax of a FunctionDeclaration, FunctionExpression, GeneratorDeclaration, GeneratorExpression, ClassDeclaration, ClassExpression, ArrowFunction, MethodDefinition, or GeneratorMethod depending upon the actual characteristics of the object." Previously, invoking toString() on a class object will return the function source string of the class' constructor function. This does not conform to the spec in that the toString string for a class does not have the syntax of a ClassDeclaration or ClassExpression. This is now fixed by doing the following: 1. Added "m_classSource" to FunctionExecutable (and correspondingly to UnlinkedFunctionExecutable, FunctionMetadataNode, and ClassExprNode). m_classSource is the SourceCode for the code range "class ... { ... }". Since the class constructor function is the in memory representation of the class object, only class constructor functions will have its m_classSource set. m_classSource will be "null" (by default) for all other functions. This is how we know if a FunctionExecutable is for a class. Note: FunctionExecutable does not have its own m_classSource. It always gets it from its UnlinkedFunctionExecutable. This is ok to do because our CodeCache currently does not cache UnlinkedFunctionExecutables for class constructors. 2. The ClassExprNode now tracks the SourceCode range for the class expression. This is used to set m_classSource in the UnlinkedFunctionExecutable at bytecode generation time, and the FunctionExecutable later at bytecode linking time. 3. Function.prototype.toString() now checks if the function is for a class. If so, it returns the string for the class source instead of just the function source for the class constructor. Note: the class source is static from the time the class was parsed. This can introduces some weirdness at runtime. Consider the following: var v1 = class {} v1.toString(); // yields "class {}". class c2 extends v1 {} c2.__proto__ === v1; // yields true i.e. c2 extends v1. c2.toString(); // yields "class c2 extends v1 {}" which is fine. v1 = {}; // point v1 to something else now. c2.__proto__ === v1; // now yields false i.e. c2 no longer extends v1. // c2 actually extends the class that v1 used to // point to, but ... c2.toString(); // still yields "class c2 extends v1 {}" which is no longer true. It is unclear how we can best implement toString() to avoid this issue. The above behavior is how Chrome (Version 51.0.2671.0 canary (64-bit)) currently implements toString() of a class, and we do the same in this patch. In Firefox (45.0), toString() of a class will yield the function source of it constructor function, which is not better. In this patch, we also added ES6 compliance for Function.name on class objects: 4. The ClassExprNode now has a m_ecmaName string for tracking the inferred name of a class according to the ES6 spec. The ASTBuilder now mirrors its handling of FuncExprNodes to ClassExprNodes in setting the nodes' m_ecmaName where relevant. The m_ecmaName is later used to set the m_ecmaName of the FunctionExecutable of the class constructor, which in turn is used to populate the initial value of the Function.name property. 5. Also renamed some variable names (/m_metadata/metadata/) to be consistent with webkit naming convention. * bytecode/UnlinkedFunctionExecutable.cpp: (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable): * bytecode/UnlinkedFunctionExecutable.h: * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitNewArrowFunctionExpression): (JSC::BytecodeGenerator::emitNewDefaultConstructor): * bytecompiler/BytecodeGenerator.h: * bytecompiler/NodesCodegen.cpp: (JSC::ClassExprNode::emitBytecode): * parser/ASTBuilder.h: (JSC::ASTBuilder::createAssignResolve): (JSC::ASTBuilder::createYield): (JSC::ASTBuilder::createClassExpr): (JSC::ASTBuilder::createFunctionExpr): (JSC::ASTBuilder::createProperty): (JSC::ASTBuilder::makeAssignNode): * parser/NodeConstructors.h: (JSC::FunctionParameters::FunctionParameters): (JSC::BaseFuncExprNode::BaseFuncExprNode): (JSC::FuncExprNode::FuncExprNode): (JSC::FuncDeclNode::FuncDeclNode): (JSC::ArrowFuncExprNode::ArrowFuncExprNode): (JSC::ClassDeclNode::ClassDeclNode): (JSC::ClassExprNode::ClassExprNode): * parser/Nodes.h: (JSC::ExpressionNode::isDestructuringNode): (JSC::ExpressionNode::isFuncExprNode): (JSC::ExpressionNode::isArrowFuncExprNode): (JSC::ExpressionNode::isClassExprNode): (JSC::ExpressionNode::isCommaNode): (JSC::ExpressionNode::isSimpleArray): (JSC::ExpressionNode::isAdd): * parser/Parser.cpp: (JSC::stringForFunctionMode): (JSC::Parser<LexerType>::parseFunctionInfo): (JSC::Parser<LexerType>::parseClass): * parser/ParserFunctionInfo.h: * parser/SyntaxChecker.h: (JSC::SyntaxChecker::createEmptyLetExpression): (JSC::SyntaxChecker::createYield): (JSC::SyntaxChecker::createClassExpr): (JSC::SyntaxChecker::createFunctionExpr): (JSC::SyntaxChecker::createFunctionMetadata): (JSC::SyntaxChecker::createArrowFunctionExpr): * runtime/Executable.cpp: (JSC::FunctionExecutable::FunctionExecutable): (JSC::FunctionExecutable::finishCreation): * runtime/Executable.h: * runtime/FunctionPrototype.cpp: (JSC::functionProtoFuncToString): * tests/es6.yaml: LayoutTests: * js/class-syntax-name-expected.txt: * js/script-tests/class-syntax-name.js: (shouldBe): (shouldBeTrue): - Rebased expected result. * js/function-toString-vs-name.html: * js/script-tests/function-toString-vs-name.js: - Added new tests for class. * platform/mac/inspector/model/remote-object-expected.txt: - Rebased expected result. Canonical link: https://commits.webkit.org/173492@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@198042 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-03-11 21:08:08 +00:00
PASS eval('class Bar { constructor() {} }; Bar.toString()');:::'class Bar { constructor() {} }'
ES6 class syntax should use block scoping https://bugs.webkit.org/show_bug.cgi?id=142567 Reviewed by Geoffrey Garen. Source/JavaScriptCore: We treat class declarations like we do "let" declarations. The class name is under TDZ until the class declaration statement is evaluated. Class declarations also follow the same rules as "let": No duplicate definitions inside a lexical environment. * parser/ASTBuilder.h: (JSC::ASTBuilder::createClassDeclStatement): * parser/Parser.cpp: (JSC::Parser<LexerType>::parseClassDeclaration): * tests/stress/class-syntax-block-scoping.js: Added. (assert): (truth): (.): * tests/stress/class-syntax-definition-semantics.js: Added. (shouldBeSyntaxError): (shouldNotBeSyntaxError): (truth): * tests/stress/class-syntax-tdz.js: (assert): (shouldThrowTDZ): (truth): (.): LayoutTests: * js/class-constructor-return-expected.txt: * js/class-syntax-call-expected.txt: * js/class-syntax-declaration-expected.txt: * js/class-syntax-default-constructor-expected.txt: * js/class-syntax-extends-expected.txt: * js/class-syntax-name-expected.txt: * js/class-syntax-super-expected.txt: * js/script-tests/class-constructor-return.js: (shouldThrow): (shouldNotThrow): (shouldBeTrue): (shouldBeFalse): * js/script-tests/class-syntax-call.js: (A): (B): (shouldThrow): (shouldNotThrow): * js/script-tests/class-syntax-declaration.js: (shouldThrow): (shouldNotThrow): (shouldBe): * js/script-tests/class-syntax-default-constructor.js: (shouldThrow): (shouldBe): (shouldBeTrue): (assert): (A): (B): * js/script-tests/class-syntax-extends.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (Base): (Base.prototype.baseMethod): * js/script-tests/class-syntax-name.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (runTestShouldBe): * js/script-tests/class-syntax-super.js: (shouldThrow): (shouldNotThrow): (shouldBe): (shouldBeTrue): (shouldBeFalse): Canonical link: https://commits.webkit.org/165577@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@187680 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-07-31 21:05:19 +00:00
PASS 'use strict'; eval('class Bar { constructor() {} }'); Bar.toString():::ReferenceError: Can't find variable: Bar
PASS successfullyParsed
ES6: Classes: Program level class statement throws exception in strict mode https://bugs.webkit.org/show_bug.cgi?id=143038 Reviewed by Ryosuke Niwa. Source/JavaScriptCore: Classes expose a name to the current lexical environment. This treats "class X {}" like "var X = class X {}". Ideally it would be "let X = class X {}". Also, improve error messages for class statements where the class is missing a name. * parser/Parser.h: * parser/Parser.cpp: (JSC::Parser<LexerType>::parseClass): Fill name in info parameter if needed. Better error message if name is needed and missing. (JSC::Parser<LexerType>::parseClassDeclaration): Pass info parameter to get name, and expose the name as a variable name. (JSC::Parser<LexerType>::parsePrimaryExpression): Pass info parameter that is ignored. * parser/ParserFunctionInfo.h: Add a parser info for class, to extract the name. LayoutTests: This updates a number of existing tests that were relying on poor behavior. `shouldBe` and friends use eval within a function not at the global scope. This means `shouldBe('class X { ... }')` behaves like `shouldBe('var x = ...')` not `shouldBe('x = ...')`. This means `x` will not be available in the next `shouldBe` call. Add a test specifically to cover the scoping of the class name in regular and strict mode code. Currently we treat it like var with one failing test that would pass when we treat it like let. * js/class-syntax-name.html: Added. * js/script-tests/class-syntax-name.js: Added. (runTestShouldBe): (runTestShouldBeTrue): (runTestShouldThrow): (runTestShouldNotThrow): Test class name scoping. * js/class-syntax-call-expected.txt: * js/class-syntax-declaration-expected.txt: * js/class-syntax-default-constructor-expected.txt: * js/class-syntax-name-expected.txt: Added. * js/script-tests/class-syntax-call.js: * js/script-tests/class-syntax-declaration.js: * js/script-tests/class-syntax-default-constructor.js: Canonical link: https://commits.webkit.org/161082@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@181973 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-03-25 21:33:59 +00:00
TEST COMPLETE