Skip to content

Commit

Permalink
Merge pull request #161 from kaitai-io/better-import-errors
Browse files Browse the repository at this point in the history
Better error messages when importing an unavailable .ksy
  • Loading branch information
generalmimon authored Jan 21, 2024
2 parents 44e8329 + 7338f1b commit 7dc1e11
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 12 deletions.
4 changes: 2 additions & 2 deletions lib/ts-types/localForage.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ interface LocalForageOptions {
}

interface LocalForageDbMethods {
getItem<T>(key: string): Promise<T>;
getItem<T>(key: string, callback: (err: any, value: T) => void): void;
getItem<T>(key: string): Promise<T | null>;
getItem<T>(key: string, callback: (err: any, value: T | null) => void): void;

setItem<T>(key: string, value: T): Promise<T>;
setItem<T>(key: string, value: T, callback: (err: any, value: T) => void): void;
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 21 additions & 2 deletions src/v1/KaitaiServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,27 @@ class JsImporter implements IYamlImporter {
}

console.log(`import yaml: ${name}, mode: ${mode}, loadFn: ${loadFn}, root:`, this.rootFsItem);
let ksyContent = await fss[importedFsType].get(`${loadFn}.ksy`);
var ksyModel = <KsySchema.IKsyFile>YAML.parse(<string>ksyContent);
const fn = `${loadFn}.ksy`;
const sourceAppendix = mode === 'abs' ? 'kaitai.io' : 'local storage';
let ksyContent;
try {
ksyContent = await fss[importedFsType].get(`${loadFn}.ksy`);
} catch (e) {
const error = new Error(`failed to import spec ${fn} from ${sourceAppendix}${e.message ? ': ' + e.message : ''}`);

// The default implementation of the Error.prototype.toString() method gives
// "Error: {message}", see
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/toString#description
// However, the error we're throwing here goes directly into the KSC code,
// which will add its own `error: ` prefix (as the severity of the problem),
// so the resulting message would contain `error: Error: ...`. By overriding
// toString() to omit the `Error: ` part, we can make the message a bit nicer.
error.toString = function () {
return this.message;
};
throw error;
}
const ksyModel = <KsySchema.IKsyFile>YAML.parse(<string>ksyContent);
return ksyModel;
}
}
Expand Down
30 changes: 28 additions & 2 deletions src/v1/app.files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,15 @@ class LocalStorageFs implements IFileSystem {
return this.save();
}

get(fn: string): Promise<string | ArrayBuffer> { return localforage.getItem<string|ArrayBuffer>(this.fileKey(fn)); }
get(fn: string): Promise<string | ArrayBuffer> {
return localforage.getItem<string | ArrayBuffer>(this.fileKey(fn))
.then(content => {
if (content === null) {
throw new Error('file not found');
}
return content;
});
}

put(fn: string, data: any): Promise<IFsItem> {
return this.getRootNode().then(root => {
Expand All @@ -84,7 +92,25 @@ class KaitaiFs implements IFileSystem {

get(fn: string): Promise<string|ArrayBuffer> {
if (fn.toLowerCase().endsWith(".ksy"))
return Promise.resolve<string>(<any>$.ajax({ url: fn }));
return fetch(fn)
.then(response => {
if (!response.ok) {
let msg;
if (response.status === 404) {
msg = 'file not found';
} else {
const textAppendix = response.statusText ? ` (${response.statusText})` : '';
msg = `server responded with HTTP status ${response.status}${textAppendix}`;
}
throw new Error(msg);
}
return response.text();
}, err => {
if (err instanceof TypeError) {
throw new Error(`cannot reach the server (message: ${err.message}), check your internet connection`);
}
throw err;
});
else
return downloadFile(fn);
}
Expand Down
5 changes: 3 additions & 2 deletions src/v1/app.layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ export class UI {
this.layout.addEditor("genCodeDebugViewer", "javascript", false);
this.layout.addComponent("hexViewer", () => {
var hexViewer = new HexViewer("#hexViewer");
hexViewer.bytesPerLine = parseInt(localStorage.getItem("HexViewer.bytesPerLine")) || 16;
const stored = localStorage.getItem("HexViewer.bytesPerLine");
hexViewer.bytesPerLine = (stored !== null && parseInt(stored, 10)) || 16;
return hexViewer;
});
this.layout.addComponent("errorWindow", cont => { cont.getElement().append($("<div />")); });
Expand All @@ -132,4 +133,4 @@ export class UI {
}

init() { this.layout.layout.init(); }
}
}
3 changes: 2 additions & 1 deletion src/v1/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,8 @@ $(() => {
app.formatReady = loadCachedFsItem(app.ksyFsItemName, "kaitai", "formats/archive/zip.ksy");

app.inputReady.then(() => {
var storedSelection = JSON.parse(localStorage.getItem("selection"));
const value = localStorage.getItem("selection");
const storedSelection = value !== null ? JSON.parse(value) : null;
if (storedSelection)
app.ui.hexViewer.setSelection(storedSelection.start, storedSelection.end);
});
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"alwaysStrict": true,
// "strictNullChecks": true,
"sourceMap": false,
"target": "es2017",
"outDir": "js/",
Expand Down

0 comments on commit 7dc1e11

Please sign in to comment.