Skip to content

fix: preserve native dispatchEvent for Deno compatibility#7

Merged
Lojhan merged 2 commits into
mainfrom
fix/deno-dispatch-event-compatibility
Apr 5, 2026
Merged

fix: preserve native dispatchEvent for Deno compatibility#7
Lojhan merged 2 commits into
mainfrom
fix/deno-dispatch-event-compatibility

Conversation

@Lojhan
Copy link
Copy Markdown
Collaborator

@Lojhan Lojhan commented Apr 5, 2026

Problem

When running tests with Happy DOM under Deno, the process exits with:

TypeError: Failed to execute 'dispatchEvent' on 'EventTarget': parameter 1 is not of type 'Event'.
    at GlobalWindow.dispatchEvent (happy-dom/src/event/EventTarget.ts:122:10)
    at dispatchBeforeUnloadEvent (ext:runtime_main/js/99_main.js:469:22)

Deno's runtime dispatches a native beforeunload event on process exit. The current dom-env.ts uses GlobalRegistrator.register() which unconditionally overwrites globalThis.dispatchEvent with Happy DOM's version. Happy DOM's implementation validates that the event argument is an instance of its own internal Event class — it rejects Deno's native Event with a TypeError.

Fix

Replace GlobalRegistrator.register() with new GlobalWindow() from happy-dom, then install each DOM global individually. Before install, save any existing dispatchEvent, Event, and CustomEvent from globalThis and restore them after, so Deno's shutdown path remains intact.

Changes

  • src/dom-env.ts: replace GlobalRegistrator.register() with new GlobalWindow() + selective global install, preserving native dispatchEvent/Event/CustomEvent
  • package.json: remove @happy-dom/global-registrator from peerDependencies and peerDependenciesMeta — it is no longer used; happy-dom (already an optional peer) is sufficient

Testing

All three runtimes pass: Node 3/3, Bun 3/3, Deno 3/3.

Lojhan added 2 commits April 5, 2026 16:30
Replace GlobalRegistrator.register() with new GlobalWindow() from
happy-dom, then selectively install DOM globals while preserving
any existing dispatchEvent, Event, and CustomEvent on globalThis.

The old approach called GlobalRegistrator.register() which
unconditionally overwrites globalThis.dispatchEvent with Happy DOM's
implementation. Deno's runtime dispatches a native 'beforeunload'
event on process exit using its own Event constructor; Happy DOM's
dispatchEvent rejects it with a TypeError because the event is not
an instance of Happy DOM's internal Event class.

The fix saves the runtime's native event primitives before setting
up the Happy DOM window and restores them afterward. This leaves
Happy DOM's DOM APIs (document, HTMLElement, etc.) fully functional
while keeping Deno's shutdown path intact.

Also removes @happy-dom/global-registrator from peerDependencies
since it is no longer used.
@Lojhan Lojhan merged commit a510a86 into main Apr 5, 2026
9 checks passed
This was referenced Apr 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant