From da20a5b4c404b10e0dd82a1538f6f1405cbcec58 Mon Sep 17 00:00:00 2001 From: pearmini Date: Sun, 12 Oct 2025 10:22:49 -0400 Subject: [PATCH 1/4] Optimize sytanx error from acorn --- runtime/index.js | 7 ++++++- test/js/index-tests.js | 1 + test/js/index.js | 1 + test/js/syntax-error3.js | 3 +++ test/output/syntaxError.js | 2 +- test/output/syntaxError3.js | 4 ++++ 6 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 test/js/syntax-error3.js create mode 100644 test/output/syntaxError3.js diff --git a/runtime/index.js b/runtime/index.js index 0653b60..4a65bca 100644 --- a/runtime/index.js +++ b/runtime/index.js @@ -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; } diff --git a/test/js/index-tests.js b/test/js/index-tests.js index f467995..7b1eee4 100644 --- a/test/js/index-tests.js +++ b/test/js/index-tests.js @@ -5,3 +5,4 @@ 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"; \ No newline at end of file diff --git a/test/js/index.js b/test/js/index.js index 69a728f..ae3fe9d 100644 --- a/test/js/index.js +++ b/test/js/index.js @@ -14,3 +14,4 @@ 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"; diff --git a/test/js/syntax-error3.js b/test/js/syntax-error3.js new file mode 100644 index 0000000..7f2435f --- /dev/null +++ b/test/js/syntax-error3.js @@ -0,0 +1,3 @@ +export const syntaxError3 = `function add(); + +echo(1 + 2);`; diff --git a/test/output/syntaxError.js b/test/output/syntaxError.js index 083805b..43a20a2 100644 --- a/test/output/syntaxError.js +++ b/test/output/syntaxError.js @@ -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); \ No newline at end of file diff --git a/test/output/syntaxError3.js b/test/output/syntaxError3.js new file mode 100644 index 0000000..4b7104a --- /dev/null +++ b/test/output/syntaxError3.js @@ -0,0 +1,4 @@ +//✗ { [SyntaxError: Unexpected token (1:14)] pos: 14, loc: Position { line: 1, column: 14 }, raisedAt: 15 } +function add(); + +echo(1 + 2); \ No newline at end of file From 8dc4c228c0ea65d9508e0915efd51688bebbb0c9 Mon Sep 17 00:00:00 2001 From: pearmini Date: Sun, 12 Oct 2025 10:25:27 -0400 Subject: [PATCH 2/4] Fix lint error --- test/js/index-tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/js/index-tests.js b/test/js/index-tests.js index 7b1eee4..f7f542a 100644 --- a/test/js/index-tests.js +++ b/test/js/index-tests.js @@ -5,4 +5,4 @@ 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"; \ No newline at end of file +export {syntaxError3} from "./syntax-error3.js"; From 1f5300278f395b292bf10daa4b4ff2a063e46bc1 Mon Sep 17 00:00:00 2001 From: pearmini Date: Sun, 12 Oct 2025 10:38:38 -0400 Subject: [PATCH 3/4] Optimize error messages in blocks --- editor/outputLines.js | 8 +++++++- test/js/index-tests.js | 1 + test/js/index.js | 1 + test/js/syntax-error4.js | 5 +++++ test/output/syntaxError4.js | 6 ++++++ 5 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 test/js/syntax-error4.js create mode 100644 test/output/syntaxError4.js diff --git a/editor/outputLines.js b/editor/outputLines.js index 2e99584..c9913a6 100644 --- a/editor/outputLines.js +++ b/editor/outputLines.js @@ -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({ @@ -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, diff --git a/test/js/index-tests.js b/test/js/index-tests.js index f7f542a..a6fc531 100644 --- a/test/js/index-tests.js +++ b/test/js/index-tests.js @@ -6,3 +6,4 @@ 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"; diff --git a/test/js/index.js b/test/js/index.js index ae3fe9d..13fd5a6 100644 --- a/test/js/index.js +++ b/test/js/index.js @@ -15,3 +15,4 @@ 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"; diff --git a/test/js/syntax-error4.js b/test/js/syntax-error4.js new file mode 100644 index 0000000..5446efb --- /dev/null +++ b/test/js/syntax-error4.js @@ -0,0 +1,5 @@ +export const syntaxError4 = `{ + const 1a = 1; +} + +echo(1 + 2);`; diff --git a/test/output/syntaxError4.js b/test/output/syntaxError4.js new file mode 100644 index 0000000..1d74747 --- /dev/null +++ b/test/output/syntaxError4.js @@ -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); \ No newline at end of file From c46a78297d64cecd2b8eccac962bd7758b8b0785 Mon Sep 17 00:00:00 2001 From: pearmini Date: Sun, 12 Oct 2025 10:43:15 -0400 Subject: [PATCH 4/4] Update docs --- app/docs/errors-handling.recho.js | 5 +++-- app/docs/getting-started.recho.js | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/docs/errors-handling.recho.js b/app/docs/errors-handling.recho.js index ea2ddfc..8c72636 100644 --- a/app/docs/errors-handling.recho.js +++ b/app/docs/errors-handling.recho.js @@ -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. diff --git a/app/docs/getting-started.recho.js b/app/docs/getting-started.recho.js index 3a84ea9..b1323f7 100644 --- a/app/docs/getting-started.recho.js +++ b/app/docs/getting-started.recho.js @@ -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 @@ -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" }