Skip to content

Use Node.js 15 native EventTarget object #1818

@piranna

Description

@piranna
  • I've searched for any related issues and avoided creating a duplicate
    issue.

Description

Node.js 15 already provides a native implementation of EventTarget, so there's no need to use our own implementation. In fact, using both of them at the same time leads to errors.

In my use case, I've created a Client class that extends from Node.js native EventTarget class, that internally it's using an ws instance (and doing some other project specific things), and setting as listeners methods from this Client class, with the idea of propagate these errors to the user:

export class Client extends EventTarget
{
  constructor(ws)
  {
    super()

    if(!(ws instanceof WebSocket)) ws = new WebSocket(ws)

    ws.binaryType = 'arraybuffer'

    ws.addEventListener('close', this.#onClose, {once: true})
    ws.addEventListener('error', this.#onError)
    ws.addEventListener('message', this.#onMessage)
    ws.addEventListener('open', this.#onOpen, {once: true})

    this.#ws = ws
  }

  #onClose = this.dispatchEvent.bind(this)
  #onError = this.dispatchEvent.bind(this)
  #onOpen  = this.dispatchEvent.bind(this)
}

Problem is, since ws is using its own implementation of both EventTarget and Event classes, when these events gets propagated to the native one, I get the next error:

TypeError [ERR_INVALID_ARG_TYPE]: The "event" argument must be an instance of Event. Received an instance of ErrorEvent
    at new NodeError (node:internal/errors:277:15)
    at EventTarget.dispatchEvent (node:internal/event_target:326:13)
    at WebSocket.onError (/home/piranna/Trabajo/Atos/awrtc_signaling/node_modules/ws/lib/event-target.js:141:16)
    at WebSocket.emit (node:events:329:20)
    at WebSocket.EventEmitter.emit (node:domain:467:12)
    at ClientRequest.<anonymous> (/home/piranna/Trabajo/Atos/awrtc_signaling/node_modules/ws/lib/websocket.js:579:15)
    at ClientRequest.emit (node:events:329:20)
    at ClientRequest.EventEmitter.emit (node:domain:467:12)
    at TLSSocket.socketErrorListener (node:_http_client:478:9)
    at TLSSocket.emit (node:events:329:20) {
  code: 'ERR_INVALID_ARG_TYPE'
}

This is due because Node.js native EventTarget class is expecting a native Event class instance, instead of the one provided by ws. According to Node.js docs it should be accepting any object with a type field, but for some reason is not accepting it.

Reproducible in:

  • version: 7.4.0
  • Node.js version(s): 15.2.0
  • OS version(s): Ubuntu 20.10

Steps to reproduce:

  1. use Node.js 15
  2. create an object instance with Node.js 15 native EventTarget class in its prototype chain
  3. create a ws instance and call to addEventListener setting one function that propagate the event to the native EventTarget
  4. emit the event
  5. BOOM

Expected result:

ws should check for actual support of both Event and EventTarget classes in the native platform (in this case, Node.js 15) and use them. In case they are not available, then use its own implementation as a polyfill.

Actual result:

ws is using always its own implementation of Event and EventTarget classes, since there was none before, so now it conflicts with the new Node.js native available ones.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions