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