1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-22 15:24:46 -05:00

refactor(core/error): use evaluated call sites for formatting (#15369)

This commit is contained in:
Nayeem Rahman 2022-08-01 16:17:55 +01:00 committed by GitHub
parent 03377ca1d2
commit 96290f1a66
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 49 additions and 136 deletions

View file

@ -17,6 +17,7 @@
Promise,
ObjectFromEntries,
MapPrototypeGet,
MapPrototypeHas,
MapPrototypeDelete,
MapPrototypeSet,
PromisePrototypeThen,

View file

@ -15,156 +15,81 @@
ArrayPrototypeJoin,
} = window.__bootstrap.primordials;
// Some of the code here is adapted directly from V8 and licensed under a BSD
// style license available here: https://github.com/v8/v8/blob/24886f2d1c565287d33d71e4109a53bf0b54b75c/LICENSE.v8
function patchCallSite(callSite, location) {
return {
getThis() {
return callSite.getThis();
},
getTypeName() {
return callSite.getTypeName();
},
getFunction() {
return callSite.getFunction();
},
getFunctionName() {
return callSite.getFunctionName();
},
getMethodName() {
return callSite.getMethodName();
},
getFileName() {
return location.fileName;
},
getLineNumber() {
return location.lineNumber;
},
getColumnNumber() {
return location.columnNumber;
},
getEvalOrigin() {
return callSite.getEvalOrigin();
},
isToplevel() {
return callSite.isToplevel();
},
isEval() {
return callSite.isEval();
},
isNative() {
return callSite.isNative();
},
isConstructor() {
return callSite.isConstructor();
},
isAsync() {
return callSite.isAsync();
},
isPromiseAll() {
return callSite.isPromiseAll();
},
getPromiseIndex() {
return callSite.getPromiseIndex();
},
};
}
// Keep in sync with `cli/fmt_errors.rs`.
function formatLocation(callSite) {
if (callSite.isNative()) {
function formatLocation(cse) {
if (cse.isNative) {
return "native";
}
let result = "";
const fileName = callSite.getFileName();
if (fileName) {
result += core.opSync("op_format_file_name", fileName);
if (cse.fileName) {
result += core.opSync("op_format_file_name", cse.fileName);
} else {
if (callSite.isEval()) {
const evalOrigin = callSite.getEvalOrigin();
if (evalOrigin == null) {
if (cse.isEval) {
if (cse.evalOrigin == null) {
throw new Error("assert evalOrigin");
}
result += `${evalOrigin}, `;
result += `${cse.evalOrigin}, `;
}
result += "<anonymous>";
}
const lineNumber = callSite.getLineNumber();
if (lineNumber != null) {
result += `:${lineNumber}`;
const columnNumber = callSite.getColumnNumber();
if (columnNumber != null) {
result += `:${columnNumber}`;
if (cse.lineNumber != null) {
result += `:${cse.lineNumber}`;
if (cse.columnNumber != null) {
result += `:${cse.columnNumber}`;
}
}
return result;
}
// Keep in sync with `cli/fmt_errors.rs`.
function formatCallSite(callSite) {
function formatCallSiteEval(cse) {
let result = "";
const functionName = callSite.getFunctionName();
const isTopLevel = callSite.isToplevel();
const isAsync = callSite.isAsync();
const isPromiseAll = callSite.isPromiseAll();
const isConstructor = callSite.isConstructor();
const isMethodCall = !(isTopLevel || isConstructor);
if (isAsync) {
if (cse.isAsync) {
result += "async ";
}
if (isPromiseAll) {
result += `Promise.all (index ${callSite.getPromiseIndex()})`;
if (cse.isPromiseAll) {
result += `Promise.all (index ${cse.promiseIndex})`;
return result;
}
const isMethodCall = !(cse.isToplevel || cse.isConstructor);
if (isMethodCall) {
const typeName = callSite.getTypeName();
const methodName = callSite.getMethodName();
if (functionName) {
if (typeName) {
if (!StringPrototypeStartsWith(functionName, typeName)) {
result += `${typeName}.`;
if (cse.functionName) {
if (cse.typeName) {
if (!StringPrototypeStartsWith(cse.functionName, cse.typeName)) {
result += `${cse.typeName}.`;
}
}
result += functionName;
if (methodName) {
if (!StringPrototypeEndsWith(functionName, methodName)) {
result += ` [as ${methodName}]`;
result += cse.functionName;
if (cse.methodName) {
if (!StringPrototypeEndsWith(cse.functionName, cse.methodName)) {
result += ` [as ${cse.methodName}]`;
}
}
} else {
if (typeName) {
result += `${typeName}.`;
if (cse.typeName) {
result += `${cse.typeName}.`;
}
if (methodName) {
result += methodName;
if (cse.methodName) {
result += cse.methodName;
} else {
result += "<anonymous>";
}
}
} else if (isConstructor) {
} else if (cse.isConstructor) {
result += "new ";
if (functionName) {
result += functionName;
if (cse.functionName) {
result += cse.functionName;
} else {
result += "<anonymous>";
}
} else if (functionName) {
result += functionName;
} else if (cse.functionName) {
result += cse.functionName;
} else {
result += formatLocation(callSite);
result += formatLocation(cse);
return result;
}
result += ` (${formatLocation(callSite)})`;
result += ` (${formatLocation(cse)})`;
return result;
}
@ -189,37 +114,24 @@
};
}
function sourceMapCallSiteEval(cse) {
if (cse.fileName && cse.lineNumber != null && cse.columnNumber != null) {
return { ...cse, ...core.opSync("op_apply_source_map", cse) };
}
return cse;
}
/** A function that can be used as `Error.prepareStackTrace`. */
function prepareStackTrace(
error,
callSites,
) {
const mappedCallSites = ArrayPrototypeMap(callSites, (callSite) => {
const fileName = callSite.getFileName();
const lineNumber = callSite.getLineNumber();
const columnNumber = callSite.getColumnNumber();
if (fileName && lineNumber != null && columnNumber != null) {
return patchCallSite(
callSite,
core.opSync("op_apply_source_map", {
fileName,
lineNumber,
columnNumber,
}),
);
}
return callSite;
});
function prepareStackTrace(error, callSites) {
let callSiteEvals = ArrayPrototypeMap(callSites, evaluateCallSite);
callSiteEvals = ArrayPrototypeMap(callSiteEvals, sourceMapCallSiteEval);
ObjectDefineProperties(error, {
__callSiteEvals: { value: [], configurable: true },
});
const formattedCallSites = [];
for (const callSite of mappedCallSites) {
ArrayPrototypePush(error.__callSiteEvals, evaluateCallSite(callSite));
ArrayPrototypePush(
formattedCallSites,
formatCallSite(callSite),
);
for (const cse of callSiteEvals) {
ArrayPrototypePush(error.__callSiteEvals, cse);
ArrayPrototypePush(formattedCallSites, formatCallSiteEval(cse));
}
const message = error.message !== undefined ? error.message : "";
const name = error.name !== undefined ? error.name : "Error";