Skip to content

Commit

Permalink
fix(bundler): put unwrapped cjs imports at top level for minifyrenamer (
Browse files Browse the repository at this point in the history
  • Loading branch information
paperclover authored Jul 31, 2024
1 parent 7ab4dc7 commit d5d4f53
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 20 deletions.
2 changes: 2 additions & 0 deletions .lldbinit
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
command script import src/deps/zig/tools/lldb_pretty_printers.py
command script import src/bun.js/WebKit/Tools/lldb/lldb_webkit.py

# type summary add --summary-string "${var} | inner=${var[0-30]}, source=${var[33-64]}, tag=${var[31-32]}" "unsigned long"
30 changes: 30 additions & 0 deletions src/ast/base.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ const std = @import("std");
const bun = @import("root").bun;
const unicode = std.unicode;

const js_ast = bun.JSAst;

pub const NodeIndex = u32;
pub const NodeIndexNone = 4294967293;

Expand Down Expand Up @@ -147,6 +149,34 @@ pub const Ref = packed struct(u64) {
);
}

pub fn dump(ref: Ref, symbol_table: anytype) std.fmt.Formatter(dumpImpl) {
return .{ .data = .{
.ref = ref,
.symbol_table = switch (@TypeOf(symbol_table)) {
*const std.ArrayList(js_ast.Symbol) => symbol_table.items,
*std.ArrayList(js_ast.Symbol) => symbol_table.items,
[]const js_ast.Symbol => symbol_table,
[]js_ast.Symbol => symbol_table,
else => |T| @compileError("Unsupported type to Ref.dump: " ++ @typeName(T)),
},
} };
}

fn dumpImpl(data: struct { ref: Ref, symbol_table: []const js_ast.Symbol }, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
const symbol = data.symbol_table[data.ref.inner_index];
try std.fmt.format(
writer,
"Ref[inner={d}, src={d}, .{s}; original_name={s}, uses={d}]",
.{
data.ref.inner_index,
data.ref.source_index,
@tagName(data.ref.tag),
symbol.original_name,
symbol.use_count_estimate,
},
);
}

pub fn isValid(this: Ref) bool {
return this.tag != .invalid;
}
Expand Down
11 changes: 7 additions & 4 deletions src/js_parser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3783,10 +3783,12 @@ pub const Parser = struct {
var remaining_stmts = all_stmts;

for (p.imports_to_convert_from_require.items) |deferred_import| {
var stmts_ = remaining_stmts[0..1];
var import_part_stmts = remaining_stmts[0..1];
remaining_stmts = remaining_stmts[1..];

stmts_[0] = Stmt.alloc(
p.module_scope.generated.push(p.allocator, deferred_import.namespace.ref.?) catch bun.outOfMemory();

import_part_stmts[0] = Stmt.alloc(
S.Import,
S.Import{
.star_name_loc = deferred_import.namespace.loc,
Expand All @@ -3798,10 +3800,11 @@ pub const Parser = struct {
var declared_symbols = DeclaredSymbol.List.initCapacity(p.allocator, 1) catch unreachable;
declared_symbols.appendAssumeCapacity(.{ .ref = deferred_import.namespace.ref.?, .is_top_level = true });
before.appendAssumeCapacity(.{
.stmts = stmts_,
.stmts = import_part_stmts,
.declared_symbols = declared_symbols,
.tag = .import_to_convert_from_require,
.can_be_removed_if_unused = p.stmtsCanBeRemovedIfUnused(stmts_),
// This part has a single symbol, so it may be removed if unused.
.can_be_removed_if_unused = true,
});
}
bun.assert(remaining_stmts.len == 0);
Expand Down
1 change: 1 addition & 0 deletions src/renamer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ pub fn assignNestedScopeSlots(allocator: std.mem.Allocator, module_scope: *js_as

pub fn assignNestedScopeSlotsHelper(sorted_members: *std.ArrayList(u32), scope: *js_ast.Scope, symbols: []js_ast.Symbol, slot_to_copy: js_ast.SlotCounts) js_ast.SlotCounts {
var slot = slot_to_copy;

// Sort member map keys for determinism
{
sorted_members.clearRetainingCapacity();
Expand Down
8 changes: 0 additions & 8 deletions src/shell/shell.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3316,14 +3316,6 @@ pub fn NewLexer(comptime encoding: StringEncoding) type {
fn read_char(self: *@This()) ?InputChar {
return self.chars.read_char();
}

// fn debug_tokens(self: *const @This()) void {
// std.debug.print("Tokens: \n", .{});
// for (self.tokens.items, 0..) |tok, i| {
// std.debug.print("{d}: ", .{i});
// tok.debug(self.strpool.items[0..self.strpool.items.len]);
// }
// }
};
}

Expand Down
40 changes: 40 additions & 0 deletions test/bundler/bundler_cjs2esm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,4 +307,44 @@ describe("bundler", () => {
},
minifySyntax: true,
});
itBundled("cjs2esm/ReactSpecificUnwrapping2", {
files: {
"/entry.js": /* js */ `
import * as react from "react-dom";
console.log(react);
`,
"/node_modules/react-dom/index.js": /* js */ `
export const stuff = [
require('./a.js'),
require('./b.js')
];
`,
"/node_modules/react-dom/a.js": /* js */ `
(function () {
var React = require('react');
var stream = require('stream');
console.log([React, stream]);
exports.version = null;
})();
`,
"/node_modules/react-dom/b.js": /* js */ `
(function () {
var React = require('react');
var util = require('util');
console.log([React, util]);
exports.version = null;
})();
`,
"/node_modules/react/index.js": /* js */ `
module.exports = 123;
`,
},
run: true,
minifyIdentifiers: true,
target: "bun",
});
});
4 changes: 2 additions & 2 deletions test/bundler/bundler_edgecase.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ describe("bundler", () => {
const std = @import("std");
pub fn main() void {
std.debug.print("Hello, world!\\n", .{});
std.log.info("Hello, world!\\n", .{});
}
`,
},
Expand All @@ -684,7 +684,7 @@ describe("bundler", () => {
"/exec.js": `
import assert from 'node:assert';
import the_path from './out/entry.js';
assert.strictEqual(the_path, './entry-6dhkdck1.zig');
assert.strictEqual(the_path, './entry-z5artd5z.zig');
`,
},
run: {
Expand Down
15 changes: 9 additions & 6 deletions test/bundler/bundler_npm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,18 @@ describe("bundler", () => {
"../entry.tsx",
],
mappings: [
["react.development.js:524:'getContextName'", "1:5404:r1"],
["react.development.js:2495:'actScopeDepth'", "1:26072:GJ++"],
["react.development.js:696:''Component'", '1:7470:\'Component "%s"'],
["entry.tsx:6:'\"Content-Type\"'", '1:221669:"Content-Type"'],
["entry.tsx:11:'<html>'", "1:221925:void"],
["entry.tsx:23:'await'", "1:222026:await"],
["react.development.js:524:'getContextName'", "1:5428:Y1"],
["react.development.js:2495:'actScopeDepth'", "1:26053:GJ++"],
["react.development.js:696:''Component'", '1:7490:\'Component "%s"'],
["entry.tsx:6:'\"Content-Type\"'", '1:221655:"Content-Type"'],
["entry.tsx:11:'<html>'", "1:221911:void"],
["entry.tsx:23:'await'", "1:222013:await"],
],
},
},
expectExactFilesize: {
"out/entry.js": 222283,
},
run: {
stdout: "<!DOCTYPE html><html><body><h1>Hello World</h1><p>This is an example.</p></body></html>",
},
Expand Down
12 changes: 12 additions & 0 deletions test/bundler/expectBundled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,8 @@ export interface BundlerTestInput {
skipIfWeDidNotImplementWildcardSideEffects?: boolean;

snapshotSourceMap?: Record<string, SourceMapTests>;

expectExactFilesize?: Record<string, number>;
}

export interface SourceMapTests {
Expand Down Expand Up @@ -440,6 +442,7 @@ function expectBundled(
useDefineForClassFields,
// @ts-expect-error
_referenceFn,
expectExactFilesize,
...unknownProps
} = opts;

Expand Down Expand Up @@ -1378,6 +1381,15 @@ for (const [key, blob] of build.outputs) {
}
}

if (expectExactFilesize) {
for (const [key, expected] of Object.entries(expectExactFilesize)) {
const actual = api.readFile(key).length;
if (actual !== expected) {
throw new Error(`Expected file ${key} to be ${expected} bytes but was ${actual} bytes.`);
}
}
}

// Runtime checks!
if (run) {
const runs = Array.isArray(run) ? run : [run];
Expand Down

0 comments on commit d5d4f53

Please sign in to comment.