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 = hi;\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 = hi;\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();