web: Prevent crashes with external libraries

This commit is contained in:
Toad06 2020-12-20 16:06:50 +01:00 committed by Mike Welsh
parent 820572f204
commit a6b7474a6b
2 changed files with 65 additions and 1 deletions

View File

@ -0,0 +1,53 @@
/* eslint @typescript-eslint/no-explicit-any: "off" */
/**
* Polyfills the `Array.prototype.reduce` method.
*
* Production steps of ECMA-262, Edition 5, 15.4.4.21
* Reference: https://es5.github.io/#x15.4.4.21
* https://tc39.github.io/ecma262/#sec-array.prototype.reduce
*
*/
export function setArrayPrototypeReduce(): void {
Object.defineProperty(Array.prototype, "reduce", {
value: function (...args: any) {
const callback = args[0];
if (this === null) {
throw new TypeError(
"Array.prototype.reduce called on null or undefined"
);
}
if (typeof callback !== "function") {
throw new TypeError(`${callback} is not a function`);
}
const o = Object(this);
const len = o.length >>> 0;
let k = 0;
let value;
if (args.length >= 2) {
value = args[1];
} else {
while (k < len && !(k in o)) {
k++;
}
if (k >= len) {
throw new TypeError(
"Reduce of empty array with no initial value"
);
}
value = o[k++];
}
while (k < len) {
if (k in o) {
value = callback(value, o[k], k, o);
}
k++;
}
return value;
},
});
}

View File

@ -6,6 +6,8 @@
import { Ruffle } from "../pkg/ruffle_web";
import { setArrayPrototypeReduce } from "./js-polyfills";
/**
* Load ruffle from an automatically-detected location.
*
@ -17,12 +19,21 @@ import { Ruffle } from "../pkg/ruffle_web";
* 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();
}
try {
// If ruffleRuntimePath is defined then we are executing inside the extension
// closure. In that case, we configure our local Webpack instance.
__webpack_public_path__ = ruffleRuntimePath + "dist/";
} catch (e) {
// Checking an undefined closure variable usually throws ReferencError,
// Checking an undefined closure variable usually throws ReferenceError,
// so we need to catch it here and continue onward.
if (!(e instanceof ReferenceError)) {
throw e;