Changeset 204842 in webkit


Ignore:
Timestamp:
Aug 23, 2016 11:14:30 AM (8 years ago)
Author:
Yusuke Suzuki
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/JavaScriptCore:

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.

  1. 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):

Location:
trunk
Files:
5 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r204714 r204842  
     12016-08-22  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [ES6] Modules' `export default function/class` should be declaration
     4        https://bugs.webkit.org/show_bug.cgi?id=160499
     5
     6        Reviewed by Saam Barati.
     7
     8        Add several module tests. And flip the failed tests flags in test262.
     9
     10        * modules/export-default-function-name-in-assignment-expression.js: Added.
     11        (export.default):
     12        * modules/export-default-function-name-in-class-declaration.js: Added.
     13        * modules/export-default-function-name-in-function-declaration.js: Added.
     14        (export.default):
     15        * modules/export-default-function-name-in-generator-declaration.js: Added.
     16        (export.default):
     17        * stress/method-name.js: Added.
     18        (testSyntax):
     19        (testSyntaxError):
     20        (testSyntaxError.Hello.prototype.hello.hello):
     21        (testSyntaxError.Hello):
     22        (SyntaxError.Unexpected.identifier.string_appeared_here.Expected.an.opening.string_appeared_here.before.a.method.testSyntaxError.let.obj.hello.hello):
     23        (testSyntaxError.Hello.prototype.get hello):
     24        (testSyntaxError.Hello.prototype.set hello):
     25        * test262.yaml:
     26
    1272016-08-22  Yusuke Suzuki  <utatane.tea@gmail.com>
    228
  • trunk/JSTests/test262.yaml

    r204714 r204842  
    7086970869  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
    7087070870- path: test262/test/language/module-code/eval-export-dflt-cls-anon.js
    70871   cmd: runTest262 :fail, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
     70871  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
    7087270872- path: test262/test/language/module-code/eval-export-dflt-cls-name-meth.js
    7087370873  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
     
    7087770877  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
    7087870878- path: test262/test/language/module-code/eval-export-dflt-expr-cls-anon.js
    70879   cmd: runTest262 :fail, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
     70879  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
    7088070880- path: test262/test/language/module-code/eval-export-dflt-expr-cls-name-meth.js
    7088170881  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
     
    7088770887  cmd: runTest262 :normal, "ReferenceError", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
    7088870888- path: test262/test/language/module-code/eval-export-dflt-expr-fn-anon.js
    70889   cmd: runTest262 :fail, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
     70889  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
    7089070890- path: test262/test/language/module-code/eval-export-dflt-expr-fn-named.js
    7089170891  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
    7089270892- path: test262/test/language/module-code/eval-export-dflt-expr-gen-anon.js
    70893   cmd: runTest262 :fail, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
     70893  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
    7089470894- path: test262/test/language/module-code/eval-export-dflt-expr-gen-named.js
    7089570895  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
     
    7107371073  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
    7107471074- path: test262/test/language/module-code/instn-named-bndng-dflt-fun-anon.js
    71075   cmd: runTest262 :fail, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
     71075  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
    7107671076- path: test262/test/language/module-code/instn-named-bndng-dflt-fun-named.js
    7107771077  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
    7107871078- path: test262/test/language/module-code/instn-named-bndng-dflt-gen-anon.js
    71079   cmd: runTest262 :fail, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
     71079  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
    7108071080- path: test262/test/language/module-code/instn-named-bndng-dflt-gen-named.js
    7108171081  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
     
    7150571505  cmd: runTest262 :fail, "SyntaxError", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
    7150671506- path: test262/test/language/module-code/parse-err-invoke-anon-fun-decl.js
    71507   cmd: runTest262 :fail, "SyntaxError", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
     71507  cmd: runTest262 :normal, "SyntaxError", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
    7150871508- path: test262/test/language/module-code/parse-err-invoke-anon-gen-decl.js
    71509   cmd: runTest262 :fail, "SyntaxError", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
     71509  cmd: runTest262 :normal, "SyntaxError", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
    7151071510- path: test262/test/language/module-code/parse-err-reference.js
    7151171511  cmd: runTest262 :normal, "ReferenceError", ["../../../harness/assert.js", "../../../harness/sta.js"], [:module]
  • trunk/Source/JavaScriptCore/ChangeLog

    r204840 r204842  
     12016-08-22  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [ES6] Modules' `export default function/class` should be declaration
     4        https://bugs.webkit.org/show_bug.cgi?id=160499
     5
     6        Reviewed by Saam Barati.
     7
     8        Previously, we parsed the following cases as FunctionExpression and ClassExpression.
     9
     10            ```
     11            export default function () { }
     12            export default class { }
     13            ```
     14
     15        But, as per ES6 spec, the above `function ...` and `class ...` parts should be parsed
     16        as function declaration and class declaration. This has big difference; the instantiation
     17        of the function declarations are done in the function prologue.
     18
     19        In this patch, we correctly parse the above cases as declaration. To handle no-named
     20        declarations, we add a new flag, DeclarationDefaultContext. This indicates [Default]
     21        flag in the ES6 spec's BNF.
     22
     23        Furthermore, this patch also fixes the following name related bugs.
     24
     25        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
     26        "default", not "*default*". This is special handling in ES6 spec. We handle this in JSFunction's reifyName.
     27
     28        2. `class Hello { hello hello() { } }` is accepted. We introduced FunctionRequirements::Unnamed and fix this bug.
     29
     30        * parser/ModuleScopeData.h:
     31        (JSC::ModuleScopeData::exportBinding):
     32        Exported names are already guranteed uniqueness by m_exportedNames. Not necessary to use set here. Use vector instead.
     33
     34        * parser/Parser.cpp:
     35        (JSC::Parser<LexerType>::parseFunctionInfo):
     36        If we pass FunctionRequirements::NoRequirements, we need to initialize functionInfo.name / classInfo.className
     37        with the default fallback name. For example, in the above `export default` case, we initialize it with `*default*`.
     38
     39        (JSC::Parser<LexerType>::parseFunctionDeclaration):
     40        (JSC::Parser<LexerType>::parseClassDeclaration):
     41        (JSC::Parser<LexerType>::parseClass):
     42        (JSC::Parser<LexerType>::parseExportDeclaration):
     43        (JSC::Parser<LexerType>::parsePropertyMethod):
     44        (JSC::Parser<LexerType>::parseGetterSetter):
     45        (JSC::Parser<LexerType>::parseClassExpression):
     46        (JSC::Parser<LexerType>::parseFunctionExpression):
     47        (JSC::Parser<LexerType>::parsePrimaryExpression):
     48        (JSC::Parser<LexerType>::parseArrowFunctionExpression):
     49        * parser/Parser.h:
     50        * runtime/JSFunction.cpp:
     51        (JSC::JSFunction::reifyName):
     52
    1532016-08-23  Saam Barati  <sbarati@apple.com>
    254
  • trunk/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp

    r204358 r204842  
    229229    result->putDirect(vm, Identifier::fromString(exec, "location"), location);
    230230
    231     String name = function->name();
     231    String name = function->name(vm);
    232232    if (!name.isEmpty())
    233233        result->putDirect(vm, Identifier::fromString(exec, "name"), jsString(exec, name));
  • trunk/Source/JavaScriptCore/parser/ModuleScopeData.h

    r203953 r204842  
    3636WTF_MAKE_FAST_ALLOCATED;
    3737public:
    38     typedef HashMap<RefPtr<UniquedStringImpl>, IdentifierSet, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> IdentifierAliasMap;
     38    typedef HashMap<RefPtr<UniquedStringImpl>, Vector<RefPtr<UniquedStringImpl>>, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> IdentifierAliasMap;
    3939
    4040    static Ref<ModuleScopeData> create() { return adoptRef(*new ModuleScopeData); }
     
    4949    void exportBinding(const Identifier& localName, const Identifier& exportedName)
    5050    {
    51         m_exportedBindings.add(localName.impl(), IdentifierSet()).iterator->value.add(exportedName.impl());
     51        m_exportedBindings.add(localName.impl(), Vector<RefPtr<UniquedStringImpl>>()).iterator->value.append(exportedName.impl());
    5252    }
    5353
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r204714 r204842  
    19311931
    19321932template <typename LexerType>
    1933 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)
     1933template <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)
    19341934{
    19351935    RELEASE_ASSERT(isFunctionParseMode(mode));
     
    20732073            upperScopeIsGenerator = false;
    20742074
    2075         if (matchSpecIdentifier(upperScopeIsGenerator)) {
    2076             functionInfo.name = m_token.m_data.ident;
    2077             m_parserState.lastFunctionName = functionInfo.name;
    2078             next();
    2079             if (!nameIsInContainingScope)
    2080                 failIfTrueIfStrict(functionScope->declareCallee(functionInfo.name) & DeclarationResult::InvalidStrictMode, "'", functionInfo.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
    2081         } else if (requirements == FunctionNeedsName) {
    2082             if (match(OPENPAREN) && mode == SourceParseMode::NormalFunctionMode)
    2083                 semanticFail("Function statements must have a name");
    2084             semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
    2085             failDueToUnexpectedToken();
    2086             return false;
     2075        if (requirements != FunctionNameRequirements::Unnamed) {
     2076            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.");
     2077            if (matchSpecIdentifier(upperScopeIsGenerator)) {
     2078                functionInfo.name = m_token.m_data.ident;
     2079                m_parserState.lastFunctionName = functionInfo.name;
     2080                next();
     2081                if (!nameIsInContainingScope)
     2082                    failIfTrueIfStrict(functionScope->declareCallee(functionInfo.name) & DeclarationResult::InvalidStrictMode, "'", functionInfo.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
     2083            } else if (requirements == FunctionNameRequirements::Named) {
     2084                if (match(OPENPAREN) && mode == SourceParseMode::NormalFunctionMode)
     2085                    semanticFail("Function statements must have a name");
     2086                semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
     2087                failDueToUnexpectedToken();
     2088                return false;
     2089            }
     2090            ASSERT(functionInfo.name);
    20872091        }
    20882092
     
    21642168    failIfFalse(functionInfo.body, "Cannot parse the body of this ", stringForFunctionMode(mode));
    21652169    context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
    2166     if (functionScope->strictMode() && functionInfo.name) {
     2170    if (functionScope->strictMode() && requirements != FunctionNameRequirements::Unnamed) {
     2171        ASSERT(functionInfo.name);
    21672172        RELEASE_ASSERT(mode == SourceParseMode::NormalFunctionMode || mode == SourceParseMode::MethodMode || mode == SourceParseMode::ArrowFunctionMode || mode == SourceParseMode::GeneratorBodyMode || mode == SourceParseMode::GeneratorWrapperFunctionMode);
    21682173        semanticFailIfTrue(m_vm->propertyNames->arguments == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
     
    22222227
    22232228template <typename LexerType>
    2224 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context, ExportType exportType)
     2229template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext)
    22252230{
    22262231    ASSERT(match(FUNCTION));
     
    22282233    unsigned functionKeywordStart = tokenStart();
    22292234    next();
    2230     ParserFunctionInfo<TreeBuilder> functionInfo;
    22312235    SourceParseMode parseMode = SourceParseMode::NormalFunctionMode;
    22322236    if (consume(TIMES))
    22332237        parseMode = SourceParseMode::GeneratorWrapperFunctionMode;
    2234     failIfFalse((parseFunctionInfo(context, FunctionNeedsName, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration)), "Cannot parse this function");
    2235     failIfFalse(functionInfo.name, "Function statements must have a name");
     2238
     2239    ParserFunctionInfo<TreeBuilder> functionInfo;
     2240    FunctionNameRequirements requirements = FunctionNameRequirements::Named;
     2241    if (declarationDefaultContext == DeclarationDefaultContext::ExportDefault) {
     2242        // Under the "export default" context, function declaration does not require the function name.
     2243        //
     2244        //     ExportDeclaration:
     2245        //         ...
     2246        //         export default HoistableDeclaration[~Yield, +Default]
     2247        //         ...
     2248        //
     2249        //     HoistableDeclaration[Yield, Default]:
     2250        //         FunctionDeclaration[?Yield, ?Default]
     2251        //         GeneratorDeclaration[?Yield, ?Default]
     2252        //
     2253        //     FunctionDeclaration[Yield, Default]:
     2254        //         ...
     2255        //         [+Default] function ( FormalParameters[~Yield] ) { FunctionBody[~Yield] }
     2256        //
     2257        //     GeneratorDeclaration[Yield, Default]:
     2258        //         ...
     2259        //         [+Default] function * ( FormalParameters[+Yield] ) { GeneratorBody }
     2260        //
     2261        // In this case, we use "*default*" as this function declaration's name.
     2262        requirements = FunctionNameRequirements::None;
     2263        functionInfo.name = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
     2264    }
     2265
     2266    failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration)), "Cannot parse this function");
     2267    ASSERT(functionInfo.name);
    22362268
    22372269    std::pair<DeclarationResultMask, ScopeRef> functionDeclaration = declareFunction(functionInfo.name);
     
    22412273        internalFailWithMessage(false, "Cannot declare a function that shadows a let/const/class/function variable '", functionInfo.name->impl(), "' in strict mode");
    22422274    if (exportType == ExportType::Exported) {
     2275        ASSERT_WITH_MESSAGE(declarationDefaultContext != DeclarationDefaultContext::ExportDefault, "Export default case will export the name and binding in the caller.");
    22432276        semanticFailIfFalse(exportName(*functionInfo.name), "Cannot export a duplicate function name: '", functionInfo.name->impl(), "'");
    22442277        m_moduleScopeData->exportBinding(*functionInfo.name);
     
    22522285
    22532286template <typename LexerType>
    2254 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseClassDeclaration(TreeBuilder& context, ExportType exportType)
     2287template <class TreeBuilder> TreeStatement Parser<LexerType>::parseClassDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext)
    22552288{
    22562289    ASSERT(match(CLASSTOKEN));
     
    22602293
    22612294    ParserClassInfo<TreeBuilder> info;
    2262     TreeClassExpression classExpr = parseClass(context, FunctionNeedsName, info);
     2295    FunctionNameRequirements requirements = FunctionNameRequirements::Named;
     2296    if (declarationDefaultContext == DeclarationDefaultContext::ExportDefault) {
     2297        // Under the "export default" context, class declaration does not require the class name.
     2298        //
     2299        //     ExportDeclaration:
     2300        //         ...
     2301        //         export default ClassDeclaration[~Yield, +Default]
     2302        //         ...
     2303        //
     2304        //     ClassDeclaration[Yield, Default]:
     2305        //         ...
     2306        //         [+Default] class ClassTail[?Yield]
     2307        //
     2308        // In this case, we use "*default*" as this class declaration's name.
     2309        requirements = FunctionNameRequirements::None;
     2310        info.className = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
     2311    }
     2312
     2313    TreeClassExpression classExpr = parseClass(context, requirements, info);
    22632314    failIfFalse(classExpr, "Failed to parse class");
     2315    ASSERT(info.className);
    22642316
    22652317    DeclarationResultMask declarationResult = declareVariable(info.className, DeclarationType::LetDeclaration);
     
    22672319        internalFailWithMessage(false, "Cannot declare a class twice: '", info.className->impl(), "'");
    22682320    if (exportType == ExportType::Exported) {
     2321        ASSERT_WITH_MESSAGE(declarationDefaultContext != DeclarationDefaultContext::ExportDefault, "Export default case will export the name and binding in the caller.");
    22692322        semanticFailIfFalse(exportName(*info.className), "Cannot export a duplicate class name: '", info.className->impl(), "'");
    22702323        m_moduleScopeData->exportBinding(*info.className);
     
    22782331
    22792332template <typename LexerType>
    2280 template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClass(TreeBuilder& context, FunctionRequirements requirements, ParserClassInfo<TreeBuilder>& info)
     2333template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClass(TreeBuilder& context, FunctionNameRequirements requirements, ParserClassInfo<TreeBuilder>& info)
    22812334{
    22822335    ASSERT(match(CLASSTOKEN));
     
    22922345    classScope->setStrictMode();
    22932346
    2294     const Identifier* className = nullptr;
     2347    ASSERT_WITH_MESSAGE(requirements != FunctionNameRequirements::Unnamed, "Currently, there is no caller that uses FunctionNameRequirements::Unnamed for class syntax.");
     2348    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.");
    22952349    if (match(IDENT)) {
    2296         className = m_token.m_data.ident;
    2297         next();
    2298         failIfTrue(classScope->declareLexicalVariable(className, true) & DeclarationResult::InvalidStrictMode, "'", className->impl(), "' is not a valid class name");
    2299     } else if (requirements == FunctionNeedsName) {
     2350        info.className = m_token.m_data.ident;
     2351        next();
     2352        failIfTrue(classScope->declareLexicalVariable(info.className, true) & DeclarationResult::InvalidStrictMode, "'", info.className->impl(), "' is not a valid class name");
     2353    } else if (requirements == FunctionNameRequirements::Named) {
    23002354        if (match(OPENBRACE))
    23012355            semanticFail("Class statements must have a name");
    23022356        semanticFailureDueToKeyword("class name");
    23032357        failDueToUnexpectedToken();
    2304     } else
    2305         className = &m_vm->propertyNames->nullIdentifier;
    2306     ASSERT(className);
    2307     info.className = className;
     2358    }
     2359    ASSERT(info.className);
    23082360
    23092361    TreeExpression parentClass = 0;
     
    24022454                semanticFailIfTrue(*ident == m_vm->propertyNames->constructor, "Cannot declare a generator named 'constructor'");
    24032455            }
    2404             failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, parseMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
    2405             methodInfo.name = isConstructor ? className : ident;
     2456            methodInfo.name = isConstructor ? info.className : ident;
     2457            failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::Unnamed, parseMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
    24062458
    24072459            TreeExpression method = context.createMethodDefinition(methodLocation, methodInfo);
     
    28572909        bool isFunctionOrClassDeclaration = false;
    28582910        const Identifier* localName = nullptr;
    2859         SavePoint savePoint = createSavePoint();
    28602911
    28612912        bool startsWithFunction = match(FUNCTION);
    28622913        if (startsWithFunction || match(CLASSTOKEN)) {
     2914            SavePoint savePoint = createSavePoint();
    28632915            isFunctionOrClassDeclaration = true;
    28642916            next();
     
    28722924        }
    28732925
    2874         if (localName) {
    2875             if (match(FUNCTION)) {
     2926        if (!localName)
     2927            localName = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
     2928
     2929        if (isFunctionOrClassDeclaration) {
     2930            if (startsWithFunction) {
     2931                ASSERT(match(FUNCTION));
    28762932                DepthManager statementDepth(&m_statementDepth);
    28772933                m_statementDepth = 1;
    2878                 result = parseFunctionDeclaration(context);
     2934                result = parseFunctionDeclaration(context, ExportType::NotExported, DeclarationDefaultContext::ExportDefault);
    28792935            } else {
    28802936                ASSERT(match(CLASSTOKEN));
    2881                 result = parseClassDeclaration(context);
     2937                result = parseClassDeclaration(context, ExportType::NotExported, DeclarationDefaultContext::ExportDefault);
    28822938            }
    28832939        } else {
     
    29022958            TreeExpression assignment = context.createAssignResolve(location, m_vm->propertyNames->builtinNames().starDefaultPrivateName(), expression, start, start, tokenEndPosition(), AssignmentContext::ConstDeclarationStatement);
    29032959            result = context.createExprStatement(location, assignment, start, tokenEndPosition());
    2904             if (!isFunctionOrClassDeclaration)
    2905                 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
    2906             localName = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
     2960            failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
    29072961        }
    29082962        failIfFalse(result, "Cannot parse the declaration");
     
    34303484    unsigned methodStart = tokenStart();
    34313485    ParserFunctionInfo<TreeBuilder> methodInfo;
     3486    methodInfo.name = methodName;
    34323487    SourceParseMode parseMode = isGenerator ? SourceParseMode::GeneratorWrapperFunctionMode : SourceParseMode::MethodMode;
    3433     failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, parseMode, false, ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
    3434     methodInfo.name = methodName;
     3488    failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::Unnamed, parseMode, false, ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
    34353489    return context.createMethodDefinition(methodLocation, methodInfo);
    34363490}
     
    34673521    if (type & PropertyNode::Getter) {
    34683522        failIfFalse(match(OPENPAREN), "Expected a parameter list for getter definition");
    3469         failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::GetterMode, false, constructorKind, SuperBinding::Needed, getterOrSetterStartOffset, info, FunctionDefinitionType::Method)), "Cannot parse getter definition");
     3523        failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::Unnamed, SourceParseMode::GetterMode, false, constructorKind, SuperBinding::Needed, getterOrSetterStartOffset, info, FunctionDefinitionType::Method)), "Cannot parse getter definition");
    34703524    } else {
    34713525        failIfFalse(match(OPENPAREN), "Expected a parameter list for setter definition");
    3472         failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::SetterMode, false, constructorKind, SuperBinding::Needed, getterOrSetterStartOffset, info, FunctionDefinitionType::Method)), "Cannot parse setter definition");
     3526        failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::Unnamed, SourceParseMode::SetterMode, false, constructorKind, SuperBinding::Needed, getterOrSetterStartOffset, info, FunctionDefinitionType::Method)), "Cannot parse setter definition");
    34733527    }
    34743528
     
    36723726
    36733727template <typename LexerType>
     3728template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClassExpression(TreeBuilder& context)
     3729{
     3730    ASSERT(match(CLASSTOKEN));
     3731    ParserClassInfo<TreeBuilder> info;
     3732    info.className = &m_vm->propertyNames->nullIdentifier;
     3733    return parseClass(context, FunctionNameRequirements::None, info);
     3734}
     3735
     3736template <typename LexerType>
    36743737template <class TreeBuilder> TreeExpression Parser<LexerType>::parseFunctionExpression(TreeBuilder& context)
    36753738{
     
    36833746    if (consume(TIMES))
    36843747        parseMode = SourceParseMode::GeneratorWrapperFunctionMode;
    3685     failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, parseMode, false, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Expression)), "Cannot parse function expression");
     3748    failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::None, parseMode, false, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Expression)), "Cannot parse function expression");
    36863749    return context.createFunctionExpr(location, functionInfo);
    36873750}
     
    37523815    case FUNCTION:
    37533816        return parseFunctionExpression(context);
    3754     case CLASSTOKEN: {
    3755         ParserClassInfo<TreeBuilder> info;
    3756         return parseClass(context, FunctionNoRequirements, info);
    3757     }
     3817    case CLASSTOKEN:
     3818        return parseClassExpression(context);
    37583819    case OPENBRACE:
    37593820        if (strictMode())
     
    40794140    ParserFunctionInfo<TreeBuilder> info;
    40804141    info.name = &m_vm->propertyNames->nullIdentifier;
    4081     failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::ArrowFunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, FunctionDefinitionType::Expression)), "Cannot parse arrow function expression");
     4142    failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::Unnamed, SourceParseMode::ArrowFunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, FunctionDefinitionType::Expression)), "Cannot parse arrow function expression");
    40824143
    40834144    return context.createArrowFunctionExpr(location, info);
  • trunk/Source/JavaScriptCore/parser/Parser.h

    r204714 r204842  
    7171enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode };
    7272enum FunctionBodyType { ArrowFunctionBodyExpression, ArrowFunctionBodyBlock, StandardFunctionBodyBlock };
    73 enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName };
     73enum class FunctionNameRequirements { None, Named, Unnamed };
    7474
    7575enum class DestructuringKind {
     
    102102typedef uint8_t DeclarationResultMask;
    103103
     104enum class DeclarationDefaultContext {
     105    Standard,
     106    ExportDefault,
     107};
    104108
    105109template <typename T> inline bool isEvalNode() { return false; }
     
    13561360    template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength = 0);
    13571361    enum class ExportType { Exported, NotExported };
    1358     template <class TreeBuilder> TreeStatement parseClassDeclaration(TreeBuilder&, ExportType = ExportType::NotExported);
    1359     template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported);
     1362    template <class TreeBuilder> TreeStatement parseClassDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard);
     1363    template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard);
    13601364    template <class TreeBuilder> TreeStatement parseVariableDeclaration(TreeBuilder&, DeclarationType, ExportType = ExportType::NotExported);
    13611365    template <class TreeBuilder> TreeStatement parseDoWhileStatement(TreeBuilder&);
     
    13891393    template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseObjectLiteral(TreeBuilder&);
    13901394    template <class TreeBuilder> NEVER_INLINE TreeExpression parseStrictObjectLiteral(TreeBuilder&);
     1395    template <class TreeBuilder> ALWAYS_INLINE TreeClassExpression parseClassExpression(TreeBuilder&);
    13911396    template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseFunctionExpression(TreeBuilder&);
    13921397    template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&);
     
    14171422
    14181423    enum class FunctionDefinitionType { Expression, Declaration, Method };
    1419     template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionRequirements, SourceParseMode, bool nameIsInContainingScope, ConstructorKind, SuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>&, FunctionDefinitionType);
     1424    template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionNameRequirements, SourceParseMode, bool nameIsInContainingScope, ConstructorKind, SuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>&, FunctionDefinitionType);
    14201425   
    14211426    ALWAYS_INLINE bool isArrowFunctionParameters();
     
    14241429    template <class TreeBuilder> NEVER_INLINE typename TreeBuilder::FormalParameterList createGeneratorParameters(TreeBuilder&);
    14251430
    1426     template <class TreeBuilder> NEVER_INLINE TreeClassExpression parseClass(TreeBuilder&, FunctionRequirements, ParserClassInfo<TreeBuilder>&);
     1431    template <class TreeBuilder> NEVER_INLINE TreeClassExpression parseClass(TreeBuilder&, FunctionNameRequirements, ParserClassInfo<TreeBuilder>&);
    14271432
    14281433    template <class TreeBuilder> NEVER_INLINE typename TreeBuilder::TemplateString parseTemplateString(TreeBuilder& context, bool isTemplateHead, typename LexerType::RawStringsBuildMode, bool& elementIsTail);
  • trunk/Source/JavaScriptCore/runtime/FunctionPrototype.cpp

    r200430 r204842  
    8383EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec)
    8484{
     85    VM& vm = exec->vm();
    8586    JSValue thisValue = exec->thisValue();
    8687    if (thisValue.inherits(JSFunction::info())) {
    8788        JSFunction* function = jsCast<JSFunction*>(thisValue);
    8889        if (function->isHostOrBuiltinFunction())
    89             return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(), "() {\n    [native code]\n}"));
     90            return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(vm), "() {\n    [native code]\n}"));
    9091
    9192        FunctionExecutable* executable = function->jsExecutable();
     
    100101            executable->parametersStartOffset(),
    101102            executable->parametersStartOffset() + executable->source().length());
    102         return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name(), source));
     103        return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name(vm), source));
    103104    }
    104105
  • trunk/Source/JavaScriptCore/runtime/JSFunction.cpp

    r204321 r204842  
    167167}
    168168
    169 String JSFunction::name()
     169String JSFunction::name(VM& vm)
    170170{
    171171    if (isHostFunction()) {
     
    173173        return executable->name();
    174174    }
    175     return jsExecutable()->name().string();
     175    const Identifier identifier = jsExecutable()->name();
     176    if (identifier == vm.propertyNames->builtinNames().starDefaultPrivateName())
     177        return emptyString();
     178    return identifier.string();
    176179}
    177180
     
    193196        return explicitName;
    194197   
    195     const String actualName = name();
     198    const String actualName = name(vm);
    196199    if (!actualName.isEmpty() || isHostOrBuiltinFunction())
    197200        return actualName;
     
    617620void JSFunction::reifyName(ExecState* exec)
    618621{
    619     String name = jsExecutable()->ecmaName().string();
     622    const Identifier& ecmaName = jsExecutable()->ecmaName();
     623    String name;
     624    // https://tc39.github.io/ecma262/#sec-exports-runtime-semantics-evaluation
     625    // When the ident is "*default*", we need to set "default" for the ecma name.
     626    // This "*default*" name is never shown to users.
     627    if (ecmaName == exec->propertyNames().builtinNames().starDefaultPrivateName())
     628        name = exec->propertyNames().defaultKeyword.string();
     629    else
     630        name = ecmaName.string();
    620631    reifyName(exec, name);
    621632}
  • trunk/Source/JavaScriptCore/runtime/JSFunction.h

    r204321 r204842  
    8282    static JSFunction* createBuiltinFunction(VM&, FunctionExecutable*, JSGlobalObject*, const String& name);
    8383
    84     JS_EXPORT_PRIVATE String name();
     84    JS_EXPORT_PRIVATE String name(VM&);
    8585    JS_EXPORT_PRIVATE String displayName(VM&);
    8686    const String calculatedDisplayName(VM&);
  • trunk/Source/JavaScriptCore/runtime/LazyClassStructure.cpp

    r200430 r204842  
    8181        name = internalFunction->name();
    8282    else if (JSFunction* function = jsDynamicCast<JSFunction*>(constructor))
    83         name = function->name();
     83        name = function->name(vm);
    8484    else
    8585        RELEASE_ASSERT_NOT_REACHED();
Note: See TracChangeset for help on using the changeset viewer.