Sprint 2: Inline Scripts blockieren Module Execution (per HTML Spec) #51

Closed
opened 2026-06-18 10:37:20 +00:00 by Artur · 2 comments
Owner

Problembeschreibung

Inline <script>-Blöcke (Config-Variablen wie __VP_HASH_MAP__, __INITIAL_STATE__, __OVERLAY__) laufen aktuell fire-and-forget via handler.loader.executeRaw(content, "inline").catch(...) — ohne await. Module können starten BEVOR die Inline-Config gesetzt ist.

Aktueller Code in dynamic-scripts.ts:_patchConnectedToDocument():

// Line 282 — fire-and-forget
handler.loader.executeRaw(content, "inline").catch((err: any) => {
  console.error("[DynamicScripts] Inline script error:", err);
});

Lösungsansatz

Option A: connectedToDocument blockieren — Inline-Script-Handler macht executeRaw synchron (es ist bereits synchron intern), aber die Module queue muss warten bis alle Inline-Scripts durch sind.

Option B: Module Queue pausierenexecuteModule darf erst starten wenn alle Inline-Scripts aus dem Parser-Durchlauf fertig sind.

Option C: Parser-FlagIncrementalParser setzt _allInlineScriptsProcessed-Flag, Module checken das.

Akzeptanzkriterien

  • Inline-Script window.__CFG__ = "hello" ist gesetzt BEVOR type="module"-Script läuft
  • Module-Code sieht window.__CFG__ und __CFG__ (bare global)
  • Keine race conditions bei mehreren Inline-Scripts
  • Bestehende Tests bleiben grün

Betroffene Dateien

Datei Änderung
src/js/dynamic-scripts.ts await + Sequentialisierung inline scripts
src/js/script-loader.ts Module-Execution erst nach inline-scripts
src/dom/parser.ts Flag für "all inline processed"

Cross-Ref

  • Sprint 1 (a274576): Module Sub-Import Resolution + Window Property Shims
  • #38: globalThis Sync in Sub-Module Resolution
## Problembeschreibung Inline `<script>`-Blöcke (Config-Variablen wie `__VP_HASH_MAP__`, `__INITIAL_STATE__`, `__OVERLAY__`) laufen aktuell fire-and-forget via `handler.loader.executeRaw(content, "inline").catch(...)` — ohne `await`. Module können starten BEVOR die Inline-Config gesetzt ist. Aktueller Code in `dynamic-scripts.ts:_patchConnectedToDocument()`: ```typescript // Line 282 — fire-and-forget handler.loader.executeRaw(content, "inline").catch((err: any) => { console.error("[DynamicScripts] Inline script error:", err); }); ``` ## Lösungsansatz **Option A: connectedToDocument blockieren** — Inline-Script-Handler macht `executeRaw` synchron (es ist bereits synchron intern), aber die Module queue muss warten bis alle Inline-Scripts durch sind. **Option B: Module Queue pausieren** — `executeModule` darf erst starten wenn alle Inline-Scripts aus dem Parser-Durchlauf fertig sind. **Option C: Parser-Flag** — `IncrementalParser` setzt `_allInlineScriptsProcessed`-Flag, Module checken das. ## Akzeptanzkriterien - [ ] Inline-Script `window.__CFG__ = "hello"` ist gesetzt BEVOR `type="module"`-Script läuft - [ ] Module-Code sieht `window.__CFG__` und `__CFG__` (bare global) - [ ] Keine race conditions bei mehreren Inline-Scripts - [ ] Bestehende Tests bleiben grün ## Betroffene Dateien | Datei | Änderung | |-------|----------| | `src/js/dynamic-scripts.ts` | await + Sequentialisierung inline scripts | | `src/js/script-loader.ts` | Module-Execution erst nach inline-scripts | | `src/dom/parser.ts` | Flag für "all inline processed" | ## Cross-Ref - Sprint 1 (a274576): Module Sub-Import Resolution + Window Property Shims - #38: globalThis Sync in Sub-Module Resolution
Author
Owner

Implemented in ab5558a — fundamentale Änderung der Script-Ausführungsreihenfolge im Parser:

Früher (fehlerhaft):

document.write(html) → inline scripts via connectedToDocument (fire-and-forget) → modules (Race!)

Jetzt (browser-accuracy):

Step 2: Inline Scripts SYNCHRON ausführen (in document order) → Config gesetzt ✅
Step 4: document.write(html) → Script-Tags intakt (currentScript etc.)
Step 6: executeModule() → sync globals → import()

Neues Flag: DynamicScriptHandler._parserHandledScripts = true

  • Verhindert doppelte Ausführung durch connectedToDocument
  • Nur dynamische Scripts (webpack chunks) werden noch abgefangen

Extrahiert: ExecutionRealm._syncGlobalsToGlobalThis()

  • Kopiert proxy-window Properties (inkl. dynamicStorage) nach globalThis
  • Aufgerufen in executeModule + _resolveSubModuleImports

Noch offen: vuejs.org __VP_HASH_MAP__ — die Inline-Script-Setzung läuft korrekt, aber der Wert wird noch nicht zuverlässig nach globalThis synchronisiert. Ursache muss tiefer debuggt werden (vermutlich JSON.parse-Fehler im Inline-Script).

Implemented in ab5558a — fundamentale Änderung der Script-Ausführungsreihenfolge im Parser: **Früher (fehlerhaft):** ``` document.write(html) → inline scripts via connectedToDocument (fire-and-forget) → modules (Race!) ``` **Jetzt (browser-accuracy):** ``` Step 2: Inline Scripts SYNCHRON ausführen (in document order) → Config gesetzt ✅ Step 4: document.write(html) → Script-Tags intakt (currentScript etc.) Step 6: executeModule() → sync globals → import() ``` **Neues Flag:** `DynamicScriptHandler._parserHandledScripts = true` - Verhindert doppelte Ausführung durch connectedToDocument - Nur dynamische Scripts (webpack chunks) werden noch abgefangen **Extrahiert:** `ExecutionRealm._syncGlobalsToGlobalThis()` - Kopiert proxy-window Properties (inkl. dynamicStorage) nach globalThis - Aufgerufen in executeModule + _resolveSubModuleImports **Noch offen:** vuejs.org `__VP_HASH_MAP__` — die Inline-Script-Setzung läuft korrekt, aber der Wert wird noch nicht zuverlässig nach globalThis synchronisiert. Ursache muss tiefer debuggt werden (vermutlich JSON.parse-Fehler im Inline-Script).
Author
Owner

Abgeschlossen

Root Cause Chain:

  1. CLI nutzt mode="strict" (nicht production) — strict proxy hatte keine ownKeys/getOwnPropertyDescriptor Traps
  2. Object.keys(proxyWindow) zeigte keine dynamicStorage-Einträge → _syncGlobalsToGlobalThis() fand __VP_HASH_MAP__ nicht
  3. Inline Module Scripts (type="module" ohne src) wurden nie gefüttert (Parser Step 6 filterte nur src-Scripts)

Fixes (7189e6f, a67191d):

  • strict-Mode Proxy: ownKeys + getOwnPropertyDescriptor Traps hinzugefügt
  • _buildModulePrologue() injiziert nicht-standard __XXX__ Globals als var-Deklarationen
  • Parser Step 6: inline module scripts werden jetzt auch zu ScriptLoader.onScriptTag() gegeben
  • _syncGlobalsToGlobalThis() kopiert proxy-window → globalThis

Test: tests/issue-51-vphashmap-sync.test.ts PASS

  • Inline Script setzt __VP_HASH_MAP__, __CFG__
  • Module (type="module") sieht beide als Bare-Globals
  • document und window im Module Scope OK

Noch offen: vuejs.org → ReferenceError: document is not defined (vue runtime, separater Issue)

## Abgeschlossen ✅ **Root Cause Chain:** 1. CLI nutzt `mode="strict"` (nicht `production`) — strict proxy hatte keine `ownKeys`/`getOwnPropertyDescriptor` Traps 2. `Object.keys(proxyWindow)` zeigte keine `dynamicStorage`-Einträge → `_syncGlobalsToGlobalThis()` fand `__VP_HASH_MAP__` nicht 3. Inline Module Scripts (`type="module"` ohne `src`) wurden nie gefüttert (Parser Step 6 filterte nur `src`-Scripts) **Fixes (7189e6f, a67191d):** - ✅ strict-Mode Proxy: `ownKeys` + `getOwnPropertyDescriptor` Traps hinzugefügt - ✅ `_buildModulePrologue()` injiziert nicht-standard `__XXX__` Globals als `var`-Deklarationen - ✅ Parser Step 6: inline module scripts werden jetzt auch zu `ScriptLoader.onScriptTag()` gegeben - ✅ `_syncGlobalsToGlobalThis()` kopiert proxy-window → globalThis **Test: `tests/issue-51-vphashmap-sync.test.ts`** ✅ PASS - Inline Script setzt `__VP_HASH_MAP__`, `__CFG__` - Module (`type="module"`) sieht beide als Bare-Globals - `document` und `window` im Module Scope OK **Noch offen:** vuejs.org → `ReferenceError: document is not defined` (vue runtime, separater Issue)
Artur closed this issue 2026-06-18 10:58:21 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
glow-all/true-headless-browser#51
No description provided.