-
Notifications
You must be signed in to change notification settings - Fork 1.2k
module: support for circular import #4551
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -277,7 +277,10 @@ namespace Js | |
| HRESULT hr = NOERROR; | ||
| if (!WasDeclarationInitialized()) | ||
| { | ||
| ModuleDeclarationInstantiation(); | ||
| if (ModuleDeclarationInstantiation()) | ||
| { | ||
| GenerateRootFunction(); | ||
| } | ||
|
|
||
| if (this->errorObject != nullptr) | ||
| { | ||
|
|
@@ -336,7 +339,10 @@ namespace Js | |
| bool isScriptActive = scriptContext->GetThreadContext()->IsScriptActive(); | ||
| Assert(!isScriptActive || this->promise != nullptr); | ||
|
|
||
| ModuleDeclarationInstantiation(); | ||
| if (ModuleDeclarationInstantiation()) | ||
| { | ||
| GenerateRootFunction(); | ||
| } | ||
| if (!hadNotifyHostReady && !WasEvaluated()) | ||
| { | ||
| OUTPUT_TRACE_DEBUGONLY(Js::ModulePhase, _u("\t>NotifyHostAboutModuleReady %s (PrepareForModuleDeclarationInitialization)\n"), this->GetSpecifierSz()); | ||
|
|
@@ -800,14 +806,14 @@ namespace Js | |
| // helper information for now. | ||
| } | ||
|
|
||
| void SourceTextModuleRecord::ModuleDeclarationInstantiation() | ||
| bool SourceTextModuleRecord::ModuleDeclarationInstantiation() | ||
| { | ||
| OUTPUT_TRACE_DEBUGONLY(Js::ModulePhase, _u("ModuleDeclarationInstantiation(%s)\n"), this->GetSpecifierSz()); | ||
| ScriptContext* scriptContext = GetScriptContext(); | ||
|
|
||
| if (this->WasDeclarationInitialized()) | ||
| { | ||
| return; | ||
| return false; | ||
| } | ||
|
|
||
| try | ||
|
|
@@ -825,7 +831,17 @@ namespace Js | |
| childrenModuleSet->Map([](LPCOLESTR specifier, SourceTextModuleRecord* moduleRecord) | ||
| { | ||
| Assert(moduleRecord->WasParsed()); | ||
| moduleRecord->ModuleDeclarationInstantiation(); | ||
| moduleRecord->shouldGenerateRootFunction = | ||
| moduleRecord->ModuleDeclarationInstantiation(); | ||
| }); | ||
|
|
||
| childrenModuleSet->Map([](LPCOLESTR specifier, SourceTextModuleRecord* moduleRecord) | ||
| { | ||
| if (moduleRecord->shouldGenerateRootFunction) | ||
| { | ||
| moduleRecord->shouldGenerateRootFunction = false; | ||
| moduleRecord->GenerateRootFunction(); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
|
|
@@ -843,12 +859,21 @@ namespace Js | |
| { | ||
| OUTPUT_TRACE_DEBUGONLY(Js::ModulePhase, _u("\t>NotifyParentsAsNeeded (errorObject)\n")); | ||
| NotifyParentsAsNeeded(); | ||
| return; | ||
| return false; | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| void SourceTextModuleRecord::GenerateRootFunction() | ||
| { | ||
| ScriptContext* scriptContext = GetScriptContext(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make sense to assert this->WasDeclarationInitialized() ?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good, done! |
||
| Js::AutoDynamicCodeReference dynamicFunctionReference(scriptContext); | ||
| Assert(this == scriptContext->GetLibrary()->GetModuleRecord(this->pSourceInfo->GetSrcInfo()->moduleID)); | ||
| CompileScriptException se; | ||
|
|
||
| Assert(this->WasDeclarationInitialized()); | ||
| Assert(this == scriptContext->GetLibrary()->GetModuleRecord(this->pSourceInfo->GetSrcInfo()->moduleID)); | ||
|
|
||
| this->rootFunction = scriptContext->GenerateRootFunction(parseTree, sourceIndex, this->parser, this->pSourceInfo->GetParseFlags(), &se, _u("module")); | ||
| if (rootFunction == nullptr) | ||
| { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,11 +27,12 @@ namespace Js | |
| virtual ExportedNames* GetExportedNames(ExportModuleRecordList* exportStarSet) override; | ||
| virtual bool IsSourceTextModuleRecord() override { return true; } // we don't really have other kind of modulerecord at this time. | ||
|
|
||
| // return false when "ambiguous". | ||
| // return false when "ambiguous". | ||
| // otherwise nullptr means "null" where we have circular reference/cannot resolve. | ||
| bool ResolveExport(PropertyId exportName, ResolveSet* resolveSet, ModuleNameRecord** exportRecord) override; | ||
| bool ResolveImport(PropertyId localName, ModuleNameRecord** importRecord); | ||
| void ModuleDeclarationInstantiation() override; | ||
| bool ModuleDeclarationInstantiation() override; | ||
| void GenerateRootFunction(); | ||
| Var ModuleEvaluation() override; | ||
| virtual ModuleNamespace* GetNamespace(); | ||
| virtual void SetNamespace(ModuleNamespace* moduleNamespace); | ||
|
|
@@ -114,8 +115,9 @@ namespace Js | |
| const static uint InvalidSlotCount = 0xffffffff; | ||
| const static uint InvalidSlotIndex = 0xffffffff; | ||
| // TODO: move non-GC fields out to avoid false reference? | ||
| // This is the parsed tree resulted from compilation. | ||
| // This is the parsed tree resulted from compilation. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this comment supposed to be one line below now? |
||
| Field(bool) wasParsed; | ||
| Field(bool) shouldGenerateRootFunction; | ||
| Field(bool) wasDeclarationInitialized; | ||
| Field(bool) parentsNotified; | ||
| Field(bool) isRootModule; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| //------------------------------------------------------------------------------------------------------- | ||
| // Copyright (C) Microsoft. All rights reserved. | ||
| // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. | ||
| //------------------------------------------------------------------------------------------------------- | ||
|
|
||
| //this test case's circular dependencies would segfault | ||
| //with CC's orriginal module implementation if JIT was enabled | ||
| //issue was that: | ||
| //i) dep 1 requires dep2 and dep3 | ||
| //ii) MDI would therefore be triggerred for dep2 (with dep3 queued) | ||
| //iii) MDI for dep2 would not explicitly require dep3 as the import is via dep1 | ||
| //iv) second half of MDI for dep2 would attempt to reference the function Thing2 defined in dep 3 | ||
| //v) Thing2 would not yet exist = segfault | ||
|
|
||
|
|
||
| import Thing1 from './module_4482_dep2.js'; | ||
| import Thing2 from './module_4482_dep3.js'; | ||
|
|
||
| export { Thing1, Thing2 }; | ||
|
|
||
| export default | ||
| function main() | ||
| {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| //------------------------------------------------------------------------------------------------------- | ||
| // Copyright (C) Microsoft. All rights reserved. | ||
| // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. | ||
| //------------------------------------------------------------------------------------------------------- | ||
|
|
||
| //thing1.js | ||
| import { Thing2 } from './module_4482_dep1.js'; | ||
|
|
||
| export default | ||
| function Thing1() | ||
| { | ||
| Thing2(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| //------------------------------------------------------------------------------------------------------- | ||
| // Copyright (C) Microsoft. All rights reserved. | ||
| // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. | ||
| //------------------------------------------------------------------------------------------------------- | ||
|
|
||
|
|
||
| import { Thing1 } from './module_4482_dep1.js'; | ||
|
|
||
| export default | ||
| function Thing2(){} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can GenerateRootFunction set the above flag false itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's actually false rest of the times.