improve error handling

This commit is contained in:
d07riv
2019-08-18 03:33:36 +03:00
parent d922765878
commit 7cbd7b0ea9
6 changed files with 43 additions and 21 deletions

2
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "diabloweb",
"version": "1.0.34",
"version": "1.0.35",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -1,6 +1,6 @@
{
"name": "diabloweb",
"version": "1.0.34",
"version": "1.0.35",
"private": true,
"dependencies": {
"@babel/core": "7.4.3",

View File

@@ -155,13 +155,19 @@ class App extends React.Component {
}
onError(message, stack) {
if (stack) {
mapStackTrace(stack, stack => {
this.setState(({error}) => !error && {error: {message, stack: stack.join("\n")}});
});
} else {
this.setState(({error}) => !error && {error: {message}});
}
(async () => {
const errorObject = {message};
if (this.saveName) {
errorObject.save = await (await this.fs).fileUrl(this.saveName);
}
if (stack) {
mapStackTrace(stack, stack => {
this.setState(({error}) => !error && {error: {...errorObject, stack: stack.join("\n")}});
});
} else {
this.setState(({error}) => !error && {error: errorObject});
}
})();
}
openKeyboard(rect) {
@@ -641,7 +647,7 @@ class App extends React.Component {
<p className="header">The following error has occurred:</p>
<p className="body">{error.message}</p>
<p className="footer">Click to create an issue on GitHub</p>
{this.saveName != null && <p className="link" onClick={this.downloadSave}>Download save file</p>}
{error.save != null && <a href={error.save} download={this.saveName}>Download save file</a>}
</Link>
)}
{!!loading && !started && !error && (

View File

@@ -20,6 +20,14 @@ let drawBelt = null;
let is_spawn = false;
let websocket = null;
function onError(err, action="error") {
if (err instanceof Error) {
worker.postMessage({action, error: err.toString(), stack: err.stack});
} else {
worker.postMessage({action, error: err.toString()});
}
}
const ChunkSize = 1 << 20;
class RemoteFile {
constructor(url) {
@@ -27,7 +35,7 @@ class RemoteFile {
request.open('HEAD', url, false);
request.send();
if (request.status < 200 || request.status >= 300) {
worker.postMessage({action: "error", error: `Failed to load remote file`});
throw Error('Failed to load remote file');
}
this.byteLength = parseInt(request.getResponseHeader('Content-Length'));
@@ -54,7 +62,7 @@ class RemoteFile {
request.responseType = 'arraybuffer';
request.send();
if (request.status < 200 || request.status >= 300) {
worker.postMessage({action: "error", error: `Failed to load remote file`});
throw Error('Failed to load remote file');
} else {
const header = request.getResponseHeader('Content-Range');
let m, start = 0;
@@ -75,7 +83,7 @@ class RemoteFile {
const DApi = {
exit_error(error) {
worker.postMessage({action: "error", error});
throw Error(error);
},
exit_game() {
@@ -131,10 +139,10 @@ const DApi = {
}
}, code => {
if (typeof code !== "number") {
worker.postMessage({action: "error", error: code.toString(), stack: code.stack});
code = 3;
throw code;
} else {
call_api("SNet_WebsocketStatus", code);
}
call_api("SNet_WebsocketStatus", code);
});
} else {
call_api("SNet_WebsocketStatus", 0);
@@ -150,7 +158,7 @@ const DApi = {
return websocket ? websocket.readyState !== 1 : false;
},
};
/*
let frameTime = 0, lastTime = 0;
function getFPS() {
const time = performance.now();
@@ -161,7 +169,7 @@ function getFPS() {
lastTime = time;
return frameTime ? 1000.0 / frameTime : 0.0;
}
*/
const DApi_renderLegacy = {
draw_begin() {
renderBatch = {
@@ -281,7 +289,7 @@ function try_api(func) {
try {
func();
} catch (e) {
worker.postMessage({action: "error", error: e.toString(), stack: e.stack});
onError(e);
}
}
@@ -409,7 +417,7 @@ worker.addEventListener("message", ({data}) => {
files = data.files;
init_game(data.mpq, data.spawn, data.offscreen).then(
() => worker.postMessage({action: "loaded"}),
e => worker.postMessage({action: "failed", error: e.toString(), stack: e.stack}));
e => onError(e, "failed"));
break;
case "event":
call_api(data.func, ...data.params);

View File

@@ -102,7 +102,7 @@ async function do_load_game(api, audio, mpq, spawn) {
api.onError(data.error, data.stack);
break;
case "failed":
reject(Error(data.stack || data.error));
reject({message: data.error, stack: data.stack});
break;
case "progress":
api.onProgress({text: data.text, loaded: data.loaded, total: data.total});

View File

@@ -93,6 +93,13 @@ export default async function create_fs(load) {
clear: () => store.clear(),
download: name => downloadFile(store, name),
upload: file => uploadFile(store, files, file),
fileUrl: async name => {
const file = await store.get(name.toLowerCase());
if (file) {
const blob = new Blob([file], {type: 'binary/octet-stream'});
return URL.createObjectURL(blob);
}
},
};
} catch (e) {
window.DownloadFile = () => console.error('IndexedDB is not supported');
@@ -104,6 +111,7 @@ export default async function create_fs(load) {
clear: () => Promise.resolve(),
download: () => Promise.resolve(),
upload: () => Promise.resolve(),
fileUrl: () => Promise.resolve(),
};
}
}