Changeset 254653 in webkit
- Timestamp:
- Jan 15, 2020 4:09:50 PM (4 years ago)
- Location:
- trunk
- Files:
-
- 6 added
- 57 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r254632 r254653 1 2020-01-15 Caitlin Potter <caitp@igalia.com> 2 3 [JSC] Add support for public class fields 4 https://bugs.webkit.org/show_bug.cgi?id=174212 5 6 Reviewed by Yusuke Suzuki. 7 8 New syntax invalidates some test expectations: 9 10 "async <linefeed> MethodDefinition" is no longer an unexpected "async" 11 token. It is now an instance field named "async" with no initializer, 12 and an automatic semicolon, followed by MethodDefinition. 13 14 "get|set GeneratorMethodDefinition"'s error message has changed, due to "get" 15 being valid class field names. 16 17 Many class-syntax tests relating to automatic semicolon insertion are 18 no longer valid, as a line containing nothing but an identifier is now 19 a valid class element. 20 21 * stress/async-await-syntax.js: 22 * stress/class-fields-bytecode-cache.js: Added. 23 * stress/class-fields-computed-to-property-key.js: Added. 24 * stress/class-fields-function-name.js: Added. 25 * stress/class-fields-harmony.js: Added. 26 * stress/class-fields-proxy-define-property.js: Added. 27 * stress/class-fields-stress-instance.js: Added. 28 * stress/generator-syntax.js: 29 * stress/method-name.js: 30 * test262/config.yaml: 31 1 32 2020-01-15 Keith Miller <keith_miller@apple.com> 2 33 -
trunk/JSTests/stress/async-await-syntax.js
r249925 r254653 561 561 { prefix: "({ async", suffix: "method() {} }).method" }, 562 562 563 // ClassLiteral AsyncMethodDefinition564 { prefix: "(class { async", suffix: "method() {} }).prototype.method" },565 566 563 // AsyncArrowFunctions 567 564 { prefix: "(async", suffix: "param => 1)" }, … … 579 576 } 580 577 578 let testsClass = [ 579 // ClassLiteral AsyncMethodDefinition 580 { prefix: "(class { async", suffix: "method() {} }).prototype.method" }, 581 ]; 582 583 for (let { prefix, suffix } of testsClass) { 584 testSyntax(`${prefix} ${suffix}`); 585 testSyntax(`"use strict";${prefix} ${suffix}`); 586 shouldBe("function", typeof eval(`${prefix} ${suffix}`)); 587 shouldBe("function", typeof eval(`"use strict";${prefix} ${suffix}`)); 588 } 589 581 590 // AsyncFunctionDeclaration 582 591 testSyntax("async function foo() {}"); -
trunk/JSTests/stress/generator-syntax.js
r208016 r254653 1 //@ requireOptions("--useClassFields=1") 2 1 3 function testSyntax(script) { 2 4 try { … … 27 29 } 28 30 } 29 `, `SyntaxError: Unexpected token '*'. Expected a n opening '(' before a method's parameter list.`);31 `, `SyntaxError: Unexpected token '*'. Expected a ';' following a class field.`); 30 32 31 33 … … 35 37 } 36 38 } 37 `, `SyntaxError: Unexpected token '*'. Expected a n opening '(' before a method's parameter list.`);39 `, `SyntaxError: Unexpected token '*'. Expected a ';' following a class field.`); 38 40 39 41 testSyntaxError(` -
trunk/JSTests/stress/method-name.js
r204842 r254653 1 //@ requireOptions("--useClassFields=1") 2 1 3 function testSyntax(script) { 2 4 try { … … 26 28 hello hello() { } 27 29 } 28 `, `SyntaxError: Unexpected identifier 'hello'. Expected a n opening '(' before a method's parameter list.`);30 `, `SyntaxError: Unexpected identifier 'hello'. Expected a ';' following a class field.`); 29 31 30 32 testSyntaxError(` -
trunk/JSTests/test262/config.yaml
r252559 r254653 4 4 BigInt: useBigInt 5 5 WeakRef: useWeakRefs 6 class-fields-public: useClassFields 6 7 skip: 7 8 features: … … 11 12 - regexp-lookbehind 12 13 13 - class-fields-public14 14 - class-fields-private 15 15 - class-methods-private -
trunk/LayoutTests/ChangeLog
r254652 r254653 1 2020-01-15 Caitlin Potter <caitp@igalia.com> 2 3 [JSC] Add support for public class fields 4 https://bugs.webkit.org/show_bug.cgi?id=174212 5 6 Reviewed by Yusuke Suzuki. 7 8 New syntax invalidates some test expectations: 9 10 "async <linefeed> MethodDefinition" is no longer an unexpected "async" 11 token. It is now an instance field named "async" with no initializer, 12 and an automatic semicolon, followed by MethodDefinition. 13 14 "get|set GeneratorMethodDefinition"'s error message has changed, due to "get" 15 being valid class field names. 16 17 Many class-syntax tests relating to automatic semicolon insertion are 18 no longer valid, as a line containing nothing but an identifier is now 19 a valid class element. 20 21 * js/class-syntax-semicolon-expected.txt: 22 * js/script-tests/class-syntax-semicolon.js: 23 1 24 2020-01-15 Chris Dumez <cdumez@apple.com> 2 25 -
trunk/LayoutTests/js/class-syntax-semicolon-expected.txt
r188018 r254653 4 4 5 5 6 PASS class A { foo;() { } } threw exception SyntaxError: Unexpected token ';'. Expected an opening '(' before a method's parameter list..7 6 PASS class A { foo() ; { } } threw exception SyntaxError: Unexpected token ';'. Expected an opening '{' at the start of a method body.. 8 PASS class A { get ; foo() { } } threw exception SyntaxError: Unexpected token ';'. Expected an opening '(' before a method's parameter list..9 PASS class A { get foo;() { } } threw exception SyntaxError: Unexpected token ';'. Expected a parameter list for getter definition..10 7 PASS class A { get foo() ; { } } threw exception SyntaxError: Unexpected token ';'. Expected an opening '{' at the start of a getter body.. 11 PASS class A { set ; foo(x) { } } threw exception SyntaxError: Unexpected token ';'. Expected an opening '(' before a method's parameter list..12 PASS class A { set foo;(x) { } } threw exception SyntaxError: Unexpected token ';'. Expected a parameter list for setter definition..13 8 PASS class A { set foo(x) ; { } } threw exception SyntaxError: Unexpected token ';'. Expected an opening '{' at the start of a setter body.. 14 9 PASS class A { ; } did not throw exception. -
trunk/LayoutTests/js/script-tests/class-syntax-semicolon.js
r199236 r254653 1 1 description('Tests for ES6 class syntax containing semicolon in the class body'); 2 2 3 shouldThrow("class A { foo;() { } }", "'SyntaxError: Unexpected token \\';\\'. Expected an opening \\'(\\' before a method\\'s parameter list.'");4 3 shouldThrow("class A { foo() ; { } }", "'SyntaxError: Unexpected token \\\';\\'. Expected an opening \\'{\\' at the start of a method body.'"); 5 shouldThrow("class A { get ; foo() { } }", "'SyntaxError: Unexpected token \\';\\'. Expected an opening \\'(\\' before a method\\'s parameter list.'");6 shouldThrow("class A { get foo;() { } }", "'SyntaxError: Unexpected token \\\';\\'. Expected a parameter list for getter definition.'");7 4 shouldThrow("class A { get foo() ; { } }", "'SyntaxError: Unexpected token \\\';\\'. Expected an opening \\'{\\' at the start of a getter body.'"); 8 shouldThrow("class A { set ; foo(x) { } }", "'SyntaxError: Unexpected token \\';\\'. Expected an opening \\'(\\' before a method\\'s parameter list.'");9 shouldThrow("class A { set foo;(x) { } }", "'SyntaxError: Unexpected token \\\';\\'. Expected a parameter list for setter definition.'");10 5 shouldThrow("class A { set foo(x) ; { } }", "'SyntaxError: Unexpected token \\\';\\'. Expected an opening \\'{\\' at the start of a setter body.'"); 11 6 -
trunk/Source/JavaScriptCore/ChangeLog
r254637 r254653 1 2020-01-15 Caitlin Potter <caitp@igalia.com> 2 3 [JSC] Add support for public class fields 4 https://bugs.webkit.org/show_bug.cgi?id=174212 5 6 Reviewed by Yusuke Suzuki. 7 8 Implements the instance class fields proposal (https://tc39.es/proposal-class-fields/), 9 minus support for private fields (split into a separate patch). 10 11 In summary, class fields are initialized by a synthetic JSFunction. In its unlinked state, 12 the UnlinkedFunctionExecutable for the function includes an ordered list of JSTokenLocations 13 pointing to the start of each class field in the class. Each of these fields are parsed and 14 included as DefineFieldNodes, which implement the appropriate DefineField behaviour in the 15 proposal. This synthetic function is only created, and only loaded, if there are class fields 16 present. The decision to use a synthetic function was for simplicity. There are a number of 17 factors which make inlining the initialization complicated, though we may opt to do this in 18 the future. For reference, the complexities are: instance fields and constructor in different 19 currently in different parsing arenas, distinct scopes between the 2 which require work to manage, 20 and complexity in doing to this work for child classes, where the location of initialization can 21 depend, and in some cases occur more than once. 22 23 Computed property fields require a new bytecode, op_to_property_key, as an implementation 24 detail. It is necessary in the proposal to convert computed properties to property keys 25 during class evaluation, rather than during field initialization. Additionally, we allocate 26 the class lexical scope when computed class fields are used (previously, only when there was 27 a class name), as a location to keep the computed property keys. They can be loaded from the 28 scope via indexed keys. 29 30 To illustrate computed field names in action, consider the following pseudocode: 31 32 <during class evaluation> 33 1) fieldName = emitNode({expr}) 34 2) fieldName = emitToPropertyKey(fieldName) 35 3) classScope[numComputedNames++] = fieldName 36 37 <during class field initialization> 38 1) fieldName = emitGetFromScope(classScope, computedFieldNameIndex++) 39 2) value = emitNode({initializer}) 40 3) instance[fieldName] = value 41 42 The feature is currently hidden behind the feature flag JSC::Options::useClassFields. 43 1 44 2020-01-15 Adrian Perez de Castro <aperez@igalia.com> 2 45 -
trunk/Source/JavaScriptCore/builtins/BuiltinExecutableCreator.cpp
r230105 r254653 33 33 UnlinkedFunctionExecutable* createBuiltinExecutable(VM& vm, const SourceCode& source, const Identifier& ident, ConstructorKind kind, ConstructAbility ability) 34 34 { 35 return BuiltinExecutables::createExecutable(vm, source, ident, kind, ability );35 return BuiltinExecutables::createExecutable(vm, source, ident, kind, ability, NeedsClassFieldInitializer::No); 36 36 } 37 37 -
trunk/Source/JavaScriptCore/builtins/BuiltinExecutables.cpp
r254087 r254653 60 60 } 61 61 62 UnlinkedFunctionExecutable* BuiltinExecutables::createDefaultConstructor(ConstructorKind constructorKind, const Identifier& name )62 UnlinkedFunctionExecutable* BuiltinExecutables::createDefaultConstructor(ConstructorKind constructorKind, const Identifier& name, NeedsClassFieldInitializer needsClassFieldInitializer) 63 63 { 64 64 switch (constructorKind) { … … 68 68 case ConstructorKind::Base: 69 69 case ConstructorKind::Extends: 70 return createExecutable(m_vm, defaultConstructorSourceCode(constructorKind), name, constructorKind, ConstructAbility::CanConstruct );70 return createExecutable(m_vm, defaultConstructorSourceCode(constructorKind), name, constructorKind, ConstructAbility::CanConstruct, needsClassFieldInitializer); 71 71 } 72 72 ASSERT_NOT_REACHED(); … … 76 76 UnlinkedFunctionExecutable* BuiltinExecutables::createBuiltinExecutable(const SourceCode& code, const Identifier& name, ConstructorKind constructorKind, ConstructAbility constructAbility) 77 77 { 78 return createExecutable(m_vm, code, name, constructorKind, constructAbility );79 } 80 81 UnlinkedFunctionExecutable* BuiltinExecutables::createExecutable(VM& vm, const SourceCode& source, const Identifier& name, ConstructorKind constructorKind, ConstructAbility constructAbility )78 return createExecutable(m_vm, code, name, constructorKind, constructAbility, NeedsClassFieldInitializer::No); 79 } 80 81 UnlinkedFunctionExecutable* BuiltinExecutables::createExecutable(VM& vm, const SourceCode& source, const Identifier& name, ConstructorKind constructorKind, ConstructAbility constructAbility, NeedsClassFieldInitializer needsClassFieldInitializer) 82 82 { 83 83 // FIXME: Can we just make MetaData computation be constexpr and have the compiler do this for us? … … 252 252 } 253 253 254 UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(vm, source, &metadata, kind, constructAbility, JSParserScriptMode::Classic, WTF::nullopt, DerivedContextType::None, isBuiltinDefaultClassConstructor);254 UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(vm, source, &metadata, kind, constructAbility, JSParserScriptMode::Classic, WTF::nullopt, DerivedContextType::None, needsClassFieldInitializer, isBuiltinDefaultClassConstructor); 255 255 return functionExecutable; 256 256 } -
trunk/Source/JavaScriptCore/builtins/BuiltinExecutables.h
r249509 r254653 26 26 #pragma once 27 27 28 #include "ExecutableInfo.h" 28 29 #include "JSCBuiltins.h" 29 30 #include "ParserModes.h" … … 58 59 59 60 static SourceCode defaultConstructorSourceCode(ConstructorKind); 60 UnlinkedFunctionExecutable* createDefaultConstructor(ConstructorKind, const Identifier& name );61 UnlinkedFunctionExecutable* createDefaultConstructor(ConstructorKind, const Identifier& name, NeedsClassFieldInitializer); 61 62 62 static UnlinkedFunctionExecutable* createExecutable(VM&, const SourceCode&, const Identifier&, ConstructorKind, ConstructAbility );63 static UnlinkedFunctionExecutable* createExecutable(VM&, const SourceCode&, const Identifier&, ConstructorKind, ConstructAbility, NeedsClassFieldInitializer); 63 64 64 65 void finalizeUnconditionally(); -
trunk/Source/JavaScriptCore/builtins/BuiltinNames.h
r254420 r254653 168 168 macro(webAssemblyCompileStreamingInternal) \ 169 169 macro(webAssemblyInstantiateStreamingInternal) \ 170 macro(instanceFieldInitializer) 170 171 171 172 namespace Symbols { -
trunk/Source/JavaScriptCore/bytecode/BytecodeList.rb
r254632 r254653 866 866 867 867 op :to_primitive, 868 args: { 869 dst: VirtualRegister, 870 src: VirtualRegister, 871 } 872 873 op :to_property_key, 868 874 args: { 869 875 dst: VirtualRegister, -
trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.cpp
r253867 r254653 164 164 USES(OpGetFromScope, scope) 165 165 USES(OpToPrimitive, src) 166 USES(OpToPropertyKey, src) 166 167 USES(OpTryGetById, base) 167 168 USES(OpGetById, base) … … 382 383 DEFS(OpStrcat, dst) 383 384 DEFS(OpToPrimitive, dst) 385 DEFS(OpToPropertyKey, dst) 384 386 DEFS(OpCreateThis, dst) 385 387 DEFS(OpCreatePromise, dst) -
trunk/Source/JavaScriptCore/bytecode/ExecutableInfo.h
r206525 r254653 31 31 32 32 enum class DerivedContextType : uint8_t { None, DerivedConstructorContext, DerivedMethodContext }; 33 enum class EvalContextType : uint8_t { None, FunctionEvalContext }; 33 enum class EvalContextType : uint8_t { None, FunctionEvalContext, InstanceFieldEvalContext }; 34 enum class NeedsClassFieldInitializer : uint8_t { No, Yes }; 34 35 35 36 // FIXME: These flags, ParserModes and propagation to XXXCodeBlocks should be reorganized. 36 37 // https://bugs.webkit.org/show_bug.cgi?id=151547 37 38 struct ExecutableInfo { 38 ExecutableInfo(bool usesEval, bool isStrictMode, bool isConstructor, bool isBuiltinFunction, ConstructorKind constructorKind, JSParserScriptMode scriptMode, SuperBinding superBinding, SourceParseMode parseMode, DerivedContextType derivedContextType, bool isArrowFunctionContext, bool isClassContext, EvalContextType evalContextType)39 ExecutableInfo(bool usesEval, bool isStrictMode, bool isConstructor, bool isBuiltinFunction, ConstructorKind constructorKind, JSParserScriptMode scriptMode, SuperBinding superBinding, SourceParseMode parseMode, DerivedContextType derivedContextType, NeedsClassFieldInitializer needsClassFieldInitializer, bool isArrowFunctionContext, bool isClassContext, EvalContextType evalContextType) 39 40 : m_usesEval(usesEval) 40 41 , m_isStrictMode(isStrictMode) … … 46 47 , m_parseMode(parseMode) 47 48 , m_derivedContextType(static_cast<unsigned>(derivedContextType)) 49 , m_needsClassFieldInitializer(static_cast<unsigned>(needsClassFieldInitializer)) 48 50 , m_isArrowFunctionContext(isArrowFunctionContext) 49 51 , m_isClassContext(isClassContext) … … 67 69 bool isArrowFunctionContext() const { return m_isArrowFunctionContext; } 68 70 bool isClassContext() const { return m_isClassContext; } 71 NeedsClassFieldInitializer needsClassFieldInitializer() const { return static_cast<NeedsClassFieldInitializer>(m_needsClassFieldInitializer); } 69 72 70 73 private: … … 78 81 SourceParseMode m_parseMode; 79 82 unsigned m_derivedContextType : 2; 83 unsigned m_needsClassFieldInitializer : 1; 80 84 unsigned m_isArrowFunctionContext : 1; 81 85 unsigned m_isClassContext : 1; -
trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
r254632 r254653 80 80 ASSERT(m_codeType == static_cast<unsigned>(codeType)); 81 81 ASSERT(m_didOptimize == static_cast<unsigned>(MixedTriState)); 82 if (info.needsClassFieldInitializer() == NeedsClassFieldInitializer::Yes) { 83 createRareDataIfNecessary(); 84 m_rareData->m_needsClassFieldInitializer = static_cast<unsigned>(NeedsClassFieldInitializer::Yes); 85 } 82 86 } 83 87 -
trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
r254632 r254653 332 332 void resetAge() { m_age = 0; } 333 333 334 NeedsClassFieldInitializer needsClassFieldInitializer() const 335 { 336 if (m_rareData) 337 return static_cast<NeedsClassFieldInitializer>(m_rareData->m_needsClassFieldInitializer); 338 return NeedsClassFieldInitializer::No; 339 } 340 334 341 void dump(PrintStream&) const; 335 342 … … 475 482 Vector<BitVector> m_bitVectors; 476 483 Vector<ConstantIdentifierSetEntry> m_constantIdentifierSets; 484 485 unsigned m_needsClassFieldInitializer : 1; 477 486 }; 478 487 -
trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp
r251425 r254653 58 58 JSParserScriptMode scriptMode = executable->scriptMode(); 59 59 ASSERT(isFunctionParseMode(executable->parseMode())); 60 Vector<JSTextPosition>* instanceFieldLocations = executable->instanceFieldLocations(); 60 61 std::unique_ptr<FunctionNode> function = parse<FunctionNode>( 61 vm, source, executable->name(), builtinMode, strictMode, scriptMode, executable->parseMode(), executable->superBinding(), error, nullptr );62 vm, source, executable->name(), builtinMode, strictMode, scriptMode, executable->parseMode(), executable->superBinding(), error, nullptr, ConstructorKind::None, DerivedContextType::None, EvalContextType::None, nullptr, instanceFieldLocations); 62 63 63 64 if (!function) { … … 71 72 bool isClassContext = executable->superBinding() == SuperBinding::Needed; 72 73 73 UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(vm, FunctionCode, ExecutableInfo(function->usesEval(), function->isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable->constructorKind(), scriptMode, executable->superBinding(), parseMode, executable->derivedContextType(), false, isClassContext, EvalContextType::FunctionEvalContext), codeGenerationMode);74 UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(vm, FunctionCode, ExecutableInfo(function->usesEval(), function->isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable->constructorKind(), scriptMode, executable->superBinding(), parseMode, executable->derivedContextType(), executable->needsClassFieldInitializer(), false, isClassContext, EvalContextType::FunctionEvalContext), codeGenerationMode); 74 75 75 76 VariableEnvironment parentScopeTDZVariables = executable->parentScopeTDZVariables(); … … 82 83 } 83 84 84 UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM& vm, Structure* structure, const SourceCode& parentSource, FunctionMetadataNode* node, UnlinkedFunctionKind kind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, Optional<CompactVariableMap::Handle> parentScopeTDZVariables, DerivedContextType derivedContextType, bool isBuiltinDefaultClassConstructor)85 UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM& vm, Structure* structure, const SourceCode& parentSource, FunctionMetadataNode* node, UnlinkedFunctionKind kind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, Optional<CompactVariableMap::Handle> parentScopeTDZVariables, DerivedContextType derivedContextType, NeedsClassFieldInitializer needsClassFieldInitializer, bool isBuiltinDefaultClassConstructor) 85 86 : Base(vm, structure) 86 87 , m_firstLineOffset(node->firstLine() - parentSource.firstLine().oneBasedInt()) … … 109 110 , m_derivedContextType(static_cast<unsigned>(derivedContextType)) 110 111 , m_isGeneratedFromCache(false) 112 , m_needsClassFieldInitializer(static_cast<unsigned>(needsClassFieldInitializer)) 111 113 , m_unlinkedCodeBlockForCall() 112 114 , m_unlinkedCodeBlockForConstruct() … … 122 124 ASSERT(m_derivedContextType == static_cast<unsigned>(derivedContextType)); 123 125 ASSERT(!(m_isBuiltinDefaultClassConstructor && constructorKind() == ConstructorKind::None)); 126 ASSERT(!m_needsClassFieldInitializer || (isClassConstructorFunction() || derivedContextType == DerivedContextType::DerivedConstructorContext)); 124 127 if (!node->classSource().isNull()) 125 128 setClassSource(node->classSource()); -
trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h
r252520 r254653 35 35 #include "JSCast.h" 36 36 #include "ParserModes.h" 37 #include "ParserTokens.h" 37 38 #include "RegExp.h" 38 39 #include "SourceCode.h" … … 70 71 } 71 72 72 static UnlinkedFunctionExecutable* create(VM& vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, Optional<CompactVariableMap::Handle> parentScopeTDZVariables, DerivedContextType derivedContextType, bool isBuiltinDefaultClassConstructor = false)73 static UnlinkedFunctionExecutable* create(VM& vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, Optional<CompactVariableMap::Handle> parentScopeTDZVariables, DerivedContextType derivedContextType, NeedsClassFieldInitializer needsClassFieldInitializer, bool isBuiltinDefaultClassConstructor = false) 73 74 { 74 75 UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm.heap)) 75 UnlinkedFunctionExecutable(vm, vm.unlinkedFunctionExecutableStructure.get(), source, node, unlinkedFunctionKind, constructAbility, scriptMode, WTFMove(parentScopeTDZVariables), derivedContextType, isBuiltinDefaultClassConstructor);76 UnlinkedFunctionExecutable(vm, vm.unlinkedFunctionExecutableStructure.get(), source, node, unlinkedFunctionKind, constructAbility, scriptMode, WTFMove(parentScopeTDZVariables), derivedContextType, needsClassFieldInitializer, isBuiltinDefaultClassConstructor); 76 77 instance->finishCreation(vm); 77 78 return instance; … … 209 210 String m_sourceMappingURLDirective; 210 211 CompactVariableMap::Handle m_parentScopeTDZVariables; 212 Vector<JSTextPosition> m_instanceFieldLocations; 211 213 }; 212 214 215 NeedsClassFieldInitializer needsClassFieldInitializer() const { return static_cast<NeedsClassFieldInitializer>(m_needsClassFieldInitializer); } 216 217 Vector<JSTextPosition>* instanceFieldLocations() const 218 { 219 if (m_rareData) 220 return &m_rareData->m_instanceFieldLocations; 221 return nullptr; 222 } 223 224 void setInstanceFieldLocations(Vector<JSTextPosition>&& instanceFieldLocations) 225 { 226 if (instanceFieldLocations.isEmpty()) 227 return; 228 ensureRareData().m_instanceFieldLocations = WTFMove(instanceFieldLocations); 229 } 230 213 231 private: 214 UnlinkedFunctionExecutable(VM&, Structure*, const SourceCode&, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, JSParserScriptMode, Optional<CompactVariableMap::Handle>, JSC::DerivedContextType, bool isBuiltinDefaultClassConstructor);232 UnlinkedFunctionExecutable(VM&, Structure*, const SourceCode&, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, JSParserScriptMode, Optional<CompactVariableMap::Handle>, JSC::DerivedContextType, JSC::NeedsClassFieldInitializer, bool isBuiltinDefaultClassConstructor); 215 233 UnlinkedFunctionExecutable(Decoder&, const CachedFunctionExecutable&); 216 234 … … 249 267 unsigned m_derivedContextType: 2; 250 268 unsigned m_isGeneratedFromCache : 1; 269 unsigned m_needsClassFieldInitializer : 1; 251 270 252 271 union { -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r254632 r254653 377 377 378 378 bool shouldCaptureAllOfTheThings = shouldEmitDebugHooks() || codeBlock->usesEval(); 379 bool needsArguments = ((functionNode->usesArguments() && !codeBlock->isArrowFunction()) || codeBlock->usesEval() || (functionNode->usesArrowFunction() && !codeBlock->isArrowFunction() && isArgumentsUsedInInnerArrowFunction())) ;379 bool needsArguments = ((functionNode->usesArguments() && !codeBlock->isArrowFunction()) || codeBlock->usesEval() || (functionNode->usesArrowFunction() && !codeBlock->isArrowFunction() && isArgumentsUsedInInnerArrowFunction())) && parseMode != SourceParseMode::InstanceFieldInitializerMode; 380 380 381 381 if (isGeneratorOrAsyncFunctionBodyParseMode(parseMode)) { … … 601 601 602 602 bool shouldCreateArgumensVariable = !haveParameterNamedArguments 603 && !SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode ).contains(m_codeBlock->parseMode());603 && !SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode, SourceParseMode::InstanceFieldInitializerMode).contains(m_codeBlock->parseMode()); 604 604 shouldCreateArgumentsVariableInParameterScope = shouldCreateArgumensVariable && !isSimpleParameterList; 605 605 // Do not create arguments variable in case of Arrow function. Value will be loaded from parent scope … … 696 696 case ConstructorKind::Base: 697 697 emitCreateThis(&m_thisRegister); 698 if (Options::useClassFields()) 699 emitInstanceFieldInitializationIfNeeded(&m_thisRegister, &m_calleeRegister, m_scopeNode->position(), m_scopeNode->position(), m_scopeNode->position()); 698 700 break; 699 701 case ConstructorKind::Extends: … … 2733 2735 } 2734 2736 2737 RegisterID* BytecodeGenerator::emitInstanceFieldInitializationIfNeeded(RegisterID* dst, RegisterID* constructor, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd) 2738 { 2739 if (!(isConstructor() || isDerivedConstructorContext()) || needsClassFieldInitializer() == NeedsClassFieldInitializer::No) 2740 return dst; 2741 2742 RefPtr<RegisterID> initializer = emitDirectGetById(newTemporary(), constructor, propertyNames().builtinNames().instanceFieldInitializerPrivateName()); 2743 CallArguments args(*this, nullptr); 2744 emitMove(args.thisRegister(), dst); 2745 emitCall(newTemporary(), initializer.get(), NoExpectedFunction, args, divot, divotStart, divotEnd, DebuggableCall::No); 2746 2747 return dst; 2748 } 2749 2735 2750 void BytecodeGenerator::emitTDZCheck(RegisterID* target) 2736 2751 { … … 3014 3029 3015 3030 RegisterID* BytecodeGenerator::emitNewDefaultConstructor(RegisterID* dst, ConstructorKind constructorKind, const Identifier& name, 3016 const Identifier& ecmaName, const SourceCode& classSource )3017 { 3018 UnlinkedFunctionExecutable* executable = m_vm.builtinExecutables()->createDefaultConstructor(constructorKind, name );3031 const Identifier& ecmaName, const SourceCode& classSource, NeedsClassFieldInitializer needsClassFieldInitializer) 3032 { 3033 UnlinkedFunctionExecutable* executable = m_vm.builtinExecutables()->createDefaultConstructor(constructorKind, name, needsClassFieldInitializer); 3019 3034 executable->setInvalidTypeProfilingOffsets(); 3020 3035 executable->setEcmaName(ecmaName); … … 3023 3038 unsigned index = m_codeBlock->addFunctionExpr(executable); 3024 3039 3040 OpNewFuncExp::emit(this, dst, scopeRegister(), index); 3041 return dst; 3042 } 3043 3044 RegisterID* BytecodeGenerator::emitNewInstanceFieldInitializerFunction(RegisterID* dst, Vector<JSTextPosition>&& instanceFieldLocations, bool isDerived) 3045 { 3046 DerivedContextType newDerivedContextType; 3047 SuperBinding superBinding; 3048 if (!isDerived) { 3049 newDerivedContextType = DerivedContextType::None; 3050 superBinding = SuperBinding::NotNeeded; 3051 } else { 3052 newDerivedContextType = DerivedContextType::DerivedMethodContext; 3053 superBinding = SuperBinding::Needed; 3054 } 3055 3056 Optional<CompactVariableMap::Handle> variablesUnderTDZ = getVariablesUnderTDZ(); 3057 SourceParseMode parseMode = SourceParseMode::InstanceFieldInitializerMode; 3058 ConstructAbility constructAbility = ConstructAbility::CannotConstruct; 3059 3060 const bool alwaysStrictInClass = true; 3061 FunctionMetadataNode metadata(parserArena(), JSTokenLocation(), JSTokenLocation(), 0, 0, 0, 0, 0, alwaysStrictInClass, ConstructorKind::None, superBinding, 0, parseMode, false); 3062 metadata.finishParsing(m_scopeNode->source(), Identifier(), FunctionMode::MethodDefinition); 3063 auto initializer = UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), &metadata, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, scriptMode(), WTFMove(variablesUnderTDZ), newDerivedContextType, NeedsClassFieldInitializer::No); 3064 initializer->setInstanceFieldLocations(WTFMove(instanceFieldLocations)); 3065 3066 unsigned index = m_codeBlock->addFunctionExpr(initializer); 3025 3067 OpNewFuncExp::emit(this, dst, scopeRegister(), index); 3026 3068 return dst; … … 3041 3083 } 3042 3084 3043 void BytecodeGenerator::emitSetFunctionNameIfNeeded(ExpressionNode* valueNode, RegisterID* value, RegisterID* name) 3085 template<typename LazyNameRegisterFn> 3086 void BytecodeGenerator::emitSetFunctionNameIfNeededImpl(ExpressionNode* valueNode, RegisterID* value, const LazyNameRegisterFn& lazyNameFn) 3044 3087 { 3045 3088 if (valueNode->isBaseFuncExprNode()) { … … 3056 3099 return; 3057 3100 3101 RegisterID* name = lazyNameFn(); 3102 3058 3103 // FIXME: We should use an op_call to an internal function here instead. 3059 3104 // https://bugs.webkit.org/show_bug.cgi?id=155547 3060 3105 OpSetFunctionName::emit(this, value, name); 3106 } 3107 3108 void BytecodeGenerator::emitSetFunctionNameIfNeeded(ExpressionNode* valueNode, RegisterID* value, const Identifier& ident) 3109 { 3110 emitSetFunctionNameIfNeededImpl(valueNode, value, [=]() { return emitLoad(newTemporary(), ident); }); 3111 } 3112 3113 void BytecodeGenerator::emitSetFunctionNameIfNeeded(ExpressionNode* valueNode, RegisterID* value, RegisterID* name) 3114 { 3115 emitSetFunctionNameIfNeededImpl(valueNode, value, [=]() { return name; }); 3061 3116 } 3062 3117 … … 3402 3457 { 3403 3458 OpToPrimitive::emit(this, dst, src); 3459 } 3460 3461 RegisterID* BytecodeGenerator::emitToPropertyKey(RegisterID* dst, RegisterID* src) 3462 { 3463 OpToPropertyKey::emit(this, dst, src); 3464 return dst; 3404 3465 } 3405 3466 … … 4234 4295 RegisterID* BytecodeGenerator::emitLoadArrowFunctionLexicalEnvironment(const Identifier& identifier) 4235 4296 { 4236 ASSERT(m_codeBlock->isArrowFunction() || m_codeBlock->isArrowFunctionContext() || constructorKind() == ConstructorKind::Extends || m_codeType == EvalCode );4297 ASSERT(m_codeBlock->isArrowFunction() || m_codeBlock->isArrowFunctionContext() || constructorKind() == ConstructorKind::Extends || m_codeType == EvalCode || m_codeBlock->parseMode() == SourceParseMode::InstanceFieldInitializerMode); 4237 4298 4238 4299 return emitResolveScope(nullptr, variable(identifier, ThisResolutionType::Scoped)); … … 4256 4317 Variable protoScopeVar = variable(propertyNames().builtinNames().derivedConstructorPrivateName()); 4257 4318 return emitGetFromScope(newTemporary(), emitLoadArrowFunctionLexicalEnvironment(propertyNames().builtinNames().derivedConstructorPrivateName()), protoScopeVar, ThrowIfNotFound); 4319 } 4320 4321 RegisterID* BytecodeGenerator::emitLoadDerivedConstructor() 4322 { 4323 ASSERT(constructorKind() == ConstructorKind::Extends || isDerivedConstructorContext()); 4324 if (constructorKind() == ConstructorKind::Extends) 4325 return &m_calleeRegister; 4326 return emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment(); 4258 4327 } 4259 4328 -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r254632 r254653 403 403 SuperBinding superBinding() const { return m_codeBlock->superBinding(); } 404 404 JSParserScriptMode scriptMode() const { return m_codeBlock->scriptMode(); } 405 NeedsClassFieldInitializer needsClassFieldInitializer() const { return m_codeBlock->needsClassFieldInitializer(); } 405 406 406 407 template<typename Node, typename UnlinkedCodeBlock> … … 555 556 } 556 557 557 RegisterID* emitDefineClassElements(PropertyListNode* n, RegisterID* constructor, RegisterID* prototype )558 RegisterID* emitDefineClassElements(PropertyListNode* n, RegisterID* constructor, RegisterID* prototype, Vector<JSTextPosition>& instanceFieldLocations) 558 559 { 559 560 ASSERT(constructor->refCount() && prototype->refCount()); … … 562 563 if (UNLIKELY(n->needsDebugHook())) 563 564 emitDebugHook(n); 564 return n->emitBytecode(*this, constructor, prototype );565 return n->emitBytecode(*this, constructor, prototype, &instanceFieldLocations); 565 566 } 566 567 … … 728 729 RegisterID* emitCreateAsyncGenerator(RegisterID* dst, RegisterID* newTarget); 729 730 RegisterID* emitCreateArgumentsButterfly(RegisterID* dst); 731 RegisterID* emitInstanceFieldInitializationIfNeeded(RegisterID* dst, RegisterID* constructor, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); 730 732 void emitTDZCheck(RegisterID* target); 731 733 bool needsTDZCheck(const Variable&); … … 743 745 RegisterID* emitNewFunction(RegisterID* dst, FunctionMetadataNode*); 744 746 RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode*); 745 RegisterID* emitNewDefaultConstructor(RegisterID* dst, ConstructorKind, const Identifier& name, const Identifier& ecmaName, const SourceCode& classSource); 747 RegisterID* emitNewDefaultConstructor(RegisterID* dst, ConstructorKind, const Identifier& name, const Identifier& ecmaName, const SourceCode& classSource, NeedsClassFieldInitializer); 748 RegisterID* emitNewInstanceFieldInitializerFunction(RegisterID* dst, Vector<JSTextPosition>&& instanceFieldLocations, bool isDerived); 746 749 RegisterID* emitNewArrowFunctionExpression(RegisterID*, ArrowFuncExprNode*); 747 750 RegisterID* emitNewMethodDefinition(RegisterID* dst, MethodDefinitionNode*); … … 749 752 750 753 void emitSetFunctionNameIfNeeded(ExpressionNode* valueNode, RegisterID* value, RegisterID* name); 754 void emitSetFunctionNameIfNeeded(ExpressionNode* valueNode, RegisterID* value, const Identifier&); 751 755 752 756 RegisterID* moveLinkTimeConstant(RegisterID* dst, LinkTimeConstant); … … 832 836 RegisterID* emitStrcat(RegisterID* dst, RegisterID* src, int count); 833 837 void emitToPrimitive(RegisterID* dst, RegisterID* src); 838 RegisterID* emitToPropertyKey(RegisterID* dst, RegisterID* src); 834 839 835 840 ResolveType resolveType(); … … 952 957 void emitPutDerivedConstructorToArrowFunctionContextScope(); 953 958 RegisterID* emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment(); 959 RegisterID* emitLoadDerivedConstructor(); 954 960 955 961 void emitDebugHook(DebugHookType, const JSTextPosition&); … … 970 976 bool emitReturnViaFinallyIfNeeded(RegisterID* returnRegister); 971 977 void emitFinallyCompletion(FinallyContext&, Label& normalCompletionLabel); 978 979 template<typename LazyNameRegisterFn> 980 void emitSetFunctionNameIfNeededImpl(ExpressionNode*, RegisterID*, const LazyNameRegisterFn&); 972 981 973 982 public: … … 1118 1127 DerivedContextType newDerivedContextType = DerivedContextType::None; 1119 1128 1129 NeedsClassFieldInitializer needsClassFieldInitializer = metadata->isConstructorAndNeedsClassFieldInitializer() ? NeedsClassFieldInitializer::Yes : NeedsClassFieldInitializer::No; 1120 1130 if (SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode, SourceParseMode::AsyncArrowFunctionBodyMode).contains(metadata->parseMode())) { 1121 if (constructorKind() == ConstructorKind::Extends || isDerivedConstructorContext()) 1131 if (constructorKind() == ConstructorKind::Extends || isDerivedConstructorContext()) { 1122 1132 newDerivedContextType = DerivedContextType::DerivedConstructorContext; 1133 needsClassFieldInitializer = m_codeBlock->needsClassFieldInitializer(); 1134 } 1123 1135 else if (m_codeBlock->isClassContext() || isDerivedClassContext()) 1124 1136 newDerivedContextType = DerivedContextType::DerivedMethodContext; … … 1134 1146 constructAbility = ConstructAbility::CanConstruct; 1135 1147 1136 return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), metadata, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, scriptMode(), WTFMove(optionalVariablesUnderTDZ), newDerivedContextType );1148 return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), metadata, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, scriptMode(), WTFMove(optionalVariablesUnderTDZ), newDerivedContextType, needsClassFieldInitializer); 1137 1149 } 1138 1150 -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r254420 r254653 179 179 static RegisterID* emitHomeObjectForCallee(BytecodeGenerator& generator) 180 180 { 181 if ( generator.isDerivedClassContext() || generator.isDerivedConstructorContext()) {181 if ((generator.isDerivedClassContext() || generator.isDerivedConstructorContext()) && generator.parseMode() != SourceParseMode::InstanceFieldInitializerMode) { 182 182 RegisterID* derivedConstructor = generator.emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment(); 183 183 return generator.emitGetById(generator.newTemporary(), derivedConstructor, generator.propertyNames().builtinNames().homeObjectPrivateName()); … … 543 543 } 544 544 545 RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dstOrConstructor, RegisterID* prototype )545 RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dstOrConstructor, RegisterID* prototype, Vector<JSTextPosition>* instanceFieldLocations) 546 546 { 547 547 // Fast case: this loop just handles regular value properties. … … 550 550 for (; p && (p->m_node->m_type & PropertyNode::Constant); p = p->m_next) { 551 551 dst = p->m_node->isInstanceClassProperty() ? prototype : dstOrConstructor; 552 553 if (p->isComputedClassField()) 554 emitSaveComputedFieldName(generator, *p->m_node); 555 556 if (p->isInstanceClassField()) { 557 ASSERT(instanceFieldLocations); 558 instanceFieldLocations->append(p->position()); 559 continue; 560 } 561 552 562 emitPutConstantProperty(generator, dst, *p->m_node); 553 563 } … … 596 606 PropertyNode* node = p->m_node; 597 607 dst = node->isInstanceClassProperty() ? prototype : dstOrConstructor; 608 609 if (p->isComputedClassField()) 610 emitSaveComputedFieldName(generator, *p->m_node); 611 612 if (p->isInstanceClassField()) { 613 ASSERT(instanceFieldLocations); 614 ASSERT(node->m_type & PropertyNode::Constant); 615 instanceFieldLocations->append(p->position()); 616 continue; 617 } 598 618 599 619 // Handle regular values. … … 718 738 } 719 739 740 void PropertyListNode::emitSaveComputedFieldName(BytecodeGenerator& generator, PropertyNode& node) 741 { 742 ASSERT(node.isComputedClassField()); 743 RefPtr<RegisterID> propertyExpr; 744 745 // The 'name' refers to a synthetic numeric variable name in the private name scope, where the property key is saved for later use. 746 const Identifier& description = *node.name(); 747 Variable var = generator.variable(description); 748 ASSERT(!var.local()); 749 750 propertyExpr = generator.emitNode(node.m_expression); 751 RegisterID* propertyName = generator.emitToPropertyKey(generator.newTemporary(), propertyExpr.get()); 752 753 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); 754 generator.emitPutToScope(scope.get(), var, propertyName, ThrowIfNotFound, InitializationMode::ConstInitialization); 755 } 756 720 757 // ------------------------------ BracketAccessorNode -------------------------------- 721 758 … … 924 961 if (generator.isDerivedConstructorContext() || doWeUseArrowFunctionInConstructor) 925 962 generator.emitPutThisToArrowFunctionContextScope(); 926 963 964 // Initialize instance fields after super-call. 965 if (Options::useClassFields() && generator.needsClassFieldInitializer() == NeedsClassFieldInitializer::Yes) { 966 ASSERT(generator.isConstructor() || generator.isDerivedConstructorContext()); 967 func = generator.emitLoadDerivedConstructor(); 968 generator.emitInstanceFieldInitializationIfNeeded(generator.thisRegister(), func.get(), divot(), divotStart(), divotEnd()); 969 } 970 927 971 return ret; 928 972 } … … 4267 4311 } 4268 4312 4313 // ------------------------------ DefineFieldNode --------------------------------- 4314 4315 void DefineFieldNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) 4316 { 4317 RefPtr<RegisterID> value = generator.newTemporary(); 4318 4319 if (!m_assign) 4320 generator.emitLoad(value.get(), jsUndefined()); 4321 else { 4322 generator.emitNode(value.get(), m_assign); 4323 if (m_ident) 4324 generator.emitSetFunctionNameIfNeeded(m_assign, value.get(), *m_ident); 4325 } 4326 4327 switch (m_type) { 4328 case DefineFieldNode::Type::Name: { 4329 // FIXME: Improve performance of public class fields 4330 // https://bugs.webkit.org/show_bug.cgi?id=198330 4331 RefPtr<RegisterID> propertyName = generator.emitLoad(nullptr, *m_ident); 4332 generator.emitCallDefineProperty(generator.thisRegister(), propertyName.get(), value.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable | BytecodeGenerator::PropertyEnumerable, m_position); 4333 break; 4334 } 4335 case DefineFieldNode::Type::ComputedName: { 4336 // FIXME: Improve performance of public class fields 4337 // https://bugs.webkit.org/show_bug.cgi?id=198330 4338 4339 // For ComputedNames, the expression has already been evaluated earlier during evaluation of a ClassExprNode. 4340 // Here, `m_ident` refers to an integer ID in a class lexical scope, containing the value already converted to an Expression. 4341 Variable var = generator.variable(*m_ident); 4342 ASSERT_WITH_MESSAGE(!var.local(), "Computed names must be stored in captured variables"); 4343 4344 generator.emitExpressionInfo(position(), position(), position() + 1); 4345 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), var); 4346 RefPtr<RegisterID> privateName = generator.newTemporary(); 4347 generator.emitGetFromScope(privateName.get(), scope.get(), var, ThrowIfNotFound); 4348 generator.emitProfileType(privateName.get(), var, m_position, JSTextPosition(-1, m_position.offset + m_ident->length(), -1)); 4349 generator.emitCallDefineProperty(generator.thisRegister(), privateName.get(), value.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable | BytecodeGenerator::PropertyEnumerable, m_position); 4350 break; 4351 } 4352 } 4353 } 4354 4269 4355 // ------------------------------ ClassDeclNode --------------------------------- 4270 4356 … … 4278 4364 RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 4279 4365 { 4280 if ( !m_name.isNull())4366 if (m_needsLexicalScope) 4281 4367 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested); 4282 4368 … … 4289 4375 RefPtr<RegisterID> constructor = generator.tempDestination(dst); 4290 4376 bool needsHomeObject = false; 4377 4378 auto needsClassFieldInitializer = this->hasInstanceFields() ? NeedsClassFieldInitializer::Yes : NeedsClassFieldInitializer::No; 4291 4379 4292 4380 if (m_constructorExpression) { … … 4295 4383 metadata->setEcmaName(ecmaName()); 4296 4384 metadata->setClassSource(m_classSource); 4385 metadata->setNeedsClassFieldInitializer(needsClassFieldInitializer == NeedsClassFieldInitializer::Yes); 4297 4386 constructor = generator.emitNode(constructor.get(), m_constructorExpression); 4298 4387 needsHomeObject = m_classHeritage || metadata->superBinding() == SuperBinding::Needed; 4299 4388 } else 4300 constructor = generator.emitNewDefaultConstructor(constructor.get(), m_classHeritage ? ConstructorKind::Extends : ConstructorKind::Base, m_name, ecmaName(), m_classSource );4389 constructor = generator.emitNewDefaultConstructor(constructor.get(), m_classHeritage ? ConstructorKind::Extends : ConstructorKind::Base, m_name, ecmaName(), m_classSource, needsClassFieldInitializer); 4301 4390 4302 4391 const auto& propertyNames = generator.propertyNames(); … … 4344 4433 generator.emitCallDefineProperty(constructor.get(), prototypeNameRegister.get(), prototype.get(), nullptr, nullptr, 0, m_position); 4345 4434 4346 if (m_classElements) 4347 generator.emitDefineClassElements(m_classElements, constructor.get(), prototype.get()); 4348 4349 if (!m_name.isNull()) { 4350 Variable classNameVar = generator.variable(m_name); 4351 RELEASE_ASSERT(classNameVar.isResolved()); 4352 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, classNameVar); 4353 generator.emitPutToScope(scope.get(), classNameVar, constructor.get(), ThrowIfNotFound, InitializationMode::Initialization); 4435 if (m_classElements) { 4436 Vector<JSTextPosition> instanceFieldLocations; 4437 generator.emitDefineClassElements(m_classElements, constructor.get(), prototype.get(), instanceFieldLocations); 4438 if (!instanceFieldLocations.isEmpty()) { 4439 RefPtr<RegisterID> instanceFieldInitializer = generator.emitNewInstanceFieldInitializerFunction(generator.newTemporary(), WTFMove(instanceFieldLocations), m_classHeritage); 4440 4441 // FIXME: Skip this if the initializer function isn't going to need a home object (no eval or super properties) 4442 // https://bugs.webkit.org/show_bug.cgi?id=196867 4443 emitPutHomeObject(generator, instanceFieldInitializer.get(), prototype.get()); 4444 4445 generator.emitDirectPutById(constructor.get(), generator.propertyNames().builtinNames().instanceFieldInitializerPrivateName(), instanceFieldInitializer.get(), PropertyNode::Unknown); 4446 } 4447 } 4448 4449 if (m_needsLexicalScope) { 4450 if (!m_name.isNull()) { 4451 Variable classNameVar = generator.variable(m_name); 4452 RELEASE_ASSERT(classNameVar.isResolved()); 4453 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, classNameVar); 4454 generator.emitPutToScope(scope.get(), classNameVar, constructor.get(), ThrowIfNotFound, InitializationMode::Initialization); 4455 } 4354 4456 generator.popLexicalScope(this); 4355 4457 } -
trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp
r252216 r254653 254 254 JSScope::collectClosureVariablesUnderTDZ(scope()->jsScope(), variablesUnderTDZ); 255 255 256 auto* eval = DirectEvalExecutable::create(globalObject, makeSource(script, callFrame->callerSourceOrigin(vm)), codeBlock->isStrictMode(), codeBlock->unlinkedCodeBlock()->derivedContextType(), codeBlock->unlinkedCodeBlock()-> isArrowFunction(), evalContextType, &variablesUnderTDZ);256 auto* eval = DirectEvalExecutable::create(globalObject, makeSource(script, callFrame->callerSourceOrigin(vm)), codeBlock->isStrictMode(), codeBlock->unlinkedCodeBlock()->derivedContextType(), codeBlock->unlinkedCodeBlock()->needsClassFieldInitializer(), codeBlock->unlinkedCodeBlock()->isArrowFunction(), evalContextType, &variablesUnderTDZ); 257 257 if (UNLIKELY(catchScope.exception())) { 258 258 exception = catchScope.exception(); -
trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
r254632 r254653 294 294 case op_yield: 295 295 case op_create_generator_frame_environment: 296 case op_to_property_key: // FIXME: op_to_property_key will need DFG/FTL support to ship class fields. 296 297 case llint_program_prologue: 297 298 case llint_eval_prologue: -
trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp
r254632 r254653 137 137 138 138 EvalContextType evalContextType; 139 if (isFunctionParseMode(callerUnlinkedCodeBlock->parseMode())) 139 if (callerUnlinkedCodeBlock->parseMode() == SourceParseMode::InstanceFieldInitializerMode) 140 evalContextType = EvalContextType::InstanceFieldEvalContext; 141 else if (isFunctionParseMode(callerUnlinkedCodeBlock->parseMode())) 140 142 evalContextType = EvalContextType::FunctionEvalContext; 141 143 else if (callerUnlinkedCodeBlock->codeType() == EvalCode) … … 163 165 VariableEnvironment variablesUnderTDZ; 164 166 JSScope::collectClosureVariablesUnderTDZ(callerScopeChain, variablesUnderTDZ); 165 eval = DirectEvalExecutable::create(globalObject, makeSource(programSource, callerCodeBlock->source().provider()->sourceOrigin()), callerCodeBlock->isStrictMode(), derivedContextType, isArrowFunctionContext, evalContextType, &variablesUnderTDZ);167 eval = DirectEvalExecutable::create(globalObject, makeSource(programSource, callerCodeBlock->source().provider()->sourceOrigin()), callerCodeBlock->isStrictMode(), derivedContextType, callerUnlinkedCodeBlock->needsClassFieldInitializer(), isArrowFunctionContext, evalContextType, &variablesUnderTDZ); 166 168 EXCEPTION_ASSERT(!!scope.exception() == !eval); 167 169 if (!eval) -
trunk/Source/JavaScriptCore/jit/JIT.cpp
r254087 r254653 426 426 DEFINE_OP(op_put_getter_by_val) 427 427 DEFINE_OP(op_put_setter_by_val) 428 DEFINE_OP(op_to_property_key) 428 429 429 430 DEFINE_OP(op_get_internal_field) … … 600 601 DEFINE_SLOWCASE_SLOW_OP(resolve_scope) 601 602 DEFINE_SLOWCASE_SLOW_OP(check_tdz) 603 DEFINE_SLOWCASE_SLOW_OP(to_property_key) 602 604 603 605 default: -
trunk/Source/JavaScriptCore/jit/JIT.h
r254632 r254653 622 622 void emit_op_log_shadow_chicken_prologue(const Instruction*); 623 623 void emit_op_log_shadow_chicken_tail(const Instruction*); 624 void emit_op_to_property_key(const Instruction*); 624 625 625 626 void emitSlow_op_add(const Instruction*, Vector<SlowCaseEntry>::iterator&); -
trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp
r254632 r254653 358 358 } 359 359 360 void JIT::emit_op_to_property_key(const Instruction* currentInstruction) 361 { 362 auto bytecode = currentInstruction->as<OpToPropertyKey>(); 363 VirtualRegister dst = bytecode.m_dst; 364 VirtualRegister src = bytecode.m_src; 365 366 emitGetVirtualRegister(src, regT0); 367 368 addSlowCase(branchIfNotCell(regT0)); 369 Jump done = branchIfSymbol(regT0); 370 addSlowCase(branchIfNotString(regT0)); 371 372 done.link(this); 373 if (src != dst) 374 emitPutVirtualRegister(dst); 375 } 376 360 377 void JIT::emit_op_set_function_name(const Instruction* currentInstruction) 361 378 { -
trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
r254632 r254653 344 344 } 345 345 346 void JIT::emit_op_to_property_key(const Instruction* currentInstruction) 347 { 348 auto bytecode = currentInstruction->as<OpToPropertyKey>(); 349 VirtualRegister dst = bytecode.m_dst; 350 VirtualRegister src = bytecode.m_src; 351 352 emitLoad(src, regT1, regT0); 353 354 addSlowCase(branchIfNotCell(regT1)); 355 Jump done = branchIfSymbol(regT0); 356 addSlowCase(branchIfNotString(regT0)); 357 358 done.link(this); 359 if (src != dst) 360 emitStore(dst, regT1, regT0); 361 } 362 346 363 void JIT::emit_op_set_function_name(const Instruction* currentInstruction) 347 364 { -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
r254632 r254653 1960 1960 1961 1961 1962 llintOpWithReturn(op_to_property_key, OpToPropertyKey, macro (size, get, dispatch, return) 1963 get(m_src, t2) 1964 loadConstantOrVariable(size, t2, t1, t0) 1965 bineq t1, CellTag, .opToPropertyKeySlow 1966 bbeq JSCell::m_type[t0], SymbolType, .done 1967 bbneq JSCell::m_type[t0], StringType, .opToPropertyKeySlow 1968 1969 .done: 1970 return(t1, t0) 1971 1972 .opToPropertyKeySlow: 1973 callSlowPath(_slow_path_to_property_key) 1974 dispatch() 1975 end) 1976 1977 1962 1978 commonOp(llint_op_catch, macro() end, macro (size) 1963 1979 # This is where we end up from the JIT's throw trampoline (because the -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r254632 r254653 2099 2099 2100 2100 2101 llintOpWithReturn(op_to_property_key, OpToPropertyKey, macro (size, get, dispatch, return) 2102 get(m_src, t2) 2103 loadConstantOrVariable(size, t2, t0) 2104 2105 btqnz t0, notCellMask, .opToPropertyKeySlow 2106 bbeq JSCell::m_type[t0], SymbolType, .done 2107 bbneq JSCell::m_type[t0], StringType, .opToPropertyKeySlow 2108 2109 .done: 2110 return(t0) 2111 2112 .opToPropertyKeySlow: 2113 callSlowPath(_slow_path_to_property_key) 2114 dispatch() 2115 end) 2116 2117 2101 2118 commonOp(llint_op_catch, macro() end, macro (size) 2102 2119 # This is where we end up from the JIT's throw trampoline (because the -
trunk/Source/JavaScriptCore/parser/ASTBuilder.h
r252032 r254653 406 406 } 407 407 408 DefineFieldNode* createDefineField(const JSTokenLocation& location, const Identifier* ident, ExpressionNode* initializer, DefineFieldNode::Type type) 409 { 410 return new (m_parserArena) DefineFieldNode(location, ident, initializer, type); 411 } 412 408 413 ClassExprNode* createClassExpr(const JSTokenLocation& location, const ParserClassInfo<ASTBuilder>& classInfo, VariableEnvironment& classEnvironment, ExpressionNode* constructor, 409 414 ExpressionNode* parentClass, PropertyListNode* classElements) … … 528 533 } 529 534 PropertyNode* createProperty(ExpressionNode* propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, ClassElementTag tag) { return new (m_parserArena) PropertyNode(propertyName, node, type, putType, superBinding, tag); } 535 PropertyNode* createProperty(const Identifier* identifier, ExpressionNode* propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, ClassElementTag tag) { return new (m_parserArena) PropertyNode(*identifier, propertyName, node, type, putType, superBinding, tag); } 530 536 PropertyListNode* createPropertyList(const JSTokenLocation& location, PropertyNode* property) { return new (m_parserArena) PropertyListNode(location, property); } 531 537 PropertyListNode* createPropertyList(const JSTokenLocation& location, PropertyNode* property, PropertyListNode* tail) { return new (m_parserArena) PropertyListNode(location, property, tail); } -
trunk/Source/JavaScriptCore/parser/NodeConstructors.h
r252032 r254653 249 249 inline PropertyNode::PropertyNode(const Identifier& name, ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding, ClassElementTag tag) 250 250 : m_name(&name) 251 , m_expression(nullptr) 251 252 , m_assign(assign) 252 253 , m_type(type) … … 260 261 inline PropertyNode::PropertyNode(ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding, ClassElementTag tag) 261 262 : m_name(nullptr) 263 , m_expression(nullptr) 262 264 , m_assign(assign) 263 265 , m_type(type) … … 281 283 } 282 284 285 inline PropertyNode::PropertyNode(const Identifier& ident, ExpressionNode* name, ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding, ClassElementTag tag) 286 : m_name(&ident) 287 , m_expression(name) 288 , m_assign(assign) 289 , m_type(type) 290 , m_needsSuperBinding(superBinding == SuperBinding::Needed) 291 , m_putType(putType) 292 , m_classElementTag(static_cast<unsigned>(tag)) 293 , m_isOverriddenByDuplicate(false) 294 { 295 } 296 283 297 inline PropertyListNode::PropertyListNode(const JSTokenLocation& location, PropertyNode* node) 284 298 : ExpressionNode(location) … … 999 1013 } 1000 1014 1015 inline DefineFieldNode::DefineFieldNode(const JSTokenLocation& location, const Identifier* ident, ExpressionNode* assign, Type type) 1016 : StatementNode(location) 1017 , m_ident(ident) 1018 , m_assign(assign) 1019 , m_type(type) 1020 { 1021 } 1022 1001 1023 inline ClassDeclNode::ClassDeclNode(const JSTokenLocation& location, ExpressionNode* classDeclaration) 1002 1024 : StatementNode(location) … … 1014 1036 , m_classHeritage(classHeritage) 1015 1037 , m_classElements(classElements) 1038 , m_needsLexicalScope(!name.isNull() || PropertyListNode::shouldCreateLexicalScopeForClass(classElements)) 1016 1039 { 1017 1040 } -
trunk/Source/JavaScriptCore/parser/Nodes.cpp
r253987 r254653 201 201 , m_superBinding(static_cast<unsigned>(superBinding)) 202 202 , m_constructorKind(static_cast<unsigned>(constructorKind)) 203 , m_needsClassFieldInitializer(static_cast<unsigned>(NeedsClassFieldInitializer::No)) 203 204 , m_isArrowFunctionBodyExpression(isArrowFunctionBodyExpression) 204 205 , m_parseMode(mode) … … 224 225 , m_superBinding(static_cast<unsigned>(superBinding)) 225 226 , m_constructorKind(static_cast<unsigned>(constructorKind)) 227 , m_needsClassFieldInitializer(static_cast<unsigned>(NeedsClassFieldInitializer::No)) 226 228 , m_isArrowFunctionBodyExpression(isArrowFunctionBodyExpression) 227 229 , m_parseMode(mode) … … 329 331 } 330 332 333 // FIXME: calculate this feature once when parsing the property list. 334 // https://bugs.webkit.org/show_bug.cgi?id=206174 335 bool PropertyListNode::shouldCreateLexicalScopeForClass(PropertyListNode* list) 336 { 337 while (list) { 338 if (list->m_node->isComputedClassField()) 339 return true; 340 list = list->m_next; 341 } 342 return false; 343 } 344 345 // ------------------------------ ClassExprNode ----------------------------- 346 347 // FIXME: calculate this feature once when parsing the property list. 348 // https://bugs.webkit.org/show_bug.cgi?id=206174 349 bool PropertyListNode::hasInstanceFields() const 350 { 351 for (auto list = this; list; list = list->m_next) { 352 if (list->m_node->isInstanceClassField()) 353 return true; 354 } 355 return false; 356 } 357 331 358 VariableEnvironmentNode::VariableEnvironmentNode(VariableEnvironment& lexicalVariables) 332 359 { -
trunk/Source/JavaScriptCore/parser/Nodes.h
r253987 r254653 252 252 virtual bool isModuleDeclarationNode() const { return false; } 253 253 virtual bool isForOfNode() const { return false; } 254 virtual bool isDefineFieldNode() const { return false; } 254 255 255 256 protected: … … 719 720 PropertyNode(ExpressionNode*, Type, PutType, SuperBinding, ClassElementTag); 720 721 PropertyNode(ExpressionNode* propertyName, ExpressionNode*, Type, PutType, SuperBinding, ClassElementTag); 722 PropertyNode(const Identifier&, ExpressionNode* propertyName, ExpressionNode*, Type, PutType, SuperBinding, ClassElementTag); 721 723 722 724 ExpressionNode* expressionName() const { return m_expression; } … … 728 730 bool isStaticClassProperty() const { return static_cast<ClassElementTag>(m_classElementTag) == ClassElementTag::Static; } 729 731 bool isInstanceClassProperty() const { return static_cast<ClassElementTag>(m_classElementTag) == ClassElementTag::Instance; } 732 bool isClassField() const { return isClassProperty() && !needsSuperBinding(); } 733 bool isInstanceClassField() const { return isInstanceClassProperty() && !needsSuperBinding(); } 730 734 bool isOverriddenByDuplicate() const { return m_isOverriddenByDuplicate; } 735 bool hasComputedName() const { return m_expression; } 736 bool isComputedClassField() const { return isClassField() && hasComputedName(); } 731 737 void setIsOverriddenByDuplicate() { m_isOverriddenByDuplicate = true; } 732 738 PutType putType() const { return static_cast<PutType>(m_putType); } … … 742 748 static_assert(1 << 2 > static_cast<unsigned>(ClassElementTag::LastTag), "ClassElementTag shouldn't use more than two bits"); 743 749 unsigned m_classElementTag : 2; 744 unsigned m_isOverriddenByDuplicate : 1;750 unsigned m_isOverriddenByDuplicate : 1; 745 751 }; 746 752 … … 751 757 752 758 bool hasStaticallyNamedProperty(const Identifier& propName); 753 754 RegisterID* emitBytecode(BytecodeGenerator&, RegisterID*, RegisterID*); 759 bool isComputedClassField() const 760 { 761 return m_node->isComputedClassField(); 762 } 763 bool isInstanceClassField() const 764 { 765 return m_node->isInstanceClassField(); 766 } 767 bool hasInstanceFields() const; 768 769 static bool shouldCreateLexicalScopeForClass(PropertyListNode*); 770 771 RegisterID* emitBytecode(BytecodeGenerator&, RegisterID*, RegisterID*, Vector<JSTextPosition>*); 755 772 756 773 private: 757 774 RegisterID* emitBytecode(BytecodeGenerator& generator, RegisterID* dst = nullptr) override 758 775 { 759 return emitBytecode(generator, dst, nullptr );776 return emitBytecode(generator, dst, nullptr, nullptr); 760 777 } 761 778 void emitPutConstantProperty(BytecodeGenerator&, RegisterID*, PropertyNode&); 779 void emitSaveComputedFieldName(BytecodeGenerator&, PropertyNode&); 762 780 763 781 PropertyNode* m_node; … … 2075 2093 SuperBinding superBinding() { return static_cast<SuperBinding>(m_superBinding); } 2076 2094 ConstructorKind constructorKind() { return static_cast<ConstructorKind>(m_constructorKind); } 2095 bool isConstructorAndNeedsClassFieldInitializer() const { return m_needsClassFieldInitializer; } 2096 void setNeedsClassFieldInitializer(bool value) 2097 { 2098 ASSERT(!value || constructorKind() != ConstructorKind::None); 2099 m_needsClassFieldInitializer = value; 2100 } 2077 2101 bool isArrowFunctionBodyExpression() const { return m_isArrowFunctionBodyExpression; } 2078 2102 … … 2095 2119 unsigned m_superBinding : 1; 2096 2120 unsigned m_constructorKind : 2; 2121 unsigned m_needsClassFieldInitializer : 1; 2097 2122 unsigned m_isArrowFunctionBodyExpression : 1; 2098 2123 SourceParseMode m_parseMode; … … 2211 2236 }; 2212 2237 2238 class DefineFieldNode final : public StatementNode { 2239 public: 2240 enum class Type { Name, ComputedName }; 2241 DefineFieldNode(const JSTokenLocation&, const Identifier*, ExpressionNode*, Type); 2242 2243 private: 2244 void emitBytecode(BytecodeGenerator&, RegisterID* destination = nullptr) override; 2245 2246 bool isDefineFieldNode() const override { return true; } 2247 2248 const Identifier* m_ident; 2249 ExpressionNode* m_assign; 2250 Type m_type; 2251 }; 2252 2213 2253 class ClassExprNode final : public ExpressionNode, public VariableEnvironmentNode { 2214 2254 JSC_MAKE_PARSER_ARENA_DELETABLE_ALLOCATED(ClassExprNode); … … 2223 2263 2224 2264 bool hasStaticProperty(const Identifier& propName) { return m_classElements ? m_classElements->hasStaticallyNamedProperty(propName) : false; } 2265 bool hasInstanceFields() const { return m_classElements ? m_classElements->hasInstanceFields() : false; } 2225 2266 2226 2267 private: … … 2235 2276 ExpressionNode* m_classHeritage; 2236 2277 PropertyListNode* m_classElements; 2278 bool m_needsLexicalScope; 2237 2279 }; 2238 2280 -
trunk/Source/JavaScriptCore/parser/Parser.cpp
r251684 r254653 209 209 210 210 template <typename LexerType> 211 String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMode parseMode, ParsingContext parsingContext, Optional<int> functionConstructorParametersEndPosition )211 String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMode parseMode, ParsingContext parsingContext, Optional<int> functionConstructorParametersEndPosition, const Vector<JSTextPosition>* instanceFieldLocations) 212 212 { 213 213 String parseError = String(); … … 223 223 if (isGeneratorOrAsyncFunctionBodyParseMode(parseMode)) 224 224 m_parameters = createGeneratorParameters(context, functionInfo.parameterCount); 225 else if (parseMode == SourceParseMode::InstanceFieldInitializerMode) 226 m_parameters = context.createFormalParameterList(); 225 227 else 226 228 m_parameters = parseFunctionParameters(context, parseMode, functionInfo); … … 255 257 else if (parsingContext == ParsingContext::FunctionConstructor) 256 258 sourceElements = parseSingleFunction(context, functionConstructorParametersEndPosition); 257 else 259 else if (parseMode == SourceParseMode::InstanceFieldInitializerMode) { 260 ASSERT(instanceFieldLocations && !instanceFieldLocations->isEmpty()); 261 sourceElements = parseInstanceFieldInitializerSourceElements(context, *instanceFieldLocations); 262 } else 258 263 sourceElements = parseSourceElements(context, CheckForStrictMode); 259 264 } … … 2114 2119 ConstructorKind constructorKind, SuperBinding superBinding, FunctionBodyType bodyType, unsigned parameterCount, SourceParseMode parseMode) 2115 2120 { 2121 SetForScope<bool> overrideParsingClassFieldInitializer(m_parserState.isParsingClassFieldInitializer, bodyType == StandardFunctionBodyBlock ? false : m_parserState.isParsingClassFieldInitializer); 2116 2122 bool isArrowFunctionBodyExpression = bodyType == ArrowFunctionBodyExpression; 2117 2123 if (!isArrowFunctionBodyExpression) { … … 2166 2172 case SourceParseMode::ModuleAnalyzeMode: 2167 2173 case SourceParseMode::ModuleEvaluateMode: 2174 case SourceParseMode::InstanceFieldInitializerMode: 2168 2175 RELEASE_ASSERT_NOT_REACHED(); 2169 2176 return ""; … … 2207 2214 case SourceParseMode::ModuleAnalyzeMode: 2208 2215 case SourceParseMode::ModuleEvaluateMode: 2216 case SourceParseMode::InstanceFieldInitializerMode: 2209 2217 RELEASE_ASSERT_NOT_REACHED(); 2210 2218 return ""; … … 2854 2862 failIfFalse(parentClass, "Cannot parse the parent class name"); 2855 2863 } 2864 classScope->setIsClassScope(); 2856 2865 const ConstructorKind constructorKind = parentClass ? ConstructorKind::Extends : ConstructorKind::Base; 2857 2866 … … 2861 2870 TreePropertyList classElements = 0; 2862 2871 TreePropertyList classElementsTail = 0; 2872 unsigned numComputedFields = 0; 2863 2873 while (!match(CLOSEBRACE)) { 2864 2874 if (match(SEMICOLON)) { … … 2872 2882 // For backwards compatibility, "static" is a non-reserved keyword in non-strict mode. 2873 2883 ClassElementTag tag = ClassElementTag::Instance; 2884 auto type = PropertyNode::Constant; 2874 2885 if (match(RESERVED_IF_STRICT) && *m_token.m_data.ident == m_vm.propertyNames->staticKeyword) { 2875 2886 SavePoint savePoint = createSavePoint(); … … 2905 2916 ident = m_token.m_data.ident; 2906 2917 next(); 2907 if (match(OPENPAREN) || match(COLON) || match(EQUAL) || m_lexer->hasLineTerminatorBeforeToken()) 2918 // We match SEMICOLON as a special case for a field called 'async' without initializer. 2919 if (match(OPENPAREN) || match(COLON) || match(SEMICOLON) || match(EQUAL) || m_lexer->hasLineTerminatorBeforeToken()) 2908 2920 break; 2909 2921 if (UNLIKELY(consume(TIMES))) … … 2933 2945 next(); 2934 2946 computedPropertyName = parseAssignmentExpression(context); 2947 type = static_cast<PropertyNode::Type>(type | PropertyNode::Computed); 2935 2948 failIfFalse(computedPropertyName, "Cannot parse computed property name"); 2936 2949 handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name"); … … 2945 2958 const bool alwaysStrictInsideClass = true; 2946 2959 if (isGetter || isSetter) { 2947 property = parseGetterSetter(context, alwaysStrictInsideClass, isGetter ? PropertyNode::Getter : PropertyNode::Setter, 2948 methodStart, ConstructorKind::None, tag); 2960 type = static_cast<PropertyNode::Type>(type & ~PropertyNode::Constant); 2961 type = static_cast<PropertyNode::Type>(type | (isGetter ? PropertyNode::Getter : PropertyNode::Setter)); 2962 property = parseGetterSetter(context, alwaysStrictInsideClass, type, methodStart, ConstructorKind::None, tag); 2949 2963 failIfFalse(property, "Cannot parse this method"); 2964 } else if (Options::useClassFields() && !match(OPENPAREN) && tag == ClassElementTag::Instance && parseMode == SourceParseMode::MethodMode) { 2965 ASSERT(!isGetter && !isSetter); 2966 if (ident) 2967 semanticFailIfTrue(*ident == propertyNames.constructor, "Cannot declare class field named 'constructor'"); 2968 2969 if (computedPropertyName) { 2970 ident = &m_parserArena.identifierArena().makeNumericIdentifier(m_vm, numComputedFields++); 2971 DeclarationResultMask declarationResult = classScope->declareLexicalVariable(ident, true); 2972 ASSERT_UNUSED(declarationResult, declarationResult == DeclarationResult::Valid); 2973 classScope->useVariable(ident, false); 2974 classScope->addClosedVariableCandidateUnconditionally(ident->impl()); 2975 } 2976 2977 TreeExpression initializer = 0; 2978 if (consume(EQUAL)) { 2979 SetForScope<bool> overrideParsingClassFieldInitializer(m_parserState.isParsingClassFieldInitializer, true); 2980 classScope->setExpectedSuperBinding(SuperBinding::Needed); 2981 initializer = parseAssignmentExpression(context); 2982 classScope->setExpectedSuperBinding(SuperBinding::NotNeeded); 2983 failIfFalse(initializer, "Cannot parse initializer for class field"); 2984 classScope->markLastUsedVariablesSetAsCaptured(); 2985 } 2986 failIfFalse(autoSemiColon(), "Expected a ';' following a class field"); 2987 auto inferName = initializer ? InferName::Allowed : InferName::Disallowed; 2988 if (computedPropertyName) 2989 property = context.createProperty(ident, computedPropertyName, initializer, type, PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::NotNeeded, tag); 2990 else 2991 property = context.createProperty(ident, initializer, type, PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::NotNeeded, inferName, tag); 2950 2992 } else { 2951 2993 ParserFunctionInfo<TreeBuilder> methodInfo; … … 2972 3014 2973 3015 if (computedPropertyName) { 2974 property = context.createProperty(computedPropertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), 2975 PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed, tag); 3016 property = context.createProperty(computedPropertyName, method, type, PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed, tag); 2976 3017 } else { 2977 property = context.createProperty(methodInfo.name, method, PropertyNode::Constant, 2978 PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed, InferName::Allowed, tag); 3018 property = context.createProperty(methodInfo.name, method, type, PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed, InferName::Allowed, tag); 2979 3019 } 2980 3020 } … … 2992 3032 popScope(classScope, TreeBuilder::NeedsFreeVariableInfo); 2993 3033 return classExpression; 3034 } 3035 3036 template <typename LexerType> 3037 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseInstanceFieldInitializerSourceElements(TreeBuilder& context, const Vector<JSTextPosition>& instanceFieldLocations) 3038 { 3039 TreeSourceElements sourceElements = context.createSourceElements(); 3040 currentScope()->setIsClassScope(); 3041 3042 unsigned numComputedFields = 0; 3043 for (auto location : instanceFieldLocations) { 3044 // We don't need to worry about hasLineTerminatorBeforeToken 3045 // on class fields, so we set this value to false. 3046 LexerState lexerState { location.offset, static_cast<unsigned>(location.lineStartOffset), static_cast<unsigned>(location.line), static_cast<unsigned>(location.line), false }; 3047 restoreLexerState(lexerState); 3048 3049 JSTokenLocation fieldLocation = tokenLocation(); 3050 const Identifier* ident = nullptr; 3051 TreeExpression computedPropertyName = 0; 3052 DefineFieldNode::Type type = DefineFieldNode::Type::Name; 3053 switch (m_token.m_type) { 3054 case STRING: 3055 case IDENT: 3056 namedKeyword: 3057 ident = m_token.m_data.ident; 3058 ASSERT(ident); 3059 next(); 3060 break; 3061 case DOUBLE: 3062 case INTEGER: 3063 ident = &m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM&>(m_vm), m_token.m_data.doubleValue); 3064 ASSERT(ident); 3065 next(); 3066 break; 3067 case OPENBRACKET: 3068 next(); 3069 computedPropertyName = parseAssignmentExpression(context); 3070 failIfFalse(computedPropertyName, "Cannot parse computed property name"); 3071 handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name"); 3072 ident = &m_parserArena.identifierArena().makeNumericIdentifier(m_vm, numComputedFields++); 3073 type = DefineFieldNode::Type::ComputedName; 3074 break; 3075 default: 3076 if (m_token.m_type & KeywordTokenFlag) 3077 goto namedKeyword; 3078 failDueToUnexpectedToken(); 3079 } 3080 3081 // Only valid class fields are handled in this function. 3082 ASSERT(match(EQUAL) || match(SEMICOLON) || match(CLOSEBRACE) || m_lexer->hasLineTerminatorBeforeToken()); 3083 3084 TreeExpression initializer = 0; 3085 if (consume(EQUAL)) 3086 initializer = parseAssignmentExpression(context); 3087 3088 TreeStatement defineField = context.createDefineField(fieldLocation, ident, initializer, type); 3089 context.appendStatement(sourceElements, defineField); 3090 } 3091 3092 ASSERT(!hasError()); 3093 // Trick parseInner() into believing we've parsed the entire SourceCode, in order to prevent it from producing an error. 3094 m_token.m_type = EOFTOK; 3095 return sourceElements; 2994 3096 } 2995 3097 … … 4485 4587 return createResolveAndUseVariable(context, ident, isEval, start, location); 4486 4588 } 4589 if (UNLIKELY(m_parserState.isParsingClassFieldInitializer)) 4590 failIfTrue(*m_token.m_data.ident == m_vm.propertyNames->arguments, "Cannot reference 'arguments' in class field initializer"); 4487 4591 identifierExpression: 4488 4592 JSTextPosition start = tokenStartPosition(); 4489 4593 const Identifier* ident = m_token.m_data.ident; 4594 if (UNLIKELY(currentScope()->evalContextType() == EvalContextType::InstanceFieldEvalContext)) 4595 failIfTrue(*ident == m_vm.propertyNames->arguments, "arguments is not valid in this context"); 4490 4596 JSTokenLocation location(tokenLocation()); 4491 4597 next(); … … 4682 4788 if (matchContextualKeyword(m_vm.propertyNames->target)) { 4683 4789 ScopeRef closestOrdinaryFunctionScope = closestParentOrdinaryFunctionNonLexicalScope(); 4684 semanticFailIfFalse(currentScope()->isFunction() || closestOrdinaryFunctionScope->evalContextType() == EvalContextType::FunctionEvalContext, "new.target is only valid inside functions"); 4790 ScopeRef classScope = closestClassScopeOrTopLevelScope(); 4791 bool isClassFieldInitializer = classScope.index() > closestOrdinaryFunctionScope.index(); 4792 bool isFunctionEvalContextType = closestOrdinaryFunctionScope->evalContextType() == EvalContextType::FunctionEvalContext || closestOrdinaryFunctionScope->evalContextType() == EvalContextType::InstanceFieldEvalContext; 4793 semanticFailIfFalse(currentScope()->isFunction() || isFunctionEvalContextType || isClassFieldInitializer, "new.target is only valid inside functions"); 4685 4794 baseIsNewTarget = true; 4686 4795 if (currentScope()->isArrowFunction()) { 4687 semanticFailIfFalse(!closestOrdinaryFunctionScope->isGlobalCodeScope() || closestOrdinaryFunctionScope->evalContextType() == EvalContextType::FunctionEvalContext, "new.target is not valid inside arrow functions in global code");4796 semanticFailIfFalse(!closestOrdinaryFunctionScope->isGlobalCodeScope() || isFunctionEvalContextType || isClassFieldInitializer, "new.target is not valid inside arrow functions in global code"); 4688 4797 currentScope()->setInnerArrowFunctionUsesNewTarget(); 4689 4798 } … … 4702 4811 if (baseIsSuper) { 4703 4812 ScopeRef closestOrdinaryFunctionScope = closestParentOrdinaryFunctionNonLexicalScope(); 4704 semanticFailIfFalse(currentScope()->isFunction() || (closestOrdinaryFunctionScope->isEvalContext() && closestOrdinaryFunctionScope->expectedSuperBinding() == SuperBinding::Needed), "super is not valid in this context"); 4813 ScopeRef classScope = closestClassScopeOrTopLevelScope(); 4814 bool isClassFieldInitializer = classScope.index() > closestOrdinaryFunctionScope.index(); 4815 semanticFailIfFalse(currentScope()->isFunction() || isClassFieldInitializer || (closestOrdinaryFunctionScope->isEvalContext() && closestOrdinaryFunctionScope->expectedSuperBinding() == SuperBinding::Needed), "super is not valid in this context"); 4705 4816 base = context.createSuperExpr(location); 4706 4817 next(); 4818 failIfTrue(match(OPENPAREN) && currentScope()->evalContextType() == EvalContextType::InstanceFieldEvalContext, "super call is not valid in this context"); 4707 4819 ScopeRef functionScope = currentFunctionScope(); 4708 4820 if (!functionScope->setNeedsSuperBinding()) { … … 4714 4826 ? functionScope->expectedSuperBinding() 4715 4827 : closestOrdinaryFunctionScope->expectedSuperBinding(); 4716 semanticFailIfTrue(functionSuperBinding == SuperBinding::NotNeeded , "super is not valid in this context");4828 semanticFailIfTrue(functionSuperBinding == SuperBinding::NotNeeded && !isClassFieldInitializer, "super is not valid in this context"); 4717 4829 } 4718 4830 } … … 4795 4907 } 4796 4908 case OPENPAREN: { 4909 if (baseIsSuper) 4910 failIfTrue(m_parserState.isParsingClassFieldInitializer, "super call is not valid in class field initializer context"); 4797 4911 m_parserState.nonTrivialExpressionCount++; 4798 4912 int nonLHSCount = m_parserState.nonLHSCount; -
trunk/Source/JavaScriptCore/parser/Parser.h
r251684 r254653 182 182 , m_isEvalContext(false) 183 183 , m_hasNonSimpleParameterList(false) 184 , m_isClassScope(false) 184 185 , m_evalContextType(EvalContextType::None) 185 186 , m_constructorKind(static_cast<unsigned>(ConstructorKind::None)) … … 259 260 case SourceParseMode::SetterMode: 260 261 case SourceParseMode::MethodMode: 262 case SourceParseMode::InstanceFieldInitializerMode: 261 263 setIsFunction(); 262 264 break; … … 288 290 bool isAsyncFunction() const { return m_isAsyncFunction; } 289 291 bool isAsyncFunctionBoundary() const { return m_isAsyncFunctionBoundary; } 292 bool isClassScope() const { return m_isClassScope; } 290 293 291 294 bool hasArguments() const { return m_hasArguments; } … … 302 305 m_allowsLexicalDeclarations = true; 303 306 } 307 308 void setIsClassScope() 309 { 310 m_isClassScope = true; 311 } 312 304 313 bool isLexicalScope() { return m_isLexicalScope; } 305 314 bool usesEval() { return m_usesEval; } … … 581 590 { 582 591 m_closedVariableCandidates.add(impl); 592 } 593 594 void markLastUsedVariablesSetAsCaptured() 595 { 596 for (UniquedStringImpl* impl : m_usedVariables.last()) 597 m_closedVariableCandidates.add(impl); 583 598 } 584 599 … … 820 835 bool m_isEvalContext; 821 836 bool m_hasNonSimpleParameterList; 837 bool m_isClassScope; 822 838 EvalContextType m_evalContextType; 823 839 unsigned m_constructorKind; … … 890 906 891 907 template <class ParsedNode> 892 std::unique_ptr<ParsedNode> parse(ParserError&, const Identifier&, SourceParseMode, ParsingContext, Optional<int> functionConstructorParametersEndPosition = WTF::nullopt );908 std::unique_ptr<ParsedNode> parse(ParserError&, const Identifier&, SourceParseMode, ParsingContext, Optional<int> functionConstructorParametersEndPosition = WTF::nullopt, const Vector<JSTextPosition>* = nullptr); 893 909 894 910 JSTextPosition positionBeforeLastNewline() const { return m_lexer->positionBeforeLastNewline(); } … … 1172 1188 return ScopeRef(&m_scopeStack, i); 1173 1189 } 1174 1190 1191 ScopeRef closestClassScopeOrTopLevelScope() 1192 { 1193 unsigned i = m_scopeStack.size() - 1; 1194 ASSERT(i < m_scopeStack.size()); 1195 while (i && !m_scopeStack[i].isClassScope()) 1196 i--; 1197 return ScopeRef(&m_scopeStack, i); 1198 } 1199 1175 1200 ScopeRef pushScope() 1176 1201 { … … 1348 1373 Parser(); 1349 1374 1350 String parseInner(const Identifier&, SourceParseMode, ParsingContext, Optional<int> functionConstructorParametersEndPosition = WTF::nullopt );1375 String parseInner(const Identifier&, SourceParseMode, ParsingContext, Optional<int> functionConstructorParametersEndPosition = WTF::nullopt, const Vector<JSTextPosition>* = nullptr); 1351 1376 1352 1377 void didFinishParsing(SourceElements*, DeclarationStacks::FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, CodeFeatures, int); … … 1577 1602 template <class TreeBuilder> TreeSourceElements parseAsyncGeneratorFunctionSourceElements(TreeBuilder&, SourceParseMode, bool isArrowFunctionBodyExpression, SourceElementsMode); 1578 1603 template <class TreeBuilder> TreeSourceElements parseSingleFunction(TreeBuilder&, Optional<int> functionConstructorParametersEndPosition); 1604 template <class TreeBuilder> TreeSourceElements parseInstanceFieldInitializerSourceElements(TreeBuilder&, const Vector<JSTextPosition>&); 1579 1605 template <class TreeBuilder> TreeStatement parseStatementListItem(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength); 1580 1606 template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength = 0); … … 1763 1789 const Identifier* lastFunctionName { nullptr }; 1764 1790 bool allowAwait { true }; 1791 bool isParsingClassFieldInitializer { false }; 1765 1792 }; 1766 1793 … … 1903 1930 template <typename LexerType> 1904 1931 template <class ParsedNode> 1905 std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const Identifier& calleeName, SourceParseMode parseMode, ParsingContext parsingContext, Optional<int> functionConstructorParametersEndPosition )1932 std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const Identifier& calleeName, SourceParseMode parseMode, ParsingContext parsingContext, Optional<int> functionConstructorParametersEndPosition, const Vector<JSTextPosition>* instanceFieldLocations) 1906 1933 { 1907 1934 int errLine; … … 1920 1947 unsigned startColumn = m_source->startColumn().zeroBasedInt(); 1921 1948 1922 String parseError = parseInner(calleeName, parseMode, parsingContext, functionConstructorParametersEndPosition );1949 String parseError = parseInner(calleeName, parseMode, parsingContext, functionConstructorParametersEndPosition, instanceFieldLocations); 1923 1950 1924 1951 int lineNumber = m_lexer->lineNumber(); … … 2004 2031 DerivedContextType derivedContextType = DerivedContextType::None, 2005 2032 EvalContextType evalContextType = EvalContextType::None, 2006 DebuggerParseData* debuggerParseData = nullptr) 2033 DebuggerParseData* debuggerParseData = nullptr, 2034 const Vector<JSTextPosition>* instanceFieldLocations = nullptr) 2007 2035 { 2008 2036 ASSERT(!source.provider()->source().isNull()); … … 2015 2043 if (source.provider()->source().is8Bit()) { 2016 2044 Parser<Lexer<LChar>> parser(vm, source, builtinMode, strictMode, scriptMode, parseMode, superBinding, defaultConstructorKindForTopLevelFunction, derivedContextType, isEvalNode<ParsedNode>(), evalContextType, debuggerParseData); 2017 result = parser.parse<ParsedNode>(error, name, parseMode, isEvalNode<ParsedNode>() ? ParsingContext::Eval : ParsingContext::Program );2045 result = parser.parse<ParsedNode>(error, name, parseMode, isEvalNode<ParsedNode>() ? ParsingContext::Eval : ParsingContext::Program, WTF::nullopt, instanceFieldLocations); 2018 2046 if (positionBeforeLastNewline) 2019 2047 *positionBeforeLastNewline = parser.positionBeforeLastNewline(); … … 2028 2056 ASSERT_WITH_MESSAGE(defaultConstructorKindForTopLevelFunction == ConstructorKind::None, "BuiltinExecutables's special constructors should always use a 8-bit string"); 2029 2057 Parser<Lexer<UChar>> parser(vm, source, builtinMode, strictMode, scriptMode, parseMode, superBinding, defaultConstructorKindForTopLevelFunction, derivedContextType, isEvalNode<ParsedNode>(), evalContextType, debuggerParseData); 2030 result = parser.parse<ParsedNode>(error, name, parseMode, isEvalNode<ParsedNode>() ? ParsingContext::Eval : ParsingContext::Program );2058 result = parser.parse<ParsedNode>(error, name, parseMode, isEvalNode<ParsedNode>() ? ParsingContext::Eval : ParsingContext::Program, WTF::nullopt, instanceFieldLocations); 2031 2059 if (positionBeforeLastNewline) 2032 2060 *positionBeforeLastNewline = parser.positionBeforeLastNewline(); -
trunk/Source/JavaScriptCore/parser/ParserModes.h
r249509 r254653 67 67 AsyncGeneratorWrapperMethodMode = 17, 68 68 GeneratorWrapperMethodMode = 18, 69 InstanceFieldInitializerMode = 19, 69 70 }; 70 71 … … 115 116 SourceParseMode::AsyncGeneratorBodyMode, 116 117 SourceParseMode::AsyncGeneratorWrapperFunctionMode, 117 SourceParseMode::AsyncGeneratorWrapperMethodMode).contains(parseMode); 118 SourceParseMode::AsyncGeneratorWrapperMethodMode, 119 SourceParseMode::InstanceFieldInitializerMode).contains(parseMode); 118 120 } 119 121 -
trunk/Source/JavaScriptCore/parser/SyntaxChecker.h
r251684 r254653 237 237 return Property(type); 238 238 } 239 Property createProperty(const Identifier*, int, int, PropertyNode::Type type, PropertyNode::PutType, bool, SuperBinding, ClassElementTag) 240 { 241 return Property(type); 242 } 239 243 int createPropertyList(const JSTokenLocation&, Property) { return PropertyListResult; } 240 244 int createPropertyList(const JSTokenLocation&, Property, int) { return PropertyListResult; } … … 248 252 int createClauseList(int, int) { return ClauseListResult; } 249 253 int createFuncDeclStatement(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return StatementResult; } 254 int createDefineField(const JSTokenLocation&, const Identifier*, int, DefineFieldNode::Type) { return 0; } 250 255 int createClassDeclStatement(const JSTokenLocation&, ClassExpression, 251 256 const JSTextPosition&, const JSTextPosition&, int, int) { return StatementResult; } -
trunk/Source/JavaScriptCore/runtime/CachedTypes.cpp
r254632 r254653 938 938 m_bitVectors.encode(encoder, rareData.m_bitVectors); 939 939 m_constantIdentifierSets.encode(encoder, rareData.m_constantIdentifierSets); 940 m_needsClassFieldInitializer = rareData.m_needsClassFieldInitializer; 940 941 } 941 942 … … 951 952 m_bitVectors.decode(decoder, rareData->m_bitVectors); 952 953 m_constantIdentifierSets.decode(decoder, rareData->m_constantIdentifierSets); 954 rareData->m_needsClassFieldInitializer = m_needsClassFieldInitializer; 953 955 return rareData; 954 956 } … … 963 965 CachedVector<CachedBitVector> m_bitVectors; 964 966 CachedVector<CachedConstantIdentifierSetEntry> m_constantIdentifierSets; 967 unsigned m_needsClassFieldInitializer : 1; 965 968 }; 966 969 … … 1702 1705 unsigned superBinding() const { return m_superBinding; } 1703 1706 unsigned derivedContextType() const { return m_derivedContextType; } 1707 unsigned needsClassFieldInitializer() const { return m_needsClassFieldInitializer; } 1704 1708 1705 1709 Identifier name(Decoder& decoder) const { return m_name.decode(decoder); } … … 1735 1739 unsigned m_functionMode : 2; // FunctionMode 1736 1740 unsigned m_derivedContextType: 2; 1741 unsigned m_needsClassFieldInitializer : 1; 1737 1742 1738 1743 CachedPtr<CachedFunctionExecutableRareData> m_rareData; … … 1787 1792 unsigned constructorKind() const { return m_constructorKind; } 1788 1793 unsigned derivedContextType() const { return m_derivedContextType; } 1794 unsigned needsClassFieldInitializer() const { return m_needsClassFieldInitializer; } 1789 1795 unsigned evalContextType() const { return m_evalContextType; } 1790 1796 unsigned hasTailCalls() const { return m_hasTailCalls; } … … 1818 1824 unsigned m_constructorKind : 2; 1819 1825 unsigned m_derivedContextType : 2; 1826 unsigned m_needsClassFieldInitializer : 1; 1820 1827 unsigned m_evalContextType : 2; 1821 1828 unsigned m_hasTailCalls : 1; … … 2096 2103 m_superBinding = executable.m_superBinding; 2097 2104 m_derivedContextType = executable.m_derivedContextType; 2105 m_needsClassFieldInitializer = executable.m_needsClassFieldInitializer; 2098 2106 2099 2107 m_rareData.encode(encoder, executable.m_rareData.get()); … … 2143 2151 , m_derivedContextType(cachedExecutable.derivedContextType()) 2144 2152 , m_isGeneratedFromCache(true) 2153 , m_needsClassFieldInitializer(cachedExecutable.needsClassFieldInitializer()) 2145 2154 , m_unlinkedCodeBlockForCall() 2146 2155 , m_unlinkedCodeBlockForConstruct() -
trunk/Source/JavaScriptCore/runtime/CodeCache.cpp
r251263 r254653 150 150 // in the global lexical environment, which we always TDZ check accesses from. 151 151 ConstructAbility constructAbility = constructAbilityForParseMode(metadata->parseMode()); 152 UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(vm, source, metadata, UnlinkedNormalFunction, constructAbility, JSParserScriptMode::Classic, WTF::nullopt, DerivedContextType::None );152 UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(vm, source, metadata, UnlinkedNormalFunction, constructAbility, JSParserScriptMode::Classic, WTF::nullopt, DerivedContextType::None, NeedsClassFieldInitializer::No); 153 153 154 154 if (!source.provider()->sourceURLDirective().isNull()) -
trunk/Source/JavaScriptCore/runtime/CodeCache.h
r251263 r254653 280 280 bool usesEval = rootNode->features() & EvalFeature; 281 281 bool isStrictMode = rootNode->features() & StrictModeFeature; 282 ExecutableInfo executableInfo(usesEval, isStrictMode, false, false, ConstructorKind::None, scriptMode, SuperBinding::NotNeeded, CacheTypes<UnlinkedCodeBlockType>::parseMode, derivedContextType, isArrowFunctionContext, false, evalContextType); 282 NeedsClassFieldInitializer needsClassFieldInitializer = NeedsClassFieldInitializer::No; 283 if constexpr (std::is_same_v<ExecutableType, DirectEvalExecutable>) 284 needsClassFieldInitializer = executable->needsClassFieldInitializer(); 285 ExecutableInfo executableInfo(usesEval, isStrictMode, false, false, ConstructorKind::None, scriptMode, SuperBinding::NotNeeded, CacheTypes<UnlinkedCodeBlockType>::parseMode, derivedContextType, needsClassFieldInitializer, isArrowFunctionContext, false, evalContextType); 283 286 284 287 UnlinkedCodeBlockType* unlinkedCodeBlock = UnlinkedCodeBlockType::create(vm, executableInfo, codeGenerationMode); -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
r254632 r254653 1016 1016 } 1017 1017 1018 SLOW_PATH_DECL(slow_path_to_property_key) 1019 { 1020 BEGIN(); 1021 auto bytecode = pc->as<OpToPropertyKey>(); 1022 RETURN(GET_C(bytecode.m_src).jsValue().toPropertyKeyValue(globalObject)); 1023 } 1024 1018 1025 SLOW_PATH_DECL(slow_path_get_enumerable_length) 1019 1026 { -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h
r253867 r254653 368 368 SLOW_PATH_HIDDEN_DECL(slow_path_strcat); 369 369 SLOW_PATH_HIDDEN_DECL(slow_path_to_primitive); 370 SLOW_PATH_HIDDEN_DECL(slow_path_to_property_key); 370 371 SLOW_PATH_HIDDEN_DECL(slow_path_get_enumerable_length); 371 372 SLOW_PATH_HIDDEN_DECL(slow_path_has_generic_property); -
trunk/Source/JavaScriptCore/runtime/DirectEvalExecutable.cpp
r251425 r254653 36 36 namespace JSC { 37 37 38 DirectEvalExecutable* DirectEvalExecutable::create(JSGlobalObject* globalObject, const SourceCode& source, bool isInStrictContext, DerivedContextType derivedContextType, bool isArrowFunctionContext, EvalContextType evalContextType, const VariableEnvironment* variablesUnderTDZ)38 DirectEvalExecutable* DirectEvalExecutable::create(JSGlobalObject* globalObject, const SourceCode& source, bool isInStrictContext, DerivedContextType derivedContextType, NeedsClassFieldInitializer needsClassFieldInitializer, bool isArrowFunctionContext, EvalContextType evalContextType, const VariableEnvironment* variablesUnderTDZ) 39 39 { 40 40 VM& vm = globalObject->vm(); … … 46 46 } 47 47 48 auto* executable = new (NotNull, allocateCell<DirectEvalExecutable>(vm.heap)) DirectEvalExecutable(globalObject, source, isInStrictContext, derivedContextType, isArrowFunctionContext, evalContextType);48 auto* executable = new (NotNull, allocateCell<DirectEvalExecutable>(vm.heap)) DirectEvalExecutable(globalObject, source, isInStrictContext, derivedContextType, needsClassFieldInitializer, isArrowFunctionContext, evalContextType); 49 49 executable->finishCreation(vm); 50 50 … … 70 70 } 71 71 72 DirectEvalExecutable::DirectEvalExecutable(JSGlobalObject* globalObject, const SourceCode& source, bool inStrictContext, DerivedContextType derivedContextType, bool isArrowFunctionContext, EvalContextType evalContextType)73 : EvalExecutable(globalObject, source, inStrictContext, derivedContextType, isArrowFunctionContext, evalContextType )72 DirectEvalExecutable::DirectEvalExecutable(JSGlobalObject* globalObject, const SourceCode& source, bool inStrictContext, DerivedContextType derivedContextType, NeedsClassFieldInitializer needsClassFieldInitializer, bool isArrowFunctionContext, EvalContextType evalContextType) 73 : EvalExecutable(globalObject, source, inStrictContext, derivedContextType, isArrowFunctionContext, evalContextType, needsClassFieldInitializer) 74 74 { 75 ASSERT(needsClassFieldInitializer == NeedsClassFieldInitializer::No || derivedContextType == DerivedContextType::DerivedConstructorContext); 75 76 } 76 77 -
trunk/Source/JavaScriptCore/runtime/DirectEvalExecutable.h
r251425 r254653 32 32 class DirectEvalExecutable final : public EvalExecutable { 33 33 public: 34 static DirectEvalExecutable* create(JSGlobalObject*, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isArrowFunctionContext, EvalContextType, const VariableEnvironment*);34 static DirectEvalExecutable* create(JSGlobalObject*, const SourceCode&, bool isInStrictContext, DerivedContextType, NeedsClassFieldInitializer, bool isArrowFunctionContext, EvalContextType, const VariableEnvironment*); 35 35 private: 36 DirectEvalExecutable(JSGlobalObject*, const SourceCode&, bool inStrictContext, DerivedContextType, bool isArrowFunctionContext, EvalContextType);36 DirectEvalExecutable(JSGlobalObject*, const SourceCode&, bool inStrictContext, DerivedContextType, NeedsClassFieldInitializer, bool isArrowFunctionContext, EvalContextType); 37 37 }; 38 38 -
trunk/Source/JavaScriptCore/runtime/EvalExecutable.cpp
r251425 r254653 34 34 const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(EvalExecutable) }; 35 35 36 EvalExecutable::EvalExecutable(JSGlobalObject* globalObject, const SourceCode& source, bool inStrictContext, DerivedContextType derivedContextType, bool isArrowFunctionContext, EvalContextType evalContextType )36 EvalExecutable::EvalExecutable(JSGlobalObject* globalObject, const SourceCode& source, bool inStrictContext, DerivedContextType derivedContextType, bool isArrowFunctionContext, EvalContextType evalContextType, NeedsClassFieldInitializer needsClassFieldInitializer) 37 37 : Base(globalObject->vm().evalExecutableStructure.get(), globalObject->vm(), source, inStrictContext, derivedContextType, isArrowFunctionContext, evalContextType, NoIntrinsic) 38 , m_needsClassFieldInitializer(static_cast<unsigned>(needsClassFieldInitializer)) 38 39 { 39 40 ASSERT(source.provider()->sourceType() == SourceProviderSourceType::Program); -
trunk/Source/JavaScriptCore/runtime/EvalExecutable.h
r251425 r254653 63 63 DECLARE_INFO; 64 64 65 ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, JSParserScriptMode::Classic, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext(), false, evalContextType()); }65 ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, JSParserScriptMode::Classic, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), needsClassFieldInitializer(), isArrowFunctionContext(), false, evalContextType()); } 66 66 67 67 unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); } … … 69 69 unsigned numTopLevelFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); } 70 70 bool allowDirectEvalCache() const { return m_unlinkedEvalCodeBlock->allowDirectEvalCache(); } 71 71 NeedsClassFieldInitializer needsClassFieldInitializer() const { return static_cast<NeedsClassFieldInitializer>(m_needsClassFieldInitializer); } 72 72 TemplateObjectMap& ensureTemplateObjectMap(VM&); 73 73 … … 77 77 78 78 using Base::finishCreation; 79 EvalExecutable(JSGlobalObject*, const SourceCode&, bool inStrictContext, DerivedContextType, bool isArrowFunctionContext, EvalContextType );79 EvalExecutable(JSGlobalObject*, const SourceCode&, bool inStrictContext, DerivedContextType, bool isArrowFunctionContext, EvalContextType, NeedsClassFieldInitializer); 80 80 81 81 static void visitChildren(JSCell*, SlotVisitor&); 82 83 unsigned m_needsClassFieldInitializer : 1; 82 84 83 85 WriteBarrier<ExecutableToCodeBlockEdge> m_evalCodeBlock; -
trunk/Source/JavaScriptCore/runtime/FunctionPrototype.cpp
r252520 r254653 114 114 115 115 case SourceParseMode::ArrowFunctionMode: 116 case SourceParseMode::InstanceFieldInitializerMode: 116 117 functionHeader = ""; 117 118 break; -
trunk/Source/JavaScriptCore/runtime/IndirectEvalExecutable.cpp
r251425 r254653 70 70 71 71 IndirectEvalExecutable::IndirectEvalExecutable(JSGlobalObject* globalObject, const SourceCode& source, bool inStrictContext, DerivedContextType derivedContextType, bool isArrowFunctionContext, EvalContextType evalContextType) 72 : EvalExecutable(globalObject, source, inStrictContext, derivedContextType, isArrowFunctionContext, evalContextType )72 : EvalExecutable(globalObject, source, inStrictContext, derivedContextType, isArrowFunctionContext, evalContextType, NeedsClassFieldInitializer::No) 73 73 { 74 74 } -
trunk/Source/JavaScriptCore/runtime/JSCJSValue.h
r252032 r254653 274 274 JSString* toStringOrNull(JSGlobalObject*) const; // On exception, this returns null, to make exception checks faster. 275 275 Identifier toPropertyKey(JSGlobalObject*) const; 276 JSValue toPropertyKeyValue(JSGlobalObject*) const; 276 277 WTF::String toWTFString(JSGlobalObject*) const; 277 278 JSObject* toObject(JSGlobalObject*) const; -
trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h
r251425 r254653 692 692 } 693 693 694 ALWAYS_INLINE JSValue JSValue::toPropertyKeyValue(JSGlobalObject* globalObject) const 695 { 696 VM& vm = getVM(globalObject); 697 auto scope = DECLARE_THROW_SCOPE(vm); 698 699 if (isString() || isSymbol()) 700 return *this; 701 702 JSValue primitive = toPrimitive(globalObject, PreferString); 703 RETURN_IF_EXCEPTION(scope, JSValue()); 704 if (primitive.isSymbol()) 705 return primitive; 706 707 RELEASE_AND_RETURN(scope, primitive.toString(globalObject)); 708 } 709 694 710 inline JSValue JSValue::toPrimitive(JSGlobalObject* globalObject, PreferredPrimitiveType preferredType) const 695 711 { -
trunk/Source/JavaScriptCore/runtime/JSFunction.cpp
r254087 r254653 430 430 case SourceParseMode::AsyncGeneratorWrapperMethodMode: 431 431 case SourceParseMode::GeneratorWrapperMethodMode: 432 case SourceParseMode::InstanceFieldInitializerMode: 432 433 if (!function->jsExecutable()->isStrictMode()) 433 434 return JSValue::encode(caller); -
trunk/Source/JavaScriptCore/runtime/ModuleProgramExecutable.h
r251425 r254653 64 64 DECLARE_INFO; 65 65 66 ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, JSParserScriptMode::Module, SuperBinding::NotNeeded, SourceParseMode::ModuleEvaluateMode, derivedContextType(), isArrowFunctionContext(), false, EvalContextType::None); }66 ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, JSParserScriptMode::Module, SuperBinding::NotNeeded, SourceParseMode::ModuleEvaluateMode, derivedContextType(), NeedsClassFieldInitializer::No, isArrowFunctionContext(), false, EvalContextType::None); } 67 67 68 68 UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock() { return m_unlinkedModuleProgramCodeBlock.get(); } -
trunk/Source/JavaScriptCore/runtime/OptionsList.h
r254558 r254653 497 497 v(Bool, forceOSRExitToLLInt, false, Normal, "If true, we always exit to the LLInt. If false, we exit to whatever is most convenient.") \ 498 498 v(Unsigned, getByValICMaxNumberOfIdentifiers, 4, Normal, "Number of identifiers we see in the LLInt that could cause us to bail on generating an IC for get_by_val.") \ 499 v(Bool, useClassFields, false, Normal, "If true, the parser will understand data fields inside classes.") \ 499 500 500 501 enum OptionEquivalence { -
trunk/Source/JavaScriptCore/runtime/ProgramExecutable.h
r251425 r254653 72 72 DECLARE_INFO; 73 73 74 ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, JSParserScriptMode::Classic, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext(), false, EvalContextType::None); }74 ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, JSParserScriptMode::Classic, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), NeedsClassFieldInitializer::No, isArrowFunctionContext(), false, EvalContextType::None); } 75 75 76 76 TemplateObjectMap& ensureTemplateObjectMap(VM&);
Note: See TracChangeset
for help on using the changeset viewer.