Changeset 273107 in webkit


Ignore:
Timestamp:
Feb 18, 2021, 3:48:28 PM (5 years ago)
Author:
Caio Lima
Message:

[JSC] Implement private static method
https://bugs.webkit.org/show_bug.cgi?id=219181

Reviewed by Yusuke Suzuki.

JSTests:

  • stress/class-private-method-access.js: Added.
  • stress/private-accessor-static-non-static.js: Added.
  • stress/private-getter-inner-class.js:
  • stress/static-private-methods-and-accessor-inner-class.js: Added.
  • stress/static-private-methods-and-accessor-multiple-evaluation.js: Added.
  • stress/static-private-methods-and-accessors-postfix-node.js: Added.
  • stress/static-private-methods-and-accessors-prefix-node.js: Added.
  • test262/config.yaml:

Source/JavaScriptCore:

This patch is implementing static private methods and accessors
proposal based on https://github.com/tc39/proposal-static-class-features.
This implementation diverge a bit from private methods&accessors on the
brand check, because we are using a simpler way to perform static
brand checks. Since only the class constructor is allowed to access
its private methods and accessors, we save it on @privateClassBrand
on class lexical scope and compare it with the receiver of the static
private method (and accessors) using === operation.
While this genenrates more bytecodes than check_private_brand, we
don't need to perform a Structure transition to install a brand,
and avoid allocation of a private symbol. Since each evaluation of a
class generates a different constructor object, we preserve the semantics
that private methods are lexically scoped.

  • builtins/BuiltinNames.h:
  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitCreatePrivateBrand):
(JSC::BytecodeGenerator::emitInstallPrivateBrand):
(JSC::BytecodeGenerator::emitInstallPrivateClassBrand):
(JSC::BytecodeGenerator::emitGetPrivateBrand):
(JSC::BytecodeGenerator::emitCheckPrivateBrand):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::BaseDotNode::emitGetPropertyValue):
(JSC::BaseDotNode::emitPutProperty):
(JSC::PostfixNode::emitDot):
(JSC::PrefixNode::emitDot):
(JSC::ClassExprNode::emitBytecode):

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseClass):
(JSC::Parser<LexerType>::parseGetterSetter):

  • parser/Parser.h:

(JSC::Scope::declarePrivateMethod):
(JSC::Scope::declarePrivateAccessor):
(JSC::Scope::declarePrivateSetter):
(JSC::Scope::declarePrivateGetter):

  • parser/VariableEnvironment.cpp:

(JSC::VariableEnvironment::declarePrivateAccessor):
(JSC::VariableEnvironment::declarePrivateSetter):
(JSC::VariableEnvironment::declarePrivateGetter):
(JSC::VariableEnvironment::declarePrivateMethod):

  • parser/VariableEnvironment.h:

(JSC::PrivateNameEntry::isStatic const):
(JSC::VariableEnvironment::isEmpty const):
(JSC::VariableEnvironment::declareStaticPrivateMethod):
(JSC::VariableEnvironment::declarePrivateSetter):
(JSC::VariableEnvironment::declareStaticPrivateSetter):
(JSC::VariableEnvironment::declarePrivateGetter):
(JSC::VariableEnvironment::declareStaticPrivateGetter):
(JSC::VariableEnvironment::hasStaticPrivateMethodOrAccessor const):
(JSC::VariableEnvironment::hasInstancePrivateMethodOrAccessor const):
(JSC::VariableEnvironment::hasPrivateMethodOrAccessor const): Deleted.

Location:
trunk
Files:
6 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r273086 r273107  
     12021-02-18  Caio Lima  <[email protected]>
     2
     3        [JSC] Implement private static method
     4        https://bugs.webkit.org/show_bug.cgi?id=219181
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        * stress/class-private-method-access.js: Added.
     9        * stress/private-accessor-static-non-static.js: Added.
     10        * stress/private-getter-inner-class.js:
     11        * stress/static-private-methods-and-accessor-inner-class.js: Added.
     12        * stress/static-private-methods-and-accessor-multiple-evaluation.js: Added.
     13        * stress/static-private-methods-and-accessors-postfix-node.js: Added.
     14        * stress/static-private-methods-and-accessors-prefix-node.js: Added.
     15        * test262/config.yaml:
     16
    1172021-02-18  Michael Saboff  <[email protected]>
    218
  • trunk/JSTests/stress/private-getter-inner-class.js

    r272883 r273107  
    127127
    128128    assert.throws(TypeError, function() {
    129         innerB.method(c);
     129        C.prototype.method.call(innerB);
    130130    });
    131131})();
  • trunk/JSTests/test262/config.yaml

    r273086 r273107  
    88  class-static-fields-public: usePublicStaticClassFields
    99  class-static-fields-private: usePrivateStaticClassFields
     10  class-static-methods-private: usePrivateMethods
    1011  Intl.DateTimeFormat-dayPeriod: useIntlDateTimeFormatDayPeriod
    1112  SharedArrayBuffer: useSharedArrayBuffer
     
    2122    - legacy-regexp
    2223
    23     - class-static-methods-private
    2424    - cleanupSome
    2525    - host-gc-required
  • trunk/Source/JavaScriptCore/ChangeLog

    r273104 r273107  
     12021-02-18  Caio Lima  <[email protected]>
     2
     3        [JSC] Implement private static method
     4        https://bugs.webkit.org/show_bug.cgi?id=219181
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        This patch is implementing static private methods and accessors
     9        proposal based on https://github.com/tc39/proposal-static-class-features.
     10        This implementation diverge a bit from private methods&accessors on the
     11        brand check, because we are using a simpler way to perform static
     12        brand checks. Since only the class constructor is allowed to access
     13        its private methods and accessors, we save it on `@privateClassBrand`
     14        on class lexical scope and compare it with the receiver of the static
     15        private method (and accessors) using `===` operation.
     16        While this genenrates more bytecodes than `check_private_brand`, we
     17        don't need to perform a Structure transition to install a brand,
     18        and avoid allocation of a private symbol. Since each evaluation of a
     19        class generates a different constructor object, we preserve the semantics
     20        that private methods are lexically scoped.
     21
     22        * builtins/BuiltinNames.h:
     23        * bytecompiler/BytecodeGenerator.cpp:
     24        (JSC::BytecodeGenerator::emitCreatePrivateBrand):
     25        (JSC::BytecodeGenerator::emitInstallPrivateBrand):
     26        (JSC::BytecodeGenerator::emitInstallPrivateClassBrand):
     27        (JSC::BytecodeGenerator::emitGetPrivateBrand):
     28        (JSC::BytecodeGenerator::emitCheckPrivateBrand):
     29        * bytecompiler/BytecodeGenerator.h:
     30        * bytecompiler/NodesCodegen.cpp:
     31        (JSC::BaseDotNode::emitGetPropertyValue):
     32        (JSC::BaseDotNode::emitPutProperty):
     33        (JSC::PostfixNode::emitDot):
     34        (JSC::PrefixNode::emitDot):
     35        (JSC::ClassExprNode::emitBytecode):
     36        * parser/Parser.cpp:
     37        (JSC::Parser<LexerType>::parseClass):
     38        (JSC::Parser<LexerType>::parseGetterSetter):
     39        * parser/Parser.h:
     40        (JSC::Scope::declarePrivateMethod):
     41        (JSC::Scope::declarePrivateAccessor):
     42        (JSC::Scope::declarePrivateSetter):
     43        (JSC::Scope::declarePrivateGetter):
     44        * parser/VariableEnvironment.cpp:
     45        (JSC::VariableEnvironment::declarePrivateAccessor):
     46        (JSC::VariableEnvironment::declarePrivateSetter):
     47        (JSC::VariableEnvironment::declarePrivateGetter):
     48        (JSC::VariableEnvironment::declarePrivateMethod):
     49        * parser/VariableEnvironment.h:
     50        (JSC::PrivateNameEntry::isStatic const):
     51        (JSC::VariableEnvironment::isEmpty const):
     52        (JSC::VariableEnvironment::declareStaticPrivateMethod):
     53        (JSC::VariableEnvironment::declarePrivateSetter):
     54        (JSC::VariableEnvironment::declareStaticPrivateSetter):
     55        (JSC::VariableEnvironment::declarePrivateGetter):
     56        (JSC::VariableEnvironment::declareStaticPrivateGetter):
     57        (JSC::VariableEnvironment::hasStaticPrivateMethodOrAccessor const):
     58        (JSC::VariableEnvironment::hasInstancePrivateMethodOrAccessor const):
     59        (JSC::VariableEnvironment::hasPrivateMethodOrAccessor const): Deleted.
     60
    1612021-02-18  Daniel Kolesa  <[email protected]>
    262
  • trunk/Source/JavaScriptCore/builtins/BuiltinNames.h

    r272580 r273107  
    175175    macro(instanceFieldInitializer) \
    176176    macro(privateBrand) \
     177    macro(privateClassBrand) \
    177178    macro(hasOwnPropertyFunction) \
    178179    macro(createPrivateSymbol) \
    179     macro(entries) \
     180    macro(entries)
    180181
    181182
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r272883 r273107  
    27772777    Variable privateBrandVar = variable(propertyNames().builtinNames().privateBrandPrivateName());
    27782778
    2779     emitPutToScope(scope, privateBrandVar, newSymbol, DoNotThrowIfNotFound, InitializationMode::Initialization);
     2779    emitPutToScope(scope, privateBrandVar, newSymbol, DoNotThrowIfNotFound, InitializationMode::ConstInitialization);
    27802780}
    27812781
     
    27842784    Variable privateBrandVar = variable(propertyNames().builtinNames().privateBrandPrivateName());
    27852785    RefPtr<RegisterID> privateBrandVarScope = emitResolveScope(nullptr, privateBrandVar);
    2786     RegisterID* privateBrandSymbol = emitGetPrivateBrand(newTemporary(), privateBrandVarScope.get());
     2786    bool isStatic = false;
     2787    RegisterID* privateBrandSymbol = emitGetPrivateBrand(newTemporary(), privateBrandVarScope.get(), isStatic);
    27872788    OpSetPrivateBrand::emit(this, target, privateBrandSymbol);
    27882789}
    27892790
    2790 RegisterID* BytecodeGenerator::emitGetPrivateBrand(RegisterID* dst, RegisterID* scope)
    2791 {
    2792     Variable privateBrandVar = variable(propertyNames().builtinNames().privateBrandPrivateName());
     2791void BytecodeGenerator::emitInstallPrivateClassBrand(RegisterID* target)
     2792{
     2793    Variable privateBrandVar = variable(propertyNames().builtinNames().privateClassBrandPrivateName());
     2794    emitPutToScope(scopeRegister(), privateBrandVar, target, DoNotThrowIfNotFound, InitializationMode::ConstInitialization);
     2795}
     2796
     2797RegisterID* BytecodeGenerator::emitGetPrivateBrand(RegisterID* dst, RegisterID* scope, bool isStatic)
     2798{
     2799    Variable privateBrandVar = isStatic
     2800        ? variable(propertyNames().builtinNames().privateClassBrandPrivateName())
     2801        : variable(propertyNames().builtinNames().privateBrandPrivateName());
    27932802    return emitGetFromScope(dst, scope, privateBrandVar, ThrowIfNotFound);
    27942803}
     
    28002809}
    28012810
    2802 void BytecodeGenerator::emitCheckPrivateBrand(RegisterID* base, RegisterID* brandSymbol)
    2803 {
    2804     OpCheckPrivateBrand::emit(this, base, brandSymbol);
     2811void BytecodeGenerator::emitCheckPrivateBrand(RegisterID* base, RegisterID* brand, bool isStatic)
     2812{
     2813    if (isStatic) {
     2814        Ref<Label> brandCheckOkLabel = newLabel();
     2815        emitJumpIfTrue(emitEqualityOp<OpStricteq>(newTemporary(), base, brand), brandCheckOkLabel.get());
     2816        emitThrowTypeError("Cannot access static private method or acessor");
     2817        emitLabel(brandCheckOkLabel.get());
     2818        return;
     2819   
     2820    }
     2821    OpCheckPrivateBrand::emit(this, base, brand);
    28052822}
    28062823
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r272883 r273107  
    828828        void emitCreatePrivateBrand(RegisterID* dst, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
    829829        void emitInstallPrivateBrand(RegisterID* target);
    830         RegisterID* emitGetPrivateBrand(RegisterID* dst, RegisterID* scope);
    831         void emitCheckPrivateBrand(RegisterID* base, RegisterID* brand);
     830        void emitInstallPrivateClassBrand(RegisterID* target);
     831
     832        RegisterID* emitGetPrivateBrand(RegisterID* dst, RegisterID* scope, bool isStatic);
     833        void emitCheckPrivateBrand(RegisterID* base, RegisterID* brand, bool isStatic);
    832834
    833835        void emitSuperSamplerBegin();
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r272883 r273107  
    983983            RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
    984984
    985             RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
    986             generator.emitCheckPrivateBrand(base, privateBrandSymbol.get());
     985            RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get(), privateTraits.isStatic());
     986            generator.emitCheckPrivateBrand(base, privateBrandSymbol.get(), privateTraits.isStatic());
    987987
    988988            return generator.emitGetFromScope(dst, scope.get(), var, ThrowIfNotFound);
     
    993993            RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
    994994
    995             RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
    996             generator.emitCheckPrivateBrand(base, privateBrandSymbol.get());
     995            RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get(), privateTraits.isStatic());
     996            generator.emitCheckPrivateBrand(base, privateBrandSymbol.get(), privateTraits.isStatic());
    997997
    998998            RefPtr<RegisterID> getterSetterObj = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
     
    10081008            RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
    10091009
    1010             RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
    1011             generator.emitCheckPrivateBrand(base, privateBrandSymbol.get());
     1010            RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get(), privateTraits.isStatic());
     1011            generator.emitCheckPrivateBrand(base, privateBrandSymbol.get(), privateTraits.isStatic());
    10121012            generator.emitThrowTypeError("Trying to access an undefined private getter");
    10131013            return dst;
     
    10481048            RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
    10491049
    1050             RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
    1051             generator.emitCheckPrivateBrand(base, privateBrandSymbol.get());
     1050            RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get(), privateTraits.isStatic());
     1051            generator.emitCheckPrivateBrand(base, privateBrandSymbol.get(), privateTraits.isStatic());
    10521052
    10531053            RefPtr<RegisterID> getterSetterObj = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
     
    10651065            RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
    10661066
    1067             RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
    1068             generator.emitCheckPrivateBrand(base, privateBrandSymbol.get());
     1067            RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get(), privateTraits.isStatic());
     1068            generator.emitCheckPrivateBrand(base, privateBrandSymbol.get(), privateTraits.isStatic());
    10691069
    10701070            generator.emitThrowTypeError("Trying to access an undefined private setter");
     
    24132413            RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
    24142414
    2415             RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
    2416             generator.emitCheckPrivateBrand(base.get(), privateBrandSymbol.get());
     2415            RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get(), privateTraits.isStatic());
     2416            generator.emitCheckPrivateBrand(base.get(), privateBrandSymbol.get(), privateTraits.isStatic());
    24172417
    24182418            generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     
    24242424        RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
    24252425
    2426         RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
    2427         generator.emitCheckPrivateBrand(base.get(), privateBrandSymbol.get());
     2426        RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get(), privateTraits.isStatic());
     2427        generator.emitCheckPrivateBrand(base.get(), privateBrandSymbol.get(), privateTraits.isStatic());
    24282428
    24292429        RefPtr<RegisterID> value;
     
    27022702            RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
    27032703
    2704             RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
    2705             generator.emitCheckPrivateBrand(base.get(), privateBrandSymbol.get());
     2704            RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get(), privateTraits.isStatic());
     2705            generator.emitCheckPrivateBrand(base.get(), privateBrandSymbol.get(), privateTraits.isStatic());
    27062706
    27072707            generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     
    27132713        RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
    27142714
    2715         RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
    2716         generator.emitCheckPrivateBrand(base.get(), privateBrandSymbol.get());
     2715        RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get(), privateTraits.isStatic());
     2716        generator.emitCheckPrivateBrand(base.get(), privateBrandSymbol.get(), privateTraits.isStatic());
    27172717
    27182718        if (privateTraits.isGetter()) {
     
    51535153
    51545154    bool hasPrivateNames = !!m_lexicalVariables.privateNamesSize();
    5155     bool shouldEmitPrivateBrand = m_lexicalVariables.hasPrivateMethodOrAccessor();
     5155    bool shouldEmitPrivateBrand = m_lexicalVariables.hasInstancePrivateMethodOrAccessor();
     5156    bool shouldInstallBrandOnConstructor = m_lexicalVariables.hasStaticPrivateMethodOrAccessor();
    51565157    if (hasPrivateNames)
    51575158        generator.pushPrivateAccessNames(m_lexicalVariables.privateNameEnvironment());
     
    52445245        generator.emitPutToScope(scope.get(), classNameVar, constructor.get(), ThrowIfNotFound, InitializationMode::Initialization);
    52455246    }
     5247
     5248    if (shouldInstallBrandOnConstructor)
     5249        generator.emitInstallPrivateClassBrand(constructor.get());
    52465250
    52475251    if (!staticFieldLocations.isEmpty()) {
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r272883 r273107  
    28822882    bool declaresPrivateMethod = false;
    28832883    bool declaresPrivateAccessor = false;
     2884    bool declaresStaticPrivateMethod = false;
     2885    bool declaresStaticPrivateAccessor = false;
    28842886    next();
    28852887
     
    30083010            next();
    30093011            if (Options::usePrivateMethods() && match(OPENPAREN)) {
    3010                 semanticFailIfTrue(tag == ClassElementTag::Static, "Cannot declare a static private method");
    3011                 semanticFailIfTrue(classScope->declarePrivateMethod(*ident) & DeclarationResult::InvalidDuplicateDeclaration, "Cannot declare private method twice");
    3012                 declaresPrivateMethod = true;
     3012                semanticFailIfTrue(classScope->declarePrivateMethod(*ident, tag) & DeclarationResult::InvalidDuplicateDeclaration, "Cannot declare private method twice");
     3013                semanticFailIfTrue(tag == ClassElementTag::Static && *ident == propertyNames.constructorPrivateField, "Cannot declare a static private method named 'constructor'");
     3014
     3015                if (tag == ClassElementTag::Static)
     3016                    declaresStaticPrivateAccessor = true;
     3017                else
     3018                    declaresPrivateMethod = true;
     3019
    30133020                type = static_cast<PropertyNode::Type>(type | PropertyNode::PrivateMethod);
    30143021                break;
     
    30303037            if (Options::usePrivateMethods() && match(PRIVATENAME)) {
    30313038                ident = m_token.m_data.ident;
    3032                 if (isSetter) {
    3033                     semanticFailIfTrue(classScope->declarePrivateSetter(*ident) & DeclarationResult::InvalidDuplicateDeclaration, "Declared private setter with an already used name");
     3039
     3040                auto declarationResult = isSetter ? classScope->declarePrivateSetter(*ident, tag) : classScope->declarePrivateGetter(*ident, tag);
     3041                semanticFailIfTrue(declarationResult & DeclarationResult::InvalidDuplicateDeclaration, "Declared private setter with an already used name");
     3042                if (tag == ClassElementTag::Static) {
     3043                    semanticFailIfTrue(declarationResult & DeclarationResult::InvalidPrivateStaticNonStatic, "Cannot declare a private static ", (isSetter ? "setter" : "getter")  , " if there is a non-static private ", (isSetter ? "getter" : "setter"), " with used name");
     3044                    declaresStaticPrivateAccessor = true;
     3045                } else {
     3046                    semanticFailIfTrue(declarationResult & DeclarationResult::InvalidPrivateStaticNonStatic, "Cannot declare a private non-static ", (isSetter ? "setter" : "getter"), " if there is a static private ", (isSetter ? "getter" : "setter"), " with used name");
    30343047                    declaresPrivateAccessor = true;
     3048                }
     3049
     3050                if (isSetter)
    30353051                    type = static_cast<PropertyNode::Type>(type | PropertyNode::PrivateSetter);
    3036                 } else {
    3037                     semanticFailIfTrue(classScope->declarePrivateGetter(*ident) & DeclarationResult::InvalidDuplicateDeclaration, "Declared private getter with an already used name");
    3038                     declaresPrivateAccessor = true;
     3052                else
    30393053                    type = static_cast<PropertyNode::Type>(type | PropertyNode::PrivateGetter);
    3040                 }
    30413054            } else {
    30423055                type = static_cast<PropertyNode::Type>(type & ~PropertyNode::Constant);
     
    31263139    if constexpr (std::is_same_v<TreeBuilder, ASTBuilder>) {
    31273140        if (classElements)
    3128             classElements->setHasPrivateAccessors(declaresPrivateAccessor);
     3141            classElements->setHasPrivateAccessors(declaresPrivateAccessor || declaresStaticPrivateAccessor);
     3142    }
     3143
     3144    if (declaresStaticPrivateMethod || declaresPrivateAccessor) {
     3145        Identifier privateClassBrandIdentifier = m_vm.propertyNames->builtinNames().privateClassBrandPrivateName();
     3146        DeclarationResultMask declarationResult = classScope->declareLexicalVariable(&privateClassBrandIdentifier, true);
     3147        ASSERT_UNUSED(declarationResult, declarationResult == DeclarationResult::Valid);
     3148        classScope->useVariable(&privateClassBrandIdentifier, false);
     3149        classScope->addClosedVariableCandidateUnconditionally(privateClassBrandIdentifier.impl());
    31293150    }
    31303151
     
    44574478            "Cannot declare a getter or setter named 'constructor'");
    44584479
    4459         if (match(PRIVATENAME)) {
     4480        if (match(PRIVATENAME))
    44604481            semanticFailIfTrue(tag == ClassElementTag::No, "Cannot declare a private setter or getter outside a class");
    4461             semanticFailIfTrue(tag == ClassElementTag::Static, "Cannot declare a private setter or getter as static");
    4462         }
    44634482        next();
    44644483    } else if (match(DOUBLE) || match(INTEGER)) {
  • trunk/Source/JavaScriptCore/parser/Parser.h

    r272883 r273107  
    9595    Valid = 0,
    9696    InvalidStrictMode = 1 << 0,
    97     InvalidDuplicateDeclaration = 1 << 1
     97    InvalidDuplicateDeclaration = 1 << 1,
     98    InvalidPrivateStaticNonStatic = 1 << 2
    9899};
    99100
     
    501502    }
    502503
    503     DeclarationResultMask declarePrivateMethod(const Identifier& ident)
     504    DeclarationResultMask declarePrivateMethod(const Identifier& ident, ClassElementTag tag)
    504505    {
    505506        ASSERT(m_allowsLexicalDeclarations);
    506507        DeclarationResultMask result = DeclarationResult::Valid;
    507         bool addResult = m_lexicalVariables.declarePrivateMethod(ident);
     508        bool addResult = tag == ClassElementTag::Static ? m_lexicalVariables.declareStaticPrivateMethod(ident) : m_lexicalVariables.declarePrivateMethod(ident);
    508509
    509510        if (!addResult) {
     
    512513        }
    513514
    514         useVariable(&ident, false);
    515         addClosedVariableCandidateUnconditionally(ident.impl());
    516 
    517515        return result;
    518516    }
    519517
    520     DeclarationResultMask declarePrivateSetter(const Identifier& ident)
     518    enum class PrivateAccessorType { Setter, Getter };
     519
     520    DeclarationResultMask declarePrivateAccessor(const Identifier& ident, ClassElementTag tag, PrivateAccessorType accessorType)
     521    {
     522        DeclarationResultMask result = DeclarationResult::Valid;
     523        VariableEnvironment::PrivateDeclarationResult addResult;
     524        if (accessorType == PrivateAccessorType::Setter)
     525            addResult = tag == ClassElementTag::Static ? m_lexicalVariables.declareStaticPrivateSetter(ident) : m_lexicalVariables.declarePrivateSetter(ident);
     526        else
     527            addResult = tag == ClassElementTag::Static ? m_lexicalVariables.declareStaticPrivateGetter(ident) : m_lexicalVariables.declarePrivateGetter(ident);
     528
     529        if (addResult == VariableEnvironment::PrivateDeclarationResult::DuplicatedName)
     530            result |= DeclarationResult::InvalidDuplicateDeclaration;
     531
     532        if (addResult == VariableEnvironment::PrivateDeclarationResult::InvalidStaticNonStatic)
     533            result |= DeclarationResult::InvalidPrivateStaticNonStatic;
     534
     535        return result;
     536    }
     537
     538    DeclarationResultMask declarePrivateSetter(const Identifier& ident, ClassElementTag tag)
    521539    {
    522540        ASSERT(m_allowsLexicalDeclarations);
    523         DeclarationResultMask result = DeclarationResult::Valid;
    524         bool addResult = m_lexicalVariables.declarePrivateSetter(ident);
    525 
    526         if (!addResult) {
    527             result |= DeclarationResult::InvalidDuplicateDeclaration;
    528             return result;
    529         }
    530 
    531         return result;
    532     }
    533 
    534     DeclarationResultMask declarePrivateGetter(const Identifier& ident)
     541        return declarePrivateAccessor(ident, tag, PrivateAccessorType::Setter);
     542    }
     543
     544    DeclarationResultMask declarePrivateGetter(const Identifier& ident, ClassElementTag tag)
    535545    {
    536546        ASSERT(m_allowsLexicalDeclarations);
    537         DeclarationResultMask result = DeclarationResult::Valid;
    538         bool addResult = m_lexicalVariables.declarePrivateGetter(ident);
    539 
    540         if (!addResult) {
    541             result |= DeclarationResult::InvalidDuplicateDeclaration;
    542             return result;
    543         }
    544 
    545         return result;
     547        return declarePrivateAccessor(ident, tag, PrivateAccessorType::Getter);
    546548    }
    547549
  • trunk/Source/JavaScriptCore/parser/VariableEnvironment.cpp

    r272883 r273107  
    105105}
    106106
    107 bool VariableEnvironment::declarePrivateAccessor(const RefPtr<UniquedStringImpl>& identifier, PrivateNameEntry::Traits accessorTraits)
     107VariableEnvironment::PrivateDeclarationResult VariableEnvironment::declarePrivateAccessor(const RefPtr<UniquedStringImpl>& identifier, PrivateNameEntry accessorTraits)
    108108{
    109109    if (!m_rareData)
     
    113113
    114114    if (findResult == m_rareData->m_privateNames.end()) {
    115         PrivateNameEntry meta(PrivateNameEntry::Traits::IsDeclared | accessorTraits);
     115        PrivateNameEntry meta(PrivateNameEntry::Traits::IsDeclared | accessorTraits.bits());
    116116
    117117        auto entry = VariableEnvironmentEntry();
    118         if (accessorTraits == PrivateNameEntry::Traits::IsSetter)
     118        if (accessorTraits.isSetter())
    119119            entry.setIsPrivateSetter();
    120120        else {
    121             ASSERT(accessorTraits == PrivateNameEntry::Traits::IsGetter);
     121            ASSERT(accessorTraits.isGetter());
    122122            entry.setIsPrivateGetter();
    123123        }
     
    126126        m_map.add(identifier, entry);
    127127
    128         auto addResult = m_rareData->m_privateNames.add(identifier, meta);
    129         return addResult.isNewEntry;
     128        m_rareData->m_privateNames.add(identifier, meta);
     129        return PrivateDeclarationResult::Success;
    130130    }
    131131
    132132    PrivateNameEntry currentEntry = findResult->value;
    133133    if (currentEntry.isDeclared()) {
    134         if ((accessorTraits == PrivateNameEntry::Traits::IsSetter && !currentEntry.isGetter())
    135             || (accessorTraits == PrivateNameEntry::Traits::IsGetter && !currentEntry.isSetter()))
    136             return false; // Error: declaring a duplicate private accessor.
    137 
    138         PrivateNameEntry meta(currentEntry.bits() | accessorTraits);
     134        if ((accessorTraits.isSetter() && !currentEntry.isGetter())
     135            || (accessorTraits.isGetter() && !currentEntry.isSetter()))
     136            return PrivateDeclarationResult::DuplicatedName;
     137
     138        if (accessorTraits.isStatic() != currentEntry.isStatic())
     139            return PrivateDeclarationResult::InvalidStaticNonStatic;
     140
     141        PrivateNameEntry meta(currentEntry.bits() | accessorTraits.bits());
    139142        m_rareData->m_privateNames.set(identifier, meta);
    140143
    141144        auto entryIterator = m_map.find(identifier);
    142145        ASSERT(entryIterator != m_map.end());
    143         if (accessorTraits == PrivateNameEntry::Traits::IsSetter)
     146        if (accessorTraits.isSetter())
    144147            entryIterator->value.setIsPrivateSetter();
    145148        else {
    146             ASSERT(accessorTraits == PrivateNameEntry::Traits::IsGetter);
     149            ASSERT(accessorTraits.isGetter());
    147150            entryIterator->value.setIsPrivateGetter();
    148151        }
    149152
    150         return true;
     153        return PrivateDeclarationResult::Success;
    151154    }
    152155
    153156    // it was previously used, mark it as declared.
    154157    auto entry = VariableEnvironmentEntry();
    155     if (accessorTraits == PrivateNameEntry::Traits::IsSetter)
     158    if (accessorTraits.isSetter())
    156159        entry.setIsPrivateSetter();
    157160    else {
    158         ASSERT(accessorTraits == PrivateNameEntry::Traits::IsGetter);
     161        ASSERT(accessorTraits.isGetter());
    159162        entry.setIsPrivateGetter();
    160163    }
     
    163166    m_map.add(identifier, entry);
    164167
    165     PrivateNameEntry newEntry(currentEntry.bits() | PrivateNameEntry::Traits::IsDeclared | accessorTraits);
     168    PrivateNameEntry newEntry(currentEntry.bits() | PrivateNameEntry::Traits::IsDeclared | accessorTraits.bits());
    166169    m_rareData->m_privateNames.set(identifier, newEntry);
    167     return true;
    168 
    169 }
    170 
    171 bool VariableEnvironment::declarePrivateSetter(const RefPtr<UniquedStringImpl>& identifier)
    172 {
    173     return declarePrivateAccessor(identifier, PrivateNameEntry::Traits::IsSetter);
    174 }
    175 
    176 bool VariableEnvironment::declarePrivateGetter(const RefPtr<UniquedStringImpl>& identifier)
    177 {
    178     return declarePrivateAccessor(identifier, PrivateNameEntry::Traits::IsGetter);
    179 }
    180 
    181 bool VariableEnvironment::declarePrivateMethod(const RefPtr<UniquedStringImpl>& identifier)
     170    return PrivateDeclarationResult::Success;
     171}
     172
     173VariableEnvironment::PrivateDeclarationResult VariableEnvironment::declarePrivateSetter(const RefPtr<UniquedStringImpl>& identifier, PrivateNameEntry::Traits modifierTraits)
     174{
     175    return declarePrivateAccessor(identifier, PrivateNameEntry(PrivateNameEntry::Traits::IsSetter | modifierTraits));
     176}
     177
     178VariableEnvironment::PrivateDeclarationResult VariableEnvironment::declarePrivateGetter(const RefPtr<UniquedStringImpl>& identifier, PrivateNameEntry::Traits modifierTraits)
     179{
     180    return declarePrivateAccessor(identifier, PrivateNameEntry(PrivateNameEntry::Traits::IsGetter | modifierTraits));
     181}
     182
     183bool VariableEnvironment::declarePrivateMethod(const RefPtr<UniquedStringImpl>& identifier, PrivateNameEntry::Traits addionalTraits)
    182184{
    183185    if (!m_rareData)
     
    187189
    188190    if (findResult == m_rareData->m_privateNames.end()) {
    189         PrivateNameEntry meta(PrivateNameEntry::Traits::IsDeclared | PrivateNameEntry::Traits::IsMethod);
     191        PrivateNameEntry meta(PrivateNameEntry::Traits::IsDeclared | PrivateNameEntry::Traits::IsMethod | addionalTraits);
    190192
    191193        auto entry = VariableEnvironmentEntry();
     
    209211
    210212    // it was previously used, mark it as declared.
    211     PrivateNameEntry meta(PrivateNameEntry::Traits::IsDeclared | PrivateNameEntry::Traits::IsUsed | PrivateNameEntry::Traits::IsMethod);
     213    PrivateNameEntry meta(PrivateNameEntry::Traits::IsDeclared | PrivateNameEntry::Traits::IsUsed | PrivateNameEntry::Traits::IsMethod | addionalTraits);
    212214    auto addResult = m_rareData->m_privateNames.set(identifier, meta);
    213215    return !addResult.isNewEntry;
  • trunk/Source/JavaScriptCore/parser/VariableEnvironment.h

    r272883 r273107  
    111111    ALWAYS_INLINE bool isGetter() const { return m_bits & IsGetter; }
    112112    ALWAYS_INLINE bool isField() const { return !isPrivateMethodOrAcessor(); }
     113    ALWAYS_INLINE bool isStatic() const { return m_bits & IsStatic; }
    113114
    114115    bool isPrivateMethodOrAcessor() const { return isMethod() || isSetter() || isGetter(); }
     
    131132        IsGetter = 1 << 3,
    132133        IsSetter = 1 << 4,
     134        IsStatic = 1 << 5,
    133135    };
    134136
     
    197199
    198200    bool isEverythingCaptured() const { return m_isEverythingCaptured; }
    199     bool isEmpty() const { return !m_map.size(); }
     201    bool isEmpty() const { return !m_map.size() && !privateNamesSize(); }
    200202
    201203    using PrivateNamesRange = WTF::IteratorRange<PrivateNameEnvironment::iterator>;
     
    205207
    206208    bool declarePrivateMethod(const Identifier& identifier) { return declarePrivateMethod(identifier.impl()); }
    207     bool declarePrivateMethod(const RefPtr<UniquedStringImpl>& identifier);
    208 
    209     bool declarePrivateAccessor(const RefPtr<UniquedStringImpl>&, PrivateNameEntry::Traits);
    210 
    211     bool declarePrivateSetter(const Identifier& identifier) { return declarePrivateSetter(identifier.impl()); }
    212     bool declarePrivateSetter(const RefPtr<UniquedStringImpl>& identifier);
    213 
    214     bool declarePrivateGetter(const Identifier& identifier) { return declarePrivateGetter(identifier.impl()); }
    215     bool declarePrivateGetter(const RefPtr<UniquedStringImpl>& identifier);
     209    bool declarePrivateMethod(const RefPtr<UniquedStringImpl>& identifier, PrivateNameEntry::Traits addionalTraits = PrivateNameEntry::Traits::None);
     210
     211    enum class PrivateDeclarationResult {
     212        Success,
     213        DuplicatedName,
     214        InvalidStaticNonStatic
     215    };
     216
     217    PrivateDeclarationResult declarePrivateAccessor(const RefPtr<UniquedStringImpl>&, PrivateNameEntry accessorTraits);
     218   
     219    bool declareStaticPrivateMethod(const Identifier& identifier)
     220    {
     221        return declarePrivateMethod(identifier.impl(), static_cast<PrivateNameEntry::Traits>(PrivateNameEntry::Traits::IsMethod | PrivateNameEntry::Traits::IsStatic));
     222    }
     223
     224    PrivateDeclarationResult declarePrivateSetter(const Identifier& identifier) { return declarePrivateSetter(identifier.impl()); }
     225    PrivateDeclarationResult declareStaticPrivateSetter(const Identifier& identifier) { return declarePrivateSetter(identifier.impl(), PrivateNameEntry::Traits::IsStatic); }
     226    PrivateDeclarationResult declarePrivateSetter(const RefPtr<UniquedStringImpl>& identifier, PrivateNameEntry::Traits modifierTraits = PrivateNameEntry::Traits::None);
     227
     228    PrivateDeclarationResult declarePrivateGetter(const Identifier& identifier) { return declarePrivateGetter(identifier.impl()); }
     229    PrivateDeclarationResult declareStaticPrivateGetter(const Identifier& identifier) { return declarePrivateGetter(identifier.impl(), PrivateNameEntry::Traits::IsStatic); }
     230    PrivateDeclarationResult declarePrivateGetter(const RefPtr<UniquedStringImpl>& identifier, PrivateNameEntry::Traits modifierTraits = PrivateNameEntry::Traits::None);
    216231
    217232    Map::AddResult declarePrivateField(const RefPtr<UniquedStringImpl>& identifier)
     
    254269    }
    255270
    256     ALWAYS_INLINE bool hasPrivateMethodOrAccessor() const
     271    ALWAYS_INLINE bool hasStaticPrivateMethodOrAccessor() const
    257272    {
    258273        if (!m_rareData)
     
    260275
    261276        for (auto entry : privateNames()) {
    262             if (entry.value.isPrivateMethodOrAcessor())
     277            if (entry.value.isPrivateMethodOrAcessor() && entry.value.isStatic())
    263278                return true;
    264279        }
    265 
     280       
     281        return false;
     282    }
     283   
     284    ALWAYS_INLINE bool hasInstancePrivateMethodOrAccessor() const
     285    {
     286        if (!m_rareData)
     287            return false;
     288       
     289        for (auto entry : privateNames()) {
     290            if (entry.value.isPrivateMethodOrAcessor() && !entry.value.isStatic())
     291                return true;
     292        }
     293       
    266294        return false;
    267295    }
Note: See TracChangeset for help on using the changeset viewer.