Skip to content

Commit

Permalink
fix(lexer): do not treat '#bun' in a url as a pragma (#15888)
Browse files Browse the repository at this point in the history
Co-authored-by: Don Isaac <don@bun.sh>
Co-authored-by: DonIsaac <DonIsaac@users.noreply.github.com>
  • Loading branch information
3 people authored Dec 20, 2024
1 parent a8893dc commit 1d9fbe7
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 32 deletions.
23 changes: 2 additions & 21 deletions src/js_lexer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,6 @@ fn NewLexer_(
code_point: CodePoint = -1,
identifier: []const u8 = "",
jsx_pragma: JSXPragma = .{},
bun_pragma: enum {
none,
bun,
bun_cjs,
bytecode,
bytecode_cjs,
} = .none,
source_mapping_url: ?js_ast.Span = null,
number: f64 = 0.0,
rescan_close_brace_as_template_token: bool = false,
Expand Down Expand Up @@ -1957,9 +1950,7 @@ fn NewLexer_(
// }
}

if (lexer.bun_pragma == .none and strings.hasPrefixWithWordBoundary(chunk, "bun")) {
lexer.bun_pragma = .bun;
} else if (strings.hasPrefixWithWordBoundary(chunk, "jsx")) {
if (strings.hasPrefixWithWordBoundary(chunk, "jsx")) {
if (PragmaArg.scan(.skip_space_first, lexer.start + i + 1, "jsx", chunk)) |span| {
lexer.jsx_pragma._jsx = span;
}
Expand All @@ -1979,10 +1970,6 @@ fn NewLexer_(
if (PragmaArg.scan(.no_space_first, lexer.start + i + 1, " sourceMappingURL=", chunk)) |span| {
lexer.source_mapping_url = span;
}
} else if ((lexer.bun_pragma == .bun or lexer.bun_pragma == .bun_cjs) and strings.hasPrefixWithWordBoundary(chunk, "bytecode")) {
lexer.bun_pragma = if (lexer.bun_pragma == .bun) .bytecode else .bytecode_cjs;
} else if ((lexer.bun_pragma == .bytecode or lexer.bun_pragma == .bun) and strings.hasPrefixWithWordBoundary(chunk, "bun-cjs")) {
lexer.bun_pragma = if (lexer.bun_pragma == .bytecode) .bytecode_cjs else .bun_cjs;
}
},
else => {},
Expand Down Expand Up @@ -2012,9 +1999,7 @@ fn NewLexer_(
}
}

if (lexer.bun_pragma == .none and strings.hasPrefixWithWordBoundary(chunk, "bun")) {
lexer.bun_pragma = .bun;
} else if (strings.hasPrefixWithWordBoundary(chunk, "jsx")) {
if (strings.hasPrefixWithWordBoundary(chunk, "jsx")) {
if (PragmaArg.scan(.skip_space_first, lexer.start + i + 1, "jsx", chunk)) |span| {
lexer.jsx_pragma._jsx = span;
}
Expand All @@ -2034,10 +2019,6 @@ fn NewLexer_(
if (PragmaArg.scan(.no_space_first, lexer.start + i + 1, " sourceMappingURL=", chunk)) |span| {
lexer.source_mapping_url = span;
}
} else if ((lexer.bun_pragma == .bun or lexer.bun_pragma == .bun_cjs) and strings.hasPrefixWithWordBoundary(chunk, "bytecode")) {
lexer.bun_pragma = if (lexer.bun_pragma == .bun) .bytecode else .bytecode_cjs;
} else if ((lexer.bun_pragma == .bytecode or lexer.bun_pragma == .bun) and strings.hasPrefixWithWordBoundary(chunk, "bun-cjs")) {
lexer.bun_pragma = if (lexer.bun_pragma == .bytecode) .bytecode_cjs else .bun_cjs;
}
},
else => {},
Expand Down
57 changes: 46 additions & 11 deletions src/js_parser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/// ** you must also increment the `expected_version` in RuntimeTranspilerCache.zig **
/// ** IMPORTANT **
pub const std = @import("std");
const bun = @import("root").bun;
pub const logger = bun.logger;
pub const js_lexer = bun.js_lexer;
pub const importRecord = @import("./import_record.zig");
Expand All @@ -15,7 +16,6 @@ pub const RuntimeImports = _runtime.Runtime.Imports;
pub const RuntimeFeatures = _runtime.Runtime.Features;
pub const RuntimeNames = _runtime.Runtime.Names;
pub const fs = @import("./fs.zig");
const bun = @import("root").bun;
const string = bun.string;
const Output = bun.Output;
const Global = bun.Global;
Expand Down Expand Up @@ -3226,16 +3226,12 @@ pub const Parser = struct {
}

// Detect a leading "// @bun" pragma
if (p.lexer.bun_pragma != .none and p.options.features.dont_bundle_twice) {
return js_ast.Result{
.already_bundled = switch (p.lexer.bun_pragma) {
.bun => .bun,
.bytecode => .bytecode,
.bytecode_cjs => .bytecode_cjs,
.bun_cjs => .bun_cjs,
else => unreachable,
},
};
if (self.options.features.dont_bundle_twice) {
if (self.hasBunPragma()) |pragma| {
return js_ast.Result{
.already_bundled = pragma,
};
}
}

// We must check the cache only after we've consumed the hashbang and leading // @bun pragma
Expand Down Expand Up @@ -4282,6 +4278,45 @@ pub const Parser = struct {
.log = log,
};
}

const PragmaState = packed struct { seen_cjs: bool = false, seen_bytecode: bool = false };

fn hasBunPragma(self: *const Parser) ?js_ast.Result.AlreadyBundled {
const BUN_PRAGMA = "// @bun";
var cursor: usize = 0;

const contents = self.lexer.source.contents;
if (!bun.strings.startsWith(contents[cursor..], BUN_PRAGMA)) return null;
cursor += BUN_PRAGMA.len;

var state: PragmaState = .{};

while (cursor < self.lexer.end) : (cursor += 1) {
switch (contents[cursor]) {
'\n' => break,
'@' => {
cursor += 1;
if (cursor >= contents.len) break;
if (contents[cursor] != 'b') continue;
const slice = contents[cursor..];
if (bun.strings.startsWith(slice, "bun-cjs")) {
state.seen_cjs = true;
cursor += "bun-cjs".len;
} else if (bun.strings.startsWith(slice, "bytecode")) {
state.seen_bytecode = true;
cursor += "bytecode".len;
}
},
else => {},
}
}

if (state.seen_cjs) {
return if (state.seen_bytecode) .bytecode_cjs else .bun_cjs;
} else {
return if (state.seen_bytecode) .bytecode else .bun;
}
}
};

const FindLabelSymbolResult = struct { ref: Ref, is_loop: bool, found: bool = false };
Expand Down
15 changes: 15 additions & 0 deletions test/bundler/transpiler/bun-pragma.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import path from "path";
import { bunExe, bunEnv } from "harness";

const fixturePath = (name: string): string => path.join(import.meta.dirname, "fixtures", name);

describe("@bun pragma", () => {
it("is not detected when embedded in a URL", async () => {
const res = Bun.spawn({
cmd: [bunExe(), "run", fixturePath("bun-in-url.ts")],
stdio: ["ignore", "ignore", "ignore"],
});
await res.exited;
expect(res.exitCode).toBe(0);
});
});
5 changes: 5 additions & 0 deletions test/bundler/transpiler/fixtures/bun-in-url.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// https://bun.sh/docs/api/http#bun-serve
const a: string = "hello";
console.log(a);

// '#bun' spotted in first comment but it's not a valid bun pragma

0 comments on commit 1d9fbe7

Please sign in to comment.