Phase 4: Webpack Chunk Capture — tolerantProxy silent data loss beheben (x.com, Discord, YouTube) #48

Closed
opened 2026-06-18 07:12:24 +00:00 by Artur · 0 comments
Owner

Phase 4: Webpack Chunk Capture — tolerantProxy silent data loss beheben

Problembeschreibung

Webpack-basierte Seiten (x.com, Discord, YouTube) laden via window.webpackChunk_*.push([chunkId, modules]). Diese Chunks landen im tolerantProxy und werden stumm verworfen — die App bootstrapped nicht.

Heutiges Verhalten:

// x.com macht:
window.webpackChunk_twitter_responsive_web.push([123, { /* modules */ }]);
// → tolerantProxy fängt .push ab → returned undefined → Chunk verloren
// → App bleibt tot, nur statisches HTML sichtbar

Impact:

  • x.com: 344 tolerantProxy calls → 270KB DOM (nur Grundgerüst)
  • Discord: 906 tolerantProxy calls → 79KB DOM (nur Grundgerüst)
  • YouTube: 12345 tolerantProxy calls → 738KB DOM (nur Grundgerüst)

Ursache

strictObject Proxy erlaubt keine unbekannten Properties auf Window. Webpack versucht window.webpackChunk_* zu setzen → fängt strictObject ab → returned tolerantProxy → .push() auf tolerantProxy macht nichts.

Lösungsansatz: Property Setter für webpack Chunks

// In DynamicScriptHandler / Page Initialisierung:
// Für jede bekannte webpack Chunk-Variable einen Setter installieren

const WEBPACK_CHUNK_PATTERN = /^webpackChunk_/;

function installWebpackInterceptor(win: Window, handler: DynamicScriptHandler): void {
  // Proxy auf Window, der webpackChunk_* Properties abfängt
  const origDefineProperty = Object.defineProperty;
  
  // Statt defineProperty: Handler installiert Setter dynamisch
  // Wenn webpack auf window[X] = value macht:
  const chunkHandler = {
    set(target, prop, value) {
      if (typeof prop === 'string' && WEBPACK_CHUNK_PATTERN.test(prop)) {
        // Echten Array installieren
        const realArray = [];
        const origPush = Array.prototype.push;
        
        // push = chunk execution
        realArray.push = function(...args: any[]) {
          origPush.apply(this, args);
          for (const arg of args) {
            if (Array.isArray(arg) && arg.length >= 2) {
              const [chunkId, modules] = arg;
              handler._executeChunk(chunkId, modules);
            }
          }
        };
        
        // Wert überschreiben (Setter → echtes Property)
        delete target[prop];
        target[prop] = realArray;
        
        // Initial-Wert pushen
        if (Array.isArray(value)) {
          for (const item of value) {
            realArray.push(item);
          }
        }
        return true;
      }
      return Reflect.set(target, prop, value);
    }
  };
  
  return new Proxy(win, chunkHandler);
}

Oder einfacher: chunk-Erkennung in tolerantProxy

// In strictObject.ts / tolerantProxy:
// Wenn ein Property wie webpackChunk_* gesetzt wird:
get(target, prop) {
  if (typeof prop === 'string' && /^webpackChunk_/.test(prop)) {
    // Installiere echten Array + interceptor
    const realArray = createChunkArray();
    Object.defineProperty(target, prop, {
      value: realArray,
      writable: true,
      configurable: true,
    });
    return realArray;
  }
  // ... restlicher tolerantProxy code
}

_executeChunk — Chunk-Code im ExecutionRealm ausführen

_executeChunk(chunkId: number | string, modules: Record<string, Function>): void {
  // Webpack-Chunk-Module im aktuellen Realm ausführen
  // Module registrieren sich über webpack's __webpack_require__.c
  for (const [moduleId, moduleFn] of Object.entries(modules)) {
    try {
      if (typeof moduleFn === 'function') {
        // Im ExecutionRealm ausführen (gleicher Scope wie alle Scripts)
        this._realm.execute(`__webpack_require__.c[${JSON.stringify(moduleId)}] = { exports: {} };
(${moduleFn.toString()})(__webpack_require__)`);
      }
    } catch (err) {
      console.warn(`[Webpack] Chunk ${chunkId}, module ${moduleId}:`, err);
    }
  }
}

Akzeptanzkriterien

  • x.com: webpack Chunks werden nicht mehr verworfen (344 → 0 tolerantProxy calls)
  • x.com: App bootstrapped (DOM > 500KB, interaktiver Content)
  • Discord: App bootstrapped (kein __OVERLAY__ error)
  • YouTube: App bootstrapped (kein 12345 tolerantProxy)
  • tolerantProxy-Kompatibilität bleibt erhalten (unbekannte Props immer noch safe)
  • Keine Regression in 1423+ Tests

Betroffene Dateien

  • src/js/dynamic-scripts.ts — Neue _executeChunk() Methode
  • src/interaction/strict-object.ts — webpack-Chunk-Erkennung im Proxy
  • src/js/execution-realm.ts — Optional: execute als Callback expose

Cross-Referenzen

  • ACTION-PLAN.md Phase 4
  • SPEC-GAP-REPORT.md Gap 8
## Phase 4: Webpack Chunk Capture — tolerantProxy silent data loss beheben ### Problembeschreibung Webpack-basierte Seiten (x.com, Discord, YouTube) laden via `window.webpackChunk_*.push([chunkId, modules])`. Diese Chunks landen im tolerantProxy und werden **stumm verworfen** — die App bootstrapped nicht. **Heutiges Verhalten:** ```javascript // x.com macht: window.webpackChunk_twitter_responsive_web.push([123, { /* modules */ }]); // → tolerantProxy fängt .push ab → returned undefined → Chunk verloren // → App bleibt tot, nur statisches HTML sichtbar ``` **Impact:** - x.com: 344 tolerantProxy calls → 270KB DOM (nur Grundgerüst) - Discord: 906 tolerantProxy calls → 79KB DOM (nur Grundgerüst) - YouTube: 12345 tolerantProxy calls → 738KB DOM (nur Grundgerüst) ### Ursache `strictObject` Proxy erlaubt keine unbekannten Properties auf Window. Webpack versucht `window.webpackChunk_*` zu setzen → fängt strictObject ab → returned tolerantProxy → `.push()` auf tolerantProxy macht nichts. ### Lösungsansatz: Property Setter für webpack Chunks ```typescript // In DynamicScriptHandler / Page Initialisierung: // Für jede bekannte webpack Chunk-Variable einen Setter installieren const WEBPACK_CHUNK_PATTERN = /^webpackChunk_/; function installWebpackInterceptor(win: Window, handler: DynamicScriptHandler): void { // Proxy auf Window, der webpackChunk_* Properties abfängt const origDefineProperty = Object.defineProperty; // Statt defineProperty: Handler installiert Setter dynamisch // Wenn webpack auf window[X] = value macht: const chunkHandler = { set(target, prop, value) { if (typeof prop === 'string' && WEBPACK_CHUNK_PATTERN.test(prop)) { // Echten Array installieren const realArray = []; const origPush = Array.prototype.push; // push = chunk execution realArray.push = function(...args: any[]) { origPush.apply(this, args); for (const arg of args) { if (Array.isArray(arg) && arg.length >= 2) { const [chunkId, modules] = arg; handler._executeChunk(chunkId, modules); } } }; // Wert überschreiben (Setter → echtes Property) delete target[prop]; target[prop] = realArray; // Initial-Wert pushen if (Array.isArray(value)) { for (const item of value) { realArray.push(item); } } return true; } return Reflect.set(target, prop, value); } }; return new Proxy(win, chunkHandler); } ``` ### Oder einfacher: chunk-Erkennung in tolerantProxy ```typescript // In strictObject.ts / tolerantProxy: // Wenn ein Property wie webpackChunk_* gesetzt wird: get(target, prop) { if (typeof prop === 'string' && /^webpackChunk_/.test(prop)) { // Installiere echten Array + interceptor const realArray = createChunkArray(); Object.defineProperty(target, prop, { value: realArray, writable: true, configurable: true, }); return realArray; } // ... restlicher tolerantProxy code } ``` ### _executeChunk — Chunk-Code im ExecutionRealm ausführen ```typescript _executeChunk(chunkId: number | string, modules: Record<string, Function>): void { // Webpack-Chunk-Module im aktuellen Realm ausführen // Module registrieren sich über webpack's __webpack_require__.c for (const [moduleId, moduleFn] of Object.entries(modules)) { try { if (typeof moduleFn === 'function') { // Im ExecutionRealm ausführen (gleicher Scope wie alle Scripts) this._realm.execute(`__webpack_require__.c[${JSON.stringify(moduleId)}] = { exports: {} }; (${moduleFn.toString()})(__webpack_require__)`); } } catch (err) { console.warn(`[Webpack] Chunk ${chunkId}, module ${moduleId}:`, err); } } } ``` ### Akzeptanzkriterien - [ ] x.com: webpack Chunks werden nicht mehr verworfen (344 → 0 tolerantProxy calls) - [ ] x.com: App bootstrapped (DOM > 500KB, interaktiver Content) - [ ] Discord: App bootstrapped (kein `__OVERLAY__` error) - [ ] YouTube: App bootstrapped (kein 12345 tolerantProxy) - [ ] tolerantProxy-Kompatibilität bleibt erhalten (unbekannte Props immer noch safe) - [ ] Keine Regression in 1423+ Tests ### Betroffene Dateien - `src/js/dynamic-scripts.ts` — Neue _executeChunk() Methode - `src/interaction/strict-object.ts` — webpack-Chunk-Erkennung im Proxy - `src/js/execution-realm.ts` — Optional: execute als Callback expose ### Cross-Referenzen - ACTION-PLAN.md Phase 4 - SPEC-GAP-REPORT.md Gap 8
Artur 2026-06-18 07:12:24 +00:00
  • closed this issue
  • added the
    bug
    label
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#48
No description provided.