diff options
-rw-r--r-- | build-id | 2 | ||||
-rw-r--r-- | src/bundler.zig | 21 | ||||
-rw-r--r-- | src/js_parser/js_parser.zig | 388 | ||||
-rw-r--r-- | src/js_printer.zig | 48 | ||||
-rw-r--r-- | src/linker.zig | 2 | ||||
-rw-r--r-- | src/options.zig | 6 | ||||
-rw-r--r-- | src/runtime/hmr.ts | 14 |
7 files changed, 334 insertions, 147 deletions
@@ -1 +1 @@ -16 +17 diff --git a/src/bundler.zig b/src/bundler.zig index 8486e64e9..d832c01fe 100644 --- a/src/bundler.zig +++ b/src/bundler.zig @@ -1902,12 +1902,21 @@ pub fn NewBundler(cache_files: bool) type { try bundler.linker.link(file_path, &result, import_path_format, false); return BuildResolveResultPair{ - .written = try bundler.print( - result, - Writer, - writer, - .esm, - ), + .written = switch (result.ast.exports_kind) { + .esm => try bundler.print( + result, + Writer, + writer, + .esm, + ), + .cjs => try bundler.print( + result, + Writer, + writer, + .cjs, + ), + else => unreachable, + }, .input_fd = result.input_fd, }; }, diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig index 1fa9f3491..24ead5013 100644 --- a/src/js_parser/js_parser.zig +++ b/src/js_parser/js_parser.zig @@ -1957,7 +1957,7 @@ pub const Parser = struct { var wrapper_expr: ?Expr = null; - if (p.es6_export_keyword.len > 0 or p.top_level_await_keyword.len > 0) { + if ((p.es6_export_keyword.len > 0 or p.top_level_await_keyword.len > 0) and !uses_module_ref and !uses_exports_ref) { exports_kind = .esm; } else if (uses_exports_ref or uses_module_ref or p.has_top_level_return) { exports_kind = .cjs; @@ -2022,13 +2022,16 @@ pub const Parser = struct { const automatic_namespace_ref = p.jsx_automatic.ref; const decls_count: u32 = - @intCast(u32, @boolToInt(jsx_symbol.use_count_estimate > 0)) * 2 + @intCast(u32, @boolToInt(jsx_static_symbol.use_count_estimate > 0)) * 2 + + @intCast(u32, @boolToInt(jsx_symbol.use_count_estimate > 0)) * 2 + + @intCast(u32, @boolToInt(jsx_static_symbol.use_count_estimate > 0)) * 2 + @intCast(u32, @boolToInt(jsx_factory_symbol.use_count_estimate > 0)) + @intCast(u32, @boolToInt(jsx_fragment_symbol.use_count_estimate > 0)) + @intCast(u32, @boolToInt(jsx_filename_symbol.use_count_estimate > 0)); const imports_count = - @intCast(u32, @boolToInt(std.math.max(jsx_symbol.use_count_estimate, jsx_static_symbol.use_count_estimate) > 0)) + @intCast(u32, std.math.max(jsx_factory_symbol.use_count_estimate, jsx_fragment_symbol.use_count_estimate)) + @intCast(u32, @boolToInt(p.options.features.react_fast_refresh)); + @intCast(u32, @boolToInt(std.math.max(jsx_symbol.use_count_estimate, jsx_static_symbol.use_count_estimate) > 0)) + + @intCast(u32, std.math.max(jsx_factory_symbol.use_count_estimate, jsx_fragment_symbol.use_count_estimate)) + + @intCast(u32, @boolToInt(p.options.features.react_fast_refresh)); const stmts_count = imports_count + 1; const symbols_count: u32 = imports_count + decls_count; const loc = logger.Loc{ .start = 0 }; @@ -2048,19 +2051,6 @@ pub const Parser = struct { var stmt_i: usize = 0; if (jsx_symbol.use_count_estimate > 0 or jsx_static_symbol.use_count_estimate > 0) { - if (jsx_automatic_symbol.use_count_estimate > 0) { - if (jsx_automatic_symbol.link != null) { - p.symbols.items[p.jsx_automatic.ref.inner_index].link = null; - p.symbols.items[p.jsx_automatic.ref.inner_index].original_name = try std.fmt.allocPrint( - p.allocator, - "jsxImport{x}", - .{ - @truncate(u16, std.hash.Wyhash.hash(0, p.options.jsx.import_source)), - }, - ); - } - } - declared_symbols[declared_symbols_i] = .{ .ref = automatic_namespace_ref, .is_top_level = true }; declared_symbols_i += 1; @@ -3543,8 +3533,8 @@ pub fn NewParser( try p.module_scope.generated.ensureUnusedCapacity(generated_symbols_count * 3); try p.module_scope.members.ensureCapacity(generated_symbols_count * 3 + p.module_scope.members.count()); - p.exports_ref = try p.declareCommonJSSymbol(.unbound, "exports"); - p.module_ref = try p.declareCommonJSSymbol(.unbound, "module"); + p.exports_ref = try p.declareCommonJSSymbol(.hoisted, "exports"); + p.module_ref = try p.declareCommonJSSymbol(.hoisted, "module"); p.require_ref = try p.declareCommonJSSymbol(.unbound, "require"); if (FeatureFlags.auto_import_buffer) { @@ -3575,8 +3565,6 @@ pub fn NewParser( p.runtime_imports.__HMRClient = try p.declareGeneratedSymbol(.other, "__HMRClient"); p.recordUsage(p.hmr_module.ref); p.recordUsage(p.runtime_imports.__HMRClient.?.ref); - } else { - p.runtime_imports.__export = GeneratedSymbol{ .ref = p.exports_ref, .primary = Ref.None, .backup = Ref.None }; } if (is_jsx_enabled) { @@ -12256,76 +12244,27 @@ pub fn NewParser( name_loc: logger.Loc, is_call_target: bool, ) ?Expr { - if (@as(Expr.Tag, target.data) == .e_identifier) { - const id = target.data.e_identifier; - - // Rewrite property accesses on explicit namespace imports as an identifier. - // This lets us replace them easily in the printer to rebind them to - // something else without paying the cost of a whole-tree traversal during - // module linking just to rewrite these EDot expressions. - // if (p.import_items_for_namespace.getPtr(id.ref)) |import_items| { - // const item: LocRef = import_items.get(name) orelse brk: { - // const _item = LocRef{ .loc = name_loc, .ref = p.newSymbol(.import, name) catch unreachable }; - // p.module_scope.generated.append(_item.ref orelse unreachable) catch unreachable; - - // import_items.put(name, _item) catch unreachable; - // p.is_import_item.put(_item.ref orelse unreachable, true) catch unreachable; - - // var symbol: *js_ast.Symbol = &p.symbols.items[_item.ref.?.inner_index]; - // // Mark this as generated in case it's missing. We don't want to - // // generate errors for missing import items that are automatically - // // generated. - // symbol.import_item_status = .generated; - - // // Make sure the printer prints this as a property access - // symbol.namespace_alias = G.NamespaceAlias{ .namespace_ref = id.ref, .alias = name }; - // break :brk _item; - // }; - - // // Undo the usage count for the namespace itself. This is used later - // // to detect whether the namespace symbol has ever been "captured" - // // or whether it has just been used to read properties off of. - // // - // // The benefit of doing this is that if both this module and the - // // imported module end up in the same module group and the namespace - // // symbol has never been captured, then we don't need to generate - // // any code for the namespace at all. - // p.ignoreUsage(id.ref); - - // // Track how many times we've referenced this symbol - // p.recordUsage(item.ref.?); - // var ident_expr = p.e( - // E.Identifier{ - // .ref = item.ref.?, - // }, - // target.loc, - // ); - - // return p.handleIdentifier(name_loc, ident_expr.data.e_identifier, name, IdentifierOpts{ - // .assign_target = assign_target, - // .is_delete_target = is_delete_target, - // // If this expression is used as the target of a call expression, make - // // sure the value of "this" is preserved. - // .was_originally_identifier = false, - // }); - // } - - if (is_call_target and id.ref.eql(p.module_ref) and strings.eqlComptime(name, "require")) { - p.ignoreUsage(p.module_ref); - p.recordUsage(p.require_ref); - return p.e(E.Identifier{ .ref = p.require_ref }, name_loc); - } + switch (target.data) { + .e_identifier => |id| { + // Rewrite "module.require()" to "require()" for Webpack compatibility. + // See https://github.com/webpack/webpack/pull/7750 for more info. + // This also makes correctness a little easier. + if (is_call_target and id.ref.eql(p.module_ref) and strings.eqlComptime(name, "require")) { + p.ignoreUsage(p.module_ref); + p.recordUsage(p.require_ref); + return p.e(E.Identifier{ .ref = p.require_ref }, name_loc); + } - // If this is a known enum value, inline the value of the enum - if (is_typescript_enabled) { - if (p.known_enum_values.get(id.ref)) |enum_value_map| { - if (enum_value_map.get(name)) |enum_value| { - return p.e(E.Number{ .value = enum_value }, loc); + // If this is a known enum value, inline the value of the enum + if (is_typescript_enabled) { + if (p.known_enum_values.get(id.ref)) |enum_value_map| { + if (enum_value_map.get(name)) |enum_value| { + return p.e(E.Number{ .value = enum_value }, loc); + } } } - } - - if (p.options.features.hot_module_reloading) {} + }, + else => {}, } return null; @@ -14233,13 +14172,223 @@ pub fn NewParser( } if (commonjs_wrapper_expr) |commonjs_wrapper| { + var part = &parts[parts.len - 1]; + var require_function_args = p.allocator.alloc(Arg, 2) catch unreachable; + var imports_count: u32 = 0; + // We have to also move export from, since we will preserve those + var exports_from_count: u32 = 0; + + var additional_stmts_because_of_exports: u32 = 0; + + // Two passes. First pass just counts. + for (parts[parts.len - 1].stmts) |stmt, i| { + imports_count += switch (stmt.data) { + .s_import => @as(u32, 1), + else => @as(u32, 0), + }; + + exports_from_count += switch (stmt.data) { + .s_export_star, .s_export_from => @as(u32, 1), + else => @as(u32, 0), + }; + } + + var new_stmts_list = p.allocator.alloc(Stmt, exports_from_count + imports_count + 1) catch unreachable; + var imports_list = new_stmts_list[0..imports_count]; + + var exports_list = if (exports_from_count > 0) new_stmts_list[imports_list.len + 1 ..] else &[_]Stmt{}; + const name_ref = null; require_function_args[0] = G.Arg{ .binding = p.b(B.Identifier{ .ref = p.module_ref }, logger.Loc.Empty) }; require_function_args[1] = G.Arg{ .binding = p.b(B.Identifier{ .ref = p.exports_ref }, logger.Loc.Empty) }; + var exports_identifier: ExprNodeIndex = undefined; + var exports_identifier_set = false; const default_name_loc_ref = LocRef{ .ref = name_ref, .loc = logger.Loc.Empty }; + var imports_list_i: u32 = 0; + var exports_list_i: u32 = 0; + + for (part.stmts) |_, i| { + switch (part.stmts[i].data) { + .s_import => { + imports_list[imports_list_i] = part.stmts[i]; + part.stmts[i] = Stmt.empty(); + part.stmts[i].loc = imports_list[imports_list_i].loc; + imports_list_i += 1; + }, + + // .s_export_default => |s_export| { + // if (!exports_identifier_set) { + // exports_identifier = p.e(E.Identifier{ .ref = p.exports_ref }, logger.Loc.Empty); + // exports_identifier_set = true; + // } + + // switch (s_export.value) { + // .expr => |default_expr| { + // part.stmts[i] = Expr.assignStmt(p.e( + // E.Dot{ .name = "default", .name_loc = part.stmts[i].loc, .target = exports_identifier }, + // part.stmts[i].loc, + // ), default_expr, p.allocator); + // }, + // .stmt => |default_stmt| { + // switch (default_stmt.data) { + // .s_function => |func| { + // part.stmts[i] = Expr.assignStmt(p.e( + // E.Dot{ .name = "default", .name_loc = part.stmts[i].loc, .target = exports_identifier }, + // part.stmts[i].loc, + // ), p.e( + // E.Function{ .func = func.func }, + // default_stmt.loc, + // ), p.allocator); + // }, + // .s_class => |class| { + // part.stmts[i] = Expr.assignStmt( + // p.e( + // E.Dot{ .name = "default", .name_loc = part.stmts[i].loc, .target = exports_identifier }, + // part.stmts[i].loc, + // ), + // p.e( + // default_stmt.data.s_class.class, + // default_stmt.loc, + // ), + // p.allocator, + // ); + // }, + // else => unreachable, + // } + // }, + // } + // }, + + // .s_function => |func| { + // if (!exports_identifier_set) { + // exports_identifier = p.e(E.Identifier{ .ref = p.exports_ref }, logger.Loc.Empty); + // exports_identifier_set = true; + // } + + // part.stmts[i] = Expr.assignStmt(p.e( + // E.Dot{ .name = "default", .name_loc = part.stmts[i].loc, .target = exports_identifier }, + // part.stmts[i].loc, + // ), default_expr, p.allocator); + // }, + // .s_local => |local| { + // if (!exports_identifier_set) { + // exports_identifier = p.e(E.Identifier{ .ref = p.exports_ref }, logger.Loc.Empty); + // exports_identifier_set = true; + // } + + // const items = local.decls; + + // for (items[1..]) |item| { + // assignment = Expr.joinWithComma(assignment, Expr.assign( + // p.e(E.Dot{ + // .name = item.alias, + // .target = exports_identifier, + // .name_loc = item.alias_loc, + // }, item.alias_loc), + // p.e( + // E.Identifier{ + // .ref = item.name.ref.?, + // }, + // item.name.loc, + // ), + // p.allocator, + // ), p.allocator); + // } + + // const original_loc = part.stmts[i].loc; + // part.stmts[i] = p.s(S.SExpr{ + // .value = assignment, + // }, original_loc); + + // }, + // .s_class => |class| { + // if (!exports_identifier_set) { + // exports_identifier = p.e(E.Identifier{ .ref = p.exports_ref }, logger.Loc.Empty); + // exports_identifier_set = true; + // } + + // part.stmts[i] = Expr.assignStmt( + // }, + + // .s_export_clause => |s_export| { + // const items = s_export.items; + // switch (items.len) { + // 0 => { + // part.stmts[i] = Stmt.empty(); + // }, + // 1 => { + // if (!exports_identifier_set) { + // exports_identifier = p.e(E.Identifier{ .ref = p.exports_ref }, logger.Loc.Empty); + // exports_identifier_set = true; + // } + + // part.stmts[i] = Expr.assignStmt(p.e( + // E.Dot{ + // .name = items[0].alias, + // .target = exports_identifier, + // .name_loc = items[0].alias_loc, + // }, + // items[0].alias_loc, + // ), p.e( + // E.Identifier{ + // .ref = items[0].name.ref.?, + // }, + // items[0].name.loc, + // ), p.allocator); + // }, + // else => { + // if (!exports_identifier_set) { + // exports_identifier = p.e(E.Identifier{ .ref = p.exports_ref }, logger.Loc.Empty); + // exports_identifier_set = true; + // } + // var assignment = Expr.assign(p.e( + // E.Dot{ + // .name = items[0].alias, + // .target = exports_identifier, + // .name_loc = items[0].alias_loc, + // }, + // items[0].alias_loc, + // ), p.e(E.Identifier{ + // .ref = items[0].name.ref.?, + // }, items[0].name.loc), p.allocator); + + // for (items[1..]) |item| { + // assignment = Expr.joinWithComma(assignment, Expr.assign( + // p.e(E.Dot{ + // .name = item.alias, + // .target = exports_identifier, + // .name_loc = item.alias_loc, + // }, item.alias_loc), + // p.e( + // E.Identifier{ + // .ref = item.name.ref.?, + // }, + // item.name.loc, + // ), + // p.allocator, + // ), p.allocator); + // } + + // const original_loc = part.stmts[i].loc; + // part.stmts[i] = p.s(S.SExpr{ + // .value = assignment, + // }, original_loc); + // }, + // } + // }, + .s_export_star, .s_export_from => { + exports_list[exports_list_i] = part.stmts[i]; + part.stmts[i] = Stmt.empty(); + part.stmts[i].loc = exports_list[exports_list_i].loc; + exports_list_i += 1; + }, + else => {}, + } + } + commonjs_wrapper.data.e_call.args[0] = p.e( E.Function{ .func = G.Fn{ .name = null, @@ -14260,8 +14409,8 @@ pub fn NewParser( } } commonjs_wrapper.data.e_call.args[1] = p.e(E.String{ .utf8 = sourcefile_name }, logger.Loc.Empty); - parts[parts.len - 1].stmts = p.allocator.alloc(Stmt, 1) catch unreachable; - parts[parts.len - 1].stmts[0] = p.s( + + new_stmts_list[imports_list.len] = p.s( S.ExportDefault{ .value = .{ .expr = commonjs_wrapper, @@ -14270,6 +14419,7 @@ pub fn NewParser( }, logger.Loc.Empty, ); + part.stmts = new_stmts_list; } else if (p.options.features.hot_module_reloading) { var named_exports_count: usize = p.named_exports.count(); const named_imports: js_ast.Ast.NamedImports = p.named_imports; @@ -14611,21 +14761,23 @@ pub fn NewParser( toplevel_stmts_i += 1; - if (named_export_i > 0) { - toplevel_stmts[toplevel_stmts_i] = p.s( - S.Local{ - .decls = exports_decls[0..named_export_i], - }, - logger.Loc.Empty, - ); - } else { - toplevel_stmts[toplevel_stmts_i] = p.s( - S.Empty{}, - logger.Loc.Empty, - ); - } + if (has_any_exports) { + if (named_export_i > 0) { + toplevel_stmts[toplevel_stmts_i] = p.s( + S.Local{ + .decls = exports_decls[0..named_export_i], + }, + logger.Loc.Empty, + ); + } else { + toplevel_stmts[toplevel_stmts_i] = p.s( + S.Empty{}, + logger.Loc.Empty, + ); + } - toplevel_stmts_i += 1; + toplevel_stmts_i += 1; + } toplevel_stmts[toplevel_stmts_i] = p.s( S.SExpr{ @@ -14641,7 +14793,7 @@ pub fn NewParser( p.e( E.Function{ .func = .{ - .body = .{ .loc = logger.Loc.Empty, .stmts = update_function_stmts[0..named_export_i] }, + .body = .{ .loc = logger.Loc.Empty, .stmts = if (named_export_i > 0) update_function_stmts[0..named_export_i] else &.{} }, .name = null, .args = update_function_args, .open_parens_loc = logger.Loc.Empty, @@ -14655,22 +14807,22 @@ pub fn NewParser( logger.Loc.Empty, ); toplevel_stmts_i += 1; - if (named_export_i > 0) { - toplevel_stmts[toplevel_stmts_i] = p.s( - S.ExportClause{ - .items = export_clauses[0..named_export_i], - }, - logger.Loc.Empty, - ); - } else { - toplevel_stmts[toplevel_stmts_i] = p.s( - S.Empty{}, - logger.Loc.Empty, - ); + if (has_any_exports) { + if (named_export_i > 0) { + toplevel_stmts[toplevel_stmts_i] = p.s( + S.ExportClause{ + .items = export_clauses[0..named_export_i], + }, + logger.Loc.Empty, + ); + } else { + toplevel_stmts[toplevel_stmts_i] = p.s( + S.Empty{}, + logger.Loc.Empty, + ); + } } - toplevel_stmts_i += 1; - part.stmts = _stmts[0 .. imports_list.len + toplevel_stmts.len + exports_from.len]; } diff --git a/src/js_printer.zig b/src/js_printer.zig index 706b52503..12c92f9fc 100644 --- a/src/js_printer.zig +++ b/src/js_printer.zig @@ -213,6 +213,7 @@ pub fn NewPrinter( comptime Linker: type, comptime rewrite_esm_to_cjs: bool, comptime bun: bool, + comptime is_inside_bundle: bool, ) type { return struct { symbols: Symbol.Map, @@ -2315,7 +2316,7 @@ pub fn NewPrinter( p.printIndent(); p.printSpaceBeforeIdentifier(); - if (!rewrite_esm_to_cjs) { + if (!is_inside_bundle) { p.print("export default"); } @@ -2323,7 +2324,7 @@ pub fn NewPrinter( switch (s.value) { .expr => |expr| { - if (rewrite_esm_to_cjs) { + if (is_inside_bundle) { p.printModuleExportSymbol(); p.print(".default = "); } @@ -2339,7 +2340,7 @@ pub fn NewPrinter( switch (s2.data) { .s_function => |func| { p.printSpaceBeforeIdentifier(); - if (rewrite_esm_to_cjs) { + if (is_inside_bundle) { if (func.func.name) |name| { // p.print("var "); // p.printSymbol(name.ref.?); @@ -2368,15 +2369,13 @@ pub fn NewPrinter( p.printFunc(func.func); - if (rewrite_esm_to_cjs) { + if (is_inside_bundle) { p.printSemicolonAfterStatement(); - if (rewrite_esm_to_cjs) { - if (func.func.name) |name| { - p.printIndent(); - p.printBundledExport("default", p.renamer.nameForSymbol(name.ref.?)); - p.printSemicolonAfterStatement(); - } + if (func.func.name) |name| { + p.printIndent(); + p.printBundledExport("default", p.renamer.nameForSymbol(name.ref.?)); + p.printSemicolonAfterStatement(); } } else { p.printNewline(); @@ -2385,7 +2384,7 @@ pub fn NewPrinter( .s_class => |class| { p.printSpaceBeforeIdentifier(); - if (rewrite_esm_to_cjs) { + if (is_inside_bundle) { if (class.class.class_name) |name| { // p.print("var "); // p.printSymbol(name.ref.?); @@ -2405,7 +2404,7 @@ pub fn NewPrinter( p.printClass(class.class); - if (rewrite_esm_to_cjs) { + if (is_inside_bundle) { p.printSemicolonAfterStatement(); if (class.class.class_name) |name| { @@ -2425,7 +2424,7 @@ pub fn NewPrinter( } }, .s_export_star => |s| { - if (rewrite_esm_to_cjs) { + if (is_inside_bundle) { p.printIndent(); p.printSpaceBeforeIdentifier(); @@ -2566,7 +2565,7 @@ pub fn NewPrinter( p.printSemicolonAfterStatement(); }, .s_export_from => |s| { - if (rewrite_esm_to_cjs) { + if (is_inside_bundle) { const record = p.import_records[s.import_record_index]; // $$lz(export, $React(), {default: "React"}); @@ -2935,7 +2934,7 @@ pub fn NewPrinter( p.printIndent(); p.printSpaceBeforeIdentifier(); - if (rewrite_esm_to_cjs) { + if (is_inside_bundle) { return p.printBundledImport(record, s, stmt); } @@ -3646,7 +3645,7 @@ pub fn NewPrinter( } pub fn printDeclStmt(p: *Printer, is_export: bool, comptime keyword: string, decls: []G.Decl) void { - if (rewrite_esm_to_cjs and keyword[0] == 'v' and is_export) { + if (rewrite_esm_to_cjs and keyword[0] == 'v' and is_export and is_inside_bundle) { // this is a top-level export if (decls.len == 1 and std.meta.activeTag(decls[0].binding.data) == .b_identifier and @@ -3680,9 +3679,16 @@ pub fn NewPrinter( for (decls) |decl, i| { p.print("'"); p.printBinding(decl.binding); - p.print("': {get: () => ("); + p.print("': {get: () => "); p.printBinding(decl.binding); - p.print("), enumerable: true, configurable: true}"); + + if (comptime !strings.eqlComptime(keyword, "const")) { + p.print(", set: ($_newValue) => {"); + p.printBinding(decl.binding); + p.print(" = $_newValue;}"); + } + + p.print(", enumerable: true, configurable: true}"); if (i < decls.len - 1) { p.print(",\n"); @@ -4040,7 +4046,7 @@ pub fn printAst( comptime LinkerType: type, linker: ?*LinkerType, ) !usize { - const PrinterType = NewPrinter(false, Writer, LinkerType, false, false); + const PrinterType = NewPrinter(false, Writer, LinkerType, false, false, false); var writer = _writer; var printer = try PrinterType.init( @@ -4086,7 +4092,7 @@ pub fn printCommonJS( comptime LinkerType: type, linker: ?*LinkerType, ) !usize { - const PrinterType = NewPrinter(false, Writer, LinkerType, true, false); + const PrinterType = NewPrinter(false, Writer, LinkerType, true, false, false); var writer = _writer; var printer = try PrinterType.init( writer, @@ -4144,7 +4150,7 @@ pub fn printCommonJSThreaded( comptime getPos: fn (ctx: GetPosType) anyerror!u64, end_off_ptr: *u32, ) !WriteResult { - const PrinterType = NewPrinter(false, Writer, LinkerType, true, false); + const PrinterType = NewPrinter(false, Writer, LinkerType, true, false, true); var writer = _writer; var printer = try PrinterType.init( writer, diff --git a/src/linker.zig b/src/linker.zig index efcde5a24..182fe3b3c 100644 --- a/src/linker.zig +++ b/src/linker.zig @@ -365,6 +365,8 @@ pub fn NewLinker(comptime BundlerType: type) type { result.ast.needs_runtime = true; needs_require = true; + } else if (result.ast.exports_kind == .cjs) { + import_record.module_id = @truncate(u32, std.hash.Wyhash.hash(0, path.pretty)); } } else |err| { had_resolve_errors = true; diff --git a/src/options.zig b/src/options.zig index ab248da1d..02d44fa08 100644 --- a/src/options.zig +++ b/src/options.zig @@ -1181,7 +1181,11 @@ pub const BundleOptions = struct { if (isWindows and opts.routes.static_dir_handle != null) { opts.routes.static_dir_handle.?.close(); } - opts.hot_module_reloading = opts.platform.isWebLike() and !(transform.disable_hmr orelse false); + opts.hot_module_reloading = opts.platform.isWebLike(); + + if (transform.disable_hmr orelse false) + opts.hot_module_reloading = false; + opts.serve = true; } diff --git a/src/runtime/hmr.ts b/src/runtime/hmr.ts index 213192c4f..4a8ccca43 100644 --- a/src/runtime/hmr.ts +++ b/src/runtime/hmr.ts @@ -66,6 +66,11 @@ if (typeof window !== "undefined") { cancel: false, lastError: null, render(error, cwd) { + if ("__BunRenderBuildError" in globalThis) { + globalThis.__BunRenderBuildError(error, cwd); + return; + } + BunError.lastError = [error, cwd]; BunError.cancel = false; @@ -1076,6 +1081,15 @@ if (typeof window !== "undefined") { URL.revokeObjectURL(blobURL); // Ensure we don't keep the bytes around longer than necessary this.bytes = null; + + if ("__BunRenderHMRError" in globalThis) { + globalThis.__BunRenderHMRError( + exception, + oldModule.file_path, + oldModule.id + ); + } + oldModule = null; throw exception; } |