web: Prevent crashes when native `Window` is overridden
This commit is contained in:
parent
4f980becb2
commit
3ae9ad57fc
|
@ -1,4 +1,5 @@
|
|||
/* eslint @typescript-eslint/no-explicit-any: "off" */
|
||||
/* eslint @typescript-eslint/ban-types: "off" */
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
|
@ -14,7 +15,7 @@ declare global {
|
|||
* https://tc39.github.io/ecma262/#sec-array.prototype.reduce
|
||||
*
|
||||
*/
|
||||
export function setArrayPrototypeReduce(): any {
|
||||
function polyfillArrayPrototypeReduce(): any {
|
||||
Object.defineProperty(Array.prototype, "reduce", {
|
||||
value: function (...args: any) {
|
||||
if (
|
||||
|
@ -67,3 +68,58 @@ export function setArrayPrototypeReduce(): any {
|
|||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Polyfills the `Window` function.
|
||||
*
|
||||
*/
|
||||
function polyfillWindow(): void {
|
||||
if (
|
||||
typeof window.constructor !== "function" ||
|
||||
!isNativeFunction(window.constructor)
|
||||
) {
|
||||
// Don't polyfill `Window` if `window.constructor` has been overridden.
|
||||
return;
|
||||
}
|
||||
// @ts-expect-error: `Function not assignable to { new (): Window; prototype: Window; }`
|
||||
window.Window = window.constructor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a function is native or not.
|
||||
*
|
||||
* @param func The function to test.
|
||||
* @returns True if the function hasn't been overridden.
|
||||
*/
|
||||
function isNativeFunction(func: Function): boolean {
|
||||
const val =
|
||||
typeof Function.prototype.toString === "function"
|
||||
? Function.prototype.toString()
|
||||
: null;
|
||||
if (typeof val === "string" && val.indexOf("[native code]") >= 0) {
|
||||
return (
|
||||
Function.prototype.toString.call(func).indexOf("[native code]") >= 0
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks and applies the polyfills to the current window, if needed.
|
||||
*
|
||||
*/
|
||||
export function setPolyfillsOnLoad(): void {
|
||||
if (
|
||||
typeof Array.prototype.reduce !== "function" ||
|
||||
!isNativeFunction(Array.prototype.reduce)
|
||||
) {
|
||||
// Some external libraries override the `Array.prototype.reduce` method in a way
|
||||
// that causes Webpack to crash (#1507, #1865), so we need to override it again.
|
||||
polyfillArrayPrototypeReduce();
|
||||
}
|
||||
if (typeof Window !== "function" || !isNativeFunction(Window)) {
|
||||
// Overriding the native `Window` function causes issues in wasm-bindgen, as a
|
||||
// code like `window instanceof Window` will no longer work.
|
||||
polyfillWindow();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { Ruffle } from "../pkg/ruffle_web";
|
||||
|
||||
import { setArrayPrototypeReduce } from "./js-polyfills";
|
||||
import { setPolyfillsOnLoad } from "./js-polyfills";
|
||||
|
||||
/**
|
||||
* Load ruffle from an automatically-detected location.
|
||||
|
@ -19,14 +19,9 @@ import { setArrayPrototypeReduce } from "./js-polyfills";
|
|||
* instances.
|
||||
*/
|
||||
async function fetchRuffle(): Promise<{ new (...args: any[]): Ruffle }> {
|
||||
if (
|
||||
typeof Array.prototype.reduce !== "function" ||
|
||||
Array.prototype.reduce.toString().indexOf("[native code]") === -1
|
||||
) {
|
||||
// Some external libraries override the `Array.prototype.reduce` method in a way
|
||||
// that causes Webpack to crash (#1507, #1865), so we need to override it again.
|
||||
setArrayPrototypeReduce();
|
||||
}
|
||||
// Apply some pure JavaScript polyfills to prevent conflicts with external
|
||||
// libraries, if needed.
|
||||
setPolyfillsOnLoad();
|
||||
|
||||
try {
|
||||
// If ruffleRuntimePath is defined then we are executing inside the extension
|
||||
|
|
Loading…
Reference in New Issue