WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-148053-20150903143410.patch (text/plain), 107.43 KB, created by
Yusuke Suzuki
on 2015-09-03 14:34:11 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Yusuke Suzuki
Created:
2015-09-03 14:34:11 PDT
Size:
107.43 KB
patch
obsolete
>Subversion Revision: 189283 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 26c847a7b028c5be283b19f49d1726757016429d..5eb3d8b5b19bd6e7b8185792383efa7f2c241688 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,152 @@ >+2015-09-03 Yusuke Suzuki <utatane.tea@gmail.com> >+ >+ [ES6] Instantiate Module Environment bindings and execute module >+ https://bugs.webkit.org/show_bug.cgi?id=148053 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This patch implements Module Environment binding instantiation. >+ And since the layout of the module environment is tightly coupled with the variable >+ look up in LLInt / Baseline / DFG, we implement the execution part at the same time. >+ >+ For the instantiation, we implement the several operations (like resolveExport) >+ specified in the spec. The original algorithm contains the recursive call, but it is not >+ good for C++ code. We flatten the algorithm by using the manual frames to avoid recursions. >+ By leveraging the information retrieved by the above operations, we instantiate and >+ initialize the slots of the module environment. >+ >+ The module namespace object is not implemented yet in this patch. It will be implemented >+ and instantiated in the module environment in the subsequent patch[1]. >+ >+ To look up the imported module bindings in the JS code, we introduce the "ModuleVar" resolve >+ type for resolve_scope, get_from_scope and put_to_scope. This "ModuleVar" will be filled >+ when linking the CodeBlock. This type is used when treating the imported bindings. >+ >+ 1. For resolve_scope, when linking, we resolve the actual module environment where >+ looked up variable resides and store it directly to the instruction. And resolve_scope >+ simply retrieve the stored pointer from the instruction. >+ >+ 2. For get_from_scope, since "ModuleVar" behavior for get_from_scope is completely same >+ to the "ClosureVar", we just store "ClosureVar" for get_from_scope to eliminate >+ unnecessary branch in LLInt layer. >+ >+ 3. For put_to_scope, we always emit the function call that immediately raises the error. >+ Because all the imported bindings are immutable and module code is always strict code. >+ In DFG, we just emit the ForceOSRExit. We don't make put_to_scope with "ModuleVar" >+ "CannotCompile" because it disables DFG compiling for the function even if this >+ problematic instruction is never executed. >+ >+ Exported module variables inside the original module environment are just treated as the >+ usual heap variables. So the types for closure variables are just used. ("ClosureVar" etc.) >+ >+ [1]: https://bugs.webkit.org/show_bug.cgi?id=148705 >+ >+ * CMakeLists.txt: >+ * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj: >+ * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters: >+ * JavaScriptCore.xcodeproj/project.pbxproj: >+ * bytecode/CodeBlock.cpp: >+ (JSC::CodeBlock::CodeBlock): >+ * bytecode/CodeBlock.h: >+ * bytecode/UnlinkedCodeBlock.cpp: >+ (JSC::UnlinkedModuleProgramCodeBlock::visitChildren): Deleted. >+ * bytecode/UnlinkedCodeBlock.h: >+ * bytecompiler/BytecodeGenerator.cpp: >+ (JSC::BytecodeGenerator::BytecodeGenerator): >+ * dfg/DFGByteCodeParser.cpp: >+ (JSC::DFG::ByteCodeParser::parseBlock): >+ * interpreter/Interpreter.cpp: >+ (JSC::Interpreter::execute): >+ * interpreter/Interpreter.h: >+ * jit/JITOperations.cpp: >+ * jit/JITPropertyAccess.cpp: >+ (JSC::JIT::emit_op_resolve_scope): >+ (JSC::JIT::emitSlow_op_resolve_scope): >+ (JSC::JIT::emit_op_get_from_scope): >+ (JSC::JIT::emit_op_put_to_scope): >+ (JSC::JIT::emitSlow_op_put_to_scope): >+ * jit/JITPropertyAccess32_64.cpp: >+ (JSC::JIT::emit_op_resolve_scope): >+ (JSC::JIT::emitSlow_op_resolve_scope): >+ (JSC::JIT::emit_op_get_from_scope): >+ (JSC::JIT::emit_op_put_to_scope): >+ (JSC::JIT::emitSlow_op_put_to_scope): >+ * llint/LLIntData.cpp: >+ (JSC::LLInt::Data::performAssertions): >+ * llint/LLIntSlowPaths.cpp: >+ (JSC::LLInt::LLINT_SLOW_PATH_DECL): >+ * llint/LowLevelInterpreter.asm: >+ * llint/LowLevelInterpreter32_64.asm: >+ * llint/LowLevelInterpreter64.asm: >+ * parser/ModuleAnalyzer.cpp: >+ (JSC::ModuleAnalyzer::exportVariable): >+ * runtime/CommonSlowPaths.cpp: >+ (JSC::SLOW_PATH_DECL): >+ * runtime/CommonSlowPaths.h: >+ * runtime/Error.cpp: >+ (JSC::throwSyntaxError): >+ * runtime/Error.h: >+ * runtime/Executable.cpp: >+ (JSC::ModuleProgramExecutable::create): >+ (JSC::ModuleProgramExecutable::visitChildren): >+ (JSC::ModuleProgramExecutable::clearCode): >+ * runtime/Executable.h: >+ * runtime/GetPutInfo.h: >+ (JSC::resolveTypeName): >+ (JSC::makeType): >+ (JSC::needsVarInjectionChecks): >+ (JSC::ResolveOp::ResolveOp): >+ * runtime/JSGlobalObject.cpp: >+ (JSC::JSGlobalObject::init): >+ (JSC::JSGlobalObject::visitChildren): >+ * runtime/JSGlobalObject.h: >+ (JSC::JSGlobalObject::moduleEnvironmentStructure): >+ * runtime/JSLexicalEnvironment.h: >+ * runtime/JSModuleEnvironment.cpp: Added. >+ (JSC::JSModuleEnvironment::create): >+ (JSC::JSModuleEnvironment::finishCreation): >+ (JSC::JSModuleEnvironment::visitChildren): >+ (JSC::JSModuleEnvironment::getOwnPropertySlot): >+ (JSC::JSModuleEnvironment::getOwnNonIndexPropertyNames): >+ (JSC::JSModuleEnvironment::put): >+ (JSC::JSModuleEnvironment::deleteProperty): >+ * runtime/JSModuleEnvironment.h: Copied from Source/JavaScriptCore/runtime/JSLexicalEnvironment.h. >+ (JSC::JSModuleEnvironment::create): >+ (JSC::JSModuleEnvironment::createStructure): >+ (JSC::JSModuleEnvironment::offsetOfModuleRecord): >+ (JSC::JSModuleEnvironment::allocationSize): >+ (JSC::JSModuleEnvironment::moduleRecord): >+ (JSC::JSModuleEnvironment::moduleRecordSlot): >+ (JSC::JSModuleEnvironment::JSModuleEnvironment): >+ * runtime/JSModuleRecord.cpp: >+ (JSC::JSModuleRecord::visitChildren): >+ (JSC::JSModuleRecord::appendRequestedModule): >+ (JSC::JSModuleRecord::addStarExportEntry): >+ (JSC::JSModuleRecord::addImportEntry): >+ (JSC::JSModuleRecord::addExportEntry): >+ (JSC::ResolveQuery::ResolveQuery): >+ (JSC::ResolveQuery::isEmptyValue): >+ (JSC::ResolveQuery::isDeletedValue): >+ (JSC::ResolveQueryHash::hash): >+ (JSC::ResolveQueryHash::equal): >+ (JSC::resolveExportLoop): >+ (JSC::JSModuleRecord::link): >+ (JSC::JSModuleRecord::instantiateDeclarations): >+ (JSC::JSModuleRecord::execute): >+ (JSC::JSModuleRecord::dump): >+ * runtime/JSModuleRecord.h: >+ (JSC::JSModuleRecord::exportEntries): >+ (JSC::JSModuleRecord::importEntries): >+ (JSC::JSModuleRecord::starExportEntries): >+ (JSC::JSModuleRecord::moduleEnvironment): >+ (JSC::JSModuleRecord::appendRequestedModule): Deleted. >+ (JSC::JSModuleRecord::addImportEntry): Deleted. >+ (JSC::JSModuleRecord::addExportEntry): Deleted. >+ (JSC::JSModuleRecord::addStarExportEntry): Deleted. >+ * runtime/JSScope.cpp: >+ (JSC::abstractAccess): >+ * runtime/ModuleLoaderObject.cpp: >+ > 2015-09-03 Saam barati <sbarati@apple.com> > > Block scoped variables should be visible across scripts >diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt >index 2d30bb91755724434634da17f32d96a86e0dce74..47e083368933e6633c2fcac935fa4566755f2a7f 100644 >--- a/Source/JavaScriptCore/CMakeLists.txt >+++ b/Source/JavaScriptCore/CMakeLists.txt >@@ -538,6 +538,7 @@ set(JavaScriptCore_RUNTIME_SOURCES > runtime/JSLock.cpp > runtime/JSMap.cpp > runtime/JSMapIterator.cpp >+ runtime/JSModuleEnvironment.cpp > runtime/JSModuleRecord.cpp > runtime/JSNativeStdFunction.cpp > runtime/JSNotAnObject.cpp >diff --git a/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj b/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj >index 42cc5f5a892d3580116974d2bc1b5fe3b5f1317c..1045fb0912859725eb5de907a4d0844ff61db9c3 100644 >--- a/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj >+++ b/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj >@@ -787,6 +787,7 @@ > <ClCompile Include="..\runtime\JSLock.cpp" /> > <ClCompile Include="..\runtime\JSMap.cpp" /> > <ClCompile Include="..\runtime\JSMapIterator.cpp" /> >+ <ClCompile Include="..\runtime\JSModuleEnvironment.cpp" /> > <ClCompile Include="..\runtime\JSModuleRecord.cpp" /> > <ClCompile Include="..\runtime\JSNativeStdFunction.cpp" /> > <ClCompile Include="..\runtime\JSNotAnObject.cpp" /> >@@ -1643,6 +1644,7 @@ > <ClInclude Include="..\runtime\JSLock.h" /> > <ClInclude Include="..\runtime\JSMap.h" /> > <ClInclude Include="..\runtime\JSMapIterator.h" /> >+ <ClInclude Include="..\runtime\JSModuleEnvironment.h" /> > <ClInclude Include="..\runtime\JSModuleRecord.h" /> > <ClInclude Include="..\runtime\JSNativeStdFunction.h" /> > <ClInclude Include="..\runtime\JSNotAnObject.h" /> >diff --git a/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters b/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters >index 5da4fe34934739bb06ae0748e3f982c59c264e97..cf9c4da6b3b28c191cdcec6f7863f62bb35e453b 100644 >--- a/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters >+++ b/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters >@@ -729,6 +729,9 @@ > <ClCompile Include="..\runtime\JSMap.cpp"> > <Filter>runtime</Filter> > </ClCompile> >+ <ClCompile Include="..\runtime\JSModuleEnvironment.cpp"> >+ <Filter>runtime</Filter> >+ </ClCompile> > <ClCompile Include="..\runtime\JSModuleRecord.cpp"> > <Filter>runtime</Filter> > </ClCompile> >@@ -3514,6 +3517,9 @@ > <ClInclude Include="..\runtime\JSMap.h"> > <Filter>runtime</Filter> > </ClInclude> >+ <ClInclude Include="..\runtime\JSModuleEnvironment.h"> >+ <Filter>runtime</Filter> >+ </ClInclude> > <ClInclude Include="..\runtime\JSModuleRecord.h"> > <Filter>runtime</Filter> > </ClInclude> >diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >index f1fd3b5b9fcf2ad86915118c498ed47f76516b45..42572dbcb0453751299a49027e658679971f80a1 100644 >--- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >+++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >@@ -1729,6 +1729,8 @@ > E3963CEE1B73F75000EB4CE5 /* NodesAnalyzeModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3963CEC1B73F75000EB4CE5 /* NodesAnalyzeModule.cpp */; }; > E39DA4A61B7E8B7C0084F33A /* JSModuleRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E39DA4A41B7E8B7C0084F33A /* JSModuleRecord.cpp */; }; > E39DA4A71B7E8B7C0084F33A /* JSModuleRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = E39DA4A51B7E8B7C0084F33A /* JSModuleRecord.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ E3D239C81B829C1C00BBEF67 /* JSModuleEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3D239C61B829C1C00BBEF67 /* JSModuleEnvironment.cpp */; }; >+ E3D239C91B829C1C00BBEF67 /* JSModuleEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = E3D239C71B829C1C00BBEF67 /* JSModuleEnvironment.h */; settings = {ATTRIBUTES = (Private, ); }; }; > E3EF88741B66DF23003F26CB /* JSPropertyNameIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3EF88721B66DF23003F26CB /* JSPropertyNameIterator.cpp */; }; > E3EF88751B66DF23003F26CB /* JSPropertyNameIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E3EF88731B66DF23003F26CB /* JSPropertyNameIterator.h */; settings = {ATTRIBUTES = (Private, ); }; }; > E49DC16B12EF293E00184A1F /* SourceProviderCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E49DC15512EF277200184A1F /* SourceProviderCache.cpp */; }; >@@ -3593,6 +3595,8 @@ > E3963CEC1B73F75000EB4CE5 /* NodesAnalyzeModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NodesAnalyzeModule.cpp; sourceTree = "<group>"; }; > E39DA4A41B7E8B7C0084F33A /* JSModuleRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSModuleRecord.cpp; sourceTree = "<group>"; }; > E39DA4A51B7E8B7C0084F33A /* JSModuleRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSModuleRecord.h; sourceTree = "<group>"; }; >+ E3D239C61B829C1C00BBEF67 /* JSModuleEnvironment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSModuleEnvironment.cpp; sourceTree = "<group>"; }; >+ E3D239C71B829C1C00BBEF67 /* JSModuleEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSModuleEnvironment.h; sourceTree = "<group>"; }; > E3EF88721B66DF23003F26CB /* JSPropertyNameIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPropertyNameIterator.cpp; sourceTree = "<group>"; }; > E3EF88731B66DF23003F26CB /* JSPropertyNameIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPropertyNameIterator.h; sourceTree = "<group>"; }; > E49DC14912EF261A00184A1F /* SourceProviderCacheItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SourceProviderCacheItem.h; sourceTree = "<group>"; }; >@@ -4786,6 +4790,8 @@ > A700874017CBE8EB00C3E643 /* JSMap.h */, > A74DEF8F182D991400522C22 /* JSMapIterator.cpp */, > A74DEF90182D991400522C22 /* JSMapIterator.h */, >+ E3D239C61B829C1C00BBEF67 /* JSModuleEnvironment.cpp */, >+ E3D239C71B829C1C00BBEF67 /* JSModuleEnvironment.h */, > E39DA4A41B7E8B7C0084F33A /* JSModuleRecord.cpp */, > E39DA4A51B7E8B7C0084F33A /* JSModuleRecord.h */, > E33E8D1A1B9013C300346B52 /* JSNativeStdFunction.cpp */, >@@ -6150,6 +6156,7 @@ > 0F2B9CE919D0BA7D00B1D1B5 /* DFGObjectMaterializationData.h in Headers */, > A7D9A29817A0BC7400EE2618 /* DFGLICMPhase.h in Headers */, > A7D89CFC17A0B8CC00773AD8 /* DFGLivenessAnalysisPhase.h in Headers */, >+ E3D239C91B829C1C00BBEF67 /* JSModuleEnvironment.h in Headers */, > 0FF0F19B16B729FA005DF95B /* DFGLongLivedState.h in Headers */, > 709FB8681AE335C60039D069 /* JSWeakSet.h in Headers */, > A767B5B617A0B9650063D940 /* DFGLoopPreHeaderCreationPhase.h in Headers */, >@@ -7398,6 +7405,7 @@ > 0F6C73501AC9F99F00BE1682 /* VariableWriteFireDetail.cpp in Sources */, > 86B5826914D2797000A9C306 /* CodeProfiling.cpp in Sources */, > 0F8F943C1667631300D61971 /* CodeSpecializationKind.cpp in Sources */, >+ E3D239C81B829C1C00BBEF67 /* JSModuleEnvironment.cpp in Sources */, > 0F8F94421667633500D61971 /* CodeType.cpp in Sources */, > 147F39C1107EC37600427A48 /* CommonIdentifiers.cpp in Sources */, > 0F9C5E5E18E35F5E00D431C3 /* FTLDWARFRegister.cpp in Sources */, >diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp >index f12046ca7a02f477a3655c0493c926ea0f2f90dc..244ae89f92a16eb1508fd9487e90cfac5256c76a 100644 >--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp >+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp >@@ -49,6 +49,7 @@ > #include "JSCJSValue.h" > #include "JSFunction.h" > #include "JSLexicalEnvironment.h" >+#include "JSModuleEnvironment.h" > #include "LLIntEntrypoint.h" > #include "LowLevelInterpreter.h" > #include "JSCInlines.h" >@@ -1786,6 +1787,17 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin > } > } > >+ // We already have the cloned symbol table for the module environment since we need to instantiate >+ // the module environments before linking the code block. We replace the stored symbol table with the alreaady cloned one. >+ if (UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock = jsDynamicCast<UnlinkedModuleProgramCodeBlock*>(unlinkedCodeBlock)) { >+ SymbolTable* clonedSymbolTable = jsCast<ModuleProgramExecutable*>(ownerExecutable)->moduleEnvironmentSymbolTable(); >+ if (m_vm->typeProfiler()) { >+ ConcurrentJITLocker locker(clonedSymbolTable->m_lock); >+ clonedSymbolTable->prepareForTypeProfiling(locker); >+ } >+ m_constantRegisters[unlinkedModuleProgramCodeBlock->moduleEnvironmentSymbolTableConstantRegisterOffset() - FirstConstantRegisterIndex].set(*m_vm, ownerExecutable, clonedSymbolTable); >+ } >+ > m_functionDecls.resizeToFit(unlinkedCodeBlock->numberOfFunctionDecls()); > for (size_t count = unlinkedCodeBlock->numberOfFunctionDecls(), i = 0; i < count; ++i) { > UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionDecl(i); >@@ -1864,6 +1876,9 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin > unsigned instructionCount = unlinkedCodeBlock->instructions().count(); > UnlinkedInstructionStream::Reader instructionReader(unlinkedCodeBlock->instructions()); > >+ // Bookkeep the strongly referenced module environments. >+ HashSet<JSModuleEnvironment*> stronglyReferencedModuleEnvironments; >+ > Vector<Instruction, 0, UnsafeVectorOverflow> instructions(instructionCount); > > for (unsigned i = 0; !instructionReader.atEnd(); ) { >@@ -1973,9 +1988,15 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin > ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, type, NotInitialization); > instructions[i + 4].u.operand = op.type; > instructions[i + 5].u.operand = op.depth; >- if (op.lexicalEnvironment) >- instructions[i + 6].u.symbolTable.set(*vm(), ownerExecutable, op.lexicalEnvironment->symbolTable()); >- else if (JSScope* constantScope = JSScope::constantScopeForCodeBlock(op.type, this)) >+ if (op.lexicalEnvironment) { >+ if (op.type == ModuleVar) { >+ // Keep the linked module environment strongly referenced. >+ if (stronglyReferencedModuleEnvironments.add(jsCast<JSModuleEnvironment*>(op.lexicalEnvironment)).isNewEntry) >+ addConstant(op.lexicalEnvironment); >+ instructions[i + 6].u.jsCell.set(*vm(), ownerExecutable, op.lexicalEnvironment); >+ } else >+ instructions[i + 6].u.symbolTable.set(*vm(), ownerExecutable, op.lexicalEnvironment->symbolTable()); >+ } else if (JSScope* constantScope = JSScope::constantScopeForCodeBlock(op.type, this)) > instructions[i + 6].u.jsCell.set(*vm(), ownerExecutable, constantScope); > else > instructions[i + 6].u.pointer = nullptr; >@@ -2004,6 +2025,8 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin > ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, getPutInfo.resolveType(), NotInitialization); > > instructions[i + 4].u.operand = GetPutInfo(getPutInfo.resolveMode(), op.type, getPutInfo.initializationMode()).operand(); >+ if (op.type == ModuleVar) >+ instructions[i + 4].u.operand = GetPutInfo(getPutInfo.resolveMode(), ClosureVar, getPutInfo.initializationMode()).operand(); > if (op.type == GlobalVar || op.type == GlobalVarWithVarInjectionChecks || op.type == GlobalLexicalVar || op.type == GlobalLexicalVarWithVarInjectionChecks) > instructions[i + 5].u.watchpointSet = op.watchpointSet; > else if (op.structure) >@@ -2071,17 +2094,18 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin > // we're abstractly "read"ing from a JSScope. > ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, type, NotInitialization); > >- if (op.type == ClosureVar) >+ if (op.type == ClosureVar || op.type == ModuleVar) > symbolTable = op.lexicalEnvironment->symbolTable(); > else if (op.type == GlobalVar) > symbolTable = m_globalObject.get()->symbolTable(); >- >+ >+ UniquedStringImpl* impl = (op.type == ModuleVar) ? op.importedName.get() : ident.impl(); > if (symbolTable) { > ConcurrentJITLocker locker(symbolTable->m_lock); > // If our parent scope was created while profiling was disabled, it will not have prepared for profiling yet. > symbolTable->prepareForTypeProfiling(locker); >- globalVariableID = symbolTable->uniqueIDForVariable(locker, ident.impl(), *vm()); >- globalTypeSet = symbolTable->globalTypeSetForVariable(locker, ident.impl(), *vm()); >+ globalVariableID = symbolTable->uniqueIDForVariable(locker, impl, *vm()); >+ globalTypeSet = symbolTable->globalTypeSetForVariable(locker, impl, *vm()); > } else > globalVariableID = TypeProfilerNoGlobalIDExists; > >diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h >index eeafd50a1efbd4bde7fbcdd0bb5e81265e5453a0..91e548c93fa20b2da5676c8b37d9ce914e29b0db 100644 >--- a/Source/JavaScriptCore/bytecode/CodeBlock.h >+++ b/Source/JavaScriptCore/bytecode/CodeBlock.h >@@ -82,6 +82,7 @@ class ExecState; > class LLIntOffsetsExtractor; > class RepatchBuffer; > class TypeLocation; >+class JSModuleEnvironment; > > enum ReoptimizationMode { DontCountReoptimization, CountReoptimization }; > >diff --git a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp >index 2fe1bb87ff2764c6eae2b36f42a1678b286726d6..c114b9b57d144d165ea41dad8f2a68ee8fa8b576 100644 >--- a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp >+++ b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp >@@ -297,7 +297,6 @@ void UnlinkedModuleProgramCodeBlock::visitChildren(JSCell* cell, SlotVisitor& vi > UnlinkedModuleProgramCodeBlock* thisObject = jsCast<UnlinkedModuleProgramCodeBlock*>(cell); > ASSERT_GC_OBJECT_INHERITS(thisObject, info()); > Base::visitChildren(thisObject, visitor); >- visitor.append(&thisObject->m_moduleEnvironmentSymbolTable); > } > > UnlinkedCodeBlock::~UnlinkedCodeBlock() >diff --git a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h >index f749bb09cb99449621e68c98eb5c522bf6e8c70d..fa514c156a7cb7cef74a9f1000165b861f0f83cf 100644 >--- a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h >+++ b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h >@@ -38,7 +38,6 @@ > #include "ParserModes.h" > #include "RegExp.h" > #include "SpecialPointer.h" >-#include "SymbolTable.h" > #include "UnlinkedFunctionExecutable.h" > #include "VariableEnvironment.h" > #include "VirtualRegister.h" >@@ -55,7 +54,6 @@ class ParserError; > class ScriptExecutable; > class SourceCode; > class SourceProvider; >-class SymbolTable; > class UnlinkedCodeBlock; > class UnlinkedFunctionCodeBlock; > class UnlinkedFunctionExecutable; >@@ -531,29 +529,35 @@ class UnlinkedModuleProgramCodeBlock final : public UnlinkedGlobalCodeBlock { > > static void visitChildren(JSCell*, SlotVisitor&); > >- // This symbol table represents the layout of the module environment. This symbol table will be modified by the byte >- // code generator since the module environment includes the top-most lexical captured variables inside the module code. >- // This means that, once the module environment is allocated and instantiated from this symbol table, it is titely >- // coupled with the specific unlinked module program code block and the symbol table. So before executing the module >- // code, we should not clear the unlinked module program code block in the module executable. This requirement is met >- // because the garbage collector only clears unlinked code in (1) unmarked executables and (2) function executables. >+ // This offset represents the constant register offset to the stored symbol table that represents the layout of the >+ // module environment. This symbol table is created by the byte code generator since the module environment includes >+ // the top-most lexical captured variables inside the module code. This means that, once the module environment is >+ // allocated and instantiated from this symbol table, it is titely coupled with the specific unlinked module program >+ // code block and the stored symbol table. So before executing the module code, we should not clear the unlinked module >+ // program code block in the module executable. This requirement is met because the garbage collector only clears >+ // unlinked code in (1) unmarked executables and (2) function executables. > // > // Since the function code may be executed repeatedly and the environment of each function execution is different, > // the function code need to allocate and instantiate the environment in the prologue of the function code. On the > // other hand, the module code is executed only once. So we can instantiate the module environment outside the module >- // code. At that time, we construct the module environment by using this symbol table before executing the module code. >- // Instantiating the module environment before executing the module code is required to link the imported bindings >- // between the modules. >+ // code. At that time, we construct the module environment by using the symbol table that is held by the module executable. >+ // The symbol table held by the executable is the cloned one from one in the unlinked code block. Instantiating the module >+ // environment before executing and linking the module code is required to link the imported bindings between the modules. > // >- // The unlinked module program code block only holds the symbol table. It does not hold the module environment. So while >- // the module environment requires the specific unlinked module program code block, the unlinked module code block >- // can be used for the module environment instantiated from this unlinked code block. There is 1:N relation between >- // the unlinked module code block and the module environments. So the unlinked module program code block can be cached. >+ // The unlinked module program code block only holds the pre-cloned symbol table in its constant register pool. It does >+ // not hold the instantiated module environment. So while the module environment requires the specific unlinked module >+ // program code block, the unlinked module code block can be used for the module environment instantiated from this >+ // unlinked code block. There is 1:N relation between the unlinked module code block and the module environments. So the >+ // unlinked module program code block can be cached. > // > // On the other hand, the linked code block for the module environment includes the resolved references to the imported > // bindings. The imported binding references the other module environment, so the linked code block is titly coupled > // with the specific set of the module environments. Thus, the linked code block should not be cached. >- SymbolTable* moduleEnvironmentSymbolTable() { return m_moduleEnvironmentSymbolTable.get(); } >+ int moduleEnvironmentSymbolTableConstantRegisterOffset() { return m_moduleEnvironmentSymbolTableConstantRegisterOffset; } >+ void setModuleEnvironmentSymbolTableConstantRegisterOffset(int offset) >+ { >+ m_moduleEnvironmentSymbolTableConstantRegisterOffset = offset; >+ } > > private: > UnlinkedModuleProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info) >@@ -561,13 +565,7 @@ class UnlinkedModuleProgramCodeBlock final : public UnlinkedGlobalCodeBlock { > { > } > >- void finishCreation(VM& vm) >- { >- Base::finishCreation(vm); >- m_moduleEnvironmentSymbolTable.set(vm, this, SymbolTable::create(vm)); >- } >- >- WriteBarrier<SymbolTable> m_moduleEnvironmentSymbolTable; >+ int m_moduleEnvironmentSymbolTableConstantRegisterOffset { 0 }; > > public: > static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) >diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >index 5089f566146b9375bdcd097ae0da76aeb64236b3..9e25be1dfebc882ad2a024f3114d02f2a37e0b6f 100644 >--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >@@ -536,9 +536,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNod > if (m_isBuiltinFunction) > m_shouldEmitDebugHooks = false; > >- // Use the symbol table allocated in the unlinked code block. This symbol table >- // will be used to allocate and instantiate the module environment. >- SymbolTable* moduleEnvironmentSymbolTable = codeBlock->moduleEnvironmentSymbolTable(); >+ SymbolTable* moduleEnvironmentSymbolTable = SymbolTable::create(*m_vm); > moduleEnvironmentSymbolTable->setUsesNonStrictEval(m_usesNonStrictEval); > moduleEnvironmentSymbolTable->setScopeType(SymbolTable::ScopeType::LexicalScope); > >@@ -592,6 +590,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNod > VariableEnvironment& lexicalVariables = moduleProgramNode->lexicalVariables(); > instantiateLexicalVariables(lexicalVariables, moduleEnvironmentSymbolTable, ScopeRegisterType::Block, lookUpVarKind); > >+ // We keep the symbol table in the constant pool. > RegisterID* constantSymbolTable = nullptr; > if (vm.typeProfiler()) > constantSymbolTable = addConstantValue(moduleEnvironmentSymbolTable); >@@ -656,6 +655,11 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNod > m_functionsToInitialize.append(std::make_pair(function, NormalFunctionVariable)); > } > } >+ >+ // Remember the constant register offset to the top-most symbol table. This symbol table will be >+ // cloned in the code block linking. After that, to create the module environment, we retrieve >+ // the cloned symbol table from the linked code block by using this offset. >+ codeBlock->setModuleEnvironmentSymbolTableConstantRegisterOffset(constantSymbolTable->index()); > } > > BytecodeGenerator::~BytecodeGenerator() >diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >index 2b89e3ab0087f7211504e912cbfe11568c9af371..786b9216c05dfb1377e94084bd3bf94f6b2d4930 100644 >--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >@@ -42,6 +42,7 @@ > #include "Heap.h" > #include "JSLexicalEnvironment.h" > #include "JSCInlines.h" >+#include "JSModuleEnvironment.h" > #include "PreciseJumpTargets.h" > #include "PutByIdStatus.h" > #include "StackAlignment.h" >@@ -3839,6 +3840,14 @@ bool ByteCodeParser::parseBlock(unsigned limit) > addToGraph(Phantom, get(VirtualRegister(scope))); > break; > } >+ case ModuleVar: { >+ // Since the value of the "scope" virtual register is not used in LLInt / baseline op_resolve_scope with ModuleVar, >+ // we need not to keep it alive by the Phantom node. >+ JSModuleEnvironment* moduleEnvironment = jsCast<JSModuleEnvironment*>(currentInstruction[6].u.jsCell.get()); >+ // Module environment is already strongly referenced by the CodeBlock. >+ set(VirtualRegister(dst), weakJSConstant(moduleEnvironment)); >+ break; >+ } > case LocalClosureVar: > case ClosureVar: > case ClosureVarWithVarInjectionChecks: { >@@ -4034,6 +4043,7 @@ bool ByteCodeParser::parseBlock(unsigned limit) > set(VirtualRegister(dst), addToGraph(JSConstant, OpInfo(m_constantUndefined))); > break; > } >+ case ModuleVar: > case Dynamic: > RELEASE_ASSERT_NOT_REACHED(); > break; >@@ -4128,6 +4138,7 @@ bool ByteCodeParser::parseBlock(unsigned limit) > } > break; > } >+ > case UnresolvedProperty: > case UnresolvedPropertyWithVarInjectionChecks: { > addToGraph(ForceOSRExit); >@@ -4135,6 +4146,13 @@ bool ByteCodeParser::parseBlock(unsigned limit) > addToGraph(Phantom, scopeNode); > break; > } >+ >+ case ModuleVar: >+ // Need not to keep "scope" and "value" register values here by Phantom because >+ // they are not used in LLInt / baseline op_put_to_scope with ModuleVar. >+ addToGraph(ForceOSRExit); >+ break; >+ > case Dynamic: > RELEASE_ASSERT_NOT_REACHED(); > break; >diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp >index 1f99e2c72e000578cfd1d8114f7ce84da4d63f7d..4b0f12c392a157b3f25597390ce480250f3c76d0 100644 >--- a/Source/JavaScriptCore/interpreter/Interpreter.cpp >+++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp >@@ -49,6 +49,7 @@ > #include "JSBoundFunction.h" > #include "JSCInlines.h" > #include "JSLexicalEnvironment.h" >+#include "JSModuleEnvironment.h" > #include "JSNotAnObject.h" > #include "JSStackInlines.h" > #include "JSString.h" >@@ -1215,6 +1216,54 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue > return checkedReturn(result); > } > >+JSValue Interpreter::execute(ModuleProgramExecutable* executable, CallFrame* callFrame, JSModuleEnvironment* scope) >+{ >+ VM& vm = *scope->vm(); >+ SamplingScope samplingScope(this); >+ >+ ASSERT(scope->vm() == &callFrame->vm()); >+ ASSERT(!vm.exception()); >+ ASSERT(!vm.isCollectorBusy()); >+ RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock()); >+ if (vm.isCollectorBusy()) >+ return jsNull(); >+ >+ VMEntryScope entryScope(vm, scope->globalObject()); >+ if (!vm.isSafeToRecurse()) >+ return checkedReturn(throwStackOverflowError(callFrame)); >+ >+ JSObject* compileError = executable->prepareForExecution(callFrame, nullptr, scope, CodeForCall); >+ if (UNLIKELY(!!compileError)) >+ return checkedReturn(callFrame->vm().throwException(callFrame, compileError)); >+ ModuleProgramCodeBlock* codeBlock = executable->codeBlock(); >+ >+ if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(callFrame))) >+ return throwTerminatedExecutionException(callFrame); >+ >+ ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'. >+ >+ // The |this| of the module is always `undefined`. >+ // http://www.ecma-international.org/ecma-262/6.0/#sec-module-environment-records-hasthisbinding >+ // http://www.ecma-international.org/ecma-262/6.0/#sec-module-environment-records-getthisbinding >+ ProtoCallFrame protoCallFrame; >+ protoCallFrame.init(codeBlock, JSCallee::create(vm, scope->globalObject(), scope), jsUndefined(), 1); >+ >+ if (LegacyProfiler* profiler = vm.enabledProfiler()) >+ profiler->willExecute(callFrame, executable->sourceURL(), executable->firstLine(), executable->startColumn()); >+ >+ // Execute the code: >+ JSValue result; >+ { >+ SamplingTool::CallRecord callRecord(m_sampler.get()); >+ result = executable->generatedJITCode()->execute(&vm, &protoCallFrame); >+ } >+ >+ if (LegacyProfiler* profiler = vm.enabledProfiler()) >+ profiler->didExecute(callFrame, executable->sourceURL(), executable->firstLine(), executable->startColumn()); >+ >+ return checkedReturn(result); >+} >+ > NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID) > { > Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger(); >diff --git a/Source/JavaScriptCore/interpreter/Interpreter.h b/Source/JavaScriptCore/interpreter/Interpreter.h >index 038bca5cfc75b9b245762d6e64f68f2e78ec6251..4fefaa6cf8e31af2d359d163bac8a1a4095af44b 100644 >--- a/Source/JavaScriptCore/interpreter/Interpreter.h >+++ b/Source/JavaScriptCore/interpreter/Interpreter.h >@@ -54,6 +54,7 @@ namespace JSC { > class JSArrowFunction; > class JSFunction; > class JSGlobalObject; >+ class JSModuleEnvironment; > class JSModuleRecord; > class LLIntOffsetsExtractor; > class ProgramExecutable; >@@ -215,6 +216,7 @@ namespace JSC { > JSValue executeCall(CallFrame*, JSObject* function, CallType, const CallData&, JSValue thisValue, const ArgList&); > JSObject* executeConstruct(CallFrame*, JSObject* function, ConstructType, const ConstructData&, const ArgList&, JSValue newTarget); > JSValue execute(EvalExecutable*, CallFrame*, JSValue thisValue, JSScope*); >+ JSValue execute(ModuleProgramExecutable*, CallFrame*, JSModuleEnvironment*); > > void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc); > >diff --git a/Source/JavaScriptCore/jit/JITOperations.cpp b/Source/JavaScriptCore/jit/JITOperations.cpp >index 6d501e6e28649fdc0299bedbdb15354da6ae3274..15960f2fae076f658c1587bdcd0b233f4b2e4856 100644 >--- a/Source/JavaScriptCore/jit/JITOperations.cpp >+++ b/Source/JavaScriptCore/jit/JITOperations.cpp >@@ -1939,6 +1939,9 @@ EncodedJSValue JIT_OPERATION operationGetFromScope(ExecState* exec, Instruction* > JSObject* scope = jsCast<JSObject*>(exec->uncheckedR(pc[2].u.operand).jsValue()); > GetPutInfo getPutInfo(pc[4].u.operand); > >+ // ModuleVar is always converted to ClosureVar for get_from_scope. >+ ASSERT(getPutInfo.resolveType() != ModuleVar); >+ > PropertySlot slot(scope); > if (!scope->getPropertySlot(exec, ident, slot)) { > if (getPutInfo.resolveMode() == ThrowIfNotFound) >@@ -1974,6 +1977,10 @@ void JIT_OPERATION operationPutToScope(ExecState* exec, Instruction* bytecodePC) > JSObject* scope = jsCast<JSObject*>(exec->uncheckedR(pc[1].u.operand).jsValue()); > JSValue value = exec->r(pc[3].u.operand).jsValue(); > GetPutInfo getPutInfo = GetPutInfo(pc[4].u.operand); >+ >+ // ModuleVar does not keep the scope register value alive in DFG. >+ ASSERT(getPutInfo.resolveType() != ModuleVar); >+ > if (getPutInfo.resolveType() == LocalClosureVar) { > JSLexicalEnvironment* environment = jsCast<JSLexicalEnvironment*>(scope); > environment->variableAt(ScopeOffset(pc[6].u.operand)).set(vm, environment, value); >diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp >index 429a0aa99ca904a05e9e1566bb969e3996091e6d..c857fcdac0cd33ae2eb06c4c5645665114ba4529 100644 >--- a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp >+++ b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp >@@ -710,6 +710,10 @@ void JIT::emit_op_resolve_scope(Instruction* currentInstruction) > case ClosureVarWithVarInjectionChecks: > emitResolveClosure(dst, scope, needsVarInjectionChecks(resolveType), depth); > break; >+ case ModuleVar: >+ move(TrustedImmPtr(currentInstruction[6].u.jsCell.get()), regT0); >+ emitPutVirtualRegister(dst); >+ break; > case UnresolvedProperty: > case UnresolvedPropertyWithVarInjectionChecks: > case Dynamic: >@@ -723,9 +727,10 @@ void JIT::emit_op_resolve_scope(Instruction* currentInstruction) > void JIT::emitSlow_op_resolve_scope(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) > { > ResolveType resolveType = static_cast<ResolveType>(currentInstruction[4].u.operand); >- if (resolveType == GlobalProperty || resolveType == GlobalVar || resolveType == ClosureVar || resolveType == GlobalLexicalVar) >+ if (resolveType == GlobalProperty || resolveType == GlobalVar || resolveType == ClosureVar || resolveType == GlobalLexicalVar || resolveType == ModuleVar) > return; > >+ > linkSlowCase(iter); > JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_resolve_scope); > slowPathCall.call(); >@@ -790,6 +795,7 @@ void JIT::emit_op_get_from_scope(Instruction* currentInstruction) > case Dynamic: > addSlowCase(jump()); > break; >+ case ModuleVar: > case LocalClosureVar: > RELEASE_ASSERT_NOT_REACHED(); > } >@@ -883,6 +889,7 @@ void JIT::emit_op_put_to_scope(Instruction* currentInstruction) > break; > case UnresolvedProperty: > case UnresolvedPropertyWithVarInjectionChecks: >+ case ModuleVar: > case Dynamic: > addSlowCase(jump()); > break; >@@ -909,7 +916,12 @@ void JIT::emitSlow_op_put_to_scope(Instruction* currentInstruction, Vector<SlowC > return; > while (linkCount--) > linkSlowCase(iter); >- callOperation(operationPutToScope, currentInstruction); >+ >+ if (resolveType == ModuleVar) { >+ JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_throw_strict_mode_readonly_property_write_error); >+ slowPathCall.call(); >+ } else >+ callOperation(operationPutToScope, currentInstruction); > } > > void JIT::emit_op_get_from_arguments(Instruction* currentInstruction) >diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp >index 0dd08533f6737cdb2a90d672eb7ce24ff2f68d17..b79a209b438e469d2f9d711b882f3e155d9f132c 100644 >--- a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp >+++ b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp >@@ -742,6 +742,11 @@ void JIT::emit_op_resolve_scope(Instruction* currentInstruction) > case ClosureVarWithVarInjectionChecks: > emitResolveClosure(dst, scope, needsVarInjectionChecks(resolveType), depth); > break; >+ case ModuleVar: >+ move(TrustedImm32(JSValue::CellTag), regT1); >+ move(TrustedImmPtr(currentInstruction[6].u.jsCell.get()), regT0); >+ emitStore(dst, regT1, regT0); >+ break; > case UnresolvedProperty: > case UnresolvedPropertyWithVarInjectionChecks: > case Dynamic: >@@ -756,7 +761,7 @@ void JIT::emitSlow_op_resolve_scope(Instruction* currentInstruction, Vector<Slow > { > ResolveType resolveType = static_cast<ResolveType>(currentInstruction[4].u.operand); > >- if (resolveType == GlobalProperty || resolveType == GlobalVar || resolveType == ClosureVar || resolveType == GlobalLexicalVar) >+ if (resolveType == GlobalProperty || resolveType == GlobalVar || resolveType == ClosureVar || resolveType == GlobalLexicalVar || resolveType == ModuleVar) > return; > > linkSlowCase(iter); >@@ -824,6 +829,7 @@ void JIT::emit_op_get_from_scope(Instruction* currentInstruction) > case Dynamic: > addSlowCase(jump()); > break; >+ case ModuleVar: > case LocalClosureVar: > RELEASE_ASSERT_NOT_REACHED(); > } >@@ -913,6 +919,7 @@ void JIT::emit_op_put_to_scope(Instruction* currentInstruction) > emitVarInjectionCheck(needsVarInjectionChecks(resolveType)); > emitPutClosureVar(scope, *operandSlot, value, currentInstruction[5].u.watchpointSet); > break; >+ case ModuleVar: > case UnresolvedProperty: > case UnresolvedPropertyWithVarInjectionChecks: > case Dynamic: >@@ -938,7 +945,12 @@ void JIT::emitSlow_op_put_to_scope(Instruction* currentInstruction, Vector<SlowC > return; > while (linkCount--) > linkSlowCase(iter); >- callOperation(operationPutToScope, currentInstruction); >+ >+ if (resolveType == ModuleVar) { >+ JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_throw_strict_mode_readonly_property_write_error); >+ slowPathCall.call(); >+ } else >+ callOperation(operationPutToScope, currentInstruction); > } > > void JIT::emit_op_get_from_arguments(Instruction* currentInstruction) >diff --git a/Source/JavaScriptCore/llint/LLIntData.cpp b/Source/JavaScriptCore/llint/LLIntData.cpp >index f1f3ea2916a331a4277a9855bf7a93222b6709b0..8e73edfcc84f6c0579aa1f034d2a2f35bfdf0c83 100644 >--- a/Source/JavaScriptCore/llint/LLIntData.cpp >+++ b/Source/JavaScriptCore/llint/LLIntData.cpp >@@ -148,10 +148,11 @@ void Data::performAssertions(VM& vm) > static_assert(GlobalLexicalVar == 2, "LLInt assumes GlobalLexicalVar ResultType is == 2"); > static_assert(ClosureVar == 3, "LLInt assumes ClosureVar ResultType is == 3"); > static_assert(LocalClosureVar == 4, "LLInt assumes LocalClosureVar ResultType is == 4"); >- static_assert(GlobalPropertyWithVarInjectionChecks == 5, "LLInt assumes GlobalPropertyWithVarInjectionChecks ResultType is == 5"); >- static_assert(GlobalVarWithVarInjectionChecks == 6, "LLInt assumes GlobalVarWithVarInjectionChecks ResultType is == 6"); >- static_assert(GlobalLexicalVarWithVarInjectionChecks == 7, "LLInt assumes GlobalLexicalVarWithVarInjectionChecks ResultType is == 7"); >- static_assert(ClosureVarWithVarInjectionChecks == 8, "LLInt assumes ClosureVarWithVarInjectionChecks ResultType is == 8"); >+ static_assert(ModuleVar == 5, "LLInt assumes ModuleVar ResultType is == 5"); >+ static_assert(GlobalPropertyWithVarInjectionChecks == 6, "LLInt assumes GlobalPropertyWithVarInjectionChecks ResultType is == 6"); >+ static_assert(GlobalVarWithVarInjectionChecks == 7, "LLInt assumes GlobalVarWithVarInjectionChecks ResultType is == 7"); >+ static_assert(GlobalLexicalVarWithVarInjectionChecks == 8, "LLInt assumes GlobalLexicalVarWithVarInjectionChecks ResultType is == 8"); >+ static_assert(ClosureVarWithVarInjectionChecks == 9, "LLInt assumes ClosureVarWithVarInjectionChecks ResultType is == 9"); > > static_assert(InitializationMode::Initialization == 0, "LLInt assumes that InitializationMode::Initialization is 0"); > >diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp >index 7eda2ba8af4cb34fb56bcf6666dc599a488c8aba..3fb485d0efa1edf10d83be0197fee6efe7ed3cc4 100644 >--- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp >+++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp >@@ -1366,6 +1366,9 @@ LLINT_SLOW_PATH_DECL(slow_path_get_from_scope) > JSObject* scope = jsCast<JSObject*>(LLINT_OP(2).jsValue()); > GetPutInfo getPutInfo(pc[4].u.operand); > >+ // ModuleVar is always converted to ClosureVar for get_from_scope. >+ ASSERT(getPutInfo.resolveType() != ModuleVar); >+ > PropertySlot slot(scope); > if (!scope->getPropertySlot(exec, ident, slot)) { > if (getPutInfo.resolveMode() == ThrowIfNotFound) >diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm >index 455b60726ca5fb116e446978e305bdcc0a12c25f..2d51d1e705d23dfdb6658c8fd8949717e2785a0a 100644 >--- a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm >+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm >@@ -193,10 +193,11 @@ const GlobalVar = 1 > const GlobalLexicalVar = 2 > const ClosureVar = 3 > const LocalClosureVar = 4 >-const GlobalPropertyWithVarInjectionChecks = 5 >-const GlobalVarWithVarInjectionChecks = 6 >-const GlobalLexicalVarWithVarInjectionChecks = 7 >-const ClosureVarWithVarInjectionChecks = 8 >+const ModuleVar = 5 >+const GlobalPropertyWithVarInjectionChecks = 6 >+const GlobalVarWithVarInjectionChecks = 7 >+const GlobalLexicalVarWithVarInjectionChecks = 8 >+const ClosureVarWithVarInjectionChecks = 9 > > const ResolveTypeMask = 0x3ff > const InitializationModeMask = 0xffc00 >diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm >index 92e3ec873685b5cccec70be1e019da003d7002f0..f5f2a03c2701171c32276a31cdf6414015f39ff7 100644 >--- a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm >+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm >@@ -2108,10 +2108,15 @@ _llint_op_resolve_scope: > dispatch(7) > > .rClosureVar: >- bineq t0, ClosureVar, .rGlobalPropertyWithVarInjectionChecks >+ bineq t0, ClosureVar, .rModuleVar > resolveScope() > dispatch(7) > >+.rModuleVar: >+ bineq t0, ModuleVar, .rGlobalPropertyWithVarInjectionChecks >+ getConstantScope(1) >+ dispatch(7) >+ > .rGlobalPropertyWithVarInjectionChecks: > bineq t0, GlobalPropertyWithVarInjectionChecks, .rGlobalVarWithVarInjectionChecks > varInjectionCheck(.rDynamic) >@@ -2339,13 +2344,18 @@ _llint_op_put_to_scope: > dispatch(7) > > .pClosureVarWithVarInjectionChecks: >- bineq t0, ClosureVarWithVarInjectionChecks, .pDynamic >+ bineq t0, ClosureVarWithVarInjectionChecks, .pModuleVar > writeBarrierOnOperands(1, 3) > varInjectionCheck(.pDynamic) > loadVariable(1, t2, t1, t0) > putClosureVar() > dispatch(7) > >+.pModuleVar: >+ bineq t0, ModuleVar, .pDynamic >+ callSlowPath(_slow_path_throw_strict_mode_readonly_property_write_error) >+ dispatch(7) >+ > .pDynamic: > callSlowPath(_llint_slow_path_put_to_scope) > dispatch(7) >diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >index 7f338da3658b044c1705622ccd0ea85103015821..efd0c7d74189805c13bf80925e6f674c186c25ef 100644 >--- a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >@@ -1976,10 +1976,15 @@ _llint_op_resolve_scope: > dispatch(7) > > .rClosureVar: >- bineq t0, ClosureVar, .rGlobalPropertyWithVarInjectionChecks >+ bineq t0, ClosureVar, .rModuleVar > resolveScope() > dispatch(7) > >+.rModuleVar: >+ bineq t0, ModuleVar, .rGlobalPropertyWithVarInjectionChecks >+ getConstantScope(1) >+ dispatch(7) >+ > .rGlobalPropertyWithVarInjectionChecks: > bineq t0, GlobalPropertyWithVarInjectionChecks, .rGlobalVarWithVarInjectionChecks > varInjectionCheck(.rDynamic) >@@ -2213,13 +2218,18 @@ _llint_op_put_to_scope: > dispatch(7) > > .pClosureVarWithVarInjectionChecks: >- bineq t0, ClosureVarWithVarInjectionChecks, .pDynamic >+ bineq t0, ClosureVarWithVarInjectionChecks, .pModuleVar > writeBarrierOnOperands(1, 3) > varInjectionCheck(.pDynamic) > loadVariable(1, t0) > putClosureVar() > dispatch(7) > >+.pModuleVar: >+ bineq t0, ModuleVar, .pDynamic >+ callSlowPath(_slow_path_throw_strict_mode_readonly_property_write_error) >+ dispatch(7) >+ > .pDynamic: > callSlowPath(_llint_slow_path_put_to_scope) > dispatch(7) >diff --git a/Source/JavaScriptCore/parser/ModuleAnalyzer.cpp b/Source/JavaScriptCore/parser/ModuleAnalyzer.cpp >index f6238fb96802be537e91adc26b82d890b954032d..c1a3cc2b1f0681e05992d5cd4e626be880d4b974 100644 >--- a/Source/JavaScriptCore/parser/ModuleAnalyzer.cpp >+++ b/Source/JavaScriptCore/parser/ModuleAnalyzer.cpp >@@ -82,7 +82,9 @@ void ModuleAnalyzer::exportVariable(const RefPtr<UniquedStringImpl>& localName, > return; > } > >- const auto& importEntry = moduleRecord()->lookUpImportEntry(localName); >+ Optional<JSModuleRecord::ImportEntry> optionalImportEntry = moduleRecord()->tryGetImportEntry(localName.get()); >+ ASSERT(optionalImportEntry); >+ const JSModuleRecord::ImportEntry& importEntry = *optionalImportEntry; > if (variable.isImportedNamespace()) { > // Exported namespace binding. > // import * as namespace from "mod" >diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp b/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >index e829f8557a2ae603e8eed0a4b4030ce6d53c02d5..e4861ba2cfc5e4264841b70f1231b6ccdb527ea5 100644 >--- a/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >+++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >@@ -270,6 +270,12 @@ SLOW_PATH_DECL(slow_path_throw_tdz_error) > THROW(createTDZError(exec)); > } > >+SLOW_PATH_DECL(slow_path_throw_strict_mode_readonly_property_write_error) >+{ >+ BEGIN(); >+ THROW(createTypeError(exec, ASCIILiteral(StrictModeReadonlyPropertyWriteError))); >+} >+ > SLOW_PATH_DECL(slow_path_not) > { > BEGIN(); >@@ -668,6 +674,10 @@ SLOW_PATH_DECL(slow_path_resolve_scope) > JSValue resolvedScope = JSScope::resolve(exec, scope, ident); > > ResolveType resolveType = static_cast<ResolveType>(pc[4].u.operand); >+ >+ // ModuleVar does not keep the scope register value alive in DFG. >+ ASSERT(resolveType != ModuleVar); >+ > if (resolveType == UnresolvedProperty || resolveType == UnresolvedPropertyWithVarInjectionChecks) { > if (JSGlobalLexicalEnvironment* globalLexicalEnvironment = jsDynamicCast<JSGlobalLexicalEnvironment*>(resolvedScope)) { > if (resolveType == UnresolvedProperty) >diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.h b/Source/JavaScriptCore/runtime/CommonSlowPaths.h >index 8c9867fc4de335a1f87e378c3eb3bf73752566bc..fbefcd0e184abebbda98955ff3e84b8e693e6e32 100644 >--- a/Source/JavaScriptCore/runtime/CommonSlowPaths.h >+++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.h >@@ -241,6 +241,7 @@ SLOW_PATH_HIDDEN_DECL(slow_path_enter); > SLOW_PATH_HIDDEN_DECL(slow_path_get_callee); > SLOW_PATH_HIDDEN_DECL(slow_path_to_this); > SLOW_PATH_HIDDEN_DECL(slow_path_throw_tdz_error); >+SLOW_PATH_HIDDEN_DECL(slow_path_throw_strict_mode_readonly_property_write_error); > SLOW_PATH_HIDDEN_DECL(slow_path_not); > SLOW_PATH_HIDDEN_DECL(slow_path_eq); > SLOW_PATH_HIDDEN_DECL(slow_path_neq); >diff --git a/Source/JavaScriptCore/runtime/Error.cpp b/Source/JavaScriptCore/runtime/Error.cpp >index 00285a67577347479bd9a9b7b93955c26434657c..1b93e8fd1257d0d78aa7936881124caf69944b8f 100644 >--- a/Source/JavaScriptCore/runtime/Error.cpp >+++ b/Source/JavaScriptCore/runtime/Error.cpp >@@ -219,6 +219,10 @@ JSObject* throwSyntaxError(ExecState* exec) > return exec->vm().throwException(exec, createSyntaxError(exec, ASCIILiteral("Syntax error"))); > } > >+JSObject* throwSyntaxError(ExecState* exec, const String& message) >+{ >+ return exec->vm().throwException(exec, createSyntaxError(exec, message)); >+} > > JSObject* createError(ExecState* exec, const String& message) > { >diff --git a/Source/JavaScriptCore/runtime/Error.h b/Source/JavaScriptCore/runtime/Error.h >index ec30a3dc466e1eb449b3e585aa80492ef1984647..f46fe376fb86c652e4aec849013cea2df3c801b4 100644 >--- a/Source/JavaScriptCore/runtime/Error.h >+++ b/Source/JavaScriptCore/runtime/Error.h >@@ -74,6 +74,7 @@ JSObject* addErrorInfo(ExecState*, JSObject* error, int line, const SourceCode&) > // Convenience wrappers, create an throw an exception with a default message. > JS_EXPORT_PRIVATE JSObject* throwTypeError(ExecState*); > JS_EXPORT_PRIVATE JSObject* throwSyntaxError(ExecState*); >+JS_EXPORT_PRIVATE JSObject* throwSyntaxError(ExecState*, const String& errorMessage); > inline JSObject* throwRangeError(ExecState* state, const String& errorMessage) { return state->vm().throwException(state, createRangeError(state, errorMessage)); } > > // Convenience wrappers, wrap result as an EncodedJSValue. >diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp >index b3172e6d37eecc603086ed57aac1126f49d2cdf8..c473c491f9b266e23b6775291db6884bca14b050 100644 >--- a/Source/JavaScriptCore/runtime/Executable.cpp >+++ b/Source/JavaScriptCore/runtime/Executable.cpp >@@ -439,6 +439,9 @@ ModuleProgramExecutable* ModuleProgramExecutable::create(ExecState* exec, const > return nullptr; > executable->m_unlinkedModuleProgramCodeBlock.set(exec->vm(), executable, unlinkedModuleProgramCode); > >+ // Clone the module environment symbol table for this executable (and the code block linked and instantiated later). >+ executable->m_moduleEnvironmentSymbolTable.set(exec->vm(), executable, jsCast<SymbolTable*>(unlinkedModuleProgramCode->constantRegister(unlinkedModuleProgramCode->moduleEnvironmentSymbolTableConstantRegisterOffset()).get())->cloneScopePart(exec->vm())); >+ > return executable; > } > >@@ -633,6 +636,7 @@ void ModuleProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor) > ASSERT_GC_OBJECT_INHERITS(thisObject, info()); > ScriptExecutable::visitChildren(thisObject, visitor); > visitor.append(&thisObject->m_unlinkedModuleProgramCodeBlock); >+ visitor.append(&thisObject->m_moduleEnvironmentSymbolTable); > if (thisObject->m_moduleProgramCodeBlock) > thisObject->m_moduleProgramCodeBlock->visitAggregate(visitor); > } >@@ -641,6 +645,7 @@ void ModuleProgramExecutable::clearCode() > { > m_moduleProgramCodeBlock = nullptr; > m_unlinkedModuleProgramCodeBlock.clear(); >+ m_moduleEnvironmentSymbolTable.clear(); > Base::clearCode(); > } > >diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h >index cdceb304265f976d0077aefd657b5b7babbf2a16..c487788f5fcf2759b67209e76ba8a9cbfe7aae95 100644 >--- a/Source/JavaScriptCore/runtime/Executable.h >+++ b/Source/JavaScriptCore/runtime/Executable.h >@@ -57,6 +57,9 @@ class ProgramCodeBlock; > class ModuleProgramCodeBlock; > class JSScope; > class WebAssemblyCodeBlock; >+class ModuleProgramCodeBlock; >+class JSModuleRecord; >+class JSScope; > > enum CompilationKind { FirstCompilation, OptimizingCompilation }; > >@@ -589,6 +592,9 @@ class ModuleProgramExecutable final : public ScriptExecutable { > ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, false); } > UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock() { return m_unlinkedModuleProgramCodeBlock.get(); } > >+ // Return the symbol table in the linked code block. >+ SymbolTable* moduleEnvironmentSymbolTable() { return m_moduleEnvironmentSymbolTable.get(); } >+ > private: > friend class ScriptExecutable; > >@@ -597,6 +603,7 @@ class ModuleProgramExecutable final : public ScriptExecutable { > static void visitChildren(JSCell*, SlotVisitor&); > > WriteBarrier<UnlinkedModuleProgramCodeBlock> m_unlinkedModuleProgramCodeBlock; >+ WriteBarrier<SymbolTable> m_moduleEnvironmentSymbolTable; > RefPtr<ModuleProgramCodeBlock> m_moduleProgramCodeBlock; > }; > >diff --git a/Source/JavaScriptCore/runtime/GetPutInfo.h b/Source/JavaScriptCore/runtime/GetPutInfo.h >index 2e7a2effe86e2f8c1874e87c5fe4c0830ce551f9..f499bcd89624dd24ae87da1e24954c0b1b3c4bae 100644 >--- a/Source/JavaScriptCore/runtime/GetPutInfo.h >+++ b/Source/JavaScriptCore/runtime/GetPutInfo.h >@@ -26,6 +26,8 @@ > #ifndef GetPutInfo_h > #define GetPutInfo_h > >+#include <wtf/text/UniquedStringImpl.h> >+ > namespace JSC { > > class Structure; >@@ -44,6 +46,7 @@ enum ResolveType { > GlobalLexicalVar, > ClosureVar, > LocalClosureVar, >+ ModuleVar, > > // Ditto, but at least one intervening scope used non-strict eval, which > // can inject an intercepting var delcaration at runtime. >@@ -84,6 +87,7 @@ ALWAYS_INLINE const char* resolveTypeName(ResolveType type) > "GlobalLexicalVar", > "ClosureVar", > "LocalClosureVar", >+ "ModuleVar", > "GlobalPropertyWithVarInjectionChecks", > "GlobalVarWithVarInjectionChecks", > "GlobalLexicalVarWithVarInjectionChecks", >@@ -122,6 +126,7 @@ ALWAYS_INLINE ResolveType makeType(ResolveType type, bool needsVarInjectionCheck > return ClosureVarWithVarInjectionChecks; > case UnresolvedProperty: > return UnresolvedPropertyWithVarInjectionChecks; >+ case ModuleVar: > case GlobalPropertyWithVarInjectionChecks: > case GlobalVarWithVarInjectionChecks: > case GlobalLexicalVarWithVarInjectionChecks: >@@ -143,6 +148,7 @@ ALWAYS_INLINE bool needsVarInjectionChecks(ResolveType type) > case GlobalLexicalVar: > case ClosureVar: > case LocalClosureVar: >+ case ModuleVar: > case UnresolvedProperty: > return false; > case GlobalPropertyWithVarInjectionChecks: >@@ -159,13 +165,14 @@ ALWAYS_INLINE bool needsVarInjectionChecks(ResolveType type) > } > > struct ResolveOp { >- ResolveOp(ResolveType type, size_t depth, Structure* structure, JSLexicalEnvironment* lexicalEnvironment, WatchpointSet* watchpointSet, uintptr_t operand) >+ ResolveOp(ResolveType type, size_t depth, Structure* structure, JSLexicalEnvironment* lexicalEnvironment, WatchpointSet* watchpointSet, uintptr_t operand, UniquedStringImpl* importedName = nullptr) > : type(type) > , depth(depth) > , structure(structure) > , lexicalEnvironment(lexicalEnvironment) > , watchpointSet(watchpointSet) > , operand(operand) >+ , importedName(importedName) > { > } > >@@ -175,6 +182,7 @@ struct ResolveOp { > JSLexicalEnvironment* lexicalEnvironment; > WatchpointSet* watchpointSet; > uintptr_t operand; >+ RefPtr<UniquedStringImpl> importedName; > }; > > class GetPutInfo { >diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp >index ad37baef92a2a7c248cd4b11a8c8493742f57112..0e77cd2889ceb8bbf10760e2ea325a5e9445adf6 100644 >--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp >+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp >@@ -84,6 +84,7 @@ > #include "JSLock.h" > #include "JSMap.h" > #include "JSMapIterator.h" >+#include "JSModuleEnvironment.h" > #include "JSModuleRecord.h" > #include "JSNativeStdFunction.h" > #include "JSONObject.h" >@@ -313,6 +314,7 @@ void JSGlobalObject::init(VM& vm) > m_typedArrays[toIndex(TypeDataView)].structure.set(vm, this, JSDataView::createStructure(vm, this, m_typedArrays[toIndex(TypeDataView)].prototype.get())); > > m_lexicalEnvironmentStructure.set(vm, this, JSLexicalEnvironment::createStructure(vm, this)); >+ m_moduleEnvironmentStructure.set(vm, this, JSModuleEnvironment::createStructure(vm, this)); > m_strictEvalActivationStructure.set(vm, this, StrictEvalActivation::createStructure(vm, this, jsNull())); > m_debuggerScopeStructure.set(m_vm, this, DebuggerScope::createStructure(m_vm, this)); > m_withScopeStructure.set(vm, this, JSWithScope::createStructure(vm, this, jsNull())); >@@ -793,6 +795,7 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor) > visitor.append(&thisObject->m_withScopeStructure); > visitor.append(&thisObject->m_strictEvalActivationStructure); > visitor.append(&thisObject->m_lexicalEnvironmentStructure); >+ visitor.append(&thisObject->m_moduleEnvironmentStructure); > visitor.append(&thisObject->m_directArgumentsStructure); > visitor.append(&thisObject->m_scopedArgumentsStructure); > visitor.append(&thisObject->m_outOfBandArgumentsStructure); >diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h >index 461959d1bd9bbc9313369776b0d9c15596878136..ec66c1a9ec3c9c53e18e0670aeccb5da9ead2238 100644 >--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h >+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h >@@ -234,6 +234,7 @@ class JSGlobalObject : public JSSegmentedVariableObject { > WriteBarrier<Structure> m_withScopeStructure; > WriteBarrier<Structure> m_strictEvalActivationStructure; > WriteBarrier<Structure> m_lexicalEnvironmentStructure; >+ WriteBarrier<Structure> m_moduleEnvironmentStructure; > WriteBarrier<Structure> m_directArgumentsStructure; > WriteBarrier<Structure> m_scopedArgumentsStructure; > WriteBarrier<Structure> m_outOfBandArgumentsStructure; >@@ -450,6 +451,7 @@ class JSGlobalObject : public JSSegmentedVariableObject { > Structure* withScopeStructure() const { return m_withScopeStructure.get(); } > Structure* strictEvalActivationStructure() const { return m_strictEvalActivationStructure.get(); } > Structure* activationStructure() const { return m_lexicalEnvironmentStructure.get(); } >+ Structure* moduleEnvironmentStructure() const { return m_moduleEnvironmentStructure.get(); } > Structure* directArgumentsStructure() const { return m_directArgumentsStructure.get(); } > Structure* scopedArgumentsStructure() const { return m_scopedArgumentsStructure.get(); } > Structure* outOfBandArgumentsStructure() const { return m_outOfBandArgumentsStructure.get(); } >diff --git a/Source/JavaScriptCore/runtime/JSLexicalEnvironment.h b/Source/JavaScriptCore/runtime/JSLexicalEnvironment.h >index 507312eb7b6ec36250a9285bee98c4f72f0e2476..bbe31618241a396e36f0524f5c0a21ebd164641d 100644 >--- a/Source/JavaScriptCore/runtime/JSLexicalEnvironment.h >+++ b/Source/JavaScriptCore/runtime/JSLexicalEnvironment.h >@@ -39,7 +39,7 @@ namespace JSC { > class Register; > > class JSLexicalEnvironment : public JSEnvironmentRecord { >-private: >+protected: > JSLexicalEnvironment(VM&, Structure*, JSScope*, SymbolTable*); > > public: >diff --git a/Source/JavaScriptCore/runtime/JSModuleEnvironment.cpp b/Source/JavaScriptCore/runtime/JSModuleEnvironment.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..c7017312c66d62537697240109e07bd002764667 >--- /dev/null >+++ b/Source/JavaScriptCore/runtime/JSModuleEnvironment.cpp >@@ -0,0 +1,133 @@ >+/* >+ * Copyright (C) 2015 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of >+ * its contributors may be used to endorse or promote products derived >+ * from this software without specific prior written permission. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED >+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE >+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY >+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES >+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; >+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND >+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF >+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+#include "JSModuleEnvironment.h" >+ >+#include "Interpreter.h" >+#include "JSCInlines.h" >+#include "JSFunction.h" >+ >+using namespace std; >+ >+namespace JSC { >+ >+const ClassInfo JSModuleEnvironment::s_info = { "JSModuleEnvironment", &Base::s_info, 0, CREATE_METHOD_TABLE(JSModuleEnvironment) }; >+ >+JSModuleEnvironment* JSModuleEnvironment::create( >+ VM& vm, Structure* structure, JSScope* currentScope, SymbolTable* symbolTable, JSValue initialValue, JSModuleRecord* moduleRecord) >+{ >+ // JSLexicalEnvironment (precisely, JSEnvironmentRecord) has the storage to store the variable slots after the its class storage. >+ // Because the offset of the variable slots are fixed in the JSEnvironmentRecord, inheritting these class and adding new member field is not allowed, >+ // the new member will overlap the variable slots. >+ // To keep the JSModuleEnvironment compatible to the JSLexicalEnvironment but add the new member to store the JSModuleRecord, we additionally allocate >+ // the storage after the variable slots. >+ // >+ // JSLexicalEnvironment: >+ // [ JSLexicalEnvironment ][ variable slots ] >+ // >+ // JSModuleEnvironment: >+ // [ JSLexicalEnvironment ][ variable slots ][ additional slots for JSModuleEnvironment ] >+ JSModuleEnvironment* result = >+ new ( >+ NotNull, >+ allocateCell<JSModuleEnvironment>(vm.heap, JSModuleEnvironment::allocationSize(symbolTable))) >+ JSModuleEnvironment(vm, structure, currentScope, symbolTable); >+ result->finishCreation(vm, initialValue, moduleRecord); >+ return result; >+} >+ >+void JSModuleEnvironment::finishCreation(VM& vm, JSValue initialValue, JSModuleRecord* moduleRecord) >+{ >+ Base::finishCreation(vm, initialValue); >+ this->moduleRecordSlot().set(vm, this, moduleRecord); >+} >+ >+void JSModuleEnvironment::visitChildren(JSCell* cell, SlotVisitor& visitor) >+{ >+ JSModuleEnvironment* thisObject = jsCast<JSModuleEnvironment*>(cell); >+ Base::visitChildren(thisObject, visitor); >+ visitor.appendValues(thisObject->variables(), thisObject->symbolTable()->scopeSize()); >+ visitor.append(&thisObject->moduleRecordSlot()); >+} >+ >+bool JSModuleEnvironment::getOwnPropertySlot(JSObject* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot) >+{ >+ JSModuleEnvironment* thisObject = jsCast<JSModuleEnvironment*>(cell); >+ JSModuleRecord::Resolution resolution = thisObject->moduleRecord()->resolveImport(exec, Identifier::fromUid(exec, propertyName.uid())); >+ if (resolution.type == JSModuleRecord::Resolution::Type::Resolved) { >+ // When resolveImport resolves the resolution, the imported module environment must have the binding. >+ JSModuleEnvironment* importedModuleEnvironment = resolution.moduleRecord->moduleEnvironment(); >+ PropertySlot redirectSlot(importedModuleEnvironment); >+ bool result = importedModuleEnvironment->methodTable(exec->vm())->getOwnPropertySlot(importedModuleEnvironment, exec, resolution.localName, redirectSlot); >+ ASSERT_UNUSED(result, result); >+ ASSERT(redirectSlot.isValue()); >+ JSValue value = redirectSlot.getValue(exec, resolution.localName); >+ ASSERT(!exec->hadException()); >+ slot.setValue(thisObject, redirectSlot.attributes(), value); >+ return true; >+ } >+ return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot); >+} >+ >+void JSModuleEnvironment::getOwnNonIndexPropertyNames(JSObject* cell, ExecState* exec, PropertyNameArray& propertyNamesArray, EnumerationMode mode) >+{ >+ JSModuleEnvironment* thisObject = jsCast<JSModuleEnvironment*>(cell); >+ if (propertyNamesArray.includeStringProperties()) { >+ for (const auto& pair : thisObject->moduleRecord()->importEntries()) { >+ const JSModuleRecord::ImportEntry& importEntry = pair.value; >+ if (!importEntry.isNamespace(exec->vm())) >+ propertyNamesArray.add(importEntry.localName); >+ } >+ } >+ return Base::getOwnNonIndexPropertyNames(thisObject, exec, propertyNamesArray, mode); >+} >+ >+void JSModuleEnvironment::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) >+{ >+ JSModuleEnvironment* thisObject = jsCast<JSModuleEnvironment*>(cell); >+ // All imported bindings are immutable. >+ JSModuleRecord::Resolution resolution = thisObject->moduleRecord()->resolveImport(exec, Identifier::fromUid(exec, propertyName.uid())); >+ if (resolution.type == JSModuleRecord::Resolution::Type::Resolved) { >+ throwTypeError(exec, ASCIILiteral(StrictModeReadonlyPropertyWriteError)); >+ return; >+ } >+ return Base::put(thisObject, exec, propertyName, value, slot); >+} >+ >+bool JSModuleEnvironment::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) >+{ >+ JSModuleEnvironment* thisObject = jsCast<JSModuleEnvironment*>(cell); >+ // All imported bindings are immutable. >+ JSModuleRecord::Resolution resolution = thisObject->moduleRecord()->resolveImport(exec, Identifier::fromUid(exec, propertyName.uid())); >+ if (resolution.type == JSModuleRecord::Resolution::Type::Resolved) >+ return false; >+ return Base::deleteProperty(thisObject, exec, propertyName); >+} >+ >+} // namespace JSC >diff --git a/Source/JavaScriptCore/runtime/JSModuleEnvironment.h b/Source/JavaScriptCore/runtime/JSModuleEnvironment.h >new file mode 100644 >index 0000000000000000000000000000000000000000..f7efa6263b2b2749f788c0a7f073f7677a009b03 >--- /dev/null >+++ b/Source/JavaScriptCore/runtime/JSModuleEnvironment.h >@@ -0,0 +1,103 @@ >+/* >+ * Copyright (C) 2015 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of >+ * its contributors may be used to endorse or promote products derived >+ * from this software without specific prior written permission. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED >+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE >+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY >+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES >+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; >+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND >+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF >+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#ifndef JSModuleEnvironment_h >+#define JSModuleEnvironment_h >+ >+#include "JSLexicalEnvironment.h" >+#include "JSModuleRecord.h" >+ >+namespace JSC { >+ >+class Register; >+ >+class JSModuleEnvironment : public JSLexicalEnvironment { >+ friend class JIT; >+ friend class LLIntOffsetsExtractor; >+public: >+ typedef JSLexicalEnvironment Base; >+ static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetPropertyNames; >+ >+ static JSModuleEnvironment* create(VM&, Structure*, JSScope*, SymbolTable*, JSValue initialValue, JSModuleRecord*); >+ >+ static JSModuleEnvironment* create(VM& vm, JSGlobalObject* globalObject, JSScope* currentScope, SymbolTable* symbolTable, JSValue initialValue, JSModuleRecord* moduleRecord) >+ { >+ Structure* structure = globalObject->moduleEnvironmentStructure(); >+ return create(vm, structure, currentScope, symbolTable, initialValue, moduleRecord); >+ } >+ >+ DECLARE_INFO; >+ >+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject) >+ { >+ return Structure::create(vm, globalObject, jsNull(), TypeInfo(ObjectType, StructureFlags), info()); >+ } >+ >+ static size_t offsetOfModuleRecord(SymbolTable* symbolTable) >+ { >+ size_t offset = Base::allocationSize(symbolTable); >+ ASSERT(WTF::roundUpToMultipleOf<sizeof(WriteBarrier<JSModuleRecord>)>(offset) == offset); >+ return offset; >+ } >+ >+ static size_t allocationSize(SymbolTable* symbolTable) >+ { >+ return offsetOfModuleRecord(symbolTable) + sizeof(WriteBarrier<JSModuleRecord>); >+ } >+ >+ JSModuleRecord* moduleRecord() >+ { >+ return moduleRecordSlot().get(); >+ } >+ >+ static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); >+ static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); >+ static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); >+ static bool deleteProperty(JSCell*, ExecState*, PropertyName); >+ >+private: >+ JSModuleEnvironment(VM&, Structure*, JSScope*, SymbolTable*); >+ >+ void finishCreation(VM&, JSValue initialValue, JSModuleRecord*); >+ >+ WriteBarrierBase<JSModuleRecord>& moduleRecordSlot() >+ { >+ return *bitwise_cast<WriteBarrierBase<JSModuleRecord>*>(bitwise_cast<char*>(this) + offsetOfModuleRecord(symbolTable())); >+ } >+ >+ static void visitChildren(JSCell*, SlotVisitor&); >+}; >+ >+inline JSModuleEnvironment::JSModuleEnvironment(VM& vm, Structure* structure, JSScope* currentScope, SymbolTable* symbolTable) >+ : Base(vm, structure, currentScope, symbolTable) >+{ >+} >+ >+} // namespace JSC >+ >+#endif // JSModuleEnvironment_h >diff --git a/Source/JavaScriptCore/runtime/JSModuleRecord.cpp b/Source/JavaScriptCore/runtime/JSModuleRecord.cpp >index 7b606374a6060b77020c4ef4512e9245e03f3fc5..2cefbe9401cad6472c71c42a0c8706518efd264b 100644 >--- a/Source/JavaScriptCore/runtime/JSModuleRecord.cpp >+++ b/Source/JavaScriptCore/runtime/JSModuleRecord.cpp >@@ -32,6 +32,7 @@ > #include "JSCJSValueInlines.h" > #include "JSCellInlines.h" > #include "JSMap.h" >+#include "JSModuleEnvironment.h" > #include "SlotVisitorInlines.h" > #include "StructureInlines.h" > >@@ -60,10 +61,49 @@ void JSModuleRecord::visitChildren(JSCell* cell, SlotVisitor& visitor) > { > JSModuleRecord* thisObject = jsCast<JSModuleRecord*>(cell); > Base::visitChildren(thisObject, visitor); >+ visitor.append(&thisObject->m_moduleEnvironment); > visitor.append(&thisObject->m_moduleProgramExecutable); > visitor.append(&thisObject->m_dependenciesMap); > } > >+void JSModuleRecord::appendRequestedModule(const Identifier& moduleName) >+{ >+ m_requestedModules.add(moduleName.impl()); >+} >+ >+void JSModuleRecord::addStarExportEntry(const Identifier& moduleName) >+{ >+ m_starExportEntries.add(moduleName.impl()); >+} >+ >+void JSModuleRecord::addImportEntry(const ImportEntry& entry) >+{ >+ bool isNewEntry = m_importEntries.add(entry.localName.impl(), entry).isNewEntry; >+ ASSERT_UNUSED(isNewEntry, isNewEntry); // This is guaranteed by the parser. >+} >+ >+void JSModuleRecord::addExportEntry(const ExportEntry& entry) >+{ >+ bool isNewEntry = m_exportEntries.add(entry.exportName.impl(), entry).isNewEntry; >+ ASSERT_UNUSED(isNewEntry, isNewEntry); // This is guaranteed by the parser. >+} >+ >+auto JSModuleRecord::tryGetImportEntry(UniquedStringImpl* localName) -> Optional<ImportEntry> >+{ >+ const auto iterator = m_importEntries.find(localName); >+ if (iterator == m_importEntries.end()) >+ return Nullopt; >+ return Optional<ImportEntry>(iterator->value); >+} >+ >+auto JSModuleRecord::tryGetExportEntry(UniquedStringImpl* exportName) -> Optional<ExportEntry> >+{ >+ const auto iterator = m_exportEntries.find(exportName); >+ if (iterator == m_exportEntries.end()) >+ return Nullopt; >+ return Optional<ExportEntry>(iterator->value); >+} >+ > auto JSModuleRecord::ExportEntry::createLocal(const Identifier& exportName, const Identifier& localName, const VariableEnvironmentEntry& variable) -> ExportEntry > { > return ExportEntry { Type::Local, exportName, Identifier(), Identifier(), localName, variable }; >@@ -79,6 +119,21 @@ auto JSModuleRecord::ExportEntry::createIndirect(const Identifier& exportName, c > return ExportEntry { Type::Indirect, exportName, moduleName, importName, Identifier(), VariableEnvironmentEntry() }; > } > >+auto JSModuleRecord::Resolution::notFound() -> Resolution >+{ >+ return Resolution { Type::NotFound, nullptr, Identifier() }; >+} >+ >+auto JSModuleRecord::Resolution::error() -> Resolution >+{ >+ return Resolution { Type::Error, nullptr, Identifier() }; >+} >+ >+auto JSModuleRecord::Resolution::ambiguous() -> Resolution >+{ >+ return Resolution { Type::Ambiguous, nullptr, Identifier() }; >+} >+ > static JSValue identifierToJSValue(ExecState* exec, const Identifier& identifier) > { > if (identifier.isSymbol()) >@@ -93,6 +148,279 @@ JSModuleRecord* JSModuleRecord::hostResolveImportedModule(ExecState* exec, const > return jsCast<JSModuleRecord*>(pair.get(exec, Identifier::fromString(exec, "value"))); > } > >+auto JSModuleRecord::resolveImport(ExecState* exec, const Identifier& localName) -> Resolution >+{ >+ Optional<ImportEntry> optionalImportEntry = tryGetImportEntry(localName.impl()); >+ if (!optionalImportEntry) >+ return Resolution::notFound(); >+ >+ const ImportEntry& importEntry = *optionalImportEntry; >+ if (importEntry.isNamespace(exec->vm())) >+ return Resolution::notFound(); >+ >+ JSModuleRecord* importedModule = hostResolveImportedModule(exec, importEntry.moduleRequest); >+ return importedModule->resolveExport(exec, importEntry.importName); >+} >+ >+struct ResolveQuery { >+ ResolveQuery(JSModuleRecord* moduleRecord, UniquedStringImpl* exportName) >+ : moduleRecord(moduleRecord) >+ , exportName(exportName) >+ { >+ } >+ >+ ResolveQuery(JSModuleRecord* moduleRecord, const Identifier& exportName) >+ : ResolveQuery(moduleRecord, exportName.impl()) >+ { >+ } >+ >+ enum EmptyValueTag { EmptyValue }; >+ ResolveQuery(EmptyValueTag) >+ { >+ } >+ >+ enum DeletedValueTag { DeletedValue }; >+ ResolveQuery(DeletedValueTag) >+ : moduleRecord(nullptr) >+ , exportName(WTF::HashTableDeletedValue) >+ { >+ } >+ >+ bool isEmptyValue() const >+ { >+ return !exportName; >+ } >+ >+ bool isDeletedValue() const >+ { >+ return exportName.isHashTableDeletedValue(); >+ } >+ >+ // The module record is not marked from the GC. But these records are reachable from the JSGlobalObject. >+ // So we don't care the reachability to this record. >+ JSModuleRecord* moduleRecord; >+ RefPtr<UniquedStringImpl> exportName; >+}; >+ >+struct ResolveQueryHash { >+ static unsigned hash(const ResolveQuery&); >+ static bool equal(const ResolveQuery&, const ResolveQuery&); >+ static const bool safeToCompareToEmptyOrDeleted = true; >+}; >+ >+inline unsigned ResolveQueryHash::hash(const ResolveQuery& query) >+{ >+ return WTF::PtrHash<JSModuleRecord*>::hash(query.moduleRecord) + IdentifierRepHash::hash(query.exportName); >+} >+ >+inline bool ResolveQueryHash::equal(const ResolveQuery& lhs, const ResolveQuery& rhs) >+{ >+ return lhs.moduleRecord == rhs.moduleRecord && lhs.exportName == rhs.exportName; >+} >+ >+static JSModuleRecord::Resolution resolveExportLoop(ExecState* exec, const ResolveQuery& root) >+{ >+ // http://www.ecma-international.org/ecma-262/6.0/#sec-resolveexport >+ // This function avoids C++ recursion of the naive ResolveExport implementation. >+ // Flatten the recursion to the loop with the task queue and frames. >+ // >+ // 1. pendingTasks >+ // We enqueue the recursive resolveExport call to this queue to avoid recursive calls in C++. >+ // The task has 3 types. (1) Query, (2) IndirectFallback and (3) GatherStars. >+ // (1) Query >+ // Querying the resolution to the current module. >+ // (2) IndirectFallback >+ // Examine the result of the indirect export resolution. Only when the indirect export resolution fails, >+ // we look into the star exports. (step 5-a-vi). >+ // (3) GatherStars >+ // Examine the result of the star export resolutions. >+ // >+ // 2. frames >+ // When the spec calls the resolveExport recursively, instead we append the frame >+ // (that holds the result resolution) to the frames and enqueue the task to the pendingTasks. >+ // The entry in the frames means the *local* resolution result of the specific recursive resolveExport. >+ // >+ // We should maintain the local resolution result instead of holding the global resolution result only. >+ // For example, >+ // >+ // star >+ // (1) ---> (2) "Resolve" >+ // | >+ // | >+ // +-> (3) "NotFound" >+ // | >+ // | star >+ // +-> (4) ---> (5) "Resolve" [here] >+ // | >+ // | >+ // +-> (6) "Error" >+ // >+ // Consider the above graph. The numbers represents the modules. Now we are [here]. >+ // If we only hold the global resolution result during the resolveExport operation, [here], >+ // we decide the entire result of resolveExport is "Ambiguous", because there are multiple >+ // "Reslove" (in module (2) and (5)). However, this should become "Error" because (6) will >+ // propagate "Error" state to the (4), (4) will become "Error" and then, (1) will become >+ // "Error". We should aggregate the results at the star exports point ((4) and (1)). >+ // >+ // Usually, both "Error" and "Ambiguous" states will throw the syntax error. So except for the content of the >+ // error message, there are no difference. (And if we fix the (6) that raises "Error", next, it will produce >+ // the "Ambiguous" error due to (5). Anyway, user need to fix the both. So which error should be raised at first >+ // doesn't matter so much. >+ // >+ // However, this may become the problem under the module namespace creation. >+ // http://www.ecma-international.org/ecma-262/6.0/#sec-getmodulenamespace >+ // section 15.2.1.18, step 3-d-ii >+ // Here, we distinguish "Ambiguous" and "Error". When "Error" state is produced, we need to throw the propagated error. >+ // But if "Ambiguous" state comes, we just ignore the result. >+ // To follow the requirement strictly, in this implementation, we keep the local resolution result to produce the >+ // correct result under the above complex cases. >+ >+ using Resolution = JSModuleRecord::Resolution; >+ typedef WTF::HashSet<ResolveQuery, ResolveQueryHash, WTF::CustomHashTraits<ResolveQuery>> ResolveSet; >+ enum class Type { Query, IndirectFallback, GatherStars }; >+ struct Task { >+ ResolveQuery query; >+ Type type; >+ }; >+ >+ Vector<Task, 8> pendingTasks; >+ ResolveSet resolveSet; >+ HashSet<JSModuleRecord*> starSet; >+ Vector<Resolution, 8> frames; >+ >+ frames.append(Resolution::notFound()); >+ >+ // Call when the query is not resolved in the current module. >+ // It will enqueue the star resolution requests. Return "false" if the error occurs. >+ auto resolveNonLocal = [&](const ResolveQuery& query) -> bool { >+ // http://www.ecma-international.org/ecma-262/6.0/#sec-resolveexport >+ // section 15.2.1.16.3, step 6 >+ // If the "default" name is not resolved in the current module, we need to throw an error and stop resolution immediately, >+ // Rationale to this error: A default export cannot be provided by an export *. >+ if (query.exportName == exec->propertyNames().defaultKeyword.impl()) >+ return false; >+ >+ // step 7, If exportStarSet contains module, then return null. >+ if (!starSet.add(query.moduleRecord).isNewEntry) >+ return true; >+ >+ // Enqueue the task to gather the results of the stars. >+ // And append the new Resolution frame to gather the local result of the stars. >+ pendingTasks.append(Task { query, Type::GatherStars }); >+ frames.append(Resolution::notFound()); >+ >+ // Enqueue the tasks in reverse order. >+ for (auto iterator = query.moduleRecord->starExportEntries().rbegin(), end = query.moduleRecord->starExportEntries().rend(); iterator != end; ++iterator) { >+ const RefPtr<UniquedStringImpl>& starModuleName = *iterator; >+ JSModuleRecord* importedModuleRecord = query.moduleRecord->hostResolveImportedModule(exec, Identifier::fromUid(exec, starModuleName.get())); >+ pendingTasks.append(Task { ResolveQuery(importedModuleRecord, query.exportName.get()), Type::Query }); >+ } >+ return true; >+ }; >+ >+ // Return the current resolution value of the top frame. >+ auto currentTop = [&] () -> Resolution& { >+ ASSERT(!frames.isEmpty()); >+ return frames.last(); >+ }; >+ >+ // Merge the given resolution to the current resolution value of the top frame. >+ // If there is ambiguity, return "false". When the "false" is returned, we should make the result "ambiguous". >+ auto mergeToCurrentTop = [&] (const Resolution& resolution) -> bool { >+ if (resolution.type == Resolution::Type::NotFound) >+ return true; >+ >+ if (currentTop().type == Resolution::Type::NotFound) { >+ currentTop() = resolution; >+ return true; >+ } >+ >+ if (currentTop().moduleRecord != resolution.moduleRecord || currentTop().localName != resolution.localName) >+ return false; >+ >+ return true; >+ }; >+ >+ pendingTasks.append(Task { root, Type::Query }); >+ while (!pendingTasks.isEmpty()) { >+ const Task task = pendingTasks.takeLast(); >+ const ResolveQuery& query = task.query; >+ >+ switch (task.type) { >+ case Type::Query: { >+ if (!resolveSet.add(task.query).isNewEntry) >+ continue; >+ >+ JSModuleRecord* moduleRecord = query.moduleRecord; >+ const Optional<JSModuleRecord::ExportEntry> optionalExportEntry = moduleRecord->tryGetExportEntry(query.exportName.get()); >+ if (!optionalExportEntry) { >+ // If there is no matched exported binding in the current module, >+ // we need to look into the stars. >+ if (!resolveNonLocal(task.query)) >+ return Resolution::error(); >+ continue; >+ } >+ >+ const JSModuleRecord::ExportEntry& exportEntry = *optionalExportEntry; >+ switch (exportEntry.type) { >+ case JSModuleRecord::ExportEntry::Type::Local: >+ case JSModuleRecord::ExportEntry::Type::Namespace: >+ if (!mergeToCurrentTop(Resolution { Resolution::Type::Resolved, moduleRecord, exportEntry.localName })) >+ return Resolution::ambiguous(); >+ continue; >+ >+ case JSModuleRecord::ExportEntry::Type::Indirect: { >+ JSModuleRecord* importedModuleRecord = moduleRecord->hostResolveImportedModule(exec, exportEntry.moduleName); >+ >+ // When the imported module does not produce any resolved binding, we need to look into the stars in the *current* >+ // module. To do this, we append the `IndirectFallback` task to the task queue. >+ pendingTasks.append(Task { query, Type::IndirectFallback }); >+ // And append the new Resolution frame to check the indirect export will be resolved or not. >+ frames.append(Resolution::notFound()); >+ pendingTasks.append(Task { ResolveQuery(importedModuleRecord, exportEntry.importName), Type::Query }); >+ continue; >+ } >+ } >+ break; >+ } >+ >+ case Type::IndirectFallback: { >+ JSModuleRecord::Resolution resolution = frames.takeLast(); >+ >+ if (resolution.type == Resolution::Type::NotFound) { >+ // Indirect export entry does not produce any resolved binding. >+ // So we will investigate the stars. >+ if (!resolveNonLocal(task.query)) >+ return Resolution::error(); >+ continue; >+ } >+ >+ // If indirect export entry produces Resolved, we should merge it to the upper frame. >+ // And do not investigate the stars of the current module. >+ if (!mergeToCurrentTop(resolution)) >+ return Resolution::ambiguous(); >+ break; >+ } >+ >+ case Type::GatherStars: { >+ // Merge the star resolution to the upper frame. >+ JSModuleRecord::Resolution starResolution = frames.takeLast(); >+ if (!mergeToCurrentTop(starResolution)) >+ return Resolution::ambiguous(); >+ break; >+ } >+ } >+ } >+ >+ ASSERT(frames.size() == 1); >+ return frames[0]; >+} >+ >+auto JSModuleRecord::resolveExport(ExecState* exec, const Identifier& exportName) -> Resolution >+{ >+ return resolveExportLoop(exec, ResolveQuery(this, exportName.impl())); >+} >+ > void JSModuleRecord::link(ExecState* exec) > { > ModuleProgramExecutable* executable = ModuleProgramExecutable::create(exec, sourceCode()); >@@ -101,11 +429,120 @@ void JSModuleRecord::link(ExecState* exec) > return; > } > m_moduleProgramExecutable.set(exec->vm(), this, executable); >+ instantiateDeclarations(exec, executable); > } > >-JSValue JSModuleRecord::execute(ExecState*) >+void JSModuleRecord::instantiateDeclarations(ExecState* exec, ModuleProgramExecutable* moduleProgramExecutable) > { >- return jsUndefined(); >+ // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation >+ >+ SymbolTable* symbolTable = moduleProgramExecutable->moduleEnvironmentSymbolTable(); >+ JSModuleEnvironment* moduleEnvironment = JSModuleEnvironment::create(exec->vm(), exec->lexicalGlobalObject(), exec->lexicalGlobalObject(), symbolTable, jsTDZValue(), this); >+ >+ VM& vm = exec->vm(); >+ >+ // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation >+ // section 15.2.1.16.4 step 9. >+ // Ensure all the indirect exports are correctly resolved to unique bindings. >+ // Even if we avoided duplicate exports in the parser, still ambiguous exports occur due to the star export (`export * from "mod"`). >+ // When we see this type of ambiguity for the indirect exports here, throw a syntax error. >+ for (const auto& pair : m_exportEntries) { >+ const ExportEntry& exportEntry = pair.value; >+ if (exportEntry.type == JSModuleRecord::ExportEntry::Type::Indirect) { >+ Resolution resolution = resolveExport(exec, exportEntry.exportName); >+ switch (resolution.type) { >+ case Resolution::Type::NotFound: >+ throwSyntaxError(exec, makeString("Indirectly exported binding name '", String(exportEntry.exportName.impl()), "' is not found.")); >+ return; >+ >+ case Resolution::Type::Ambiguous: >+ throwSyntaxError(exec, makeString("Indirectly exported binding name '", String(exportEntry.exportName.impl()), "' cannot be resolved due to ambiguous multiple bindings.")); >+ return; >+ >+ case Resolution::Type::Error: >+ throwSyntaxError(exec, makeString("Indirectly exported binding name 'default' cannot be resolved by star export entries.")); >+ return; >+ >+ case Resolution::Type::Resolved: >+ break; >+ } >+ } >+ } >+ >+ // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation >+ // section 15.2.1.16.4 step 12. >+ // Instantiate namespace objects and initialize the bindings with them if required. >+ // And ensure that all the imports correctly resolved to unique bindings. >+ for (const auto& pair : m_importEntries) { >+ const ImportEntry& importEntry = pair.value; >+ JSModuleRecord* importedModule = hostResolveImportedModule(exec, importEntry.moduleRequest); >+ if (importEntry.isNamespace(vm)) { >+ // FIXME: ModuleNamespaceObject will be implemented. >+ // https://bugs.webkit.org/show_bug.cgi?id=148705 >+ } else { >+ Resolution resolution = importedModule->resolveExport(exec, importEntry.importName); >+ switch (resolution.type) { >+ case Resolution::Type::NotFound: >+ throwSyntaxError(exec, makeString("Importing binding name '", String(importEntry.importName.impl()), "' is not found.")); >+ return; >+ >+ case Resolution::Type::Ambiguous: >+ throwSyntaxError(exec, makeString("Importing binding name '", String(importEntry.importName.impl()), "' cannot be resolved due to ambiguous multiple bindings.")); >+ return; >+ >+ case Resolution::Type::Error: >+ throwSyntaxError(exec, makeString("Importing binding name 'default' cannot be resolved by star export entries.")); >+ return; >+ >+ case Resolution::Type::Resolved: >+ break; >+ } >+ } >+ } >+ >+ // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation >+ // section 15.2.1.16.4 step 14. >+ // Module environment contains the heap allocated "var", "function", "let", "const", and "class". >+ // When creating the environment, we initialized all the slots with empty, it's ok for lexical values. >+ // But for "var" and "function", we should initialize it with undefined. They are contained in the declared variables. >+ for (const auto& variable : m_declaredVariables) { >+ SymbolTableEntry entry = symbolTable->get(variable.key.get()); >+ VarOffset offset = entry.varOffset(); >+ if (!offset.isStack()) >+ symbolTablePut(moduleEnvironment, exec, Identifier::fromUid(exec, variable.key.get()), jsUndefined(), false, true); >+ } >+ >+ // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation >+ // section 15.2.1.16.4 step 16-a-iv. >+ // Initialize heap allocated function declarations. >+ // They can be called before the body of the module is executed under circular dependencies. >+ UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock = moduleProgramExecutable->unlinkedModuleProgramCodeBlock(); >+ for (size_t i = 0, numberOfFunctions = unlinkedCodeBlock->numberOfFunctionDecls(); i < numberOfFunctions; ++i) { >+ UnlinkedFunctionExecutable* unlinkedFunctionExecutable = unlinkedCodeBlock->functionDecl(i); >+ SymbolTableEntry entry = symbolTable->get(unlinkedFunctionExecutable->name().impl()); >+ VarOffset offset = entry.varOffset(); >+ if (!offset.isStack()) { >+ ASSERT(!unlinkedFunctionExecutable->name().isEmpty()); >+ if (vm.typeProfiler() || vm.controlFlowProfiler()) { >+ vm.functionHasExecutedCache()->insertUnexecutedRange(moduleProgramExecutable->sourceID(), >+ unlinkedFunctionExecutable->typeProfilingStartOffset(), >+ unlinkedFunctionExecutable->typeProfilingEndOffset()); >+ } >+ JSFunction* function = JSFunction::create(vm, unlinkedFunctionExecutable->link(vm, moduleProgramExecutable->source()), moduleEnvironment); >+ symbolTablePut(moduleEnvironment, exec, unlinkedFunctionExecutable->name(), function, false, true); >+ } >+ } >+ >+ m_moduleEnvironment.set(vm, this, moduleEnvironment); >+} >+ >+JSValue JSModuleRecord::execute(ExecState* exec) >+{ >+ if (!m_moduleProgramExecutable) >+ return jsUndefined(); >+ JSValue result = exec->interpreter()->execute(m_moduleProgramExecutable.get(), exec, m_moduleEnvironment.get()); >+ m_moduleProgramExecutable.clear(); >+ return result; > } > > static String printableName(const RefPtr<UniquedStringImpl>& uid) >@@ -129,23 +566,25 @@ void JSModuleRecord::dump() > dataLog(" module(", printableName(moduleName), ")\n"); > > dataLog(" Import: ", m_importEntries.size(), " entries\n"); >- for (const auto& pair : m_importEntries) >- dataLog(" import(", printableName(pair.value.importName), "), local(", printableName(pair.value.localName), "), module(", printableName(pair.value.moduleRequest), ")\n"); >+ for (const auto& pair : m_importEntries) { >+ const ImportEntry& importEntry = pair.value; >+ dataLog(" import(", printableName(importEntry.importName), "), local(", printableName(importEntry.localName), "), module(", printableName(importEntry.moduleRequest), ")\n"); >+ } > > dataLog(" Export: ", m_exportEntries.size(), " entries\n"); > for (const auto& pair : m_exportEntries) { >- const ExportEntry& entry = pair.value; >- switch (entry.type) { >+ const ExportEntry& exportEntry = pair.value; >+ switch (exportEntry.type) { > case ExportEntry::Type::Local: >- dataLog(" [Local] ", "export(", printableName(entry.exportName), "), local(", printableName(entry.localName), ")\n"); >+ dataLog(" [Local] ", "export(", printableName(exportEntry.exportName), "), local(", printableName(exportEntry.localName), ")\n"); > break; > > case ExportEntry::Type::Namespace: >- dataLog(" [Namespace] ", "export(", printableName(entry.exportName), "), module(", printableName(entry.moduleName), ")\n"); >+ dataLog(" [Namespace] ", "export(", printableName(exportEntry.exportName), "), module(", printableName(exportEntry.moduleName), ")\n"); > break; > > case ExportEntry::Type::Indirect: >- dataLog(" [Indirect] ", "export(", printableName(entry.exportName), "), import(", printableName(entry.importName), "), module(", printableName(entry.moduleName), ")\n"); >+ dataLog(" [Indirect] ", "export(", printableName(exportEntry.exportName), "), import(", printableName(exportEntry.importName), "), module(", printableName(exportEntry.moduleName), ")\n"); > break; > } > } >diff --git a/Source/JavaScriptCore/runtime/JSModuleRecord.h b/Source/JavaScriptCore/runtime/JSModuleRecord.h >index 81da3966e8c5a8da9304d282f4fbca94f24eae48..08521b4ccd3b04aaee03b3b441a21c1f6d419647 100644 >--- a/Source/JavaScriptCore/runtime/JSModuleRecord.h >+++ b/Source/JavaScriptCore/runtime/JSModuleRecord.h >@@ -32,6 +32,7 @@ > #include "VariableEnvironment.h" > #include <wtf/HashMap.h> > #include <wtf/ListHashSet.h> >+#include <wtf/Optional.h> > > namespace JSC { > >@@ -78,8 +79,8 @@ class JSModuleRecord : public JSDestructibleObject { > }; > > typedef WTF::ListHashSet<RefPtr<UniquedStringImpl>, IdentifierRepHash> OrderedIdentifierSet; >- typedef HashMap<RefPtr<UniquedStringImpl>, ImportEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> ImportMap; >- typedef HashMap<RefPtr<UniquedStringImpl>, ExportEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> ExportMap; >+ typedef HashMap<RefPtr<UniquedStringImpl>, ImportEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> ImportEntries; >+ typedef HashMap<RefPtr<UniquedStringImpl>, ExportEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> ExportEntries; > > DECLARE_EXPORT_INFO; > >@@ -100,25 +101,49 @@ class JSModuleRecord : public JSDestructibleObject { > void addImportEntry(const ImportEntry&); > void addExportEntry(const ExportEntry&); > >- const ImportEntry& lookUpImportEntry(const RefPtr<UniquedStringImpl>& localName); >+ Optional<ImportEntry> tryGetImportEntry(UniquedStringImpl* localName); >+ Optional<ExportEntry> tryGetExportEntry(UniquedStringImpl* exportName); > > const SourceCode& sourceCode() const { return m_sourceCode; } > const Identifier& moduleKey() const { return m_moduleKey; } > const OrderedIdentifierSet& requestedModules() const { return m_requestedModules; } >- const ExportMap& exportEntries() const { return m_exportEntries; } >- const ImportMap& importEntries() const { return m_importEntries; } >+ const ExportEntries& exportEntries() const { return m_exportEntries; } >+ const ImportEntries& importEntries() const { return m_importEntries; } >+ const OrderedIdentifierSet& starExportEntries() const { return m_starExportEntries; } > > const VariableEnvironment& declaredVariables() const { return m_declaredVariables; } > const VariableEnvironment& lexicalVariables() const { return m_lexicalVariables; } > > void dump(); > >+ JSModuleEnvironment* moduleEnvironment() >+ { >+ ASSERT(m_moduleEnvironment); >+ return m_moduleEnvironment.get(); >+ } > > void link(ExecState*); > JSValue execute(ExecState*); > > ModuleProgramExecutable* moduleProgramExecutable() const { return m_moduleProgramExecutable.get(); } > >+ struct Resolution { >+ enum class Type { Resolved, NotFound, Ambiguous, Error }; >+ >+ static Resolution notFound(); >+ static Resolution error(); >+ static Resolution ambiguous(); >+ >+ Type type; >+ JSModuleRecord* moduleRecord; >+ Identifier localName; >+ }; >+ >+ Resolution resolveExport(ExecState*, const Identifier& exportName); >+ Resolution resolveImport(ExecState*, const Identifier& localName); >+ >+ JSModuleRecord* hostResolveImportedModule(ExecState*, const Identifier& moduleName); >+ > private: > JSModuleRecord(VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables) > : Base(vm, structure) >@@ -134,7 +159,7 @@ class JSModuleRecord : public JSDestructibleObject { > static void visitChildren(JSCell*, SlotVisitor&); > static void destroy(JSCell*); > >- JSModuleRecord* hostResolveImportedModule(ExecState*, const Identifier& moduleName); >+ void instantiateDeclarations(ExecState*, ModuleProgramExecutable*); > > // The loader resolves the given module name to the module key. The module key is the unique value to represent this module. > Identifier m_moduleKey; >@@ -144,46 +169,37 @@ class JSModuleRecord : public JSDestructibleObject { > VariableEnvironment m_declaredVariables; > VariableEnvironment m_lexicalVariables; > >+ // Currently, we don't keep the occurrence order of the import / export entries. >+ // So, we does not guarantee the order of the errors. >+ // e.g. The import declaration that occurr later than the another import declaration may >+ // throw the error even if the former import declaration also has the invalid content. >+ // >+ // import ... // (1) this has some invalid content. >+ // import ... // (2) this also has some invalid content. >+ // >+ // In the above case, (2) may throw the error earlier than (1) >+ // >+ // But, in the all cases, we will throw the syntax error. So except for the content of the syntax error, >+ // there are no difference. >+ > // Map localName -> ImportEntry. >- ImportMap m_importEntries; >+ ImportEntries m_importEntries; > > // Map exportName -> ExportEntry. >- ExportMap m_exportEntries; >+ ExportEntries m_exportEntries; > >- IdentifierSet m_starExportEntries; >+ // Save the occurrence order since resolveExport requires it. >+ OrderedIdentifierSet m_starExportEntries; > > // Save the occurrence order since the module loader loads and runs the modules in this order. > // http://www.ecma-international.org/ecma-262/6.0/#sec-moduleevaluation > OrderedIdentifierSet m_requestedModules; > >- WriteBarrier<ModuleProgramExecutable> m_moduleProgramExecutable; > WriteBarrier<JSMap> m_dependenciesMap; >-}; > >-inline void JSModuleRecord::appendRequestedModule(const Identifier& moduleName) >-{ >- m_requestedModules.add(moduleName.impl()); >-} >- >-inline void JSModuleRecord::addImportEntry(const ImportEntry& entry) >-{ >- m_importEntries.add(entry.localName.impl(), entry); >-} >- >-inline void JSModuleRecord::addExportEntry(const ExportEntry& entry) >-{ >- m_exportEntries.add(entry.exportName.impl(), entry); >-} >- >-inline void JSModuleRecord::addStarExportEntry(const Identifier& moduleName) >-{ >- m_starExportEntries.add(moduleName.impl()); >-} >- >-inline auto JSModuleRecord::lookUpImportEntry(const RefPtr<UniquedStringImpl>& localName) -> const ImportEntry& >-{ >- return (*m_importEntries.find(localName)).value; >-} >+ WriteBarrier<ModuleProgramExecutable> m_moduleProgramExecutable; >+ WriteBarrier<JSModuleEnvironment> m_moduleEnvironment; >+}; > > } // namespace JSC > >diff --git a/Source/JavaScriptCore/runtime/JSScope.cpp b/Source/JavaScriptCore/runtime/JSScope.cpp >index 128a6022959c907ada7fc2073426b72b75e19ef2..087953e0165808caca64fa5f4e40d528146c95bc 100644 >--- a/Source/JavaScriptCore/runtime/JSScope.cpp >+++ b/Source/JavaScriptCore/runtime/JSScope.cpp >@@ -28,6 +28,8 @@ > > #include "JSGlobalObject.h" > #include "JSLexicalEnvironment.h" >+#include "JSModuleEnvironment.h" >+#include "JSModuleRecord.h" > #include "JSWithScope.h" > #include "JSCInlines.h" > >@@ -65,6 +67,19 @@ static inline bool abstractAccess(ExecState* exec, JSScope* scope, const Identif > return true; > } > >+ if (JSModuleEnvironment* moduleEnvironment = jsDynamicCast<JSModuleEnvironment*>(scope)) { >+ JSModuleRecord* moduleRecord = moduleEnvironment->moduleRecord(); >+ JSModuleRecord::Resolution resolution = moduleRecord->resolveImport(exec, ident); >+ if (resolution.type == JSModuleRecord::Resolution::Type::Resolved) { >+ JSModuleRecord* importedRecord = resolution.moduleRecord; >+ JSModuleEnvironment* importedEnvironment = importedRecord->moduleEnvironment(); >+ SymbolTableEntry entry = importedEnvironment->symbolTable()->get(resolution.localName.impl()); >+ ASSERT(!entry.isNull()); >+ op = ResolveOp(makeType(ModuleVar, needsVarInjectionChecks), depth, 0, importedEnvironment, entry.watchpointSet(), entry.scopeOffset().offset(), resolution.localName.impl()); >+ return true; >+ } >+ } >+ > if (lexicalEnvironment->symbolTable()->usesNonStrictEval()) > needsVarInjectionChecks = true; > return false; >diff --git a/Source/JavaScriptCore/runtime/ModuleLoaderObject.cpp b/Source/JavaScriptCore/runtime/ModuleLoaderObject.cpp >index 28e0badaa72af30cc771919604a612d6cdb73e07..6e6f9f9a6da61812e3c21ad4366fd87b7cd147d8 100644 >--- a/Source/JavaScriptCore/runtime/ModuleLoaderObject.cpp >+++ b/Source/JavaScriptCore/runtime/ModuleLoaderObject.cpp >@@ -35,6 +35,7 @@ > #include "JSInternalPromise.h" > #include "JSInternalPromiseDeferred.h" > #include "JSMap.h" >+#include "JSModuleEnvironment.h" > #include "JSModuleRecord.h" > #include "ModuleAnalyzer.h" > #include "Nodes.h"
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 148053
:
260413
|
260414
|
260415
|
260416
|
260426
|
260501
|
260503
|
260506
|
260514
|
260525
|
260527
|
260536