diff --git a/README.md b/README.md index 4a54b80..92c3b1b 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,14 @@ console.log(ast.type); // "File" console.log(ast.program.body.length); // 2 — ImportDeclaration + ClassDeclaration ``` +Script syntax errors do not throw. oxc-parser reports them on `ast.errors`, and on an unrecoverable error it returns an empty `program.body`; check `ast.errors` to tell that apart from an empty file. + +```js +let ast = toTree(`let planets = []);`); +ast.program.body.length; // 0 +ast.errors.length; // 1 +``` + `parse` is a lower-level alternative that returns the `Program` node directly. ```js diff --git a/src/index.d.ts b/src/index.d.ts index f5e62f8..31961f5 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -10,10 +10,22 @@ export interface ASTNode { [key: string]: unknown; } +export interface ParseError { + message: string; + severity?: string; + [key: string]: unknown; +} + export interface FileNode extends ASTNode { type: "File"; program: ASTNode; comments: ASTNode[]; + /** + * Diagnostics from the JS/TS parser (oxc-parser on the default path). On an + * unrecoverable script error oxc returns an empty `program.body`; check + * this to tell that apart from an empty file. + */ + errors: ParseError[]; } export interface TemplateResult { diff --git a/src/parse.js b/src/parse.js index 4ce476c..312d5e1 100644 --- a/src/parse.js +++ b/src/parse.js @@ -115,6 +115,10 @@ export function toTree(source, options = {}) { type: "File", program: oxcResult.program, comments: oxcResult.comments || [], + // oxc's diagnostics for the script. On an unrecoverable error oxc + // returns an empty `program.body`; this is how callers tell that apart + // from an empty file. + errors: oxcResult.errors || [], start: oxcResult.program.start, end: oxcResult.program.end, }, diff --git a/tests/toTree-options.test.js b/tests/toTree-options.test.js index cbaa24a..bd362d6 100644 --- a/tests/toTree-options.test.js +++ b/tests/toTree-options.test.js @@ -76,6 +76,22 @@ describe("glimmerVisitorKeys", () => { }); }); +describe("toTree — script errors", () => { + it("reports oxc diagnostics on ast.errors", () => { + const ast = toTree("let planets = []);\nconst a = ;\n"); + expect(ast.errors.length).toBeGreaterThan(0); + expect(ast.errors[0].message).toMatch(/semicolon/i); + // oxc gives up on the whole program for this one. + expect(ast.program.body).toEqual([]); + }); + + it("has no errors for a valid file", () => { + const ast = toTree("const a = ;\n"); + expect(ast.errors).toEqual([]); + expect(ast.program.body).toHaveLength(1); + }); +}); + describe("toTree — error handling", () => { it("throws on invalid JS with a content-tag parse error", () => { expect(() => toTree("console.log('unterminated")).toThrow();