Sprint 4: 'instanceof' TypeError bei fehlenden Browser-Constructors (SVGElement, MathMLElement) #54
Labels
No labels
bug
docs
feature
housekeeping
html-spec
performance
react-compat
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
glow-all/true-headless-browser#54
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problembeschreibung
Nach Sprint 3 (
document is not definedgefixt) tritt ein neuer TypeError auf:Stacktrace (Vue Runtime, vuejs.org):
Root Cause: Der Proxy-Window (
strict-Mode) gibtundefinedfür nicht-existente Browser-APIs zurück (specProxyGetLayer D). Wenn Module-Codex instanceof SVGElementmacht, istSVGElement→window.SVGElement→ Proxy-get →undefined→instanceof undefined→ TypeError.Betroffen sind ALLE
instanceof-Prüfungen gegen Browser-Klassen die Happy DOM nicht implementiert:SVGElement(Vue renderer:vt()→e instanceof SVGElement)MathMLElement(Vue renderer:e instanceof MathMLElement)ShadowRoot,HTMLDialogElement,TextTrack,MediaStream,AudioContext,BroadcastChannel,ServiceWorker, etc.Analyse
Proxy-Fallthrough
In
tolerant-proxy.ts:strictProxyGet():Jeder unbekannte Key gibt
undefinedzurück.instanceof undefinedist ein TypeError.KNOWN_MISSING_APISist nicht genugKNOWN_MISSING_APISist eine statische Liste (aktuell ~30 Einträge). Es gibt hunderte nicht-implementierte Browser-APIs. Jede Website könnte jede davon viainstanceofnutzen.Lösungsansätze
Option A: NullBrowserClass — Smart Fallback für Constructor-Namen
Die abstrakteste und zukunftssicherste Lösung:
Damit:
x instanceof SVGElement→falsestatt TypeError.typeof NullBrowserClass→"function"✅NullBrowserClass.prototype→ existiert ✅new NullBrowserClass()→ Nat-Error (akzeptabel für Constructor-Call) ⚠️Symbol.hasInstance→ immerfalse✅Option B: catch
instanceofim ExecutionRealminstanceofim Module-Code durch try/catch ersetzen — sehr invasiv (Code-Rewrite), keine Option.Option C: Alle bekannten Constructor-Namen in
KNOWN_MISSING_APISVollständige Liste aller nicht-implementierten Browser-APIs anlegen:
SVGElement,MathMLElement,HTMLDialogElement,HTMLDetailsElement,ShadowRoot,HTMLTemplateElement.content...MediaStream,AudioContext,MediaRecorder...BroadcastChannel,WebSocketStream...IDBFactory,IDBDatabase,IDBObjectStore...PerformanceObserver,PerformanceEntry...Aufwändig (100+ Einträge) und nicht zukunftssicher.
Option D: Proxy gibt
nullstattundefinedinstanceof nullwirft auch TypeError. Keine Lösung.Akzeptanzkriterien
x instanceof SVGElementwirft keinen TypeError mehr (returnfalse)x instanceof MathMLElementwirft keinen TypeError mehr (returnfalse)instanceof-Prüfungen gegen unbekannte Globals sind sichertypeof SVGElement === "function"(anders alsundefined)typeof MathMLElement === "function"] Keine Regression beiVP_HASH_MAP`-Syncinstanceof-TypeError (auch wenn andere Fehler bleiben)tests/issue-51-vphashmap-sync.test.ts✅Betroffene Dateien
src/tolerant-proxy.tsstrictProxyGet/specProxyGet: Fallback für Constructor-Namensrc/runtime-isolation.tsKNOWN_MISSING_APISerweitern oderNullBrowserClassimportierenCross-Ref
Details zum Fix (Option A — empfohlen)
Die Idee: Im Proxy-
get-Trap, WENN der Key mit Großbuchstaben beginnt (Constructor-Pattern) UND nicht indynamicStorageodertargetist, NICHTundefinedzurückgeben, sondern eineNullBrowserClass.Eingebaut in
strictProxyGet():Damit:
typeof window.SVGElement→"object"(nicht ideal, besser wäre"function")SVGElement[Symbol.hasInstance]→false✅x instanceof SVGElement→false✅Alternativ: stattdessen
functionzurückgeben:typeof window.SVGElement→"function"✅x instanceof SVGElement→false✅new SVGElement()wirft Error statt TypeError ✅Test Case
Implementiert ✅ (
9af39a1)Layer E: NullBrowserClass in
tolerant-proxy.ts9/9 Tests passen:
typeof SVGElement === "function"div instanceof SVGElement === falsenew SVGElement() throws TypeError(diagnostische Meldung)typeof MathMLElement === "function"div instanceof MathMLElement === falsetypeof window === "object"(bestehende APIs)react === undefined(Framework-Globals)typeof webkitURL === "function"(KNOWN_MISSING_APIS)Nächster Fehler bei vuejs.org:
IntersectionObserver is not implemented by this browser→ Saubere, implementierbare API-Lücke → Sprint 5.
Test:
bun run tests/null-browser-class.test.ts