web: Remove ruffleIndexError as a global thing on Error, make our own Error classes
This commit is contained in:
parent
a8b146df3e
commit
e67cc08da5
|
@ -1,4 +1,3 @@
|
|||
interface Error {
|
||||
ruffleIndexError?: number;
|
||||
avmStack?: string;
|
||||
}
|
||||
|
|
|
@ -14,3 +14,101 @@ export enum PanicError {
|
|||
SwfFetchError,
|
||||
SwfCors,
|
||||
}
|
||||
|
||||
export class LoadSwfError extends Error {
|
||||
readonly #swfUrl: URL | undefined;
|
||||
|
||||
constructor(swfUrl: URL | undefined) {
|
||||
super(`Failed to fetch ${swfUrl}`);
|
||||
this.#swfUrl = swfUrl;
|
||||
}
|
||||
|
||||
get ruffleIndexError() {
|
||||
if (this.#swfUrl && !this.#swfUrl.protocol.includes("http")) {
|
||||
return PanicError.FileProtocol;
|
||||
} else if (
|
||||
window.location.origin === this.#swfUrl?.origin ||
|
||||
// The extension's internal player page is not restricted by CORS
|
||||
window.location.protocol.includes("extension")
|
||||
) {
|
||||
return PanicError.SwfFetchError;
|
||||
} else {
|
||||
// This is a selfhosted build of Ruffle that tried to make a cross-origin request
|
||||
return PanicError.SwfCors;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class InvalidSwfError extends Error {
|
||||
constructor(swfUrl: URL | undefined) {
|
||||
super(`Not a valid swf: ${swfUrl}`);
|
||||
}
|
||||
|
||||
get ruffleIndexError() {
|
||||
return PanicError.InvalidSwf;
|
||||
}
|
||||
}
|
||||
|
||||
export class LoadRuffleWasmError extends Error {
|
||||
constructor(public cause: Error) {
|
||||
super("Failed to load Ruffle WASM");
|
||||
}
|
||||
|
||||
get ruffleIndexError() {
|
||||
// Serious duck typing. In error conditions, let's not make assumptions.
|
||||
if (window.location.protocol === "file:") {
|
||||
return PanicError.FileProtocol;
|
||||
} else {
|
||||
const message = String(this.cause.message).toLowerCase();
|
||||
if (message.includes("mime")) {
|
||||
return PanicError.WasmMimeType;
|
||||
} else if (
|
||||
message.includes("networkerror") ||
|
||||
message.includes("failed to fetch")
|
||||
) {
|
||||
return PanicError.WasmCors;
|
||||
} else if (message.includes("disallowed by embedder")) {
|
||||
return PanicError.CSPConflict;
|
||||
} else if (this.cause.name === "CompileError") {
|
||||
return PanicError.InvalidWasm;
|
||||
} else if (
|
||||
message.includes("could not download wasm module") &&
|
||||
this.cause.name === "TypeError"
|
||||
) {
|
||||
return PanicError.WasmDownload;
|
||||
} else if (this.cause.name === "TypeError") {
|
||||
return PanicError.JavascriptConflict;
|
||||
} else if (
|
||||
navigator.userAgent.includes("Edg") &&
|
||||
message.includes("webassembly is not defined")
|
||||
) {
|
||||
// Microsoft Edge detection.
|
||||
return PanicError.WasmDisabledMicrosoftEdge;
|
||||
} else {
|
||||
return PanicError.WasmNotFound;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class InvalidOptionsError extends Error {
|
||||
constructor(message: string) {
|
||||
super(`Invalid options: ${message}`);
|
||||
}
|
||||
|
||||
get ruffleIndexError() {
|
||||
return PanicError.JavascriptConfiguration;
|
||||
}
|
||||
}
|
||||
|
||||
export function getRuffleIndexError(error: Error | null): PanicError {
|
||||
if (
|
||||
error instanceof InvalidOptionsError ||
|
||||
error instanceof InvalidSwfError ||
|
||||
error instanceof LoadRuffleWasmError ||
|
||||
error instanceof LoadSwfError
|
||||
) {
|
||||
return error.ruffleIndexError;
|
||||
}
|
||||
return PanicError.Unknown;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { text, textAsParagraphs } from "../../i18n";
|
|||
import { createRef } from "tsx-dom";
|
||||
import { buildInfo } from "../../build-info";
|
||||
import { RUFFLE_ORIGIN } from "../constants";
|
||||
import { PanicError } from "../errors";
|
||||
import { getRuffleIndexError, PanicError } from "../errors";
|
||||
|
||||
interface PanicLink {
|
||||
type: "open_link";
|
||||
|
@ -284,13 +284,13 @@ function createReportAction({
|
|||
|
||||
export function showPanicScreen(
|
||||
container: HTMLElement,
|
||||
errorIndex: number,
|
||||
error: Error | null,
|
||||
errorArray: ErrorArray,
|
||||
swfUrl: URL | undefined,
|
||||
) {
|
||||
const errorText = errorArray.join("");
|
||||
let { body, actions } = createPanicError(
|
||||
errorIndex,
|
||||
getRuffleIndexError(error),
|
||||
errorText,
|
||||
errorArray,
|
||||
swfUrl,
|
||||
|
|
|
@ -19,7 +19,12 @@ import { isExtension } from "./current-script";
|
|||
import { configureBuilder } from "./internal/builder";
|
||||
import { showPanicScreen } from "./internal/ui/panic";
|
||||
import { RUFFLE_ORIGIN } from "./internal/constants";
|
||||
import { PanicError } from "./internal/errors";
|
||||
import {
|
||||
InvalidOptionsError,
|
||||
InvalidSwfError,
|
||||
LoadRuffleWasmError,
|
||||
LoadSwfError,
|
||||
} from "./internal/errors";
|
||||
|
||||
const DIMENSION_REGEX = /^\s*(\d+(\.\d+)?(%)?)/;
|
||||
|
||||
|
@ -668,41 +673,9 @@ export class RufflePlayer extends HTMLElement {
|
|||
this.onRuffleDownloadProgress.bind(this),
|
||||
).catch((e) => {
|
||||
console.error(`Serious error loading Ruffle: ${e}`);
|
||||
|
||||
// Serious duck typing. In error conditions, let's not make assumptions.
|
||||
if (window.location.protocol === "file:") {
|
||||
e.ruffleIndexError = PanicError.FileProtocol;
|
||||
} else {
|
||||
e.ruffleIndexError = PanicError.WasmNotFound;
|
||||
const message = String(e.message).toLowerCase();
|
||||
if (message.includes("mime")) {
|
||||
e.ruffleIndexError = PanicError.WasmMimeType;
|
||||
} else if (
|
||||
message.includes("networkerror") ||
|
||||
message.includes("failed to fetch")
|
||||
) {
|
||||
e.ruffleIndexError = PanicError.WasmCors;
|
||||
} else if (message.includes("disallowed by embedder")) {
|
||||
e.ruffleIndexError = PanicError.CSPConflict;
|
||||
} else if (e.name === "CompileError") {
|
||||
e.ruffleIndexError = PanicError.InvalidWasm;
|
||||
} else if (
|
||||
message.includes("could not download wasm module") &&
|
||||
e.name === "TypeError"
|
||||
) {
|
||||
e.ruffleIndexError = PanicError.WasmDownload;
|
||||
} else if (e.name === "TypeError") {
|
||||
e.ruffleIndexError = PanicError.JavascriptConflict;
|
||||
} else if (
|
||||
navigator.userAgent.includes("Edg") &&
|
||||
message.includes("webassembly is not defined")
|
||||
) {
|
||||
// Microsoft Edge detection.
|
||||
e.ruffleIndexError = PanicError.WasmDisabledMicrosoftEdge;
|
||||
}
|
||||
}
|
||||
this.panic(e);
|
||||
throw e;
|
||||
const error = new LoadRuffleWasmError(e);
|
||||
this.panic(error);
|
||||
throw error;
|
||||
});
|
||||
this.newZipWriter = zipWriterClass;
|
||||
configureBuilder(builder, this.loadedConfig || {});
|
||||
|
@ -878,8 +851,7 @@ export class RufflePlayer extends HTMLElement {
|
|||
message: string,
|
||||
) => asserts condition = (condition, message) => {
|
||||
if (!condition) {
|
||||
const error = new TypeError(message);
|
||||
error.ruffleIndexError = PanicError.JavascriptConfiguration;
|
||||
const error = new InvalidOptionsError(message);
|
||||
this.panic(error);
|
||||
throw error;
|
||||
}
|
||||
|
@ -1981,8 +1953,6 @@ export class RufflePlayer extends HTMLElement {
|
|||
return;
|
||||
}
|
||||
|
||||
const errorIndex = error?.ruffleIndexError ?? PanicError.Unknown;
|
||||
|
||||
const errorArray: Array<string | null> & {
|
||||
stackIndex: number;
|
||||
avmStackIndex: number;
|
||||
|
@ -2019,7 +1989,7 @@ export class RufflePlayer extends HTMLElement {
|
|||
errorArray.push(this.getPanicData());
|
||||
|
||||
// Clears out any existing content (ie play button or canvas) and replaces it with the error screen
|
||||
showPanicScreen(this.container, errorIndex, errorArray, this.swfUrl);
|
||||
showPanicScreen(this.container, error, errorArray, this.swfUrl);
|
||||
|
||||
// Do this last, just in case it causes any cascading issues.
|
||||
this.destroy();
|
||||
|
@ -2059,21 +2029,9 @@ export class RufflePlayer extends HTMLElement {
|
|||
div.appendChild(innerDiv);
|
||||
this.container.prepend(div);
|
||||
} else {
|
||||
const error = new Error("Failed to fetch: " + this.swfUrl);
|
||||
if (this.swfUrl && !this.swfUrl.protocol.includes("http")) {
|
||||
error.ruffleIndexError = PanicError.FileProtocol;
|
||||
} else if (invalidSwf) {
|
||||
error.ruffleIndexError = PanicError.InvalidSwf;
|
||||
} else if (
|
||||
window.location.origin === this.swfUrl?.origin ||
|
||||
// The extension's internal player page is not restricted by CORS
|
||||
window.location.protocol.includes("extension")
|
||||
) {
|
||||
error.ruffleIndexError = PanicError.SwfFetchError;
|
||||
} else {
|
||||
// This is a selfhosted build of Ruffle that tried to make a cross-origin request
|
||||
error.ruffleIndexError = PanicError.SwfCors;
|
||||
}
|
||||
const error = invalidSwf
|
||||
? new InvalidSwfError(this.swfUrl)
|
||||
: new LoadSwfError(this.swfUrl);
|
||||
this.panic(error);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue