@masknet/compartment
Advanced tools
Comparing version 0.3.5 to 0.3.6
@@ -497,6 +497,8 @@ class ModuleSource { | ||
this.#ContextObject.import = async (specifier, options)=>{ | ||
const [module] = await Module.#HostResolveModules(this, [ | ||
await Module.#HostResolveModules(this, [ | ||
specifier | ||
]); | ||
assert(module); | ||
const cap = this.#ResolvedModules.get(specifier); | ||
assert(cap?.Status.Type === 'Fulfilled'); | ||
const module = cap.Status.Value; | ||
return Module.#DynamicImportModule(module); | ||
@@ -891,3 +893,5 @@ }; | ||
// if (!(#HasTLA in module)) throw new TypeError('ImportHook must return a Module instance') | ||
await this.#HostResolveModules(module, module.#RequestedModules); | ||
// Note: do not await here, otherwise it will deadlock under self-import. | ||
// But can we make sure the top promise resolved when and only when all of it's transitive dependency resolved? | ||
this.#HostResolveModules(module, module.#RequestedModules); | ||
return module; | ||
@@ -902,16 +906,26 @@ }, (error)=>{ | ||
// call importHook recursively to get all module referenced. | ||
static async #HostResolveModules(module14, requestModules) { | ||
const promises = requestModules.map(async (spec)=>{ | ||
const cache = module14.#ResolvedModules.get(spec); | ||
if (!cache) { | ||
return this.#HostResolveModulesInner(module14, spec); | ||
} else if (cache.Status.Type === 'Pending') { | ||
return cache.Status.Promise; | ||
} else if (cache.Status.Type === 'Fulfilled') { | ||
return cache.Status.Value; | ||
static #HostResolveModules(module14, requestModules) { | ||
if (requestModules.length === 0) return Promise.resolve(); | ||
const overallCapability = PromiseCapability(); | ||
function check() { | ||
if (overallCapability.Status.Type !== 'Pending') return; | ||
for (const m of module14.#ResolvedModules.values()){ | ||
if (m.Status.Type === 'Rejected') return overallCapability.Reject(m.Status.Reason); | ||
if (m.Status.Type === 'Pending') return void overallCapability.Promise.then(check, overallCapability.Reject); | ||
} | ||
overallCapability.Resolve(); | ||
} | ||
for (const spec2 of requestModules){ | ||
const capability3 = module14.#ResolvedModules.get(spec2); | ||
if (!capability3) { | ||
this.#HostResolveModulesInner(module14, spec2).then(check, overallCapability.Reject); | ||
} else if (capability3.Status.Type === 'Fulfilled') { | ||
check(); | ||
} else if (capability3.Status.Type === 'Pending') { | ||
capability3.Promise.then(check, overallCapability.Reject); | ||
} else { | ||
throw cache.Status.Reason; | ||
overallCapability.Reject(capability3.Status.Reason); | ||
} | ||
}); | ||
return Promise.all(promises); | ||
} | ||
return overallCapability.Promise; | ||
} | ||
@@ -918,0 +932,0 @@ //#endregion |
@@ -286,4 +286,6 @@ import { all, ambiguous, empty, namespace, PromiseCapability, } from './utils/spec.js'; | ||
this.#ContextObject.import = async (specifier, options) => { | ||
const [module] = await Module.#HostResolveModules(this, [specifier]); | ||
assert(module); | ||
await Module.#HostResolveModules(this, [specifier]); | ||
const cap = this.#ResolvedModules.get(specifier); | ||
assert(cap?.Status.Type === 'Fulfilled'); | ||
const module = cap.Status.Value; | ||
return Module.#DynamicImportModule(module); | ||
@@ -655,3 +657,5 @@ }; | ||
// if (!(#HasTLA in module)) throw new TypeError('ImportHook must return a Module instance') | ||
await this.#HostResolveModules(module, module.#RequestedModules); | ||
// Note: do not await here, otherwise it will deadlock under self-import. | ||
// But can we make sure the top promise resolved when and only when all of it's transitive dependency resolved? | ||
this.#HostResolveModules(module, module.#RequestedModules); | ||
return module; | ||
@@ -665,19 +669,33 @@ }, (error) => { | ||
// call importHook recursively to get all module referenced. | ||
static async #HostResolveModules(module, requestModules) { | ||
const promises = requestModules.map(async (spec) => { | ||
const cache = module.#ResolvedModules.get(spec); | ||
if (!cache) { | ||
return this.#HostResolveModulesInner(module, spec); | ||
static #HostResolveModules(module, requestModules) { | ||
if (requestModules.length === 0) | ||
return Promise.resolve(); | ||
const overallCapability = PromiseCapability(); | ||
function check() { | ||
if (overallCapability.Status.Type !== 'Pending') | ||
return; | ||
for (const m of module.#ResolvedModules.values()) { | ||
if (m.Status.Type === 'Rejected') | ||
return overallCapability.Reject(m.Status.Reason); | ||
if (m.Status.Type === 'Pending') | ||
return void overallCapability.Promise.then(check, overallCapability.Reject); | ||
} | ||
else if (cache.Status.Type === 'Pending') { | ||
return cache.Status.Promise; | ||
overallCapability.Resolve(); | ||
} | ||
for (const spec of requestModules) { | ||
const capability = module.#ResolvedModules.get(spec); | ||
if (!capability) { | ||
this.#HostResolveModulesInner(module, spec).then(check, overallCapability.Reject); | ||
} | ||
else if (cache.Status.Type === 'Fulfilled') { | ||
return cache.Status.Value; | ||
else if (capability.Status.Type === 'Fulfilled') { | ||
check(); | ||
} | ||
else if (capability.Status.Type === 'Pending') { | ||
capability.Promise.then(check, overallCapability.Reject); | ||
} | ||
else { | ||
throw cache.Status.Reason; | ||
overallCapability.Reject(capability.Status.Reason); | ||
} | ||
}); | ||
return Promise.all(promises); | ||
} | ||
return overallCapability.Promise; | ||
} | ||
@@ -684,0 +702,0 @@ //#endregion |
{ | ||
"name": "@masknet/compartment", | ||
"version": "0.3.5", | ||
"version": "0.3.6", | ||
"type": "module", | ||
@@ -5,0 +5,0 @@ "main": "./dist/index.js", |
@@ -318,4 +318,6 @@ import type { ModuleSource } from './ModuleSource.js' | ||
this.#ContextObject!.import = async (specifier: string, options?: ImportCallOptions) => { | ||
const [module] = await Module.#HostResolveModules(this, [specifier]) | ||
assert(module) | ||
await Module.#HostResolveModules(this, [specifier]) | ||
const cap = this.#ResolvedModules.get(specifier) | ||
assert(cap?.Status.Type === 'Fulfilled') | ||
const module = cap.Status.Value | ||
return Module.#DynamicImportModule(module) | ||
@@ -705,3 +707,5 @@ } | ||
// if (!(#HasTLA in module)) throw new TypeError('ImportHook must return a Module instance') | ||
await this.#HostResolveModules(module, module.#RequestedModules) | ||
// Note: do not await here, otherwise it will deadlock under self-import. | ||
// But can we make sure the top promise resolved when and only when all of it's transitive dependency resolved? | ||
this.#HostResolveModules(module, module.#RequestedModules) | ||
return module | ||
@@ -717,16 +721,28 @@ }, | ||
// call importHook recursively to get all module referenced. | ||
static async #HostResolveModules(module: Module, requestModules: string[]) { | ||
const promises = requestModules.map(async (spec) => { | ||
const cache = module.#ResolvedModules.get(spec) | ||
if (!cache) { | ||
return this.#HostResolveModulesInner(module, spec) | ||
} else if (cache.Status.Type === 'Pending') { | ||
return cache.Status.Promise | ||
} else if (cache.Status.Type === 'Fulfilled') { | ||
return cache.Status.Value | ||
static #HostResolveModules(module: Module, requestModules: string[]) { | ||
if (requestModules.length === 0) return Promise.resolve() | ||
const overallCapability = PromiseCapability<void>() | ||
function check(): void { | ||
if (overallCapability.Status.Type !== 'Pending') return | ||
for (const m of module.#ResolvedModules.values()) { | ||
if (m.Status.Type === 'Rejected') return overallCapability.Reject(m.Status.Reason) | ||
if (m.Status.Type === 'Pending') | ||
return void overallCapability.Promise.then(check, overallCapability.Reject) | ||
} | ||
overallCapability.Resolve() | ||
} | ||
for (const spec of requestModules) { | ||
const capability = module.#ResolvedModules.get(spec) | ||
if (!capability) { | ||
this.#HostResolveModulesInner(module, spec).then(check, overallCapability.Reject) | ||
} else if (capability.Status.Type === 'Fulfilled') { | ||
check() | ||
} else if (capability.Status.Type === 'Pending') { | ||
capability.Promise.then(check, overallCapability.Reject) | ||
} else { | ||
throw cache.Status.Reason | ||
overallCapability.Reject(capability.Status.Reason) | ||
} | ||
}) | ||
return Promise.all(promises) | ||
} | ||
return overallCapability.Promise | ||
} | ||
@@ -733,0 +749,0 @@ //#endregion |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
195915
3725