From 9b3fa336d3a0acf0efe233266a1d38259c5a37ec Mon Sep 17 00:00:00 2001 From: pfg Date: Fri, 17 Jan 2025 13:15:40 -0800 Subject: [PATCH 1/2] Strop query parameter in File import --- src/bun.js/module_loader.zig | 2 +- test/regression/issue/16476/16476.test.ts | 13 +++++++++++++ test/regression/issue/16476/a.txt | 1 + test/regression/issue/16476/a.wasm | Bin 0 -> 61 bytes 4 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 test/regression/issue/16476/16476.test.ts create mode 100644 test/regression/issue/16476/a.txt create mode 100755 test/regression/issue/16476/a.wasm diff --git a/src/bun.js/module_loader.zig b/src/bun.js/module_loader.zig index a015716e913a7f..e9a86f166e07dd 100644 --- a/src/bun.js/module_loader.zig +++ b/src/bun.js/module_loader.zig @@ -2184,7 +2184,7 @@ pub const ModuleLoader = struct { } else { // search keywords: "export default \"{}\";" writer.writeAll("export default ") catch bun.outOfMemory(); - buf = js_printer.quoteForJSON(specifier, buf, true) catch bun.outOfMemory(); + buf = js_printer.quoteForJSON(path.text, buf, true) catch bun.outOfMemory(); writer = buf.writer(); writer.writeAll(";\n") catch bun.outOfMemory(); } diff --git a/test/regression/issue/16476/16476.test.ts b/test/regression/issue/16476/16476.test.ts new file mode 100644 index 00000000000000..6b2b997b8614ef --- /dev/null +++ b/test/regression/issue/16476/16476.test.ts @@ -0,0 +1,13 @@ +import t1 from "./a.txt?1" with { type: "file" }; +import t2 from "./a.txt?2"; +import t3 from "./a.txt" with { type: "file" }; +import w1 from "./a.wasm?1"; +import w2 from "./a.wasm?2"; + +test("question mark imports", () => { + expect(t1).toEndWith("a.txt"); + expect(t2).toBe("hello"); + expect(t3).toEndWith("a.txt"); + expect(w1).toEndWith("a.wasm"); + expect(w2).toEndWith("a.wasm"); +}); diff --git a/test/regression/issue/16476/a.txt b/test/regression/issue/16476/a.txt new file mode 100644 index 00000000000000..b6fc4c620b67d9 --- /dev/null +++ b/test/regression/issue/16476/a.txt @@ -0,0 +1 @@ +hello \ No newline at end of file diff --git a/test/regression/issue/16476/a.wasm b/test/regression/issue/16476/a.wasm new file mode 100755 index 0000000000000000000000000000000000000000..1781203915d720b4a908bc90b7b4ad49127ea8db GIT binary patch literal 61 zcmZQbEY4+QU|?WmVN76PU}j=uU}a`x5MbkEtY>s=XgI*Y%`VKumYbTJUsTD&z!qOz Ql2}y2z`(`A$i%=601aUY&;S4c literal 0 HcmV?d00001 From 5807d3451351b61ab3abb1cd1f080370f02fea8d Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Sat, 18 Jan 2025 11:07:21 -0800 Subject: [PATCH 2/2] Use a virtual module instead of printing source code --- src/bun.js/module_loader.zig | 127 ++++++++++++++-------------- src/bun.js/modules/ObjectModule.cpp | 3 + 2 files changed, 68 insertions(+), 62 deletions(-) diff --git a/src/bun.js/module_loader.zig b/src/bun.js/module_loader.zig index e9a86f166e07dd..06c02b01467e7a 100644 --- a/src/bun.js/module_loader.zig +++ b/src/bun.js/module_loader.zig @@ -2119,83 +2119,86 @@ pub const ModuleLoader = struct { }, else => { + if (flags.disableTranspiling()) { + return ResolvedSource{ + .allocator = null, + .source_code = bun.String.empty, + .specifier = input_specifier, + .source_url = input_specifier.createIfDifferent(path.text), + .hash = 0, + .tag = .esm, + }; + } + if (virtual_source == null) { - if (comptime !disable_transpilying) { - if (jsc_vm.isWatcherEnabled()) auto_watch: { - if (std.fs.path.isAbsolute(path.text) and !strings.contains(path.text, "node_modules")) { - const input_fd: bun.StoredFileDescriptorType = brk: { - // on macOS, we need a file descriptor to receive event notifications on it. - // so we use O_EVTONLY to open the file descriptor without asking any additional permissions. + if (jsc_vm.isWatcherEnabled()) auto_watch: { + if (std.fs.path.isAbsolute(path.text) and !strings.contains(path.text, "node_modules")) { + const input_fd: bun.StoredFileDescriptorType = brk: { + // on macOS, we need a file descriptor to receive event notifications on it. + // so we use O_EVTONLY to open the file descriptor without asking any additional permissions. + if (comptime Environment.isMac) { + switch (bun.sys.open( + &(std.posix.toPosixPath(path.text) catch break :auto_watch), + bun.C.O_EVTONLY, + 0, + )) { + .err => break :auto_watch, + .result => |fd| break :brk @enumFromInt(fd.cast()), + } + } else { + // Otherwise, don't even bother opening it. + break :brk .zero; + } + }; + const hash = JSC.GenericWatcher.getHash(path.text); + switch (jsc_vm.bun_watcher.addFile( + input_fd, + path.text, + hash, + loader, + .zero, + null, + true, + )) { + .err => { if (comptime Environment.isMac) { - switch (bun.sys.open( - &(std.posix.toPosixPath(path.text) catch break :auto_watch), - bun.C.O_EVTONLY, - 0, - )) { - .err => break :auto_watch, - .result => |fd| break :brk @enumFromInt(fd.cast()), + // If any error occurs and we just + // opened the file descriptor to + // receive event notifications on + // it, we should close it. + if (input_fd != .zero) { + _ = bun.sys.close(bun.toFD(input_fd)); } - } else { - // Otherwise, don't even bother opening it. - break :brk .zero; } - }; - const hash = JSC.GenericWatcher.getHash(path.text); - switch (jsc_vm.bun_watcher.addFile( - input_fd, - path.text, - hash, - loader, - .zero, - null, - true, - )) { - .err => { - if (comptime Environment.isMac) { - // If any error occurs and we just - // opened the file descriptor to - // receive event notifications on - // it, we should close it. - if (input_fd != .zero) { - _ = bun.sys.close(bun.toFD(input_fd)); - } - } - // we don't consider it a failure if we cannot watch the file - // they didn't open the file - }, - .result => {}, - } + // we don't consider it a failure if we cannot watch the file + // they didn't open the file + }, + .result => {}, } } } } - var stack_buf = std.heap.stackFallback(4096, jsc_vm.allocator); - const allocator = stack_buf.get(); - var buf = MutableString.init2048(allocator) catch bun.outOfMemory(); - defer buf.deinit(); - var writer = buf.writer(); - if (!jsc_vm.origin.isEmpty()) { - writer.writeAll("export default `") catch bun.outOfMemory(); - // TODO: escape backtick char, though we might already do that - JSC.API.Bun.getPublicPath(specifier, jsc_vm.origin, @TypeOf(&writer), &writer); - writer.writeAll("`;\n") catch bun.outOfMemory(); - } else { - // search keywords: "export default \"{}\";" - writer.writeAll("export default ") catch bun.outOfMemory(); - buf = js_printer.quoteForJSON(path.text, buf, true) catch bun.outOfMemory(); - writer = buf.writer(); - writer.writeAll(";\n") catch bun.outOfMemory(); - } + const value = brk: { + if (!jsc_vm.origin.isEmpty()) { + var buf = MutableString.init2048(jsc_vm.allocator) catch bun.outOfMemory(); + defer buf.deinit(); + var writer = buf.writer(); + JSC.API.Bun.getPublicPath(specifier, jsc_vm.origin, @TypeOf(&writer), &writer); + break :brk bun.String.createUTF8ForJS(globalObject.?, buf.slice()); + } + + break :brk bun.String.createUTF8ForJS(globalObject.?, path.text); + }; - const public_url = bun.String.createUTF8(buf.slice()); return ResolvedSource{ - .allocator = &jsc_vm.allocator, - .source_code = public_url, + .allocator = null, + .jsvalue_for_export = value, .specifier = input_specifier, .source_url = input_specifier.createIfDifferent(path.text), .hash = 0, + .tag = .export_default_object, }; }, } diff --git a/src/bun.js/modules/ObjectModule.cpp b/src/bun.js/modules/ObjectModule.cpp index fddf20cf0a64ab..6854c31de70755 100644 --- a/src/bun.js/modules/ObjectModule.cpp +++ b/src/bun.js/modules/ObjectModule.cpp @@ -100,6 +100,9 @@ generateJSValueExportDefaultObjectSourceCode(JSC::JSGlobalObject* globalObject, JSC::VM& vm = lexicalGlobalObject->vm(); exportNames.append(vm.propertyNames->defaultKeyword); exportValues.append(value); + const Identifier& esModuleMarker = vm.propertyNames->__esModule; + exportNames.append(esModuleMarker); + exportValues.append(jsBoolean(true)); if (value.isCell()) gcUnprotectNullTolerant(value.asCell());