Dynamic `import.defer()` semantics
7f06296
JSTests/modules/import-defer-dynamic-evaluation.js
+const ns = await import.defer("./import-defer/eval-tracker.js");
+shouldBe(JSON.stringify(globalThis.deferEvaluations), "[]");
+
+// Symbol 키를 이용한 접근도 evaluation을 유발해서는 안 됩니다.
+shouldBe(ns[Symbol.toStringTag], "Deferred Module");
+shouldBe(JSON.stringify(globalThis.deferEvaluations), "[]");
+
+// Symbol이 아닌 첫 번째 접근에서 모듈이 동기적으로 평가됩니다.
+shouldBe(ns.value, 42);
+shouldBe(JSON.stringify(globalThis.deferEvaluations), JSON.stringify(["eval-tracker"]));
+
+// 이후 import.defer() 호출은 동일한 namespace를 반환하며, 재평가는 발생하지 않습니다.
+const ns2 = await import.defer("./import-defer/eval-tracker.js");
+shouldBe(ns2, ns);
TC39 Deferred Module Evaluation 제안은 모듈 링킹과 모듈 실행을 분리합니다. deferred namespace proxy는 즉시 반환되며, 모듈 본문은 첫 번째 non-Symbol 프로퍼티 접근 시에만 실행됩니다. JSC의 모듈 파이프라인은 엔진 측(graph 탐색, bytecode, microtask 스케줄링)과 WebCore 바인딩 계층(ScriptModuleLoader, JSDOMGlobalObject)으로 나뉘는데, 새로운 "import phase" 파라미터는 두 계층 모두를 거쳐 전달되어야 합니다.
이 commit은 동적 import.defer(specifier) 형식을 구현합니다. 모듈 그래프는 로드 및 링크 단계까지 진행하되, deferred root 자체는 즉시 실행하지 않습니다. GatherAsynchronousTransitiveDependencies()는 실행되지 않은 top-level-await (TLA) 모듈을 post-order로 수집합니다. 수집된 모듈은 두 개의 새로운 내부 microtask(DynamicImportDeferLoadSettled, DynamicImportDeferDependencySettled)를 통해 평가되며, 모든 의존성이 settle되면 반환된 promise가 deferred module namespace로 resolve됩니다.
모든 TLA 의존성 promise를 대기하는 AND-join은 JSPromiseCombinatorsGlobalContext를 shared counter cell로 재사용합니다. Promise.all 내부 구현에서 차용한 패턴이지만, 사양상 핵심 제약이 있습니다. 의존성 promise에 대해 then을 조회해서는 안 됩니다.
import.defer(specifier)
├─► load() + link()
├─► GatherAsyncTransitiveDeps() → [dep1, dep2, ...]
├─► evaluate(depN) ──► AND-join counter (DynamicImportDeferDependencySettled)
└─► resolve(deferredNamespace)
Namespace proxy dispatch:
Symbol key ──► return value (NO evaluation)
String key ──► evaluate() ──► return value
Significance
이 변경은 새로운 JS-visible API와 새로운 microtask 유형을 도입하며, promise AND-join과 namespace proxy dispatch 동작 방식이 JSC 모듈 시스템의 모든 계층에 걸쳐 새롭게 추가됩니다. 이 영역은 JS 엔진에서 역사적으로 보안 버그 밀도가 가장 높은 곳에 해당합니다.
Audit directions
a Aaaaaaaaaa Aaaaaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaa Aaaaaaa Aaaaa Aaaaaaa Aaaaaaa Aaa Aaaaa Aa Aa a Aaaa Aaaaaaa Aaaaaaaaaa Aaaaaaaaaaaaaaaaa Aa Aa Aaaaaaaa Aaaaaaaaaaaaa Aa Aaa Aaaa Aa Aaaaaa a Aaa Aaa Aaa Aaa Aaaaaaaa Aa Aaaaaaa Aaaa Aaa Aaaaa Aaaaa Aaaaa Aa Aaa Aaaa Aaaa Aaaaaaa Aaaaaaa Aa Aaaaaaaaaa Aaa Aaa Aaa a Aaaaa
a Aaaaaaaaaa Aaaaaaaaa Aaaaa Aaaaaaaaaaaaa Aaaaaaaaaaa Aaaaaa Aa Aa Aaa Aaaaaaaaaaa Aaaaa a Aaa Aaaaaaa Aa Aaaaaa Aaa Aaa Aaaaaaaaaaa Aaaaa Aaaa Aaaa Aaaaaa Aaaaaaaa Aaa Aa Aaaaaaaa Aaaaaaaa Aaa Aaaaa Aaaaaa Aaa Aaaaaaa Aaaa Aaaaaaaaaaaaa Aaaaa Aaaaaa Aaaaaaaaaaaa Aaaaaa Aaaa Aaaaaaaaa Aaaaa Aaa Aaa Aaa Aaaaa
a Aaaa Aaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaa Aaa Aaaaaa Aaaa Aaaa Aaaa Aaaaaaaaaaaa Aaa Aaaaa Aaaa Aaaa Aaa Aaaaaaaaaaaaaaaa Aa Aa Aaa Aaa Aaa Aaaaa Aa Aaaaa Aa Aaa Aaa a Aaaaa
a Aaaaa Aaa Aa Aaaaaa Aaaaa Aaaaa Aaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaa Aa Aaa Aa Aaaaaa Aa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaa Aa Aaaaa Aaaaaa Aaaaa Aaaaa Aa Aaaaa Aaaaaaaa Aaa Aaaa Aa Aaa Aaa Aaa a Aaaaa
a Aaaaaaaaaaa Aaa Aa Aaaaaaa Aaaa Aaa Aaaaaa Aa Aaa Aaa Aaa Aaa Aaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaa Aaaaaaaaa Aaa Aaa Aaa Aa Aaa Aaaaa Aaa Aaa Aaa Aaaa Aaaaa Aaa Aaaaaaa Aaa Aa Aaaaaaaa Aaaa Aaaaa Aaa Aaa Aaaaa
🔒New promise AND-join mechanics, namespace proxy dispatch boundaries, and cross-layer import phase propagation all have audit-worthy angles.
더 확인하려면 구독해 주세요