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";