Skip to content

Commit

Permalink
fix(parser): uncaught mismatch between JSX opening/closing tags (#14528)
Browse files Browse the repository at this point in the history
  • Loading branch information
DonIsaac authored Oct 13, 2024
1 parent 6b8fd71 commit 09b031d
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 2 deletions.
6 changes: 4 additions & 2 deletions src/js_parser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,8 @@ const JSXTag = struct {
};
data: Data,
range: logger.Range,
name: string = "",
/// Empty string for fragments.
name: string,

pub fn parse(comptime P: type, p: *P) anyerror!JSXTag {
const loc = p.lexer.loc();
Expand Down Expand Up @@ -559,6 +560,7 @@ const JSXTag = struct {
.data = name,
}, loc) },
.range = tag_range,
.name = name,
};
}

Expand Down Expand Up @@ -15778,7 +15780,7 @@ fn NewParser_(
const end_tag = try JSXTag.parse(P, p);

if (!strings.eql(end_tag.name, tag.name)) {
try p.log.addRangeErrorFmt(p.source, end_tag.range, p.allocator, "Expected closing tag \\</{s}> to match opening tag \\<{s}>", .{
try p.log.addRangeErrorFmt(p.source, end_tag.range, p.allocator, "Expected closing tag \\</{s}\\> to match opening tag \\<{s}\\>", .{
end_tag.name,
tag.name,
});
Expand Down
23 changes: 23 additions & 0 deletions test/regression/issue/14477/14477.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { expect, test } from "bun:test";
import { bunEnv, bunExe } from "harness";
import { join } from "path";
import fs from "fs";

test("JSXElement with mismatched closing tags produces a syntax error", async () => {
const files = await fs.promises.readdir(import.meta.dir);
const fixtures = files.filter(file => !file.endsWith(".test.ts")).map(fixture => join(import.meta.dir, fixture));

const bakery = fixtures.map(
fixture =>
Bun.spawn({
cmd: [bunExe(), fixture],
cwd: import.meta.dir,
stdio: ["inherit", "inherit", "inherit"],
env: bunEnv,
}).exited,
);

// all subprocesses should fail.
const exited = await Promise.all(bakery);
expect(exited).toEqual(Array.from({ length: fixtures.length }, () => 1));
});
1 change: 1 addition & 0 deletions test/regression/issue/14477/builtin-mismatch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log(<div></p>);
2 changes: 2 additions & 0 deletions test/regression/issue/14477/component-mismatch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

console.log(<Foo></Bar>);
3 changes: 3 additions & 0 deletions test/regression/issue/14477/non-identifier-mismatch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// mismatch where openening tag is not a valid IdentifierName, but is a valid
// JSXIdentifierName
console.log(<div-:button></p>);

0 comments on commit 09b031d

Please sign in to comment.