Prozi / pixi-shim

PIXI.js Back-End "shim". For mocking Canvas in Node.js with ❤️
https://pietal.dev
46 stars 11 forks source link

TypeError: 'addEventListener' called on an object that is not a valid instance of EventTarget. #27

Closed gapgag55 closed 2 years ago

gapgag55 commented 2 years ago

I face the problem of initializing the PIXI application

My code is that

const PIXI = require("pixi-shim/pixi.js");

const app = new PIXI.Application({ width: 200, height: 200 });

And output

pixi-shim ❤️ DOM
pixi-shim ❤️ Window 1024x768
pixi-shim ❤️ Canvas
WebGL not available for compressed textures. Silently failing.
/Users/kopkap/Desktop/2.learn/3.pixi-node/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:101
        throw new globalObject.TypeError(
        ^

TypeError: 'addEventListener' called on an object that is not a valid instance of EventTarget.
    at addEventListener (/Users/kopkap/Desktop/2.learn/3.pixi-node/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:101:15)
    at new AccessibilityManager (/Users/kopkap/Desktop/2.learn/3.pixi-node/node_modules/@pixi/accessibility/dist/cjs/accessibility.js:177:20)
    at CanvasRenderer.AbstractRenderer.initPlugins (/Users/kopkap/Desktop/2.learn/3.pixi-node/node_modules/@pixi/core/dist/cjs/core.js:9043:31)
    at new CanvasRenderer (/Users/kopkap/Desktop/2.learn/3.pixi-node/node_modules/@pixi/canvas-renderer/dist/cjs/canvas-renderer.js:419:15)
    at Function.create (/Users/kopkap/Desktop/2.learn/3.pixi-node/node_modules/@pixi/canvas-renderer/dist/cjs/canvas-renderer.js:871:12)
    at Object.autoDetectRenderer (/Users/kopkap/Desktop/2.learn/3.pixi-node/node_modules/@pixi/core/dist/cjs/core.js:9717:21)
    at Object.Application (/Users/kopkap/Desktop/2.learn/3.pixi-node/node_modules/@pixi/app/dist/cjs/app.js:78:30)
    at Object.<anonymous> (/Users/kopkap/Desktop/2.learn/3.pixi-node/index.js:3:18)
    at Module._compile (node:internal/modules/cjs/loader:1099:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)

I guess it's related to jsdom-global

mutewinter commented 2 years ago

Temporary fix is to do this assignment before importing PIXI:

global.globalThis = global.window;
Prozi commented 2 years ago

I've tried to fix this @mutewinter @gapgag55 just now

please try latest version ^2.3.23

mutewinter commented 2 years ago

I actually ended up making my own polyfill with the minimal includes I needed for my Pixi / React Pixi app.

import jsdom from 'jsdom';

export default function createHeadlessCanvas() {
  const dom = new jsdom.JSDOM(`<!DOCTYPE html><body><canvas /></body></html>`, {
    pretendToBeVisual: true,
    resources: 'usable',
  });
  const {
    window,
    window: { document },
  } = dom;

  global.document = document;
  // PIXI uses globalThis as if it were window, so we overwrite specific
  // functions it expects
  global.globalThis.addEventListener = window.addEventListener.bind(window);
  global.globalThis.removeEventListener = window.removeEventListener.bind(
    window,
  );
  global.globalThis.requestAnimationFrame = window.requestAnimationFrame.bind(
    window,
  );
  global.globalThis.cancelAnimationFrame = window.cancelAnimationFrame.bind(
    window,
  );

  global.navigator = window.navigator;
  global.HTMLImageElement = window.HTMLImageElement;
  global.HTMLVideoElement = window.HTMLVideoElement;
  global.HTMLCanvasElement = window.HTMLCanvasElement;
  global.XMLDocument = window.XMLDocument;
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
  global.Image = window.Image;

  return document.querySelector('canvas') as HTMLCanvasElement;
}

JSDom can actually take care of requestAnimationFrame, but only if you pass pretendToBeVisual: true. I also added resources: 'usable' which makes image fetching work! Greatly reduces the amount of code needed to polyfill (for my use case).

Prozi commented 2 years ago

nice! closing then as afaik the fix works now