Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions app/docs/errors-handling.recho.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
* Errors are echoed as normal output. There are two types of errors in Recho:
* syntax errors and runtime errors.
*
* For syntax errors, they will be positioned at the beginning of the notebook.
* The notebook will not run until the syntax error is fixed.
* For syntax errors, they will be positioned at the start of the line where
* the error occurred.The notebook will not run until the syntax error is
* fixed.
*
* You can fix the following syntax error by removing the prefix `1` for the
* variable name, then click the ▶️ button.
Expand Down
8 changes: 4 additions & 4 deletions app/docs/getting-started.recho.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ echo(counter);
const showDetails = recho.toggle(true);

//➜ "Details: Enabled"
echo(`Details: ${showDetails ? 'Enabled' : 'Disabled'}`);
echo(`Details: ${showDetails ? "Enabled" : "Disabled"}`);

/**
* The `recho.radio` function creates a radio button group for selecting from
Expand Down Expand Up @@ -253,9 +253,9 @@ echo(d3.range(10));
* Errors Handling
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Errors are echoed as normal output. For syntax errors, they will be
* positioned at the beginning of the notebook. For runtime errors, they will
* be positioned above the block that caused the error.
* Errors are echoed as normal output. For syntax errors, they will be positioned
* at the start of the line where the error occurred. For runtime errors, they
* will be positioned above the block that caused the error.
*/

//➜ { [TypeError: Assignment to constant variable.] [Symbol(next.console.error.digest)]: "NEXT_CONSOLE_ERROR" }
Expand Down
8 changes: 7 additions & 1 deletion editor/outputLines.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ function computeLineNumbers(state) {
enter: (node) => {
// Find top-level single-line comments.
if (node.name === "LineComment" && node.node.parent.name === "Script") {
// Check if the line comment covers the entire line.
const line = state.doc.lineAt(node.from);
// Check if the line comment covers the entire line.
if (line.from !== node.from || line.to !== node.to) return;
if (line.text.codePointAt(2) === OUTPUT_MARK_CODE_POINT) {
lineNumbers.push({
Expand All @@ -36,6 +36,12 @@ function computeLineNumbers(state) {
type: "output",
});
}
}

// For error messages, it's Ok if the line is not top-level.
if (node.name === "LineComment") {
const line = state.doc.lineAt(node.from);
if (line.from !== node.from || line.to !== node.to) return;
if (line.text.codePointAt(2) === ERROR_MARK_CODE_POINT) {
lineNumbers.push({
number: line.number,
Expand Down
7 changes: 6 additions & 1 deletion runtime/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,14 @@ export function createRuntime(initialCode) {
return parse(code, {ecmaVersion: "latest", sourceType: "module"}).body;
} catch (error) {
console.error(error);
// Display the error at the start of the line where the error occurred.
const loc = error.loc;
const prevLine = code.split("\n").slice(0, loc.line - 1);
const offset = loc.line === 1 ? 0 : 1;
const from = prevLine.join("\n").length + offset;
const changes = removeChanges(code);
const errorMsg = formatError(error) + "\n";
changes.push({from: 0, insert: errorMsg});
changes.push({from, insert: errorMsg});
dispatch(changes);
return null;
}
Expand Down
2 changes: 2 additions & 0 deletions test/js/index-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ export {mandelbrotSet} from "./mandelbrot-set.js";
export {syntaxError} from "./syntax-error.js";
export {runtimeError} from "./runtime-error.js";
export {syntaxError2} from "./syntax-error2.js";
export {syntaxError3} from "./syntax-error3.js";
export {syntaxError4} from "./syntax-error4.js";
2 changes: 2 additions & 0 deletions test/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ export {mandelbrotSet} from "./mandelbrot-set.js";
export {matrixRain} from "./matrix-rain.js";
export {jsDocString} from "./js-doc-string.js";
export {commentLink} from "./comment-link.js";
export {syntaxError3} from "./syntax-error3.js";
export {syntaxError4} from "./syntax-error4.js";
3 changes: 3 additions & 0 deletions test/js/syntax-error3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const syntaxError3 = `function add();

echo(1 + 2);`;
5 changes: 5 additions & 0 deletions test/js/syntax-error4.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const syntaxError4 = `{
const 1a = 1;
}

echo(1 + 2);`;
2 changes: 1 addition & 1 deletion test/output/syntaxError.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//✗ { [SyntaxError: Unexpected token (3:14)] pos: 28, loc: Position { line: 3, column: 14 }, raisedAt: 29 }
const a = 1;

//✗ { [SyntaxError: Unexpected token (3:14)] pos: 28, loc: Position { line: 3, column: 14 }, raisedAt: 29 }
function add();

echo(1 + 2);
4 changes: 4 additions & 0 deletions test/output/syntaxError3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//✗ { [SyntaxError: Unexpected token (1:14)] pos: 14, loc: Position { line: 1, column: 14 }, raisedAt: 15 }
function add();

echo(1 + 2);
6 changes: 6 additions & 0 deletions test/output/syntaxError4.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
//✗ { [SyntaxError: Identifier directly after number (2:9)] pos: 11, loc: Position { line: 2, column: 9 }, raisedAt: 11 }
const 1a = 1;
}

echo(1 + 2);