diff --git a/features.txt b/features.txt index dc88a06b8d..ebc838fb83 100644 --- a/features.txt +++ b/features.txt @@ -84,6 +84,10 @@ Atomics.pause # https://github.com/tc39/proposal-is-error Error.isError +# Deferred import evaluation +# https://tc39.es/proposal-defer-import-eval +import-defer + ## Standard language features # # Language features that have been included in a published version of the diff --git a/test/language/import/import-defer/deferred-namespace-object/dep-defer-ns_FIXTURE.js b/test/language/import/import-defer/deferred-namespace-object/dep-defer-ns_FIXTURE.js new file mode 100644 index 0000000000..fff88eceb5 --- /dev/null +++ b/test/language/import/import-defer/deferred-namespace-object/dep-defer-ns_FIXTURE.js @@ -0,0 +1,6 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import defer * as depDeferredNamespace from "./dep_FIXTURE.js"; + +export { depDeferredNamespace }; diff --git a/test/language/import/import-defer/deferred-namespace-object/dep_FIXTURE.js b/test/language/import/import-defer/deferred-namespace-object/dep_FIXTURE.js new file mode 100644 index 0000000000..417ffa70bc --- /dev/null +++ b/test/language/import/import-defer/deferred-namespace-object/dep_FIXTURE.js @@ -0,0 +1,5 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +export const foo = 1; +export const bar = 2; diff --git a/test/language/import/import-defer/deferred-namespace-object/exotic-object-behavior.js b/test/language/import/import-defer/deferred-namespace-object/exotic-object-behavior.js new file mode 100644 index 0000000000..2b2b041ae9 --- /dev/null +++ b/test/language/import/import-defer/deferred-namespace-object/exotic-object-behavior.js @@ -0,0 +1,52 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-modulenamespacecreate +description: > + Deferred namespace objects have the correct MOP implementation +info: | + ModuleNamespaceCreate ( _module_, _exports_, _phase_ ) + 1. Let _internalSlotsList_ be the internal slots listed in . + 1. Let _M_ be MakeBasicObject(_internalSlotsList_). + 1. Set _M_'s essential internal methods to the definitions specified in . + 1. ... + + [[GetPrototypeOf]] ( ) + 1. Return null. + + [[IsExtensible]] ( ) + 1. Return false. + +flags: [module] +features: [import-defer] +includes: [propertyHelper.js, compareArray.js] +---*/ + +import defer * as ns from "./dep_FIXTURE.js"; + +assert.sameValue(typeof ns, "object", "Deferred namespaces are objects"); + +assert(!Reflect.isExtensible(ns), "Deferred namespaces are not extensible"); +assert.sameValue(Reflect.preventExtensions(ns), true, "Deferred namespaces can made non-extensible"); + +assert.sameValue(Reflect.getPrototypeOf(ns), null, "Deferred namespaces have a null prototype"); +assert.sameValue(Reflect.setPrototypeOf(ns, {}), false, "Deferred namespaces' prototype cannot be changed"); +assert.sameValue(Reflect.setPrototypeOf(ns, null), true, "Deferred namespaces' prototype can be 'set' to null"); + +assert.throws(TypeError, () => Reflect.apply(ns, null, []), "Deferred namespaces are not callable"); +assert.throws(TypeError, () => Reflect.construct(ns, [], ns), "Deferred namespaces are not constructable"); + +assert.compareArray( + Reflect.ownKeys(ns), + ["bar", "foo", Symbol.toStringTag], + "Deferred namespaces' keys are the exports sorted alphabetically, followed by @@toStringTag" +); + +verifyProperty(ns, "foo", { + value: 1, + writable: true, + enumerable: true, + configurable: false, +}); +assert.sameValue(Reflect.getOwnPropertyDescriptor(ns, "non-existent"), undefined, "No descriptors for non-exports"); diff --git a/test/language/import/import-defer/deferred-namespace-object/identity.js b/test/language/import/import-defer/deferred-namespace-object/identity.js new file mode 100644 index 0000000000..0df6955233 --- /dev/null +++ b/test/language/import/import-defer/deferred-namespace-object/identity.js @@ -0,0 +1,43 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-getmodulenamespace +description: > + Deferred namespace objects are created and cached appropriately +info: | + GetModuleNamespace ( _module_, _phase_ ) + 1. ... + 1. If _phase_ is ~defer~, let _namespace_ be _module_.[[DeferredNamespace]], otherwise let _namespace_ be _module_.[[Namespace]]. + 1. If _namespace_ is ~empty~, then + 1. ... + 1. Set _namespace_ to ModuleNamespaceCreate(_module_, _unambiguousNames_, _phase_). + 1. Return _namespace_. + + ModuleNamespaceCreate ( _module_, _exports_, _phase_ ) + 1. ... + 1. Let _M_ be MakeBasicObject(_internalSlotsList_). + 1. ... + 1. If _phase_ is ~defer~, then + 1. Set _module_.[[DeferredNamespace]] to _M_. + 1. ... + 1. Else, + 1. Set _module_.[[Namespace]] to _M_. + 1. ... + 1. Return _M_. + +flags: [module] +features: [import-defer] +---*/ + +import * as nsEager from "./dep_FIXTURE.js"; + +import defer * as nsDeferred1 from "./dep_FIXTURE.js"; +import defer * as nsDeferred2 from "./dep_FIXTURE.js"; +import { depDeferredNamespace as nsDeferred3 } from "./dep-defer-ns_FIXTURE.js"; +const nsDeferred4 = await import.defer("./dep_FIXTURE.js"); + +assert.sameValue(nsDeferred1, nsDeferred2, "Deferred import of the same module twice gives the same object"); +assert.sameValue(nsDeferred1, nsDeferred3, "Deferred import of the same module twice from different files gives the same object"); +assert.sameValue(nsDeferred1, nsDeferred4, "Static and dynamic deferred import of the same module gives the same object"); +assert.notSameValue(nsDeferred1, nsEager, "Deferred namespaces are distinct from eager namespaces"); diff --git a/test/language/import/import-defer/errors/get-other-while-dep-evaluating-async/dep-1-tla_FIXTURE.js b/test/language/import/import-defer/errors/get-other-while-dep-evaluating-async/dep-1-tla_FIXTURE.js new file mode 100644 index 0000000000..535f935349 --- /dev/null +++ b/test/language/import/import-defer/errors/get-other-while-dep-evaluating-async/dep-1-tla_FIXTURE.js @@ -0,0 +1,13 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import { resolveFirst, resolveThird, second } from "./promises_FIXTURE.js"; +import "./dep-1.1_FIXTURE.js" + +await Promise.resolve(); + +resolveFirst(); + +await second; + +resolveThird(); diff --git a/test/language/import/import-defer/errors/get-other-while-dep-evaluating-async/dep-1.1.1_FIXTURE.js b/test/language/import/import-defer/errors/get-other-while-dep-evaluating-async/dep-1.1.1_FIXTURE.js new file mode 100644 index 0000000000..7b6523f051 --- /dev/null +++ b/test/language/import/import-defer/errors/get-other-while-dep-evaluating-async/dep-1.1.1_FIXTURE.js @@ -0,0 +1,6 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import defer * as ns from "./dep-1-tla_FIXTURE.js"; + +export let foo = 1; diff --git a/test/language/import/import-defer/errors/get-other-while-dep-evaluating-async/dep-1.1_FIXTURE.js b/test/language/import/import-defer/errors/get-other-while-dep-evaluating-async/dep-1.1_FIXTURE.js new file mode 100644 index 0000000000..dada1f27fc --- /dev/null +++ b/test/language/import/import-defer/errors/get-other-while-dep-evaluating-async/dep-1.1_FIXTURE.js @@ -0,0 +1,28 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import { first, third, rejectDone, resolveDone, resolveSecond } from "./promises_FIXTURE.js"; +import defer * as ns from "./dep-1.1.1_FIXTURE.js"; + +// dep-1 is now in the ~evaluating~ state +try { + ns.foo; +} catch (error) { + globalThis["error on ns.foo while evaluating"] = error; +} + +first.then(() => { + // dep-1 is now in the ~evaluating-async~ state + try { + ns.foo; + } catch (error) { + globalThis["error on ns.foo while evaluating-async"] = error; + } + resolveSecond(); +}).then(() => { + return third.then(() => { + // dep-1 is now in the ~evaluated~ state + let foo = ns.foo; + globalThis["value of ns.foo when evaluated"] = foo; + }) +}).then(resolveDone, rejectDone); diff --git a/test/language/import/import-defer/errors/get-other-while-dep-evaluating-async/main.js b/test/language/import/import-defer/errors/get-other-while-dep-evaluating-async/main.js new file mode 100644 index 0000000000..67f72ff87e --- /dev/null +++ b/test/language/import/import-defer/errors/get-other-while-dep-evaluating-async/main.js @@ -0,0 +1,47 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-namespace-exotic-objects-get-p-receiver-EnsureDeferredNamespaceEvaluation +description: > + Modules cannot try to trigger evaluation of modules that have dependencies in their ~evaluating-async~ phase +info: | + 10.4.6.8 [[Get]] ( _P_, _Receiver_ ) + 1. ... + 1. If _O_.[[Deferred]] is **true**, perform ? EnsureDeferredNamespaceEvaluation(_O_). + 1. ... + + EnsureDeferredNamespaceEvaluation ( _O_ ) + 1. Assert: _O_.[[Deferred]] is *false*. + 1. Let _m_ be _O_.[[Module]]. + 1. If _m_ is a Cyclic Module Record, _m_.[[Status]] is not ~evaluated~, and ReadyForSyncExecution(_m_) is *false*, throw a *TypeError* exception. + 1. ... + + ReadyForSyncExecution( _module_, _seen_ ) + 1. If _seen_ is not provided, let _seen_ be a new empty List. + 1. If _seen_ contains _module_, return *true*. + 1. Append _module_ to _seen_. + 1. If _module_.[[Status]] is ~evaluated~, return *true*. + 1. If _module_.[[Status]] is ~evaluating~ or ~evaluating-async~, return *false*. + 1. Assert: _module_.[[Status]] is ~linked~. + 1. If _module_.[[HasTLA]] is *true*, return *false*. + 1. For each ModuleRequest Record _required_ of _module_.[[RequestedModules]], do + 1. Let _requiredModule_ be GetImportedModule(_module_, _required_.[[Specifier]]). + 1. If ReadyForSyncExecution(_requiredModule_, _seen_) is *false*, then + 1. Return *false*. + 1. Return *true*. + +flags: [module, async] +features: [import-defer, top-level-await] +includes: [asyncHelpers.js] +---*/ + +import { done } from "./promises_FIXTURE.js"; +import "./dep-1-tla_FIXTURE.js"; + +asyncTest(async () => { + await done; + assert(globalThis["error on ns.foo while evaluating"] instanceof TypeError, "ns.foo while evaluating throws a TypeError"); + assert(globalThis["error on ns.foo while evaluating-async"] instanceof TypeError, "ns.foo while evaluating-async throws a TypeError"); + assert.sameValue(globalThis["value of ns.foo when evaluated"], 1); +}); diff --git a/test/language/import/import-defer/errors/get-other-while-dep-evaluating-async/promises_FIXTURE.js b/test/language/import/import-defer/errors/get-other-while-dep-evaluating-async/promises_FIXTURE.js new file mode 100644 index 0000000000..d58fd54b1e --- /dev/null +++ b/test/language/import/import-defer/errors/get-other-while-dep-evaluating-async/promises_FIXTURE.js @@ -0,0 +1,14 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +export let resolveDone, rejectDone; +export const done = new Promise((r, j) => (resolveDone = r, rejectDone = j)); + +export let resolveFirst, rejectFirst; +export const first = new Promise((r, j) => (resolveFirst = r, rejectFirst = j)); + +export let resolveSecond, rejectSecond; +export const second = new Promise((r, j) => (resolveSecond = r, rejectSecond = j)); + +export let resolveThird, rejectThird; +export const third = new Promise((r, j) => (resolveThird = r, rejectThird = j)); diff --git a/test/language/import/import-defer/errors/get-other-while-dep-evaluating/dep-1_FIXTURE.js b/test/language/import/import-defer/errors/get-other-while-dep-evaluating/dep-1_FIXTURE.js new file mode 100644 index 0000000000..4e39108d29 --- /dev/null +++ b/test/language/import/import-defer/errors/get-other-while-dep-evaluating/dep-1_FIXTURE.js @@ -0,0 +1,14 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import defer * as dep2 from "./dep-2_FIXTURE.js"; + +globalThis.dep3evaluated = false; + +try { + dep2.foo; +} catch (error) { + globalThis["evaluating dep2.foo error"] = error; +} + +globalThis["evaluating dep2.foo evaluates dep3"] = globalThis.dep3evaluated; diff --git a/test/language/import/import-defer/errors/get-other-while-dep-evaluating/dep-2_FIXTURE.js b/test/language/import/import-defer/errors/get-other-while-dep-evaluating/dep-2_FIXTURE.js new file mode 100644 index 0000000000..dde1545135 --- /dev/null +++ b/test/language/import/import-defer/errors/get-other-while-dep-evaluating/dep-2_FIXTURE.js @@ -0,0 +1,5 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import "./dep-3_FIXTURE.js"; +import "./main.js"; diff --git a/test/language/import/import-defer/errors/get-other-while-dep-evaluating/dep-3_FIXTURE.js b/test/language/import/import-defer/errors/get-other-while-dep-evaluating/dep-3_FIXTURE.js new file mode 100644 index 0000000000..b8c2449eab --- /dev/null +++ b/test/language/import/import-defer/errors/get-other-while-dep-evaluating/dep-3_FIXTURE.js @@ -0,0 +1,4 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.dep3evaluated = true; diff --git a/test/language/import/import-defer/errors/get-other-while-dep-evaluating/main.js b/test/language/import/import-defer/errors/get-other-while-dep-evaluating/main.js new file mode 100644 index 0000000000..4446fd5cef --- /dev/null +++ b/test/language/import/import-defer/errors/get-other-while-dep-evaluating/main.js @@ -0,0 +1,42 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-namespace-exotic-objects-get-p-receiver-EnsureDeferredNamespaceEvaluation +description: > + Modules cannot try to trigger their own evaluation +info: | + 10.4.6.8 [[Get]] ( _P_, _Receiver_ ) + 1. ... + 1. If _O_.[[Deferred]] is **true**, perform ? EnsureDeferredNamespaceEvaluation(_O_). + 1. ... + + EnsureDeferredNamespaceEvaluation ( _O_ ) + 1. Assert: _O_.[[Deferred]] is *false*. + 1. Let _m_ be _O_.[[Module]]. + 1. If _m_ is a Cyclic Module Record, _m_.[[Status]] is not ~evaluated~, and ReadyForSyncExecution(_m_) is *false*, throw a *TypeError* exception. + 1. ... + + ReadyForSyncExecution( _module_, _seen_ ) + 1. If _seen_ is not provided, let _seen_ be a new empty List. + 1. If _seen_ contains _module_, return *true*. + 1. Append _module_ to _seen_. + 1. If _module_.[[Status]] is ~evaluated~, return *true*. + 1. If _module_.[[Status]] is ~evaluating~ or ~evaluating-async~, return *false*. + 1. Assert: _module_.[[Status]] is ~linked~. + 1. If _module_.[[HasTLA]] is *true*, return *false*. + 1. For each ModuleRequest Record _required_ of _module_.[[RequestedModules]], do + 1. Let _requiredModule_ be GetImportedModule(_module_, _required_.[[Specifier]]). + 1. If ReadyForSyncExecution(_requiredModule_, _seen_) is *false*, then + 1. Return *false*. + 1. Return *true*. + +flags: [module] +features: [import-defer] +---*/ + +import "./dep-1_FIXTURE.js"; + +assert(globalThis["evaluating dep2.foo error"] instanceof TypeError, "evaluating dep2.foo throws a TypeError"); +assert(!globalThis["evaluating dep2.foo evaluates dep3"], "evaluating dep2.foo does not evaluate dep3"); +assert(!globalThis.dep3evaluated, "dep3 is not evaluated at all"); diff --git a/test/language/import/import-defer/errors/get-other-while-evaluating-async/dep-1-tla_FIXTURE.js b/test/language/import/import-defer/errors/get-other-while-evaluating-async/dep-1-tla_FIXTURE.js new file mode 100644 index 0000000000..6e399aa3cc --- /dev/null +++ b/test/language/import/import-defer/errors/get-other-while-evaluating-async/dep-1-tla_FIXTURE.js @@ -0,0 +1,15 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import { resolveFirst, resolveThird, second } from "./promises_FIXTURE.js"; +import "./dep-1.1_FIXTURE.js" + +await Promise.resolve(); + +resolveFirst(); + +await second; + +resolveThird(); + +export let foo = 1; diff --git a/test/language/import/import-defer/errors/get-other-while-evaluating-async/dep-1.1_FIXTURE.js b/test/language/import/import-defer/errors/get-other-while-evaluating-async/dep-1.1_FIXTURE.js new file mode 100644 index 0000000000..ac91601172 --- /dev/null +++ b/test/language/import/import-defer/errors/get-other-while-evaluating-async/dep-1.1_FIXTURE.js @@ -0,0 +1,28 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import { first, third, resolveSecond, rejectDone, resolveDone } from "./promises_FIXTURE.js"; +import defer * as ns from "./dep-1-tla_FIXTURE.js"; + +// ns is now in the ~evaluating~ state +try { + ns.foo; +} catch (error) { + globalThis["error on ns.foo while evaluating"] = error; +} + +first.then(() => { + // ns is now in the ~evaluating-async~ state + try { + ns.foo; + } catch (error) { + globalThis["error on ns.foo while evaluating-async"] = error; + } + resolveSecond(); +}).then(() => { + return third.then(() => { + // ns is now in the ~evaluated~ state + let foo = ns.foo; + globalThis["value of ns.foo when evaluated"] = foo; + }) +}).then(resolveDone, rejectDone); diff --git a/test/language/import/import-defer/errors/get-other-while-evaluating-async/main.js b/test/language/import/import-defer/errors/get-other-while-evaluating-async/main.js new file mode 100644 index 0000000000..ca66754aef --- /dev/null +++ b/test/language/import/import-defer/errors/get-other-while-evaluating-async/main.js @@ -0,0 +1,47 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-namespace-exotic-objects-get-p-receiver-EnsureDeferredNamespaceEvaluation +description: > + Modules cannot try to trigger evaluation of modules that are in their ~evaluating-async~ phase +info: | + 10.4.6.8 [[Get]] ( _P_, _Receiver_ ) + 1. ... + 1. If _O_.[[Deferred]] is **true**, perform ? EnsureDeferredNamespaceEvaluation(_O_). + 1. ... + + EnsureDeferredNamespaceEvaluation ( _O_ ) + 1. Assert: _O_.[[Deferred]] is *false*. + 1. Let _m_ be _O_.[[Module]]. + 1. If _m_ is a Cyclic Module Record, _m_.[[Status]] is not ~evaluated~, and ReadyForSyncExecution(_m_) is *false*, throw a *TypeError* exception. + 1. ... + + ReadyForSyncExecution( _module_, _seen_ ) + 1. If _seen_ is not provided, let _seen_ be a new empty List. + 1. If _seen_ contains _module_, return *true*. + 1. Append _module_ to _seen_. + 1. If _module_.[[Status]] is ~evaluated~, return *true*. + 1. If _module_.[[Status]] is ~evaluating~ or ~evaluating-async~, return *false*. + 1. Assert: _module_.[[Status]] is ~linked~. + 1. If _module_.[[HasTLA]] is *true*, return *false*. + 1. For each ModuleRequest Record _required_ of _module_.[[RequestedModules]], do + 1. Let _requiredModule_ be GetImportedModule(_module_, _required_.[[Specifier]]). + 1. If ReadyForSyncExecution(_requiredModule_, _seen_) is *false*, then + 1. Return *false*. + 1. Return *true*. + +flags: [module, async] +features: [import-defer, top-level-await] +includes: [asyncHelpers.js] +---*/ + +import { done } from "./promises_FIXTURE.js"; +import "./dep-1-tla_FIXTURE.js"; + +asyncTest(async () => { + await done; + assert(globalThis["error on ns.foo while evaluating"] instanceof TypeError, "ns.foo while evaluating throws a TypeError"); + assert(globalThis["error on ns.foo while evaluating-async"] instanceof TypeError, "ns.foo while evaluating-async throws a TypeError"); + assert.sameValue(globalThis["value of ns.foo when evaluated"], 1); +}); diff --git a/test/language/import/import-defer/errors/get-other-while-evaluating-async/promises_FIXTURE.js b/test/language/import/import-defer/errors/get-other-while-evaluating-async/promises_FIXTURE.js new file mode 100644 index 0000000000..d58fd54b1e --- /dev/null +++ b/test/language/import/import-defer/errors/get-other-while-evaluating-async/promises_FIXTURE.js @@ -0,0 +1,14 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +export let resolveDone, rejectDone; +export const done = new Promise((r, j) => (resolveDone = r, rejectDone = j)); + +export let resolveFirst, rejectFirst; +export const first = new Promise((r, j) => (resolveFirst = r, rejectFirst = j)); + +export let resolveSecond, rejectSecond; +export const second = new Promise((r, j) => (resolveSecond = r, rejectSecond = j)); + +export let resolveThird, rejectThird; +export const third = new Promise((r, j) => (resolveThird = r, rejectThird = j)); diff --git a/test/language/import/import-defer/errors/get-other-while-evaluating/dep_FIXTURE.js b/test/language/import/import-defer/errors/get-other-while-evaluating/dep_FIXTURE.js new file mode 100644 index 0000000000..dd9fcdb9e4 --- /dev/null +++ b/test/language/import/import-defer/errors/get-other-while-evaluating/dep_FIXTURE.js @@ -0,0 +1,10 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import defer * as main from "./main.js"; + +try { + main.foo; +} catch (error) { + globalThis["error on main.foo"] = error; +} diff --git a/test/language/import/import-defer/errors/get-other-while-evaluating/main.js b/test/language/import/import-defer/errors/get-other-while-evaluating/main.js new file mode 100644 index 0000000000..6373afde00 --- /dev/null +++ b/test/language/import/import-defer/errors/get-other-while-evaluating/main.js @@ -0,0 +1,40 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-namespace-exotic-objects-get-p-receiver-EnsureDeferredNamespaceEvaluation +description: > + Deferred namespaces' properties cannot be accessed on a module that is being evaluated +info: | + 10.4.6.8 [[Get]] ( _P_, _Receiver_ ) + 1. ... + 1. If _O_.[[Deferred]] is **true**, perform ? EnsureDeferredNamespaceEvaluation(_O_). + 1. ... + + EnsureDeferredNamespaceEvaluation ( _O_ ) + 1. Assert: _O_.[[Deferred]] is *false*. + 1. Let _m_ be _O_.[[Module]]. + 1. If _m_ is a Cyclic Module Record, _m_.[[Status]] is not ~evaluated~, and ReadyForSyncExecution(_m_) is *false*, throw a *TypeError* exception. + 1. ... + + ReadyForSyncExecution( _module_, _seen_ ) + 1. If _seen_ is not provided, let _seen_ be a new empty List. + 1. If _seen_ contains _module_, return *true*. + 1. Append _module_ to _seen_. + 1. If _module_.[[Status]] is ~evaluated~, return *true*. + 1. If _module_.[[Status]] is ~evaluating~ or ~evaluating-async~, return *false*. + 1. Assert: _module_.[[Status]] is ~linked~. + 1. If _module_.[[HasTLA]] is *true*, return *false*. + 1. For each ModuleRequest Record _required_ of _module_.[[RequestedModules]], do + 1. Let _requiredModule_ be GetImportedModule(_module_, _required_.[[Specifier]]). + 1. If ReadyForSyncExecution(_requiredModule_, _seen_) is *false*, then + 1. Return *false*. + 1. Return *true*. + +flags: [module] +features: [import-defer] +---*/ + +import "./dep_FIXTURE.js"; + +assert(globalThis["error on main.foo"] instanceof TypeError, "main.foo while evaluating throws a TypeError"); diff --git a/test/language/import/import-defer/errors/get-self-while-defer-evaluating/dep_FIXTURE.js b/test/language/import/import-defer/errors/get-self-while-defer-evaluating/dep_FIXTURE.js new file mode 100644 index 0000000000..3052c5c725 --- /dev/null +++ b/test/language/import/import-defer/errors/get-self-while-defer-evaluating/dep_FIXTURE.js @@ -0,0 +1,10 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import defer * as ns from "./dep_FIXTURE.js"; + +try { + ns.foo; +} catch (error) { + globalThis["error on ns.foo"] = error; +} diff --git a/test/language/import/import-defer/errors/get-self-while-defer-evaluating/main.js b/test/language/import/import-defer/errors/get-self-while-defer-evaluating/main.js new file mode 100644 index 0000000000..cfcf4328ce --- /dev/null +++ b/test/language/import/import-defer/errors/get-self-while-defer-evaluating/main.js @@ -0,0 +1,42 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-namespace-exotic-objects-get-p-receiver-EnsureDeferredNamespaceEvaluation +description: > + Modules cannot try to trigger their own evaluation +info: | + 10.4.6.8 [[Get]] ( _P_, _Receiver_ ) + 1. ... + 1. If _O_.[[Deferred]] is **true**, perform ? EnsureDeferredNamespaceEvaluation(_O_). + 1. ... + + EnsureDeferredNamespaceEvaluation ( _O_ ) + 1. Assert: _O_.[[Deferred]] is *false*. + 1. Let _m_ be _O_.[[Module]]. + 1. If _m_ is a Cyclic Module Record, _m_.[[Status]] is not ~evaluated~, and ReadyForSyncExecution(_m_) is *false*, throw a *TypeError* exception. + 1. ... + + ReadyForSyncExecution( _module_, _seen_ ) + 1. If _seen_ is not provided, let _seen_ be a new empty List. + 1. If _seen_ contains _module_, return *true*. + 1. Append _module_ to _seen_. + 1. If _module_.[[Status]] is ~evaluated~, return *true*. + 1. If _module_.[[Status]] is ~evaluating~ or ~evaluating-async~, return *false*. + 1. Assert: _module_.[[Status]] is ~linked~. + 1. If _module_.[[HasTLA]] is *true*, return *false*. + 1. For each ModuleRequest Record _required_ of _module_.[[RequestedModules]], do + 1. Let _requiredModule_ be GetImportedModule(_module_, _required_.[[Specifier]]). + 1. If ReadyForSyncExecution(_requiredModule_, _seen_) is *false*, then + 1. Return *false*. + 1. Return *true*. + +flags: [module] +features: [import-defer] +---*/ + +import defer * as ns from "./dep_FIXTURE.js"; + +assert(globalThis["error on ns.foo"] instanceof TypeError, "ns.foo while evaluating throws a TypeError"); + +ns.foo; diff --git a/test/language/import/import-defer/errors/get-self-while-evaluating-async/dep_FIXTURE.js b/test/language/import/import-defer/errors/get-self-while-evaluating-async/dep_FIXTURE.js new file mode 100644 index 0000000000..a990c9bbbd --- /dev/null +++ b/test/language/import/import-defer/errors/get-self-while-evaluating-async/dep_FIXTURE.js @@ -0,0 +1,12 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import defer * as ns from "./dep_FIXTURE.js"; + +await Promise.resolve(0); + +try { + ns.foo; +} catch (error) { + globalThis["error on ns.foo"] = error; +} diff --git a/test/language/import/import-defer/errors/get-self-while-evaluating-async/main.js b/test/language/import/import-defer/errors/get-self-while-evaluating-async/main.js new file mode 100644 index 0000000000..069d07699e --- /dev/null +++ b/test/language/import/import-defer/errors/get-self-while-evaluating-async/main.js @@ -0,0 +1,49 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-namespace-exotic-objects-get-p-receiver-EnsureDeferredNamespaceEvaluation +description: > + Modules cannot try to trigger their own evaluation +info: | + 10.4.6.8 [[Get]] ( _P_, _Receiver_ ) + 1. ... + 1. If _O_.[[Deferred]] is **true**, perform ? EnsureDeferredNamespaceEvaluation(_O_). + 1. ... + + EnsureDeferredNamespaceEvaluation ( _O_ ) + 1. Assert: _O_.[[Deferred]] is *false*. + 1. Let _m_ be _O_.[[Module]]. + 1. If _m_ is a Cyclic Module Record, _m_.[[Status]] is not ~evaluated~, and ReadyForSyncExecution(_m_) is *false*, throw a *TypeError* exception. + 1. ... + + ReadyForSyncExecution( _module_, _seen_ ) + 1. If _seen_ is not provided, let _seen_ be a new empty List. + 1. If _seen_ contains _module_, return *true*. + 1. Append _module_ to _seen_. + 1. If _module_.[[Status]] is ~evaluated~, return *true*. + 1. If _module_.[[Status]] is ~evaluating~ or ~evaluating-async~, return *false*. + 1. ... + +flags: [module, async] +features: [import-defer, top-level-await] +---*/ + +/* +`./dep_FIXTURE.js` is _not_ deferred, because it contains top-level await. So what is happening in this test is that: +- the deferred module is not actually deferred, so `dep_FIXTURE.js` starts executing and goes in its `evaluating` state +- it has access to a deferred namespace of itself +- once it reaches the `await`, the state changes to `evaluating-async` +- the test tries then to access a property from the deferred namespace while it's `evaluating-async` (which is what this test it testing). It should throw. +- `dep_FIXTURE.js` is done, and becomes `evaluated` +- `main.js` starts evaluating, and the error is already there +- `ns.foo` now works, because `ns` is `evaluated` and not `evaluating-async` +*/ + +import defer * as ns from "./dep_FIXTURE.js"; + +assert(globalThis["error on ns.foo"] instanceof TypeError, "ns.foo while evaluating throws a TypeError"); + +ns.foo; + +$DONE(); diff --git a/test/language/import/import-defer/errors/get-self-while-evaluating.js b/test/language/import/import-defer/errors/get-self-while-evaluating.js new file mode 100644 index 0000000000..6fbd0c27b3 --- /dev/null +++ b/test/language/import/import-defer/errors/get-self-while-evaluating.js @@ -0,0 +1,40 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-namespace-exotic-objects-get-p-receiver-EnsureDeferredNamespaceEvaluation +description: > + Modules cannot try to trigger their own evaluation +info: | + 10.4.6.8 [[Get]] ( _P_, _Receiver_ ) + 1. ... + 1. If _O_.[[Deferred]] is **true**, perform ? EnsureDeferredNamespaceEvaluation(_O_). + 1. ... + + EnsureDeferredNamespaceEvaluation ( _O_ ) + 1. Assert: _O_.[[Deferred]] is *false*. + 1. Let _m_ be _O_.[[Module]]. + 1. If _m_ is a Cyclic Module Record, _m_.[[Status]] is not ~evaluated~, and ReadyForSyncExecution(_m_) is *false*, throw a *TypeError* exception. + 1. ... + + ReadyForSyncExecution( _module_, _seen_ ) + 1. If _seen_ is not provided, let _seen_ be a new empty List. + 1. If _seen_ contains _module_, return *true*. + 1. Append _module_ to _seen_. + 1. If _module_.[[Status]] is ~evaluated~, return *true*. + 1. If _module_.[[Status]] is ~evaluating~ or ~evaluating-async~, return *false*. + 1. Assert: _module_.[[Status]] is ~linked~. + 1. If _module_.[[HasTLA]] is *true*, return *false*. + 1. For each ModuleRequest Record _required_ of _module_.[[RequestedModules]], do + 1. Let _requiredModule_ be GetImportedModule(_module_, _required_.[[Specifier]]). + 1. If ReadyForSyncExecution(_requiredModule_, _seen_) is *false*, then + 1. Return *false*. + 1. Return *true*. + +flags: [module] +features: [import-defer] +---*/ + +import defer * as self from "./get-self-while-evaluating.js"; + +assert.throws(TypeError, () => self.foo); diff --git a/test/language/import/import-defer/errors/module-throws/defer-import-after-evaluation.js b/test/language/import/import-defer/errors/module-throws/defer-import-after-evaluation.js new file mode 100644 index 0000000000..cb32449e1c --- /dev/null +++ b/test/language/import/import-defer/errors/module-throws/defer-import-after-evaluation.js @@ -0,0 +1,46 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-namespace-exotic-objects-get-p-receiver-EnsureDeferredNamespaceEvaluation +description: > + Module evaluation errors are thrown +info: | + [[Get]] ( _P_, _Receiver_ ) + 1. ... + 1. If _O_.[[Deferred]] is **true**, perform ? EnsureDeferredNamespaceEvaluation(_O_). + 1. ... + + EnsureDeferredNamespaceEvaluation( _O_ ) + 1. ... + 1. Perform ? EvaluateSync(_m_). + 1. ... + + EvaluateSync ( _module_ ) + 1. ... + 1. Let _promise_ be ! _module_.Evaluate(). + 1. Assert: _promise_.[[PromiseState]] is either ~fulfilled~ or ~rejected~. + 1. If _promise_.[[PromiseState]] is ~rejected~, then + 1. Return ThrowCompletion(_promise_.[[PromiseResult]]). + 1. ... + +flags: [module, async] +features: [import-defer] +includes: [asyncHelpers.js] +---*/ + +asyncTest(async () => { + let err1; + await import("./throws_FIXTURE.js").catch((e) => { err1 = e }); + assert.sameValue(err1.someError, "the error from throws_FIXTURE"); + + const { ns } = await import("./import-defer-throws_FIXTURE.js"); + + let err2; + try { ns.foo } catch (e) { err2 = e }; + assert.sameValue( + err1, + err2, + "Evaluation errors are thrown for modules evaluated before getting the deferred namespace" + ); +}); diff --git a/test/language/import/import-defer/errors/module-throws/import-defer-throws_FIXTURE.js b/test/language/import/import-defer/errors/module-throws/import-defer-throws_FIXTURE.js new file mode 100644 index 0000000000..8049a5263c --- /dev/null +++ b/test/language/import/import-defer/errors/module-throws/import-defer-throws_FIXTURE.js @@ -0,0 +1,5 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import defer * as ns from "./import-defer-throws_FIXTURE.js"; +export { ns }; diff --git a/test/language/import/import-defer/errors/module-throws/third-party-evaluation-after-defer-import.js b/test/language/import/import-defer/errors/module-throws/third-party-evaluation-after-defer-import.js new file mode 100644 index 0000000000..ad37535b4a --- /dev/null +++ b/test/language/import/import-defer/errors/module-throws/third-party-evaluation-after-defer-import.js @@ -0,0 +1,46 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-namespace-exotic-objects-get-p-receiver-EnsureDeferredNamespaceEvaluation +description: > + Module evaluation errors are thrown +info: | + [[Get]] ( _P_, _Receiver_ ) + 1. ... + 1. If _O_.[[Deferred]] is **true**, perform ? EnsureDeferredNamespaceEvaluation(_O_). + 1. ... + + EnsureDeferredNamespaceEvaluation( _O_ ) + 1. ... + 1. Perform ? EvaluateSync(_m_). + 1. ... + + EvaluateSync ( _module_ ) + 1. ... + 1. Let _promise_ be ! _module_.Evaluate(). + 1. Assert: _promise_.[[PromiseState]] is either ~fulfilled~ or ~rejected~. + 1. If _promise_.[[PromiseState]] is ~rejected~, then + 1. Return ThrowCompletion(_promise_.[[PromiseResult]]). + 1. ... + +flags: [module, async] +features: [import-defer] +includes: [asyncHelpers.js] +---*/ + +import defer * as ns from "./throws_FIXTURE.js"; + +asyncTest(async () => { + let err1; + await import("./throws_FIXTURE.js").catch((e) => { err1 = e }); + assert.sameValue(err1.someError, "the error from throws_FIXTURE"); + + let err2; + try { ns.foo } catch (e) { err2 = e }; + assert.sameValue( + err1, + err2, + "Evaluation errors are thrown for modules evaluated after getting the deferred namespace" + ); +}); diff --git a/test/language/import/import-defer/errors/module-throws/throws_FIXTURE.js b/test/language/import/import-defer/errors/module-throws/throws_FIXTURE.js new file mode 100644 index 0000000000..85290878c9 --- /dev/null +++ b/test/language/import/import-defer/errors/module-throws/throws_FIXTURE.js @@ -0,0 +1,4 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +throw { someError: "the error from throws_FIXTURE" } diff --git a/test/language/import/import-defer/errors/module-throws/trigger-evaluation.js b/test/language/import/import-defer/errors/module-throws/trigger-evaluation.js new file mode 100644 index 0000000000..e18d4dec0f --- /dev/null +++ b/test/language/import/import-defer/errors/module-throws/trigger-evaluation.js @@ -0,0 +1,38 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-namespace-exotic-objects-get-p-receiver-EnsureDeferredNamespaceEvaluation +description: > + Module evaluation errors are thrown +info: | + [[Get]] ( _P_, _Receiver_ ) + 1. ... + 1. If _O_.[[Deferred]] is **true**, perform ? EnsureDeferredNamespaceEvaluation(_O_). + 1. ... + + EnsureDeferredNamespaceEvaluation( _O_ ) + 1. ... + 1. Perform ? EvaluateSync(_m_). + 1. ... + + EvaluateSync ( _module_ ) + 1. ... + 1. Let _promise_ be ! _module_.Evaluate(). + 1. Assert: _promise_.[[PromiseState]] is either ~fulfilled~ or ~rejected~. + 1. If _promise_.[[PromiseState]] is ~rejected~, then + 1. Return ThrowCompletion(_promise_.[[PromiseResult]]). + 1. ... + +flags: [module] +features: [import-defer] +---*/ + +import defer * as ns from "./throws_FIXTURE.js"; + +let err1, err2; +try { ns.foo } catch (e) { err1 = e }; +assert.deepEqual(err1, { someError: "the error from throws_FIXTURE" }, "Evaluation errors are thrown when evaluating"); + +try { ns.foo } catch (e) { err2 = e }; +assert.sameValue(err1, err2, "Evaluation errors are thrown for already evaluated modules"); diff --git a/test/language/import/import-defer/errors/resolution-error/import-defer-of-missing-module-fails.js b/test/language/import/import-defer/errors/resolution-error/import-defer-of-missing-module-fails.js new file mode 100644 index 0000000000..94cac22af3 --- /dev/null +++ b/test/language/import/import-defer/errors/resolution-error/import-defer-of-missing-module-fails.js @@ -0,0 +1,22 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-namespace-exotic-objects-get-p-receiver-EnsureDeferredNamespaceEvaluation +description: > + Host resolution errors are reported eagerly +info: | + LoadRequestedModules ([ _hostDefined_ ]) + - just notice that it does not check if the module is deferred + +flags: [module] +features: [import-defer] + +negative: + phase: resolution + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +import defer * as ns "./resolution-error_FIXTURE.js"; diff --git a/test/language/import/import-defer/errors/resolution-error/resolution-error_FIXTURE.js b/test/language/import/import-defer/errors/resolution-error/resolution-error_FIXTURE.js new file mode 100644 index 0000000000..1701da4f25 --- /dev/null +++ b/test/language/import/import-defer/errors/resolution-error/resolution-error_FIXTURE.js @@ -0,0 +1,4 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import "./missing.js"; diff --git a/test/language/import/import-defer/errors/syntax-error/import-defer-of-syntax-error-fails.js b/test/language/import/import-defer/errors/syntax-error/import-defer-of-syntax-error-fails.js new file mode 100644 index 0000000000..f3c2ebda9f --- /dev/null +++ b/test/language/import/import-defer/errors/syntax-error/import-defer-of-syntax-error-fails.js @@ -0,0 +1,22 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-namespace-exotic-objects-get-p-receiver-EnsureDeferredNamespaceEvaluation +description: > + Syntax errors in deferred modules are reported eagerly +info: | + LoadRequestedModules ([ _hostDefined_ ]) + - just notice that it does not check if the module is deferred + +flags: [module] +features: [import-defer] + +negative: + phase: resolution + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +import defer * as ns "./syntax-error_FIXTURE.js"; diff --git a/test/language/import/import-defer/errors/syntax-error/syntax-error_FIXTURE.js b/test/language/import/import-defer/errors/syntax-error/syntax-error_FIXTURE.js new file mode 100644 index 0000000000..b7d2217541 --- /dev/null +++ b/test/language/import/import-defer/errors/syntax-error/syntax-error_FIXTURE.js @@ -0,0 +1,4 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +invalid syntax! diff --git a/test/language/import/import-defer/evaluation-sync/dep-1.1_FIXTURE.js b/test/language/import/import-defer/evaluation-sync/dep-1.1_FIXTURE.js new file mode 100644 index 0000000000..a249c2f008 --- /dev/null +++ b/test/language/import/import-defer/evaluation-sync/dep-1.1_FIXTURE.js @@ -0,0 +1,4 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push(1.1); diff --git a/test/language/import/import-defer/evaluation-sync/dep-1.2_FIXTURE.js b/test/language/import/import-defer/evaluation-sync/dep-1.2_FIXTURE.js new file mode 100644 index 0000000000..f2a00d2679 --- /dev/null +++ b/test/language/import/import-defer/evaluation-sync/dep-1.2_FIXTURE.js @@ -0,0 +1,4 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push(1.2); diff --git a/test/language/import/import-defer/evaluation-sync/dep-1_FIXTURE.js b/test/language/import/import-defer/evaluation-sync/dep-1_FIXTURE.js new file mode 100644 index 0000000000..4121c65e75 --- /dev/null +++ b/test/language/import/import-defer/evaluation-sync/dep-1_FIXTURE.js @@ -0,0 +1,9 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import "./dep-1.1_FIXTURE.js"; +import defer * as ns_1_2 from "./dep-1.2_FIXTURE.js"; + +globalThis.evaluations.push(1); + +export { ns_1_2 }; diff --git a/test/language/import/import-defer/evaluation-sync/dep-2_FIXTURE.js b/test/language/import/import-defer/evaluation-sync/dep-2_FIXTURE.js new file mode 100644 index 0000000000..7adbcd3bd7 --- /dev/null +++ b/test/language/import/import-defer/evaluation-sync/dep-2_FIXTURE.js @@ -0,0 +1,4 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push(2); diff --git a/test/language/import/import-defer/evaluation-sync/evaluation-ignore-get-symbol.js b/test/language/import/import-defer/evaluation-sync/evaluation-ignore-get-symbol.js new file mode 100644 index 0000000000..c7588800e4 --- /dev/null +++ b/test/language/import/import-defer/evaluation-sync/evaluation-ignore-get-symbol.js @@ -0,0 +1,28 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-namespace-exotic-objects-get-p-receiver +description: > + [[Get]] of a symbol does not trigger evaluation of the module +info: | + [[Get]] ( _P_, _Receiver_ ) + 1. If _P_ is a Symbol, then + 1. Return ! OrdinaryGet(_O_, _P_, _Receiver_). + 1. If _O_.[[Deferred]] is **true**, perform ? EnsureDeferredNamespaceEvaluation(_O_). + 1. ... + +flags: [module] +features: [import-defer] +---*/ + +import "./setup_FIXTURE.js"; + +import defer * as ns1 from "./dep-1_FIXTURE.js"; + +assert.sameValue(globalThis.evaluations.length, 0, "import defer does not trigger evaluation"); + +ns1[Symbol.toStringTag]; +ns1[Symbol()]; + +assert.sameValue(globalThis.evaluations.length, 0, "[[Get]] of a symbol does not trigger evaluation"); diff --git a/test/language/import/import-defer/evaluation-sync/evaluation-ignore-getPrototypeOf.js b/test/language/import/import-defer/evaluation-sync/evaluation-ignore-getPrototypeOf.js new file mode 100644 index 0000000000..4cd7224c55 --- /dev/null +++ b/test/language/import/import-defer/evaluation-sync/evaluation-ignore-getPrototypeOf.js @@ -0,0 +1,24 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-namespace-exotic-objects-getprototypeof +description: > + [[GetPrototypeOf]] does not trigger evaluation of the module +info: | + [[GetPrototypeOf]] ( ) + 1. Return **null**. + +flags: [module] +features: [import-defer] +---*/ + +import "./setup_FIXTURE.js"; + +import defer * as ns1 from "./dep-1_FIXTURE.js"; + +assert.sameValue(globalThis.evaluations.length, 0, "import defer does not trigger evaluation"); + +Object.getPrototypeOf(ns1); + +assert.sameValue(globalThis.evaluations.length, 0, "[[GetPrototypeOf]] does not trigger evaluation"); diff --git a/test/language/import/import-defer/evaluation-sync/evaluation-ignore-isExtensible.js b/test/language/import/import-defer/evaluation-sync/evaluation-ignore-isExtensible.js new file mode 100644 index 0000000000..47f441bffa --- /dev/null +++ b/test/language/import/import-defer/evaluation-sync/evaluation-ignore-isExtensible.js @@ -0,0 +1,24 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-namespace-exotic-objects-isextensible +description: > + [[IsExtensible]] does not trigger evaluation of the module +info: | + [[IsExtensible]] ( ) + 1. Return **false**. + +flags: [module] +features: [import-defer] +---*/ + +import "./setup_FIXTURE.js"; + +import defer * as ns1 from "./dep-1_FIXTURE.js"; + +assert.sameValue(globalThis.evaluations.length, 0, "import defer does not trigger evaluation"); + +Object.isExtensible(ns1); + +assert.sameValue(globalThis.evaluations.length, 0, "[[IsExtensible]] does not trigger evaluation"); diff --git a/test/language/import/import-defer/evaluation-sync/evaluation-ignore-preventExtensions.js b/test/language/import/import-defer/evaluation-sync/evaluation-ignore-preventExtensions.js new file mode 100644 index 0000000000..e2438de032 --- /dev/null +++ b/test/language/import/import-defer/evaluation-sync/evaluation-ignore-preventExtensions.js @@ -0,0 +1,24 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-namespace-exotic-objects-preventextensions +description: > + [[PreventExtensions]] does not trigger evaluation of the module +info: | + [[PreventExtensions]] ( ) + 1. Return **true**. + +flags: [module] +features: [import-defer] +---*/ + +import "./setup_FIXTURE.js"; + +import defer * as ns1 from "./dep-1_FIXTURE.js"; + +assert.sameValue(globalThis.evaluations.length, 0, "import defer does not trigger evaluation"); + +Object.preventExtensions(ns1); + +assert.sameValue(globalThis.evaluations.length, 0, "[[PreventExtensions]] does not trigger evaluation"); diff --git a/test/language/import/import-defer/evaluation-sync/evaluation-ignore-set.js b/test/language/import/import-defer/evaluation-sync/evaluation-ignore-set.js new file mode 100644 index 0000000000..e2416db5bb --- /dev/null +++ b/test/language/import/import-defer/evaluation-sync/evaluation-ignore-set.js @@ -0,0 +1,29 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-namespace-exotic-objects-set-p-v-receiver +description: > + [[Set]] does not trigger evaluation of the module +info: | + [[Set]] ( _P_, _V_, _Receiver_ ) + 1. Return **false**. + +flags: [module] +features: [import-defer] +---*/ + +import "./setup_FIXTURE.js"; + +import defer * as ns1 from "./dep-1_FIXTURE.js"; + +assert.sameValue(globalThis.evaluations.length, 0, "import defer does not trigger evaluation"); + +try { + ns1.foo = 2; +} catch {} +try { + ns1.ns_1_2 = 3; +} catch {} + +assert.sameValue(globalThis.evaluations.length, 0, "[[Set]] of a symbol does not trigger evaluation"); diff --git a/test/language/import/import-defer/evaluation-sync/evaluation-ignore-setPrototypeOf.js b/test/language/import/import-defer/evaluation-sync/evaluation-ignore-setPrototypeOf.js new file mode 100644 index 0000000000..d2b82a7b84 --- /dev/null +++ b/test/language/import/import-defer/evaluation-sync/evaluation-ignore-setPrototypeOf.js @@ -0,0 +1,25 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-namespace-exotic-objects-setprototypeof-v +description: > + [[SetPrototypeOf]] does not trigger evaluation of the module +info: | + [[SetPrototypeOf]] ( _V_ ) + 1. Return ! SetImmutablePrototype(_O_, _V_). + +flags: [module] +features: [import-defer] +---*/ + +import "./setup_FIXTURE.js"; + +import defer * as ns1 from "./dep-1_FIXTURE.js"; + +assert.sameValue(globalThis.evaluations.length, 0, "import defer does not trigger evaluation"); + +Reflect.setPrototypeOf(ns1, null); +Reflect.setPrototypeOf(ns1, {}); + +assert.sameValue(globalThis.evaluations.length, 0, "[[SetPrototypeOf]] does not trigger evaluation"); diff --git a/test/language/import/import-defer/evaluation-sync/evaluation-trigger-get-string.js b/test/language/import/import-defer/evaluation-sync/evaluation-trigger-get-string.js new file mode 100644 index 0000000000..21e82b4182 --- /dev/null +++ b/test/language/import/import-defer/evaluation-sync/evaluation-trigger-get-string.js @@ -0,0 +1,27 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-module-namespace-exotic-objects-get-p-receiver +description: > + [[Get]] of a string triggers evaluation of the module +info: | + [[Get]] ( _P_, _Receiver_ ) + 1. If _P_ is a Symbol, then + 1. Return ! OrdinaryGet(_O_, _P_, _Receiver_). + 1. If _O_.[[Deferred]] is **true**, perform ? EnsureDeferredNamespaceEvaluation(_O_). + 1. ... + +flags: [module] +features: [import-defer] +---*/ + +import "./setup_FIXTURE.js"; + +import defer * as ns1 from "./dep-1_FIXTURE.js"; + +assert.sameValue(globalThis.evaluations.length, 0, "import defer does not trigger evaluation"); + +ns1.foo; + +assert(globalThis.evaluations.length > 0, "[[Get]] of a string triggers evaluation"); diff --git a/test/language/import/import-defer/evaluation-sync/import-defer-does-not-evaluate.js b/test/language/import/import-defer/evaluation-sync/import-defer-does-not-evaluate.js new file mode 100644 index 0000000000..3afade5801 --- /dev/null +++ b/test/language/import/import-defer/evaluation-sync/import-defer-does-not-evaluate.js @@ -0,0 +1,47 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-innermoduleevaluation +description: > + `import defer` by itself does not trigger evaluation of sync modules +info: | + 16.2.1.5.3.1 InnerModuleEvaluation ( _module_, _stack_, _index_ ) + 1. ... + 1. Let _evaluationList_ be a new empty List. + 1. For each ModuleRequest Record _required_ of _module_.[[RequestedModules]], do + 1. Let _requiredModule_ be GetImportedModule(_module_, _required_.[[Specifier]]). + 1. If _required_.[[Phase]] is ~defer~, then + i. Let _additionalModules_ be GatherAsynchronousTransitiveDependencies(_requiredModule_). + ii. For each Module Record _additionalModule_ of _additionalModules_, do + 1. If _evaluationList_ does not contain _additionalModule_, then + a. Append _additionalModule_ to _evaluationList_. + 1. Else if _evaluationList_ does not contain _requiredModule_, then + i. Append _requiredModule_ to _evaluationList_. + 1. ... + 1. For each Module Record _requiredModule_ of _evaluationList_, do + 1. Set _index_ to ? InnerModuleEvaluation(_requiredModule_, _stack_, _index_). + 1. ... + +flags: [module] +features: [import-defer] +includes: [compareArray.js] +---*/ + +import "./setup_FIXTURE.js"; + +import defer * as ns1 from "./dep-1_FIXTURE.js"; + +assert.sameValue(globalThis.evaluations.length, 0, "import defer does not trigger evaluation"); + +const ns_1_2 = ns1.ns_1_2; + +assert.compareArray(globalThis.evaluations, [1.1, 1], "when evaluation is triggered, deferred sub-dependencies are not evaluated"); + +ns1.ns_1_2; + +assert.compareArray(globalThis.evaluations, [1.1, 1], "the module is not re-executed"); + +ns_1_2.foo; + +assert.compareArray(globalThis.evaluations, [1.1, 1, 1.2]); diff --git a/test/language/import/import-defer/evaluation-sync/module-imported-defer-and-eager.js b/test/language/import/import-defer/evaluation-sync/module-imported-defer-and-eager.js new file mode 100644 index 0000000000..d488fc4f98 --- /dev/null +++ b/test/language/import/import-defer/evaluation-sync/module-imported-defer-and-eager.js @@ -0,0 +1,51 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-static-semantics-modulerequests +description: > + `import defer` by itself does not trigger evaluation of sync modules +info: | + Static Semantics: ModuleRequests + ModuleItemList : ModuleItemList ModuleItem + 1. Let _requests_ be ModuleRequests of ModuleItemList. + 1. Let _additionalRequests_ be ModuleRequests of ModuleItem. + 1. For each ModuleRequest Record _mr_ of _additionalRequests_, do + 1. Let _found_ be false. + 1. For each ModuleRequest Record _mr2_ of _requests_, do + 1. If _mr_.[[Specifier]] is _mr2_.[[Specifier]] and _mr_.[[Phase]] is _mr2_.[[Phase]], then + 1. Assert: _found_ is false. + 1. Set _found_ to true. + 1. If _found_ is false, then + 1. Append _mr_ to _requests_. + 1. Return _requests_. + + 16.2.1.5.3.1 InnerModuleEvaluation ( _module_, _stack_, _index_ ) + 1. ... + 1. Let _evaluationList_ be a new empty List. + 1. For each ModuleRequest Record _required_ of _module_.[[RequestedModules]], do + 1. Let _requiredModule_ be GetImportedModule(_module_, _required_.[[Specifier]]). + 1. If _required_.[[Phase]] is ~defer~, then + i. Let _additionalModules_ be GatherAsynchronousTransitiveDependencies(_requiredModule_). + ii. For each Module Record _additionalModule_ of _additionalModules_, do + 1. If _evaluationList_ does not contain _additionalModule_, then + a. Append _additionalModule_ to _evaluationList_. + 1. Else if _evaluationList_ does not contain _requiredModule_, then + i. Append _requiredModule_ to _evaluationList_. + 1. ... + 1. For each Module Record _requiredModule_ of _evaluationList_, do + 1. Set _index_ to ? InnerModuleEvaluation(_requiredModule_, _stack_, _index_). + 1. ... + +flags: [module] +features: [import-defer] +includes: [compareArray.js] +---*/ + +import "./setup_FIXTURE.js"; + +import defer * as ns1 from "./dep-1_FIXTURE.js"; +import "./dep-2_FIXTURE.js"; +import "./dep-1_FIXTURE.js"; + +assert.compareArray(globalThis.evaluations, [2, 1.1, 1], "the module is evaluated in the order where it's imported as non-deferred"); diff --git a/test/language/import/import-defer/evaluation-sync/setup_FIXTURE.js b/test/language/import/import-defer/evaluation-sync/setup_FIXTURE.js new file mode 100644 index 0000000000..d71b2fa95e --- /dev/null +++ b/test/language/import/import-defer/evaluation-sync/setup_FIXTURE.js @@ -0,0 +1,4 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations = []; diff --git a/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-1_FIXTURE.js b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-1_FIXTURE.js new file mode 100644 index 0000000000..1b2d700252 --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-1_FIXTURE.js @@ -0,0 +1,4 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("1"); diff --git a/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-2.1.1-tla_FIXTURE.js b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-2.1.1-tla_FIXTURE.js new file mode 100644 index 0000000000..6a4e668524 --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-2.1.1-tla_FIXTURE.js @@ -0,0 +1,8 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("2.1.1 start"); + +await Promise.resolve(0); + +globalThis.evaluations.push("2.1.1 end"); diff --git a/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-2.1_FIXTURE.js b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-2.1_FIXTURE.js new file mode 100644 index 0000000000..69b1c69da0 --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-2.1_FIXTURE.js @@ -0,0 +1,6 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import "./dep-2.1.1-tla_FIXTURE.js"; + +globalThis.evaluations.push("2.1"); diff --git a/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-2.2-tla_FIXTURE.js b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-2.2-tla_FIXTURE.js new file mode 100644 index 0000000000..5190e54741 --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-2.2-tla_FIXTURE.js @@ -0,0 +1,10 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import "./dep-2.2.1_FIXTURE.js" + +globalThis.evaluations.push("2.2 start"); + +await Promise.resolve(0); + +globalThis.evaluations.push("2.2 end"); diff --git a/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-2.2.1_FIXTURE.js b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-2.2.1_FIXTURE.js new file mode 100644 index 0000000000..b04fbc6e93 --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-2.2.1_FIXTURE.js @@ -0,0 +1,4 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("2.2.1"); diff --git a/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-2_FIXTURE.js b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-2_FIXTURE.js new file mode 100644 index 0000000000..c449575557 --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-2_FIXTURE.js @@ -0,0 +1,7 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import "./dep-2.1_FIXTURE.js"; +import "./dep-2.2-tla_FIXTURE.js"; + +globalThis.evaluations.push("2"); diff --git a/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-3_FIXTURE.js b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-3_FIXTURE.js new file mode 100644 index 0000000000..7517381157 --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-3_FIXTURE.js @@ -0,0 +1,4 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("3"); diff --git a/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-4.1-tla_FIXTURE.js b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-4.1-tla_FIXTURE.js new file mode 100644 index 0000000000..5b17bff759 --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-4.1-tla_FIXTURE.js @@ -0,0 +1,10 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import "./dep-2.2-tla_FIXTURE.js"; + +globalThis.evaluations.push("4.1 start"); + +await Promise.resolve(0); + +globalThis.evaluations.push("4.1 end"); diff --git a/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-4_FIXTURE.js b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-4_FIXTURE.js new file mode 100644 index 0000000000..9c2219483a --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-4_FIXTURE.js @@ -0,0 +1,6 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import "./dep-4.1-tla_FIXTURE.js"; + +globalThis.evaluations.push("4"); diff --git a/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-5_FIXTURE.js b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-5_FIXTURE.js new file mode 100644 index 0000000000..3c62ffc84c --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/dep-5_FIXTURE.js @@ -0,0 +1,4 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("5"); diff --git a/test/language/import/import-defer/evaluation-top-level-await/flattening-order/main.js b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/main.js new file mode 100644 index 0000000000..6fde991263 --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/main.js @@ -0,0 +1,78 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-innermoduleevaluation +description: > + Async dependencies of deferred modules are executed in the right order +info: | + 16.2.1.5.3.1 InnerModuleEvaluation ( _module_, _stack_, _index_ ) + 1. ... + 1. Let _evaluationList_ be a new empty List. + 1. For each ModuleRequest Record _required_ of _module_.[[RequestedModules]], do + 1. Let _requiredModule_ be GetImportedModule(_module_, _required_.[[Specifier]]). + 1. If _required_.[[Phase]] is ~defer~, then + i. Let _additionalModules_ be GatherAsynchronousTransitiveDependencies(_requiredModule_). + ii. For each Module Record _additionalModule_ of _additionalModules_, do + 1. If _evaluationList_ does not contain _additionalModule_, then + a. Append _additionalModule_ to _evaluationList_. + 1. Else if _evaluationList_ does not contain _requiredModule_, then + i. Append _requiredModule_ to _evaluationList_. + 1. ... + 1. For each Module Record _requiredModule_ of _evaluationList_, do + 1. Set _index_ to ? InnerModuleEvaluation(_requiredModule_, _stack_, _index_). + 1. ... + + GatherAsynchronousTransitiveDependencies ( _module_, [ _seen_ ] ) + 1. If _seen_ is not specified, let _seen_ be a new empty List. + 1. Let _result_ be a new empty List. + 1. If _seen_ contains _module_, return _result_. + 1. Append _module_ to _seen_. + 1. If _module_ is not a Cyclic Module Record, return _result_. + 1. If _module_.[[Status]] is either ~evaluating~ or ~evaluated~, return _result_. + 1. If _module_.[[HasTLA]] is *true*, then + 1. Append _module_ to _result_. + 1. Return _result_. + 1. For each ModuleRequest Record _required_ of _module_.[[RequestedModules]], do + 1. Let _requiredModule_ be GetImportedModule(_module_, _required_.[[Specifier]]). + 1. Let _additionalModules_ be GatherAsynchronousTransitiveDependencies(_requiredModule_, _seen_). + 1. For each Module Record _m_ of _additionalModules_, do + 1. If _result_ does not contain _m_, append _m_ to _result_. + 1. Return _result_. + +flags: [module, async] +features: [import-defer, top-level-await] +includes: [compareArray.js] +---*/ + +import "./setup_FIXTURE.js"; + +import "./dep-1_FIXTURE.js"; +import defer * as ns2 from "./dep-2_FIXTURE.js"; +import "./dep-3_FIXTURE.js"; +import defer * as ns4 from "./dep-4_FIXTURE.js"; +import "./dep-5_FIXTURE.js"; + +assert.compareArray(globalThis.evaluations, [ + "1", + "2.1.1 start", + "2.2.1", + "2.2 start", + "3", + "5", + "2.1.1 end", + "2.2 end", + "4.1 start", + "4.1 end", + "5" +]); + +globalThis.evaluations = []; +ns2.x; +assert.compareArray(globalThis.evaluations, ["2.1", "2"]); + +globalThis.evaluations = []; +ns4.x; +assert.compareArray(globalThis.evaluations, ["4"]); + +$DONE(); diff --git a/test/language/import/import-defer/evaluation-top-level-await/flattening-order/setup_FIXTURE.js b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/setup_FIXTURE.js new file mode 100644 index 0000000000..d71b2fa95e --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/flattening-order/setup_FIXTURE.js @@ -0,0 +1,4 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations = []; diff --git a/test/language/import/import-defer/evaluation-top-level-await/import-defer-async-module/main.js b/test/language/import/import-defer/evaluation-top-level-await/import-defer-async-module/main.js new file mode 100644 index 0000000000..e130d65e96 --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/import-defer-async-module/main.js @@ -0,0 +1,55 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-innermoduleevaluation +description: > + `import defer` causes eager evaluation of dependencies with top-level await +info: | + 16.2.1.5.3.1 InnerModuleEvaluation ( _module_, _stack_, _index_ ) + 1. ... + 1. Let _evaluationList_ be a new empty List. + 1. For each ModuleRequest Record _required_ of _module_.[[RequestedModules]], do + 1. Let _requiredModule_ be GetImportedModule(_module_, _required_.[[Specifier]]). + 1. If _required_.[[Phase]] is ~defer~, then + i. Let _additionalModules_ be GatherAsynchronousTransitiveDependencies(_requiredModule_). + ii. For each Module Record _additionalModule_ of _additionalModules_, do + 1. If _evaluationList_ does not contain _additionalModule_, then + a. Append _additionalModule_ to _evaluationList_. + 1. Else if _evaluationList_ does not contain _requiredModule_, then + i. Append _requiredModule_ to _evaluationList_. + 1. ... + 1. For each Module Record _requiredModule_ of _evaluationList_, do + 1. Set _index_ to ? InnerModuleEvaluation(_requiredModule_, _stack_, _index_). + 1. ... + + GatherAsynchronousTransitiveDependencies ( _module_, [ _seen_ ] ) + 1. If _seen_ is not specified, let _seen_ be a new empty List. + 1. Let _result_ be a new empty List. + 1. If _seen_ contains _module_, return _result_. + 1. Append _module_ to _seen_. + 1. If _module_ is not a Cyclic Module Record, return _result_. + 1. If _module_.[[Status]] is either ~evaluating~ or ~evaluated~, return _result_. + 1. If _module_.[[HasTLA]] is *true*, then + 1. Append _module_ to _result_. + 1. Return _result_. + 1. For each ModuleRequest Record _required_ of _module_.[[RequestedModules]], do + 1. Let _requiredModule_ be GetImportedModule(_module_, _required_.[[Specifier]]). + 1. Let _additionalModules_ be GatherAsynchronousTransitiveDependencies(_requiredModule_, _seen_). + 1. For each Module Record _m_ of _additionalModules_, do + 1. If _result_ does not contain _m_, append _m_ to _result_. + 1. Return _result_. + +flags: [module, async] +features: [import-defer, top-level-await] +includes: [compareArray.js] +---*/ + +import "./setup_FIXTURE.js"; +import defer * as ns from "./tla_FIXTURE.js"; + +assert.compareArray(globalThis.evaluations, ["tla start", "tla end"]); +ns.x; +assert.compareArray(globalThis.evaluations, ["tla start", "tla end"]); + +$DONE(); diff --git a/test/language/import/import-defer/evaluation-top-level-await/import-defer-async-module/setup_FIXTURE.js b/test/language/import/import-defer/evaluation-top-level-await/import-defer-async-module/setup_FIXTURE.js new file mode 100644 index 0000000000..d71b2fa95e --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/import-defer-async-module/setup_FIXTURE.js @@ -0,0 +1,4 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations = []; diff --git a/test/language/import/import-defer/evaluation-top-level-await/import-defer-async-module/tla_FIXTURE.js b/test/language/import/import-defer/evaluation-top-level-await/import-defer-async-module/tla_FIXTURE.js new file mode 100644 index 0000000000..f6a330837f --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/import-defer-async-module/tla_FIXTURE.js @@ -0,0 +1,8 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("tla start"); + +await Promise.resolve(0); + +globalThis.evaluations.push("tla end"); diff --git a/test/language/import/import-defer/evaluation-top-level-await/import-defer-transitive-async-module/imports-tla_FIXTURE.js b/test/language/import/import-defer/evaluation-top-level-await/import-defer-transitive-async-module/imports-tla_FIXTURE.js new file mode 100644 index 0000000000..cb87e3fbe3 --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/import-defer-transitive-async-module/imports-tla_FIXTURE.js @@ -0,0 +1,6 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import "./tla_FIXTURE.js"; + +globalThis.evaluations.push("imports-tla"); diff --git a/test/language/import/import-defer/evaluation-top-level-await/import-defer-transitive-async-module/main.js b/test/language/import/import-defer/evaluation-top-level-await/import-defer-transitive-async-module/main.js new file mode 100644 index 0000000000..c4317959b6 --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/import-defer-transitive-async-module/main.js @@ -0,0 +1,55 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-innermoduleevaluation +description: > + `import defer` causes eager evaluation of transitive dependencies with top-level await +info: | + 16.2.1.5.3.1 InnerModuleEvaluation ( _module_, _stack_, _index_ ) + 1. ... + 1. Let _evaluationList_ be a new empty List. + 1. For each ModuleRequest Record _required_ of _module_.[[RequestedModules]], do + 1. Let _requiredModule_ be GetImportedModule(_module_, _required_.[[Specifier]]). + 1. If _required_.[[Phase]] is ~defer~, then + i. Let _additionalModules_ be GatherAsynchronousTransitiveDependencies(_requiredModule_). + ii. For each Module Record _additionalModule_ of _additionalModules_, do + 1. If _evaluationList_ does not contain _additionalModule_, then + a. Append _additionalModule_ to _evaluationList_. + 1. Else if _evaluationList_ does not contain _requiredModule_, then + i. Append _requiredModule_ to _evaluationList_. + 1. ... + 1. For each Module Record _requiredModule_ of _evaluationList_, do + 1. Set _index_ to ? InnerModuleEvaluation(_requiredModule_, _stack_, _index_). + 1. ... + + GatherAsynchronousTransitiveDependencies ( _module_, [ _seen_ ] ) + 1. If _seen_ is not specified, let _seen_ be a new empty List. + 1. Let _result_ be a new empty List. + 1. If _seen_ contains _module_, return _result_. + 1. Append _module_ to _seen_. + 1. If _module_ is not a Cyclic Module Record, return _result_. + 1. If _module_.[[Status]] is either ~evaluating~ or ~evaluated~, return _result_. + 1. If _module_.[[HasTLA]] is *true*, then + 1. Append _module_ to _result_. + 1. Return _result_. + 1. For each ModuleRequest Record _required_ of _module_.[[RequestedModules]], do + 1. Let _requiredModule_ be GetImportedModule(_module_, _required_.[[Specifier]]). + 1. Let _additionalModules_ be GatherAsynchronousTransitiveDependencies(_requiredModule_, _seen_). + 1. For each Module Record _m_ of _additionalModules_, do + 1. If _result_ does not contain _m_, append _m_ to _result_. + 1. Return _result_. + +flags: [module, async] +features: [import-defer, top-level-await] +includes: [compareArray.js] +---*/ + +import "./setup_FIXTURE.js"; +import defer * as ns from "./imports-tla_FIXTURE.js"; + +assert.compareArray(globalThis.evaluations, ["tla start", "tla end"]); +ns.x; +assert.compareArray(globalThis.evaluations, ["tla start", "tla end", "imports-tla"]); + +$DONE(); diff --git a/test/language/import/import-defer/evaluation-top-level-await/import-defer-transitive-async-module/setup_FIXTURE.js b/test/language/import/import-defer/evaluation-top-level-await/import-defer-transitive-async-module/setup_FIXTURE.js new file mode 100644 index 0000000000..d71b2fa95e --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/import-defer-transitive-async-module/setup_FIXTURE.js @@ -0,0 +1,4 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations = []; diff --git a/test/language/import/import-defer/evaluation-top-level-await/import-defer-transitive-async-module/tla_FIXTURE.js b/test/language/import/import-defer/evaluation-top-level-await/import-defer-transitive-async-module/tla_FIXTURE.js new file mode 100644 index 0000000000..f6a330837f --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/import-defer-transitive-async-module/tla_FIXTURE.js @@ -0,0 +1,8 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("tla start"); + +await Promise.resolve(0); + +globalThis.evaluations.push("tla end"); diff --git a/test/language/import/import-defer/evaluation-top-level-await/sync-dependency-of-deferred-async-module/dep_FIXTURE.js b/test/language/import/import-defer/evaluation-top-level-await/sync-dependency-of-deferred-async-module/dep_FIXTURE.js new file mode 100644 index 0000000000..a3e50d5d6f --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/sync-dependency-of-deferred-async-module/dep_FIXTURE.js @@ -0,0 +1,4 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations.push("dep"); diff --git a/test/language/import/import-defer/evaluation-top-level-await/sync-dependency-of-deferred-async-module/imports-tla-with-dep_FIXTURE.js b/test/language/import/import-defer/evaluation-top-level-await/sync-dependency-of-deferred-async-module/imports-tla-with-dep_FIXTURE.js new file mode 100644 index 0000000000..0c4e34d0c6 --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/sync-dependency-of-deferred-async-module/imports-tla-with-dep_FIXTURE.js @@ -0,0 +1,6 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import "./tla-with-dep_FIXTURE.js"; + +globalThis.evaluations.push("imports-tla-with-dep"); diff --git a/test/language/import/import-defer/evaluation-top-level-await/sync-dependency-of-deferred-async-module/main.js b/test/language/import/import-defer/evaluation-top-level-await/sync-dependency-of-deferred-async-module/main.js new file mode 100644 index 0000000000..b1a7cb6f9b --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/sync-dependency-of-deferred-async-module/main.js @@ -0,0 +1,61 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-innermoduleevaluation +description: > + `import defer` causes eager evaluation of synchronous dependencies of async dependencies +info: | + 16.2.1.5.3.1 InnerModuleEvaluation ( _module_, _stack_, _index_ ) + 1. ... + 1. Let _evaluationList_ be a new empty List. + 1. For each ModuleRequest Record _required_ of _module_.[[RequestedModules]], do + 1. Let _requiredModule_ be GetImportedModule(_module_, _required_.[[Specifier]]). + 1. If _required_.[[Phase]] is ~defer~, then + i. Let _additionalModules_ be GatherAsynchronousTransitiveDependencies(_requiredModule_). + ii. For each Module Record _additionalModule_ of _additionalModules_, do + 1. If _evaluationList_ does not contain _additionalModule_, then + a. Append _additionalModule_ to _evaluationList_. + 1. Else if _evaluationList_ does not contain _requiredModule_, then + i. Append _requiredModule_ to _evaluationList_. + 1. ... + 1. For each Module Record _requiredModule_ of _evaluationList_, do + 1. Set _index_ to ? InnerModuleEvaluation(_requiredModule_, _stack_, _index_). + 1. ... + + GatherAsynchronousTransitiveDependencies ( _module_, [ _seen_ ] ) + 1. If _seen_ is not specified, let _seen_ be a new empty List. + 1. Let _result_ be a new empty List. + 1. If _seen_ contains _module_, return _result_. + 1. Append _module_ to _seen_. + 1. If _module_ is not a Cyclic Module Record, return _result_. + 1. If _module_.[[Status]] is either ~evaluating~ or ~evaluated~, return _result_. + 1. If _module_.[[HasTLA]] is *true*, then + 1. Append _module_ to _result_. + 1. Return _result_. + 1. For each ModuleRequest Record _required_ of _module_.[[RequestedModules]], do + 1. Let _requiredModule_ be GetImportedModule(_module_, _required_.[[Specifier]]). + 1. Let _additionalModules_ be GatherAsynchronousTransitiveDependencies(_requiredModule_, _seen_). + 1. For each Module Record _m_ of _additionalModules_, do + 1. If _result_ does not contain _m_, append _m_ to _result_. + 1. Return _result_. + +flags: [module, async] +features: [import-defer, top-level-await] +includes: [compareArray.js] +---*/ + +import "./setup_FIXTURE.js"; +import defer * as ns from "./imports-tla-with-dep_FIXTURE.js"; + +assert.compareArray( + globalThis.evaluations, + ["dep", "tla-with-dep start", "tla-with-dep end"] +); +ns.x; +assert.compareArray( + globalThis.evaluations, + ["dep", "tla-with-dep start", "tla-with-dep end", "imports-tla-with-dep"] +); + +$DONE(); diff --git a/test/language/import/import-defer/evaluation-top-level-await/sync-dependency-of-deferred-async-module/setup_FIXTURE.js b/test/language/import/import-defer/evaluation-top-level-await/sync-dependency-of-deferred-async-module/setup_FIXTURE.js new file mode 100644 index 0000000000..d71b2fa95e --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/sync-dependency-of-deferred-async-module/setup_FIXTURE.js @@ -0,0 +1,4 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +globalThis.evaluations = []; diff --git a/test/language/import/import-defer/evaluation-top-level-await/sync-dependency-of-deferred-async-module/tla-with-dep_FIXTURE.js b/test/language/import/import-defer/evaluation-top-level-await/sync-dependency-of-deferred-async-module/tla-with-dep_FIXTURE.js new file mode 100644 index 0000000000..fe6946f0e0 --- /dev/null +++ b/test/language/import/import-defer/evaluation-top-level-await/sync-dependency-of-deferred-async-module/tla-with-dep_FIXTURE.js @@ -0,0 +1,10 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +import "./dep_FIXTURE.js"; + +globalThis.evaluations.push("tla-with-dep start"); + +await Promise.resolve(0); + +globalThis.evaluations.push("tla-with-dep end"); diff --git a/test/language/import/import-defer/syntax/dep_FIXTURE.js b/test/language/import/import-defer/syntax/dep_FIXTURE.js new file mode 100644 index 0000000000..c0a2af180a --- /dev/null +++ b/test/language/import/import-defer/syntax/dep_FIXTURE.js @@ -0,0 +1,4 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +export default 1; diff --git a/test/language/import/import-defer/syntax/import-attributes.js b/test/language/import/import-defer/syntax/import-attributes.js new file mode 100644 index 0000000000..56b52d5da0 --- /dev/null +++ b/test/language/import/import-defer/syntax/import-attributes.js @@ -0,0 +1,21 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-imports +description: > + `import defer` can be used with namespace imports +info: | + ImportDeclaration : + `import` ImportClause FromClause WithClause? `;` + `import` `defer` NameSpaceImport FromClause WithClause? `;` + `import` ModuleSpecifier WithClause? `;` + + NameSpaceImport : + `*` `as` ImportedBinding + +flags: [module] +features: [import-defer] +---*/ + +import defer * as ns from "./dep_FIXTURE.js" with { }; diff --git a/test/language/import/import-defer/syntax/invalid-default-and-defer-namespace.js b/test/language/import/import-defer/syntax/invalid-default-and-defer-namespace.js new file mode 100644 index 0000000000..5a33f20e76 --- /dev/null +++ b/test/language/import/import-defer/syntax/invalid-default-and-defer-namespace.js @@ -0,0 +1,33 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-imports +description: > + `import defer` cannot be used if there are both a default and namespace bindings +info: | + ImportDeclaration : + `import` ImportClause FromClause `;` + `import` `defer` NameSpaceImport FromClause `;` + `import` ModuleSpecifier `;` + + ImportClause : + ImportedDefaultBinding + NameSpaceImport + NamedImports + ImportedDefaultBinding `,` NameSpaceImport + ImportedDefaultBinding `,` NamedImports + + NameSpaceImport : + `*` `as` ImportedBinding + +features: [import-defer] + +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +import defer x, * as ns from "./dep_FIXTURE.js"; diff --git a/test/language/import/import-defer/syntax/invalid-defer-as-with-no-asterisk.js b/test/language/import/import-defer/syntax/invalid-defer-as-with-no-asterisk.js new file mode 100644 index 0000000000..008108dee9 --- /dev/null +++ b/test/language/import/import-defer/syntax/invalid-defer-as-with-no-asterisk.js @@ -0,0 +1,33 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-imports +description: > + `import defer` must be followed by `*` +info: | + ImportDeclaration : + `import` ImportClause FromClause `;` + `import` `defer` NameSpaceImport FromClause `;` + `import` ModuleSpecifier `;` + + ImportClause : + ImportedDefaultBinding + NameSpaceImport + NamedImports + ImportedDefaultBinding `,` NameSpaceImport + ImportedDefaultBinding `,` NamedImports + + NameSpaceImport : + `*` `as` ImportedBinding + +features: [import-defer] + +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +import defer as ns from "./dep_FIXTURE.js"; diff --git a/test/language/import/import-defer/syntax/invalid-defer-default-and-namespace.js b/test/language/import/import-defer/syntax/invalid-defer-default-and-namespace.js new file mode 100644 index 0000000000..b7ba83936f --- /dev/null +++ b/test/language/import/import-defer/syntax/invalid-defer-default-and-namespace.js @@ -0,0 +1,33 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-imports +description: > + `import defer` cannot be used if there are both a default and namespace bindings +info: | + ImportDeclaration : + `import` ImportClause FromClause `;` + `import` `defer` NameSpaceImport FromClause `;` + `import` ModuleSpecifier `;` + + ImportClause : + ImportedDefaultBinding + NameSpaceImport + NamedImports + ImportedDefaultBinding `,` NameSpaceImport + ImportedDefaultBinding `,` NamedImports + + NameSpaceImport : + `*` `as` ImportedBinding + +features: [import-defer] + +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +import x, defer * as ns from "./dep_FIXTURE.js"; diff --git a/test/language/import/import-defer/syntax/invalid-defer-default.js b/test/language/import/import-defer/syntax/invalid-defer-default.js new file mode 100644 index 0000000000..e3af0bf784 --- /dev/null +++ b/test/language/import/import-defer/syntax/invalid-defer-default.js @@ -0,0 +1,33 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-imports +description: > + `import defer` cannot be used with default imports +info: | + ImportDeclaration : + `import` ImportClause FromClause `;` + `import` `defer` NameSpaceImport FromClause `;` + `import` ModuleSpecifier `;` + + ImportClause : + ImportedDefaultBinding + NameSpaceImport + NamedImports + ImportedDefaultBinding `,` NameSpaceImport + ImportedDefaultBinding `,` NamedImports + + NameSpaceImport : + `*` `as` ImportedBinding + +features: [import-defer] + +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +import defer x from "./dep_FIXTURE.js"; diff --git a/test/language/import/import-defer/syntax/invalid-defer-named.js b/test/language/import/import-defer/syntax/invalid-defer-named.js new file mode 100644 index 0000000000..6f94674dbd --- /dev/null +++ b/test/language/import/import-defer/syntax/invalid-defer-named.js @@ -0,0 +1,33 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-imports +description: > + `import defer` cannot be used with named imports +info: | + ImportDeclaration : + `import` ImportClause FromClause `;` + `import` `defer` NameSpaceImport FromClause `;` + `import` ModuleSpecifier `;` + + ImportClause : + ImportedDefaultBinding + NameSpaceImport + NamedImports + ImportedDefaultBinding `,` NameSpaceImport + ImportedDefaultBinding `,` NamedImports + + NameSpaceImport : + `*` `as` ImportedBinding + +features: [import-defer] + +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +import defer { default as x } from "./dep_FIXTURE.js"; diff --git a/test/language/import/import-defer/syntax/invalid-export-defer-namespace.js b/test/language/import/import-defer/syntax/invalid-export-defer-namespace.js new file mode 100644 index 0000000000..ff797659d0 --- /dev/null +++ b/test/language/import/import-defer/syntax/invalid-export-defer-namespace.js @@ -0,0 +1,32 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-exports +description: > + `export defer` is not valid +info: | + ExportDeclaration : + `export` ExportFromClause FromClause `;` + `export` NamedExports `;` + `export` VariableStatement + `export` Declaration + `export` `default` HoistableDeclaration + `export` `default` ClassDeclaration + `export` `default` [lookahead ∉ { function, async [no LineTerminator here] function, class }] AssignmentExpression `;` + + ExportFromClause : + `*` + `*` `as` ModuleExportName + NamedExports + +features: [import-defer] + +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +export defer * as ns from "./dep_FIXTURE.js"; diff --git a/test/language/import/import-defer/syntax/valid-default-binding-named-defer.js b/test/language/import/import-defer/syntax/valid-default-binding-named-defer.js new file mode 100644 index 0000000000..a69b000742 --- /dev/null +++ b/test/language/import/import-defer/syntax/valid-default-binding-named-defer.js @@ -0,0 +1,30 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-imports +description: > + `defer` is a valid name for default imports +info: | + ImportDeclaration : + `import` ImportClause FromClause `;` + `import` `defer` NameSpaceImport FromClause `;` + `import` ModuleSpecifier `;` + + ImportClause : + ImportedDefaultBinding + ... + + ImportedDefaultBinding : + ImportedBinding + + ImportedBinding : + BindingIdentifier[~Yield, +Await] + +flags: [module] +features: [import-defer] +---*/ + +import defer from "./dep_FIXTURE.js"; + +asserts.sameValue(defer, 1, "`defer` is the default export binding"); diff --git a/test/language/import/import-defer/syntax/valid-defer-namespace.js b/test/language/import/import-defer/syntax/valid-defer-namespace.js new file mode 100644 index 0000000000..2cf3637e1d --- /dev/null +++ b/test/language/import/import-defer/syntax/valid-defer-namespace.js @@ -0,0 +1,21 @@ +// Copyright (C) 2024 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-imports +description: > + `import defer` can be used with namespace imports +info: | + ImportDeclaration : + `import` ImportClause FromClause `;` + `import` `defer` NameSpaceImport FromClause `;` + `import` ModuleSpecifier `;` + + NameSpaceImport : + `*` `as` ImportedBinding + +flags: [module] +features: [import-defer] +---*/ + +import defer * as ns from "./dep_FIXTURE.js";