Skip to content

Commit 639d5e0

Browse files
authored
feat: Add a crash handler to asc (AssemblyScript#1764)
1 parent de2845b commit 639d5e0

File tree

2 files changed

+118
-28
lines changed

2 files changed

+118
-28
lines changed

cli/asc.js

Lines changed: 114 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,6 @@
3333
const fs = require("fs");
3434
const path = require("path");
3535
const process = require("process"); // ensure shim
36-
37-
process.exit = ((exit) => function(code) {
38-
if (code) console.log(new Error("exit " + code.toString()).stack);
39-
exit(code);
40-
})(process.exit);
41-
4236
const utf8 = require("./util/utf8");
4337
const colorsUtil = require("./util/colors");
4438
const optionsUtil = require("./util/options");
@@ -795,7 +789,11 @@ exports.main = function main(argv, options, callback) {
795789
// Pre-emptively initialize the program
796790
stats.initializeCount++;
797791
stats.initializeTime += measure(() => {
798-
assemblyscript.initializeProgram(program);
792+
try {
793+
assemblyscript.initializeProgram(program);
794+
} catch (e) {
795+
crash("initialize", e);
796+
}
799797
});
800798

801799
// Call afterInitialize transform hook
@@ -807,7 +805,11 @@ exports.main = function main(argv, options, callback) {
807805
var module;
808806
stats.compileCount++;
809807
stats.compileTime += measure(() => {
810-
module = assemblyscript.compile(program);
808+
try {
809+
module = assemblyscript.compile(program);
810+
} catch (e) {
811+
crash("compile", e);
812+
}
811813
// From here on we are going to use Binaryen.js, except that we keep pass
812814
// order as defined in the compiler.
813815
if (typeof module === "number") { // Wasm
@@ -877,23 +879,50 @@ exports.main = function main(argv, options, callback) {
877879
}
878880
if (opts.runPasses.length) {
879881
opts.runPasses.forEach(pass => {
880-
if (runPasses.indexOf(pass = pass.trim()) < 0)
882+
if (runPasses.indexOf(pass = pass.trim()) < 0) {
881883
runPasses.push(pass);
884+
}
882885
});
883886
}
884887
}
885888

886889
stats.optimizeTime += measure(() => {
887890
stats.optimizeCount++;
888-
module.optimize(optimizeLevel, shrinkLevel, debugInfo);
889-
module.runPasses(runPasses);
891+
try {
892+
module.optimize(optimizeLevel, shrinkLevel, debugInfo);
893+
} catch (e) {
894+
crash("optimize", e);
895+
}
896+
try {
897+
module.runPasses(runPasses);
898+
} catch (e) {
899+
crash("runPasses", e);
900+
}
890901
if (converge) {
891-
let last = module.emitBinary();
902+
let last;
903+
try {
904+
last = module.emitBinary();
905+
} catch (e) {
906+
crash("emitBinary (converge)", e);
907+
}
892908
do {
893909
stats.optimizeCount++;
894-
module.optimize(optimizeLevel, shrinkLevel, debugInfo);
895-
module.runPasses(runPasses);
896-
let next = module.emitBinary();
910+
try {
911+
module.optimize(optimizeLevel, shrinkLevel, debugInfo);
912+
} catch (e) {
913+
crash("optimize (converge)", e);
914+
}
915+
try {
916+
module.runPasses(runPasses);
917+
} catch (e) {
918+
crash("runPasses (converge)", e);
919+
}
920+
let next;
921+
try {
922+
next = module.emitBinary();
923+
} catch (e) {
924+
crash("emitBinary (converge)", e);
925+
}
897926
if (next.length >= last.length) {
898927
if (next.length > last.length) {
899928
stderr.write("Last converge was suboptimial." + EOL);
@@ -936,7 +965,11 @@ exports.main = function main(argv, options, callback) {
936965
let wasm;
937966
stats.emitCount++;
938967
stats.emitTime += measure(() => {
939-
wasm = module.emitBinary(sourceMapURL);
968+
try {
969+
wasm = module.emitBinary(sourceMapURL);
970+
} catch (e) {
971+
crash("emitBinary", e);
972+
}
940973
});
941974

942975
if (opts.binaryFile.length) {
@@ -977,17 +1010,25 @@ exports.main = function main(argv, options, callback) {
9771010
let wastFormat = opts.textFile.endsWith('.wast');
9781011
stats.emitCount++;
9791012
stats.emitTime += measure(() => {
980-
if (wastFormat) {
981-
out = module.emitText();
982-
} else {
983-
out = module.emitStackIR(true);
1013+
try {
1014+
if (wastFormat) {
1015+
out = module.emitText();
1016+
} else {
1017+
out = module.emitStackIR(true);
1018+
}
1019+
} catch (e) {
1020+
crash("emitText", e);
9841021
}
9851022
});
9861023
writeFile(opts.textFile, out, baseDir);
9871024
} else if (!hasStdout) {
9881025
stats.emitCount++;
9891026
stats.emitTime += measure(() => {
990-
out = module.emitStackIR(true);
1027+
try {
1028+
out = module.emitStackIR(true);
1029+
} catch (e) {
1030+
crash("emitText", e);
1031+
}
9911032
});
9921033
writeStdout(out);
9931034
}
@@ -999,13 +1040,21 @@ exports.main = function main(argv, options, callback) {
9991040
if (opts.idlFile.length) {
10001041
stats.emitCount++;
10011042
stats.emitTime += measure(() => {
1002-
idl = assemblyscript.buildIDL(program);
1043+
try {
1044+
idl = assemblyscript.buildIDL(program);
1045+
} catch (e) {
1046+
crash("buildIDL", e);
1047+
}
10031048
});
10041049
writeFile(opts.idlFile, __getString(idl), baseDir);
10051050
} else if (!hasStdout) {
10061051
stats.emitCount++;
10071052
stats.emitTime += measure(() => {
1008-
idl = assemblyscript.buildIDL(program);
1053+
try {
1054+
idl = assemblyscript.buildIDL(program);
1055+
} catch (e) {
1056+
crash("buildIDL", e);
1057+
}
10091058
});
10101059
writeStdout(__getString(idl));
10111060
hasStdout = true;
@@ -1018,13 +1067,21 @@ exports.main = function main(argv, options, callback) {
10181067
if (opts.tsdFile.length) {
10191068
stats.emitCount++;
10201069
stats.emitTime += measure(() => {
1021-
tsd = assemblyscript.buildTSD(program);
1070+
try {
1071+
tsd = assemblyscript.buildTSD(program);
1072+
} catch (e) {
1073+
crash("buildTSD", e);
1074+
}
10221075
});
10231076
writeFile(opts.tsdFile, __getString(tsd), baseDir);
10241077
} else if (!hasStdout) {
10251078
stats.emitCount++;
10261079
stats.emitTime += measure(() => {
1027-
tsd = assemblyscript.buildTSD(program);
1080+
try {
1081+
tsd = assemblyscript.buildTSD(program);
1082+
} catch (e) {
1083+
crash("buildTSD", e);
1084+
}
10281085
});
10291086
writeStdout(__getString(tsd));
10301087
hasStdout = true;
@@ -1037,13 +1094,21 @@ exports.main = function main(argv, options, callback) {
10371094
if (opts.jsFile.length) {
10381095
stats.emitCount++;
10391096
stats.emitTime += measure(() => {
1040-
js = module.emitAsmjs();
1097+
try {
1098+
js = module.emitAsmjs();
1099+
} catch (e) {
1100+
crash("emitJS", e);
1101+
}
10411102
});
10421103
writeFile(opts.jsFile, js, baseDir);
10431104
} else if (!hasStdout) {
10441105
stats.emitCount++;
10451106
stats.emitTime += measure(() => {
1046-
js = module.emitAsmjs();
1107+
try {
1108+
js = module.emitAsmjs();
1109+
} catch (e) {
1110+
crash("emitJS", e);
1111+
}
10471112
});
10481113
writeStdout(js);
10491114
}
@@ -1332,3 +1397,25 @@ exports.tscOptions = {
13321397
types: [],
13331398
allowJs: false
13341399
};
1400+
1401+
// Gracefully handle crashes
1402+
function crash(stage, e) {
1403+
const BAR = colorsUtil.red("▌ ");
1404+
console.error([
1405+
EOL,
1406+
BAR, "Whoops, the AssemblyScript compiler has crashed during ", stage, " :-(", EOL,
1407+
BAR, EOL,
1408+
BAR, "Here is a stack trace that may or may not be useful:", EOL,
1409+
BAR, EOL,
1410+
e.stack.replace(/^/mg, BAR), EOL,
1411+
BAR, EOL,
1412+
BAR, "If it refers to the dist files, try to 'npm install source-map-support' and", EOL,
1413+
BAR, "run again, which should then show the actual code location in the sources.", EOL,
1414+
BAR, EOL,
1415+
BAR, "If you see where the error is, feel free to send us a pull request. If not,", EOL,
1416+
BAR, "please let us know: https://github.com/AssemblyScript/assemblyscript/issues", EOL,
1417+
BAR, EOL,
1418+
BAR, "Thank you!", EOL
1419+
].join(""));
1420+
process.exit(1);
1421+
}

cli/shim/process.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ module.exports = {
77
return 0;
88
},
99
hrtime,
10-
argv: []
10+
argv: [],
11+
exit(code = 0) {
12+
throw Error(`exit ${code}`);
13+
}
1114
};
1215

1316
// https://github.com/kumavis/browser-process-hrtime v1.0.0

0 commit comments

Comments
 (0)