Title: [198332] trunk
Revision
198332
Author
[email protected]
Date
2016-03-17 07:58:57 -0700 (Thu, 17 Mar 2016)

Log Message

Method names should not appear in the lexical scope of the method's body.
https://bugs.webkit.org/show_bug.cgi?id=155568

Reviewed by Saam Barati.

Source/_javascript_Core:

Consider this scenario:

    var f = "foo";
    var result = ({
        f() {
            return f; // f should be the string "foo", not this method f.
        }
    }).f();
    result === "foo"; // Should be true.

The reason this is not current working is because the parser does not yet
distinguish between FunctionExpressions and MethodDefinitions.  The ES6 spec
explicitly distinguishes between the 2, and we should do the same.
        
This patch changes all methods (and getters and setters which are also methods)
to have a FunctionMode of MethodDefinition (instead of FunctionExpression).
functionNameIsInScope() is responsible for determining whether a function's name
should be in its scope or not.  It already returns false for any function
whose FunctionMode is not FunctionExpression.  Giving methods the MethodDefinition
FunctionMode gets us the correct behavior ES6 expects.

* bytecode/UnlinkedFunctionExecutable.cpp:
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
* bytecode/UnlinkedFunctionExecutable.h:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitNewArrowFunctionExpression):
(JSC::BytecodeGenerator::emitNewMethodDefinition):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::ArrowFuncExprNode::emitBytecode):
(JSC::MethodDefinitionNode::emitBytecode):
(JSC::YieldExprNode::emitBytecode):
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createFunctionExpr):
(JSC::ASTBuilder::createMethodDefinition):
(JSC::ASTBuilder::createFunctionMetadata):
(JSC::ASTBuilder::createGetterOrSetterProperty):
(JSC::ASTBuilder::createArguments):
* parser/NodeConstructors.h:
(JSC::FunctionParameters::FunctionParameters):
(JSC::BaseFuncExprNode::BaseFuncExprNode):
(JSC::FuncExprNode::FuncExprNode):
(JSC::FuncDeclNode::FuncDeclNode):
(JSC::ArrowFuncExprNode::ArrowFuncExprNode):
(JSC::MethodDefinitionNode::MethodDefinitionNode):
(JSC::YieldExprNode::YieldExprNode):
* parser/Nodes.h:
(JSC::BaseFuncExprNode::metadata):
* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseClass):
(JSC::Parser<LexerType>::parsePropertyMethod):
* parser/ParserModes.h:
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createFunctionExpr):
(JSC::SyntaxChecker::createFunctionMetadata):
(JSC::SyntaxChecker::createArrowFunctionExpr):
(JSC::SyntaxChecker::createMethodDefinition):
(JSC::SyntaxChecker::setFunctionNameStart):
(JSC::SyntaxChecker::createArguments):
* tests/es6.yaml:

LayoutTests:

* inspector/model/scope-chain-node-expected.txt:
- rebased expected result.

* js/script-tests/function-toString-vs-name.js:
- fixed a bug in the shouldBe() function.

* js/methods-names-should-not-be-in-lexical-scope-expected.txt: Added.
* js/methods-names-should-not-be-in-lexical-scope.html: Added.
* js/script-tests/methods-names-should-not-be-in-lexical-scope.js: Added.
- test all variations of methods.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (198331 => 198332)


--- trunk/LayoutTests/ChangeLog	2016-03-17 13:57:03 UTC (rev 198331)
+++ trunk/LayoutTests/ChangeLog	2016-03-17 14:58:57 UTC (rev 198332)
@@ -1,3 +1,21 @@
+2016-03-17  Mark Lam  <[email protected]>
+
+        Method names should not appear in the lexical scope of the method's body.
+        https://bugs.webkit.org/show_bug.cgi?id=155568
+
+        Reviewed by Saam Barati.
+
+        * inspector/model/scope-chain-node-expected.txt:
+        - rebased expected result.
+
+        * js/script-tests/function-toString-vs-name.js:
+        - fixed a bug in the shouldBe() function.
+
+        * js/methods-names-should-not-be-in-lexical-scope-expected.txt: Added.
+        * js/methods-names-should-not-be-in-lexical-scope.html: Added.
+        * js/script-tests/methods-names-should-not-be-in-lexical-scope.js: Added.
+        - test all variations of methods.
+
 2016-03-17  Csaba Osztrogonác  <[email protected]>
 
         Unreviewed, line ending fixes.

Modified: trunk/LayoutTests/inspector/model/scope-chain-node-expected.txt (198331 => 198332)


--- trunk/LayoutTests/inspector/model/scope-chain-node-expected.txt	2016-03-17 13:57:03 UTC (rev 198331)
+++ trunk/LayoutTests/inspector/model/scope-chain-node-expected.txt	2016-03-17 14:58:57 UTC (rev 198332)
@@ -65,8 +65,6 @@
 -- Running test case: WebInspector.ScopeChainNode.FunctionNameInClassMethod
 SCOPE CHAIN:
     Closure
-    FunctionName
-      - staticMethod: function staticMethod() {
     Block
       - MyClass: class MyClass
     Closure
@@ -109,8 +107,6 @@
 PASS: Pause #17 - Contains a Block scope.
 SCOPE CHAIN:
     Closure
-    FunctionName
-      - method: function method() {
     Block
       - MyClass: class MyClass
     Closure
@@ -122,8 +118,6 @@
 PASS: Pause #18 - Contains a Block scope.
 SCOPE CHAIN:
     Closure
-    FunctionName
-      - staticMethod: function staticMethod() {
     Block
       - MyClassWithStaticMethod: class MyClassWithStaticMethod
     Closure

Added: trunk/LayoutTests/js/methods-names-should-not-be-in-lexical-scope-expected.txt (0 => 198332)


--- trunk/LayoutTests/js/methods-names-should-not-be-in-lexical-scope-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/methods-names-should-not-be-in-lexical-scope-expected.txt	2016-03-17 14:58:57 UTC (rev 198332)
@@ -0,0 +1,3 @@
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/methods-names-should-not-be-in-lexical-scope.html (0 => 198332)


--- trunk/LayoutTests/js/methods-names-should-not-be-in-lexical-scope.html	                        (rev 0)
+++ trunk/LayoutTests/js/methods-names-should-not-be-in-lexical-scope.html	2016-03-17 14:58:57 UTC (rev 198332)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Modified: trunk/LayoutTests/js/script-tests/function-toString-vs-name.js (198331 => 198332)


--- trunk/LayoutTests/js/script-tests/function-toString-vs-name.js	2016-03-17 13:57:03 UTC (rev 198331)
+++ trunk/LayoutTests/js/script-tests/function-toString-vs-name.js	2016-03-17 14:58:57 UTC (rev 198332)
@@ -50,13 +50,10 @@
 }
 
 function shouldBe(desc, funcName, actual, expected) {
-    if (typeof(actual) !== typeof(expected)) {
+    if (typeof(actual) !== typeof(expected) || actual !== expected) {
         failures += ("   " + section + ": " + desc + "'" + funcName + "': typeof expected: " + typeof(expected) + ", typeof actual: " + typeof(actual) + "\n");
         failures += ("       expected: '" + expected + "', actual: '" + actual + "'\n");
         failureCount++;
-    } else if (typeof(actual) !== typeof(expected) || actual !== expected) {
-        failures += ("   " + section + ": " + desc + "'" + funcName + "': expected: '" + expected + "', actual: '" + actual + "'\n");
-        failureCount++;
     }
 }
 

Added: trunk/LayoutTests/js/script-tests/methods-names-should-not-be-in-lexical-scope.js (0 => 198332)


--- trunk/LayoutTests/js/script-tests/methods-names-should-not-be-in-lexical-scope.js	                        (rev 0)
+++ trunk/LayoutTests/js/script-tests/methods-names-should-not-be-in-lexical-scope.js	2016-03-17 14:58:57 UTC (rev 198332)
@@ -0,0 +1,292 @@
+let section;
+let failures = "";
+let failureCount = 0;
+
+function shouldBe(actual, expected) {
+    if (typeof(actual) !== typeof(expected) || actual !== expected) {
+        failures += ("   " + section + ": typeof expected: " + typeof(expected) + ", typeof actual: " + typeof(actual) + "\n");
+        failures += ("       expected: '" + expected + "', actual: '" + actual + "'\n");
+        failureCount++;
+    }
+}
+
+section = "object method";
+(function () {
+    let foo = "good";
+    let result = ({ foo () { return foo; } }).foo();
+    shouldBe(result, "good");
+})();
+section = "object method with computed name";
+(function () {
+    let foo = "good";
+    let x = "foo";
+    let result = ({ [x] () { return foo; } }).foo();
+    shouldBe(result, "good");
+})();
+
+section = "object getter method";
+(function () {
+    let foo = "good";
+    let result;
+    ({ get foo () { result = foo; } }).foo;
+    shouldBe(result, "good");
+})();
+(function () {
+    let get = "good";
+    let result;
+    ({ get foo () { result = get; } }).foo;
+    shouldBe(result, "good");
+})();
+section = "object getter method with computed name";
+(function () {
+    let foo = "good";
+    let x = "foo";
+    let result;
+    ({ get [x] () { result = foo; } })[x];
+    shouldBe(result, "good");
+})();
+(function () {
+    let get = "good";
+    let x = "get";
+    let result;
+    ({ get [x] () { result = get; } })[x];
+    shouldBe(result, "good");
+})();
+
+section = "object setter method";
+(function () {
+    let foo = "good";
+    let result;
+    ({ set foo (v) { result = foo; } }).foo = 5;
+    shouldBe(result, "good");
+})();
+(function () {
+    let set = "good";
+    let result;
+    ({ set foo (v) { result = set; } }).foo = 5;
+    shouldBe(result, "good");
+})();
+section = "object setter method with computed name";
+(function () {
+    let foo = "good";
+    let x = "foo";
+    let result;
+    ({ set [x] (v) { result = foo; } })[x] = 5;
+    shouldBe(result, "good");
+})();
+(function () {
+    let get = "good";
+    let x = "get";
+    let result;
+    ({ set [x] (v) { result = get; } })[x] = 5;
+    shouldBe(result, "good");
+})();
+
+section = "object generator method";
+(function () {
+    let foo = "good";
+    let result;
+    let value = ({ *foo () { result = foo; yield foo; } }).foo().next().value;
+    shouldBe(result, "good");
+    shouldBe(value, "good");
+})();
+section = "object generator method with computed name";
+(function () {
+    let foo = "good";
+    let x = "foo";
+    let result;
+    let value = ({ *[x] () { result = foo; yield foo; } })[x]().next().value;
+    shouldBe(result, "good");
+    shouldBe(value, "good");
+})();
+
+section = "class constructor";
+(function () {
+    let constructor = "good";
+    let result;
+    new class { constructor () { result = constructor; } };
+    shouldBe(result, "good");
+})();
+
+section = "class static method";
+(function () {
+    let foo = "good";
+    let result = (class { static foo () { return foo; } }).foo();
+    shouldBe(result, "good");
+})();
+section = "class static method with computed name";
+(function () {
+    let foo = "good";
+    let x = "foo";
+    var result = (class { static [x] () { return foo; } })[x]();
+    shouldBe(result, "good");
+})();
+
+section = "class instance method";
+(function () {
+    let foo = "good";
+    let result = (new class { foo () { return foo; } }).foo();
+    shouldBe(result, "good");
+})();
+section = "class instance method with computed name";
+(function () {
+    let foo = "good";
+    let x = "foo";
+    let result = (new class { [x] () { return foo; } })[x]();
+    shouldBe(result, "good");
+})();
+
+section = "class static getter method";
+(function () {
+    let foo = "good";
+    let result;
+    (class { static get foo() { result = foo; } }).foo;
+    shouldBe(result, "good");
+})();
+(function () {
+    let get = "good";
+    let result;
+    (class { static get foo() { result = get; } }).foo;
+    shouldBe(result, "good");
+})();
+section = "class static getter method with computed name";
+(function () {
+    let foo = "good";
+    let x = "foo";
+    let result;
+    (class { static get [x]() { result = foo; } })[x];
+    shouldBe(result, "good");
+})();
+(function () {
+    let get = "good";
+    let x = "foo";
+    let result;
+    (class { static get [x]() { result = get; } })[x];
+    shouldBe(result, "good");
+})();
+
+section = "class instance getter method";
+(function () {
+    let foo = "good";
+    let result;
+    (new class { get foo() { result = foo; } }).foo;
+    shouldBe(result, "good");
+})();
+(function () {
+    let get = "good";
+    let result;
+    (new class { get foo() { result = get; } }).foo;
+    shouldBe(result, "good");
+})();
+section = "class instance getter method with computed name";
+(function () {
+    let foo = "good";
+    let x = "foo";
+    let result;
+    (new class { get [x]() { result = foo; } })[x];
+    shouldBe(result, "good");
+})();
+(function () {
+    let get = "good";
+    let x = "foo";
+    let result;
+    (new class { get [x]() { result = get; } })[x];
+    shouldBe(result, "good");
+})();
+
+section = "class static setter method";
+(function () {
+    let foo = "good";
+    let result;
+    (class { static set foo(v) { result = foo; } }).foo = 5;
+    shouldBe(result, "good");
+})();
+(function () {
+    let set = "good";
+    let result;
+    (class { static set foo(v) { result = set; } }).foo = 5;
+    shouldBe(result, "good");
+})();
+section = "class static setter method with computed name";
+(function () {
+    let foo = "good";
+    let x = "foo";
+    let result;
+    (class { static set [x](v) { result = foo; } })[x] = 5;
+    shouldBe(result, "good");
+})();
+(function () {
+    let set = "good";
+    let x = "foo";
+    let result;
+    (class { static set [x](v) { result = set; } })[x] = 5;
+    shouldBe(result, "good");
+})();
+
+section = "class instance setter method";
+(function () {
+    let foo = "good";
+    let result;
+    (new class { set foo(v) { result = foo; } }).foo = 5;
+    shouldBe(result, "good");
+})();
+(function () {
+    let set = "good";
+    let result;
+    (new class { set foo(v) { result = set; } }).foo = 5;
+    shouldBe(result, "good");
+})();
+section = "class instance setter  methodwith computed name";
+(function () {
+    let foo = "good";
+    let x = "foo";
+    let result;
+    (new class { set [x](v) { result = foo; } })[x] = 5;
+    shouldBe(result, "good");
+})();
+(function () {
+    let set = "good";
+    let x = "foo";
+    let result;
+    (new class { set [x](v) { result = set; } })[x] = 5;
+    shouldBe(result, "good");
+})();
+
+section = "class static generator method";
+(function () {
+    let foo = "good";
+    let result;
+    let value = (class { static *foo () { result = foo; yield foo; } }).foo().next().value;
+    shouldBe(result, "good");
+    shouldBe(value, "good");
+})();
+section = "class static generator method with computed name";
+(function () {
+    let foo = "good";
+    let x = "foo";
+    let result;
+    let value = (class { static *[x] () { result = foo; yield foo; } })[x]().next().value;
+    shouldBe(result, "good");
+    shouldBe(value, "good");
+})();
+
+section = "class instance generator method";
+(function () {
+    let foo = "good";
+    let result;
+    let value = (new class { *foo () { result = foo; yield foo; } }).foo().next().value;
+    shouldBe(result, "good");
+    shouldBe(value, "good");
+})();
+section = "class instance generator method with computed name";
+(function () {
+    let foo = "good";
+    let x = "foo";
+    let result;
+    let value = (new class { *[x] () { result = foo; yield foo; } })[x]().next().value;
+    shouldBe(result, "good");
+    shouldBe(value, "good");
+})();
+
+if (failureCount)
+    throw Error("Found " + failureCount + " failures:\n" + failures);

Modified: trunk/Source/_javascript_Core/ChangeLog (198331 => 198332)


--- trunk/Source/_javascript_Core/ChangeLog	2016-03-17 13:57:03 UTC (rev 198331)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-03-17 14:58:57 UTC (rev 198332)
@@ -1,3 +1,71 @@
+2016-03-16  Mark Lam  <[email protected]>
+
+        Method names should not appear in the lexical scope of the method's body.
+        https://bugs.webkit.org/show_bug.cgi?id=155568
+
+        Reviewed by Saam Barati.
+
+        Consider this scenario:
+
+            var f = "foo";
+            var result = ({
+                f() {
+                    return f; // f should be the string "foo", not this method f.
+                }
+            }).f();
+            result === "foo"; // Should be true.
+
+        The reason this is not current working is because the parser does not yet
+        distinguish between FunctionExpressions and MethodDefinitions.  The ES6 spec
+        explicitly distinguishes between the 2, and we should do the same.
+        
+        This patch changes all methods (and getters and setters which are also methods)
+        to have a FunctionMode of MethodDefinition (instead of FunctionExpression).
+        functionNameIsInScope() is responsible for determining whether a function's name
+        should be in its scope or not.  It already returns false for any function
+        whose FunctionMode is not FunctionExpression.  Giving methods the MethodDefinition
+        FunctionMode gets us the correct behavior ES6 expects.
+
+        * bytecode/UnlinkedFunctionExecutable.cpp:
+        (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
+        * bytecode/UnlinkedFunctionExecutable.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitNewArrowFunctionExpression):
+        (JSC::BytecodeGenerator::emitNewMethodDefinition):
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::ArrowFuncExprNode::emitBytecode):
+        (JSC::MethodDefinitionNode::emitBytecode):
+        (JSC::YieldExprNode::emitBytecode):
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createFunctionExpr):
+        (JSC::ASTBuilder::createMethodDefinition):
+        (JSC::ASTBuilder::createFunctionMetadata):
+        (JSC::ASTBuilder::createGetterOrSetterProperty):
+        (JSC::ASTBuilder::createArguments):
+        * parser/NodeConstructors.h:
+        (JSC::FunctionParameters::FunctionParameters):
+        (JSC::BaseFuncExprNode::BaseFuncExprNode):
+        (JSC::FuncExprNode::FuncExprNode):
+        (JSC::FuncDeclNode::FuncDeclNode):
+        (JSC::ArrowFuncExprNode::ArrowFuncExprNode):
+        (JSC::MethodDefinitionNode::MethodDefinitionNode):
+        (JSC::YieldExprNode::YieldExprNode):
+        * parser/Nodes.h:
+        (JSC::BaseFuncExprNode::metadata):
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseClass):
+        (JSC::Parser<LexerType>::parsePropertyMethod):
+        * parser/ParserModes.h:
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createFunctionExpr):
+        (JSC::SyntaxChecker::createFunctionMetadata):
+        (JSC::SyntaxChecker::createArrowFunctionExpr):
+        (JSC::SyntaxChecker::createMethodDefinition):
+        (JSC::SyntaxChecker::setFunctionNameStart):
+        (JSC::SyntaxChecker::createArguments):
+        * tests/es6.yaml:
+
 2016-03-17  Yusuke Suzuki  <[email protected]>
 
         REGRESSION(r197380): Build fails with new GCC and Clang

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp (198331 => 198332)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp	2016-03-17 13:57:03 UTC (rev 198331)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp	2016-03-17 14:58:57 UTC (rev 198332)
@@ -107,7 +107,14 @@
     , m_sourceOverride(WTFMove(sourceOverride))
     , m_classSource(node->classSource())
 {
+    // Make sure these bitfields are adequately wide.
+    ASSERT(m_constructAbility == static_cast<unsigned>(constructAbility));
     ASSERT(m_constructorKind == static_cast<unsigned>(node->constructorKind()));
+    ASSERT(m_functionMode == node->functionMode());
+    ASSERT(m_superBinding == static_cast<unsigned>(node->superBinding()));
+    ASSERT(m_derivedContextType == static_cast<unsigned>(derivedContextType));
+    ASSERT(m_sourceParseMode == static_cast<unsigned>(node->parseMode()));
+
     m_parentScopeTDZVariables.swap(parentScopeTDZVariables);
 }
 

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h (198331 => 198332)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h	2016-03-17 13:57:03 UTC (rev 198331)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h	2016-03-17 14:58:57 UTC (rev 198332)
@@ -156,7 +156,7 @@
     unsigned m_isBuiltinFunction : 1;
     unsigned m_constructAbility: 1;
     unsigned m_constructorKind : 2;
-    unsigned m_functionMode : 1; // FunctionMode
+    unsigned m_functionMode : 2; // FunctionMode
     unsigned m_superBinding : 1;
     unsigned m_derivedContextType: 2;
     unsigned m_sourceParseMode : 4; // SourceParseMode

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (198331 => 198332)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2016-03-17 13:57:03 UTC (rev 198331)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2016-03-17 14:58:57 UTC (rev 198332)
@@ -2791,11 +2791,21 @@
 
 RegisterID* BytecodeGenerator::emitNewArrowFunctionExpression(RegisterID* dst, ArrowFuncExprNode* func)
 {
-    ASSERT(func->metadata()->parseMode() == SourceParseMode::ArrowFunctionMode);    
+    ASSERT(func->metadata()->parseMode() == SourceParseMode::ArrowFunctionMode);
     emitNewFunctionExpressionCommon(dst, func->metadata());
     return dst;
 }
 
+RegisterID* BytecodeGenerator::emitNewMethodDefinition(RegisterID* dst, MethodDefinitionNode* func)
+{
+    ASSERT(func->metadata()->parseMode() == SourceParseMode::GeneratorWrapperFunctionMode
+        || func->metadata()->parseMode() == SourceParseMode::GetterMode
+        || func->metadata()->parseMode() == SourceParseMode::SetterMode
+        || func->metadata()->parseMode() == SourceParseMode::MethodMode);
+    emitNewFunctionExpressionCommon(dst, func->metadata());
+    return dst;
+}
+
 RegisterID* BytecodeGenerator::emitNewDefaultConstructor(RegisterID* dst, ConstructorKind constructorKind, const Identifier& name,
     const Identifier& ecmaName, const SourceCode& classSource)
 {

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (198331 => 198332)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2016-03-17 13:57:03 UTC (rev 198331)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2016-03-17 14:58:57 UTC (rev 198332)
@@ -517,9 +517,10 @@
         RegisterID* emitNewArrayWithSize(RegisterID* dst, RegisterID* length);
 
         RegisterID* emitNewFunction(RegisterID* dst, FunctionMetadataNode*);
-        RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func);
+        RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode*);
         RegisterID* emitNewDefaultConstructor(RegisterID* dst, ConstructorKind, const Identifier& name, const Identifier& ecmaName, const SourceCode& classSource);
         RegisterID* emitNewArrowFunctionExpression(RegisterID*, ArrowFuncExprNode*);
+        RegisterID* emitNewMethodDefinition(RegisterID* dst, MethodDefinitionNode*);
         RegisterID* emitNewRegExp(RegisterID* dst, RegExp*);
 
         void emitSetFunctionNameIfNeeded(ExpressionNode* valueNode, RegisterID* value, RegisterID* name);

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (198331 => 198332)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2016-03-17 13:57:03 UTC (rev 198331)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2016-03-17 14:58:57 UTC (rev 198332)
@@ -3175,6 +3175,13 @@
     return generator.emitNewArrowFunctionExpression(generator.finalDestination(dst), this);
 }
 
+// ------------------------------ MethodDefinitionNode ---------------------------------
+
+RegisterID* MethodDefinitionNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    return generator.emitNewMethodDefinition(generator.finalDestination(dst), this);
+}
+
 // ------------------------------ YieldExprNode --------------------------------
 
 RegisterID* YieldExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)

Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (198331 => 198332)


--- trunk/Source/_javascript_Core/parser/ASTBuilder.h	2016-03-17 13:57:03 UTC (rev 198331)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h	2016-03-17 14:58:57 UTC (rev 198332)
@@ -380,6 +380,14 @@
         return result;
     }
 
+    ExpressionNode* createMethodDefinition(const JSTokenLocation& location, const ParserFunctionInfo<ASTBuilder>& functionInfo)
+    {
+        MethodDefinitionNode* result = new (m_parserArena) MethodDefinitionNode(location, *functionInfo.name, functionInfo.body,
+            m_sourceCode->subExpression(functionInfo.startOffset, functionInfo.endOffset, functionInfo.startLine, functionInfo.bodyStartColumn));
+        functionInfo.body->setLoc(functionInfo.startLine, functionInfo.endLine, location.startOffset, location.lineStartOffset);
+        return result;
+    }
+    
     FunctionMetadataNode* createFunctionMetadata(
         const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, 
         unsigned startColumn, unsigned endColumn, int functionKeywordStart, 
@@ -409,8 +417,8 @@
         functionInfo.body->setEcmaName(*name);
         functionInfo.body->setInferredName(*name);
         SourceCode source = m_sourceCode->subExpression(functionInfo.startOffset, functionInfo.endOffset, functionInfo.startLine, functionInfo.bodyStartColumn);
-        FuncExprNode* funcExpr = new (m_parserArena) FuncExprNode(location, m_vm->propertyNames->nullIdentifier, functionInfo.body, source);
-        return new (m_parserArena) PropertyNode(*name, funcExpr, type, PropertyNode::Unknown, superBinding);
+        MethodDefinitionNode* methodDef = new (m_parserArena) MethodDefinitionNode(location, m_vm->propertyNames->nullIdentifier, functionInfo.body, source);
+        return new (m_parserArena) PropertyNode(*name, methodDef, type, PropertyNode::Unknown, superBinding);
     }
 
     NEVER_INLINE PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type, bool,
@@ -419,8 +427,8 @@
         ASSERT(name);
         functionInfo.body->setLoc(functionInfo.startLine, functionInfo.endLine, location.startOffset, location.lineStartOffset);
         SourceCode source = m_sourceCode->subExpression(functionInfo.startOffset, functionInfo.endOffset, functionInfo.startLine, functionInfo.bodyStartColumn);
-        FuncExprNode* funcExpr = new (m_parserArena) FuncExprNode(location, m_vm->propertyNames->nullIdentifier, functionInfo.body, source);
-        return new (m_parserArena) PropertyNode(name, funcExpr, type, PropertyNode::Unknown, superBinding);
+        MethodDefinitionNode* methodDef = new (m_parserArena) MethodDefinitionNode(location, m_vm->propertyNames->nullIdentifier, functionInfo.body, source);
+        return new (m_parserArena) PropertyNode(name, methodDef, type, PropertyNode::Unknown, superBinding);
     }
 
     NEVER_INLINE PropertyNode* createGetterOrSetterProperty(VM* vm, ParserArena& parserArena, const JSTokenLocation& location, PropertyNode::Type type, bool,
@@ -429,8 +437,8 @@
         functionInfo.body->setLoc(functionInfo.startLine, functionInfo.endLine, location.startOffset, location.lineStartOffset);
         const Identifier& ident = parserArena.identifierArena().makeNumericIdentifier(vm, name);
         SourceCode source = m_sourceCode->subExpression(functionInfo.startOffset, functionInfo.endOffset, functionInfo.startLine, functionInfo.bodyStartColumn);
-        FuncExprNode* funcExpr = new (m_parserArena) FuncExprNode(location, vm->propertyNames->nullIdentifier, functionInfo.body, source);
-        return new (m_parserArena) PropertyNode(ident, funcExpr, type, PropertyNode::Unknown, superBinding);
+        MethodDefinitionNode* methodDef = new (m_parserArena) MethodDefinitionNode(location, vm->propertyNames->nullIdentifier, functionInfo.body, source);
+        return new (m_parserArena) PropertyNode(ident, methodDef, type, PropertyNode::Unknown, superBinding);
     }
 
     ArgumentsNode* createArguments() { return new (m_parserArena) ArgumentsNode(); }

Modified: trunk/Source/_javascript_Core/parser/NodeConstructors.h (198331 => 198332)


--- trunk/Source/_javascript_Core/parser/NodeConstructors.h	2016-03-17 13:57:03 UTC (rev 198331)
+++ trunk/Source/_javascript_Core/parser/NodeConstructors.h	2016-03-17 14:58:57 UTC (rev 198332)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2009, 2013, 2015 Apple Inc. All rights reserved.
+ *  Copyright (C) 2009, 2013, 2015-2016 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -890,18 +890,23 @@
     }
 
     
-    inline BaseFuncExprNode::BaseFuncExprNode(const JSTokenLocation& location, const Identifier& ident, FunctionMetadataNode* metadata, const SourceCode& source)
+    inline BaseFuncExprNode::BaseFuncExprNode(const JSTokenLocation& location, const Identifier& ident, FunctionMetadataNode* metadata, const SourceCode& source, FunctionMode functionMode)
         : ExpressionNode(location)
         , m_metadata(metadata)
     {
-        m_metadata->finishParsing(source, ident, FunctionExpression);
+        m_metadata->finishParsing(source, ident, functionMode);
     }
 
     inline FuncExprNode::FuncExprNode(const JSTokenLocation& location, const Identifier& ident, FunctionMetadataNode* metadata, const SourceCode& source)
-        : BaseFuncExprNode(location, ident, metadata, source)
+        : BaseFuncExprNode(location, ident, metadata, source, FunctionExpression)
     {
     }
 
+    inline FuncExprNode::FuncExprNode(const JSTokenLocation& location, const Identifier& ident, FunctionMetadataNode* metadata, const SourceCode& source, FunctionMode functionMode)
+        : BaseFuncExprNode(location, ident, metadata, source, functionMode)
+    {
+    }
+    
     inline FuncDeclNode::FuncDeclNode(const JSTokenLocation& location, const Identifier& ident, FunctionMetadataNode* metadata, const SourceCode& source)
         : StatementNode(location)
         , m_metadata(metadata)
@@ -910,10 +915,15 @@
     }
 
     inline ArrowFuncExprNode::ArrowFuncExprNode(const JSTokenLocation& location, const Identifier& ident, FunctionMetadataNode* metadata, const SourceCode& source)
-        : BaseFuncExprNode(location, ident, metadata, source)
+        : BaseFuncExprNode(location, ident, metadata, source, FunctionExpression)
     {
     }
 
+    inline MethodDefinitionNode::MethodDefinitionNode(const JSTokenLocation& location, const Identifier& ident, FunctionMetadataNode* metadata, const SourceCode& source)
+        : FuncExprNode(location, ident, metadata, source, MethodDefinition)
+    {
+    }
+    
     inline YieldExprNode::YieldExprNode(const JSTokenLocation& location, ExpressionNode* argument, bool delegate)
         : ExpressionNode(location)
         , m_argument(argument)

Modified: trunk/Source/_javascript_Core/parser/Nodes.h (198331 => 198332)


--- trunk/Source/_javascript_Core/parser/Nodes.h	2016-03-17 13:57:03 UTC (rev 198331)
+++ trunk/Source/_javascript_Core/parser/Nodes.h	2016-03-17 14:58:57 UTC (rev 198332)
@@ -1914,7 +1914,7 @@
         
         const Identifier& ident() { return m_ident; }
 
-        FunctionMode functionMode() { return m_functionMode; }
+        FunctionMode functionMode() const { return m_functionMode; }
 
         unsigned startColumn() const { return m_startColumn; }
         unsigned endColumn() const { return m_endColumn; }
@@ -1931,11 +1931,11 @@
 
     class BaseFuncExprNode : public ExpressionNode {
     public:
-        BaseFuncExprNode(const JSTokenLocation&, const Identifier&, FunctionMetadataNode*, const SourceCode&);
-
         FunctionMetadataNode* metadata() { return m_metadata; }
 
     protected:
+        BaseFuncExprNode(const JSTokenLocation&, const Identifier&, FunctionMetadataNode*, const SourceCode&, FunctionMode);
+
         FunctionMetadataNode* m_metadata;
     };
 
@@ -1944,6 +1944,9 @@
     public:
         FuncExprNode(const JSTokenLocation&, const Identifier&, FunctionMetadataNode*, const SourceCode&);
 
+    protected:
+        FuncExprNode(const JSTokenLocation&, const Identifier&, FunctionMetadataNode*, const SourceCode&, FunctionMode);
+
     private:
         RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
 
@@ -1960,6 +1963,14 @@
         bool isArrowFuncExprNode() const override { return true; }
     };
 
+    class MethodDefinitionNode : public FuncExprNode {
+    public:
+        MethodDefinitionNode(const JSTokenLocation&, const Identifier&, FunctionMetadataNode*, const SourceCode&);
+        
+    private:
+        RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
+    };
+
     class YieldExprNode final : public ExpressionNode, public ThrowableExpressionData {
     public:
         YieldExprNode(const JSTokenLocation&, ExpressionNode* argument, bool delegate);

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (198331 => 198332)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2016-03-17 13:57:03 UTC (rev 198331)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2016-03-17 14:58:57 UTC (rev 198332)
@@ -2327,7 +2327,7 @@
             failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, parseMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
             methodInfo.name = isConstructor ? className : ident;
 
-            TreeExpression method = context.createFunctionExpr(methodLocation, methodInfo);
+            TreeExpression method = context.createMethodDefinition(methodLocation, methodInfo);
             if (isConstructor) {
                 semanticFailIfTrue(constructor, "Cannot declare multiple constructors in a single class");
                 constructor = method;
@@ -3314,7 +3314,7 @@
     SourceParseMode parseMode = isGenerator ? SourceParseMode::GeneratorWrapperFunctionMode : SourceParseMode::MethodMode;
     failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, parseMode, false, ConstructorKind::None, SuperBinding::NotNeeded, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
     methodInfo.name = methodName;
-    return context.createFunctionExpr(methodLocation, methodInfo);
+    return context.createMethodDefinition(methodLocation, methodInfo);
 }
 
 template <typename LexerType>

Modified: trunk/Source/_javascript_Core/parser/ParserModes.h (198331 => 198332)


--- trunk/Source/_javascript_Core/parser/ParserModes.h	2016-03-17 13:57:03 UTC (rev 198331)
+++ trunk/Source/_javascript_Core/parser/ParserModes.h	2016-03-17 14:58:57 UTC (rev 198332)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2013, 2015-2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -42,7 +42,7 @@
 enum ProfilerMode { ProfilerOff, ProfilerOn };
 enum DebuggerMode { DebuggerOff, DebuggerOn };
 
-enum FunctionMode { FunctionExpression, FunctionDeclaration };
+enum FunctionMode { FunctionExpression, FunctionDeclaration, MethodDefinition };
 
 enum class SourceParseMode : uint8_t {
     NormalFunctionMode,

Modified: trunk/Source/_javascript_Core/parser/SyntaxChecker.h (198331 => 198332)


--- trunk/Source/_javascript_Core/parser/SyntaxChecker.h	2016-03-17 13:57:03 UTC (rev 198331)
+++ trunk/Source/_javascript_Core/parser/SyntaxChecker.h	2016-03-17 14:58:57 UTC (rev 198332)
@@ -186,6 +186,7 @@
     ExpressionType createFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
     int createFunctionMetadata(const JSTokenLocation&, const JSTokenLocation&, int, int, bool, int, int, int, ConstructorKind, SuperBinding, unsigned, SourceParseMode, bool, InnerArrowFunctionCodeFeatures = NoInnerArrowFunctionFeatures) { return FunctionBodyResult; }
     ExpressionType createArrowFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
+    ExpressionType createMethodDefinition(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
     void setFunctionNameStart(int, int) { }
     int createArguments() { return ArgumentsResult; }
     int createArguments(int) { return ArgumentsResult; }

Modified: trunk/Source/_javascript_Core/tests/es6.yaml (198331 => 198332)


--- trunk/Source/_javascript_Core/tests/es6.yaml	2016-03-17 13:57:03 UTC (rev 198331)
+++ trunk/Source/_javascript_Core/tests/es6.yaml	2016-03-17 14:58:57 UTC (rev 198332)
@@ -805,7 +805,7 @@
 - path: es6/function_name_property_object_methods_function.js
   cmd: runES6 :normal
 - path: es6/function_name_property_shorthand_methods_no_lexical_binding.js
-  cmd: runES6 :fail
+  cmd: runES6 :normal
 - path: es6/function_name_property_symbol-keyed_methods.js
   cmd: runES6 :normal
 - path: es6/function_name_property_variables_class.js
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to