npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

dom-events-wintercg

v21.0.0

Published

An polyfill for DOM Events and related APIs, extracted from Node.js, for use in WinterCG runtimes

Downloads

28

Readme

DOM Events implementation for WinterCG

npm status

A polyfill for DOM Events and related APIs:

Implementation extracted from the Node.js codebase as of 10th March 2024 (version 21.7.1, I believe). Some simplified internals extracted from readable-stream.

To clarify, this project is not affiliated with WinterCG (i.e. is not an official work). It merely implements part of the WinterCG Common Minimum API proposal.

Installation

Install this npm package as follows, depending on which package manager you're using.

  • npm:

    npm install --save dom-events-wintercg
  • Yarn:

    yarn add dom-events-wintercg
  • pnpm:

    pnpm add dom-events-wintercg
  • Bun:

    bun add dom-events-wintercg
  • Deno: No need to install. Just add the npm: specifier when importing.

Usage

As a polyfill

Run this polyfill in your app's entrypoint file so that it fills in the APIs as early as possible in the app lifecycle.

import { polyfill } from 'dom-events-wintercg';

polyfill(globalThis);

// All implemented APIs will now be available in global scope

const eventTarget = new EventTarget();
const event = new Event('click', {});
eventTarget.addEventListener('click', (event) => {
  console.log(`Fired "${event.type}" event!`, event);
});
eventTarget.dispatchEvent(event, 'abc');

And for TypeScript typings, add the DOM lib in tsconfig.json:

{
  "compilerOptions": {
    "lib": ["DOM"],
    // ...
  }
}

As a module

Here, we import from the npm package each time we want to use an API, rather than polyfilling globally.

import { Event, EventTarget } from 'dom-events-wintercg';

const eventTarget = new EventTarget();
const event = new Event('click', {});
eventTarget.addEventListener('click', (event) => {
  console.log(`Fired "${event.type}" event!`, event);
});
eventTarget.dispatchEvent(event, 'abc');

Some limited TypeScript typings will be inferred from the library's JavaScript source code, but if you'd rather use the lib.dom.d.ts typings built into TypeScript (which I would recommend), then:

  1. Add the DOM lib in tsconfig.json:

    {
      "compilerOptions": {
        "lib": ["DOM"],
        // ...
      }
    }
  2. Do this little dance:

    import {
      Event as EventImpl,
      EventTarget as EventTargetImpl,
    } from 'dom-events-wintercg';
    
    // Redeclare the implementation using the types from lib.dom.d.ts
    const Event = EventImpl as unknown as Event;
    const EventTarget = EventTargetImpl as unknown as EventTarget;
    
    const eventTarget = new EventTarget();
    const event = new Event('click', {});
    eventTarget.addEventListener('click', (event) => {
      console.log(`Fired "${event.type}" event!`, event);
    });
    eventTarget.dispatchEvent(event, 'abc');

Via a bundler

This is my best-effort attempt to document usage with a bundler. These instructions are untested, so please open a PR if you find they need tweaking!

In all cases, you can set up TypeScript typings via adding the DOM lib to your tsconfig.json:

{
  "compilerOptions": {
    "lib": ["DOM"],
    // ...
  }
}

Below, I'll describe for each bundler how to integrate this package into your bundle.

Webpack 5

This configuration ensures that all the implemented APIs are available from global scope:

const webpackConfig = {
  plugins: [
    new webpack.ProvidePlugin({
      AbortController: ['dom-events-wintercg', 'AbortController'],
      AbortSignal: ['dom-events-wintercg', 'AbortSignal'],
      CustomEvent: ['dom-events-wintercg', 'CustomEvent'],
      DOMException: ['dom-events-wintercg', 'DOMException'],
      Event: ['dom-events-wintercg', 'Event'],
      EventTarget: ['dom-events-wintercg', 'EventTarget'],
    }),
  ],
};

Additionally, you can polyfill some of the Node.js events module (e.g. to use a Node.js library in a browser app) as follows. ⚠️ Be warned that while this package implements CustomEvent, Event, and EventTarget, it does not implement all the APIs in the Node.js events module. For example, it does not implement EventEmitter.

  const webpackConfig = {
+   resolve: {
+     fallback: {
+       events: require.resolve('dom-events-wintercg'),
+     },
+   },
    plugins: [
      new webpack.ProvidePlugin({
        AbortController: ['dom-events-wintercg', 'AbortController'],
        AbortSignal: ['dom-events-wintercg', 'AbortSignal'],
        CustomEvent: ['dom-events-wintercg', 'CustomEvent'],
        DOMException: ['dom-events-wintercg', 'DOMException'],
        Event: ['dom-events-wintercg', 'Event'],
        EventTarget: ['dom-events-wintercg', 'EventTarget'],
      }),
    ],
  };

Prerequisities

This polyfill relies on a few language features.

Required APIs

Your JS engine/runtime must support the following APIs (this is a non-exhaustive list):

Optional APIs

Some of the features of this polyfill are optional, and will fail gracefully if your JS engine/runtime lacks support for the underlying APIs.

AbortSignal.timeout()

AbortSignal.timeout() support requires the following APIs:

If missing, AbortSignal.timeout() will throw an Error with code ERR_METHOD_NOT_IMPLEMENTED when called.

Differences from browser EventTarget

Beyond the differences explained in the Node.js SDK docs, see this excellent article from NearForm about how they first brought EventTarget to Node.js, which covers some of the compromises they had to make in the implementation. In particular, there is no concept of bubbling or capturing, and event.preventDefault() is a bit useless, as it never has a "default action" to prevent.

Integrating into runtimes

This library, being runtime-agnostic, does nothing to keep the event loop alive for Worker event listeners. See the Node.js internals for how they implemented that.