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/no-explicit-any: "off" */
|
||||||
|
/* eslint @typescript-eslint/ban-types: "off" */
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
|
@ -14,7 +15,7 @@ declare global {
|
||||||
* https://tc39.github.io/ecma262/#sec-array.prototype.reduce
|
* https://tc39.github.io/ecma262/#sec-array.prototype.reduce
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export function setArrayPrototypeReduce(): any {
|
function polyfillArrayPrototypeReduce(): any {
|
||||||
Object.defineProperty(Array.prototype, "reduce", {
|
Object.defineProperty(Array.prototype, "reduce", {
|
||||||
value: function (...args: any) {
|
value: function (...args: any) {
|
||||||
if (
|
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 { Ruffle } from "../pkg/ruffle_web";
|
||||||
|
|
||||||
import { setArrayPrototypeReduce } from "./js-polyfills";
|
import { setPolyfillsOnLoad } from "./js-polyfills";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load ruffle from an automatically-detected location.
|
* Load ruffle from an automatically-detected location.
|
||||||
|
@ -19,14 +19,9 @@ import { setArrayPrototypeReduce } from "./js-polyfills";
|
||||||
* instances.
|
* instances.
|
||||||
*/
|
*/
|
||||||
async function fetchRuffle(): Promise<{ new (...args: any[]): Ruffle }> {
|
async function fetchRuffle(): Promise<{ new (...args: any[]): Ruffle }> {
|
||||||
if (
|
// Apply some pure JavaScript polyfills to prevent conflicts with external
|
||||||
typeof Array.prototype.reduce !== "function" ||
|
// libraries, if needed.
|
||||||
Array.prototype.reduce.toString().indexOf("[native code]") === -1
|
setPolyfillsOnLoad();
|
||||||
) {
|
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// If ruffleRuntimePath is defined then we are executing inside the extension
|
// If ruffleRuntimePath is defined then we are executing inside the extension
|
||||||
|
|
Loading…
Reference in New Issue