diff options
-rw-r--r-- | src/bundler.zig | 36 | ||||
-rw-r--r-- | src/js_printer.zig | 278 | ||||
-rw-r--r-- | src/runtime.js | 13 | ||||
-rw-r--r-- | src/runtime.version | 2 | ||||
-rw-r--r-- | src/runtime.zig | 8 |
5 files changed, 306 insertions, 31 deletions
diff --git a/src/bundler.zig b/src/bundler.zig index d347aaedb..bb10af3f4 100644 --- a/src/bundler.zig +++ b/src/bundler.zig @@ -207,7 +207,7 @@ pub fn NewBundler(cache_files: bool) type { package_list: std.ArrayList(Api.JavascriptBundledPackage), header_string_buffer: MutableString, // Just need to know if we've already enqueued this one - resolved_paths: hash_map.StringHashMap(void), + resolved_paths: hash_map.StringHashMap(u32), package_list_map: std.AutoHashMap(u64, u32), resolve_queue: std.fifo.LinearFifo(_resolver.Result, .Dynamic), bundler: *ThisBundler, @@ -276,7 +276,7 @@ pub fn NewBundler(cache_files: bool) type { .scan_pass_result = js_parser.ScanPassResult.init(allocator), .header_string_buffer = try MutableString.init(allocator, 0), .allocator = allocator, - .resolved_paths = hash_map.StringHashMap(void).init(allocator), + .resolved_paths = hash_map.StringHashMap(u32).init(allocator), .resolve_queue = std.fifo.LinearFifo(_resolver.Result, .Dynamic).init(allocator), .bundler = bundler, .tmpfile = tmpfile, @@ -534,27 +534,36 @@ pub fn NewBundler(cache_files: bool) type { // This reduces metadata size by about 30% for a large-ish file // A future optimization here could be to reuse the string from the original path var node_module_root = strings.indexOf(resolved_import.path_pair.primary.text, node_module_root_string) orelse unreachable; - // // omit package name - node_module_root += package_json.name.len; + // omit node_modules node_module_root += node_module_root_string.len; + // // omit package name + node_module_root += package_json.name.len; + + node_module_root += 1; + // It should be the first index, not the last to support bundling multiple of the same package import_record.path = Fs.Path.init( absolute_path[node_module_root..], ); - hasher = std.hash.Wyhash.init(0); - hasher.update(import_record.path.text); - hasher.update(std.mem.asBytes(&package_json.hash)); - import_record.module_id = @truncate(u32, hasher.final()); - import_record.is_bundled = true; const get_or_put_result = try this.resolved_paths.getOrPut(absolute_path); if (get_or_put_result.found_existing) { + import_record.module_id = get_or_put_result.entry.value; + import_record.is_bundled = true; continue; } + hasher = std.hash.Wyhash.init(0); + hasher.update(import_record.path.text); + hasher.update(std.mem.asBytes(&package_json.hash)); + + import_record.module_id = @truncate(u32, hasher.final()); + get_or_put_result.entry.value = import_record.module_id; + import_record.is_bundled = true; + try this.resolve_queue.writeItem(_resolved_import.*); } else |err| {} } @@ -585,6 +594,7 @@ pub fn NewBundler(cache_files: bool) type { const E = js_ast.E; const Expr = js_ast.Expr; const Stmt = js_ast.Stmt; + var part = &ast.parts[ast.parts.len - 1]; var new_stmts: [1]Stmt = undefined; var register_args: [4]Expr = undefined; @@ -595,6 +605,12 @@ pub fn NewBundler(cache_files: bool) type { var cjs_args: [2]js_ast.G.Arg = undefined; var module_binding = js_ast.B.Identifier{ .ref = ast.module_ref.? }; var exports_binding = js_ast.B.Identifier{ .ref = ast.exports_ref.? }; + + // if (!ast.uses_module_ref) { + // var symbol = &ast.symbols[ast.module_ref.?.inner_index]; + // symbol.original_name = "_$$"; + // } + cjs_args[0] = js_ast.G.Arg{ .binding = js_ast.Binding{ .loc = logger.Loc.Empty, @@ -652,7 +668,7 @@ pub fn NewBundler(cache_files: bool) type { var symbols: [][]js_ast.Symbol = &([_][]js_ast.Symbol{ast.symbols}); hasher = std.hash.Wyhash.init(0); hasher.update(package_relative_path); - hasher.update(std.mem.asBytes(&package.hash)); + hasher.update(std.mem.asBytes(&package.hash)[0..4]); const module_id = @truncate(u32, hasher.final()); const code_length = @truncate( diff --git a/src/js_printer.zig b/src/js_printer.zig index 54cf7611c..0e7ca5201 100644 --- a/src/js_printer.zig +++ b/src/js_printer.zig @@ -936,13 +936,13 @@ pub fn NewPrinter( } }, .e_require => |e| { - if (rewrite_esm_to_cjs) { + if (rewrite_esm_to_cjs and p.import_records[e.import_record_index].is_bundled) { p.printIndent(); p.printBundledRequire(e.*); p.printSemicolonIfNeeded(); } - if (!rewrite_esm_to_cjs) { + if (!rewrite_esm_to_cjs or !p.import_records[e.import_record_index].is_bundled) { p.printRequireOrImportExpr(e.import_record_index, &([_]G.Comment{}), level, flags); } }, @@ -2138,8 +2138,19 @@ pub fn NewPrinter( .s_function => |s| { p.printIndent(); p.printSpaceBeforeIdentifier(); + const name = s.func.name orelse Global.panic("Internal error: expected func to have a name ref\n{s}", .{s}); + const nameRef = name.ref orelse Global.panic("Internal error: expected func to have a name\n{s}", .{s}); if (s.func.flags.is_export) { - p.print("export "); + if (!rewrite_esm_to_cjs) { + p.print("export "); + } else { + if (rewrite_esm_to_cjs) { + p.printSymbol(p.options.runtime_imports.__export.?); + p.print("."); + p.printSymbol(nameRef); + p.print(" = "); + } + } } if (s.func.flags.is_async) { p.print("async "); @@ -2149,8 +2160,7 @@ pub fn NewPrinter( p.print("*"); p.printSpace(); } - const name = s.func.name orelse Global.panic("Internal error: expected func to have a name ref\n{s}", .{s}); - const nameRef = name.ref orelse Global.panic("Internal error: expected func to have a name\n{s}", .{s}); + p.printSpace(); p.printSymbol(nameRef); p.printFunc(s.func); @@ -2165,8 +2175,18 @@ pub fn NewPrinter( p.printIndent(); p.printSpaceBeforeIdentifier(); if (s.is_export) { - p.print("export "); + if (!rewrite_esm_to_cjs) { + p.print("export "); + } + + if (rewrite_esm_to_cjs) { + p.printSymbol(p.options.runtime_imports.__export.?); + p.print("."); + p.printSymbol(s.class.class_name.?.ref.?); + p.print(" = "); + } } + p.print("class "); p.printSymbol(s.class.class_name.?.ref.?); p.printClass(s.class); @@ -2245,6 +2265,32 @@ pub fn NewPrinter( } }, .s_export_star => |s| { + if (rewrite_esm_to_cjs) { + p.printIndent(); + p.printSpaceBeforeIdentifier(); + + // module.exports.react = $react(); + if (s.alias) |alias| { + p.printSymbol(p.options.runtime_imports.__export.?); + p.print("."); + p.printClauseAlias(alias.original_name); + p.print(" = "); + p.printLoadFromBundle(s.import_record_index); + p.printSemicolonAfterStatement(); + return; + // module.exports = $react(); + } else { + p.printSymbol(p.options.runtime_imports.__reExport.?); + p.print("("); + p.printSymbol(p.options.runtime_imports.__export.?); + p.print(","); + p.printLoadFromBundle(s.import_record_index); + p.print(")"); + p.printSemicolonAfterStatement(); + return; + } + } + // Give an extra newline for readaiblity if (!prev_stmt_tag.isExportLike()) { p.printNewline(); @@ -2268,6 +2314,56 @@ pub fn NewPrinter( p.printSemicolonAfterStatement(); }, .s_export_clause => |s| { + if (rewrite_esm_to_cjs) { + p.printIndent(); + p.printSpaceBeforeIdentifier(); + + switch (s.items.len) { + 0 => {}, + // __export.prop1 = prop1; + 1 => { + const item = s.items[0]; + + p.printSymbol(p.options.runtime_imports.__export.?); + p.print("."); + const name = p.renamer.nameForSymbol(item.name.ref.?); + if (!strings.eql(name, item.alias)) { + p.printClauseAlias(item.alias); + } else { + p.printIdentifier(name); + } + p.print(" = "); + p.printIdentifier(name); + p.printSemicolonAfterStatement(); + }, + + // Object.assign(__export, {prop1, prop2, prop3}); + else => { + p.print("Object.assign"); + p.print("("); + p.printSymbol(p.options.runtime_imports.__export.?); + p.print(", {"); + const last = s.items.len - 1; + for (s.items) |item, i| { + const name = p.renamer.nameForSymbol(item.name.ref.?); + p.printIdentifier(name); + if (!strings.eql(name, item.alias)) { + p.print(":"); + p.printSpace(); + p.printClauseAlias(item.alias); + } + + if (i < last) { + p.print(","); + } + } + p.print("})"); + p.printSemicolonAfterStatement(); + }, + } + return; + } + // Give an extra newline for export default for readability if (!prev_stmt_tag.isExportLike()) { p.printNewline(); @@ -2313,9 +2409,48 @@ pub fn NewPrinter( p.printSemicolonAfterStatement(); }, .s_export_from => |s| { - // Give an extra newline for readaiblity - if (!prev_stmt_tag.isExportLike()) { - p.printNewline(); + if (rewrite_esm_to_cjs) { + const record = p.import_records[s.import_record_index]; + + // $$lz(export, $React(), {default: "React"}); + if (s.items.len == 1) { + const item = s.items[0]; + p.printSymbol(p.options.runtime_imports.lazy_export.?); + p.print("("); + p.printSymbol(p.options.runtime_imports.__export.?); + p.print(","); + // Avoid initializing an entire component library because you imported one icon + p.printLoadFromBundleWithoutCall(s.import_record_index); + p.print(",{"); + p.printClauseAlias(item.alias); + p.print(":"); + const name = p.renamer.nameForSymbol(item.name.ref.?); + p.printQuotedUTF8(name, true); + p.print("})"); + + p.printSemicolonAfterStatement(); + // $$lz(export, $React(), {createElement: "React"}); + } else { + p.printSymbol(p.options.runtime_imports.lazy_export.?); + p.print("("); + p.printSymbol(p.options.runtime_imports.__export.?); + + // Avoid initializing an entire component library because you imported one icon + p.printLoadFromBundleWithoutCall(s.import_record_index); + p.print(",{"); + for (s.items) |item, i| { + p.printClauseAlias(item.alias); + p.print(":"); + p.printQuotedUTF8(p.renamer.nameForSymbol(item.name.ref.?), true); + if (i < s.items.len - 1) { + p.print(","); + } + } + p.print("})"); + p.printSemicolonAfterStatement(); + } + + return; } p.printIndent(); p.printSpaceBeforeIdentifier(); @@ -2836,11 +2971,13 @@ pub fn NewPrinter( var variant = ImportVariant.path_only; - if (s.star_name_loc != null and s.star_name_loc.?.start > -1) { + var namespace = p.symbols.get(s.namespace_ref).?; + + if (record.contains_import_star) { variant = variant.hasStar(); } - if (s.default_name != null) { + if (record.contains_default_alias or s.default_name != null) { variant = variant.hasDefault(); } @@ -2849,7 +2986,8 @@ pub fn NewPrinter( } switch (variant) { - .import_star => { + // we treat path_only the same as import_star because we may have property accesses using it. + .path_only, .import_star => { p.print("var "); p.printSymbol(s.namespace_ref); p.print(" = "); @@ -2906,20 +3044,107 @@ pub fn NewPrinter( p.printSemicolonAfterStatement(); }, - .import_items_and_default => {}, - .import_items_and_star => {}, - .import_items_and_default_and_star => {}, - .path_only => { + .import_items_and_default => { + p.print("var {"); + + const default_name = s.default_name.?.ref.?; + p.print("default: "); + p.printSymbol(default_name); + + for (s.items) |*item, i| { + p.print(","); + + p.printClauseAlias(item.alias); + const name = p.renamer.nameForSymbol(item.name.ref.?); + if (!strings.eql(name, item.alias)) { + p.printSpace(); + p.print(":"); + p.printSpaceBeforeIdentifier(); + p.printIdentifier(name); + } + } + + p.print("}"); + p.print(" = "); + p.printLoadFromBundle(s.import_record_index); + + p.printSemicolonAfterStatement(); + }, + .import_items_and_star => { + p.print("var "); + + p.printSymbol(s.namespace_ref); + p.print(" = "); + p.printLoadFromBundle(s.import_record_index); + p.print(", {"); + + for (s.items) |*item, i| { + if (i > 0) { + p.print(","); + } + + p.printClauseAlias(item.alias); + const name = p.renamer.nameForSymbol(item.name.ref.?); + if (!strings.eql(name, item.alias)) { + p.printSpace(); + p.print(":"); + p.printSpaceBeforeIdentifier(); + p.printIdentifier(name); + } + } + + p.print("} = "); + p.printSymbol(s.namespace_ref); + p.printSemicolonAfterStatement(); + }, + .import_items_and_default_and_star => { + p.print("var "); + + p.printSymbol(s.namespace_ref); + p.print(" = "); p.printLoadFromBundle(s.import_record_index); + p.print(", {"); + + const default_name = s.default_name.?.ref.?; + p.print("default: "); + p.printSymbol(default_name); + + for (s.items) |*item, i| { + p.print(","); + + p.printClauseAlias(item.alias); + const name = p.renamer.nameForSymbol(item.name.ref.?); + if (!strings.eql(name, item.alias)) { + p.printSpace(); + p.print(":"); + + p.printIdentifier(name); + } + } + + p.print("}"); + p.print(" = "); + p.printSymbol(s.namespace_ref); + p.printSemicolonAfterStatement(); }, + // .path_only => { + // p.printLoadFromBundle(s.import_record_index); + // p.print("/* "); + // p.printSymbol(s.namespace_ref); + // p.print(" */"); + // p.printSemicolonAfterStatement(); + // }, } } pub fn printLoadFromBundle(p: *Printer, import_record_index: u32) void { + p.printLoadFromBundleWithoutCall(import_record_index); + p.print("()"); + } + pub fn printLoadFromBundleWithoutCall(p: *Printer, import_record_index: u32) void { const record = p.import_records[import_record_index]; p.print("$"); - std.fmt.formatInt(record.module_id, 16, true, .{}, p) catch unreachable; - p.print("()"); + std.fmt.formatInt(record.module_id, 16, false, .{}, p) catch unreachable; } pub fn printBundledRequire(p: *Printer, require: E.Require) void { if (p.import_records[require.import_record_index].is_internal) { @@ -3071,7 +3296,7 @@ pub fn NewPrinter( p.print("// "); p.print(p.options.source_path.?.pretty); p.print("\nexport var $"); - std.fmt.formatInt(p.options.module_hash, 16, true, .{}, p) catch unreachable; + std.fmt.formatInt(p.options.module_hash, 16, false, .{}, p) catch unreachable; p.print(" = "); p.printExpr(decls[0].value.?, .comma, ExprFlag.None()); p.printSemicolonAfterStatement(); @@ -3087,6 +3312,21 @@ pub fn NewPrinter( } p.printDecls(keyword, decls, ExprFlag.None()); p.printSemicolonAfterStatement(); + if (rewrite_esm_to_cjs and is_export and decls.len > 0) { + p.printIndent(); + p.printSpaceBeforeIdentifier(); + for (decls) |decl, i| { + p.printSymbol(p.options.runtime_imports.__export.?); + p.print("."); + p.printBinding(decl.binding); + p.print(" = "); + p.printBinding(decl.binding); + if (i < decls.len - 1) { + p.print(","); + } + } + p.printSemicolonAfterStatement(); + } } pub fn printIdentifier(p: *Printer, identifier: string) void { diff --git a/src/runtime.js b/src/runtime.js index 5d204a922..ddcdaddd7 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -22,6 +22,17 @@ export var __reExport = (target, module, desc) => { return target; }; +export var $$lz = (target, module, props) => { + for (key in props) { + if (!__hasOwnProp.call(target, key) && key !== "default") + __defProp(target, key, { + get: () => module()[props[key]], + enumerable: true, + }); + } + return target; +}; + export var __toModule = (module) => { return __reExport( __markAsModule( @@ -43,7 +54,7 @@ export var __commonJS = return ( mod, // friendly name for any errors while requiring - (__name(cb, `export default ${name}`), + (__name(cb, name), cb((mod = { exports: {} }), mod.exports), __name(mod, name), mod), diff --git a/src/runtime.version b/src/runtime.version index 6bf95182a..b48df3c1c 100644 --- a/src/runtime.version +++ b/src/runtime.version @@ -1 +1 @@ -6e0bb8ddff21cfa4
\ No newline at end of file +9e9dfde98026fc70
\ No newline at end of file diff --git a/src/runtime.zig b/src/runtime.zig index 5526d589f..5eceba772 100644 --- a/src/runtime.zig +++ b/src/runtime.zig @@ -24,6 +24,7 @@ pub const Runtime = struct { __load: ?Ref = null, load_from_bundle: ?Ref = null, register: ?Ref = null, + lazy_export: ?Ref = null, pub const all = [_][]const u8{ "__name", @@ -37,6 +38,7 @@ pub const Runtime = struct { "load_from_bundle", // "register", + "lazy_export", }; pub const Name = "<RUNTIME"; @@ -100,6 +102,11 @@ pub const Runtime = struct { return Entry{ .key = 8, .value = val }; } }, + 9 => { + if (@field(this.runtime_imports, all[9])) |val| { + return Entry{ .key = 9, .value = val }; + } + }, else => { return null; @@ -154,6 +161,7 @@ pub const Runtime = struct { 6 => @field(imports, all[6]), 7 => @field(imports, all[7]), 8 => @field(imports, all[8]), + 9 => @field(imports, all[9]), else => null, }; } |