forked from sashin/sashinexists
run npm install to generate a package lock
This commit is contained in:
104
node_modules/@weborigami/language/src/runtime/errors.js
generated
vendored
Normal file
104
node_modules/@weborigami/language/src/runtime/errors.js
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
// Text we look for in an error stack to guess whether a given line represents a
|
||||
|
||||
import { scope as scopeFn, trailingSlash } from "@weborigami/async-tree";
|
||||
import codeFragment from "./codeFragment.js";
|
||||
import { typos } from "./typos.js";
|
||||
|
||||
// function in the Origami source code.
|
||||
const origamiSourceSignals = [
|
||||
"async-tree/src/",
|
||||
"language/src/",
|
||||
"origami/src/",
|
||||
"at Scope.evaluate",
|
||||
];
|
||||
|
||||
export async function builtinReferenceError(tree, builtins, key) {
|
||||
const messages = [
|
||||
`"${key}" is being called as if it were a builtin function, but it's not.`,
|
||||
];
|
||||
// See if the key is in scope (but not as a builtin)
|
||||
const scope = scopeFn(tree);
|
||||
const value = await scope.get(key);
|
||||
if (value === undefined) {
|
||||
const typos = await formatScopeTypos(builtins, key);
|
||||
messages.push(typos);
|
||||
} else {
|
||||
messages.push(`Use "${key}/" instead.`);
|
||||
}
|
||||
const message = messages.join(" ");
|
||||
return new ReferenceError(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format an error for display in the console.
|
||||
*
|
||||
* @param {Error} error
|
||||
*/
|
||||
export function formatError(error) {
|
||||
let message;
|
||||
if (error.stack) {
|
||||
// Display the stack only until we reach the Origami source code.
|
||||
message = "";
|
||||
let lines = error.stack.split("\n");
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
if (maybeOrigamiSourceCode(line)) {
|
||||
break;
|
||||
}
|
||||
if (message) {
|
||||
message += "\n";
|
||||
}
|
||||
message += lines[i];
|
||||
}
|
||||
} else {
|
||||
message = error.toString();
|
||||
}
|
||||
|
||||
// Add location
|
||||
let location = /** @type {any} */ (error).location;
|
||||
if (location) {
|
||||
const fragment = codeFragment(location);
|
||||
let { source, start } = location;
|
||||
|
||||
message += `\nevaluating: ${fragment}`;
|
||||
if (typeof source === "object" && source.url) {
|
||||
message += `\n at ${source.url.href}:${start.line}:${start.column}`;
|
||||
} else if (source.text.includes("\n")) {
|
||||
message += `\n at line ${start.line}, column ${start.column}`;
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
export async function formatScopeTypos(scope, key) {
|
||||
const keys = await scopeTypos(scope, key);
|
||||
// Don't match deprecated keys
|
||||
const filtered = keys.filter((key) => !key.startsWith("@"));
|
||||
if (filtered.length === 0) {
|
||||
return "";
|
||||
}
|
||||
const quoted = filtered.map((key) => `"${key}"`);
|
||||
const list = quoted.join(", ");
|
||||
return `Maybe you meant ${list}?`;
|
||||
}
|
||||
|
||||
export function maybeOrigamiSourceCode(text) {
|
||||
return origamiSourceSignals.some((signal) => text.includes(signal));
|
||||
}
|
||||
|
||||
export async function scopeReferenceError(scope, key) {
|
||||
const messages = [
|
||||
`"${key}" is not in scope.`,
|
||||
await formatScopeTypos(scope, key),
|
||||
];
|
||||
const message = messages.join(" ");
|
||||
return new ReferenceError(message);
|
||||
}
|
||||
|
||||
// Return all possible typos for `key` in scope
|
||||
async function scopeTypos(scope, key) {
|
||||
const scopeKeys = [...(await scope.keys())];
|
||||
const normalizedScopeKeys = scopeKeys.map((key) => trailingSlash.remove(key));
|
||||
const normalizedKey = trailingSlash.remove(key);
|
||||
return typos(normalizedKey, normalizedScopeKeys);
|
||||
}
|
||||
Reference in New Issue
Block a user