Title: [204842] trunk
Revision
204842
Author
[email protected]
Date
2016-08-23 11:14:30 -0700 (Tue, 23 Aug 2016)

Log Message

[ES6] Modules' `export default function/class` should be declaration
https://bugs.webkit.org/show_bug.cgi?id=160499

Reviewed by Saam Barati.

JSTests:

Add several module tests. And flip the failed tests flags in test262.

* modules/export-default-function-name-in-assignment-_expression_.js: Added.
(export.default):
* modules/export-default-function-name-in-class-declaration.js: Added.
* modules/export-default-function-name-in-function-declaration.js: Added.
(export.default):
* modules/export-default-function-name-in-generator-declaration.js: Added.
(export.default):
* stress/method-name.js: Added.
(testSyntax):
(testSyntaxError):
(testSyntaxError.Hello.prototype.hello.hello):
(testSyntaxError.Hello):
(SyntaxError.Unexpected.identifier.string_appeared_here.Expected.an.opening.string_appeared_here.before.a.method.testSyntaxError.let.obj.hello.hello):
(testSyntaxError.Hello.prototype.get hello):
(testSyntaxError.Hello.prototype.set hello):
* test262.yaml:

Source/_javascript_Core:

Previously, we parsed the following cases as FunctionExpression and ClassExpression.

    ```
    export default function () { }
    export default class { }
    ```

But, as per ES6 spec, the above `function ...` and `class ...` parts should be parsed
as function declaration and class declaration. This has big difference; the instantiation
of the function declarations are done in the function prologue.

In this patch, we correctly parse the above cases as declaration. To handle no-named
declarations, we add a new flag, DeclarationDefaultContext. This indicates [Default]
flag in the ES6 spec's BNF.

Furthermore, this patch also fixes the following name related bugs.

1. The bug related to "export default"'s function name. If the name is not provided (like the above case), the name of the function becomes
"default", not "*default*". This is special handling in ES6 spec. We handle this in JSFunction's reifyName.

2. `class Hello { hello hello() { } }` is accepted. We introduced FunctionRequirements::Unnamed and fix this bug.

* parser/ModuleScopeData.h:
(JSC::ModuleScopeData::exportBinding):
Exported names are already guranteed uniqueness by m_exportedNames. Not necessary to use set here. Use vector instead.

* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseFunctionInfo):
If we pass FunctionRequirements::NoRequirements, we need to initialize functionInfo.name / classInfo.className
with the default fallback name. For example, in the above `export default` case, we initialize it with `*default*`.

(JSC::Parser<LexerType>::parseFunctionDeclaration):
(JSC::Parser<LexerType>::parseClassDeclaration):
(JSC::Parser<LexerType>::parseClass):
(JSC::Parser<LexerType>::parseExportDeclaration):
(JSC::Parser<LexerType>::parsePropertyMethod):
(JSC::Parser<LexerType>::parseGetterSetter):
(JSC::Parser<LexerType>::parseClassExpression):
(JSC::Parser<LexerType>::parseFunctionExpression):
(JSC::Parser<LexerType>::parsePrimaryExpression):
(JSC::Parser<LexerType>::parseArrowFunctionExpression):
* parser/Parser.h:
* runtime/JSFunction.cpp:
(JSC::JSFunction::reifyName):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (204841 => 204842)


--- trunk/JSTests/ChangeLog	2016-08-23 18:09:21 UTC (rev 204841)
+++ trunk/JSTests/ChangeLog	2016-08-23 18:14:30 UTC (rev 204842)
@@ -1,5 +1,31 @@
 2016-08-22  Yusuke Suzuki  <[email protected]>
 
+        [ES6] Modules' `export default function/class` should be declaration
+        https://bugs.webkit.org/show_bug.cgi?id=160499
+
+        Reviewed by Saam Barati.
+
+        Add several module tests. And flip the failed tests flags in test262.
+
+        * modules/export-default-function-name-in-assignment-_expression_.js: Added.
+        (export.default):
+        * modules/export-default-function-name-in-class-declaration.js: Added.
+        * modules/export-default-function-name-in-function-declaration.js: Added.
+        (export.default):
+        * modules/export-default-function-name-in-generator-declaration.js: Added.
+        (export.default):
+        * stress/method-name.js: Added.
+        (testSyntax):
+        (testSyntaxError):
+        (testSyntaxError.Hello.prototype.hello.hello):
+        (testSyntaxError.Hello):
+        (SyntaxError.Unexpected.identifier.string_appeared_here.Expected.an.opening.string_appeared_here.before.a.method.testSyntaxError.let.obj.hello.hello):
+        (testSyntaxError.Hello.prototype.get hello):
+        (testSyntaxError.Hello.prototype.set hello):
+        * test262.yaml:
+
+2016-08-22  Yusuke Suzuki  <[email protected]>
+
         [ES6] Module should not allow HTML comments
         https://bugs.webkit.org/show_bug.cgi?id=161041
 

Added: trunk/JSTests/modules/export-default-function-name-in-assignment-_expression_.js (0 => 204842)


--- trunk/JSTests/modules/export-default-function-name-in-assignment-_expression_.js	                        (rev 0)
+++ trunk/JSTests/modules/export-default-function-name-in-assignment-_expression_.js	2016-08-23 18:14:30 UTC (rev 204842)
@@ -0,0 +1,8 @@
+import func from "./export-default-function-name-in-assignment-_expression_.js"
+import { shouldBe } from "./resources/assert.js";
+
+export default (function () { });
+
+// https://tc39.github.io/ecma262/#sec-exports-runtime-semantics-evaluation
+shouldBe(func.name, 'default');
+shouldBe(func.toString(), `function () { }`);

Added: trunk/JSTests/modules/export-default-function-name-in-class-declaration.js (0 => 204842)


--- trunk/JSTests/modules/export-default-function-name-in-class-declaration.js	                        (rev 0)
+++ trunk/JSTests/modules/export-default-function-name-in-class-declaration.js	2016-08-23 18:14:30 UTC (rev 204842)
@@ -0,0 +1,8 @@
+import cls from "./export-default-function-name-in-class-declaration.js"
+import { shouldBe } from "./resources/assert.js";
+
+export default class { }
+
+// https://tc39.github.io/ecma262/#sec-exports-runtime-semantics-evaluation
+shouldBe(cls.name, 'default');
+shouldBe(cls.toString(), `class { }`);

Added: trunk/JSTests/modules/export-default-function-name-in-function-declaration.js (0 => 204842)


--- trunk/JSTests/modules/export-default-function-name-in-function-declaration.js	                        (rev 0)
+++ trunk/JSTests/modules/export-default-function-name-in-function-declaration.js	2016-08-23 18:14:30 UTC (rev 204842)
@@ -0,0 +1,8 @@
+import func from "./export-default-function-name-in-function-declaration.js"
+import { shouldBe } from "./resources/assert.js";
+
+export default function () { }
+
+// https://tc39.github.io/ecma262/#sec-exports-runtime-semantics-evaluation
+shouldBe(func.name, 'default');
+shouldBe(func.toString(), `function () { }`);

Added: trunk/JSTests/modules/export-default-function-name-in-generator-declaration.js (0 => 204842)


--- trunk/JSTests/modules/export-default-function-name-in-generator-declaration.js	                        (rev 0)
+++ trunk/JSTests/modules/export-default-function-name-in-generator-declaration.js	2016-08-23 18:14:30 UTC (rev 204842)
@@ -0,0 +1,8 @@
+import func from "./export-default-function-name-in-generator-declaration.js"
+import { shouldBe } from "./resources/assert.js";
+
+export default function * () { }
+
+// https://tc39.github.io/ecma262/#sec-exports-runtime-semantics-evaluation
+shouldBe(func.name, 'default');
+// shouldBe(func.toString(), `function * () { }`);

Added: trunk/JSTests/stress/method-name.js (0 => 204842)


--- trunk/JSTests/stress/method-name.js	                        (rev 0)
+++ trunk/JSTests/stress/method-name.js	2016-08-23 18:14:30 UTC (rev 204842)
@@ -0,0 +1,46 @@
+function testSyntax(script) {
+    try {
+        eval(script);
+    } catch (error) {
+        if (error instanceof SyntaxError)
+            throw new Error("Bad error: " + String(error));
+    }
+}
+
+function testSyntaxError(script, message) {
+    var error = null;
+    try {
+        eval(script);
+    } catch (e) {
+        error = e;
+    }
+    if (!error)
+        throw new Error("Expected syntax error not thrown");
+
+    if (String(error) !== message)
+        throw new Error("Bad error: " + String(error));
+}
+
+testSyntaxError(`
+class Hello {
+    hello hello() { }
+}
+`, `SyntaxError: Unexpected identifier 'hello'. Expected an opening '(' before a method's parameter list.`);
+
+testSyntaxError(`
+let obj = {
+    hello hello() { }
+}
+`, `SyntaxError: Unexpected identifier 'hello'. Expected a ':' following the property name 'hello'.`);
+
+testSyntaxError(`
+class Hello {
+    get hello hello() { }
+}
+`, `SyntaxError: Unexpected identifier 'hello'. Expected a parameter list for getter definition.`);
+
+testSyntaxError(`
+class Hello {
+    set hello hello(v) { }
+}
+`, `SyntaxError: Unexpected identifier 'hello'. Expected a parameter list for setter definition.`);

Modified: trunk/JSTests/test262.yaml (204841 => 204842)


--- trunk/JSTests/test262.yaml	2016-08-23 18:09:21 UTC (rev 204841)
+++ trunk/JSTests/test262.yaml	2016-08-23 18:14:30 UTC (rev 204842)
@@ -70868,7 +70868,7 @@
 - path: test262/test/language/module-code/eval-export-dflt-cls-anon-semi.js
   cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
 - path: test262/test/language/module-code/eval-export-dflt-cls-anon.js
-  cmd: runTest262 :fail, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
+  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
 - path: test262/test/language/module-code/eval-export-dflt-cls-name-meth.js
   cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
 - path: test262/test/language/module-code/eval-export-dflt-cls-named-semi.js
@@ -70876,7 +70876,7 @@
 - path: test262/test/language/module-code/eval-export-dflt-cls-named.js
   cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
 - path: test262/test/language/module-code/eval-export-dflt-expr-cls-anon.js
-  cmd: runTest262 :fail, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
+  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
 - path: test262/test/language/module-code/eval-export-dflt-expr-cls-name-meth.js
   cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
 - path: test262/test/language/module-code/eval-export-dflt-expr-cls-named.js
@@ -70886,11 +70886,11 @@
 - path: test262/test/language/module-code/eval-export-dflt-expr-err-get-value.js
   cmd: runTest262 :normal, "ReferenceError", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
 - path: test262/test/language/module-code/eval-export-dflt-expr-fn-anon.js
-  cmd: runTest262 :fail, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
+  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
 - path: test262/test/language/module-code/eval-export-dflt-expr-fn-named.js
   cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
 - path: test262/test/language/module-code/eval-export-dflt-expr-gen-anon.js
-  cmd: runTest262 :fail, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
+  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
 - path: test262/test/language/module-code/eval-export-dflt-expr-gen-named.js
   cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
 - path: test262/test/language/module-code/eval-export-dflt-expr-in.js
@@ -71072,11 +71072,11 @@
 - path: test262/test/language/module-code/instn-named-bndng-dflt-expr.js
   cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
 - path: test262/test/language/module-code/instn-named-bndng-dflt-fun-anon.js
-  cmd: runTest262 :fail, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
+  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
 - path: test262/test/language/module-code/instn-named-bndng-dflt-fun-named.js
   cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
 - path: test262/test/language/module-code/instn-named-bndng-dflt-gen-anon.js
-  cmd: runTest262 :fail, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
+  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
 - path: test262/test/language/module-code/instn-named-bndng-dflt-gen-named.js
   cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
 - path: test262/test/language/module-code/instn-named-bndng-dflt-named.js
@@ -71504,9 +71504,9 @@
 - path: test262/test/language/module-code/parse-err-hoist-lex-gen.js
   cmd: runTest262 :fail, "SyntaxError", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
 - path: test262/test/language/module-code/parse-err-invoke-anon-fun-decl.js
-  cmd: runTest262 :fail, "SyntaxError", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
+  cmd: runTest262 :normal, "SyntaxError", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
 - path: test262/test/language/module-code/parse-err-invoke-anon-gen-decl.js
-  cmd: runTest262 :fail, "SyntaxError", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
+  cmd: runTest262 :normal, "SyntaxError", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
 - path: test262/test/language/module-code/parse-err-reference.js
   cmd: runTest262 :normal, "ReferenceError", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
 - path: test262/test/language/module-code/parse-err-semi-dflt-expr.js

Modified: trunk/Source/_javascript_Core/ChangeLog (204841 => 204842)


--- trunk/Source/_javascript_Core/ChangeLog	2016-08-23 18:09:21 UTC (rev 204841)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-08-23 18:14:30 UTC (rev 204842)
@@ -1,3 +1,55 @@
+2016-08-22  Yusuke Suzuki  <[email protected]>
+
+        [ES6] Modules' `export default function/class` should be declaration
+        https://bugs.webkit.org/show_bug.cgi?id=160499
+
+        Reviewed by Saam Barati.
+
+        Previously, we parsed the following cases as FunctionExpression and ClassExpression.
+
+            ```
+            export default function () { }
+            export default class { }
+            ```
+
+        But, as per ES6 spec, the above `function ...` and `class ...` parts should be parsed
+        as function declaration and class declaration. This has big difference; the instantiation
+        of the function declarations are done in the function prologue.
+
+        In this patch, we correctly parse the above cases as declaration. To handle no-named
+        declarations, we add a new flag, DeclarationDefaultContext. This indicates [Default]
+        flag in the ES6 spec's BNF.
+
+        Furthermore, this patch also fixes the following name related bugs.
+
+        1. The bug related to "export default"'s function name. If the name is not provided (like the above case), the name of the function becomes
+        "default", not "*default*". This is special handling in ES6 spec. We handle this in JSFunction's reifyName.
+
+        2. `class Hello { hello hello() { } }` is accepted. We introduced FunctionRequirements::Unnamed and fix this bug.
+
+        * parser/ModuleScopeData.h:
+        (JSC::ModuleScopeData::exportBinding):
+        Exported names are already guranteed uniqueness by m_exportedNames. Not necessary to use set here. Use vector instead.
+
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseFunctionInfo):
+        If we pass FunctionRequirements::NoRequirements, we need to initialize functionInfo.name / classInfo.className
+        with the default fallback name. For example, in the above `export default` case, we initialize it with `*default*`.
+
+        (JSC::Parser<LexerType>::parseFunctionDeclaration):
+        (JSC::Parser<LexerType>::parseClassDeclaration):
+        (JSC::Parser<LexerType>::parseClass):
+        (JSC::Parser<LexerType>::parseExportDeclaration):
+        (JSC::Parser<LexerType>::parsePropertyMethod):
+        (JSC::Parser<LexerType>::parseGetterSetter):
+        (JSC::Parser<LexerType>::parseClassExpression):
+        (JSC::Parser<LexerType>::parseFunctionExpression):
+        (JSC::Parser<LexerType>::parsePrimaryExpression):
+        (JSC::Parser<LexerType>::parseArrowFunctionExpression):
+        * parser/Parser.h:
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::reifyName):
+
 2016-08-23  Saam Barati  <[email protected]>
 
         JIT::updateTopCallframe() in the baseline JIT should use PC instead of PC+1

Modified: trunk/Source/_javascript_Core/inspector/JSInjectedScriptHost.cpp (204841 => 204842)


--- trunk/Source/_javascript_Core/inspector/JSInjectedScriptHost.cpp	2016-08-23 18:09:21 UTC (rev 204841)
+++ trunk/Source/_javascript_Core/inspector/JSInjectedScriptHost.cpp	2016-08-23 18:14:30 UTC (rev 204842)
@@ -228,7 +228,7 @@
     JSObject* result = constructEmptyObject(exec);
     result->putDirect(vm, Identifier::fromString(exec, "location"), location);
 
-    String name = function->name();
+    String name = function->name(vm);
     if (!name.isEmpty())
         result->putDirect(vm, Identifier::fromString(exec, "name"), jsString(exec, name));
 

Modified: trunk/Source/_javascript_Core/parser/ModuleScopeData.h (204841 => 204842)


--- trunk/Source/_javascript_Core/parser/ModuleScopeData.h	2016-08-23 18:09:21 UTC (rev 204841)
+++ trunk/Source/_javascript_Core/parser/ModuleScopeData.h	2016-08-23 18:14:30 UTC (rev 204842)
@@ -35,7 +35,7 @@
 WTF_MAKE_NONCOPYABLE(ModuleScopeData);
 WTF_MAKE_FAST_ALLOCATED;
 public:
-    typedef HashMap<RefPtr<UniquedStringImpl>, IdentifierSet, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> IdentifierAliasMap;
+    typedef HashMap<RefPtr<UniquedStringImpl>, Vector<RefPtr<UniquedStringImpl>>, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> IdentifierAliasMap;
 
     static Ref<ModuleScopeData> create() { return adoptRef(*new ModuleScopeData); }
 
@@ -48,7 +48,7 @@
 
     void exportBinding(const Identifier& localName, const Identifier& exportedName)
     {
-        m_exportedBindings.add(localName.impl(), IdentifierSet()).iterator->value.add(exportedName.impl());
+        m_exportedBindings.add(localName.impl(), Vector<RefPtr<UniquedStringImpl>>()).iterator->value.append(exportedName.impl());
     }
 
     void exportBinding(const Identifier& localName)

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (204841 => 204842)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2016-08-23 18:09:21 UTC (rev 204841)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2016-08-23 18:14:30 UTC (rev 204842)
@@ -1930,7 +1930,7 @@
 }
 
 template <typename LexerType>
-template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionRequirements requirements, SourceParseMode mode, bool nameIsInContainingScope, ConstructorKind constructorKind, SuperBinding expectedSuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>& functionInfo, FunctionDefinitionType functionDefinitionType)
+template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionNameRequirements requirements, SourceParseMode mode, bool nameIsInContainingScope, ConstructorKind constructorKind, SuperBinding expectedSuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>& functionInfo, FunctionDefinitionType functionDefinitionType)
 {
     RELEASE_ASSERT(isFunctionParseMode(mode));
 
@@ -2072,18 +2072,22 @@
         if (functionDefinitionType == FunctionDefinitionType::_expression_ && mode == SourceParseMode::NormalFunctionMode)
             upperScopeIsGenerator = false;
 
-        if (matchSpecIdentifier(upperScopeIsGenerator)) {
-            functionInfo.name = m_token.m_data.ident;
-            m_parserState.lastFunctionName = functionInfo.name;
-            next();
-            if (!nameIsInContainingScope)
-                failIfTrueIfStrict(functionScope->declareCallee(functionInfo.name) & DeclarationResult::InvalidStrictMode, "'", functionInfo.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
-        } else if (requirements == FunctionNeedsName) {
-            if (match(OPENPAREN) && mode == SourceParseMode::NormalFunctionMode)
-                semanticFail("Function statements must have a name");
-            semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
-            failDueToUnexpectedToken();
-            return false;
+        if (requirements != FunctionNameRequirements::Unnamed) {
+            ASSERT_WITH_MESSAGE(!(requirements == FunctionNameRequirements::None && !functionInfo.name), "When specifying FunctionNameRequirements::None, we need to initialize functionInfo.name with the default value in the caller side.");
+            if (matchSpecIdentifier(upperScopeIsGenerator)) {
+                functionInfo.name = m_token.m_data.ident;
+                m_parserState.lastFunctionName = functionInfo.name;
+                next();
+                if (!nameIsInContainingScope)
+                    failIfTrueIfStrict(functionScope->declareCallee(functionInfo.name) & DeclarationResult::InvalidStrictMode, "'", functionInfo.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
+            } else if (requirements == FunctionNameRequirements::Named) {
+                if (match(OPENPAREN) && mode == SourceParseMode::NormalFunctionMode)
+                    semanticFail("Function statements must have a name");
+                semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
+                failDueToUnexpectedToken();
+                return false;
+            }
+            ASSERT(functionInfo.name);
         }
 
         startLocation = tokenLocation();
@@ -2163,7 +2167,8 @@
     restoreParserState(oldState);
     failIfFalse(functionInfo.body, "Cannot parse the body of this ", stringForFunctionMode(mode));
     context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
-    if (functionScope->strictMode() && functionInfo.name) {
+    if (functionScope->strictMode() && requirements != FunctionNameRequirements::Unnamed) {
+        ASSERT(functionInfo.name);
         RELEASE_ASSERT(mode == SourceParseMode::NormalFunctionMode || mode == SourceParseMode::MethodMode || mode == SourceParseMode::ArrowFunctionMode || mode == SourceParseMode::GeneratorBodyMode || mode == SourceParseMode::GeneratorWrapperFunctionMode);
         semanticFailIfTrue(m_vm->propertyNames->arguments == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
         semanticFailIfTrue(m_vm->propertyNames->eval == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
@@ -2221,19 +2226,46 @@
 static FunctionMetadataNode* getMetadata(ParserFunctionInfo<ASTBuilder>& info) { return info.body; }
 
 template <typename LexerType>
-template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context, ExportType exportType)
+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext)
 {
     ASSERT(match(FUNCTION));
     JSTokenLocation location(tokenLocation());
     unsigned functionKeywordStart = tokenStart();
     next();
-    ParserFunctionInfo<TreeBuilder> functionInfo;
     SourceParseMode parseMode = SourceParseMode::NormalFunctionMode;
     if (consume(TIMES))
         parseMode = SourceParseMode::GeneratorWrapperFunctionMode;
-    failIfFalse((parseFunctionInfo(context, FunctionNeedsName, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration)), "Cannot parse this function");
-    failIfFalse(functionInfo.name, "Function statements must have a name");
 
+    ParserFunctionInfo<TreeBuilder> functionInfo;
+    FunctionNameRequirements requirements = FunctionNameRequirements::Named;
+    if (declarationDefaultContext == DeclarationDefaultContext::ExportDefault) {
+        // Under the "export default" context, function declaration does not require the function name.
+        //
+        //     ExportDeclaration:
+        //         ...
+        //         export default HoistableDeclaration[~Yield, +Default]
+        //         ...
+        //
+        //     HoistableDeclaration[Yield, Default]:
+        //         FunctionDeclaration[?Yield, ?Default]
+        //         GeneratorDeclaration[?Yield, ?Default]
+        //
+        //     FunctionDeclaration[Yield, Default]:
+        //         ...
+        //         [+Default] function ( FormalParameters[~Yield] ) { FunctionBody[~Yield] }
+        //
+        //     GeneratorDeclaration[Yield, Default]:
+        //         ...
+        //         [+Default] function * ( FormalParameters[+Yield] ) { GeneratorBody }
+        //
+        // In this case, we use "*default*" as this function declaration's name.
+        requirements = FunctionNameRequirements::None;
+        functionInfo.name = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
+    }
+
+    failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration)), "Cannot parse this function");
+    ASSERT(functionInfo.name);
+
     std::pair<DeclarationResultMask, ScopeRef> functionDeclaration = declareFunction(functionInfo.name);
     DeclarationResultMask declarationResult = functionDeclaration.first;
     failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a function named '", functionInfo.name->impl(), "' in strict mode");
@@ -2240,6 +2272,7 @@
     if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
         internalFailWithMessage(false, "Cannot declare a function that shadows a let/const/class/function variable '", functionInfo.name->impl(), "' in strict mode");
     if (exportType == ExportType::Exported) {
+        ASSERT_WITH_MESSAGE(declarationDefaultContext != DeclarationDefaultContext::ExportDefault, "Export default case will export the name and binding in the caller.");
         semanticFailIfFalse(exportName(*functionInfo.name), "Cannot export a duplicate function name: '", functionInfo.name->impl(), "'");
         m_moduleScopeData->exportBinding(*functionInfo.name);
     }
@@ -2251,7 +2284,7 @@
 }
 
 template <typename LexerType>
-template <class TreeBuilder> TreeStatement Parser<LexerType>::parseClassDeclaration(TreeBuilder& context, ExportType exportType)
+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseClassDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext)
 {
     ASSERT(match(CLASSTOKEN));
     JSTokenLocation location(tokenLocation());
@@ -2259,13 +2292,33 @@
     unsigned classStartLine = tokenLine();
 
     ParserClassInfo<TreeBuilder> info;
-    TreeClassExpression classExpr = parseClass(context, FunctionNeedsName, info);
+    FunctionNameRequirements requirements = FunctionNameRequirements::Named;
+    if (declarationDefaultContext == DeclarationDefaultContext::ExportDefault) {
+        // Under the "export default" context, class declaration does not require the class name.
+        //
+        //     ExportDeclaration:
+        //         ...
+        //         export default ClassDeclaration[~Yield, +Default]
+        //         ...
+        //
+        //     ClassDeclaration[Yield, Default]:
+        //         ...
+        //         [+Default] class ClassTail[?Yield]
+        //
+        // In this case, we use "*default*" as this class declaration's name.
+        requirements = FunctionNameRequirements::None;
+        info.className = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
+    }
+
+    TreeClassExpression classExpr = parseClass(context, requirements, info);
     failIfFalse(classExpr, "Failed to parse class");
+    ASSERT(info.className);
 
     DeclarationResultMask declarationResult = declareVariable(info.className, DeclarationType::LetDeclaration);
     if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
         internalFailWithMessage(false, "Cannot declare a class twice: '", info.className->impl(), "'");
     if (exportType == ExportType::Exported) {
+        ASSERT_WITH_MESSAGE(declarationDefaultContext != DeclarationDefaultContext::ExportDefault, "Export default case will export the name and binding in the caller.");
         semanticFailIfFalse(exportName(*info.className), "Cannot export a duplicate class name: '", info.className->impl(), "'");
         m_moduleScopeData->exportBinding(*info.className);
     }
@@ -2277,7 +2330,7 @@
 }
 
 template <typename LexerType>
-template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClass(TreeBuilder& context, FunctionRequirements requirements, ParserClassInfo<TreeBuilder>& info)
+template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClass(TreeBuilder& context, FunctionNameRequirements requirements, ParserClassInfo<TreeBuilder>& info)
 {
     ASSERT(match(CLASSTOKEN));
     JSTokenLocation location(tokenLocation());
@@ -2291,20 +2344,19 @@
     classScope->preventVarDeclarations();
     classScope->setStrictMode();
 
-    const Identifier* className = nullptr;
+    ASSERT_WITH_MESSAGE(requirements != FunctionNameRequirements::Unnamed, "Currently, there is no caller that uses FunctionNameRequirements::Unnamed for class syntax.");
+    ASSERT_WITH_MESSAGE(!(requirements == FunctionNameRequirements::None && !info.className), "When specifying FunctionNameRequirements::None, we need to initialize info.className with the default value in the caller side.");
     if (match(IDENT)) {
-        className = m_token.m_data.ident;
+        info.className = m_token.m_data.ident;
         next();
-        failIfTrue(classScope->declareLexicalVariable(className, true) & DeclarationResult::InvalidStrictMode, "'", className->impl(), "' is not a valid class name");
-    } else if (requirements == FunctionNeedsName) {
+        failIfTrue(classScope->declareLexicalVariable(info.className, true) & DeclarationResult::InvalidStrictMode, "'", info.className->impl(), "' is not a valid class name");
+    } else if (requirements == FunctionNameRequirements::Named) {
         if (match(OPENBRACE))
             semanticFail("Class statements must have a name");
         semanticFailureDueToKeyword("class name");
         failDueToUnexpectedToken();
-    } else
-        className = &m_vm->propertyNames->nullIdentifier;
-    ASSERT(className);
-    info.className = className;
+    }
+    ASSERT(info.className);
 
     TreeExpression parentClass = 0;
     if (consume(EXTENDS)) {
@@ -2401,8 +2453,8 @@
                 semanticFailIfTrue(*ident == m_vm->propertyNames->prototype, "Cannot declare a generator named 'prototype'");
                 semanticFailIfTrue(*ident == m_vm->propertyNames->constructor, "Cannot declare a generator named 'constructor'");
             }
-            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;
+            methodInfo.name = isConstructor ? info.className : ident;
+            failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::Unnamed, parseMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
 
             TreeExpression method = context.createMethodDefinition(methodLocation, methodInfo);
             if (isConstructor) {
@@ -2856,10 +2908,10 @@
         TreeStatement result = 0;
         bool isFunctionOrClassDeclaration = false;
         const Identifier* localName = nullptr;
-        SavePoint savePoint = createSavePoint();
 
         bool startsWithFunction = match(FUNCTION);
         if (startsWithFunction || match(CLASSTOKEN)) {
+            SavePoint savePoint = createSavePoint();
             isFunctionOrClassDeclaration = true;
             next();
 
@@ -2871,14 +2923,18 @@
             restoreSavePoint(savePoint);
         }
 
-        if (localName) {
-            if (match(FUNCTION)) {
+        if (!localName)
+            localName = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
+
+        if (isFunctionOrClassDeclaration) {
+            if (startsWithFunction) {
+                ASSERT(match(FUNCTION));
                 DepthManager statementDepth(&m_statementDepth);
                 m_statementDepth = 1;
-                result = parseFunctionDeclaration(context);
+                result = parseFunctionDeclaration(context, ExportType::NotExported, DeclarationDefaultContext::ExportDefault);
             } else {
                 ASSERT(match(CLASSTOKEN));
-                result = parseClassDeclaration(context);
+                result = parseClassDeclaration(context, ExportType::NotExported, DeclarationDefaultContext::ExportDefault);
             }
         } else {
             // export default expr;
@@ -2901,9 +2957,7 @@
 
             TreeExpression assignment = context.createAssignResolve(location, m_vm->propertyNames->builtinNames().starDefaultPrivateName(), _expression_, start, start, tokenEndPosition(), AssignmentContext::ConstDeclarationStatement);
             result = context.createExprStatement(location, assignment, start, tokenEndPosition());
-            if (!isFunctionOrClassDeclaration)
-                failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
-            localName = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
+            failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
         }
         failIfFalse(result, "Cannot parse the declaration");
 
@@ -3429,9 +3483,9 @@
     JSTokenLocation methodLocation(tokenLocation());
     unsigned methodStart = tokenStart();
     ParserFunctionInfo<TreeBuilder> methodInfo;
+    methodInfo.name = methodName;
     SourceParseMode parseMode = isGenerator ? SourceParseMode::GeneratorWrapperFunctionMode : SourceParseMode::MethodMode;
-    failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, parseMode, false, ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
-    methodInfo.name = methodName;
+    failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::Unnamed, parseMode, false, ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
     return context.createMethodDefinition(methodLocation, methodInfo);
 }
 
@@ -3466,10 +3520,10 @@
     ParserFunctionInfo<TreeBuilder> info;
     if (type & PropertyNode::Getter) {
         failIfFalse(match(OPENPAREN), "Expected a parameter list for getter definition");
-        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::GetterMode, false, constructorKind, SuperBinding::Needed, getterOrSetterStartOffset, info, FunctionDefinitionType::Method)), "Cannot parse getter definition");
+        failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::Unnamed, SourceParseMode::GetterMode, false, constructorKind, SuperBinding::Needed, getterOrSetterStartOffset, info, FunctionDefinitionType::Method)), "Cannot parse getter definition");
     } else {
         failIfFalse(match(OPENPAREN), "Expected a parameter list for setter definition");
-        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::SetterMode, false, constructorKind, SuperBinding::Needed, getterOrSetterStartOffset, info, FunctionDefinitionType::Method)), "Cannot parse setter definition");
+        failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::Unnamed, SourceParseMode::SetterMode, false, constructorKind, SuperBinding::Needed, getterOrSetterStartOffset, info, FunctionDefinitionType::Method)), "Cannot parse setter definition");
     }
 
     if (stringPropertyName)
@@ -3671,6 +3725,15 @@
 }
 
 template <typename LexerType>
+template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClassExpression(TreeBuilder& context)
+{
+    ASSERT(match(CLASSTOKEN));
+    ParserClassInfo<TreeBuilder> info;
+    info.className = &m_vm->propertyNames->nullIdentifier;
+    return parseClass(context, FunctionNameRequirements::None, info);
+}
+
+template <typename LexerType>
 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseFunctionExpression(TreeBuilder& context)
 {
     ASSERT(match(FUNCTION));
@@ -3682,7 +3745,7 @@
     SourceParseMode parseMode = SourceParseMode::NormalFunctionMode;
     if (consume(TIMES))
         parseMode = SourceParseMode::GeneratorWrapperFunctionMode;
-    failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, parseMode, false, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::_expression_)), "Cannot parse function _expression_");
+    failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::None, parseMode, false, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::_expression_)), "Cannot parse function _expression_");
     return context.createFunctionExpr(location, functionInfo);
 }
 
@@ -3751,10 +3814,8 @@
     switch (m_token.m_type) {
     case FUNCTION:
         return parseFunctionExpression(context);
-    case CLASSTOKEN: {
-        ParserClassInfo<TreeBuilder> info;
-        return parseClass(context, FunctionNoRequirements, info);
-    }
+    case CLASSTOKEN:
+        return parseClassExpression(context);
     case OPENBRACE:
         if (strictMode())
             return parseStrictObjectLiteral(context);
@@ -4078,7 +4139,7 @@
     location = tokenLocation();
     ParserFunctionInfo<TreeBuilder> info;
     info.name = &m_vm->propertyNames->nullIdentifier;
-    failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::ArrowFunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, FunctionDefinitionType::_expression_)), "Cannot parse arrow function _expression_");
+    failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::Unnamed, SourceParseMode::ArrowFunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, FunctionDefinitionType::_expression_)), "Cannot parse arrow function _expression_");
 
     return context.createArrowFunctionExpr(location, info);
 }

Modified: trunk/Source/_javascript_Core/parser/Parser.h (204841 => 204842)


--- trunk/Source/_javascript_Core/parser/Parser.h	2016-08-23 18:09:21 UTC (rev 204841)
+++ trunk/Source/_javascript_Core/parser/Parser.h	2016-08-23 18:14:30 UTC (rev 204842)
@@ -70,7 +70,7 @@
 
 enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode };
 enum FunctionBodyType { ArrowFunctionBodyExpression, ArrowFunctionBodyBlock, StandardFunctionBodyBlock };
-enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName };
+enum class FunctionNameRequirements { None, Named, Unnamed };
 
 enum class DestructuringKind {
     DestructureToVariables,
@@ -101,6 +101,10 @@
 
 typedef uint8_t DeclarationResultMask;
 
+enum class DeclarationDefaultContext {
+    Standard,
+    ExportDefault,
+};
 
 template <typename T> inline bool isEvalNode() { return false; }
 template <> inline bool isEvalNode<EvalNode>() { return true; }
@@ -1355,8 +1359,8 @@
     template <class TreeBuilder> TreeStatement parseStatementListItem(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength);
     template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength = 0);
     enum class ExportType { Exported, NotExported };
-    template <class TreeBuilder> TreeStatement parseClassDeclaration(TreeBuilder&, ExportType = ExportType::NotExported);
-    template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported);
+    template <class TreeBuilder> TreeStatement parseClassDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard);
+    template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard);
     template <class TreeBuilder> TreeStatement parseVariableDeclaration(TreeBuilder&, DeclarationType, ExportType = ExportType::NotExported);
     template <class TreeBuilder> TreeStatement parseDoWhileStatement(TreeBuilder&);
     template <class TreeBuilder> TreeStatement parseWhileStatement(TreeBuilder&);
@@ -1388,6 +1392,7 @@
     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseArrayLiteral(TreeBuilder&);
     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseObjectLiteral(TreeBuilder&);
     template <class TreeBuilder> NEVER_INLINE TreeExpression parseStrictObjectLiteral(TreeBuilder&);
+    template <class TreeBuilder> ALWAYS_INLINE TreeClassExpression parseClassExpression(TreeBuilder&);
     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseFunctionExpression(TreeBuilder&);
     template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&);
     template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseArgument(TreeBuilder&, ArgumentType&);
@@ -1416,7 +1421,7 @@
     template <class TreeBuilder> TreeStatement parseExportDeclaration(TreeBuilder&);
 
     enum class FunctionDefinitionType { _expression_, Declaration, Method };
-    template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionRequirements, SourceParseMode, bool nameIsInContainingScope, ConstructorKind, SuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>&, FunctionDefinitionType);
+    template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionNameRequirements, SourceParseMode, bool nameIsInContainingScope, ConstructorKind, SuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>&, FunctionDefinitionType);
     
     ALWAYS_INLINE bool isArrowFunctionParameters();
     
@@ -1423,7 +1428,7 @@
     template <class TreeBuilder, class FunctionInfoType> NEVER_INLINE typename TreeBuilder::FormalParameterList parseFunctionParameters(TreeBuilder&, SourceParseMode, FunctionInfoType&);
     template <class TreeBuilder> NEVER_INLINE typename TreeBuilder::FormalParameterList createGeneratorParameters(TreeBuilder&);
 
-    template <class TreeBuilder> NEVER_INLINE TreeClassExpression parseClass(TreeBuilder&, FunctionRequirements, ParserClassInfo<TreeBuilder>&);
+    template <class TreeBuilder> NEVER_INLINE TreeClassExpression parseClass(TreeBuilder&, FunctionNameRequirements, ParserClassInfo<TreeBuilder>&);
 
     template <class TreeBuilder> NEVER_INLINE typename TreeBuilder::TemplateString parseTemplateString(TreeBuilder& context, bool isTemplateHead, typename LexerType::RawStringsBuildMode, bool& elementIsTail);
     template <class TreeBuilder> NEVER_INLINE typename TreeBuilder::TemplateLiteral parseTemplateLiteral(TreeBuilder&, typename LexerType::RawStringsBuildMode);

Modified: trunk/Source/_javascript_Core/runtime/FunctionPrototype.cpp (204841 => 204842)


--- trunk/Source/_javascript_Core/runtime/FunctionPrototype.cpp	2016-08-23 18:09:21 UTC (rev 204841)
+++ trunk/Source/_javascript_Core/runtime/FunctionPrototype.cpp	2016-08-23 18:14:30 UTC (rev 204842)
@@ -82,11 +82,12 @@
 
 EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec)
 {
+    VM& vm = exec->vm();
     JSValue thisValue = exec->thisValue();
     if (thisValue.inherits(JSFunction::info())) {
         JSFunction* function = jsCast<JSFunction*>(thisValue);
         if (function->isHostOrBuiltinFunction())
-            return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(), "() {\n    [native code]\n}"));
+            return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(vm), "() {\n    [native code]\n}"));
 
         FunctionExecutable* executable = function->jsExecutable();
         if (executable->isClass()) {
@@ -99,7 +100,7 @@
         StringView source = executable->source().provider()->getRange(
             executable->parametersStartOffset(),
             executable->parametersStartOffset() + executable->source().length());
-        return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name(), source));
+        return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name(vm), source));
     }
 
     if (thisValue.inherits(InternalFunction::info())) {

Modified: trunk/Source/_javascript_Core/runtime/JSFunction.cpp (204841 => 204842)


--- trunk/Source/_javascript_Core/runtime/JSFunction.cpp	2016-08-23 18:09:21 UTC (rev 204841)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.cpp	2016-08-23 18:14:30 UTC (rev 204842)
@@ -166,13 +166,16 @@
     return m_rareData.get();
 }
 
-String JSFunction::name()
+String JSFunction::name(VM& vm)
 {
     if (isHostFunction()) {
         NativeExecutable* executable = jsCast<NativeExecutable*>(this->executable());
         return executable->name();
     }
-    return jsExecutable()->name().string();
+    const Identifier identifier = jsExecutable()->name();
+    if (identifier == vm.propertyNames->builtinNames().starDefaultPrivateName())
+        return emptyString();
+    return identifier.string();
 }
 
 String JSFunction::displayName(VM& vm)
@@ -192,7 +195,7 @@
     if (!explicitName.isEmpty())
         return explicitName;
     
-    const String actualName = name();
+    const String actualName = name(vm);
     if (!actualName.isEmpty() || isHostOrBuiltinFunction())
         return actualName;
     
@@ -616,7 +619,15 @@
 
 void JSFunction::reifyName(ExecState* exec)
 {
-    String name = jsExecutable()->ecmaName().string();
+    const Identifier& ecmaName = jsExecutable()->ecmaName();
+    String name;
+    // https://tc39.github.io/ecma262/#sec-exports-runtime-semantics-evaluation
+    // When the ident is "*default*", we need to set "default" for the ecma name.
+    // This "*default*" name is never shown to users.
+    if (ecmaName == exec->propertyNames().builtinNames().starDefaultPrivateName())
+        name = exec->propertyNames().defaultKeyword.string();
+    else
+        name = ecmaName.string();
     reifyName(exec, name);
 }
 

Modified: trunk/Source/_javascript_Core/runtime/JSFunction.h (204841 => 204842)


--- trunk/Source/_javascript_Core/runtime/JSFunction.h	2016-08-23 18:09:21 UTC (rev 204841)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.h	2016-08-23 18:14:30 UTC (rev 204842)
@@ -81,7 +81,7 @@
     JS_EXPORT_PRIVATE static JSFunction* createBuiltinFunction(VM&, FunctionExecutable*, JSGlobalObject*);
     static JSFunction* createBuiltinFunction(VM&, FunctionExecutable*, JSGlobalObject*, const String& name);
 
-    JS_EXPORT_PRIVATE String name();
+    JS_EXPORT_PRIVATE String name(VM&);
     JS_EXPORT_PRIVATE String displayName(VM&);
     const String calculatedDisplayName(VM&);
 

Modified: trunk/Source/_javascript_Core/runtime/LazyClassStructure.cpp (204841 => 204842)


--- trunk/Source/_javascript_Core/runtime/LazyClassStructure.cpp	2016-08-23 18:09:21 UTC (rev 204841)
+++ trunk/Source/_javascript_Core/runtime/LazyClassStructure.cpp	2016-08-23 18:14:30 UTC (rev 204842)
@@ -80,7 +80,7 @@
     if (InternalFunction* internalFunction = jsDynamicCast<InternalFunction*>(constructor))
         name = internalFunction->name();
     else if (JSFunction* function = jsDynamicCast<JSFunction*>(constructor))
-        name = function->name();
+        name = function->name(vm);
     else
         RELEASE_ASSERT_NOT_REACHED();
     
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to