Changeset 273107 in webkit
- Timestamp:
- Feb 18, 2021, 3:48:28 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 6 added
- 12 edited
-
JSTests/ChangeLog (modified) (1 diff)
-
JSTests/stress/class-private-method-access.js (added)
-
JSTests/stress/private-accessor-static-non-static.js (added)
-
JSTests/stress/private-getter-inner-class.js (modified) (1 diff)
-
JSTests/stress/static-private-methods-and-accessor-inner-class.js (added)
-
JSTests/stress/static-private-methods-and-accessor-multiple-evaluation.js (added)
-
JSTests/stress/static-private-methods-and-accessors-postfix-node.js (added)
-
JSTests/stress/static-private-methods-and-accessors-prefix-node.js (added)
-
JSTests/test262/config.yaml (modified) (2 diffs)
-
Source/JavaScriptCore/ChangeLog (modified) (1 diff)
-
Source/JavaScriptCore/builtins/BuiltinNames.h (modified) (1 diff)
-
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (modified) (1 diff)
-
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (modified) (11 diffs)
-
Source/JavaScriptCore/parser/Parser.cpp (modified) (5 diffs)
-
Source/JavaScriptCore/parser/Parser.h (modified) (3 diffs)
-
Source/JavaScriptCore/parser/VariableEnvironment.cpp (modified) (6 diffs)
-
Source/JavaScriptCore/parser/VariableEnvironment.h (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r273086 r273107 1 2021-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 1 17 2021-02-18 Michael Saboff <[email protected]> 2 18 -
trunk/JSTests/stress/private-getter-inner-class.js
r272883 r273107 127 127 128 128 assert.throws(TypeError, function() { 129 innerB.method(c);129 C.prototype.method.call(innerB); 130 130 }); 131 131 })(); -
trunk/JSTests/test262/config.yaml
r273086 r273107 8 8 class-static-fields-public: usePublicStaticClassFields 9 9 class-static-fields-private: usePrivateStaticClassFields 10 class-static-methods-private: usePrivateMethods 10 11 Intl.DateTimeFormat-dayPeriod: useIntlDateTimeFormatDayPeriod 11 12 SharedArrayBuffer: useSharedArrayBuffer … … 21 22 - legacy-regexp 22 23 23 - class-static-methods-private24 24 - cleanupSome 25 25 - host-gc-required -
trunk/Source/JavaScriptCore/ChangeLog
r273104 r273107 1 2021-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 1 61 2021-02-18 Daniel Kolesa <[email protected]> 2 62 -
trunk/Source/JavaScriptCore/builtins/BuiltinNames.h
r272580 r273107 175 175 macro(instanceFieldInitializer) \ 176 176 macro(privateBrand) \ 177 macro(privateClassBrand) \ 177 178 macro(hasOwnPropertyFunction) \ 178 179 macro(createPrivateSymbol) \ 179 macro(entries) \180 macro(entries) 180 181 181 182 -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r272883 r273107 2777 2777 Variable privateBrandVar = variable(propertyNames().builtinNames().privateBrandPrivateName()); 2778 2778 2779 emitPutToScope(scope, privateBrandVar, newSymbol, DoNotThrowIfNotFound, InitializationMode:: Initialization);2779 emitPutToScope(scope, privateBrandVar, newSymbol, DoNotThrowIfNotFound, InitializationMode::ConstInitialization); 2780 2780 } 2781 2781 … … 2784 2784 Variable privateBrandVar = variable(propertyNames().builtinNames().privateBrandPrivateName()); 2785 2785 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); 2787 2788 OpSetPrivateBrand::emit(this, target, privateBrandSymbol); 2788 2789 } 2789 2790 2790 RegisterID* BytecodeGenerator::emitGetPrivateBrand(RegisterID* dst, RegisterID* scope) 2791 { 2792 Variable privateBrandVar = variable(propertyNames().builtinNames().privateBrandPrivateName()); 2791 void BytecodeGenerator::emitInstallPrivateClassBrand(RegisterID* target) 2792 { 2793 Variable privateBrandVar = variable(propertyNames().builtinNames().privateClassBrandPrivateName()); 2794 emitPutToScope(scopeRegister(), privateBrandVar, target, DoNotThrowIfNotFound, InitializationMode::ConstInitialization); 2795 } 2796 2797 RegisterID* BytecodeGenerator::emitGetPrivateBrand(RegisterID* dst, RegisterID* scope, bool isStatic) 2798 { 2799 Variable privateBrandVar = isStatic 2800 ? variable(propertyNames().builtinNames().privateClassBrandPrivateName()) 2801 : variable(propertyNames().builtinNames().privateBrandPrivateName()); 2793 2802 return emitGetFromScope(dst, scope, privateBrandVar, ThrowIfNotFound); 2794 2803 } … … 2800 2809 } 2801 2810 2802 void BytecodeGenerator::emitCheckPrivateBrand(RegisterID* base, RegisterID* brandSymbol) 2803 { 2804 OpCheckPrivateBrand::emit(this, base, brandSymbol); 2811 void 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); 2805 2822 } 2806 2823 -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r272883 r273107 828 828 void emitCreatePrivateBrand(RegisterID* dst, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); 829 829 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); 832 834 833 835 void emitSuperSamplerBegin(); -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r272883 r273107 983 983 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); 984 984 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()); 987 987 988 988 return generator.emitGetFromScope(dst, scope.get(), var, ThrowIfNotFound); … … 993 993 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); 994 994 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()); 997 997 998 998 RefPtr<RegisterID> getterSetterObj = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound); … … 1008 1008 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); 1009 1009 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()); 1012 1012 generator.emitThrowTypeError("Trying to access an undefined private getter"); 1013 1013 return dst; … … 1048 1048 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); 1049 1049 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()); 1052 1052 1053 1053 RefPtr<RegisterID> getterSetterObj = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound); … … 1065 1065 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); 1066 1066 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()); 1069 1069 1070 1070 generator.emitThrowTypeError("Trying to access an undefined private setter"); … … 2413 2413 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); 2414 2414 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()); 2417 2417 2418 2418 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); … … 2424 2424 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); 2425 2425 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()); 2428 2428 2429 2429 RefPtr<RegisterID> value; … … 2702 2702 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); 2703 2703 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()); 2706 2706 2707 2707 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); … … 2713 2713 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); 2714 2714 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()); 2717 2717 2718 2718 if (privateTraits.isGetter()) { … … 5153 5153 5154 5154 bool hasPrivateNames = !!m_lexicalVariables.privateNamesSize(); 5155 bool shouldEmitPrivateBrand = m_lexicalVariables.hasPrivateMethodOrAccessor(); 5155 bool shouldEmitPrivateBrand = m_lexicalVariables.hasInstancePrivateMethodOrAccessor(); 5156 bool shouldInstallBrandOnConstructor = m_lexicalVariables.hasStaticPrivateMethodOrAccessor(); 5156 5157 if (hasPrivateNames) 5157 5158 generator.pushPrivateAccessNames(m_lexicalVariables.privateNameEnvironment()); … … 5244 5245 generator.emitPutToScope(scope.get(), classNameVar, constructor.get(), ThrowIfNotFound, InitializationMode::Initialization); 5245 5246 } 5247 5248 if (shouldInstallBrandOnConstructor) 5249 generator.emitInstallPrivateClassBrand(constructor.get()); 5246 5250 5247 5251 if (!staticFieldLocations.isEmpty()) { -
trunk/Source/JavaScriptCore/parser/Parser.cpp
r272883 r273107 2882 2882 bool declaresPrivateMethod = false; 2883 2883 bool declaresPrivateAccessor = false; 2884 bool declaresStaticPrivateMethod = false; 2885 bool declaresStaticPrivateAccessor = false; 2884 2886 next(); 2885 2887 … … 3008 3010 next(); 3009 3011 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 3013 3020 type = static_cast<PropertyNode::Type>(type | PropertyNode::PrivateMethod); 3014 3021 break; … … 3030 3037 if (Options::usePrivateMethods() && match(PRIVATENAME)) { 3031 3038 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"); 3034 3047 declaresPrivateAccessor = true; 3048 } 3049 3050 if (isSetter) 3035 3051 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 3039 3053 type = static_cast<PropertyNode::Type>(type | PropertyNode::PrivateGetter); 3040 }3041 3054 } else { 3042 3055 type = static_cast<PropertyNode::Type>(type & ~PropertyNode::Constant); … … 3126 3139 if constexpr (std::is_same_v<TreeBuilder, ASTBuilder>) { 3127 3140 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()); 3129 3150 } 3130 3151 … … 4457 4478 "Cannot declare a getter or setter named 'constructor'"); 4458 4479 4459 if (match(PRIVATENAME)) {4480 if (match(PRIVATENAME)) 4460 4481 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 }4463 4482 next(); 4464 4483 } else if (match(DOUBLE) || match(INTEGER)) { -
trunk/Source/JavaScriptCore/parser/Parser.h
r272883 r273107 95 95 Valid = 0, 96 96 InvalidStrictMode = 1 << 0, 97 InvalidDuplicateDeclaration = 1 << 1 97 InvalidDuplicateDeclaration = 1 << 1, 98 InvalidPrivateStaticNonStatic = 1 << 2 98 99 }; 99 100 … … 501 502 } 502 503 503 DeclarationResultMask declarePrivateMethod(const Identifier& ident )504 DeclarationResultMask declarePrivateMethod(const Identifier& ident, ClassElementTag tag) 504 505 { 505 506 ASSERT(m_allowsLexicalDeclarations); 506 507 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); 508 509 509 510 if (!addResult) { … … 512 513 } 513 514 514 useVariable(&ident, false);515 addClosedVariableCandidateUnconditionally(ident.impl());516 517 515 return result; 518 516 } 519 517 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) 521 539 { 522 540 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) 535 545 { 536 546 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); 546 548 } 547 549 -
trunk/Source/JavaScriptCore/parser/VariableEnvironment.cpp
r272883 r273107 105 105 } 106 106 107 bool VariableEnvironment::declarePrivateAccessor(const RefPtr<UniquedStringImpl>& identifier, PrivateNameEntry::TraitsaccessorTraits)107 VariableEnvironment::PrivateDeclarationResult VariableEnvironment::declarePrivateAccessor(const RefPtr<UniquedStringImpl>& identifier, PrivateNameEntry accessorTraits) 108 108 { 109 109 if (!m_rareData) … … 113 113 114 114 if (findResult == m_rareData->m_privateNames.end()) { 115 PrivateNameEntry meta(PrivateNameEntry::Traits::IsDeclared | accessorTraits );115 PrivateNameEntry meta(PrivateNameEntry::Traits::IsDeclared | accessorTraits.bits()); 116 116 117 117 auto entry = VariableEnvironmentEntry(); 118 if (accessorTraits == PrivateNameEntry::Traits::IsSetter)118 if (accessorTraits.isSetter()) 119 119 entry.setIsPrivateSetter(); 120 120 else { 121 ASSERT(accessorTraits == PrivateNameEntry::Traits::IsGetter);121 ASSERT(accessorTraits.isGetter()); 122 122 entry.setIsPrivateGetter(); 123 123 } … … 126 126 m_map.add(identifier, entry); 127 127 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; 130 130 } 131 131 132 132 PrivateNameEntry currentEntry = findResult->value; 133 133 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()); 139 142 m_rareData->m_privateNames.set(identifier, meta); 140 143 141 144 auto entryIterator = m_map.find(identifier); 142 145 ASSERT(entryIterator != m_map.end()); 143 if (accessorTraits == PrivateNameEntry::Traits::IsSetter)146 if (accessorTraits.isSetter()) 144 147 entryIterator->value.setIsPrivateSetter(); 145 148 else { 146 ASSERT(accessorTraits == PrivateNameEntry::Traits::IsGetter);149 ASSERT(accessorTraits.isGetter()); 147 150 entryIterator->value.setIsPrivateGetter(); 148 151 } 149 152 150 return true;153 return PrivateDeclarationResult::Success; 151 154 } 152 155 153 156 // it was previously used, mark it as declared. 154 157 auto entry = VariableEnvironmentEntry(); 155 if (accessorTraits == PrivateNameEntry::Traits::IsSetter)158 if (accessorTraits.isSetter()) 156 159 entry.setIsPrivateSetter(); 157 160 else { 158 ASSERT(accessorTraits == PrivateNameEntry::Traits::IsGetter);161 ASSERT(accessorTraits.isGetter()); 159 162 entry.setIsPrivateGetter(); 160 163 } … … 163 166 m_map.add(identifier, entry); 164 167 165 PrivateNameEntry newEntry(currentEntry.bits() | PrivateNameEntry::Traits::IsDeclared | accessorTraits );168 PrivateNameEntry newEntry(currentEntry.bits() | PrivateNameEntry::Traits::IsDeclared | accessorTraits.bits()); 166 169 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 173 VariableEnvironment::PrivateDeclarationResult VariableEnvironment::declarePrivateSetter(const RefPtr<UniquedStringImpl>& identifier, PrivateNameEntry::Traits modifierTraits) 174 { 175 return declarePrivateAccessor(identifier, PrivateNameEntry(PrivateNameEntry::Traits::IsSetter | modifierTraits)); 176 } 177 178 VariableEnvironment::PrivateDeclarationResult VariableEnvironment::declarePrivateGetter(const RefPtr<UniquedStringImpl>& identifier, PrivateNameEntry::Traits modifierTraits) 179 { 180 return declarePrivateAccessor(identifier, PrivateNameEntry(PrivateNameEntry::Traits::IsGetter | modifierTraits)); 181 } 182 183 bool VariableEnvironment::declarePrivateMethod(const RefPtr<UniquedStringImpl>& identifier, PrivateNameEntry::Traits addionalTraits) 182 184 { 183 185 if (!m_rareData) … … 187 189 188 190 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); 190 192 191 193 auto entry = VariableEnvironmentEntry(); … … 209 211 210 212 // 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); 212 214 auto addResult = m_rareData->m_privateNames.set(identifier, meta); 213 215 return !addResult.isNewEntry; -
trunk/Source/JavaScriptCore/parser/VariableEnvironment.h
r272883 r273107 111 111 ALWAYS_INLINE bool isGetter() const { return m_bits & IsGetter; } 112 112 ALWAYS_INLINE bool isField() const { return !isPrivateMethodOrAcessor(); } 113 ALWAYS_INLINE bool isStatic() const { return m_bits & IsStatic; } 113 114 114 115 bool isPrivateMethodOrAcessor() const { return isMethod() || isSetter() || isGetter(); } … … 131 132 IsGetter = 1 << 3, 132 133 IsSetter = 1 << 4, 134 IsStatic = 1 << 5, 133 135 }; 134 136 … … 197 199 198 200 bool isEverythingCaptured() const { return m_isEverythingCaptured; } 199 bool isEmpty() const { return !m_map.size() ; }201 bool isEmpty() const { return !m_map.size() && !privateNamesSize(); } 200 202 201 203 using PrivateNamesRange = WTF::IteratorRange<PrivateNameEnvironment::iterator>; … … 205 207 206 208 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); 216 231 217 232 Map::AddResult declarePrivateField(const RefPtr<UniquedStringImpl>& identifier) … … 254 269 } 255 270 256 ALWAYS_INLINE bool has PrivateMethodOrAccessor() const271 ALWAYS_INLINE bool hasStaticPrivateMethodOrAccessor() const 257 272 { 258 273 if (!m_rareData) … … 260 275 261 276 for (auto entry : privateNames()) { 262 if (entry.value.isPrivateMethodOrAcessor() )277 if (entry.value.isPrivateMethodOrAcessor() && entry.value.isStatic()) 263 278 return true; 264 279 } 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 266 294 return false; 267 295 }
Note:
See TracChangeset
for help on using the changeset viewer.