diff options
-rw-r--r-- | src/js_parser.zig | 26 | ||||
-rw-r--r-- | test/bun.js/transpiler.test.js | 157 |
2 files changed, 109 insertions, 74 deletions
diff --git a/src/js_parser.zig b/src/js_parser.zig index 9f422d9b8..b671682a9 100644 --- a/src/js_parser.zig +++ b/src/js_parser.zig @@ -739,10 +739,10 @@ pub const ImportScanner = struct { // Skip to the underlying reference var value = decl.value; - if (decl.value) |val| { + if (decl.value != null) { while (true) { - if (@as(Expr.Tag, val.data) == .e_dot) { - value = val.data.e_dot.target; + if (@as(Expr.Tag, value.?.data) == .e_dot) { + value = value.?.data.e_dot.target; } else { break; } @@ -8097,7 +8097,8 @@ fn NewParser_( const kind = S.Local.Kind.k_const; const name = p.lexer.identifier; - var value = p.e(E.Identifier{ .ref = p.storeNameInRef(name) catch unreachable }, p.lexer.loc()); + const target = p.e(E.Identifier{ .ref = p.storeNameInRef(name) catch unreachable }, p.lexer.loc()); + var value = target; try p.lexer.expect(.t_identifier); if (strings.eqlComptime(name, "require") and p.lexer.token == .t_open_paren) { @@ -8106,17 +8107,17 @@ fn NewParser_( const path = p.e(p.lexer.toEString(), p.lexer.loc()); try p.lexer.expect(.t_string_literal); try p.lexer.expect(.t_close_paren); - const args = try ExprNodeList.one(p.allocator, path); - value.data = .{ .e_call = Expr.Data.Store.All.append(E.Call, E.Call{ .target = value, .close_paren_loc = p.lexer.loc(), .args = args }) }; + if (!opts.is_typescript_declare) { + const args = try ExprNodeList.one(p.allocator, path); + value = p.e(E.Call{ .target = target, .close_paren_loc = p.lexer.loc(), .args = args }, loc); + } } else { // "import Foo = Bar" // "import Foo = Bar.Baz" - while (p.lexer.token == .t_dot) { + var prev_value = value; + while (p.lexer.token == .t_dot) : (prev_value = value) { try p.lexer.next(); - value.data = .{ .e_dot = Expr.Data.Store.All.append( - E.Dot, - E.Dot{ .target = value, .name = p.lexer.identifier, .name_loc = p.lexer.loc() }, - ) }; + value = p.e(E.Dot{ .target = prev_value, .name = p.lexer.identifier, .name_loc = p.lexer.loc() }, loc); try p.lexer.expect(.t_identifier); } } @@ -15717,8 +15718,9 @@ fn NewParser_( pub fn ignoreUsage(p: *P, ref: Ref) void { if (!p.is_control_flow_dead) { + assert(@as(usize, ref.innerIndex()) < p.symbols.items.len); p.symbols.items[ref.innerIndex()].use_count_estimate -|= 1; - var use = p.symbol_uses.get(ref) orelse p.panic("Expected symbol_uses to exist {s}\n{s}", .{ ref, p.symbol_uses }); + var use = p.symbol_uses.get(ref) orelse return; use.count_estimate -|= 1; if (use.count_estimate == 0) { _ = p.symbol_uses.swapRemove(ref); diff --git a/test/bun.js/transpiler.test.js b/test/bun.js/transpiler.test.js index f8da4c18c..51e1e669d 100644 --- a/test/bun.js/transpiler.test.js +++ b/test/bun.js/transpiler.test.js @@ -1,6 +1,101 @@ import { expect, it, describe } from "bun:test"; describe("Bun.Transpiler", () => { + const transpiler = new Bun.Transpiler({ + loader: "tsx", + define: { + "process.env.NODE_ENV": JSON.stringify("development"), + user_undefined: "undefined", + }, + macro: { + react: { + bacon: `${import.meta.dir}/macro-check.js`, + }, + }, + platform: "browser", + }); + + const ts = { + parsed: (code, trim = true, autoExport = false) => { + if (autoExport) { + code = "export default (" + code + ")"; + } + + var out = transpiler.transformSync(code, "ts"); + if (autoExport && out.startsWith("export default ")) { + out = out.substring("export default ".length); + } + + if (trim) { + out = out.trim(); + + if (out.endsWith(";")) { + out = out.substring(0, out.length - 1); + } + + return out.trim(); + } + + return out; + }, + + expectPrinted: (code, out) => { + expect(ts.parsed(code, true, true)).toBe(out); + }, + + expectPrinted_: (code, out) => { + expect(ts.parsed(code, !out.endsWith(";\n"), false)).toBe(out); + }, + + expectParseError: (code, message) => { + try { + ts.parsed(code, false, false); + } catch (er) { + var err = er; + if (er instanceof AggregateError) { + err = err.errors[0]; + } + + expect(er.message).toBe(message); + + return; + } + + throw new Error("Expected parse error for code\n\t" + code); + }, + }; + + describe("TypeScript", () => { + it("import Foo = Baz.Bar", () => { + ts.expectPrinted_( + "import Foo = Baz.Bar;\nexport default Foo;", + "const Foo = Baz.Bar;\nexport default Foo" + ); + }); + + it("import Foo = require('bar')", () => { + ts.expectPrinted_( + "import React = require('react')", + 'const React = require("react")' + ); + }); + + it("import type Foo = require('bar')", () => { + ts.expectPrinted_("import type Foo = require('bar')", ""); + }); + + it("unused import = gets removed", () => { + ts.expectPrinted_("import Foo = Baz.Bar;", ""); + }); + + it("export import Foo = Baz.Bar", () => { + ts.expectPrinted_( + "export import Foo = Baz.Bar;", + "export const Foo = Baz.Bar" + ); + }); + }); + describe("exports.replace", () => { const transpiler = new Bun.Transpiler({ exports: { @@ -111,19 +206,6 @@ describe("Bun.Transpiler", () => { }); }); - const transpiler = new Bun.Transpiler({ - loader: "tsx", - define: { - "process.env.NODE_ENV": JSON.stringify("development"), - user_undefined: "undefined", - }, - macro: { - react: { - bacon: `${import.meta.dir}/macro-check.js`, - }, - }, - platform: "browser", - }); const bunTranspiler = new Bun.Transpiler({ loader: "tsx", define: { @@ -496,55 +578,6 @@ export var ComponentThatHasSpreadCausesDeopt = jsx(Hello, { throw new Error("Expected parse error for code\n\t" + code); }; - const ts = { - parsed: (code, trim = true, autoExport = false) => { - if (autoExport) { - code = "export default (" + code + ")"; - } - - var out = transpiler.transformSync(code, "ts"); - if (autoExport && out.startsWith("export default ")) { - out = out.substring("export default ".length); - } - - if (trim) { - out = out.trim(); - - if (out.endsWith(";")) { - out = out.substring(0, out.length - 1); - } - - return out.trim(); - } - - return out; - }, - - expectPrinted: (code, out) => { - expect(ts.parsed(code, true, true)).toBe(out); - }, - - expectPrinted_: (code, out) => { - expect(ts.parsed(code, !out.endsWith(";\n"), false)).toBe(out); - }, - - expectParseError: (code, message) => { - try { - ts.parsed(code, false, false); - } catch (er) { - var err = er; - if (er instanceof AggregateError) { - err = err.errors[0]; - } - - expect(er.message).toBe(message); - - return; - } - - throw new Error("Expected parse error for code\n\t" + code); - }, - }; describe("parser", () => { it("arrays", () => { |