Search code examples
javascriptfirefoxfirefox-addonfirefox-addon-webextensionscontent-script

EventTarget doesn't work in Firefox content script, does work in Chrome


In Chrome extension content scripts it is fine to do:

const myTarget = new EventTarget()
myTarget.addEventListener('test', () => console.log('test1'))
myTarget.dispatchEvent(new Event('test'))

but this does not work in Firefox, because in Firefox this !== window. Instead Firefox has this === globalThis where for some reason some standard Web API's like EventTarget in globalThis['EventTarget'] do not work, while window['EventTarget'] does work.

As a result this would mean to be able to use various standard Web APIs like EventTarget I'd need to call them via Window as window['EventTarget'] even though it works fine in Chrome as is. Alternatively deleting the EventTarget with delete globalThis['EventTarget'] makes it fallback to window['EvenTarget'] as well. I don't think either solutions are acceptable.

How can I deal with this in a sane way?

Example:

const { log } = console

log(EventTarget === EventTarget)
log(EventTarget === window['EventTarget'])
log(EventTarget === globalThis['EventTarget'])
log(EventTarget === self['EventTarget'])

const test1 = new EventTarget()
const test2 = new window['EventTarget']()
const test3 = new globalThis['EventTarget']()

test1.addEventListener('test', () => log('test1'))
test2.addEventListener('test', () => log('test2'))
test3.addEventListener('test', () => log('test3'))

test1.dispatchEvent(new Event('test'))
test2.dispatchEvent(new Event('test'))
test3.dispatchEvent(new Event('test'))

will log in Firefox add-on content script:

true
false
true
false
test2

and in Chrome extension content script:

true
true
true
true
test1
test2
test3

Firefox version: 128 (Latest)
Firefox manifest version: v2
Chrome manifest version: v3


Solution

  • Conclusion is, as @woxxom mentioned, that it's yet another decade old bug in Firefox that never got fixed. Instead of reinventing standard Web API's for this by coding it ourselves, it suffices to:

    globalThis['EventTarget'] = window['EventTarget']
    

    or

    delete globalThis['EventTarget']
    

    for Firefox only, as unsightly as it is.