diff options
-rw-r--r-- | src/bun.js/api/bun.zig | 21 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGlobalObject.cpp | 19 | ||||
-rw-r--r-- | src/bun.js/bindings/bindings.zig | 10 | ||||
-rw-r--r-- | src/bun.js/bindings/exports.zig | 28 | ||||
-rw-r--r-- | src/bun.js/bindings/headers-cpp.h | 2 | ||||
-rw-r--r-- | src/bun.js/bindings/headers.h | 4 | ||||
-rw-r--r-- | src/bun.js/javascript.zig | 107 | ||||
-rw-r--r-- | src/bun.js/module_loader.zig | 24 | ||||
-rw-r--r-- | src/http_client_async.zig | 13 | ||||
-rw-r--r-- | src/resolver/resolver.zig | 8 | ||||
-rw-r--r-- | src/string_immutable.zig | 5 |
11 files changed, 181 insertions, 60 deletions
diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig index bcaa5e09f..ad015e0ba 100644 --- a/src/bun.js/api/bun.zig +++ b/src/bun.js/api/bun.zig @@ -964,6 +964,7 @@ fn doResolveWithArgs( comptime is_file_path: bool, ) ?JSC.JSValue { var errorable: ErrorableZigString = undefined; + var query_string = ZigString.Empty; if (comptime is_file_path) { VirtualMachine.resolveFilePathForAPI( @@ -971,6 +972,7 @@ fn doResolveWithArgs( ctx.ptr(), specifier, from, + &query_string, is_esm, ); } else { @@ -979,6 +981,7 @@ fn doResolveWithArgs( ctx.ptr(), specifier, from, + &query_string, is_esm, ); } @@ -988,7 +991,23 @@ fn doResolveWithArgs( return null; } - return errorable.result.value.toValue(ctx.ptr()); + if (query_string.len > 0) { + var stack = std.heap.stackFallback(1024, ctx.allocator()); + const allocator = stack.get(); + var arraylist = std.ArrayList(u8).initCapacity(allocator, 1024) catch unreachable; + defer arraylist.deinit(); + arraylist.writer().print("{any}{any}", .{ + errorable.result.value, + query_string, + }) catch { + JSC.JSError(allocator, "Failed to allocate memory", .{}, ctx, exception); + return null; + }; + + return ZigString.initUTF8(arraylist.items).toValueGC(ctx); + } + + return errorable.result.value.toValue(ctx); } pub fn resolveSync( diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 74b8eab9e..b37e280f3 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -3585,9 +3585,14 @@ JSC::Identifier GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, res.success = false; ZigString keyZ = toZigString(key, globalObject); ZigString referrerZ = referrer && !referrer.isUndefinedOrNull() && referrer.isString() ? toZigString(referrer, globalObject) : ZigStringEmpty; - Zig__GlobalObject__resolve(&res, globalObject, &keyZ, &referrerZ); + ZigString queryString = { 0, 0 }; + Zig__GlobalObject__resolve(&res, globalObject, &keyZ, &referrerZ, &queryString); if (res.success) { + if (queryString.len > 0) { + return JSC::Identifier::fromString(globalObject->vm(), makeString(Zig::toString(res.result.value), Zig::toString(queryString))); + } + return toIdentifier(res.result.value, globalObject); } else { auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); @@ -3612,14 +3617,22 @@ JSC::JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject* g ErrorableZigString resolved; auto moduleNameZ = toZigString(moduleNameValue, globalObject); auto sourceOriginZ = sourceURL.isEmpty() ? ZigStringCwd : toZigString(sourceURL.fileSystemPath()); + ZigString queryString = { 0, 0 }; resolved.success = false; - Zig__GlobalObject__resolve(&resolved, globalObject, &moduleNameZ, &sourceOriginZ); + Zig__GlobalObject__resolve(&resolved, globalObject, &moduleNameZ, &sourceOriginZ, &queryString); if (!resolved.success) { throwException(scope, resolved.result.err, globalObject); return promise->rejectWithCaughtException(globalObject, scope); } - auto result = JSC::importModule(globalObject, toIdentifier(resolved.result.value, globalObject), + JSC::Identifier resolvedIdentifier; + if (queryString.len == 0) { + resolvedIdentifier = toIdentifier(resolved.result.value, globalObject); + } else { + resolvedIdentifier = JSC::Identifier::fromString(vm, makeString(Zig::toString(resolved.result.value), Zig::toString(queryString))); + } + + auto result = JSC::importModule(globalObject, resolvedIdentifier, JSC::jsUndefined(), parameters, JSC::jsUndefined()); RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope)); diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index 49e0fad23..d77a9dbb6 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -1354,9 +1354,15 @@ pub fn NewGlobalObject(comptime Type: type) type { } return ErrorableZigString.err(error.ImportFailed, ZigString.init(importNotImpl).toErrorInstance(global).asVoid()); } - pub fn resolve(res: *ErrorableZigString, global: *JSGlobalObject, specifier: *ZigString, source: *ZigString) callconv(.C) void { + pub fn resolve( + res: *ErrorableZigString, + global: *JSGlobalObject, + specifier: *ZigString, + source: *ZigString, + query_string: *ZigString, + ) callconv(.C) void { if (comptime @hasDecl(Type, "resolve")) { - @call(.always_inline, Type.resolve, .{ res, global, specifier.*, source.*, true }); + @call(.always_inline, Type.resolve, .{ res, global, specifier.*, source.*, query_string, true }); return; } res.* = ErrorableZigString.err(error.ResolveFailed, ZigString.init(resolveNotImpl).toErrorInstance(global).asVoid()); diff --git a/src/bun.js/bindings/exports.zig b/src/bun.js/bindings/exports.zig index d4956b1c4..54d855d23 100644 --- a/src/bun.js/bindings/exports.zig +++ b/src/bun.js/bindings/exports.zig @@ -54,43 +54,31 @@ pub const ZigGlobalObject = extern struct { } pub fn import(global: *JSGlobalObject, specifier: *ZigString, source: *ZigString) callconv(.C) ErrorableZigString { - if (comptime is_bindgen) { - unreachable; - } + JSC.markBinding(@src()); return @call(.always_inline, Interface.import, .{ global, specifier, source }); } - pub fn resolve(res: *ErrorableZigString, global: *JSGlobalObject, specifier: *ZigString, source: *ZigString) callconv(.C) void { - if (comptime is_bindgen) { - unreachable; - } - @call(.always_inline, Interface.resolve, .{ res, global, specifier, source }); + pub fn resolve(res: *ErrorableZigString, global: *JSGlobalObject, specifier: *ZigString, source: *ZigString, query: *ZigString) callconv(.C) void { + JSC.markBinding(@src()); + @call(.always_inline, Interface.resolve, .{ res, global, specifier, source, query }); } pub fn fetch(ret: *ErrorableResolvedSource, global: *JSGlobalObject, specifier: *ZigString, source: *ZigString) callconv(.C) void { - if (comptime is_bindgen) { - unreachable; - } + JSC.markBinding(@src()); @call(.always_inline, Interface.fetch, .{ ret, global, specifier, source }); } pub fn promiseRejectionTracker(global: *JSGlobalObject, promise: *JSPromise, rejection: JSPromiseRejectionOperation) callconv(.C) JSValue { - if (comptime is_bindgen) { - unreachable; - } + JSC.markBinding(@src()); return @call(.always_inline, Interface.promiseRejectionTracker, .{ global, promise, rejection }); } pub fn reportUncaughtException(global: *JSGlobalObject, exception: *Exception) callconv(.C) JSValue { - if (comptime is_bindgen) { - unreachable; - } + JSC.markBinding(@src()); return @call(.always_inline, Interface.reportUncaughtException, .{ global, exception }); } pub fn onCrash() callconv(.C) void { - if (comptime is_bindgen) { - unreachable; - } + JSC.markBinding(@src()); return @call(.always_inline, Interface.onCrash, .{}); } diff --git a/src/bun.js/bindings/headers-cpp.h b/src/bun.js/bindings/headers-cpp.h index a05007fff..969134e50 100644 --- a/src/bun.js/bindings/headers-cpp.h +++ b/src/bun.js/bindings/headers-cpp.h @@ -1,4 +1,4 @@ -//-- AUTOGENERATED FILE -- 1673376494 +//-- AUTOGENERATED FILE -- 1674359227 // clang-format off #pragma once diff --git a/src/bun.js/bindings/headers.h b/src/bun.js/bindings/headers.h index 71a8d1034..269698a98 100644 --- a/src/bun.js/bindings/headers.h +++ b/src/bun.js/bindings/headers.h @@ -1,5 +1,5 @@ // clang-format off -//-- AUTOGENERATED FILE -- 1673376494 +//-- AUTOGENERATED FILE -- 1674359227 #pragma once #include <stddef.h> @@ -521,7 +521,7 @@ ZIG_DECL ErrorableZigString Zig__GlobalObject__import(JSC__JSGlobalObject* arg0, ZIG_DECL void Zig__GlobalObject__onCrash(); ZIG_DECL JSC__JSValue Zig__GlobalObject__promiseRejectionTracker(JSC__JSGlobalObject* arg0, JSC__JSPromise* arg1, uint32_t JSPromiseRejectionOperation2); ZIG_DECL JSC__JSValue Zig__GlobalObject__reportUncaughtException(JSC__JSGlobalObject* arg0, JSC__Exception* arg1); -ZIG_DECL void Zig__GlobalObject__resolve(ErrorableZigString* arg0, JSC__JSGlobalObject* arg1, ZigString* arg2, ZigString* arg3); +ZIG_DECL void Zig__GlobalObject__resolve(ErrorableZigString* arg0, JSC__JSGlobalObject* arg1, ZigString* arg2, ZigString* arg3, ZigString* arg4); #endif diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig index d9cfcaac3..49f9df802 100644 --- a/src/bun.js/javascript.zig +++ b/src/bun.js/javascript.zig @@ -880,8 +880,8 @@ pub const VirtualMachine = struct { if (try ModuleLoader.fetchBuiltinModule(jsc_vm, _specifier, log, comptime flags.disableTranspiling())) |builtin| { return builtin; } - - var specifier = ModuleLoader.normalizeSpecifier(jsc_vm, _specifier); + var display_specifier = _specifier; + var specifier = ModuleLoader.normalizeSpecifier(jsc_vm, _specifier, &display_specifier); var path = Fs.Path.init(specifier); const loader = jsc_vm.bundler.options.loaders.get(path.name.ext) orelse brk: { if (strings.eqlLong(specifier, jsc_vm.main, true)) { @@ -894,6 +894,7 @@ pub const VirtualMachine = struct { return try ModuleLoader.transpileSourceCode( jsc_vm, specifier, + display_specifier, referrer, path, loader, @@ -910,8 +911,22 @@ pub const VirtualMachine = struct { pub const ResolveFunctionResult = struct { result: ?Resolver.Result, path: string, + query_string: []const u8 = "", }; + fn normalizeSpecifierForResolution(specifier_: []const u8, query_string: *[]const u8) []const u8 { + var specifier = specifier_; + if (strings.hasPrefixComptime(specifier, "file://")) specifier = specifier["file://".len..]; + + if (strings.indexOfChar(specifier, '?')) |i| { + specifier = specifier[0..i]; + query_string.* = specifier[i..]; + } + + return specifier; + } + + threadlocal var specifier_cache_resolver_buf: [bun.MAX_PATH_BYTES]u8 = undefined; fn _resolve( ret: *ResolveFunctionResult, _: *JSGlobalObject, @@ -952,30 +967,65 @@ pub const VirtualMachine = struct { } const is_special_source = strings.eqlComptime(source, main_file_name) or js_ast.Macro.isMacroPath(source); - - const result = try switch (jsc_vm.bundler.resolver.resolveAndAutoInstall( - if (!is_special_source) - if (is_a_file_path) - Fs.PathName.init(source).dirWithTrailingSlash() - else - source + var query_string: []const u8 = ""; + const normalized_specifier = normalizeSpecifierForResolution(specifier, &query_string); + const source_to_use = if (!is_special_source) + if (is_a_file_path) + Fs.PathName.init(source).dirWithTrailingSlash() else - jsc_vm.bundler.fs.top_level_dir, - // TODO: do we need to handle things like query string params? - if (strings.hasPrefixComptime(specifier, "file://")) specifier["file://".len..] else specifier, - if (is_esm) .stmt else .require, - .read_only, - )) { - .success => |r| r, - .failure => |e| e, - .not_found => error.ModuleNotFound, - .pending => unreachable, + source + else + jsc_vm.bundler.fs.top_level_dir; + + const result: Resolver.Result = try brk: { + var retry_on_not_found = query_string.len > 0; + while (true) { + break :brk switch (jsc_vm.bundler.resolver.resolveAndAutoInstall( + source_to_use, + normalized_specifier, + if (is_esm) .stmt else .require, + .read_only, + )) { + .success => |r| r, + .failure => |e| e, + .pending => unreachable, + .not_found => if (!retry_on_not_found) + error.ModuleNotFound + else { + retry_on_not_found = false; + + const buster_name = name: { + if (std.fs.path.isAbsolute(normalized_specifier)) { + if (std.fs.path.dirname(normalized_specifier)) |dir| { + break :name strings.withTrailingSlash(dir, normalized_specifier); + } + } + + var parts = [_]string{ + source_to_use, + normalized_specifier, + }; + + break :name bun.path.joinAbsStringBuf( + jsc_vm.bundler.fs.top_level_dir, + &specifier_cache_resolver_buf, + &parts, + .auto, + ); + }; + + jsc_vm.bundler.resolver.bustDirCache(buster_name); + continue; + }, + }; + } }; if (!jsc_vm.macro_mode) { jsc_vm.has_any_macro_remappings = jsc_vm.has_any_macro_remappings or jsc_vm.bundler.options.macro_remap.count() > 0; } ret.result = result; + ret.query_string = query_string; const result_path = result.pathConst() orelse return error.ModuleNotFound; jsc_vm.resolved_count += 1; if (comptime !realpath) { @@ -1044,9 +1094,10 @@ pub const VirtualMachine = struct { global: *JSGlobalObject, specifier: ZigString, source: ZigString, + query_string: *ZigString, is_esm: bool, ) void { - resolveMaybeNeedsTrailingSlash(res, global, specifier, source, is_esm, false, true); + resolveMaybeNeedsTrailingSlash(res, global, specifier, source, query_string, is_esm, false, true); } pub fn resolveFilePathForAPI( @@ -1054,9 +1105,10 @@ pub const VirtualMachine = struct { global: *JSGlobalObject, specifier: ZigString, source: ZigString, + query_string: *ZigString, is_esm: bool, ) void { - resolveMaybeNeedsTrailingSlash(res, global, specifier, source, is_esm, true, true); + resolveMaybeNeedsTrailingSlash(res, global, specifier, source, query_string, is_esm, true, true); } pub fn resolve( @@ -1064,9 +1116,10 @@ pub const VirtualMachine = struct { global: *JSGlobalObject, specifier: ZigString, source: ZigString, + query_string: *ZigString, is_esm: bool, ) void { - resolveMaybeNeedsTrailingSlash(res, global, specifier, source, is_esm, true, false); + resolveMaybeNeedsTrailingSlash(res, global, specifier, source, query_string, is_esm, true, false); } fn normalizeSource(source: []const u8) []const u8 { @@ -1077,11 +1130,12 @@ pub const VirtualMachine = struct { return source; } - pub fn resolveMaybeNeedsTrailingSlash( + fn resolveMaybeNeedsTrailingSlash( res: *ErrorableZigString, global: *JSGlobalObject, specifier: ZigString, source: ZigString, + query_string: ?*ZigString, is_esm: bool, comptime is_a_file_path: bool, comptime realpath: bool, @@ -1156,6 +1210,10 @@ pub const VirtualMachine = struct { return; }; + if (query_string) |query| { + query.* = ZigString.init(result.query_string); + } + res.* = ErrorableZigString.ok(ZigString.init(result.path)); } @@ -2726,8 +2784,7 @@ pub const HotReloader = struct { entries_option = rfs.entries.get(file_path); } - rfs.bustEntriesCache(file_path); - resolver.dir_cache.remove(file_path); + resolver.bustDirCache(file_path); if (entries_option) |dir_ent| { var last_file_hash: Watcher.HashType = std.math.maxInt(Watcher.HashType); diff --git a/src/bun.js/module_loader.zig b/src/bun.js/module_loader.zig index b689dea83..f60c3fe29 100644 --- a/src/bun.js/module_loader.zig +++ b/src/bun.js/module_loader.zig @@ -887,6 +887,7 @@ pub const ModuleLoader = struct { pub fn transpileSourceCode( jsc_vm: *VirtualMachine, specifier: string, + display_specifier: string, referrer: string, path: Fs.Path, loader: options.Loader, @@ -993,7 +994,7 @@ pub const ModuleLoader = struct { .print_source => ZigString.init(parse_result.source.contents), else => unreachable, }, - .specifier = ZigString.init(specifier), + .specifier = ZigString.init(display_specifier), .source_url = ZigString.init(path.text), .hash = 0, }; @@ -1105,7 +1106,7 @@ pub const ModuleLoader = struct { } if (jsc_vm.isWatcherEnabled()) { - const resolved_source = jsc_vm.refCountedResolvedSource(printer.ctx.written, specifier, path.text, null); + const resolved_source = jsc_vm.refCountedResolvedSource(printer.ctx.written, display_specifier, path.text, null); if (parse_result.input_fd) |fd_| { if (jsc_vm.bun_watcher != null and !is_node_override and std.fs.path.isAbsolute(path.text) and !strings.contains(path.text, "node_modules")) { @@ -1127,7 +1128,7 @@ pub const ModuleLoader = struct { return ResolvedSource{ .allocator = null, .source_code = ZigString.init(try default_allocator.dupe(u8, printer.ctx.getWritten())), - .specifier = ZigString.init(specifier), + .specifier = ZigString.init(display_specifier), .source_url = ZigString.init(path.text), // // TODO: change hash to a bitfield // .hash = 1, @@ -1328,7 +1329,7 @@ pub const ModuleLoader = struct { } } } - pub fn normalizeSpecifier(jsc_vm: *VirtualMachine, slice_: string) string { + pub fn normalizeSpecifier(jsc_vm: *VirtualMachine, slice_: string, string_to_use_for_source: *[]const u8) string { var slice = slice_; if (slice.len == 0) return slice; var was_http = false; @@ -1360,6 +1361,12 @@ pub const ModuleLoader = struct { } } + string_to_use_for_source.* = slice; + + if (strings.indexOfChar(slice, '?')) |i| { + slice = slice[0..i]; + } + return slice; } @@ -1405,7 +1412,12 @@ pub const ModuleLoader = struct { var referrer_slice = referrer.toSlice(jsc_vm.allocator); defer _specifier.deinit(); defer referrer_slice.deinit(); - var specifier = normalizeSpecifier(jsc_vm, _specifier.slice()); + var display_specifier: []const u8 = ""; + var specifier = normalizeSpecifier( + jsc_vm, + _specifier.slice(), + &display_specifier, + ); const path = Fs.Path.init(specifier); const loader = jsc_vm.bundler.options.loaders.get(path.name.ext) orelse options.Loader.js; var promise: ?*JSC.JSInternalPromise = null; @@ -1413,6 +1425,7 @@ pub const ModuleLoader = struct { ModuleLoader.transpileSourceCode( jsc_vm, specifier, + display_specifier, referrer_slice.slice(), path, loader, @@ -1977,6 +1990,7 @@ pub const ModuleLoader = struct { ModuleLoader.transpileSourceCode( jsc_vm, specifier, + specifier, referrer_slice.slice(), path, options.Loader.fromString(@tagName(loader)).?, diff --git a/src/http_client_async.zig b/src/http_client_async.zig index 41b12fce3..853ab8f3d 100644 --- a/src/http_client_async.zig +++ b/src/http_client_async.zig @@ -1178,7 +1178,18 @@ pub const AsyncHTTP = struct { }; const AtomicState = std.atomic.Atomic(State); - pub fn init(allocator: std.mem.Allocator, method: Method, url: URL, headers: Headers.Entries, headers_buf: string, response_buffer: *MutableString, request_body: []const u8, timeout: usize, callback: HTTPClientResult.Callback, http_proxy: ?URL) AsyncHTTP { + pub fn init( + allocator: std.mem.Allocator, + method: Method, + url: URL, + headers: Headers.Entries, + headers_buf: string, + response_buffer: *MutableString, + request_body: []const u8, + timeout: usize, + callback: HTTPClientResult.Callback, + http_proxy: ?URL, + ) AsyncHTTP { var this = AsyncHTTP{ .allocator = allocator, .url = url, .method = method, .request_headers = headers, .request_header_buf = headers_buf, .request_body = request_body, .response_buffer = response_buffer, .completion_callback = callback, .http_proxy = http_proxy }; this.client = HTTPClient.init(allocator, method, url, headers, headers_buf); this.client.timeout = timeout; diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index f2a81a35a..5ba5eb74f 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -1373,6 +1373,14 @@ pub const Resolver = struct { } } + const dev = Output.scoped(.Resolver, false); + + pub fn bustDirCache(r: *ThisResolver, path: string) void { + dev("Bust {s}", .{path}); + r.fs.fs.bustEntriesCache(path); + r.dir_cache.remove(path); + } + threadlocal var esm_subpath_buf: [512]u8 = undefined; threadlocal var esm_absolute_package_path: [bun.MAX_PATH_BYTES]u8 = undefined; threadlocal var esm_absolute_package_path_joined: [bun.MAX_PATH_BYTES]u8 = undefined; diff --git a/src/string_immutable.zig b/src/string_immutable.zig index e4a92fb26..27f9ac5d7 100644 --- a/src/string_immutable.zig +++ b/src/string_immutable.zig @@ -553,6 +553,11 @@ pub fn withoutTrailingSlash(this: string) []const u8 { return href; } +pub fn withTrailingSlash(dir: string, in: string) []const u8 { + std.debug.assert(bun.isSliceInBuffer(dir, in)); + return in[0..@min(strings.withoutTrailingSlash(in[0..@min(dir.len + 1, in.len)]).len + 1, in.len)]; +} + pub fn withoutLeadingSlash(this: string) []const u8 { return std.mem.trimLeft(u8, this, "/"); } |