diff options
Diffstat (limited to '')
-rw-r--r-- | src/js_printer.zig | 202 |
1 files changed, 135 insertions, 67 deletions
diff --git a/src/js_printer.zig b/src/js_printer.zig index 82c849df9..42af0cd63 100644 --- a/src/js_printer.zig +++ b/src/js_printer.zig @@ -189,6 +189,8 @@ const ImportVariant = enum { variant = variant.hasDefault(); } } + } else { + variant = variant.hasDefault(); } if (s_import.items.len > 0) { @@ -224,6 +226,8 @@ pub fn NewPrinter( call_target: ?Expr.Data = null, writer: Writer, + has_printed_bundled_import_statement: bool = false, + renamer: rename.Renamer, prev_stmt_tag: Stmt.Tag = .s_empty, @@ -520,6 +524,12 @@ pub fn NewPrinter( backtick_cost += 1; } }, + '\r', '\n' => { + if (comptime isDebug) { + std.debug.assert(allow_backtick); + } + return '`'; + }, else => {}, } i += 1; @@ -1869,11 +1879,13 @@ pub fn NewPrinter( // "=" and ":" are not valid // So we need to check var needs_quoted = !js_lexer.isIdentifierStart(@intCast(js_lexer.CodePoint, key.utf8[0])); - var i: usize = 1; - while (i < key.utf8.len and !needs_quoted) : (i += 1) { - if (!js_lexer.isIdentifierContinue(@intCast(js_lexer.CodePoint, key.utf8[i]))) { - needs_quoted = true; - break; + if (!needs_quoted) { + var i: usize = 1; + while (i < key.utf8.len) : (i += 1) { + if (!js_lexer.isIdentifierContinue(@intCast(js_lexer.CodePoint, key.utf8[i]))) { + needs_quoted = true; + break; + } } } @@ -2118,17 +2130,27 @@ pub fn NewPrinter( if (str.isUTF8()) { p.addSourceMapping(property.key.loc); p.printSpaceBeforeIdentifier(); - p.printIdentifier(str.utf8); - - // Use a shorthand property if the names are the same - switch (property.value.data) { - .b_identifier => |id| { - if (str.eql(string, p.renamer.nameForSymbol(id.ref))) { - p.maybePrintDefaultBindingValue(property); - continue; - } - }, - else => {}, + // Example case: + // const Menu = React.memo(function Menu({ + // aria-label: ariaLabel, + // ^ + // That needs to be: + // "aria-label": ariaLabel, + if (p.canPrintIdentifier(str.utf8)) { + p.printIdentifier(str.utf8); + + // Use a shorthand property if the names are the same + switch (property.value.data) { + .b_identifier => |id| { + if (str.eql(string, p.renamer.nameForSymbol(id.ref))) { + p.maybePrintDefaultBindingValue(property); + continue; + } + }, + else => {}, + } + } else { + p.printQuotedUTF8(str.utf8, false); } } else if (p.canPrintIdentifierUTF16(str.value)) { p.addSourceMapping(property.key.loc); @@ -2245,11 +2267,7 @@ pub fn NewPrinter( if (rewrite_esm_to_cjs and s.func.flags.is_export) { p.printIndent(); - p.printSymbol(p.options.runtime_imports.__export.?); - p.print("."); - p.printSymbol(nameRef); - p.print(" = "); - p.printSymbol(nameRef); + p.printBundledExport(p.renamer.nameForSymbol(nameRef), p.renamer.nameForSymbol(nameRef)); p.printSemicolonAfterStatement(); } }, @@ -2287,11 +2305,7 @@ pub fn NewPrinter( if (rewrite_esm_to_cjs) { if (s.is_export) { p.printIndent(); - p.printSymbol(p.options.runtime_imports.__export.?); - p.print("."); - p.printSymbol(nameRef); - p.print(" = "); - p.printSymbol(nameRef); + p.printBundledExport(p.renamer.nameForSymbol(nameRef), p.renamer.nameForSymbol(nameRef)); p.printSemicolonAfterStatement(); } } @@ -2369,10 +2383,7 @@ pub fn NewPrinter( if (rewrite_esm_to_cjs) { if (func.func.name) |name| { p.printIndent(); - p.printSpaceBeforeIdentifier(); - p.printSymbol(p.options.runtime_imports.__export.?); - p.print(".default = "); - p.printSymbol(name.ref.?); + p.printBundledExport("default", p.renamer.nameForSymbol(name.ref.?)); p.printSemicolonAfterStatement(); } } @@ -2408,10 +2419,7 @@ pub fn NewPrinter( if (class.class.class_name) |name| { p.printIndent(); - p.printSpaceBeforeIdentifier(); - p.printSymbol(p.options.runtime_imports.__export.?); - p.print(".default = "); - p.printSymbol(name.ref.?); + p.printBundledExport("default", p.renamer.nameForSymbol(name.ref.?)); p.printSemicolonAfterStatement(); } } else { @@ -2432,12 +2440,9 @@ pub fn NewPrinter( // 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.printBundledRexport(alias.original_name, s.import_record_index); p.printSemicolonAfterStatement(); + return; // module.exports = $react(); } else { @@ -2445,7 +2450,9 @@ pub fn NewPrinter( p.print("("); p.printSymbol(p.options.runtime_imports.__export.?); p.print(","); + p.printLoadFromBundle(s.import_record_index); + p.print(")"); p.printSemicolonAfterStatement(); return; @@ -2481,20 +2488,17 @@ pub fn NewPrinter( switch (s.items.len) { 0 => {}, - // __export.prop1 = prop1; + // It unfortunately cannot be so simple as exports.foo = foo; + // If we have a lazy re-export and it's read-only... + // we have to overwrite it via Object.defineProperty 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); + const identifier = p.renamer.nameForSymbol(item.name.ref.?); + const name = if (!strings.eql(identifier, item.alias)) + item.alias + else + identifier; + p.printBundledExport(name, identifier); p.printSemicolonAfterStatement(); }, @@ -2978,13 +2982,46 @@ pub fn NewPrinter( return; } } else if (record.is_bundled) { - p.print("import {"); + if (!record.path.is_disabled) { + if (!p.has_printed_bundled_import_statement) { + p.has_printed_bundled_import_statement = true; + p.print("import {"); + + const last = p.import_records.len - 1; + var needs_comma = false; + // This might be a determinsim issue + // But, it's not random + skip: for (p.import_records) |_record, i| { + if (!_record.is_bundled or _record.module_id == 0) continue; - p.printLoadFromBundleWithoutCall(s.import_record_index); + if (i < last) { + // Prevent importing the same module ID twice + // We could use a map but we want to avoid allocating + // and this should be pretty quick since it's just comparing a uint32 + for (p.import_records[i + 1 ..]) |_record2| { + if (_record2.is_bundled and _record2.module_id > 0 and _record2.module_id == _record.module_id) { + continue :skip; + } + } + } - p.print("} from "); - p.printQuotedUTF8(record.path.text, false); - p.printSemicolonAfterStatement(); + if (needs_comma) p.print(", "); + p.printLoadFromBundleWithoutCall(@truncate(u32, i)); + needs_comma = true; + } + + p.print("} from "); + + p.printQuotedUTF8(record.path.text, false); + p.printSemicolonAfterStatement(); + } + } else { + p.print("var "); + + p.printLoadFromBundleWithoutCall(s.import_record_index); + + p.print(" = () => ({default: {}});\n"); + } if (s.items.len > 0) { p.printIndent(); @@ -3248,8 +3285,6 @@ pub fn NewPrinter( .import_items => { p.print("var {"); - var item_count: usize = 0; - for (s.items) |*item, i| { if (i != 0) { p.print(","); @@ -3266,7 +3301,6 @@ pub fn NewPrinter( p.printSpaceBeforeIdentifier(); p.printIdentifier(name); } - item_count += 1; } p.print("}"); @@ -3278,12 +3312,20 @@ pub fn NewPrinter( .import_items_and_default => { p.print("var {"); - const default_name = s.default_name.?.ref.?; - p.print("default: "); - p.printSymbol(default_name); + var need_comma = false; + if (s.default_name) |default_name| { + if (default_name.ref) |ref| { + p.print("default: "); + p.printSymbol(ref); + need_comma = true; + } + } for (s.items) |*item, i| { - p.print(","); + if (need_comma) + p.print(","); + + defer need_comma = true; p.printClauseAlias(item.alias); const name = p.renamer.nameForSymbol(item.name.ref.?); @@ -3392,6 +3434,27 @@ pub fn NewPrinter( p.printLoadFromBundle(require.import_record_index); } + pub fn printBundledRexport(p: *Printer, name: string, import_record_index: u32) void { + p.print("Object.defineProperty("); + p.print("module.exports"); + p.print(","); + p.printQuotedUTF8(name, true); + + p.print(",{get: () => ("); + p.printLoadFromBundle(import_record_index); + p.print("), enumerable: true, configurable: true})"); + } + + pub fn printBundledExport(p: *Printer, name: string, identifier: string) void { + p.print("Object.defineProperty("); + p.print("module.exports"); + p.print(","); + p.printQuotedUTF8(name, true); + p.print(",{get: () => ("); + p.printIdentifier(identifier); + p.print("), enumerable: true, configurable: true})"); + } + pub fn printForLoopInit(p: *Printer, initSt: Stmt) void { switch (initSt.data) { .s_expr => |s| { @@ -3553,16 +3616,21 @@ pub fn NewPrinter( if (rewrite_esm_to_cjs and is_export and decls.len > 0) { p.printIndent(); p.printSpaceBeforeIdentifier(); + p.print("Object.defineProperties("); + p.printSymbol(p.options.runtime_imports.__export.?); + p.print(",{"); for (decls) |decl, i| { - p.printSymbol(p.options.runtime_imports.__export.?); - p.print("."); + p.print("'"); p.printBinding(decl.binding); - p.print(" = "); + p.print("': {get: () => ("); p.printBinding(decl.binding); + p.print("), enumerable: true, configurable: true}"); + if (i < decls.len - 1) { - p.print(","); + p.print(",\n"); } } + p.print("})"); p.printSemicolonAfterStatement(); } } |