Compare commits

...

1 Commits

Author SHA1 Message Date
Claude Bot
7fc6bdaa1d fix(parser): emit SyntaxError for 'use strict' in functions with non-simple params
The parser was consuming 'use strict' directives without emitting them
as .s_directive AST nodes, which prevented fnBodyContainsUseStrict from
finding them during validation. This made the existing spec compliance
check in visitArgs dead code.

Now 'use strict' is emitted as an .s_directive (like other directives)
while still setting the scope's strict mode flag, enabling the existing
validation to correctly report SyntaxError per ES spec Section 15.2.1.

Closes #18333

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-19 09:41:12 +00:00
2 changed files with 115 additions and 1 deletions

View File

@@ -1192,11 +1192,15 @@ pub fn Parse(
isDirectivePrologue = true;
if (str.eqlComptime("use strict")) {
skip = true;
// Track "use strict" directives
p.current_scope.strict_mode = .explicit_strict_mode;
if (p.current_scope == p.module_scope)
p.module_scope_directive_loc = stmt.loc;
// Emit as .s_directive so fnBodyContainsUseStrict can
// find it and report errors for non-simple parameter lists
stmt = Stmt.alloc(S.Directive, S.Directive{
.value = str.slice(p.allocator),
}, stmt.loc);
} else if (str.eqlComptime("use asm")) {
skip = true;
stmt.data = Prefill.Data.SEmpty;

View File

@@ -0,0 +1,110 @@
import { expect, test } from "bun:test";
import { bunEnv, bunExe } from "harness";
// https://github.com/oven-sh/bun/issues/18333
// "use strict" in a function with non-simple parameters should be a SyntaxError
// per ECMAScript spec Section 15.2.1.
test("'use strict' in function with default parameter is a SyntaxError", async () => {
await using proc = Bun.spawn({
cmd: [bunExe(), "-e", `function test(a = 5) { 'use strict'; }`],
env: bunEnv,
stderr: "pipe",
});
const [stderr, exitCode] = await Promise.all([proc.stderr.text(), proc.exited]);
expect(stderr).toContain("use strict");
expect(exitCode).not.toBe(0);
});
test("'use strict' in function with rest parameter is a SyntaxError", async () => {
await using proc = Bun.spawn({
cmd: [bunExe(), "-e", `function test(...args) { 'use strict'; }`],
env: bunEnv,
stderr: "pipe",
});
const [stderr, exitCode] = await Promise.all([proc.stderr.text(), proc.exited]);
expect(stderr).toContain("use strict");
expect(exitCode).not.toBe(0);
});
test("'use strict' in function with destructuring parameter is a SyntaxError", async () => {
await using proc = Bun.spawn({
cmd: [bunExe(), "-e", `function test({a, b}) { 'use strict'; }`],
env: bunEnv,
stderr: "pipe",
});
const [stderr, exitCode] = await Promise.all([proc.stderr.text(), proc.exited]);
expect(stderr).toContain("use strict");
expect(exitCode).not.toBe(0);
});
test("'use strict' in arrow function with default parameter is a SyntaxError", async () => {
await using proc = Bun.spawn({
cmd: [bunExe(), "-e", `const test = (a = 1) => { 'use strict'; }`],
env: bunEnv,
stderr: "pipe",
});
const [stderr, exitCode] = await Promise.all([proc.stderr.text(), proc.exited]);
expect(stderr).toContain("use strict");
expect(exitCode).not.toBe(0);
});
test("'use strict' in function with array destructuring parameter is a SyntaxError", async () => {
await using proc = Bun.spawn({
cmd: [bunExe(), "-e", `function test([a, b]) { 'use strict'; }`],
env: bunEnv,
stderr: "pipe",
});
const [stderr, exitCode] = await Promise.all([proc.stderr.text(), proc.exited]);
expect(stderr).toContain("use strict");
expect(exitCode).not.toBe(0);
});
test("'use strict' in function with simple parameters is allowed", async () => {
await using proc = Bun.spawn({
cmd: [bunExe(), "-e", `function test(a, b) { 'use strict'; console.log('ok'); }`],
env: bunEnv,
stderr: "pipe",
});
const [stderr, exitCode] = await Promise.all([proc.stderr.text(), proc.exited]);
expect(stderr).toBe("");
expect(exitCode).toBe(0);
});
test("'use strict' in function with no parameters is allowed", async () => {
await using proc = Bun.spawn({
cmd: [bunExe(), "-e", `function test() { 'use strict'; console.log('ok'); }`],
env: bunEnv,
stderr: "pipe",
});
const [stderr, exitCode] = await Promise.all([proc.stderr.text(), proc.exited]);
expect(stderr).toBe("");
expect(exitCode).toBe(0);
});
test("'use strict' in method with default parameter is a SyntaxError", async () => {
await using proc = Bun.spawn({
cmd: [bunExe(), "-e", `({ test(a = 5) { 'use strict'; } })`],
env: bunEnv,
stderr: "pipe",
});
const [stderr, exitCode] = await Promise.all([proc.stderr.text(), proc.exited]);
expect(stderr).toContain("use strict");
expect(exitCode).not.toBe(0);
});