3

A number of us using browsers other than the latest Chromium or Firefox browsers noticed in the last quarter of 2021 that a lot of things on the web started breaking within a few weeks of each other. It quickly became apparent that it wasn't something isolated, but something much larger going on. All of the issues seem to be relatively new JavaScript being used by sites that isn't compatible with older or non-Chromium/Firefox browsers, and their presence in many libraries is probably what made the issue pop up everywhere at once.

As a case in point, there are no browsers that I use that support things on many websites which used to work. That is, this is a case of websites that used to work perfectly fine but because some software devs were bored and decided to replace perfectly compatible JS with less-compatible JS, no longer do.

As examples, Iron (Chromium) 70 no longer works with many things, and Pale Moon / New Moon 28 no longer work with many things. Some things don't work with either of them and some only don't work with either.

StackOverflow.com has recently joined this bleeding edge JS bandwagon: I can no longer vote on or comment on anything in Iron 70, and posting questions is half-broken, though it all still works (for now) in New Moon 28. Here are some of the JS errors I get in the Developer Tools console when this page loads:

Uncaught ReferenceError: globalThis is not defined
    at stub.en.js?v=05770adb5484:1
    at stub.en.js?v=05770adb5484:1
    at stub.en.js?v=05770adb5484:1
how-do-i-escape-only-single-quotes:45 Uncaught TypeError: StackExchange.ready is not a function
    at how-do-i-escape-only-single-quotes:45
how-do-i-escape-only-single-quotes:79 Uncaught TypeError: StackExchange.ready is not a function
    at how-do-i-escape-only-single-quotes:79
how-do-i-escape-only-single-quotes:87 Uncaught TypeError: StackExchange.init is not a function
    at how-do-i-escape-only-single-quotes:87
how-do-i-escape-only-single-quotes:90 Uncaught TypeError: Cannot read property 'setCacheBreakers' of undefined
    at how-do-i-escape-only-single-quotes:90
how-do-i-escape-only-single-quotes:519 Uncaught TypeError: StackExchange.ready is not a function
    at how-do-i-escape-only-single-quotes:519
how-do-i-escape-only-single-quotes:3598 Uncaught TypeError: StackExchange.ifUsing is not a function
    at how-do-i-escape-only-single-quotes:3598
how-do-i-escape-only-single-quotes:3609 Uncaught TypeError: StackExchange.ready is not a function
    at how-do-i-escape-only-single-quotes:3609
how-do-i-escape-only-single-quotes:4137 Uncaught TypeError: StackExchange.ready is not a function
    at how-do-i-escape-only-single-quotes:4137
how-do-i-escape-only-single-quotes:4181 Uncaught TypeError: StackExchange.ready is not a function
    at how-do-i-escape-only-single-quotes:4181
how-do-i-escape-only-single-quotes:4294 Uncaught TypeError: StackExchange.ready is not a function
    at how-do-i-escape-only-single-quotes:4294
how-do-i-escape-only-single-quotes:4306 Uncaught TypeError: StackExchange.ready is not a function
    at how-do-i-escape-only-single-quotes:4306

Yeah, I know this is a 3+ year old browser, but the fact that it used to work fine, until all this JavaScript got replaced, makes me think that if I hack around with the code enough, maybe I can get things to work again. In any case, it's an interesting exercise I'm trying to see if it works. (And even though Iron 70 is 3+ years old, recent Pale Moon/New Moon are not brand new, and are affected by many of the same compatibility issues, so for the sake of a more open web that's more widely browser compatible, I'm trying to figure this out.) So, rather than complain about this, I'm trying to see how much of these compatibility issues can be reversed or fixed with polyfills. A lot of people have run into this same issue and so some kind of resolution to this would be really nice.

The first error in the list is easy to see what the issue: globalThis wasn't introduced in Chromium until version 71, exactly the version after the one I happen to be using. However, there are a number of polyfills out there for globalThis, to add support to older browsers. So in theory, it seems like I should be able to polyfill support for this into Chromium 70.

At first, I took a look at the core-js polyfill, but realized that was all way more than I really needed for a proof of concept.

I ended up trying to use the polyfill here: https://mathiasbynens.be/demo/globalthis.mjs

The polyfill itself is explained quite well here: https://mathiasbynens.be/notes/globalthis

To test this out, I went ahead and put together a simple Chrome extension, consisting of the following:

manifest.json:

{
    "manifest_version": 2,
    "name": "My Extension",
    "version": "0.1",
    "description": "My Description",
    "author": "Me",
    "permissions": ["https://stackoverflow.com/*"],
    "content_scripts": [{
            "matches": ["https://stackoverflow.com/*"],
            "js": ["corejsmin.js"],
            "run_at": "document_start",
            "all_frames": true
        }
    ]
}

corejsmin.js:

// https://mathiasbynens.be/notes/globalthis

// The polyfill starts here.
(function() {
    if (typeof globalThis === 'object') return;
    Object.defineProperty(Object.prototype, '__magic__', {
        get: function() {
            return this;
        },
        configurable: true
    });
    __magic__.globalThis = __magic__;
    delete Object.prototype.__magic__;
}());
// The polyfill ends here.


console.log(String(globalThis));

The polyfill seems to work, to some extent, because in the Developer Tools console, I do see the following printed out, before any of the page JS errors:

[object Window]

Yet, the errors persist - specifically here, the globalThis error remains and is unchanged.

I imagined that by injecting this JavaScript into the page before any of the JS on it executes, I would be able to polyfill globalThis so that when it is referenced, in this case in StackOverflow's JS code, it'll work properly. Yet, it doesn't seem to, even though it appears to work fine in the extension code.

What am I missing here? Why is globalThis defined before the page loads, but not in the Stack Overflow script? Ultimately, this seems like probably the simplest of the errors I'm seeing to address, but something here isn't quite right and I don't think there's any hope for this method if this can't be gotten to work. Is there something about this approach that wouldn't work, and is a different method of injection needed here?

InterLinked
  • 1,247
  • 2
  • 18
  • 50
  • This isn't the fault of JS. This is the fault of the browsers you're using not keeping up to speed with current enhancements which is what happens when you rely on forks of code that aren't being updated. What benefits does Pale Moon give you over and above Firefox (for example) at the moment? – Andy Jan 19 '22 at 21:16
  • Content scripts are isolated from the page so in a FF-based browser like PaleMoon all you need is `wrappedJSObject.globalThis = wrappedJSObject` instead of that clunky polyfill. – wOxxOm Jan 19 '22 at 21:35
  • 1
    @Andy Pale Moon is following web standards and is up to date, so I beg to disagree. It's companies like Google and Mozilla trying to shove their idea of the web down everyone's throats. Anyone who cares about the original vision of a truly free and open web should be concerned about this. The end result of this is coercing everyone towards the browser duopoly. As for why I don't use modern Chromium or FF, they both suck. The UI/UX is awful. – InterLinked Jan 19 '22 at 22:23
  • @wOxxOm Thanks, I don't think Pale Moon actually needs the globalThis polyfill, at least S.O. seems to work fine on it at the moment. This seems to be specifically needed for Chromium <= 70 – InterLinked Jan 19 '22 at 22:24
  • 2
    In Chromium you need to use a script element with `window.globalThis = window` inside its textContent, [see method 2](/a/9517879). – wOxxOm Jan 19 '22 at 23:03
  • @wOxxOm WOW! This did it. StackOverflow.com works again in Iron 70! I guess globalThis alone was responsible for all the other errors, everything works perfectly again - definitely going to pursue this further! If you post as answer, I will accept. – InterLinked Jan 19 '22 at 23:15
  • I'm confused, You like web standards, and you use Pale Moon which is basically a fork of FF which exemplifies web standards. Which is it? You hate web standards, or you just hate the web standards of the companies that your browser uses? There's an irony here I don't understand. – Andy Jan 19 '22 at 23:23
  • @Andy Chrome and FF follow their own ambitions by adopting features that aren't established web standards. There are a lot more browsers in the world than just those two, and yet, they don't seem to realize or care about that. Following web standards means being widely compatible, not adopting bleeding edge vendor-specific features – InterLinked Jan 19 '22 at 23:29
  • Oh, so PM has its own web standards? Tell me all about those. @InterLinked. – Andy Jan 20 '22 at 00:06
  • Nope, they follow established standards, unlike Google and Mozilla. What Pale Moon *doesn't* have is the bleeding-edge vendor-specific crap that Google and Mozilla are jumping on now – InterLinked Jan 20 '22 at 00:22

1 Answers1

2

Content script's JS environment is isolated from the page so changes to objects or prototypes do not affect the page scripts.

In Chromium-based browsers you need to run the code inside a script element (more info):

document.documentElement.appendChild(
  Object.assign(document.createElement('script'), {
    textContent: 'window.globalThis = window',
  })
).remove();

In Firefox-based browsers you can use wrappedJSObject:

wrappedJSObject.globalThis = wrappedJSObject;
wOxxOm
  • 65,848
  • 11
  • 132
  • 136