diff --git a/CMakeLists.txt b/CMakeLists.txt index afcb105971..b2c1d2abce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,9 @@ cmake_minimum_required(VERSION 3.22) cmake_policy(SET CMP0091 NEW) cmake_policy(SET CMP0067 NEW) +set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) set(Bun_VERSION "1.1.18") -set(WEBKIT_TAG 5bbfe7e880090b9d0b5feaf3563e85957dd7b10d) +set(WEBKIT_TAG 00e8a32b3ca72cefae683cd65140428ff1d4ff09) set(BUN_WORKDIR "${CMAKE_CURRENT_BINARY_DIR}") message(STATUS "Configuring Bun ${Bun_VERSION} in ${BUN_WORKDIR}") @@ -14,6 +15,8 @@ set(CMAKE_C_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION OFF) + # Should not start with v # Used in process.version, process.versions.node, napi, and elsewhere set(REPORTED_NODEJS_VERSION "22.3.0") @@ -1117,8 +1120,12 @@ if(WIN32) # set_property(TARGET ${bun} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") set_property(TARGET ${bun} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") + if(USE_LTO) + target_compile_options(${bun} PUBLIC "-Xclang -emit-llvm-bc") + endif() + target_compile_options(${bun} PUBLIC "/EHsc" "/GR-") - target_link_options(${bun} PUBLIC "/STACK:0x1200000,0x100000" "/DEF:${BUN_SRC}/symbols.def") + target_link_options(${bun} PUBLIC "/STACK:0x1200000,0x100000" "/DEF:${BUN_SRC}/symbols.def" "/errorlimit:0") else() target_compile_options(${bun} PUBLIC -fPIC diff --git a/build.zig b/build.zig index 193d7b3e3d..e383b2f513 100644 --- a/build.zig +++ b/build.zig @@ -288,6 +288,40 @@ pub fn build(b: *Build) !void { } } + // zig build check-windows + { + var step = b.step("check-windows", "Check for semantic analysis errors on Windows x64"); + inline for (.{ + .{ .os = .windows, .arch = .x86_64 }, + }) |check| { + inline for (.{ .Debug, .ReleaseFast }) |mode| { + const check_target = b.resolveTargetQuery(.{ + .os_tag = OperatingSystem.stdOSTag(check.os), + .cpu_arch = check.arch, + .os_version_min = getOSVersionMin(check.os), + .glibc_version = getOSGlibCVersion(check.os), + }); + + var options = BunBuildOptions{ + .target = check_target, + .os = check.os, + .arch = check_target.result.cpu.arch, + .optimize = mode, + + .canary_revision = build_options.canary_revision, + .sha = build_options.sha, + .tracy_callstack_depth = build_options.tracy_callstack_depth, + .version = build_options.version, + .reported_nodejs_version = build_options.reported_nodejs_version, + .generated_code_dir = build_options.generated_code_dir, + }; + var obj = addBunObject(b, &options); + obj.generated_bin = null; + step.dependOn(&obj.step); + } + } + } + // Running `zig build` with no arguments is almost always a mistake. // TODO: revive this error. cannot right now since ZLS runs zig build without arguments { diff --git a/misctools/fetch.zig b/misctools/fetch.zig index 8d0ff34e31..7c91b6d9ec 100644 --- a/misctools/fetch.zig +++ b/misctools/fetch.zig @@ -182,7 +182,7 @@ pub fn main() anyerror!void { try channel.buffer.ensureTotalCapacity(1); - try HTTPThread.init(); + HTTPThread.init(); var ctx = try default_allocator.create(HTTP.HTTPChannelContext); ctx.* = .{ diff --git a/package.json b/package.json index 8346d40e79..c56f372c64 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "build:tidy": "BUN_SILENT=1 cmake --log-level=WARNING . -DZIG_OPTIMIZE=Debug -DUSE_DEBUG_JSC=ON -DBUN_TIDY_ONLY=ON -DCMAKE_BUILD_TYPE=Debug -GNinja -Bbuild-tidy >> ${GITHUB_STEP_SUMMARY:-/dev/stdout} && BUN_SILENT=1 ninja -Cbuild-tidy >> ${GITHUB_STEP_SUMMARY:-/dev/stdout}", "build:tidy-extra": "cmake . -DZIG_OPTIMIZE=Debug -DUSE_DEBUG_JSC=ON -DBUN_TIDY_ONLY_EXTRA=ON -DCMAKE_BUILD_TYPE=Debug -GNinja -Bbuild-tidy && ninja -Cbuild-tidy", "build:release": "cmake . -DCMAKE_BUILD_TYPE=Release -GNinja -Bbuild-release && ninja -Cbuild-release", + "build:release:local": "cmake . -DCMAKE_BUILD_TYPE=Release -DWEBKIT_DIR=$(pwd)/src/bun.js/WebKit/WebKitBuild/Release -GNinja -Bbuild-release-local && ninja -Cbuild-release-local", "build:release:with_logs": "cmake . -DCMAKE_BUILD_TYPE=Release -DENABLE_LOGS=true -GNinja -Bbuild-release && ninja -Cbuild-release", "build:debug-zig-release": "cmake . -DCMAKE_BUILD_TYPE=Release -DZIG_OPTIMIZE=Debug -GNinja -Bbuild-debug-zig-release && ninja -Cbuild-debug-zig-release", "build:safe": "cmake . -DZIG_OPTIMIZE=ReleaseSafe -DUSE_DEBUG_JSC=ON -DCMAKE_BUILD_TYPE=Release -GNinja -Bbuild-safe && ninja -Cbuild-safe", @@ -47,6 +48,7 @@ "test:release": "node scripts/runner.node.mjs ./build-release/bun", "zig-check": ".cache/zig/zig.exe build check --summary new", "zig-check-all": ".cache/zig/zig.exe build check-all --summary new", + "zig-check-windows": ".cache/zig/zig.exe build check-windows --summary new", "zig": ".cache/zig/zig.exe " } } diff --git a/scripts/build-tinycc.ps1 b/scripts/build-tinycc.ps1 index 07e9800edd..de1ba3199d 100755 --- a/scripts/build-tinycc.ps1 +++ b/scripts/build-tinycc.ps1 @@ -24,7 +24,7 @@ try { # TODO: -MT Run clang-cl @($env:CFLAGS -split ' ') libtcc.c -o tcc.obj "-DTCC_TARGET_PE" "-DTCC_TARGET_X86_64" "-O2" "-W2" "-Zi" "-MD" "-GS-" "-c" - Run lib "tcc.obj" "-OUT:tcc.lib" + Run llvm-lib "tcc.obj" "-OUT:tcc.lib" Copy-Item tcc.obj $BUN_DEPS_OUT_DIR/tcc.lib diff --git a/src/bun.js/BuildMessage.zig b/src/bun.js/BuildMessage.zig index f010ef7ead..468dd29c42 100644 --- a/src/bun.js/BuildMessage.zig +++ b/src/bun.js/BuildMessage.zig @@ -22,12 +22,12 @@ pub const BuildMessage = struct { pub fn constructor( globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) ?*BuildMessage { + ) ?*BuildMessage { globalThis.throw("BuildMessage is not constructable", .{}); return null; } - pub fn getNotes(this: *BuildMessage, globalThis: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getNotes(this: *BuildMessage, globalThis: *JSC.JSGlobalObject) JSC.JSValue { const notes: []const logger.Data = this.msg.notes orelse &[_]logger.Data{}; const array = JSC.JSValue.createEmptyArray(globalThis, notes.len); for (notes, 0..) |note, i| { @@ -81,7 +81,7 @@ pub const BuildMessage = struct { this: *BuildMessage, globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return this.toStringFn(globalThis); } @@ -89,7 +89,7 @@ pub const BuildMessage = struct { this: *BuildMessage, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const args_ = callframe.arguments(1); const args = args_.ptr[0..args_.len]; if (args.len > 0) { @@ -110,7 +110,7 @@ pub const BuildMessage = struct { this: *BuildMessage, globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { var object = JSC.JSValue.createEmptyObject(globalThis, 4); object.put(globalThis, ZigString.static("name"), ZigString.init("BuildMessage").toJS(globalThis)); object.put(globalThis, ZigString.static("position"), this.getPosition(globalThis)); @@ -163,7 +163,7 @@ pub const BuildMessage = struct { } // https://github.com/oven-sh/bun/issues/2375#issuecomment-2121530202 - pub fn getColumn(this: *BuildMessage, _: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getColumn(this: *BuildMessage, _: *JSC.JSGlobalObject) JSC.JSValue { if (this.msg.data.location) |location| { return JSC.JSValue.jsNumber(@max(location.column - 1, 0)); } @@ -171,7 +171,7 @@ pub const BuildMessage = struct { return JSC.JSValue.jsNumber(@as(i32, 0)); } - pub fn getLine(this: *BuildMessage, _: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getLine(this: *BuildMessage, _: *JSC.JSGlobalObject) JSC.JSValue { if (this.msg.data.location) |location| { return JSC.JSValue.jsNumber(@max(location.line - 1, 0)); } @@ -182,25 +182,25 @@ pub const BuildMessage = struct { pub fn getPosition( this: *BuildMessage, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return BuildMessage.generatePositionObject(this.msg, globalThis); } pub fn getMessage( this: *BuildMessage, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return ZigString.init(this.msg.data.text).toJS(globalThis); } pub fn getLevel( this: *BuildMessage, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return ZigString.init(this.msg.kind.string()).toJS(globalThis); } - pub fn finalize(this: *BuildMessage) callconv(.C) void { + pub fn finalize(this: *BuildMessage) void { this.msg.deinit(bun.default_allocator); } }; diff --git a/src/bun.js/ConsoleObject.zig b/src/bun.js/ConsoleObject.zig index 8ec5f97de4..04553fa537 100644 --- a/src/bun.js/ConsoleObject.zig +++ b/src/bun.js/ConsoleObject.zig @@ -87,7 +87,7 @@ pub fn messageWithTypeAndLevel( global: *JSGlobalObject, vals: [*]const JSValue, len: usize, -) callconv(.C) void { +) callconv(JSC.conv) void { if (comptime is_bindgen) { return; } @@ -3191,7 +3191,7 @@ pub fn count( ptr: [*]const u8, // len len: usize, -) callconv(.C) void { +) callconv(JSC.conv) void { var this = globalThis.bunVM().console; const slice = ptr[0..len]; const hash = bun.hash(slice); @@ -3217,7 +3217,7 @@ pub fn countReset( ptr: [*]const u8, // len len: usize, -) callconv(.C) void { +) callconv(JSC.conv) void { var this = globalThis.bunVM().console; const slice = ptr[0..len]; const hash = bun.hash(slice); @@ -3237,7 +3237,7 @@ pub fn time( _: *JSGlobalObject, chars: [*]const u8, len: usize, -) callconv(.C) void { +) callconv(JSC.conv) void { const id = bun.hash(chars[0..len]); if (!pending_time_logs_loaded) { pending_time_logs = PendingTimers.init(default_allocator); @@ -3257,7 +3257,7 @@ pub fn timeEnd( _: *JSGlobalObject, chars: [*]const u8, len: usize, -) callconv(.C) void { +) callconv(JSC.conv) void { if (!pending_time_logs_loaded) { return; } @@ -3288,7 +3288,7 @@ pub fn timeLog( // args args: [*]JSValue, args_len: usize, -) callconv(.C) void { +) callconv(JSC.conv) void { if (!pending_time_logs_loaded) { return; } @@ -3335,7 +3335,7 @@ pub fn profile( _: [*]const u8, // len _: usize, -) callconv(.C) void {} +) callconv(JSC.conv) void {} pub fn profileEnd( // console _: ConsoleObject.Type, @@ -3345,7 +3345,7 @@ pub fn profileEnd( _: [*]const u8, // len _: usize, -) callconv(.C) void {} +) callconv(JSC.conv) void {} pub fn takeHeapSnapshot( // console _: ConsoleObject.Type, @@ -3355,7 +3355,7 @@ pub fn takeHeapSnapshot( _: [*]const u8, // len _: usize, -) callconv(.C) void { +) callconv(JSC.conv) void { // TODO: this does an extra JSONStringify and we don't need it to! var snapshot: [1]JSValue = .{globalThis.generateHeapSnapshot()}; ConsoleObject.messageWithTypeAndLevel(undefined, MessageType.Log, MessageLevel.Debug, globalThis, &snapshot, 1); @@ -3367,7 +3367,7 @@ pub fn timeStamp( _: *JSGlobalObject, // args _: *ScriptArguments, -) callconv(.C) void {} +) callconv(JSC.conv) void {} pub fn record( // console _: ConsoleObject.Type, @@ -3375,7 +3375,7 @@ pub fn record( _: *JSGlobalObject, // args _: *ScriptArguments, -) callconv(.C) void {} +) callconv(JSC.conv) void {} pub fn recordEnd( // console _: ConsoleObject.Type, @@ -3383,7 +3383,7 @@ pub fn recordEnd( _: *JSGlobalObject, // args _: *ScriptArguments, -) callconv(.C) void {} +) callconv(JSC.conv) void {} pub fn screenshot( // console _: ConsoleObject.Type, @@ -3391,62 +3391,20 @@ pub fn screenshot( _: *JSGlobalObject, // args _: *ScriptArguments, -) callconv(.C) void {} - -pub const Export = shim.exportFunctions(.{ - .messageWithTypeAndLevel = messageWithTypeAndLevel, - .count = count, - .countReset = countReset, - .time = time, - .timeLog = timeLog, - .timeEnd = timeEnd, - .profile = profile, - .profileEnd = profileEnd, - .takeHeapSnapshot = takeHeapSnapshot, - .timeStamp = timeStamp, - .record = record, - .recordEnd = recordEnd, - .screenshot = screenshot, -}); +) callconv(JSC.conv) void {} comptime { - @export(messageWithTypeAndLevel, .{ - .name = Export[0].symbol_name, - }); - @export(count, .{ - .name = Export[1].symbol_name, - }); - @export(countReset, .{ - .name = Export[2].symbol_name, - }); - @export(time, .{ - .name = Export[3].symbol_name, - }); - @export(timeLog, .{ - .name = Export[4].symbol_name, - }); - @export(timeEnd, .{ - .name = Export[5].symbol_name, - }); - @export(profile, .{ - .name = Export[6].symbol_name, - }); - @export(profileEnd, .{ - .name = Export[7].symbol_name, - }); - @export(takeHeapSnapshot, .{ - .name = Export[8].symbol_name, - }); - @export(timeStamp, .{ - .name = Export[9].symbol_name, - }); - @export(record, .{ - .name = Export[10].symbol_name, - }); - @export(recordEnd, .{ - .name = Export[11].symbol_name, - }); - @export(screenshot, .{ - .name = Export[12].symbol_name, - }); + @export(messageWithTypeAndLevel, .{ .name = shim.symbolName("messageWithTypeAndLevel") }); + @export(count, .{ .name = shim.symbolName("count") }); + @export(countReset, .{ .name = shim.symbolName("countReset") }); + @export(time, .{ .name = shim.symbolName("time") }); + @export(timeLog, .{ .name = shim.symbolName("timeLog") }); + @export(timeEnd, .{ .name = shim.symbolName("timeEnd") }); + @export(profile, .{ .name = shim.symbolName("profile") }); + @export(profileEnd, .{ .name = shim.symbolName("profileEnd") }); + @export(takeHeapSnapshot, .{ .name = shim.symbolName("takeHeapSnapshot") }); + @export(timeStamp, .{ .name = shim.symbolName("timeStamp") }); + @export(record, .{ .name = shim.symbolName("record") }); + @export(recordEnd, .{ .name = shim.symbolName("recordEnd") }); + @export(screenshot, .{ .name = shim.symbolName("screenshot") }); } diff --git a/src/bun.js/ResolveMessage.zig b/src/bun.js/ResolveMessage.zig index 660aac3bbb..1a2f5e7745 100644 --- a/src/bun.js/ResolveMessage.zig +++ b/src/bun.js/ResolveMessage.zig @@ -21,12 +21,12 @@ pub const ResolveMessage = struct { pub fn constructor( globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) ?*ResolveMessage { + ) ?*ResolveMessage { globalThis.throw("ResolveMessage is not constructable", .{}); return null; } - pub fn getCode(this: *ResolveMessage, globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getCode(this: *ResolveMessage, globalObject: *JSC.JSGlobalObject) JSC.JSValue { switch (this.msg.metadata) { .resolve => |resolve| { const label: []const u8 = brk: { @@ -49,7 +49,7 @@ pub const ResolveMessage = struct { } // https://github.com/oven-sh/bun/issues/2375#issuecomment-2121530202 - pub fn getColumn(this: *ResolveMessage, _: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getColumn(this: *ResolveMessage, _: *JSC.JSGlobalObject) JSC.JSValue { if (this.msg.data.location) |location| { return JSC.JSValue.jsNumber(@max(location.column - 1, 0)); } @@ -57,7 +57,7 @@ pub const ResolveMessage = struct { return JSC.JSValue.jsNumber(@as(i32, 0)); } - pub fn getLine(this: *ResolveMessage, _: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getLine(this: *ResolveMessage, _: *JSC.JSGlobalObject) JSC.JSValue { if (this.msg.data.location) |location| { return JSC.JSValue.jsNumber(@max(location.line - 1, 0)); } @@ -111,7 +111,7 @@ pub const ResolveMessage = struct { this: *ResolveMessage, globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return this.toStringFn(globalThis); } @@ -119,7 +119,7 @@ pub const ResolveMessage = struct { this: *ResolveMessage, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const args_ = callframe.arguments(1); const args = args_.ptr[0..args_.len]; if (args.len > 0) { @@ -140,7 +140,7 @@ pub const ResolveMessage = struct { this: *ResolveMessage, globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { var object = JSC.JSValue.createEmptyObject(globalThis, 7); object.put(globalThis, ZigString.static("name"), ZigString.init("ResolveMessage").toJS(globalThis)); object.put(globalThis, ZigString.static("position"), this.getPosition(globalThis)); @@ -170,42 +170,42 @@ pub const ResolveMessage = struct { pub fn getPosition( this: *ResolveMessage, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return JSC.BuildMessage.generatePositionObject(this.msg, globalThis); } pub fn getMessage( this: *ResolveMessage, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return ZigString.init(this.msg.data.text).toJS(globalThis); } pub fn getLevel( this: *ResolveMessage, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return ZigString.init(this.msg.kind.string()).toJS(globalThis); } pub fn getSpecifier( this: *ResolveMessage, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return ZigString.init(this.msg.metadata.resolve.specifier.slice(this.msg.data.text)).toJS(globalThis); } pub fn getImportKind( this: *ResolveMessage, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return ZigString.init(this.msg.metadata.resolve.import_kind.label()).toJS(globalThis); } pub fn getReferrer( this: *ResolveMessage, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { if (this.referrer) |referrer| { return ZigString.init(referrer.text).toJS(globalThis); } else { diff --git a/src/bun.js/WebKit b/src/bun.js/WebKit index 64d04ec1a6..00e8a32b3c 160000 --- a/src/bun.js/WebKit +++ b/src/bun.js/WebKit @@ -1 +1 @@ -Subproject commit 64d04ec1a65d91326c5f2298b9c7d05b56125252 +Subproject commit 00e8a32b3ca72cefae683cd65140428ff1d4ff09 diff --git a/src/bun.js/api/BunObject.zig b/src/bun.js/api/BunObject.zig index 8cf35abe7a..155cbba348 100644 --- a/src/bun.js/api/BunObject.zig +++ b/src/bun.js/api/BunObject.zig @@ -1,3 +1,4 @@ +const conv = std.builtin.CallingConvention.Unspecified; /// How to add a new function or property to the Bun global /// /// - Add a callback or property to the below struct @@ -8,69 +9,69 @@ /// - Run "make dev" pub const BunObject = struct { // --- Callbacks --- - pub const allocUnsafe = Bun.allocUnsafe; - pub const build = Bun.JSBundler.buildFn; - pub const connect = JSC.wrapStaticMethod(JSC.API.Listener, "connect", false); - pub const deflateSync = JSC.wrapStaticMethod(JSZlib, "deflateSync", true); - pub const file = WebCore.Blob.constructBunFile; - pub const gc = Bun.runGC; - pub const generateHeapSnapshot = Bun.generateHeapSnapshot; - pub const gunzipSync = JSC.wrapStaticMethod(JSZlib, "gunzipSync", true); - pub const gzipSync = JSC.wrapStaticMethod(JSZlib, "gzipSync", true); - pub const indexOfLine = Bun.indexOfLine; - pub const inflateSync = JSC.wrapStaticMethod(JSZlib, "inflateSync", true); - pub const jest = @import("../test/jest.zig").Jest.call; - pub const listen = JSC.wrapStaticMethod(JSC.API.Listener, "listen", false); - pub const udpSocket = JSC.wrapStaticMethod(JSC.API.UDPSocket, "udpSocket", false); - pub const mmap = Bun.mmapFile; - pub const nanoseconds = Bun.nanoseconds; - pub const openInEditor = Bun.openInEditor; - pub const registerMacro = Bun.registerMacro; - pub const resolve = Bun.resolve; - pub const resolveSync = Bun.resolveSync; - pub const serve = Bun.serve; - pub const sha = JSC.wrapStaticMethod(Crypto.SHA512_256, "hash_", true); - pub const shrink = Bun.shrink; - pub const sleepSync = Bun.sleepSync; - pub const spawn = JSC.wrapStaticMethod(JSC.Subprocess, "spawn", false); - pub const spawnSync = JSC.wrapStaticMethod(JSC.Subprocess, "spawnSync", false); - pub const which = Bun.which; - pub const write = JSC.WebCore.Blob.writeFile; - pub const stringWidth = Bun.stringWidth; - pub const braces = Bun.braces; - pub const shellEscape = Bun.shellEscape; - pub const createParsedShellScript = bun.shell.ParsedShellScript.createParsedShellScript; - pub const createShellInterpreter = bun.shell.Interpreter.createShellInterpreter; + pub const allocUnsafe = toJSCallback(Bun.allocUnsafe); + pub const build = toJSCallback(Bun.JSBundler.buildFn); + pub const connect = toJSCallback(JSC.wrapStaticMethod(JSC.API.Listener, "connect", false)); + pub const deflateSync = toJSCallback(JSC.wrapStaticMethod(JSZlib, "deflateSync", true)); + pub const file = toJSCallback(WebCore.Blob.constructBunFile); + pub const gc = toJSCallback(Bun.runGC); + pub const generateHeapSnapshot = toJSCallback(Bun.generateHeapSnapshot); + pub const gunzipSync = toJSCallback(JSC.wrapStaticMethod(JSZlib, "gunzipSync", true)); + pub const gzipSync = toJSCallback(JSC.wrapStaticMethod(JSZlib, "gzipSync", true)); + pub const indexOfLine = toJSCallback(Bun.indexOfLine); + pub const inflateSync = toJSCallback(JSC.wrapStaticMethod(JSZlib, "inflateSync", true)); + pub const jest = toJSCallback(@import("../test/jest.zig").Jest.call); + pub const listen = toJSCallback(JSC.wrapStaticMethod(JSC.API.Listener, "listen", false)); + pub const udpSocket = toJSCallback(JSC.wrapStaticMethod(JSC.API.UDPSocket, "udpSocket", false)); + pub const mmap = toJSCallback(Bun.mmapFile); + pub const nanoseconds = toJSCallback(Bun.nanoseconds); + pub const openInEditor = toJSCallback(Bun.openInEditor); + pub const registerMacro = toJSCallback(Bun.registerMacro); + pub const resolve = toJSCallback(Bun.resolve); + pub const resolveSync = toJSCallback(Bun.resolveSync); + pub const serve = toJSCallback(Bun.serve); + pub const sha = toJSCallback(JSC.wrapStaticMethod(Crypto.SHA512_256, "hash_", true)); + pub const shrink = toJSCallback(Bun.shrink); + pub const sleepSync = toJSCallback(Bun.sleepSync); + pub const spawn = toJSCallback(JSC.wrapStaticMethod(JSC.Subprocess, "spawn", false)); + pub const spawnSync = toJSCallback(JSC.wrapStaticMethod(JSC.Subprocess, "spawnSync", false)); + pub const which = toJSCallback(Bun.which); + pub const write = toJSCallback(JSC.WebCore.Blob.writeFile); + pub const stringWidth = toJSCallback(Bun.stringWidth); + pub const braces = toJSCallback(Bun.braces); + pub const shellEscape = toJSCallback(Bun.shellEscape); + pub const createParsedShellScript = toJSCallback(bun.shell.ParsedShellScript.createParsedShellScript); + pub const createShellInterpreter = toJSCallback(bun.shell.Interpreter.createShellInterpreter); // --- Callbacks --- // --- Getters --- - pub const CryptoHasher = Crypto.CryptoHasher.getter; - pub const FFI = Bun.FFIObject.getter; - pub const FileSystemRouter = Bun.getFileSystemRouter; - pub const MD4 = Crypto.MD4.getter; - pub const MD5 = Crypto.MD5.getter; - pub const SHA1 = Crypto.SHA1.getter; - pub const SHA224 = Crypto.SHA224.getter; - pub const SHA256 = Crypto.SHA256.getter; - pub const SHA384 = Crypto.SHA384.getter; - pub const SHA512 = Crypto.SHA512.getter; - pub const SHA512_256 = Crypto.SHA512_256.getter; - pub const TOML = Bun.getTOMLObject; - pub const Glob = Bun.getGlobConstructor; - pub const Transpiler = Bun.getTranspilerConstructor; - pub const argv = Bun.getArgv; - pub const assetPrefix = Bun.getAssetPrefix; - pub const cwd = Bun.getCWD; - pub const enableANSIColors = Bun.enableANSIColors; - pub const hash = Bun.getHashObject; - pub const inspect = Bun.getInspect; - pub const main = Bun.getMain; - pub const origin = Bun.getOrigin; - pub const stderr = Bun.getStderr; - pub const stdin = Bun.getStdin; - pub const stdout = Bun.getStdout; - pub const unsafe = Bun.getUnsafe; - pub const semver = Bun.getSemver; + pub const CryptoHasher = toJSGetter(Crypto.CryptoHasher.getter); + pub const FFI = toJSGetter(Bun.FFIObject.getter); + pub const FileSystemRouter = toJSGetter(Bun.getFileSystemRouter); + pub const MD4 = toJSGetter(Crypto.MD4.getter); + pub const MD5 = toJSGetter(Crypto.MD5.getter); + pub const SHA1 = toJSGetter(Crypto.SHA1.getter); + pub const SHA224 = toJSGetter(Crypto.SHA224.getter); + pub const SHA256 = toJSGetter(Crypto.SHA256.getter); + pub const SHA384 = toJSGetter(Crypto.SHA384.getter); + pub const SHA512 = toJSGetter(Crypto.SHA512.getter); + pub const SHA512_256 = toJSGetter(Crypto.SHA512_256.getter); + pub const TOML = toJSGetter(Bun.getTOMLObject); + pub const Glob = toJSGetter(Bun.getGlobConstructor); + pub const Transpiler = toJSGetter(Bun.getTranspilerConstructor); + pub const argv = toJSGetter(Bun.getArgv); + pub const assetPrefix = toJSGetter(Bun.getAssetPrefix); + pub const cwd = toJSGetter(Bun.getCWD); + pub const enableANSIColors = toJSGetter(Bun.enableANSIColors); + pub const hash = toJSGetter(Bun.getHashObject); + pub const inspect = toJSGetter(Bun.getInspect); + pub const main = toJSGetter(Bun.getMain); + pub const origin = toJSGetter(Bun.getOrigin); + pub const stderr = toJSGetter(Bun.getStderr); + pub const stdin = toJSGetter(Bun.getStdin); + pub const stdout = toJSGetter(Bun.getStdout); + pub const unsafe = toJSGetter(Bun.getUnsafe); + pub const semver = toJSGetter(Bun.getSemver); // --- Getters --- fn getterName(comptime baseName: anytype) [:0]const u8 { @@ -81,6 +82,18 @@ pub const BunObject = struct { return "BunObject_callback_" ++ baseName; } + const toJSCallback = JSC.toJSHostFunction; + + const LazyPropertyCallback = fn (*JSC.JSGlobalObject, *JSC.JSObject) callconv(JSC.conv) JSC.JSValue; + + fn toJSGetter(comptime getter: anytype) LazyPropertyCallback { + return struct { + pub fn callback(this: *JSC.JSGlobalObject, object: *JSC.JSObject) callconv(JSC.conv) JSC.JSValue { + return @call(.always_inline, getter, .{ this, object }); + } + }.callback; + } + pub fn exportAll() void { if (!@inComptime()) { @compileError("Must be comptime"); @@ -303,7 +316,7 @@ const ShellTask = struct { pub fn shell( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { const Interpreter = @import("../../shell/interpreter.zig").Interpreter; // var allocator = globalThis.bunVM().allocator; @@ -395,7 +408,7 @@ pub fn shell( pub fn shellEscape( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { const arguments = callframe.arguments(1); if (arguments.len < 1) { globalThis.throw("shell escape expected at least 1 argument", .{}); @@ -439,7 +452,7 @@ pub fn shellEscape( pub fn braces( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { const arguments_ = callframe.arguments(2); var arguments = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments_.slice()); defer arguments.deinit(); @@ -546,7 +559,7 @@ pub fn braces( pub fn which( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { const arguments_ = callframe.arguments(2); var path_buf: bun.PathBuffer = undefined; var arguments = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments_.slice()); @@ -617,7 +630,7 @@ pub fn which( pub fn inspect( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { const arguments = callframe.arguments(4).slice(); if (arguments.len == 0) return bun.String.empty.toJS(globalThis); @@ -727,8 +740,8 @@ pub fn inspect( return ret; } -pub fn getInspect(globalObject: *JSC.JSGlobalObject, _: *JSC.JSObject) callconv(.C) JSC.JSValue { - const fun = JSC.createCallback(globalObject, ZigString.static("inspect"), 2, &inspect); +pub fn getInspect(globalObject: *JSC.JSGlobalObject, _: *JSC.JSObject) JSC.JSValue { + const fun = JSC.createCallback(globalObject, ZigString.static("inspect"), 2, inspect); var str = ZigString.init("nodejs.util.inspect.custom"); fun.put(globalObject, ZigString.static("custom"), JSC.JSValue.symbolFor(globalObject, &str)); return fun; @@ -737,7 +750,7 @@ pub fn getInspect(globalObject: *JSC.JSGlobalObject, _: *JSC.JSObject) callconv( pub fn registerMacro( globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { const arguments_ = callframe.arguments(2); const arguments = arguments_.slice(); if (arguments.len != 2 or !arguments[0].isNumber()) { @@ -770,21 +783,21 @@ pub fn registerMacro( pub fn getCWD( globalThis: *JSC.JSGlobalObject, _: *JSC.JSObject, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { return ZigString.init(VirtualMachine.get().bundler.fs.top_level_dir).toJS(globalThis); } pub fn getOrigin( globalThis: *JSC.JSGlobalObject, _: *JSC.JSObject, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { return ZigString.init(VirtualMachine.get().origin.origin).toJS(globalThis); } pub fn getStdin( globalThis: *JSC.JSGlobalObject, _: *JSC.JSObject, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { var rare_data = globalThis.bunVM().rareData(); var store = rare_data.stdin(); store.ref(); @@ -798,7 +811,7 @@ pub fn getStdin( pub fn getStderr( globalThis: *JSC.JSGlobalObject, _: *JSC.JSObject, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { var rare_data = globalThis.bunVM().rareData(); var store = rare_data.stderr(); store.ref(); @@ -812,7 +825,7 @@ pub fn getStderr( pub fn getStdout( globalThis: *JSC.JSGlobalObject, _: *JSC.JSObject, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { var rare_data = globalThis.bunVM().rareData(); var store = rare_data.stdout(); store.ref(); @@ -826,14 +839,14 @@ pub fn getStdout( pub fn enableANSIColors( globalThis: *JSC.JSGlobalObject, _: *JSC.JSObject, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { _ = globalThis; return JSValue.jsBoolean(Output.enable_ansi_colors); } pub fn getMain( globalThis: *JSC.JSGlobalObject, _: *JSC.JSObject, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { const vm = globalThis.bunVM(); // Attempt to use the resolved filesystem path @@ -886,14 +899,14 @@ pub fn getMain( pub fn getAssetPrefix( globalThis: *JSC.JSGlobalObject, _: *JSC.JSObject, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { return ZigString.init(VirtualMachine.get().bundler.options.routes.asset_prefix_path).toJS(globalThis); } pub fn getArgv( globalThis: *JSC.JSGlobalObject, _: *JSC.JSObject, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { return JSC.Node.Process.getArgv(globalThis); } @@ -901,7 +914,7 @@ const Editor = @import("../../open.zig").Editor; pub fn openInEditor( globalThis: js.JSContextRef, callframe: *JSC.CallFrame, -) callconv(.C) JSValue { +) JSValue { var edit = &VirtualMachine.get().rareData().editor_context; const args = callframe.arguments(4); var arguments = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), args.slice()); @@ -1019,7 +1032,7 @@ pub fn getPublicPathWithAssetPrefix( } } -pub fn sleepSync(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { +pub fn sleepSync(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const arguments = callframe.arguments(1); // Expect at least one argument. We allow more than one but ignore them; this @@ -1047,16 +1060,16 @@ pub fn sleepSync(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) c return .undefined; } -pub fn generateHeapSnapshot(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { +pub fn generateHeapSnapshot(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { return globalObject.generateHeapSnapshot(); } -pub fn runGC(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { +pub fn runGC(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const arguments_ = callframe.arguments(1); const arguments = arguments_.slice(); return globalObject.bunVM().garbageCollect(arguments.len > 0 and arguments[0].isBoolean() and arguments[0].toBoolean()); } -pub fn shrink(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { +pub fn shrink(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { globalObject.vm().shrinkFootprint(); return .undefined; } @@ -1173,7 +1186,7 @@ fn doResolveWithArgs( return errorable.result.value.toJS(ctx); } -pub fn resolveSync(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { +pub fn resolveSync(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { var exception_ = [1]JSC.JSValueRef{null}; const exception = &exception_; const arguments = callframe.arguments(3); @@ -1186,7 +1199,7 @@ pub fn resolveSync(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) return result orelse .zero; } -pub fn resolve(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { +pub fn resolve(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { var exception_ = [1]JSC.JSValueRef{null}; const exception = &exception_; const arguments = callframe.arguments(3); @@ -1266,7 +1279,7 @@ export fn Bun__resolveSyncWithSource( }; } -pub fn getPublicPathJS(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { +pub fn getPublicPathJS(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const arguments = callframe.arguments(1).slice(); if (arguments.len < 1) { return bun.String.empty.toJS(globalObject); @@ -1284,7 +1297,7 @@ pub fn getPublicPathJS(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFr extern fn dump_zone_malloc_stats() void; -export fn dump_mimalloc(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { +fn dump_mimalloc(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { globalObject.bunVM().arena.dumpStats(); if (comptime bun.is_heap_breakdown_enabled) { dump_zone_malloc_stats(); @@ -1292,7 +1305,7 @@ export fn dump_mimalloc(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) ca return .undefined; } -pub fn indexOfLine(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { +pub fn indexOfLine(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const arguments_ = callframe.arguments(2); const arguments = arguments_.slice(); if (arguments.len == 0) { @@ -2305,10 +2318,10 @@ pub const Crypto = struct { } // Once we have bindings generator, this should be replaced with a generated function - pub export fn JSPasswordObject__hash( + pub fn JSPasswordObject__hash( globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const arguments_ = callframe.arguments(2); const arguments = arguments_.ptr[0..arguments_.len]; @@ -2339,10 +2352,10 @@ pub const Crypto = struct { } // Once we have bindings generator, this should be replaced with a generated function - pub export fn JSPasswordObject__hashSync( + pub fn JSPasswordObject__hashSync( globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const arguments_ = callframe.arguments(2); const arguments = arguments_.ptr[0..arguments_.len]; @@ -2464,10 +2477,10 @@ pub const Crypto = struct { }; // Once we have bindings generator, this should be replaced with a generated function - pub export fn JSPasswordObject__verify( + pub fn JSPasswordObject__verify( globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const arguments_ = callframe.arguments(3); const arguments = arguments_.ptr[0..arguments_.len]; @@ -2517,10 +2530,10 @@ pub const Crypto = struct { } // Once we have bindings generator, this should be replaced with a generated function - pub export fn JSPasswordObject__verifySync( + pub fn JSPasswordObject__verifySync( globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const arguments_ = callframe.arguments(3); const arguments = arguments_.ptr[0..arguments_.len]; @@ -2586,7 +2599,7 @@ pub const Crypto = struct { pub fn getByteLength( this: *CryptoHasher, _: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return JSC.JSValue.jsNumber(switch (this.*) { .evp => |*inner| inner.size(), .zig => |*inner| inner.digest_length, @@ -2596,7 +2609,7 @@ pub const Crypto = struct { pub fn getAlgorithm( this: *CryptoHasher, globalObject: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return switch (this.*) { inline else => |*inner| ZigString.fromUTF8(bun.asByteSlice(@tagName(inner.algorithm))).toJS(globalObject), }; @@ -2606,7 +2619,7 @@ pub const Crypto = struct { globalThis_: *JSC.JSGlobalObject, _: JSValue, _: JSValue, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { var values = EVP.Algorithm.names.values; return JSC.JSValue.createStringArray(globalThis_, &values, values.len, true); } @@ -2708,7 +2721,7 @@ pub const Crypto = struct { } } - pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) ?*CryptoHasher { + pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) ?*CryptoHasher { const arguments = callframe.arguments(2); if (arguments.len == 0) { globalThis.throwInvalidArguments("Expected an algorithm name as an argument", .{}); @@ -2740,11 +2753,11 @@ pub const Crypto = struct { pub fn getter( globalObject: *JSC.JSGlobalObject, _: *JSC.JSObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return CryptoHasher.getConstructor(globalObject); } - pub fn update(this: *CryptoHasher, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn update(this: *CryptoHasher, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const thisValue = callframe.this(); const arguments = callframe.arguments(2); const input = arguments.ptr[0]; @@ -2783,7 +2796,7 @@ pub const Crypto = struct { this: *CryptoHasher, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { var new: CryptoHasher = undefined; switch (this.*) { .evp => |*inner| { @@ -2862,7 +2875,7 @@ pub const Crypto = struct { }; } - pub fn finalize(this: *CryptoHasher) callconv(.C) void { + pub fn finalize(this: *CryptoHasher) void { switch (this.*) { .evp => |*inner| { // https://github.com/oven-sh/bun/issues/3250 @@ -2959,7 +2972,7 @@ pub const Crypto = struct { } } - fn constructor(algorithm: ZigString) callconv(.C) ?*CryptoHasher { + fn constructor(algorithm: ZigString) ?*CryptoHasher { inline for (algo_map) |item| { if (bun.strings.eqlComptime(algorithm.slice(), item[0])) { return CryptoHasher.new(.{ .zig = .{ @@ -3028,7 +3041,7 @@ pub const Crypto = struct { pub fn getByteLength( _: *@This(), _: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return JSC.JSValue.jsNumber(@as(u16, Hasher.digest)); } @@ -3036,7 +3049,7 @@ pub const Crypto = struct { _: *JSC.JSGlobalObject, _: JSValue, _: JSValue, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return JSC.JSValue.jsNumber(@as(u16, Hasher.digest)); } @@ -3123,7 +3136,7 @@ pub const Crypto = struct { } } - pub fn constructor(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) ?*@This() { + pub fn constructor(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) ?*@This() { const this = bun.default_allocator.create(@This()) catch return null; this.* = .{ .hashing = Hasher.init() }; @@ -3133,11 +3146,11 @@ pub const Crypto = struct { pub fn getter( globalObject: *JSC.JSGlobalObject, _: *JSC.JSObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return ThisHasher.getConstructor(globalObject); } - pub fn update(this: *@This(), globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn update(this: *@This(), globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const thisValue = callframe.this(); const input = callframe.argument(0); const buffer = JSC.Node.BlobOrStringOrBuffer.fromJS(globalThis, globalThis.bunVM().allocator, input) orelse { @@ -3224,7 +3237,7 @@ pub const Crypto = struct { return encoding.encodeWithSize(globalThis, Hasher.digest, output_digest_slice); } - pub fn finalize(this: *@This()) callconv(.C) void { + pub fn finalize(this: *@This()) void { VirtualMachine.get().allocator.destroy(this); } }; @@ -3243,7 +3256,7 @@ pub const Crypto = struct { pub fn nanoseconds( globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { const ns = globalThis.bunVM().origin_timer.read(); return JSC.JSValue.jsNumberFromUint64(ns); } @@ -3251,7 +3264,7 @@ pub fn nanoseconds( pub fn serve( globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { const arguments = callframe.arguments(2).slice(); var config: JSC.API.ServerConfig = brk: { var exception_ = [1]JSC.JSValueRef{null}; @@ -3503,7 +3516,7 @@ comptime { pub fn allocUnsafe( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { const arguments = callframe.arguments(1); const size = arguments.ptr[0]; if (!size.isUInt32AsAnyInt()) { @@ -3517,7 +3530,7 @@ pub fn allocUnsafe( pub fn mmapFile( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { if (comptime Environment.isWindows) { globalThis.throwTODO("mmapFile is not supported on Windows"); return JSC.JSValue.zero; @@ -3596,33 +3609,33 @@ pub fn mmapFile( pub fn getTranspilerConstructor( globalThis: *JSC.JSGlobalObject, _: *JSC.JSObject, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { return JSC.API.JSTranspiler.getConstructor(globalThis); } pub fn getFileSystemRouter( globalThis: *JSC.JSGlobalObject, _: *JSC.JSObject, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { return JSC.API.FileSystemRouter.getConstructor(globalThis); } pub fn getHashObject( globalThis: *JSC.JSGlobalObject, _: *JSC.JSObject, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { return HashObject.create(globalThis); } const HashObject = struct { - pub const wyhash = hashWrap(std.hash.Wyhash).hash; - pub const adler32 = hashWrap(std.hash.Adler32).hash; - pub const crc32 = hashWrap(std.hash.Crc32).hash; - pub const cityHash32 = hashWrap(std.hash.CityHash32).hash; - pub const cityHash64 = hashWrap(std.hash.CityHash64).hash; - pub const murmur32v2 = hashWrap(std.hash.murmur.Murmur2_32).hash; - pub const murmur32v3 = hashWrap(std.hash.murmur.Murmur3_32).hash; - pub const murmur64v2 = hashWrap(std.hash.murmur.Murmur2_64).hash; + pub const wyhash = hashWrap(std.hash.Wyhash); + pub const adler32 = hashWrap(std.hash.Adler32); + pub const crc32 = hashWrap(std.hash.Crc32); + pub const cityHash32 = hashWrap(std.hash.CityHash32); + pub const cityHash64 = hashWrap(std.hash.CityHash64); + pub const murmur32v2 = hashWrap(std.hash.murmur.Murmur2_32); + pub const murmur32v3 = hashWrap(std.hash.murmur.Murmur3_32); + pub const murmur64v2 = hashWrap(std.hash.murmur.Murmur2_64); pub fn create(globalThis: *JSC.JSGlobalObject) JSC.JSValue { const function = JSC.createCallback(globalThis, ZigString.static("hash"), 1, &wyhash); @@ -3641,7 +3654,7 @@ const HashObject = struct { globalThis, ZigString.static(name), 1, - &@field(HashObject, name), + @field(HashObject, name), ); function.put(globalThis, comptime ZigString.static(name), value); } @@ -3649,13 +3662,13 @@ const HashObject = struct { return function; } - fn hashWrap(comptime Hasher_: anytype) type { + fn hashWrap(comptime Hasher_: anytype) JSC.JSHostFunctionType { return struct { const Hasher = Hasher_; pub fn hash( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(2).slice(); var args = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments); defer args.deinit(); @@ -3726,35 +3739,35 @@ const HashObject = struct { return JSC.JSValue.fromUInt64NoTruncate(globalThis, value); } } - }; + }.hash; } }; pub fn getTOMLObject( globalThis: *JSC.JSGlobalObject, _: *JSC.JSObject, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { return TOMLObject.create(globalThis); } pub fn getGlobConstructor( globalThis: *JSC.JSGlobalObject, _: *JSC.JSObject, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { return JSC.API.Glob.getConstructor(globalThis); } pub fn getSemver( globalThis: *JSC.JSGlobalObject, _: *JSC.JSObject, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { return SemverObject.create(globalThis); } pub fn getUnsafe( globalThis: *JSC.JSGlobalObject, _: *JSC.JSObject, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { return UnsafeObject.create(globalThis); } @@ -3762,9 +3775,9 @@ const UnsafeObject = struct { pub fn create(globalThis: *JSC.JSGlobalObject) JSC.JSValue { const object = JSValue.createEmptyObject(globalThis, 3); const fields = comptime .{ - .gcAggressionLevel = &gcAggressionLevel, - .arrayBufferToString = &arrayBufferToString, - .mimallocDump = &dump_mimalloc, + .gcAggressionLevel = gcAggressionLevel, + .arrayBufferToString = arrayBufferToString, + .mimallocDump = dump_mimalloc, }; inline for (comptime std.meta.fieldNames(@TypeOf(fields))) |name| { object.put( @@ -3779,7 +3792,7 @@ const UnsafeObject = struct { pub fn gcAggressionLevel( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const ret = JSValue.jsNumber(@as(i32, @intFromEnum(globalThis.bunVM().aggressive_garbage_collection))); const value = callframe.arguments(1).ptr[0]; @@ -3797,7 +3810,7 @@ const UnsafeObject = struct { pub fn arrayBufferToString( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const args = callframe.arguments(2).slice(); if (args.len < 1 or !args[0].isCell() or !args[0].jsType().isTypedArray()) { globalThis.throwInvalidArguments("Expected an ArrayBuffer", .{}); @@ -3832,7 +3845,7 @@ const TOMLObject = struct { globalThis, ZigString.static("parse"), 1, - &parse, + parse, ), ); @@ -3842,7 +3855,7 @@ const TOMLObject = struct { pub fn parse( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { var arena = bun.ArenaAllocator.init(globalThis.allocator()); const allocator = arena.allocator(); defer arena.deinit(); @@ -3911,7 +3924,7 @@ pub const FFIObject = struct { } } - pub const dom_call = JSC.DOMCall("FFI", @This(), "ptr", f64, JSC.DOMEffect.forRead(.TypedArrayProperties)); + pub const dom_call = JSC.DOMCall("FFI", @This(), "ptr", JSC.DOMEffect.forRead(.TypedArrayProperties)); pub fn toJS(globalObject: *JSC.JSGlobalObject) JSC.JSValue { const object = JSC.JSValue.createEmptyObject(globalObject, comptime std.meta.fieldNames(@TypeOf(fields)).len + 2); @@ -3931,18 +3944,18 @@ pub const FFIObject = struct { pub const Reader = struct { pub const DOMCalls = .{ - .u8 = JSC.DOMCall("Reader", @This(), "u8", i32, JSC.DOMEffect.forRead(.World)), - .u16 = JSC.DOMCall("Reader", @This(), "u16", i32, JSC.DOMEffect.forRead(.World)), - .u32 = JSC.DOMCall("Reader", @This(), "u32", i32, JSC.DOMEffect.forRead(.World)), - .ptr = JSC.DOMCall("Reader", @This(), "ptr", i52, JSC.DOMEffect.forRead(.World)), - .i8 = JSC.DOMCall("Reader", @This(), "i8", i32, JSC.DOMEffect.forRead(.World)), - .i16 = JSC.DOMCall("Reader", @This(), "i16", i32, JSC.DOMEffect.forRead(.World)), - .i32 = JSC.DOMCall("Reader", @This(), "i32", i32, JSC.DOMEffect.forRead(.World)), - .i64 = JSC.DOMCall("Reader", @This(), "i64", i64, JSC.DOMEffect.forRead(.World)), - .u64 = JSC.DOMCall("Reader", @This(), "u64", u64, JSC.DOMEffect.forRead(.World)), - .intptr = JSC.DOMCall("Reader", @This(), "intptr", i52, JSC.DOMEffect.forRead(.World)), - .f32 = JSC.DOMCall("Reader", @This(), "f32", f64, JSC.DOMEffect.forRead(.World)), - .f64 = JSC.DOMCall("Reader", @This(), "f64", f64, JSC.DOMEffect.forRead(.World)), + .u8 = JSC.DOMCall("Reader", @This(), "u8", JSC.DOMEffect.forRead(.World)), + .u16 = JSC.DOMCall("Reader", @This(), "u16", JSC.DOMEffect.forRead(.World)), + .u32 = JSC.DOMCall("Reader", @This(), "u32", JSC.DOMEffect.forRead(.World)), + .ptr = JSC.DOMCall("Reader", @This(), "ptr", JSC.DOMEffect.forRead(.World)), + .i8 = JSC.DOMCall("Reader", @This(), "i8", JSC.DOMEffect.forRead(.World)), + .i16 = JSC.DOMCall("Reader", @This(), "i16", JSC.DOMEffect.forRead(.World)), + .i32 = JSC.DOMCall("Reader", @This(), "i32", JSC.DOMEffect.forRead(.World)), + .i64 = JSC.DOMCall("Reader", @This(), "i64", JSC.DOMEffect.forRead(.World)), + .u64 = JSC.DOMCall("Reader", @This(), "u64", JSC.DOMEffect.forRead(.World)), + .intptr = JSC.DOMCall("Reader", @This(), "intptr", JSC.DOMEffect.forRead(.World)), + .f32 = JSC.DOMCall("Reader", @This(), "f32", JSC.DOMEffect.forRead(.World)), + .f64 = JSC.DOMCall("Reader", @This(), "f64", JSC.DOMEffect.forRead(.World)), }; pub fn toJS(globalThis: *JSC.JSGlobalObject) JSC.JSValue { @@ -4121,7 +4134,7 @@ pub const FFIObject = struct { _: *anyopaque, raw_addr: i64, offset: i32, - ) callconv(.C) JSValue { + ) callconv(JSC.conv) JSValue { const addr = @as(usize, @intCast(raw_addr)) + @as(usize, @intCast(offset)); const value = @as(*align(1) u8, @ptrFromInt(addr)).*; return JSValue.jsNumber(value); @@ -4131,7 +4144,7 @@ pub const FFIObject = struct { _: *anyopaque, raw_addr: i64, offset: i32, - ) callconv(.C) JSValue { + ) callconv(JSC.conv) JSValue { const addr = @as(usize, @intCast(raw_addr)) + @as(usize, @intCast(offset)); const value = @as(*align(1) u16, @ptrFromInt(addr)).*; return JSValue.jsNumber(value); @@ -4141,7 +4154,7 @@ pub const FFIObject = struct { _: *anyopaque, raw_addr: i64, offset: i32, - ) callconv(.C) JSValue { + ) callconv(JSC.conv) JSValue { const addr = @as(usize, @intCast(raw_addr)) + @as(usize, @intCast(offset)); const value = @as(*align(1) u32, @ptrFromInt(addr)).*; return JSValue.jsNumber(value); @@ -4151,7 +4164,7 @@ pub const FFIObject = struct { _: *anyopaque, raw_addr: i64, offset: i32, - ) callconv(.C) JSValue { + ) callconv(JSC.conv) JSValue { const addr = @as(usize, @intCast(raw_addr)) + @as(usize, @intCast(offset)); const value = @as(*align(1) u64, @ptrFromInt(addr)).*; return JSValue.jsNumber(value); @@ -4161,7 +4174,7 @@ pub const FFIObject = struct { _: *anyopaque, raw_addr: i64, offset: i32, - ) callconv(.C) JSValue { + ) callconv(JSC.conv) JSValue { const addr = @as(usize, @intCast(raw_addr)) + @as(usize, @intCast(offset)); const value = @as(*align(1) i8, @ptrFromInt(addr)).*; return JSValue.jsNumber(value); @@ -4171,7 +4184,7 @@ pub const FFIObject = struct { _: *anyopaque, raw_addr: i64, offset: i32, - ) callconv(.C) JSValue { + ) callconv(JSC.conv) JSValue { const addr = @as(usize, @intCast(raw_addr)) + @as(usize, @intCast(offset)); const value = @as(*align(1) i16, @ptrFromInt(addr)).*; return JSValue.jsNumber(value); @@ -4181,7 +4194,7 @@ pub const FFIObject = struct { _: *anyopaque, raw_addr: i64, offset: i32, - ) callconv(.C) JSValue { + ) callconv(JSC.conv) JSValue { const addr = @as(usize, @intCast(raw_addr)) + @as(usize, @intCast(offset)); const value = @as(*align(1) i32, @ptrFromInt(addr)).*; return JSValue.jsNumber(value); @@ -4191,7 +4204,7 @@ pub const FFIObject = struct { _: *anyopaque, raw_addr: i64, offset: i32, - ) callconv(.C) JSValue { + ) callconv(JSC.conv) JSValue { const addr = @as(usize, @intCast(raw_addr)) + @as(usize, @intCast(offset)); const value = @as(*align(1) i64, @ptrFromInt(addr)).*; return JSValue.jsNumber(value); @@ -4202,7 +4215,7 @@ pub const FFIObject = struct { _: *anyopaque, raw_addr: i64, offset: i32, - ) callconv(.C) JSValue { + ) callconv(JSC.conv) JSValue { const addr = @as(usize, @intCast(raw_addr)) + @as(usize, @intCast(offset)); const value = @as(*align(1) f32, @ptrFromInt(addr)).*; return JSValue.jsNumber(value); @@ -4213,7 +4226,7 @@ pub const FFIObject = struct { _: *anyopaque, raw_addr: i64, offset: i32, - ) callconv(.C) JSValue { + ) callconv(JSC.conv) JSValue { const addr = @as(usize, @intCast(raw_addr)) + @as(usize, @intCast(offset)); const value = @as(*align(1) f64, @ptrFromInt(addr)).*; return JSValue.jsNumber(value); @@ -4224,7 +4237,7 @@ pub const FFIObject = struct { _: *anyopaque, raw_addr: i64, offset: i32, - ) callconv(.C) JSValue { + ) callconv(JSC.conv) JSValue { const addr = @as(usize, @intCast(raw_addr)) + @as(usize, @intCast(offset)); const value = @as(*align(1) u64, @ptrFromInt(addr)).*; return JSValue.fromUInt64NoTruncate(global, value); @@ -4235,7 +4248,7 @@ pub const FFIObject = struct { _: *anyopaque, raw_addr: i64, offset: i32, - ) callconv(.C) JSValue { + ) callconv(JSC.conv) JSValue { const addr = @as(usize, @intCast(raw_addr)) + @as(usize, @intCast(offset)); const value = @as(*align(1) i64, @ptrFromInt(addr)).*; return JSValue.fromInt64NoTruncate(global, value); @@ -4258,7 +4271,7 @@ pub const FFIObject = struct { _: *JSGlobalObject, _: *anyopaque, array: *JSC.JSUint8Array, - ) callconv(.C) JSValue { + ) callconv(JSC.conv) JSValue { return JSValue.fromPtrAddress(@intFromPtr(array.ptr())); } @@ -4518,12 +4531,12 @@ pub const FFIObject = struct { pub fn getter( globalObject: *JSC.JSGlobalObject, _: *JSC.JSObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return FFIObject.toJS(globalObject); } }; -fn stringWidth(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { +fn stringWidth(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const arguments = callframe.arguments(2).slice(); const value = if (arguments.len > 0) arguments[0] else JSC.JSValue.jsUndefined(); const options_object = if (arguments.len > 1) arguments[1] else JSC.JSValue.jsUndefined(); @@ -4755,7 +4768,7 @@ pub const JSZlib = struct { pub usingnamespace @import("./bun/subprocess.zig"); const InternalTestingAPIs = struct { - pub fn BunInternalFunction__syntaxHighlighter(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn BunInternalFunction__syntaxHighlighter(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) JSValue { const args = callframe.arguments(1); if (args.len < 1) { globalThis.throwNotEnoughArguments("code", 1, 0); diff --git a/src/bun.js/api/JSBundler.zig b/src/bun.js/api/JSBundler.zig index bb56790106..150fe7f62c 100644 --- a/src/bun.js/api/JSBundler.zig +++ b/src/bun.js/api/JSBundler.zig @@ -565,7 +565,7 @@ pub const JSBundler = struct { pub fn buildFn( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const arguments = callframe.arguments(1); return build(globalThis, arguments.slice()); } @@ -1081,7 +1081,7 @@ pub const BuildArtifact = struct { this: *BuildArtifact, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return @call(bun.callmod_inline, Blob.getText, .{ &this.blob, globalThis, callframe }); } @@ -1089,27 +1089,27 @@ pub const BuildArtifact = struct { this: *BuildArtifact, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return @call(bun.callmod_inline, Blob.getJSON, .{ &this.blob, globalThis, callframe }); } pub fn getArrayBuffer( this: *BuildArtifact, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { return @call(bun.callmod_inline, Blob.getArrayBuffer, .{ &this.blob, globalThis, callframe }); } pub fn getSlice( this: *BuildArtifact, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return @call(bun.callmod_inline, Blob.getSlice, .{ &this.blob, globalThis, callframe }); } pub fn getType( this: *BuildArtifact, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { return @call(bun.callmod_inline, Blob.getType, .{ &this.blob, globalThis }); } @@ -1117,7 +1117,7 @@ pub const BuildArtifact = struct { this: *BuildArtifact, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { return @call(bun.callmod_inline, Blob.getStream, .{ &this.blob, globalThis, @@ -1128,39 +1128,39 @@ pub const BuildArtifact = struct { pub fn getPath( this: *BuildArtifact, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { return ZigString.fromUTF8(this.path).toJS(globalThis); } pub fn getLoader( this: *BuildArtifact, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { return ZigString.fromUTF8(@tagName(this.loader)).toJS(globalThis); } pub fn getHash( this: *BuildArtifact, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { var buf: [512]u8 = undefined; const out = std.fmt.bufPrint(&buf, "{any}", .{options.PathTemplate.hashFormatter(this.hash)}) catch @panic("Unexpected"); return ZigString.init(out).toJS(globalThis); } - pub fn getSize(this: *BuildArtifact, globalObject: *JSC.JSGlobalObject) callconv(.C) JSValue { + pub fn getSize(this: *BuildArtifact, globalObject: *JSC.JSGlobalObject) JSValue { return @call(bun.callmod_inline, Blob.getSize, .{ &this.blob, globalObject }); } - pub fn getMimeType(this: *BuildArtifact, globalObject: *JSC.JSGlobalObject) callconv(.C) JSValue { + pub fn getMimeType(this: *BuildArtifact, globalObject: *JSC.JSGlobalObject) JSValue { return @call(bun.callmod_inline, Blob.getType, .{ &this.blob, globalObject }); } - pub fn getOutputKind(this: *BuildArtifact, globalObject: *JSC.JSGlobalObject) callconv(.C) JSValue { + pub fn getOutputKind(this: *BuildArtifact, globalObject: *JSC.JSGlobalObject) JSValue { return ZigString.init(@tagName(this.output_kind)).toJS(globalObject); } - pub fn getSourceMap(this: *BuildArtifact, _: *JSC.JSGlobalObject) callconv(.C) JSValue { + pub fn getSourceMap(this: *BuildArtifact, _: *JSC.JSGlobalObject) JSValue { if (this.sourcemap.get()) |value| { return value; } diff --git a/src/bun.js/api/JSTranspiler.zig b/src/bun.js/api/JSTranspiler.zig index d60efa3fde..4c9b78f640 100644 --- a/src/bun.js/api/JSTranspiler.zig +++ b/src/bun.js/api/JSTranspiler.zig @@ -743,7 +743,7 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std pub fn constructor( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, -) callconv(.C) ?*Transpiler { +) ?*Transpiler { var temp = bun.ArenaAllocator.init(getAllocator(globalThis)); const arguments = callframe.arguments(3); var args = JSC.Node.ArgumentsSlice.init( @@ -907,7 +907,7 @@ pub fn scan( this: *Transpiler, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { JSC.markBinding(@src()); const arguments = callframe.arguments(3); var args = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments.slice()); @@ -1005,7 +1005,7 @@ pub fn transform( this: *Transpiler, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { JSC.markBinding(@src()); var exception_ref = [_]JSC.C.JSValueRef{null}; const exception: JSC.C.ExceptionRef = &exception_ref; @@ -1061,7 +1061,7 @@ pub fn transformSync( this: *Transpiler, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { JSC.markBinding(@src()); var exception_value = [_]JSC.C.JSValueRef{null}; const exception: JSC.C.ExceptionRef = &exception_value; @@ -1246,7 +1246,7 @@ pub fn scanImports( this: *Transpiler, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { const arguments = callframe.arguments(2); var exception_val = [_]JSC.C.JSValueRef{null}; const exception: JSC.C.ExceptionRef = &exception_val; diff --git a/src/bun.js/api/Timer.zig b/src/bun.js/api/Timer.zig index 5fda636d0b..782bf3a231 100644 --- a/src/bun.js/api/Timer.zig +++ b/src/bun.js/api/Timer.zig @@ -550,7 +550,7 @@ pub const TimerObject = struct { return .{ timer, timer_js }; } - pub fn doRef(this: *TimerObject, _: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn doRef(this: *TimerObject, _: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { const this_value = callframe.this(); this_value.ensureStillAlive(); @@ -564,7 +564,7 @@ pub const TimerObject = struct { return this_value; } - pub fn doRefresh(this: *TimerObject, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn doRefresh(this: *TimerObject, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { const this_value = callframe.this(); // setImmediate does not support refreshing and we do not support refreshing after cleanup @@ -578,7 +578,7 @@ pub const TimerObject = struct { return this_value; } - pub fn doUnref(this: *TimerObject, _: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn doUnref(this: *TimerObject, _: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { const this_value = callframe.this(); this_value.ensureStillAlive(); @@ -643,10 +643,10 @@ pub const TimerObject = struct { } } - pub fn hasRef(this: *TimerObject, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSValue { + pub fn hasRef(this: *TimerObject, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSValue { return JSValue.jsBoolean(this.is_keeping_event_loop_alive); } - pub fn toPrimitive(this: *TimerObject, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSValue { + pub fn toPrimitive(this: *TimerObject, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSValue { if (!this.has_accessed_primitive) { this.has_accessed_primitive = true; const vm = VirtualMachine.get(); @@ -655,7 +655,7 @@ pub const TimerObject = struct { return JSValue.jsNumber(this.id); } - pub fn finalize(this: *TimerObject) callconv(.C) void { + pub fn finalize(this: *TimerObject) void { this.strong_this.deinit(); this.deref(); } diff --git a/src/bun.js/api/bun/dns_resolver.zig b/src/bun.js/api/bun/dns_resolver.zig index 621aa342c0..19c342da20 100644 --- a/src/bun.js/api/bun/dns_resolver.zig +++ b/src/bun.js/api/bun/dns_resolver.zig @@ -1562,7 +1562,7 @@ pub const InternalDNS = struct { var dns_cache_errors: usize = 0; var getaddrinfo_calls: usize = 0; - pub fn getDNSCacheStats(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn getDNSCacheStats(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const object = JSC.JSValue.createEmptyObject(globalObject, 6); object.put(globalObject, JSC.ZigString.static("cacheHitsCompleted"), JSC.JSValue.jsNumber(@atomicLoad(usize, &dns_cache_hits_completed, .monotonic))); object.put(globalObject, JSC.ZigString.static("cacheHitsInflight"), JSC.JSValue.jsNumber(@atomicLoad(usize, &dns_cache_hits_inflight, .monotonic))); @@ -1633,7 +1633,7 @@ pub const InternalDNS = struct { return req; } - pub fn prefetchFromJS(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn prefetchFromJS(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(2).slice(); if (arguments.len < 1) { @@ -2252,7 +2252,7 @@ pub const DNSResolver = struct { }); }; - pub fn resolve(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn resolve(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(3); if (arguments.len < 1) { globalThis.throwNotEnoughArguments("resolve", 2, arguments.len); @@ -2337,7 +2337,7 @@ pub const DNSResolver = struct { } } - pub fn reverse(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn reverse(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(2); if (arguments.len < 1) { globalThis.throwNotEnoughArguments("reverse", 2, arguments.len); @@ -2402,7 +2402,7 @@ pub const DNSResolver = struct { return promise; } - pub fn lookup(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn lookup(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(2); if (arguments.len < 1) { globalThis.throwNotEnoughArguments("lookup", 2, arguments.len); @@ -2472,7 +2472,7 @@ pub const DNSResolver = struct { }; } - pub fn resolveSrv(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn resolveSrv(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(2); if (arguments.len < 1) { globalThis.throwNotEnoughArguments("resolveSrv", 2, arguments.len); @@ -2503,7 +2503,7 @@ pub const DNSResolver = struct { return resolver.doResolveCAres(c_ares.struct_ares_srv_reply, "srv", name.slice(), globalThis); } - pub fn resolveSoa(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn resolveSoa(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(2); if (arguments.len < 1) { globalThis.throwNotEnoughArguments("resolveSoa", 2, arguments.len); @@ -2529,7 +2529,7 @@ pub const DNSResolver = struct { return resolver.doResolveCAres(c_ares.struct_ares_soa_reply, "soa", name.slice(), globalThis); } - pub fn resolveCaa(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn resolveCaa(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(2); if (arguments.len < 1) { globalThis.throwNotEnoughArguments("resolveCaa", 2, arguments.len); @@ -2560,7 +2560,7 @@ pub const DNSResolver = struct { return resolver.doResolveCAres(c_ares.struct_ares_caa_reply, "caa", name.slice(), globalThis); } - pub fn resolveNs(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn resolveNs(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(2); if (arguments.len < 1) { globalThis.throwNotEnoughArguments("resolveNs", 2, arguments.len); @@ -2586,7 +2586,7 @@ pub const DNSResolver = struct { return resolver.doResolveCAres(c_ares.struct_hostent, "ns", name.slice(), globalThis); } - pub fn resolvePtr(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn resolvePtr(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(2); if (arguments.len < 1) { globalThis.throwNotEnoughArguments("resolvePtr", 2, arguments.len); @@ -2617,7 +2617,7 @@ pub const DNSResolver = struct { return resolver.doResolveCAres(c_ares.struct_hostent, "ptr", name.slice(), globalThis); } - pub fn resolveCname(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn resolveCname(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(2); if (arguments.len < 1) { globalThis.throwNotEnoughArguments("resolveCname", 2, arguments.len); @@ -2648,7 +2648,7 @@ pub const DNSResolver = struct { return resolver.doResolveCAres(c_ares.struct_hostent, "cname", name.slice(), globalThis); } - pub fn resolveMx(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn resolveMx(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(2); if (arguments.len < 1) { globalThis.throwNotEnoughArguments("resolveMx", 2, arguments.len); @@ -2679,7 +2679,7 @@ pub const DNSResolver = struct { return resolver.doResolveCAres(c_ares.struct_ares_mx_reply, "mx", name.slice(), globalThis); } - pub fn resolveNaptr(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn resolveNaptr(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(2); if (arguments.len < 1) { globalThis.throwNotEnoughArguments("resolveNaptr", 2, arguments.len); @@ -2710,7 +2710,7 @@ pub const DNSResolver = struct { return resolver.doResolveCAres(c_ares.struct_ares_naptr_reply, "naptr", name.slice(), globalThis); } - pub fn resolveTxt(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn resolveTxt(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(2); if (arguments.len < 1) { globalThis.throwNotEnoughArguments("resolveTxt", 2, arguments.len); @@ -2831,7 +2831,7 @@ pub const DNSResolver = struct { return promise; } - pub fn getServers(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn getServers(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { _ = callframe; var vm = globalThis.bunVM(); @@ -2917,7 +2917,7 @@ pub const DNSResolver = struct { // Resolves the given address and port into a host name and service using the operating system's underlying getnameinfo implementation. // If address is not a valid IP address, a TypeError will be thrown. The port will be coerced to a number. // If it is not a legal port, a TypeError will be thrown. - pub fn lookupService(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn lookupService(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(3); if (arguments.len < 2) { globalThis.throwNotEnoughArguments("lookupService", 3, arguments.len); diff --git a/src/bun.js/api/bun/h2_frame_parser.zig b/src/bun.js/api/bun/h2_frame_parser.zig index 06150fc952..a98142aa92 100644 --- a/src/bun.js/api/bun/h2_frame_parser.zig +++ b/src/bun.js/api/bun/h2_frame_parser.zig @@ -261,7 +261,7 @@ const SingleValueHeaders = bun.ComptimeStringMap(void, .{ .{"x-content-type-options"}, }); -pub fn jsGetUnpackedSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { +fn jsGetUnpackedSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { JSC.markBinding(@src()); var settings: FullSettingsPayload = .{}; @@ -296,7 +296,7 @@ pub fn jsGetUnpackedSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC. } } -pub fn jsGetPackedSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { +fn jsGetPackedSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSValue { var settings: FullSettingsPayload = .{}; const args_list = callframe.arguments(1); @@ -1415,7 +1415,7 @@ pub const H2FrameParser = struct { } } - pub fn setEncoding(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn setEncoding(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { JSC.markBinding(@src()); const args_list = callframe.arguments(1); if (args_list.len < 1) { @@ -1532,7 +1532,7 @@ pub const H2FrameParser = struct { return true; } - pub fn updateSettings(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn updateSettings(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { JSC.markBinding(@src()); const args_list = callframe.arguments(1); if (args_list.len < 1) { @@ -1550,7 +1550,7 @@ pub const H2FrameParser = struct { return .zero; } - pub fn getCurrentState(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSValue { + pub fn getCurrentState(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSValue { JSC.markBinding(@src()); var result = JSValue.createEmptyObject(globalObject, 9); result.put(globalObject, JSC.ZigString.static("effectiveLocalWindowSize"), JSC.JSValue.jsNumber(this.windowSize)); @@ -1568,7 +1568,7 @@ pub const H2FrameParser = struct { result.put(globalObject, JSC.ZigString.static("outboundQueueSize"), JSC.JSValue.jsNumber(0)); return result; } - pub fn goaway(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn goaway(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { JSC.markBinding(@src()); const args_list = callframe.arguments(3); if (args_list.len < 1) { @@ -1618,7 +1618,7 @@ pub const H2FrameParser = struct { return JSC.JSValue.jsUndefined(); } - pub fn ping(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn ping(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { JSC.markBinding(@src()); const args_list = callframe.arguments(1); if (args_list.len < 1) { @@ -1636,7 +1636,7 @@ pub const H2FrameParser = struct { return .zero; } - pub fn getEndAfterHeaders(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn getEndAfterHeaders(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { JSC.markBinding(@src()); const args_list = callframe.arguments(1); if (args_list.len < 1) { @@ -1664,7 +1664,7 @@ pub const H2FrameParser = struct { return JSC.JSValue.jsBoolean(stream.endAfterHeaders); } - pub fn setEndAfterHeaders(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn setEndAfterHeaders(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { JSC.markBinding(@src()); const args_list = callframe.arguments(2); if (args_list.len < 2) { @@ -1698,7 +1698,7 @@ pub const H2FrameParser = struct { return JSC.JSValue.jsBoolean(true); } - pub fn isStreamAborted(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn isStreamAborted(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { JSC.markBinding(@src()); const args_list = callframe.arguments(1); if (args_list.len < 1) { @@ -1728,7 +1728,7 @@ pub const H2FrameParser = struct { } return JSC.JSValue.jsBoolean(true); } - pub fn getStreamState(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn getStreamState(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { JSC.markBinding(@src()); const args_list = callframe.arguments(1); if (args_list.len < 1) { @@ -1765,7 +1765,7 @@ pub const H2FrameParser = struct { return state; } - pub fn setStreamPriority(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn setStreamPriority(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { JSC.markBinding(@src()); const args_list = callframe.arguments(2); if (args_list.len < 2) { @@ -1859,7 +1859,7 @@ pub const H2FrameParser = struct { } return JSC.JSValue.jsBoolean(true); } - pub fn rstStream(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn rstStream(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { JSC.markBinding(@src()); const args_list = callframe.arguments(2); if (args_list.len < 2) { @@ -1938,7 +1938,7 @@ pub const H2FrameParser = struct { } } - pub fn sendTrailers(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn sendTrailers(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { JSC.markBinding(@src()); const args_list = callframe.arguments(3); if (args_list.len < 3) { @@ -2077,7 +2077,7 @@ pub const H2FrameParser = struct { return JSC.JSValue.jsUndefined(); } - pub fn writeStream(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn writeStream(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { JSC.markBinding(@src()); const args_list = callframe.arguments(3); if (args_list.len < 3) { @@ -2147,7 +2147,7 @@ pub const H2FrameParser = struct { return stream_id; } - pub fn request(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn request(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { JSC.markBinding(@src()); // we use PADDING_STRATEGY_NONE with is default // TODO: PADDING_STRATEGY_MAX AND PADDING_STRATEGY_ALIGNED @@ -2423,7 +2423,7 @@ pub const H2FrameParser = struct { return JSC.JSValue.jsNumber(stream.id); } - pub fn read(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn read(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { JSC.markBinding(@src()); const args_list = callframe.arguments(1); if (args_list.len < 1) { @@ -2445,7 +2445,7 @@ pub const H2FrameParser = struct { return .zero; } - pub fn constructor(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) ?*H2FrameParser { + pub fn constructor(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) ?*H2FrameParser { const args_list = callframe.arguments(1); if (args_list.len < 1) { globalObject.throw("Expected 1 argument", .{}); @@ -2528,7 +2528,7 @@ pub const H2FrameParser = struct { pub fn finalize( this: *H2FrameParser, - ) callconv(.C) void { + ) void { log("finalize", .{}); this.deinit(); } diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig index 67bf08d5cd..d6642fcf17 100644 --- a/src/bun.js/api/bun/socket.zig +++ b/src/bun.js/api/bun/socket.zig @@ -514,7 +514,7 @@ pub const Listener = struct { pub fn getData( this: *Listener, _: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { log("getData()", .{}); return this.strong_data.get() orelse JSValue.jsUndefined(); } @@ -569,7 +569,7 @@ pub const Listener = struct { } }; - pub fn reload(this: *Listener, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn reload(this: *Listener, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { const args = callframe.arguments(1); if (args.len < 1 or (this.listener == null and this.handlers.active_connections == 0)) { @@ -810,7 +810,7 @@ pub const Listener = struct { onCreate(false, socket); } - pub fn constructor(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) ?*Listener { + pub fn constructor(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) ?*Listener { globalObject.throw("Cannot construct Listener", .{}); return null; } @@ -874,7 +874,7 @@ pub const Listener = struct { return JSValue.jsUndefined(); } - pub fn stop(this: *Listener, _: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn stop(this: *Listener, _: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { const arguments = callframe.arguments(1); log("close", .{}); @@ -940,11 +940,11 @@ pub const Listener = struct { bun.default_allocator.destroy(this); } - pub fn getConnectionsCount(this: *Listener, _: *JSC.JSGlobalObject) callconv(.C) JSValue { + pub fn getConnectionsCount(this: *Listener, _: *JSC.JSGlobalObject) JSValue { return JSValue.jsNumber(this.handlers.active_connections); } - pub fn getUnix(this: *Listener, globalObject: *JSC.JSGlobalObject) callconv(.C) JSValue { + pub fn getUnix(this: *Listener, globalObject: *JSC.JSGlobalObject) JSValue { if (this.connection != .unix) { return JSValue.jsUndefined(); } @@ -952,21 +952,21 @@ pub const Listener = struct { return ZigString.init(this.connection.unix).withEncoding().toJS(globalObject); } - pub fn getHostname(this: *Listener, globalObject: *JSC.JSGlobalObject) callconv(.C) JSValue { + pub fn getHostname(this: *Listener, globalObject: *JSC.JSGlobalObject) JSValue { if (this.connection != .host) { return JSValue.jsUndefined(); } return ZigString.init(this.connection.host.host).withEncoding().toJS(globalObject); } - pub fn getPort(this: *Listener, _: *JSC.JSGlobalObject) callconv(.C) JSValue { + pub fn getPort(this: *Listener, _: *JSC.JSGlobalObject) JSValue { if (this.connection != .host) { return JSValue.jsUndefined(); } return JSValue.jsNumber(this.connection.host.port); } - pub fn ref(this: *Listener, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn ref(this: *Listener, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { const this_value = callframe.this(); if (this.listener == null) return JSValue.jsUndefined(); this.poll_ref.ref(globalObject.bunVM()); @@ -974,7 +974,7 @@ pub const Listener = struct { return JSValue.jsUndefined(); } - pub fn unref(this: *Listener, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSValue { + pub fn unref(this: *Listener, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSValue { this.poll_ref.unref(globalObject.bunVM()); if (this.handlers.active_connections == 0) { this.strong_self.clear(); @@ -1250,7 +1250,7 @@ fn NewSocket(comptime ssl: bool) type { } } - pub fn constructor(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) ?*This { + pub fn constructor(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) ?*This { globalObject.throw("Cannot construct Socket", .{}); return null; } @@ -1684,7 +1684,7 @@ fn NewSocket(comptime ssl: bool) type { pub fn getData( _: *This, _: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { log("getData()", .{}); return JSValue.jsUndefined(); } @@ -1702,7 +1702,7 @@ fn NewSocket(comptime ssl: bool) type { pub fn getListener( this: *This, _: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (!this.handlers.is_server or this.detached) { return JSValue.jsUndefined(); } @@ -1714,7 +1714,7 @@ fn NewSocket(comptime ssl: bool) type { pub fn getReadyState( this: *This, _: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { log("getReadyState()", .{}); if (this.detached) { @@ -1733,7 +1733,7 @@ fn NewSocket(comptime ssl: bool) type { pub fn getAuthorized( this: *This, _: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { log("getAuthorized()", .{}); return JSValue.jsBoolean(this.authorized); } @@ -1741,7 +1741,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { JSC.markBinding(@src()); const args = callframe.arguments(1); if (this.detached) return JSValue.jsUndefined(); @@ -1764,7 +1764,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { JSC.markBinding(@src()); if (this.detached) { @@ -1794,7 +1794,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { JSC.markBinding(@src()); if (this.detached) { @@ -1817,7 +1817,7 @@ fn NewSocket(comptime ssl: bool) type { pub fn getLocalPort( this: *This, _: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (this.detached) { return JSValue.jsUndefined(); } @@ -1828,7 +1828,7 @@ fn NewSocket(comptime ssl: bool) type { pub fn getRemoteAddress( this: *This, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (this.detached) { return JSValue.jsUndefined(); } @@ -2018,7 +2018,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, _: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { JSC.markBinding(@src()); if (!this.detached) this.socket.flush(); @@ -2030,7 +2030,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, _: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { JSC.markBinding(@src()); if (!this.detached) { this.socket.close(.failure); @@ -2043,7 +2043,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, _: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { JSC.markBinding(@src()); const args = callframe.arguments(1); if (!this.detached) { @@ -2061,7 +2061,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { JSC.markBinding(@src()); const args = callframe.arguments(4); @@ -2085,20 +2085,20 @@ fn NewSocket(comptime ssl: bool) type { }; } - pub fn ref(this: *This, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSValue { + pub fn ref(this: *This, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSValue { JSC.markBinding(@src()); if (this.detached) return JSValue.jsUndefined(); this.poll_ref.ref(globalObject.bunVM()); return JSValue.jsUndefined(); } - pub fn unref(this: *This, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSValue { + pub fn unref(this: *This, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSValue { JSC.markBinding(@src()); this.poll_ref.unref(globalObject.bunVM()); return JSValue.jsUndefined(); } - pub fn finalize(this: *This) callconv(.C) void { + pub fn finalize(this: *This) void { log("finalize() {d}", .{@intFromPtr(this)}); this.finalizing = true; if (!this.detached) { @@ -2130,7 +2130,7 @@ fn NewSocket(comptime ssl: bool) type { } } - pub fn reload(this: *This, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn reload(this: *This, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { const args = callframe.arguments(1); if (args.len < 1) { @@ -2172,7 +2172,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, _: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (comptime ssl == false) { return JSValue.jsUndefined(); } @@ -2189,7 +2189,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (comptime ssl == false) { return JSValue.jsUndefined(); } @@ -2230,7 +2230,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (comptime ssl == false) { return JSValue.jsUndefined(); } @@ -2250,7 +2250,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (comptime ssl == false) { return JSValue.jsUndefined(); } @@ -2277,7 +2277,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (comptime ssl == false) { return JSValue.jsUndefined(); } @@ -2323,7 +2323,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (comptime ssl == false) { return JSValue.jsUndefined(); } @@ -2351,7 +2351,7 @@ fn NewSocket(comptime ssl: bool) type { pub fn getALPNProtocol( this: *This, globalObject: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (comptime ssl == false) { return JSValue.jsBoolean(false); } @@ -2383,7 +2383,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (comptime ssl == false) { return JSValue.jsUndefined(); } @@ -2471,7 +2471,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (comptime ssl == false) { return JSValue.jsNull(); } @@ -2540,7 +2540,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (comptime ssl == false) { return JSValue.jsUndefined(); } @@ -2587,7 +2587,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (comptime ssl == false) { return JSValue.jsUndefined(); } @@ -2619,7 +2619,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (comptime ssl == false) { return JSValue.jsUndefined(); } @@ -2651,7 +2651,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { JSC.markBinding(@src()); if (comptime ssl == false) { return JSValue.jsNull(); @@ -2742,7 +2742,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { JSC.markBinding(@src()); if (comptime ssl == false) { return JSValue.jsNull(); @@ -2765,7 +2765,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { JSC.markBinding(@src()); if (comptime ssl == false) { return JSValue.jsBoolean(false); @@ -2804,7 +2804,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { JSC.markBinding(@src()); if (comptime ssl == false) { return JSValue.jsUndefined(); @@ -2859,7 +2859,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (comptime ssl == false) { return JSValue.jsUndefined(); } @@ -2881,7 +2881,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (comptime ssl == false) { return JSValue.jsUndefined(); } @@ -2897,7 +2897,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (comptime ssl == false) { return JSValue.jsUndefined(); } @@ -2956,7 +2956,7 @@ fn NewSocket(comptime ssl: bool) type { this: *This, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { JSC.markBinding(@src()); if (comptime ssl) { return JSValue.jsUndefined(); @@ -3252,7 +3252,7 @@ pub fn NewWrappedHandler(comptime tls: bool) type { } }; } -pub fn jsAddServerName(global: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { +pub fn jsAddServerName(global: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { JSC.markBinding(@src()); const arguments = callframe.arguments(3); @@ -3270,6 +3270,6 @@ pub fn jsAddServerName(global: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) c pub fn createNodeTLSBinding(global: *JSC.JSGlobalObject) JSC.JSValue { return JSC.JSArray.create(global, &.{ - JSC.JSFunction.create(global, "addServerName", jsAddServerName, 3, .{}), + JSC.JSFunction.create(global, "addServerName", JSC.toJSHostFunction(jsAddServerName), 3, .{}), }); } diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig index f5ec360e1d..6d8822f27e 100644 --- a/src/bun.js/api/bun/subprocess.zig +++ b/src/bun.js/api/bun/subprocess.zig @@ -43,14 +43,14 @@ pub const ResourceUsage = struct { pub fn constructor( _: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) ?*Subprocess { + ) ?*Subprocess { return null; } pub fn getCPUTime( this: *ResourceUsage, globalObject: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { var cpu = JSC.JSValue.createEmptyObjectWithNullPrototype(globalObject); const rusage = this.rusage; @@ -67,28 +67,28 @@ pub const ResourceUsage = struct { pub fn getMaxRSS( this: *ResourceUsage, _: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { return JSC.JSValue.jsNumber(this.rusage.maxrss); } pub fn getSharedMemorySize( this: *ResourceUsage, _: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { return JSC.JSValue.jsNumber(this.rusage.ixrss); } pub fn getSwapCount( this: *ResourceUsage, _: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { return JSC.JSValue.jsNumber(this.rusage.nswap); } pub fn getOps( this: *ResourceUsage, globalObject: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { var ops = JSC.JSValue.createEmptyObjectWithNullPrototype(globalObject); ops.put(globalObject, JSC.ZigString.static("in"), JSC.JSValue.jsNumber(this.rusage.inblock)); ops.put(globalObject, JSC.ZigString.static("out"), JSC.JSValue.jsNumber(this.rusage.oublock)); @@ -98,7 +98,7 @@ pub const ResourceUsage = struct { pub fn getMessages( this: *ResourceUsage, globalObject: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { var msgs = JSC.JSValue.createEmptyObjectWithNullPrototype(globalObject); msgs.put(globalObject, JSC.ZigString.static("sent"), JSC.JSValue.jsNumber(this.rusage.msgsnd)); msgs.put(globalObject, JSC.ZigString.static("received"), JSC.JSValue.jsNumber(this.rusage.msgrcv)); @@ -108,14 +108,14 @@ pub const ResourceUsage = struct { pub fn getSignalCount( this: *ResourceUsage, _: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { return JSC.JSValue.jsNumber(this.rusage.nsignals); } pub fn getContextSwitches( this: *ResourceUsage, globalObject: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { var ctx = JSC.JSValue.createEmptyObjectWithNullPrototype(globalObject); ctx.put(globalObject, JSC.ZigString.static("voluntary"), JSC.JSValue.jsNumber(this.rusage.nvcsw)); ctx.put(globalObject, JSC.ZigString.static("involuntary"), JSC.JSValue.jsNumber(this.rusage.nivcsw)); @@ -227,7 +227,7 @@ pub const Subprocess = struct { this: *Subprocess, globalObject: *JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { return this.createResourceUsageObject(globalObject); } @@ -386,7 +386,7 @@ pub const Subprocess = struct { pub fn constructor( _: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) ?*Subprocess { + ) ?*Subprocess { return null; } @@ -560,7 +560,7 @@ pub const Subprocess = struct { pub fn getStderr( this: *Subprocess, globalThis: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { this.observable_getters.insert(.stderr); return this.stderr.toJS(globalThis, this.hasExited()); } @@ -568,7 +568,7 @@ pub const Subprocess = struct { pub fn getStdin( this: *Subprocess, globalThis: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { this.observable_getters.insert(.stdin); return this.stdin.toJS(globalThis, this); } @@ -576,7 +576,7 @@ pub const Subprocess = struct { pub fn getStdout( this: *Subprocess, globalThis: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { this.observable_getters.insert(.stdout); return this.stdout.toJS(globalThis, this.hasExited()); } @@ -585,7 +585,7 @@ pub const Subprocess = struct { this: *Subprocess, global: *JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (this.process.hasExited()) { // rely on GC to clean everything up in this case return .undefined; @@ -613,7 +613,7 @@ pub const Subprocess = struct { this: *Subprocess, globalThis: *JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { this.this_jsvalue = callframe.this(); var arguments = callframe.arguments(1); @@ -694,12 +694,12 @@ pub const Subprocess = struct { this.process.close(); } - pub fn doRef(this: *Subprocess, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSValue { + pub fn doRef(this: *Subprocess, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSValue { this.ref(); return JSC.JSValue.jsUndefined(); } - pub fn doUnref(this: *Subprocess, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSValue { + pub fn doUnref(this: *Subprocess, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSValue { this.unref(); return JSC.JSValue.jsUndefined(); } @@ -717,7 +717,7 @@ pub const Subprocess = struct { } } - pub fn doSend(this: *Subprocess, global: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn doSend(this: *Subprocess, global: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) JSValue { const ipc_data = &(this.ipc_data orelse { if (this.hasExited()) { global.throw("Subprocess.send() cannot be used after the process has exited.", .{}); @@ -753,21 +753,21 @@ pub const Subprocess = struct { pub fn getPid( this: *Subprocess, _: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { return JSValue.jsNumber(this.pid()); } pub fn getKilled( this: *Subprocess, _: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { return JSValue.jsBoolean(this.hasKilled()); } pub fn getStdio( this: *Subprocess, global: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { const array = JSValue.createEmptyArray(global, 0); array.push(global, .null); array.push(global, .null); // TODO: align this with options @@ -1574,7 +1574,7 @@ pub const Subprocess = struct { pub fn getExited( this: *Subprocess, globalThis: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { switch (this.process.status) { .exited => |exit| { return JSC.JSPromise.resolvedPromiseValue(globalThis, JSValue.jsNumber(exit.code)); @@ -1598,7 +1598,7 @@ pub const Subprocess = struct { pub fn getExitCode( this: *Subprocess, _: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (this.process.status == .exited) { return JSC.JSValue.jsNumber(this.process.status.exited.code); } @@ -1608,7 +1608,7 @@ pub const Subprocess = struct { pub fn getSignalCode( this: *Subprocess, global: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (this.process.signalCode()) |signal| { if (signal.name()) |name| return JSC.ZigString.init(name).toJS(global) diff --git a/src/bun.js/api/bun/udp_socket.zig b/src/bun.js/api/bun/udp_socket.zig index 27bebaeb5a..ea43d4947d 100644 --- a/src/bun.js/api/bun/udp_socket.zig +++ b/src/bun.js/api/bun/udp_socket.zig @@ -280,7 +280,7 @@ pub const UDPSocket = struct { pub usingnamespace JSC.Codegen.JSUDPSocket; - pub fn constructor(globalThis: *JSGlobalObject, _: *CallFrame) callconv(.C) ?*This { + pub fn constructor(globalThis: *JSGlobalObject, _: *CallFrame) ?*This { globalThis.throw("Cannot construct UDPSocket", .{}); return null; } @@ -372,7 +372,7 @@ pub const UDPSocket = struct { return true; } - pub fn sendMany(this: *This, globalThis: *JSGlobalObject, callframe: *CallFrame) callconv(.C) JSValue { + pub fn sendMany(this: *This, globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { if (this.closed) { globalThis.throw("Socket is closed", .{}); return .zero; @@ -462,7 +462,7 @@ pub const UDPSocket = struct { this: *This, globalThis: *JSGlobalObject, callframe: *CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (this.closed) { globalThis.throw("Socket is closed", .{}); return .zero; @@ -566,7 +566,7 @@ pub const UDPSocket = struct { address: JSValue, }; - pub fn ref(this: *This, globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSValue { + pub fn ref(this: *This, globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSValue { if (!this.closed) { this.poll_ref.ref(globalThis.bunVM()); } @@ -574,7 +574,7 @@ pub const UDPSocket = struct { return .undefined; } - pub fn unref(this: *This, globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSValue { + pub fn unref(this: *This, globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSValue { if (!this.closed) { this.poll_ref.unref(globalThis.bunVM()); } @@ -586,13 +586,13 @@ pub const UDPSocket = struct { this: *This, _: *JSGlobalObject, _: *CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (!this.closed) this.socket.close(); return .undefined; } - pub fn reload(this: *This, globalThis: *JSGlobalObject, callframe: *CallFrame) callconv(.C) JSValue { + pub fn reload(this: *This, globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { const args = callframe.arguments(1); if (args.len < 1) { @@ -613,16 +613,16 @@ pub const UDPSocket = struct { return .undefined; } - pub fn getClosed(this: *This, _: *JSGlobalObject) callconv(.C) JSValue { + pub fn getClosed(this: *This, _: *JSGlobalObject) JSValue { return JSValue.jsBoolean(this.closed); } - pub fn getHostname(this: *This, _: *JSGlobalObject) callconv(.C) JSValue { + pub fn getHostname(this: *This, _: *JSGlobalObject) JSValue { const hostname = JSC.ZigString.init(this.config.hostname); return hostname.toJS(this.globalThis); } - pub fn getPort(this: *This, _: *JSGlobalObject) callconv(.C) JSValue { + pub fn getPort(this: *This, _: *JSGlobalObject) JSValue { if (this.closed) return .undefined; return JSValue.jsNumber(this.socket.boundPort()); } @@ -639,7 +639,7 @@ pub const UDPSocket = struct { return bun.String.createLatin1(slice).toJS(globalThis); } - pub fn getAddress(this: *This, globalThis: *JSGlobalObject) callconv(.C) JSValue { + pub fn getAddress(this: *This, globalThis: *JSGlobalObject) JSValue { if (this.closed) return .undefined; var buf: [64]u8 = [_]u8{0} ** 64; var length: i32 = 64; @@ -655,7 +655,7 @@ pub const UDPSocket = struct { ); } - pub fn getRemoteAddress(this: *This, globalThis: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getRemoteAddress(this: *This, globalThis: *JSC.JSGlobalObject) JSC.JSValue { if (this.closed) return .undefined; const connect_info = this.connect_info orelse return .undefined; var buf: [64]u8 = [_]u8{0} ** 64; @@ -674,7 +674,7 @@ pub const UDPSocket = struct { pub fn getBinaryType( this: *This, globalThis: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { return switch (this.config.binary_type) { .Buffer => JSC.ZigString.init("buffer").toJS(globalThis), .Uint8Array => JSC.ZigString.init("uint8array").toJS(globalThis), @@ -697,7 +697,7 @@ pub const UDPSocket = struct { this.destroy(); } - pub fn jsConnect(globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn jsConnect(globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) JSC.JSValue { const args = callFrame.arguments(2); const this = callFrame.this().as(UDPSocket) orelse { @@ -747,7 +747,7 @@ pub const UDPSocket = struct { return .undefined; } - pub fn jsDisconnect(globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn jsDisconnect(globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) JSC.JSValue { const this = callFrame.this().as(UDPSocket) orelse { globalObject.throwInvalidArguments("Expected UDPSocket as 'this'", .{}); return .zero; diff --git a/src/bun.js/api/ffi.zig b/src/bun.js/api/ffi.zig index 16dc982c76..7b64c504c0 100644 --- a/src/bun.js/api/ffi.zig +++ b/src/bun.js/api/ffi.zig @@ -424,7 +424,7 @@ pub const FFI = struct { return js_object; } - pub fn getSymbols(_: *FFI, _: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getSymbols(_: *FFI, _: *JSC.JSGlobalObject) JSC.JSValue { // This shouldn't be called. The cachedValue is what should be called. return .undefined; } diff --git a/src/bun.js/api/filesystem_router.zig b/src/bun.js/api/filesystem_router.zig index 5b8ae51214..74052edbe6 100644 --- a/src/bun.js/api/filesystem_router.zig +++ b/src/bun.js/api/filesystem_router.zig @@ -49,7 +49,7 @@ pub const FileSystemRouter = struct { pub usingnamespace JSC.Codegen.JSFileSystemRouter; - pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) ?*FileSystemRouter { + pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) ?*FileSystemRouter { const argument_ = callframe.arguments(1); if (argument_.len == 0) { globalThis.throwInvalidArguments("Expected object", .{}); @@ -211,7 +211,7 @@ pub const FileSystemRouter = struct { return fs_router; } - pub fn reload(this: *FileSystemRouter, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn reload(this: *FileSystemRouter, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { const this_value = callframe.this(); var arena = globalThis.allocator().create(bun.ArenaAllocator) catch unreachable; @@ -259,7 +259,7 @@ pub const FileSystemRouter = struct { return this_value; } - pub fn match(this: *FileSystemRouter, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn match(this: *FileSystemRouter, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { const argument_ = callframe.arguments(2); if (argument_.len == 0) { globalThis.throwInvalidArguments("Expected string, Request or Response", .{}); @@ -327,7 +327,7 @@ pub const FileSystemRouter = struct { return result.toJS(globalThis); } - pub fn getOrigin(this: *FileSystemRouter, globalThis: *JSC.JSGlobalObject) callconv(.C) JSValue { + pub fn getOrigin(this: *FileSystemRouter, globalThis: *JSC.JSGlobalObject) JSValue { if (this.origin) |origin| { return JSC.ZigString.init(origin.slice()).withEncoding().toJS(globalThis); } @@ -335,7 +335,7 @@ pub const FileSystemRouter = struct { return JSValue.jsNull(); } - pub fn getRoutes(this: *FileSystemRouter, globalThis: *JSC.JSGlobalObject) callconv(.C) JSValue { + pub fn getRoutes(this: *FileSystemRouter, globalThis: *JSC.JSGlobalObject) JSValue { const paths = this.router.getEntryPoints() catch unreachable; const names = this.router.getNames() catch unreachable; var name_strings = bun.default_allocator.alloc(ZigString, names.len * 2) catch unreachable; @@ -354,11 +354,11 @@ pub const FileSystemRouter = struct { ); } - pub fn getStyle(_: *FileSystemRouter, globalThis: *JSC.JSGlobalObject) callconv(.C) JSValue { + pub fn getStyle(_: *FileSystemRouter, globalThis: *JSC.JSGlobalObject) JSValue { return ZigString.static("nextjs").toJS(globalThis); } - pub fn getAssetPrefix(this: *FileSystemRouter, globalThis: *JSC.JSGlobalObject) callconv(.C) JSValue { + pub fn getAssetPrefix(this: *FileSystemRouter, globalThis: *JSC.JSGlobalObject) JSValue { if (this.asset_prefix) |asset_prefix| { return JSC.ZigString.init(asset_prefix.slice()).withEncoding().toJS(globalThis); } @@ -399,7 +399,7 @@ pub const MatchedRoute = struct { pub usingnamespace JSC.Codegen.JSMatchedRoute; - pub fn getName(this: *MatchedRoute, globalThis: *JSC.JSGlobalObject) callconv(.C) JSValue { + pub fn getName(this: *MatchedRoute, globalThis: *JSC.JSGlobalObject) JSValue { return ZigString.init(this.route.name).withEncoding().toJS(globalThis); } @@ -466,7 +466,7 @@ pub const MatchedRoute = struct { pub fn getFilePath( this: *MatchedRoute, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { return ZigString.init(this.route.file_path) .withEncoding() .toJS(globalThis); @@ -478,13 +478,13 @@ pub const MatchedRoute = struct { this.deinit(); } - pub fn getPathname(this: *MatchedRoute, globalThis: *JSC.JSGlobalObject) callconv(.C) JSValue { + pub fn getPathname(this: *MatchedRoute, globalThis: *JSC.JSGlobalObject) JSValue { return ZigString.init(this.route.pathname) .withEncoding() .toJS(globalThis); } - pub fn getRoute(this: *MatchedRoute, globalThis: *JSC.JSGlobalObject) callconv(.C) JSValue { + pub fn getRoute(this: *MatchedRoute, globalThis: *JSC.JSGlobalObject) JSValue { return ZigString.init(this.route.name) .withEncoding() .toJS(globalThis); @@ -510,13 +510,13 @@ pub const MatchedRoute = struct { } }; - pub fn getKind(this: *MatchedRoute, globalThis: *JSC.JSGlobalObject) callconv(.C) JSValue { + pub fn getKind(this: *MatchedRoute, globalThis: *JSC.JSGlobalObject) JSValue { return KindEnum.init(this.route.name).toJS(globalThis); } threadlocal var query_string_values_buf: [256]string = undefined; threadlocal var query_string_value_refs_buf: [256]ZigString = undefined; - pub fn createQueryObject(ctx: js.JSContextRef, map: *QueryStringMap) callconv(.C) JSValue { + pub fn createQueryObject(ctx: js.JSContextRef, map: *QueryStringMap) JSValue { const QueryObjectCreator = struct { query: *QueryStringMap, pub fn create(this: *@This(), obj: *JSObject, global: *JSGlobalObject) void { @@ -577,7 +577,7 @@ pub const MatchedRoute = struct { pub fn getScriptSrc( this: *MatchedRoute, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { var buf: bun.PathBuffer = undefined; var stream = std.io.fixedBufferStream(&buf); var writer = stream.writer(); @@ -598,7 +598,7 @@ pub const MatchedRoute = struct { pub fn getParams( this: *MatchedRoute, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { if (this.route.params.len == 0) return JSValue.createEmptyObject(globalThis, 0); @@ -621,7 +621,7 @@ pub const MatchedRoute = struct { pub fn getQuery( this: *MatchedRoute, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { if (this.route.query_string.len == 0 and this.route.params.len == 0) { return JSValue.createEmptyObject(globalThis, 0); } else if (this.route.query_string.len == 0) { diff --git a/src/bun.js/api/glob.zig b/src/bun.js/api/glob.zig index 1ea9ca9086..2aa6fd17ad 100644 --- a/src/bun.js/api/glob.zig +++ b/src/bun.js/api/glob.zig @@ -317,7 +317,7 @@ fn makeGlobWalker( pub fn constructor( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, -) callconv(.C) ?*Glob { +) ?*Glob { const alloc = getAllocator(globalThis); const arguments_ = callframe.arguments(1); @@ -384,7 +384,7 @@ fn decrPendingActivityFlag(has_pending_activity: *std.atomic.Value(usize)) void _ = has_pending_activity.fetchSub(1, .seq_cst); } -pub fn __scan(this: *Glob, globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { +pub fn __scan(this: *Glob, globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const alloc = getAllocator(globalThis); const arguments_ = callframe.arguments(1); @@ -408,7 +408,7 @@ pub fn __scan(this: *Glob, globalThis: *JSGlobalObject, callframe: *JSC.CallFram return task.promise.value(); } -pub fn __scanSync(this: *Glob, globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { +pub fn __scanSync(this: *Glob, globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const alloc = getAllocator(globalThis); const arguments_ = callframe.arguments(1); @@ -438,7 +438,7 @@ pub fn __scanSync(this: *Glob, globalThis: *JSGlobalObject, callframe: *JSC.Call return matchedPaths; } -pub fn match(this: *Glob, globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { +pub fn match(this: *Glob, globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const alloc = getAllocator(globalThis); var arena = Arena.init(alloc); defer arena.deinit(); diff --git a/src/bun.js/api/html_rewriter.zig b/src/bun.js/api/html_rewriter.zig index 4f9ca29a1d..3de0d37fed 100644 --- a/src/bun.js/api/html_rewriter.zig +++ b/src/bun.js/api/html_rewriter.zig @@ -1091,7 +1091,7 @@ pub const TextChunk = struct { this: *TextChunk, _: *JSGlobalObject, callFrame: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (this.text_chunk == null) return JSValue.jsUndefined(); this.text_chunk.?.remove(); @@ -1101,17 +1101,17 @@ pub const TextChunk = struct { pub fn getText( this: *TextChunk, global: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (this.text_chunk == null) return JSValue.jsUndefined(); return ZigString.init(this.text_chunk.?.getContent().slice()).withEncoding().toJS(global); } - pub fn removed(this: *TextChunk, _: *JSGlobalObject) callconv(.C) JSValue { + pub fn removed(this: *TextChunk, _: *JSGlobalObject) JSValue { return JSValue.jsBoolean(this.text_chunk.?.isRemoved()); } - pub fn lastInTextNode(this: *TextChunk, _: *JSGlobalObject) callconv(.C) JSValue { + pub fn lastInTextNode(this: *TextChunk, _: *JSGlobalObject) JSValue { return JSValue.jsBoolean(this.text_chunk.?.isLastInTextNode()); } @@ -1135,7 +1135,7 @@ pub const DocType = struct { pub fn name( this: *DocType, globalObject: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (this.doctype == null) return JSValue.jsUndefined(); const str = this.doctype.?.getName().slice(); @@ -1147,7 +1147,7 @@ pub const DocType = struct { pub fn systemId( this: *DocType, globalObject: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (this.doctype == null) return JSValue.jsUndefined(); @@ -1160,7 +1160,7 @@ pub const DocType = struct { pub fn publicId( this: *DocType, globalObject: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (this.doctype == null) return JSValue.jsUndefined(); @@ -1273,7 +1273,7 @@ pub const Comment = struct { this: *Comment, _: *JSGlobalObject, callFrame: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (this.comment == null) return JSValue.jsNull(); this.comment.?.remove(); @@ -1283,7 +1283,7 @@ pub const Comment = struct { pub fn getText( this: *Comment, globalObject: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (this.comment == null) return JSValue.jsNull(); return this.comment.?.getText().toJS(globalObject); @@ -1309,7 +1309,7 @@ pub const Comment = struct { pub fn removed( this: *Comment, _: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (this.comment == null) return JSValue.jsUndefined(); return JSValue.jsBoolean(this.comment.?.isRemoved()); @@ -1395,7 +1395,7 @@ pub const EndTag = struct { this: *EndTag, _: *JSGlobalObject, callFrame: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (this.end_tag == null) return JSValue.jsUndefined(); @@ -1406,7 +1406,7 @@ pub const EndTag = struct { pub fn getName( this: *EndTag, globalObject: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (this.end_tag == null) return JSValue.jsUndefined(); @@ -1444,7 +1444,7 @@ pub const AttributeIterator = struct { pub usingnamespace JSC.Codegen.JSAttributeIterator; - pub fn next(this: *AttributeIterator, globalObject: *JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSValue { + pub fn next(this: *AttributeIterator, globalObject: *JSGlobalObject, _: *JSC.CallFrame) JSValue { const done_label = JSC.ZigString.static("done"); const value_label = JSC.ZigString.static("value"); @@ -1470,7 +1470,7 @@ pub const AttributeIterator = struct { )); } - pub fn getThis(_: *AttributeIterator, _: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn getThis(_: *AttributeIterator, _: *JSGlobalObject, callFrame: *JSC.CallFrame) JSValue { return callFrame.this(); } }; @@ -1669,7 +1669,7 @@ pub const Element = struct { this: *Element, _: *JSGlobalObject, callFrame: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (this.element == null) return JSValue.jsUndefined(); @@ -1682,14 +1682,14 @@ pub const Element = struct { this: *Element, _: *JSGlobalObject, callFrame: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { if (this.element == null) return JSValue.jsUndefined(); this.element.?.removeAndKeepContent(); return callFrame.this(); } - pub fn getTagName(this: *Element, globalObject: *JSGlobalObject) callconv(.C) JSValue { + pub fn getTagName(this: *Element, globalObject: *JSGlobalObject) JSValue { if (this.element == null) return JSValue.jsUndefined(); @@ -1700,7 +1700,7 @@ pub const Element = struct { this: *Element, global: *JSGlobalObject, value: JSValue, - ) callconv(.C) bool { + ) bool { if (this.element == null) return false; @@ -1718,7 +1718,7 @@ pub const Element = struct { pub fn getRemoved( this: *Element, _: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (this.element == null) return JSValue.jsUndefined(); return JSValue.jsBoolean(this.element.?.isRemoved()); @@ -1727,7 +1727,7 @@ pub const Element = struct { pub fn getSelfClosing( this: *Element, _: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (this.element == null) return JSValue.jsUndefined(); return JSValue.jsBoolean(this.element.?.isSelfClosing()); @@ -1736,7 +1736,7 @@ pub const Element = struct { pub fn getCanHaveContent( this: *Element, _: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (this.element == null) return JSValue.jsUndefined(); return JSValue.jsBoolean(this.element.?.canHaveContent()); @@ -1745,7 +1745,7 @@ pub const Element = struct { pub fn getNamespaceURI( this: *Element, globalObject: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (this.element == null) return JSValue.jsUndefined(); var str = bun.String.createUTF8(std.mem.span(this.element.?.namespaceURI())); @@ -1756,7 +1756,7 @@ pub const Element = struct { pub fn getAttributes( this: *Element, globalObject: *JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (this.element == null) return JSValue.jsUndefined(); diff --git a/src/bun.js/api/brotli.classes.ts b/src/bun.js/api/js_brotli.classes.ts similarity index 100% rename from src/bun.js/api/brotli.classes.ts rename to src/bun.js/api/js_brotli.classes.ts diff --git a/src/bun.js/api/brotli.zig b/src/bun.js/api/js_brotli.zig similarity index 97% rename from src/bun.js/api/brotli.zig rename to src/bun.js/api/js_brotli.zig index 9a467a81a1..ec2402fc3d 100644 --- a/src/bun.js/api/brotli.zig +++ b/src/bun.js/api/js_brotli.zig @@ -35,12 +35,12 @@ pub const BrotliEncoder = struct { return this.has_pending_activity.load(.monotonic) > 0; } - pub fn constructor(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) ?*BrotliEncoder { + pub fn constructor(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) ?*BrotliEncoder { globalThis.throw("BrotliEncoder is not constructable", .{}); return null; } - pub fn create(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn create(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const arguments = callframe.arguments(3).slice(); if (arguments.len < 3) { @@ -220,7 +220,7 @@ pub const BrotliEncoder = struct { } }; - pub fn encode(this: *BrotliEncoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn encode(this: *BrotliEncoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const arguments = callframe.arguments(3); if (arguments.len < 2) { @@ -262,7 +262,7 @@ pub const BrotliEncoder = struct { return .undefined; } - pub fn encodeSync(this: *BrotliEncoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn encodeSync(this: *BrotliEncoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const arguments = callframe.arguments(3); if (arguments.len < 2) { @@ -303,7 +303,7 @@ pub const BrotliEncoder = struct { return if (!is_last and this.output.items.len == 0) .undefined else this.collectOutputValue(); } - pub fn end(this: *BrotliEncoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn end(this: *BrotliEncoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { _ = this; _ = globalThis; _ = callframe; @@ -311,7 +311,7 @@ pub const BrotliEncoder = struct { return .zero; } - pub fn endSync(this: *BrotliEncoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn endSync(this: *BrotliEncoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { _ = this; _ = globalThis; _ = callframe; @@ -357,12 +357,12 @@ pub const BrotliDecoder = struct { this.destroy(); } - pub fn constructor(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) ?*BrotliDecoder { + pub fn constructor(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) ?*BrotliDecoder { globalThis.throw("Crypto is not constructable", .{}); return null; } - pub fn create(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn create(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const arguments = callframe.arguments(3).slice(); if (arguments.len < 3) { @@ -444,7 +444,7 @@ pub const BrotliDecoder = struct { this.freelist.discard(to_free.len); } - pub fn decode(this: *BrotliDecoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn decode(this: *BrotliDecoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const arguments = callframe.arguments(3); if (arguments.len < 2) { @@ -486,7 +486,7 @@ pub const BrotliDecoder = struct { return .undefined; } - pub fn decodeSync(this: *BrotliDecoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn decodeSync(this: *BrotliDecoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const arguments = callframe.arguments(3); if (arguments.len < 2) { @@ -603,7 +603,7 @@ pub const BrotliDecoder = struct { } }; - pub fn end(this: *BrotliDecoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn end(this: *BrotliDecoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { _ = this; _ = globalThis; _ = callframe; @@ -611,7 +611,7 @@ pub const BrotliDecoder = struct { return .zero; } - pub fn endSync(this: *BrotliDecoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn endSync(this: *BrotliDecoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { _ = this; _ = globalThis; _ = callframe; diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index 38e26aae72..3178abffb6 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -1467,7 +1467,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp } } - pub fn onResolve(_: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn onResolve(_: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSValue { ctxLog("onResolve", .{}); const arguments = callframe.arguments(2); @@ -1542,7 +1542,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp if (this.pending_promises_for_abort == 0) this.finalize(); } - pub fn onReject(_: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn onReject(_: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSValue { ctxLog("onReject", .{}); const arguments = callframe.arguments(2); @@ -2817,7 +2817,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp req.finalize(); } - pub fn onResolveStream(_: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn onResolveStream(_: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSValue { streamLog("onResolveStream", .{}); var args = callframe.arguments(2); var req: *@This() = args.ptr[args.len - 1].asPromisePtr(@This()); @@ -2825,7 +2825,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp req.handleResolveStream(); return JSValue.jsUndefined(); } - pub fn onRejectStream(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn onRejectStream(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSValue { streamLog("onRejectStream", .{}); const args = callframe.arguments(2); var req = args.ptr[args.len - 1].asPromisePtr(@This()); @@ -3595,20 +3595,18 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp }); comptime { - if (!JSC.is_bindgen) { - @export(onResolve, .{ - .name = Export[0].symbol_name, - }); - @export(onReject, .{ - .name = Export[1].symbol_name, - }); - @export(onResolveStream, .{ - .name = Export[2].symbol_name, - }); - @export(onRejectStream, .{ - .name = Export[3].symbol_name, - }); - } + @export(onResolve, .{ + .name = Export[0].symbol_name, + }); + @export(onReject, .{ + .name = Export[1].symbol_name, + }); + @export(onResolveStream, .{ + .name = Export[2].symbol_name, + }); + @export(onRejectStream, .{ + .name = Export[3].symbol_name, + }); } }; } @@ -4297,7 +4295,7 @@ pub const ServerWebSocket = struct { return uws.WebSocketBehavior.Wrap(ServerType, @This(), ssl).apply(opts); } - pub fn constructor(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) ?*ServerWebSocket { + pub fn constructor(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) ?*ServerWebSocket { globalObject.throw("Cannot construct ServerWebSocket", .{}); return null; } @@ -4311,7 +4309,7 @@ pub const ServerWebSocket = struct { this: *ServerWebSocket, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { const args = callframe.arguments(4); if (args.len < 1) { @@ -4397,7 +4395,7 @@ pub const ServerWebSocket = struct { this: *ServerWebSocket, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { const args = callframe.arguments(4); if (args.len < 1) { @@ -4460,7 +4458,7 @@ pub const ServerWebSocket = struct { this: *ServerWebSocket, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { const args = callframe.arguments(4); if (args.len < 1) { @@ -4527,7 +4525,7 @@ pub const ServerWebSocket = struct { globalThis: *JSC.JSGlobalObject, topic_str: *JSC.JSString, array: *JSC.JSUint8Array, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const app = this.handler.app orelse { log("publish() closed", .{}); return JSValue.jsNumber(0); @@ -4567,7 +4565,7 @@ pub const ServerWebSocket = struct { globalThis: *JSC.JSGlobalObject, topic_str: *JSC.JSString, str: *JSC.JSString, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const app = this.handler.app orelse { log("publish() closed", .{}); return JSValue.jsNumber(0); @@ -4608,7 +4606,7 @@ pub const ServerWebSocket = struct { this: *ServerWebSocket, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { const args = callframe.arguments(1); if (args.len < 1) { @@ -4649,7 +4647,7 @@ pub const ServerWebSocket = struct { this: *ServerWebSocket, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { const args = callframe.arguments(2); if (args.len < 1) { @@ -4723,7 +4721,7 @@ pub const ServerWebSocket = struct { this: *ServerWebSocket, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { const args = callframe.arguments(2); if (args.len < 1) { @@ -4777,7 +4775,7 @@ pub const ServerWebSocket = struct { globalThis: *JSC.JSGlobalObject, message_str: *JSC.JSString, compress: bool, - ) callconv(.C) JSValue { + ) JSValue { if (this.isClosed()) { log("sendText() closed", .{}); return JSValue.jsNumber(0); @@ -4807,7 +4805,7 @@ pub const ServerWebSocket = struct { this: *ServerWebSocket, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { const args = callframe.arguments(2); if (args.len < 1) { @@ -4857,7 +4855,7 @@ pub const ServerWebSocket = struct { _: *JSC.JSGlobalObject, array_buffer: *JSC.JSUint8Array, compress: bool, - ) callconv(.C) JSValue { + ) JSValue { if (this.isClosed()) { log("sendBinary() closed", .{}); return JSValue.jsNumber(0); @@ -4885,7 +4883,7 @@ pub const ServerWebSocket = struct { this: *ServerWebSocket, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { return sendPing(this, globalThis, callframe, "ping", .ping); } @@ -4893,7 +4891,7 @@ pub const ServerWebSocket = struct { this: *ServerWebSocket, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { return sendPing(this, globalThis, callframe, "pong", .pong); } @@ -4973,7 +4971,7 @@ pub const ServerWebSocket = struct { pub fn getData( _: *ServerWebSocket, _: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { log("getData()", .{}); return JSValue.jsUndefined(); } @@ -4991,7 +4989,7 @@ pub const ServerWebSocket = struct { pub fn getReadyState( this: *ServerWebSocket, _: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { log("getReadyState()", .{}); if (this.isClosed()) { @@ -5005,7 +5003,7 @@ pub const ServerWebSocket = struct { this: *ServerWebSocket, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { const args = callframe.arguments(2); log("close()", .{}); @@ -5049,7 +5047,7 @@ pub const ServerWebSocket = struct { this: *ServerWebSocket, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { _ = globalThis; const args = callframe.arguments(2); _ = args; @@ -5069,7 +5067,7 @@ pub const ServerWebSocket = struct { pub fn getBinaryType( this: *ServerWebSocket, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { log("getBinaryType()", .{}); return switch (this.flags.binary_type) { @@ -5105,7 +5103,7 @@ pub const ServerWebSocket = struct { this: *ServerWebSocket, _: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { log("getBufferedAmount()", .{}); if (this.isClosed()) { @@ -5118,7 +5116,7 @@ pub const ServerWebSocket = struct { this: *ServerWebSocket, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { const args = callframe.arguments(1); if (args.len < 1) { globalThis.throw("subscribe requires at least 1 argument", .{}); @@ -5155,7 +5153,7 @@ pub const ServerWebSocket = struct { this: *ServerWebSocket, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { const args = callframe.arguments(1); if (args.len < 1) { globalThis.throw("unsubscribe requires at least 1 argument", .{}); @@ -5192,7 +5190,7 @@ pub const ServerWebSocket = struct { this: *ServerWebSocket, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { const args = callframe.arguments(1); if (args.len < 1) { globalThis.throw("isSubscribed requires at least 1 argument", .{}); @@ -5229,7 +5227,7 @@ pub const ServerWebSocket = struct { pub fn getRemoteAddress( this: *ServerWebSocket, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (this.isClosed()) { return JSValue.jsUndefined(); } @@ -5295,7 +5293,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp pub usingnamespace NamespaceType; - pub fn constructor(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) ?*ThisServer { + pub fn constructor(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) ?*ThisServer { globalThis.throw("Server() is not a constructor", .{}); return null; } @@ -5562,7 +5560,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp this: *ThisServer, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const arguments = callframe.arguments(1).slice(); if (arguments.len < 1) { globalThis.throwNotEnoughArguments("reload", 1, 0); @@ -5593,7 +5591,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp this: *ThisServer, ctx: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { JSC.markBinding(@src()); const arguments = callframe.arguments(2).slice(); if (arguments.len == 0) { @@ -5737,7 +5735,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp pub fn getPort( this: *ThisServer, _: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { switch (this.config.address) { .unix => return .undefined, else => {}, @@ -5750,7 +5748,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp pub fn getId( this: *ThisServer, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { var str = bun.String.createUTF8(this.config.id); defer str.deref(); return str.toJS(globalThis); @@ -5759,18 +5757,18 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp pub fn getPendingRequests( this: *ThisServer, _: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return JSC.JSValue.jsNumber(@as(i32, @intCast(@as(u31, @truncate(this.pending_requests))))); } pub fn getPendingWebSockets( this: *ThisServer, _: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return JSC.JSValue.jsNumber(@as(i32, @intCast(@as(u31, @truncate(this.activeSocketsCount()))))); } - pub fn getAddress(this: *ThisServer, globalThis: *JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getAddress(this: *ThisServer, globalThis: *JSGlobalObject) JSC.JSValue { switch (this.config.address) { .unix => |unix| { var value = bun.String.createUTF8(unix); @@ -5802,7 +5800,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp } } - pub fn getURL(this: *ThisServer, globalThis: *JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getURL(this: *ThisServer, globalThis: *JSGlobalObject) JSC.JSValue { const fmt = switch (this.config.address) { .unix => |unix| brk: { if (unix.len > 1 and unix[0] == 0) { @@ -5839,7 +5837,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp return value.toJSDOMURL(globalThis); } - pub fn getHostname(this: *ThisServer, globalThis: *JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getHostname(this: *ThisServer, globalThis: *JSGlobalObject) JSC.JSValue { switch (this.config.address) { .unix => return .undefined, else => {}, @@ -5872,7 +5870,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp return this.cached_hostname.toJS(globalThis); } - pub fn getProtocol(this: *ThisServer, globalThis: *JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getProtocol(this: *ThisServer, globalThis: *JSGlobalObject) JSC.JSValue { if (this.cached_protocol.isEmpty()) { this.cached_protocol = bun.String.createUTF8(if (ssl_enabled) "https" else "http"); } @@ -5883,7 +5881,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp pub fn getDevelopment( _: *ThisServer, _: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return JSC.JSValue.jsBoolean(debug_mode); } @@ -6137,14 +6135,14 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp this.poll_ref.unref(this.vm); } - pub fn doRef(this: *ThisServer, _: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn doRef(this: *ThisServer, _: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const this_value = callframe.this(); this.ref(); return this_value; } - pub fn doUnref(this: *ThisServer, _: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn doUnref(this: *ThisServer, _: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const this_value = callframe.this(); this.unref(); diff --git a/src/bun.js/base.zig b/src/bun.js/base.zig index 16ab349138..9c3e789712 100644 --- a/src/bun.js/base.zig +++ b/src/bun.js/base.zig @@ -931,7 +931,6 @@ pub fn DOMCall( comptime class_name: string, comptime Container: type, comptime functionName: string, - comptime ResultType: type, comptime dom_effect: DOMEffect, ) type { return extern struct { @@ -949,7 +948,7 @@ pub fn DOMCall( thisValue: JSC.JSValue, arguments_ptr: [*]const JSC.JSValue, arguments_len: usize, - ) callconv(.C) JSValue { + ) callconv(JSC.conv) JSValue { return @field(Container, functionName)( globalObject, thisValue, @@ -961,215 +960,18 @@ pub fn DOMCall( pub const Fastpath = @TypeOf(fastpath); pub const Arguments = std.meta.ArgsTuple(Fastpath); - pub const Export = shim.exportFunctions(.{ - .slowpath = slowpath, - .fastpath = fastpath, - }); - pub fn put(globalObject: *JSC.JSGlobalObject, value: JSValue) void { shim.cppFn("put", .{ globalObject, value }); } pub const effect = dom_effect; - pub fn printGenerateDOMJITSignature(comptime Writer: type, writer: Writer) !void { - const signatureName = "DOMJIT_" ++ shim.name ++ "_signature"; - const slowPathName = Export[0].symbol_name; - const fastPathName = Export[1].symbol_name; - const Fields: []const std.builtin.Type.StructField = std.meta.fields(Arguments); - - const options = .{ - .name = functionName, - .exportName = name ++ "__put", - .signatureName = signatureName, - .IDLResultName = DOMCallResultType(ResultType), - .fastPathName = fastPathName, - .slowPathName = slowPathName, - .argumentsCount = Fields.len - 2, - }; - { - const fmt = - \\extern "C" JSC_DECLARE_HOST_FUNCTION({[slowPathName]s}Wrapper); - \\extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL({[fastPathName]s}Wrapper, EncodedJSValue, (JSC::JSGlobalObject* lexicalGlobalObject, void* thisValue - ; - try writer.print(fmt, .{ .fastPathName = options.fastPathName, .slowPathName = options.slowPathName }); - } - { - switch (Fields.len - 2) { - 0 => { - try writer.writeAll("));\n"); - }, - 1 => { - try writer.writeAll(", "); - try writer.writeAll(DOMCallArgumentTypeWrapper(Fields[2].type)); - try writer.writeAll("));\n"); - }, - 2 => { - try writer.writeAll(", "); - try writer.writeAll(DOMCallArgumentTypeWrapper(Fields[2].type)); - try writer.writeAll(", "); - try writer.writeAll(DOMCallArgumentTypeWrapper(Fields[3].type)); - try writer.writeAll("));\n"); - }, - else => @compileError("Must be <= 3 arguments"), - } - } - - { - const fmt = - \\ - \\JSC_DEFINE_JIT_OPERATION({[fastPathName]s}Wrapper, EncodedJSValue, (JSC::JSGlobalObject* lexicalGlobalObject, void* thisValue - ; - try writer.print(fmt, .{ .fastPathName = options.fastPathName }); - } - { - switch (Fields.len - 2) { - 0 => { - try writer.writeAll(")) {\n"); - }, - 1 => { - try writer.writeAll(", "); - try writer.writeAll(DOMCallArgumentTypeWrapper(Fields[2].type)); - try writer.writeAll(" arg1)) {\n"); - }, - 2 => { - try writer.writeAll(", "); - try writer.writeAll(DOMCallArgumentTypeWrapper(Fields[2].type)); - try writer.writeAll(" arg1, "); - try writer.writeAll(DOMCallArgumentTypeWrapper(Fields[3].type)); - try writer.writeAll(" arg2)) {\n"); - }, - else => @compileError("Must be <= 3 arguments"), - } - { - const fmt = - \\VM& vm = JSC::getVM(lexicalGlobalObject); - \\IGNORE_WARNINGS_BEGIN("frame-address") - \\CallFrame* callFrame = DECLARE_CALL_FRAME(vm); - \\IGNORE_WARNINGS_END - \\JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - \\return {[fastPathName]s}(lexicalGlobalObject, thisValue - ; - try writer.print(fmt, .{ .fastPathName = options.fastPathName }); - } - { - switch (Fields.len - 2) { - 0 => { - try writer.writeAll(");\n}\n"); - }, - 1 => { - try writer.writeAll(", arg1);\n}\n"); - }, - 2 => { - try writer.writeAll(", arg1, arg2);\n}\n"); - }, - else => @compileError("Must be <= 3 arguments"), - } - } - } - - { - const fmt = - \\JSC_DEFINE_HOST_FUNCTION({[slowPathName]s}Wrapper, (JSC::JSGlobalObject *globalObject, JSC::CallFrame* frame)) {{ - \\ return {[slowPathName]s}(globalObject, JSValue::encode(frame->thisValue()), reinterpret_cast(frame->addressOfArgumentsStart()), frame->argumentCount()); - \\}} - \\ - \\extern "C" void {[exportName]s}(JSC::JSGlobalObject *globalObject, JSC::EncodedJSValue value) {{ - \\ JSC::JSObject *thisObject = JSC::jsCast(JSC::JSValue::decode(value)); - \\ static const JSC::DOMJIT::Signature {[signatureName]s}( - \\ {[fastPathName]s}Wrapper, - \\ thisObject->classInfo(), - \\ - ; - - try writer.print(fmt, .{ - .slowPathName = options.slowPathName, - .exportName = options.exportName, - .fastPathName = options.fastPathName, - .signatureName = options.signatureName, - }); - } - if (effect.isPure()) { - try writer.writeAll("JSC::DOMJIT::Effect::forPure(),\n "); - } else if (effect.writes[0] == DOMEffect.pure.writes[0]) { - try writer.print( - "JSC::DOMJIT::Effect::forReadKinds(JSC::DFG::AbstractHeapKind::{s}, JSC::DFG::AbstractHeapKind::{s}, JSC::DFG::AbstractHeapKind::{s}, JSC::DFG::AbstractHeapKind::{s}),\n ", - .{ - @tagName(effect.reads[0]), - @tagName(effect.reads[1]), - @tagName(effect.reads[2]), - @tagName(effect.reads[3]), - }, - ); - } else if (effect.reads[0] == DOMEffect.pure.reads[0]) { - try writer.print( - "JSC::DOMJIT::Effect::forWriteKinds(JSC::DFG::AbstractHeapKind::{s}, JSC::DFG::AbstractHeapKind::{s}, JSC::DFG::AbstractHeapKind::{s}, JSC::DFG::AbstractHeapKind::{s}),\n ", - .{ - @tagName(effect.writes[0]), - @tagName(effect.writes[1]), - @tagName(effect.writes[2]), - @tagName(effect.writes[3]), - }, - ); - } else { - try writer.writeAll("JSC::DOMJIT::Effect::forReadWrite(JSC::DOMJIT::HeapRange::top(), JSC::DOMJIT::HeapRange::top()),\n "); - } - - { - try writer.writeAll(DOMCallResultType(ResultType)); - } - - switch (Fields.len - 2) { - 0 => {}, - 1 => { - try writer.writeAll(",\n "); - try writer.writeAll(DOMCallArgumentType(Fields[2].type)); - try writer.writeAll("\n "); - }, - 2 => { - try writer.writeAll(",\n "); - try writer.writeAll(DOMCallArgumentType(Fields[2].type)); - try writer.writeAll(",\n "); - try writer.writeAll(DOMCallArgumentType(Fields[3].type)); - try writer.writeAll("\n "); - }, - else => @compileError("Must be <= 3 arguments"), - } - - try writer.writeAll(");\n "); - - { - const fmt = - \\ JSFunction* function = JSFunction::create( - \\ globalObject->vm(), - \\ globalObject, - \\ {[argumentsCount]d}, - \\ String("{[name]s}"_s), - \\ {[slowPathName]s}Wrapper, ImplementationVisibility::Public, NoIntrinsic, {[slowPathName]s}Wrapper, - \\ &{[signatureName]s} - \\ ); - \\ thisObject->putDirect( - \\ globalObject->vm(), - \\ Identifier::fromString(globalObject->vm(), "{[name]s}"_s), - \\ function - \\ ); - \\}} - ; - try writer.print(fmt, .{ - .argumentsCount = options.argumentsCount, - .name = options.name, - .slowPathName = options.slowPathName, - .signatureName = options.signatureName, - }); - } - } - pub const Extern = [_][]const u8{"put"}; comptime { if (!JSC.is_bindgen) { - @export(slowpath, .{ .name = Export[0].symbol_name }); - @export(fastpath, .{ .name = Export[1].symbol_name }); + @export(slowpath, .{ .name = shim.symbolName("slowpath") }); + @export(fastpath, .{ .name = shim.symbolName("fastpath") }); } else { _ = slowpath; _ = fastpath; @@ -1179,7 +981,7 @@ pub fn DOMCall( } pub fn InstanceMethodType(comptime Container: type) type { - return fn (instance: *Container, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue; + return fn (instance: *Container, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue; } pub fn wrapInstanceMethod( @@ -1197,7 +999,7 @@ pub fn wrapInstanceMethod( this: *Container, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(FunctionTypeInfo.params.len); var iter = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments.slice()); var args: Args = undefined; @@ -1351,7 +1153,7 @@ pub fn wrapInstanceMethod( } } - return @call(.auto, @field(Container, name), args); + return @call(.always_inline, @field(Container, name), args); } }.method; } @@ -1370,7 +1172,7 @@ pub fn wrapStaticMethod( pub fn method( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(FunctionTypeInfo.params.len); var iter = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments.slice()); var args: Args = undefined; @@ -1504,7 +1306,7 @@ pub fn wrapStaticMethod( defer iter.deinit(); - return @call(.auto, @field(Container, name), args); + return @call(.always_inline, @field(Container, name), args); } }.method; } diff --git a/src/bun.js/bindings/BunObject+exports.h b/src/bun.js/bindings/BunObject+exports.h index 17bf201b60..2925acbfd1 100644 --- a/src/bun.js/bindings/BunObject+exports.h +++ b/src/bun.js/bindings/BunObject+exports.h @@ -1,3 +1,4 @@ +#pragma once // clang-format off // --- Getters --- @@ -67,15 +68,15 @@ macro(createShellInterpreter) \ macro(createParsedShellScript) \ -#define DECLARE_ZIG_BUN_OBJECT_CALLBACK(name) extern "C" JSC::EncodedJSValue BunObject_callback_##name(JSC::JSGlobalObject*, JSC::CallFrame*); +#define DECLARE_ZIG_BUN_OBJECT_CALLBACK(name) BUN_DECLARE_HOST_FUNCTION(BunObject_callback_##name); FOR_EACH_CALLBACK(DECLARE_ZIG_BUN_OBJECT_CALLBACK); #undef DECLARE_ZIG_BUN_OBJECT_CALLBACK -#define DECLARE_ZIG_BUN_OBJECT_GETTER(name) extern "C" JSC::EncodedJSValue BunObject_getter_##name(JSC::JSGlobalObject*, JSC::JSObject*); +#define DECLARE_ZIG_BUN_OBJECT_GETTER(name) extern "C" JSC::EncodedJSValue SYSV_ABI BunObject_getter_##name(JSC::JSGlobalObject*, JSC::JSObject*); FOR_EACH_GETTER(DECLARE_ZIG_BUN_OBJECT_GETTER); #undef DECLARE_ZIG_BUN_OBJECT_GETTER -#define DEFINE_ZIG_BUN_OBJECT_GETTER_WRAPPER(name) JSC::JSValue BunObject_getter_wrap_##name(JSC::VM &vm, JSC::JSObject *object) { \ +#define DEFINE_ZIG_BUN_OBJECT_GETTER_WRAPPER(name) static JSC::JSValue BunObject_getter_wrap_##name(JSC::VM &vm, JSC::JSObject *object) { \ return JSC::JSValue::decode(BunObject_getter_##name(object->globalObject(), object)); \ } \ diff --git a/src/bun.js/bindings/BunObject.cpp b/src/bun.js/bindings/BunObject.cpp index 0f2b1f67e7..c15cb12a5a 100644 --- a/src/bun.js/bindings/BunObject.cpp +++ b/src/bun.js/bindings/BunObject.cpp @@ -25,18 +25,36 @@ #include "DOMJITIDLType.h" #include "DOMJITIDLTypeFilter.h" #include "Exception.h" -#include "BunObject+exports.h" #include "JSDOMException.h" #include "JSDOMConvert.h" #include "wtf/Compiler.h" #include "PathInlines.h" +#include "wtf/text/ASCIILiteral.h" +#include "BunObject+exports.h" + +BUN_DECLARE_HOST_FUNCTION(Bun__DNSResolver__lookup); +BUN_DECLARE_HOST_FUNCTION(Bun__DNSResolver__resolve); +BUN_DECLARE_HOST_FUNCTION(Bun__DNSResolver__resolveSrv); +BUN_DECLARE_HOST_FUNCTION(Bun__DNSResolver__resolveTxt); +BUN_DECLARE_HOST_FUNCTION(Bun__DNSResolver__resolveSoa); +BUN_DECLARE_HOST_FUNCTION(Bun__DNSResolver__resolveNaptr); +BUN_DECLARE_HOST_FUNCTION(Bun__DNSResolver__resolveMx); +BUN_DECLARE_HOST_FUNCTION(Bun__DNSResolver__resolveCaa); +BUN_DECLARE_HOST_FUNCTION(Bun__DNSResolver__resolveNs); +BUN_DECLARE_HOST_FUNCTION(Bun__DNSResolver__resolvePtr); +BUN_DECLARE_HOST_FUNCTION(Bun__DNSResolver__resolveCname); +BUN_DECLARE_HOST_FUNCTION(Bun__DNSResolver__getServers); +BUN_DECLARE_HOST_FUNCTION(Bun__DNSResolver__reverse); +BUN_DECLARE_HOST_FUNCTION(Bun__DNSResolver__lookupService); +BUN_DECLARE_HOST_FUNCTION(Bun__DNSResolver__prefetch); +BUN_DECLARE_HOST_FUNCTION(Bun__DNSResolver__getCacheStats); +BUN_DECLARE_HOST_FUNCTION(Bun__fetch); namespace Bun { using namespace JSC; using namespace WebCore; -extern "C" JSC::EncodedJSValue Bun__fetch(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); extern "C" bool has_bun_garbage_collector_flag_enabled; static JSValue BunObject_getter_wrap_ArrayBufferSink(VM& vm, JSObject* bunObject) @@ -219,12 +237,12 @@ JSC_DECLARE_HOST_FUNCTION(functionConcatTypedArrays); static JSValue constructBunVersion(VM& vm, JSObject*) { - return JSC::jsString(vm, makeString(Bun__version + 1)); + return JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(Bun__version + 1))); } static JSValue constructBunRevision(VM& vm, JSObject*) { - return JSC::jsString(vm, makeString(Bun__version_sha)); + return JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(Bun__version_sha))); } static JSValue constructIsMainThread(VM&, JSObject* object) @@ -275,23 +293,6 @@ static JSValue constructBunShell(VM& vm, JSObject* bunObject) return bunShell; } -extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__DNSResolver__lookup); -extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__DNSResolver__resolve); -extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__DNSResolver__resolveSrv); -extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__DNSResolver__resolveTxt); -extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__DNSResolver__resolveSoa); -extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__DNSResolver__resolveNaptr); -extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__DNSResolver__resolveMx); -extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__DNSResolver__resolveCaa); -extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__DNSResolver__resolveNs); -extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__DNSResolver__resolvePtr); -extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__DNSResolver__resolveCname); -extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__DNSResolver__getServers); -extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__DNSResolver__reverse); -extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__DNSResolver__lookupService); -extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__DNSResolver__prefetch); -extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__DNSResolver__getCacheStats); - static JSValue constructDNSObject(VM& vm, JSObject* bunObject) { JSGlobalObject* globalObject = bunObject->globalObject(); @@ -389,7 +390,7 @@ JSC_DEFINE_HOST_FUNCTION(functionBunEscapeHTML, (JSC::JSGlobalObject * lexicalGl if (!length) RELEASE_AND_RETURN(scope, JSValue::encode(string)); - auto resolvedString = string->value(lexicalGlobalObject); + String resolvedString = string->value(lexicalGlobalObject); JSC::EncodedJSValue encodedInput = JSValue::encode(string); if (!resolvedString.is8Bit()) { const auto span = resolvedString.span16(); diff --git a/src/bun.js/bindings/BunPlugin.cpp b/src/bun.js/bindings/BunPlugin.cpp index d30185f781..f0019a56d0 100644 --- a/src/bun.js/bindings/BunPlugin.cpp +++ b/src/bun.js/bindings/BunPlugin.cpp @@ -251,20 +251,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionAppendOnResolvePluginBrowser, (JSC::JSGlobalO return jsFunctionAppendOnResolvePluginGlobal(globalObject, callframe, BunPluginTargetBrowser); } -extern "C" JSC::EncodedJSValue jsFunctionBunPluginClear(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe) -{ - Zig::GlobalObject* global = reinterpret_cast(globalObject); - global->onLoadPlugins.fileNamespace.clear(); - global->onResolvePlugins.fileNamespace.clear(); - global->onLoadPlugins.groups.clear(); - global->onResolvePlugins.namespaces.clear(); - - delete global->onLoadPlugins.virtualModules; - - return JSValue::encode(jsUndefined()); -} - -extern "C" JSC::EncodedJSValue setupBunPlugin(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe, BunPluginTarget target) +static inline JSC::EncodedJSValue setupBunPlugin(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe, BunPluginTarget target) { JSC::VM& vm = globalObject->vm(); auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -287,7 +274,7 @@ extern "C" JSC::EncodedJSValue setupBunPlugin(JSC::JSGlobalObject* globalObject, if (JSValue targetValue = obj->getIfPropertyExists(globalObject, Identifier::fromString(vm, "target"_s))) { if (auto* targetJSString = targetValue.toStringOrNull(globalObject)) { - auto targetString = targetJSString->value(globalObject); + String targetString = targetJSString->value(globalObject); if (!(targetString == "node"_s || targetString == "bun"_s || targetString == "browser"_s)) { JSC::throwTypeError(globalObject, throwScope, "plugin target must be one of 'node', 'bun' or 'browser'"_s); return JSValue::encode(jsUndefined()); @@ -343,11 +330,6 @@ extern "C" JSC::EncodedJSValue setupBunPlugin(JSC::JSGlobalObject* globalObject, RELEASE_AND_RETURN(throwScope, JSValue::encode(jsUndefined())); } -extern "C" JSC::EncodedJSValue jsFunctionBunPlugin(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe) -{ - return setupBunPlugin(globalObject, callframe, BunPluginTargetBun); -} - void BunPlugin::Group::append(JSC::VM& vm, JSC::RegExp* filter, JSC::JSFunction* func) { filters.append(JSC::Strong { vm, filter }); @@ -488,7 +470,8 @@ JSObject* JSModuleMock::executeOnce(JSC::JSGlobalObject* lexicalGlobalObject) } extern "C" JSC::EncodedJSValue Bun__resolveSyncWithSource(JSC::JSGlobalObject* global, JSC::EncodedJSValue specifier, BunString* from, bool is_esm); -extern "C" EncodedJSValue JSMock__jsModuleMock(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callframe) +BUN_DECLARE_HOST_FUNCTION(JSMock__jsModuleMock); +extern "C" JSC_DEFINE_HOST_FUNCTION(JSMock__jsModuleMock, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callframe)) { JSC::VM& vm = lexicalGlobalObject->vm(); Zig::GlobalObject* globalObject = jsDynamicCast(lexicalGlobalObject); @@ -929,4 +912,22 @@ JSC::JSValue runVirtualModule(Zig::GlobalObject* globalObject, BunString* specif return fallback(); } -} // namespace Bun \ No newline at end of file +} // namespace Bun + +BUN_DEFINE_HOST_FUNCTION(jsFunctionBunPluginClear, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + Zig::GlobalObject* global = reinterpret_cast(globalObject); + global->onLoadPlugins.fileNamespace.clear(); + global->onResolvePlugins.fileNamespace.clear(); + global->onLoadPlugins.groups.clear(); + global->onResolvePlugins.namespaces.clear(); + + delete global->onLoadPlugins.virtualModules; + + return JSC::JSValue::encode(JSC::jsUndefined()); +} + +BUN_DEFINE_HOST_FUNCTION(jsFunctionBunPlugin, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + return Bun::setupBunPlugin(globalObject, callframe, BunPluginTargetBun); +} \ No newline at end of file diff --git a/src/bun.js/bindings/BunPlugin.h b/src/bun.js/bindings/BunPlugin.h index 41f1956cde..44a606234e 100644 --- a/src/bun.js/bindings/BunPlugin.h +++ b/src/bun.js/bindings/BunPlugin.h @@ -6,8 +6,8 @@ #include #include "helpers.h" -extern "C" JSC_DECLARE_HOST_FUNCTION(jsFunctionBunPlugin); -extern "C" JSC_DECLARE_HOST_FUNCTION(jsFunctionBunPluginClear); +BUN_DECLARE_HOST_FUNCTION(jsFunctionBunPlugin); +BUN_DECLARE_HOST_FUNCTION(jsFunctionBunPluginClear); namespace Zig { diff --git a/src/bun.js/bindings/BunProcess.cpp b/src/bun.js/bindings/BunProcess.cpp index 45c625af6e..0e7ac404d1 100644 --- a/src/bun.js/bindings/BunProcess.cpp +++ b/src/bun.js/bindings/BunProcess.cpp @@ -113,15 +113,15 @@ extern "C" Zig::GlobalObject* Bun__getDefaultGlobal(); extern "C" bool Bun__GlobalObject__hasIPC(JSGlobalObject*); extern "C" bool Bun__ensureProcessIPCInitialized(JSGlobalObject*); extern "C" const char* Bun__githubURL; -extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__Process__send); -extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__Process__disconnect); +BUN_DECLARE_HOST_FUNCTION(Bun__Process__send); +BUN_DECLARE_HOST_FUNCTION(Bun__Process__disconnect); static JSValue constructArch(VM& vm, JSObject* processObject) { #if CPU(X86_64) - return JSC::jsString(vm, makeAtomString("x64")); + return JSC::jsString(vm, makeAtomString("x64"_s)); #elif CPU(ARM64) - return JSC::jsString(vm, makeAtomString("arm64")); + return JSC::jsString(vm, makeAtomString("arm64"_s)); #else #error "Unknown architecture" #endif @@ -146,55 +146,55 @@ static JSValue constructVersions(VM& vm, JSObject* processObject) JSC::JSObject* object = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 23); object->putDirect(vm, JSC::Identifier::fromString(vm, "node"_s), - JSC::JSValue(JSC::jsOwnedString(vm, makeAtomString(REPORTED_NODEJS_VERSION)))); + JSC::JSValue(JSC::jsOwnedString(vm, makeAtomString(ASCIILiteral::fromLiteralUnsafe(REPORTED_NODEJS_VERSION))))); object->putDirect( vm, JSC::Identifier::fromString(vm, "bun"_s), - JSC::JSValue(JSC::jsOwnedString(vm, makeAtomString(Bun__version + 1 /* remove "v" prefix */)))); + JSC::JSValue(JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(Bun__version)).substring(1)))); object->putDirect(vm, JSC::Identifier::fromString(vm, "boringssl"_s), - JSC::JSValue(JSC::jsString(vm, makeString(Bun__versions_boringssl))), 0); + JSC::JSValue(JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(Bun__versions_boringssl)))), 0); object->putDirect(vm, JSC::Identifier::fromString(vm, "openssl"_s), // https://github.com/oven-sh/bun/issues/7921 // BoringSSL is a fork of OpenSSL 1.1.0, so we can report OpenSSL 1.1.0 JSC::JSValue(JSC::jsString(vm, String("1.1.0"_s), 0))); object->putDirect(vm, JSC::Identifier::fromString(vm, "libarchive"_s), - JSC::JSValue(JSC::jsString(vm, makeString(Bun__versions_libarchive))), 0); + JSC::JSValue(JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(Bun__versions_libarchive)))), 0); object->putDirect(vm, JSC::Identifier::fromString(vm, "mimalloc"_s), - JSC::JSValue(JSC::jsString(vm, makeString(Bun__versions_mimalloc))), 0); + JSC::JSValue(JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(Bun__versions_mimalloc)))), 0); object->putDirect(vm, JSC::Identifier::fromString(vm, "picohttpparser"_s), - JSC::JSValue(JSC::jsString(vm, makeString(Bun__versions_picohttpparser))), 0); + JSC::JSValue(JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(Bun__versions_picohttpparser)))), 0); object->putDirect(vm, JSC::Identifier::fromString(vm, "uwebsockets"_s), - JSC::JSValue(JSC::jsString(vm, makeString(Bun__versions_uws))), 0); + JSC::JSValue(JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(Bun__versions_uws)))), 0); object->putDirect(vm, JSC::Identifier::fromString(vm, "webkit"_s), - JSC::JSValue(JSC::jsString(vm, makeString(Bun__versions_webkit))), 0); + JSC::JSValue(JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(Bun__versions_webkit)))), 0); object->putDirect(vm, JSC::Identifier::fromString(vm, "zig"_s), - JSC::JSValue(JSC::jsString(vm, makeString(Bun__versions_zig))), 0); + JSC::JSValue(JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(Bun__versions_zig)))), 0); object->putDirect(vm, JSC::Identifier::fromString(vm, "zlib"_s), - JSC::JSValue(JSC::jsString(vm, makeString(Bun__versions_zlib))), 0); + JSC::JSValue(JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(Bun__versions_zlib)))), 0); object->putDirect(vm, JSC::Identifier::fromString(vm, "tinycc"_s), - JSC::JSValue(JSC::jsString(vm, makeString(Bun__versions_tinycc))), 0); + JSC::JSValue(JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(Bun__versions_tinycc)))), 0); object->putDirect(vm, JSC::Identifier::fromString(vm, "lolhtml"_s), - JSC::JSValue(JSC::jsString(vm, makeString(Bun__versions_lolhtml))), 0); + JSC::JSValue(JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(Bun__versions_lolhtml)))), 0); object->putDirect(vm, JSC::Identifier::fromString(vm, "ares"_s), - JSC::JSValue(JSC::jsString(vm, makeString(Bun__versions_c_ares))), 0); + JSC::JSValue(JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(Bun__versions_c_ares)))), 0); object->putDirect(vm, JSC::Identifier::fromString(vm, "usockets"_s), - JSC::JSValue(JSC::jsString(vm, makeString(Bun__versions_usockets))), 0); + JSC::JSValue(JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(Bun__versions_usockets)))), 0); object->putDirect(vm, JSC::Identifier::fromString(vm, "lshpack"_s), - JSC::JSValue(JSC::jsString(vm, makeString(Bun__versions_lshpack))), 0); + JSC::JSValue(JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(Bun__versions_lshpack)))), 0); object->putDirect(vm, JSC::Identifier::fromString(vm, "zstd"_s), - JSC::JSValue(JSC::jsString(vm, makeString(Bun__versions_zstd))), 0); + JSC::JSValue(JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(Bun__versions_zstd)))), 0); object->putDirect(vm, JSC::Identifier::fromString(vm, "v8"_s), JSValue(JSC::jsString(vm, makeString("12.4.254.14-node.12"_s))), 0); #if OS(WINDOWS) - object->putDirect(vm, JSC::Identifier::fromString(vm, "uv"_s), JSValue(JSC::jsString(vm, makeString(uv_version_string()))), 0); + object->putDirect(vm, JSC::Identifier::fromString(vm, "uv"_s), JSValue(JSC::jsString(vm, String::fromLatin1(uv_version_string()))), 0); #else object->putDirect(vm, JSC::Identifier::fromString(vm, "uv"_s), JSValue(JSC::jsString(vm, makeString("1.48.0"_s))), 0); #endif object->putDirect(vm, JSC::Identifier::fromString(vm, "napi"_s), JSValue(JSC::jsString(vm, makeString("9"_s))), 0); - object->putDirect(vm, JSC::Identifier::fromString(vm, "icu"_s), JSValue(JSC::jsString(vm, makeString(U_ICU_VERSION))), 0); - object->putDirect(vm, JSC::Identifier::fromString(vm, "unicode"_s), JSValue(JSC::jsString(vm, makeString(U_UNICODE_VERSION))), 0); + object->putDirect(vm, JSC::Identifier::fromString(vm, "icu"_s), JSValue(JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(U_ICU_VERSION)))), 0); + object->putDirect(vm, JSC::Identifier::fromString(vm, "unicode"_s), JSValue(JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(U_UNICODE_VERSION)))), 0); object->putDirect(vm, JSC::Identifier::fromString(vm, "modules"_s), - JSC::JSValue(JSC::jsString(vm, makeAtomString("115")))); + JSC::JSValue(JSC::jsString(vm, makeString("115"_s)))); return object; } @@ -339,7 +339,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionDlopen, LPWSTR messageBuffer = nullptr; size_t size = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorId, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, NULL); - WTF::String msg = makeString("LoadLibrary failed: ", WTF::StringView(std::span { (UCHAR*)messageBuffer, size })); + WTF::String msg = makeString("LoadLibrary failed: "_s, WTF::StringView(std::span { (UCHAR*)messageBuffer, size })); LocalFree(messageBuffer); #else WTF::String msg = WTF::String::fromUTF8(dlerror()); @@ -1949,7 +1949,7 @@ static JSValue constructBrowser(VM& vm, JSObject* processObject) static JSValue constructVersion(VM& vm, JSObject* processObject) { - return JSC::jsString(vm, makeString("v", REPORTED_NODEJS_VERSION)); + return JSC::jsString(vm, makeString("v"_s, ASCIILiteral::fromLiteralUnsafe(REPORTED_NODEJS_VERSION))); } static JSValue constructIsBun(VM& vm, JSObject* processObject) @@ -1959,7 +1959,7 @@ static JSValue constructIsBun(VM& vm, JSObject* processObject) static JSValue constructRevision(VM& vm, JSObject* processObject) { - return JSC::jsString(vm, makeAtomString(Bun__version_sha)); + return JSC::jsString(vm, makeAtomString(ASCIILiteral::fromLiteralUnsafe(Bun__version_sha))); } static JSValue constructEnv(VM& vm, JSObject* processObject) diff --git a/src/bun.js/bindings/DOMURL.cpp b/src/bun.js/bindings/DOMURL.cpp index 638111df9d..6bd1b63683 100644 --- a/src/bun.js/bindings/DOMURL.cpp +++ b/src/bun.js/bindings/DOMURL.cpp @@ -65,7 +65,7 @@ ExceptionOr> DOMURL::create(const String& url) { URL completeURL { url }; if (!completeURL.isValid()) - return Exception { TypeError, makeString(redact(url), " cannot be parsed as a URL.") }; + return Exception { TypeError, makeString(redact(url), " cannot be parsed as a URL."_s) }; return adoptRef(*new DOMURL(WTFMove(completeURL))); } @@ -74,7 +74,7 @@ ExceptionOr> DOMURL::create(const String& url, const URL& base) ASSERT(base.isValid() || base.isNull()); URL completeURL { base, url }; if (!completeURL.isValid()) - return Exception { TypeError, makeString(redact(url), " cannot be parsed as a URL.") }; + return Exception { TypeError, makeString(redact(url), " cannot be parsed as a URL."_s) }; return adoptRef(*new DOMURL(WTFMove(completeURL))); } @@ -114,7 +114,7 @@ ExceptionOr DOMURL::setHref(const String& url) URL completeURL { URL {}, url }; if (!completeURL.isValid()) { - return Exception { TypeError, makeString(redact(url), " cannot be parsed as a URL.") }; + return Exception { TypeError, makeString(redact(url), " cannot be parsed as a URL."_s) }; } m_url = WTFMove(completeURL); if (m_searchParams) diff --git a/src/bun.js/bindings/ImportMetaObject.cpp b/src/bun.js/bindings/ImportMetaObject.cpp index fa93fc9f67..7b557e34d6 100644 --- a/src/bun.js/bindings/ImportMetaObject.cpp +++ b/src/bun.js/bindings/ImportMetaObject.cpp @@ -666,7 +666,7 @@ void ImportMetaObject::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) { // if (void* wrapped = thisObject->wrapped()) { // if (thisObject->scriptExecutionContext()) - // analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + // analyzer.setLabelForCell(cell, makeString("url "_s, thisObject->scriptExecutionContext()->url().string())); // } Base::analyzeHeap(cell, analyzer); } diff --git a/src/bun.js/bindings/InternalModuleRegistry.cpp b/src/bun.js/bindings/InternalModuleRegistry.cpp index d83ad266be..501c7a92aa 100644 --- a/src/bun.js/bindings/InternalModuleRegistry.cpp +++ b/src/bun.js/bindings/InternalModuleRegistry.cpp @@ -11,6 +11,7 @@ #include #include "InternalModuleRegistryConstants.h" +#include "wtf/Forward.h" namespace Bun { @@ -78,7 +79,7 @@ JSValue initializeInternalModuleFromDisk( WTF::String fileBase, const WTF::String& urlString) { - WTF::String file = makeString(BUN_DYNAMIC_JS_LOAD_PATH, "/"_s, WTFMove(fileBase)); + WTF::String file = makeString(ASCIILiteral::fromLiteralUnsafe(BUN_DYNAMIC_JS_LOAD_PATH), "/"_s, WTFMove(fileBase)); if (auto contents = WTF::FileSystemImpl::readEntireFile(file)) { auto string = WTF::String::fromUTF8(contents.value()); INTERNAL_MODULE_REGISTRY_GENERATE_(globalObject, vm, string, moduleName, urlString); diff --git a/src/bun.js/bindings/JS2Native.cpp b/src/bun.js/bindings/JS2Native.cpp index f0a89109b3..61b16fefb1 100644 --- a/src/bun.js/bindings/JS2Native.cpp +++ b/src/bun.js/bindings/JS2Native.cpp @@ -1,3 +1,4 @@ +#include "root.h" #include "JS2Native.h" #include @@ -5,6 +6,7 @@ #include #include "ZigGlobalObject.h" + #include "GeneratedJS2Native.h" #include "wtf/Assertions.h" diff --git a/src/bun.js/bindings/JSBuffer.cpp b/src/bun.js/bindings/JSBuffer.cpp index 55ad01ddba..fa6aa12eac 100644 --- a/src/bun.js/bindings/JSBuffer.cpp +++ b/src/bun.js/bindings/JSBuffer.cpp @@ -222,7 +222,7 @@ JSC::EncodedJSValue JSBuffer__bufferFromPointerAndLengthAndDeinit(JSC::JSGlobalO auto* subclassStructure = globalObject->JSBufferSubclassStructure(); if (LIKELY(length > 0)) { - auto buffer = ArrayBuffer::createFromBytes(ptr, length, createSharedTask([ctx, bytesDeallocator](void* p) { + auto buffer = ArrayBuffer::createFromBytes({ reinterpret_cast(ptr), length }, createSharedTask([ctx, bytesDeallocator](void* p) { if (bytesDeallocator) bytesDeallocator(p, ctx); })); @@ -256,11 +256,11 @@ static inline JSC::EncodedJSValue writeToBuffer(JSC::JSGlobalObject* lexicalGlob case WebCore::BufferEncodingType::base64url: case WebCore::BufferEncodingType::hex: { - if (view.is8Bit()) { - const auto span = view.span8(); + if (view->is8Bit()) { + const auto span = view->span8(); written = Bun__encoding__writeLatin1(span.data(), span.size(), reinterpret_cast(castedThis->vector()) + offset, length, static_cast(encoding)); } else { - const auto span = view.span16(); + const auto span = view->span16(); written = Bun__encoding__writeUTF16(span.data(), span.size(), reinterpret_cast(castedThis->vector()) + offset, length, static_cast(encoding)); } break; @@ -374,8 +374,8 @@ static JSC::EncodedJSValue constructFromEncoding(JSGlobalObject* lexicalGlobalOb const auto& view = str->tryGetValue(lexicalGlobalObject); JSC::EncodedJSValue result; - if (view.is8Bit()) { - const auto span = view.span8(); + if (view->is8Bit()) { + const auto span = view->span8(); switch (encoding) { case WebCore::BufferEncodingType::utf8: @@ -399,7 +399,7 @@ static JSC::EncodedJSValue constructFromEncoding(JSGlobalObject* lexicalGlobalOb } } } else { - const auto span = view.span16(); + const auto span = view->span16(); switch (encoding) { case WebCore::BufferEncodingType::utf8: case WebCore::BufferEncodingType::base64: @@ -568,7 +568,7 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocUnsafeSlowBod } // new SlowBuffer(size) -EncodedJSValue constructSlowBuffer(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) +JSC_DEFINE_HOST_FUNCTION(constructSlowBuffer, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return jsBufferConstructorFunction_allocUnsafeSlowBody(lexicalGlobalObject, callFrame); } @@ -605,8 +605,8 @@ static inline JSC::EncodedJSValue jsBufferByteLengthFromStringAndEncoding(JSC::J int64_t length = str->length(); const auto& view = str->tryGetValue(lexicalGlobalObject); - if (view.is8Bit()) { - const auto span = view.span8(); + if (view->is8Bit()) { + const auto span = view->span8(); if (span.data()[length - 1] == 0x3D) { length--; @@ -614,7 +614,7 @@ static inline JSC::EncodedJSValue jsBufferByteLengthFromStringAndEncoding(JSC::J length--; } } else { - const auto span = view.span16(); + const auto span = view->span16(); if (span.data()[length - 1] == 0x3D) { length--; @@ -633,11 +633,11 @@ static inline JSC::EncodedJSValue jsBufferByteLengthFromStringAndEncoding(JSC::J case WebCore::BufferEncodingType::utf8: { const auto& view = str->tryGetValue(lexicalGlobalObject); - if (view.is8Bit()) { - const auto span = view.span8(); + if (view->is8Bit()) { + const auto span = view->span8(); written = Bun__encoding__byteLengthLatin1(span.data(), span.size(), static_cast(encoding)); } else { - const auto span = view.span16(); + const auto span = view->span16(); written = Bun__encoding__byteLengthUTF16(span.data(), span.size(), static_cast(encoding)); } break; @@ -1715,7 +1715,7 @@ extern "C" JSC::EncodedJSValue JSBuffer__fromMmap(Zig::GlobalObject* globalObjec auto* structure = globalObject->JSBufferSubclassStructure(); - auto buffer = ArrayBuffer::createFromBytes(ptr, length, createSharedTask([length](void* p) { + auto buffer = ArrayBuffer::createFromBytes({ static_cast(ptr), length }, createSharedTask([length](void* p) { #if !OS(WINDOWS) munmap(p, length); #else @@ -1814,7 +1814,7 @@ JSC_DEFINE_JIT_OPERATION(jsBufferConstructorAllocWithoutTypeChecks, JSUint8Array CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - return allocBuffer(lexicalGlobalObject, byteLength); + return { allocBuffer(lexicalGlobalObject, byteLength) }; } JSC_DEFINE_JIT_OPERATION(jsBufferConstructorAllocUnsafeWithoutTypeChecks, JSUint8Array*, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int byteLength)) @@ -1824,7 +1824,7 @@ JSC_DEFINE_JIT_OPERATION(jsBufferConstructorAllocUnsafeWithoutTypeChecks, JSUint CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - return allocBufferUnsafe(lexicalGlobalObject, byteLength); + return { allocBufferUnsafe(lexicalGlobalObject, byteLength) }; } JSC_DEFINE_JIT_OPERATION(jsBufferConstructorAllocUnsafeSlowWithoutTypeChecks, JSUint8Array*, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int byteLength)) @@ -1834,7 +1834,7 @@ JSC_DEFINE_JIT_OPERATION(jsBufferConstructorAllocUnsafeSlowWithoutTypeChecks, JS CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - return allocBufferUnsafe(lexicalGlobalObject, byteLength); + return { allocBufferUnsafe(lexicalGlobalObject, byteLength) }; } JSC_ANNOTATE_HOST_FUNCTION(JSBufferConstructorConstruct, JSBufferConstructor::construct); diff --git a/src/bun.js/bindings/JSBuffer.h b/src/bun.js/bindings/JSBuffer.h index 0e18b1513b..2936564a40 100644 --- a/src/bun.js/bindings/JSBuffer.h +++ b/src/bun.js/bindings/JSBuffer.h @@ -44,7 +44,7 @@ JSC::JSUint8Array* createBuffer(JSC::JSGlobalObject* lexicalGlobalObject, const JSC::JSUint8Array* createBuffer(JSC::JSGlobalObject* lexicalGlobalObject, const char* ptr, size_t length); JSC::JSUint8Array* createEmptyBuffer(JSC::JSGlobalObject* lexicalGlobalObject); -JSC::EncodedJSValue constructSlowBuffer(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(constructSlowBuffer); JSC::JSObject* createBufferPrototype(JSC::VM&, JSC::JSGlobalObject*); JSC::Structure* createBufferStructure(JSC::VM&, JSC::JSGlobalObject*, JSC::JSValue prototype); JSC::JSObject* createBufferConstructor(JSC::VM&, JSC::JSGlobalObject*, JSC::JSObject* bufferPrototype); diff --git a/src/bun.js/bindings/JSBufferEncodingType.cpp b/src/bun.js/bindings/JSBufferEncodingType.cpp index 8645ee6914..336d7cfdda 100644 --- a/src/bun.js/bindings/JSBufferEncodingType.cpp +++ b/src/bun.js/bindings/JSBufferEncodingType.cpp @@ -20,6 +20,7 @@ #include "config.h" #include "JSBufferEncodingType.h" +#include "wtf/Forward.h" #include #include @@ -59,7 +60,7 @@ template<> std::optional parseEnumerationvalue(&lexicalGlobalObject); + String encoding = str->value(&lexicalGlobalObject); switch (encoding.length()) { case 0: { return BufferEncodingType::utf8; @@ -128,9 +129,9 @@ template<> std::optional parseEnumeration const char* expectedEnumerationValues() +template<> ASCIILiteral expectedEnumerationValues() { - return "\"utf8\", \"ucs2\", \"utf16le\", \"latin1\", \"ascii\", \"base64\", \"base64url\", \"hex\""; + return "\"utf8\", \"ucs2\", \"utf16le\", \"latin1\", \"ascii\", \"base64\", \"base64url\", \"hex\""_s; } } // namespace WebCore diff --git a/src/bun.js/bindings/JSBufferEncodingType.h b/src/bun.js/bindings/JSBufferEncodingType.h index ee78800624..76b3aea301 100644 --- a/src/bun.js/bindings/JSBufferEncodingType.h +++ b/src/bun.js/bindings/JSBufferEncodingType.h @@ -8,6 +8,6 @@ String convertEnumerationToString(BufferEncodingType); template<> JSC::JSString* convertEnumerationToJS(JSC::JSGlobalObject&, BufferEncodingType); template<> std::optional parseEnumeration(JSC::JSGlobalObject&, JSC::JSValue); -template<> const char* expectedEnumerationValues(); +template<> WTF::ASCIILiteral expectedEnumerationValues(); } // namespace WebCore \ No newline at end of file diff --git a/src/bun.js/bindings/JSBufferList.cpp b/src/bun.js/bindings/JSBufferList.cpp index 9a4e9aa7c0..b523b938ba 100644 --- a/src/bun.js/bindings/JSBufferList.cpp +++ b/src/bun.js/bindings/JSBufferList.cpp @@ -448,7 +448,6 @@ void JSBufferListConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* const ClassInfo JSBufferListConstructor::s_info = { "BufferList"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSBufferListConstructor) }; - JSValue getBufferList(Zig::GlobalObject* globalObject) { return reinterpret_cast(globalObject)->JSBufferList(); diff --git a/src/bun.js/bindings/JSCTaskScheduler.cpp b/src/bun.js/bindings/JSCTaskScheduler.cpp index 9f280e061c..ae090cf1c7 100644 --- a/src/bun.js/bindings/JSCTaskScheduler.cpp +++ b/src/bun.js/bindings/JSCTaskScheduler.cpp @@ -29,14 +29,19 @@ public: WTF_MAKE_ISO_ALLOCATED_IMPL(JSCDeferredWorkTask); -static JSC::VM& getVM(Ticket ticket) +static JSC::VM& getVM(Ref ticket) { - return ticket->scriptExecutionOwner.get()->vm(); + return ticket->scriptExecutionOwner()->vm(); } -void JSCTaskScheduler::onAddPendingWork(std::unique_ptr ticket, JSC::DeferredWorkTimer::WorkKind kind) +static JSC::VM& getVM(Ticket& ticket) { - JSC::VM& vm = getVM(ticket.get()); + return ticket->scriptExecutionOwner()->vm(); +} + +void JSCTaskScheduler::onAddPendingWork(Ref ticket, JSC::DeferredWorkTimer::WorkKind kind) +{ + JSC::VM& vm = getVM(ticket); auto clientData = WebCore::clientData(vm); auto& scheduler = clientData->deferredWorkTimer; Locker holder { scheduler.m_lock }; @@ -59,8 +64,8 @@ void JSCTaskScheduler::onCancelPendingWork(Ticket ticket) auto& scheduler = WebCore::clientData(getVM(ticket))->deferredWorkTimer; Locker holder { scheduler.m_lock }; - bool isKeepingEventLoopAlive = scheduler.m_pendingTicketsKeepingEventLoopAlive.removeIf([ticket](const auto& pendingTicket) { - return pendingTicket.get() == ticket; + bool isKeepingEventLoopAlive = scheduler.m_pendingTicketsKeepingEventLoopAlive.removeIf([ticket](auto pendingTicket) { + return pendingTicket.ptr() == ticket; }); if (isKeepingEventLoopAlive) { @@ -68,8 +73,8 @@ void JSCTaskScheduler::onCancelPendingWork(Ticket ticket) JSC::VM& vm = getVM(ticket); Bun__eventLoop__incrementRefConcurrently(WebCore::clientData(vm)->bunVM, -1); } else { - scheduler.m_pendingTicketsOther.removeIf([ticket](const auto& pendingTicket) { - return pendingTicket.get() == ticket; + scheduler.m_pendingTicketsOther.removeIf([ticket](auto pendingTicket) { + return pendingTicket.ptr() == ticket; }); } } diff --git a/src/bun.js/bindings/JSCTaskScheduler.h b/src/bun.js/bindings/JSCTaskScheduler.h index 3257eb9c88..325f063975 100644 --- a/src/bun.js/bindings/JSCTaskScheduler.h +++ b/src/bun.js/bindings/JSCTaskScheduler.h @@ -12,14 +12,14 @@ public: { } - static void onAddPendingWork(std::unique_ptr ticket, JSC::DeferredWorkTimer::WorkKind kind); + static void onAddPendingWork(Ref ticket, JSC::DeferredWorkTimer::WorkKind kind); static void onScheduleWorkSoon(JSC::DeferredWorkTimer::Ticket ticket, JSC::DeferredWorkTimer::Task&& task); static void onCancelPendingWork(JSC::DeferredWorkTimer::Ticket ticket); public: Lock m_lock; - HashSet> m_pendingTicketsKeepingEventLoopAlive; - HashSet> m_pendingTicketsOther; + HashSet> m_pendingTicketsKeepingEventLoopAlive; + HashSet> m_pendingTicketsOther; }; } \ No newline at end of file diff --git a/src/bun.js/bindings/JSDOMExceptionHandling.cpp b/src/bun.js/bindings/JSDOMExceptionHandling.cpp index e3f9971063..acb1a30948 100644 --- a/src/bun.js/bindings/JSDOMExceptionHandling.cpp +++ b/src/bun.js/bindings/JSDOMExceptionHandling.cpp @@ -148,29 +148,29 @@ JSValue createDOMException(JSGlobalObject* lexicalGlobalObject, ExceptionCode ec return jsUndefined(); switch (ec) { - case ExistingExceptionError: + case ExceptionCode::ExistingExceptionError: return jsUndefined(); // FIXME: Handle other WebIDL exception types. - case TypeError: + case ExceptionCode::TypeError: if (message.isEmpty()) return createTypeError(lexicalGlobalObject); return createTypeError(lexicalGlobalObject, message); - case RangeError: + case ExceptionCode::RangeError: if (message.isEmpty()) return createRangeError(lexicalGlobalObject, "Bad value"_s); return createRangeError(lexicalGlobalObject, message); - case JSSyntaxError: + case ExceptionCode::JSSyntaxError: if (message.isEmpty()) return createSyntaxError(lexicalGlobalObject); return createSyntaxError(lexicalGlobalObject, message); - case StackOverflowError: + case ExceptionCode::StackOverflowError: return createStackOverflowError(lexicalGlobalObject); - case OutOfMemoryError: + case ExceptionCode::OutOfMemoryError: return createOutOfMemoryError(lexicalGlobalObject); default: { @@ -178,7 +178,7 @@ JSValue createDOMException(JSGlobalObject* lexicalGlobalObject, ExceptionCode ec // For now, we're going to assume the lexicalGlobalObject. Which is wrong in cases like this: // frames[0].document.createElement(null, null); // throws an exception which should have the subframe's prototypes. // https://bugs.webkit.org/show_bug.cgi?id=222229 - JSDOMGlobalObject* globalObject = JSC::jsCast(lexicalGlobalObject); + JSDOMGlobalObject* globalObject = deprecatedGlobalObjectForPrototype(lexicalGlobalObject); JSValue errorObject = toJS(lexicalGlobalObject, globalObject, DOMException::create(ec, message)); ASSERT(errorObject); @@ -200,70 +200,70 @@ void propagateExceptionSlowPath(JSC::JSGlobalObject& lexicalGlobalObject, JSC::T throwException(&lexicalGlobalObject, throwScope, createDOMException(lexicalGlobalObject, WTFMove(exception))); } -static JSC::EncodedJSValue throwTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, const String& errorMessage) +static EncodedJSValue throwTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, const String& errorMessage) { return throwVMTypeError(&lexicalGlobalObject, scope, errorMessage); } -template static String makeArgumentTypeErrorMessage(unsigned argumentIndex, const char* argumentName, const char* interfaceName, const char* functionName, StringTypes... strings) +template static String makeArgumentTypeErrorMessage(unsigned argumentIndex, ASCIILiteral argumentName, ASCIILiteral interfaceName, ASCIILiteral functionName, StringTypes... strings) { return makeString( - "Argument ", argumentIndex + 1, " ('", argumentName, "') to ", - functionName ? std::make_tuple(interfaceName, ".", functionName) : std::make_tuple("the ", interfaceName, " constructor"), - " must be ", strings...); + "Argument "_s, argumentIndex + 1, " ('"_s, argumentName, "') to "_s, + functionName ? std::make_tuple(interfaceName, "."_s, functionName) : std::make_tuple("the "_s, interfaceName, " constructor"_s), + " must be "_s, strings...); } void throwNotSupportedError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, ASCIILiteral message) { scope.assertNoExceptionExceptTermination(); - throwException(&lexicalGlobalObject, scope, createDOMException(&lexicalGlobalObject, NotSupportedError, message)); + throwException(&lexicalGlobalObject, scope, createDOMException(&lexicalGlobalObject, ExceptionCode::NotSupportedError, message)); } void throwInvalidStateError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, ASCIILiteral message) { scope.assertNoExceptionExceptTermination(); - throwException(&lexicalGlobalObject, scope, createDOMException(&lexicalGlobalObject, InvalidStateError, message)); + throwException(&lexicalGlobalObject, scope, createDOMException(&lexicalGlobalObject, ExceptionCode::InvalidStateError, message)); } void throwSecurityError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, const String& message) { scope.assertNoExceptionExceptTermination(); - throwException(&lexicalGlobalObject, scope, createDOMException(&lexicalGlobalObject, SecurityError, message)); + throwException(&lexicalGlobalObject, scope, createDOMException(&lexicalGlobalObject, ExceptionCode::SecurityError, message)); } -JSC::EncodedJSValue throwArgumentMustBeEnumError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedValues) +JSC::EncodedJSValue throwArgumentMustBeEnumError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, unsigned argumentIndex, ASCIILiteral argumentName, ASCIILiteral functionInterfaceName, ASCIILiteral functionName, ASCIILiteral expectedValues) { - return throwVMTypeError(&lexicalGlobalObject, scope, makeArgumentTypeErrorMessage(argumentIndex, argumentName, functionInterfaceName, functionName, "one of: ", expectedValues)); + return throwVMTypeError(&lexicalGlobalObject, scope, makeArgumentTypeErrorMessage(argumentIndex, argumentName, functionInterfaceName, functionName, "one of: "_s, expectedValues)); } -JSC::EncodedJSValue throwArgumentMustBeFunctionError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, unsigned argumentIndex, const char* argumentName, const char* interfaceName, const char* functionName) +JSC::EncodedJSValue throwArgumentMustBeFunctionError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, unsigned argumentIndex, ASCIILiteral argumentName, ASCIILiteral interfaceName, ASCIILiteral functionName) { - return throwVMTypeError(&lexicalGlobalObject, scope, makeArgumentTypeErrorMessage(argumentIndex, argumentName, interfaceName, functionName, "a function")); + return throwVMTypeError(&lexicalGlobalObject, scope, makeArgumentTypeErrorMessage(argumentIndex, argumentName, interfaceName, functionName, "a function"_s)); } -JSC::EncodedJSValue throwArgumentMustBeObjectError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, unsigned argumentIndex, const char* argumentName, const char* interfaceName, const char* functionName) +JSC::EncodedJSValue throwArgumentMustBeObjectError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, unsigned argumentIndex, ASCIILiteral argumentName, ASCIILiteral interfaceName, ASCIILiteral functionName) { - return throwVMTypeError(&lexicalGlobalObject, scope, makeArgumentTypeErrorMessage(argumentIndex, argumentName, interfaceName, functionName, "an object")); + return throwVMTypeError(&lexicalGlobalObject, scope, makeArgumentTypeErrorMessage(argumentIndex, argumentName, interfaceName, functionName, "an object"_s)); } -JSC::EncodedJSValue throwArgumentTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedType) +JSC::EncodedJSValue throwArgumentTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, unsigned argumentIndex, ASCIILiteral argumentName, ASCIILiteral functionInterfaceName, ASCIILiteral functionName, ASCIILiteral expectedType) { - return throwVMTypeError(&lexicalGlobalObject, scope, makeArgumentTypeErrorMessage(argumentIndex, argumentName, functionInterfaceName, functionName, "an instance of ", expectedType)); + return throwVMTypeError(&lexicalGlobalObject, scope, makeArgumentTypeErrorMessage(argumentIndex, argumentName, functionInterfaceName, functionName, "an instance of "_s, expectedType)); } -void throwAttributeTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, const char* interfaceName, const char* attributeName, const char* expectedType) +void throwAttributeTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, ASCIILiteral interfaceName, ASCIILiteral attributeName, ASCIILiteral expectedType) { - throwTypeError(lexicalGlobalObject, scope, makeString("The ", interfaceName, '.', attributeName, " attribute must be an instance of ", expectedType)); + throwTypeError(lexicalGlobalObject, scope, makeString("The "_s, interfaceName, '.', attributeName, " attribute must be an instance of "_s, expectedType)); } -JSC::EncodedJSValue throwRequiredMemberTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, const char* memberName, const char* dictionaryName, const char* expectedType) +JSC::EncodedJSValue throwRequiredMemberTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, ASCIILiteral memberName, ASCIILiteral dictionaryName, ASCIILiteral expectedType) { - return throwVMTypeError(&lexicalGlobalObject, scope, makeString("Member ", dictionaryName, '.', memberName, " is required and must be an instance of ", expectedType)); + return throwVMTypeError(&lexicalGlobalObject, scope, makeString("Member "_s, dictionaryName, '.', memberName, " is required and must be an instance of "_s, expectedType)); } -JSC::EncodedJSValue throwConstructorScriptExecutionContextUnavailableError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, const char* interfaceName) +JSC::EncodedJSValue throwConstructorScriptExecutionContextUnavailableError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, ASCIILiteral interfaceName) { - return throwVMError(&lexicalGlobalObject, scope, createReferenceError(&lexicalGlobalObject, makeString(interfaceName, " constructor associated execution context is unavailable"))); + return throwVMError(&lexicalGlobalObject, scope, createReferenceError(&lexicalGlobalObject, makeString(interfaceName, " constructor associated execution context is unavailable"_s))); } void throwSequenceTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) @@ -283,12 +283,13 @@ JSC::EncodedJSValue rejectPromiseWithGetterTypeError(JSC::JSGlobalObject& lexica String makeThisTypeErrorMessage(const char* interfaceName, const char* functionName) { - return makeString("Can only call ", interfaceName, '.', functionName, " on instances of ", interfaceName); + auto interfaceNameSpan = span(interfaceName); + return makeString("Can only call "_s, interfaceNameSpan, '.', span(functionName), " on instances of "_s, interfaceNameSpan); } -String makeUnsupportedIndexedSetterErrorMessage(const char* interfaceName) +String makeUnsupportedIndexedSetterErrorMessage(ASCIILiteral interfaceName) { - return makeString("Failed to set an indexed property on ", interfaceName, ": Indexed property setter is not supported."); + return makeString("Failed to set an indexed property on "_s, interfaceName, ": Indexed property setter is not supported."_s); } EncodedJSValue throwThisTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, const char* interfaceName, const char* functionName) @@ -298,7 +299,7 @@ EncodedJSValue throwThisTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC: JSC::EncodedJSValue rejectPromiseWithThisTypeError(DeferredPromise& promise, const char* interfaceName, const char* methodName) { - promise.reject(TypeError, makeThisTypeErrorMessage(interfaceName, methodName)); + promise.reject(ExceptionCode::TypeError, makeThisTypeErrorMessage(interfaceName, methodName)); return JSValue::encode(jsUndefined()); } @@ -310,13 +311,13 @@ JSC::EncodedJSValue rejectPromiseWithThisTypeError(JSC::JSGlobalObject& lexicalG void throwDOMSyntaxError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, ASCIILiteral message) { scope.assertNoExceptionExceptTermination(); - throwException(&lexicalGlobalObject, scope, createDOMException(&lexicalGlobalObject, SyntaxError, message)); + throwException(&lexicalGlobalObject, scope, createDOMException(&lexicalGlobalObject, ExceptionCode::SyntaxError, message)); } void throwDataCloneError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { scope.assertNoExceptionExceptTermination(); - throwException(&lexicalGlobalObject, scope, createDOMException(&lexicalGlobalObject, DataCloneError)); + throwException(&lexicalGlobalObject, scope, createDOMException(&lexicalGlobalObject, ExceptionCode::DataCloneError)); } } // namespace WebCore diff --git a/src/bun.js/bindings/JSDOMExceptionHandling.h b/src/bun.js/bindings/JSDOMExceptionHandling.h index 97153d5aa9..d4a3c7cd2c 100644 --- a/src/bun.js/bindings/JSDOMExceptionHandling.h +++ b/src/bun.js/bindings/JSDOMExceptionHandling.h @@ -23,8 +23,6 @@ #pragma once -#include "root.h" - #include "ExceptionDetails.h" #include "ExceptionOr.h" #include @@ -38,7 +36,7 @@ namespace WebCore { class CachedScript; class DeferredPromise; -void throwAttributeTypeError(JSC::JSGlobalObject&, JSC::ThrowScope&, const char* interfaceName, const char* attributeName, const char* expectedType); +void throwAttributeTypeError(JSC::JSGlobalObject&, JSC::ThrowScope&, ASCIILiteral interfaceName, ASCIILiteral attributeName, ASCIILiteral expectedType); void throwDataCloneError(JSC::JSGlobalObject&, JSC::ThrowScope&); void throwDOMSyntaxError(JSC::JSGlobalObject&, JSC::ThrowScope&, ASCIILiteral); // Not the same as a JavaScript syntax error. @@ -48,15 +46,15 @@ void throwNotSupportedError(JSC::JSGlobalObject&, JSC::ThrowScope&, ASCIILiteral void throwSecurityError(JSC::JSGlobalObject&, JSC::ThrowScope&, const String& message); WEBCORE_EXPORT void throwSequenceTypeError(JSC::JSGlobalObject&, JSC::ThrowScope&); -WEBCORE_EXPORT JSC::EncodedJSValue throwArgumentMustBeEnumError(JSC::JSGlobalObject&, JSC::ThrowScope&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedValues); -WEBCORE_EXPORT JSC::EncodedJSValue throwArgumentMustBeFunctionError(JSC::JSGlobalObject&, JSC::ThrowScope&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName); -WEBCORE_EXPORT JSC::EncodedJSValue throwArgumentMustBeObjectError(JSC::JSGlobalObject&, JSC::ThrowScope&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName); -WEBCORE_EXPORT JSC::EncodedJSValue throwArgumentTypeError(JSC::JSGlobalObject&, JSC::ThrowScope&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedType); -WEBCORE_EXPORT JSC::EncodedJSValue throwRequiredMemberTypeError(JSC::JSGlobalObject&, JSC::ThrowScope&, const char* memberName, const char* dictionaryName, const char* expectedType); -JSC::EncodedJSValue throwConstructorScriptExecutionContextUnavailableError(JSC::JSGlobalObject&, JSC::ThrowScope&, const char* interfaceName); +WEBCORE_EXPORT JSC::EncodedJSValue throwArgumentMustBeEnumError(JSC::JSGlobalObject&, JSC::ThrowScope&, unsigned argumentIndex, ASCIILiteral argumentName, ASCIILiteral functionInterfaceName, ASCIILiteral functionName, ASCIILiteral expectedValues); +WEBCORE_EXPORT JSC::EncodedJSValue throwArgumentMustBeFunctionError(JSC::JSGlobalObject&, JSC::ThrowScope&, unsigned argumentIndex, ASCIILiteral argumentName, ASCIILiteral functionInterfaceName, ASCIILiteral functionName); +WEBCORE_EXPORT JSC::EncodedJSValue throwArgumentMustBeObjectError(JSC::JSGlobalObject&, JSC::ThrowScope&, unsigned argumentIndex, ASCIILiteral argumentName, ASCIILiteral functionInterfaceName, ASCIILiteral functionName); +WEBCORE_EXPORT JSC::EncodedJSValue throwArgumentTypeError(JSC::JSGlobalObject&, JSC::ThrowScope&, unsigned argumentIndex, ASCIILiteral argumentName, ASCIILiteral functionInterfaceName, ASCIILiteral functionName, ASCIILiteral expectedType); +WEBCORE_EXPORT JSC::EncodedJSValue throwRequiredMemberTypeError(JSC::JSGlobalObject&, JSC::ThrowScope&, ASCIILiteral memberName, ASCIILiteral dictionaryName, ASCIILiteral expectedType); +JSC::EncodedJSValue throwConstructorScriptExecutionContextUnavailableError(JSC::JSGlobalObject&, JSC::ThrowScope&, ASCIILiteral interfaceName); String makeThisTypeErrorMessage(const char* interfaceName, const char* attributeName); -String makeUnsupportedIndexedSetterErrorMessage(const char* interfaceName); +String makeUnsupportedIndexedSetterErrorMessage(ASCIILiteral interfaceName); WEBCORE_EXPORT JSC::EncodedJSValue throwThisTypeError(JSC::JSGlobalObject&, JSC::ThrowScope&, const char* interfaceName, const char* functionName); @@ -68,6 +66,7 @@ String retrieveErrorMessageWithoutName(JSC::JSGlobalObject&, JSC::VM&, JSC::JSVa String retrieveErrorMessage(JSC::JSGlobalObject&, JSC::VM&, JSC::JSValue exception, JSC::CatchScope&); WEBCORE_EXPORT void reportException(JSC::JSGlobalObject*, JSC::JSValue exception, CachedScript* = nullptr, bool = false); WEBCORE_EXPORT void reportException(JSC::JSGlobalObject*, JSC::Exception*, CachedScript* = nullptr, bool = false, ExceptionDetails* = nullptr); +WEBCORE_EXPORT void reportExceptionIfJSDOMWindow(JSC::JSGlobalObject*, JSC::JSValue exception); void reportCurrentException(JSC::JSGlobalObject*); JSC::JSValue createDOMException(JSC::JSGlobalObject&, Exception&&); diff --git a/src/bun.js/bindings/JSDOMFile.cpp b/src/bun.js/bindings/JSDOMFile.cpp index 37536729d5..212cbeb0c0 100644 --- a/src/bun.js/bindings/JSDOMFile.cpp +++ b/src/bun.js/bindings/JSDOMFile.cpp @@ -7,8 +7,8 @@ using namespace JSC; -extern "C" void* JSDOMFile__construct(JSC::JSGlobalObject*, JSC::CallFrame* callframe); -extern "C" bool JSDOMFile__hasInstance(EncodedJSValue, JSC::JSGlobalObject*, EncodedJSValue); +extern "C" SYSV_ABI void* JSDOMFile__construct(JSC::JSGlobalObject*, JSC::CallFrame* callframe); +extern "C" SYSV_ABI bool JSDOMFile__hasInstance(EncodedJSValue, JSC::JSGlobalObject*, EncodedJSValue); // TODO: make this inehrit from JSBlob instead of InternalFunction // That will let us remove this hack for [Symbol.hasInstance] and fix the prototype chain. @@ -63,7 +63,7 @@ public: return JSDOMFile__hasInstance(JSValue::encode(object), globalObject, JSValue::encode(value)); } - static JSC::EncodedJSValue construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) + static JSC_HOST_CALL_ATTRIBUTES JSC::EncodedJSValue construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { Zig::GlobalObject* globalObject = reinterpret_cast(lexicalGlobalObject); JSC::VM& vm = globalObject->vm(); @@ -93,7 +93,7 @@ public: WebCore::JSBlob::create(vm, globalObject, structure, ptr)); } - static EncodedJSValue call(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) + static JSC_HOST_CALL_ATTRIBUTES EncodedJSValue call(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { auto scope = DECLARE_THROW_SCOPE(lexicalGlobalObject->vm()); throwTypeError(lexicalGlobalObject, scope, "Class constructor File cannot be invoked without 'new'"_s); diff --git a/src/bun.js/bindings/JSFFIFunction.cpp b/src/bun.js/bindings/JSFFIFunction.cpp index ac4120c2d5..6f5d9dcf4c 100644 --- a/src/bun.js/bindings/JSFFIFunction.cpp +++ b/src/bun.js/bindings/JSFFIFunction.cpp @@ -115,15 +115,18 @@ extern "C" void Bun__untrackFFIFunction(Zig::GlobalObject* globalObject, JSC::En } extern "C" JSC::EncodedJSValue Bun__CreateFFIFunctionValue(Zig::GlobalObject* globalObject, const ZigString* symbolName, unsigned argCount, Zig::FFIFunction functionPointer, bool strong, bool addPtrField) { - auto* function = Bun__CreateFFIFunction(globalObject, symbolName, argCount, functionPointer, strong); if (addPtrField) { + auto* function = Zig::JSFFIFunction::createForFFI(globalObject->vm(), globalObject, argCount, symbolName != nullptr ? Zig::toStringCopy(*symbolName) : String(), reinterpret_cast(functionPointer)); auto& vm = globalObject->vm(); // We should only expose the "ptr" field when it's a JSCallback for bun:ffi. // Not for internal usages of this function type. // We should also consider a separate JSFunction type for our usage to not have this branch in the first place... function->putDirect(vm, JSC::Identifier::fromString(vm, String(MAKE_STATIC_STRING_IMPL("ptr"))), JSC::jsNumber(bitwise_cast(functionPointer)), JSC::PropertyAttribute::ReadOnly | 0); + + return JSC::JSValue::encode(function); } - return JSC::JSValue::encode(function); + + return Bun__CreateFFIFunctionWithDataValue(globalObject, symbolName, argCount, functionPointer, strong, nullptr); } namespace Zig { @@ -131,7 +134,7 @@ using namespace JSC; const ClassInfo JSFFIFunction::s_info = { "Function"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSFFIFunction) }; -JSFFIFunction::JSFFIFunction(VM& vm, NativeExecutable* executable, JSGlobalObject* globalObject, Structure* structure, FFIFunction&& function) +JSFFIFunction::JSFFIFunction(VM& vm, NativeExecutable* executable, JSGlobalObject* globalObject, Structure* structure, CFFIFunction&& function) : Base(vm, executable, globalObject, structure) , m_function(WTFMove(function)) { @@ -157,11 +160,32 @@ void JSFFIFunction::finishCreation(VM& vm, NativeExecutable* executable, unsigne JSFFIFunction* JSFFIFunction::create(VM& vm, Zig::GlobalObject* globalObject, unsigned length, const String& name, FFIFunction FFIFunction, Intrinsic intrinsic, NativeFunction nativeConstructor) { - NativeExecutable* executable = vm.getHostFunction(FFIFunction, ImplementationVisibility::Public, intrinsic, FFIFunction, nullptr, name); - Structure* structure = globalObject->FFIFunctionStructure(); - JSFFIFunction* function = new (NotNull, allocateCell(vm)) JSFFIFunction(vm, executable, globalObject, structure, WTFMove(FFIFunction)); + JSFFIFunction* function = new (NotNull, allocateCell(vm)) JSFFIFunction(vm, executable, globalObject, structure, reinterpret_cast(WTFMove(FFIFunction))); + function->finishCreation(vm, executable, length, name); + return function; +} + +#if OS(WINDOWS) + +JSC_DEFINE_HOST_FUNCTION(JSFFIFunction::trampoline, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + const auto* function = jsCast(callFrame->jsCallee()); + return function->function()(globalObject, callFrame); +} + +#endif + +JSFFIFunction* JSFFIFunction::createForFFI(VM& vm, Zig::GlobalObject* globalObject, unsigned length, const String& name, CFFIFunction FFIFunction) +{ +#if OS(WINDOWS) + NativeExecutable* executable = vm.getHostFunction(trampoline, ImplementationVisibility::Public, NoIntrinsic, trampoline, nullptr, name); +#else + NativeExecutable* executable = vm.getHostFunction(FFIFunction, ImplementationVisibility::Public, NoIntrinsic, FFIFunction, nullptr, name); +#endif + Structure* structure = globalObject->FFIFunctionStructure(); + JSFFIFunction* function = new (NotNull, allocateCell(vm)) JSFFIFunction(vm, executable, globalObject, structure, reinterpret_cast(WTFMove(FFIFunction))); function->finishCreation(vm, executable, length, name); return function; } diff --git a/src/bun.js/bindings/JSFFIFunction.h b/src/bun.js/bindings/JSFFIFunction.h index e186c73036..078cb8073b 100644 --- a/src/bun.js/bindings/JSFFIFunction.h +++ b/src/bun.js/bindings/JSFFIFunction.h @@ -20,7 +20,13 @@ namespace Zig { using namespace JSC; -using FFIFunction = JSC::EncodedJSValue (*)(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); +using FFIFunction = SYSV_ABI JSC::EncodedJSValue (*)(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); + +#if OS(WINDOWS) +using CFFIFunction = JSC::EncodedJSValue __attribute__((cdecl)) (*)(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); +#else +using CFFIFunction = FFIFunction; +#endif /** * Call a C function with low overhead, modeled after JSC::JSNativeStdFunction @@ -64,6 +70,7 @@ public: DECLARE_EXPORT_INFO; JS_EXPORT_PRIVATE static JSFFIFunction* create(VM&, Zig::GlobalObject*, unsigned length, const String& name, FFIFunction, Intrinsic = NoIntrinsic, NativeFunction nativeConstructor = callHostFunctionAsConstructor); + JS_EXPORT_PRIVATE static JSFFIFunction* createForFFI(VM&, Zig::GlobalObject*, unsigned length, const String& name, CFFIFunction); static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { @@ -71,16 +78,22 @@ public: return Structure::create(vm, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), info()); } - const FFIFunction function() { return m_function; } + const CFFIFunction function() const { return m_function; } + +#if OS(WINDOWS) + + static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES trampoline(JSGlobalObject* globalObject, CallFrame* callFrame); + +#endif void* dataPtr; private: - JSFFIFunction(VM&, NativeExecutable*, JSGlobalObject*, Structure*, FFIFunction&&); + JSFFIFunction(VM&, NativeExecutable*, JSGlobalObject*, Structure*, CFFIFunction&&); void finishCreation(VM&, NativeExecutable*, unsigned length, const String& name); DECLARE_VISIT_CHILDREN; - FFIFunction m_function; + CFFIFunction m_function; }; } // namespace JSC diff --git a/src/bun.js/bindings/JSMockFunction.cpp b/src/bun.js/bindings/JSMockFunction.cpp index ec2229765d..7c5c46a83d 100644 --- a/src/bun.js/bindings/JSMockFunction.cpp +++ b/src/bun.js/bindings/JSMockFunction.cpp @@ -23,6 +23,16 @@ #include #include #include "BunPlugin.h" + +BUN_DECLARE_HOST_FUNCTION(JSMock__jsUseFakeTimers); +BUN_DECLARE_HOST_FUNCTION(JSMock__jsUseRealTimers); +BUN_DECLARE_HOST_FUNCTION(JSMock__jsNow); +BUN_DECLARE_HOST_FUNCTION(JSMock__jsSetSystemTime); +BUN_DECLARE_HOST_FUNCTION(JSMock__jsRestoreAllMocks); +BUN_DECLARE_HOST_FUNCTION(JSMock__jsClearAllMocks); +BUN_DECLARE_HOST_FUNCTION(JSMock__jsSpyOn); +BUN_DECLARE_HOST_FUNCTION(JSMock__jsMockFn); + namespace Bun { /** @@ -68,41 +78,6 @@ JSC_DECLARE_HOST_FUNCTION(jsMockFunctionMockRejectedValueOnce); JSC_DECLARE_HOST_FUNCTION(jsMockFunctionWithImplementationCleanup); JSC_DECLARE_HOST_FUNCTION(jsMockFunctionWithImplementation); -// This is a stub. Exists so that the same code can be run in Jest -extern "C" JSC::EncodedJSValue JSMock__jsUseFakeTimers(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) -{ - return JSValue::encode(callFrame->thisValue()); -} - -extern "C" JSC::EncodedJSValue JSMock__jsUseRealTimers(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) -{ - globalObject->overridenDateNow = -1; - return JSValue::encode(callFrame->thisValue()); -} - -extern "C" JSC::EncodedJSValue JSMock__jsNow(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) -{ - return JSValue::encode(jsNumber(globalObject->jsDateNow())); -} -extern "C" JSC::EncodedJSValue JSMock__jsSetSystemTime(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) -{ - JSValue argument0 = callFrame->argument(0); - - if (auto* dateInstance = jsDynamicCast(argument0)) { - if (std::isnormal(dateInstance->internalNumber())) { - globalObject->overridenDateNow = dateInstance->internalNumber(); - } - return JSValue::encode(callFrame->thisValue()); - } - - if (argument0.isNumber() && argument0.asNumber() > 0) { - globalObject->overridenDateNow = argument0.asNumber(); - } - - globalObject->overridenDateNow = -1; - return JSValue::encode(callFrame->thisValue()); -} - uint64_t JSMockModule::s_nextInvocationId = 0; // This is taken from JSWeakSet @@ -582,12 +557,6 @@ extern "C" void JSMock__resetSpies(Zig::GlobalObject* globalObject) globalObject->mockModule.activeSpies.clear(); } -extern "C" JSC::EncodedJSValue JSMock__jsRestoreAllMocks(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe) -{ - JSMock__resetSpies(jsCast(globalObject)); - return JSValue::encode(jsUndefined()); -} - extern "C" void JSMock__clearAllMocks(Zig::GlobalObject* globalObject) { if (!globalObject->mockModule.activeMocks) { @@ -612,131 +581,6 @@ extern "C" void JSMock__clearAllMocks(Zig::GlobalObject* globalObject) } } -extern "C" JSC::EncodedJSValue JSMock__jsClearAllMocks(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe) -{ - JSMock__clearAllMocks(jsCast(globalObject)); - return JSValue::encode(jsUndefined()); -} - -extern "C" JSC::EncodedJSValue JSMock__jsSpyOn(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callframe) -{ - auto& vm = lexicalGlobalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - - auto* globalObject = jsDynamicCast(lexicalGlobalObject); - if (UNLIKELY(!globalObject)) { - throwVMError(globalObject, scope, "Cannot run spyOn from a different global context"_s); - return {}; - } - - JSValue objectValue = callframe->argument(0); - JSValue propertyKeyValue = callframe->argument(1); - - if (callframe->argumentCount() < 2 || !objectValue.isObject()) { - throwVMError(globalObject, scope, "spyOn(target, prop) expects a target object and a property key"_s); - return {}; - } - - PropertyName propertyKey = propertyKeyValue.toPropertyKey(globalObject); - RETURN_IF_EXCEPTION(scope, {}); - - if (propertyKey.isNull()) { - throwVMError(globalObject, scope, "spyOn(target, prop) expects a property key"_s); - return {}; - } - - JSC::JSObject* object = objectValue.getObject(); - if (object->type() == JSC::JSType::GlobalProxyType) - object = jsCast(object)->target(); - - JSC::PropertySlot slot(object, JSC::PropertySlot::InternalMethodType::HasProperty); - bool hasValue = object->getPropertySlot(globalObject, propertyKey, slot); - - // easymode: regular property or missing property - if (!hasValue || slot.isValue()) { - JSValue value = jsUndefined(); - if (hasValue) { - if (UNLIKELY(slot.isTaintedByOpaqueObject())) { - // if it's a Proxy or JSModuleNamespaceObject - value = object->get(globalObject, propertyKey); - } else { - value = slot.getValue(globalObject, propertyKey); - } - - if (jsDynamicCast(value)) { - return JSValue::encode(value); - } - } - - auto* mock = JSMockFunction::create(vm, globalObject, globalObject->mockModule.mockFunctionStructure.getInitializedOnMainThread(globalObject), CallbackKind::GetterSetter); - mock->spyTarget = JSC::Weak(object, &weakValueHandleOwner(), nullptr); - mock->spyIdentifier = propertyKey.isSymbol() ? Identifier::fromUid(vm, propertyKey.uid()) : Identifier::fromString(vm, propertyKey.publicName()); - mock->spyAttributes = hasValue ? slot.attributes() : 0; - unsigned attributes = 0; - - if (hasValue && ((slot.attributes() & PropertyAttribute::Function) != 0 || (value.isCell() && value.isCallable()))) { - if (hasValue) - attributes = slot.attributes(); - - mock->copyNameAndLength(vm, globalObject, value); - - if (JSModuleNamespaceObject* moduleNamespaceObject = jsDynamicCast(object)) { - moduleNamespaceObject->overrideExportValue(globalObject, propertyKey, mock); - mock->spyAttributes |= JSMockFunction::SpyAttributeESModuleNamespace; - } else { - object->putDirect(vm, propertyKey, mock, attributes); - } - - RETURN_IF_EXCEPTION(scope, {}); - - pushImpl(mock, globalObject, JSMockImplementation::Kind::Call, value); - } else { - if (hasValue) - attributes = slot.attributes(); - - attributes |= PropertyAttribute::Accessor; - - if (JSModuleNamespaceObject* moduleNamespaceObject = jsDynamicCast(object)) { - moduleNamespaceObject->overrideExportValue(globalObject, propertyKey, mock); - mock->spyAttributes |= JSMockFunction::SpyAttributeESModuleNamespace; - } else { - object->putDirectAccessor(globalObject, propertyKey, JSC::GetterSetter::create(vm, globalObject, mock, mock), attributes); - } - - // mock->setName(propertyKey.publicName()); - RETURN_IF_EXCEPTION(scope, {}); - - pushImpl(mock, globalObject, JSMockImplementation::Kind::ReturnValue, value); - } - - mock->spyOriginal.set(vm, mock, value); - - { - if (!globalObject->mockModule.activeSpies) { - ActiveSpySet* activeSpies = ActiveSpySet::create(vm, globalObject->mockModule.activeSpySetStructure.getInitializedOnMainThread(globalObject)); - globalObject->mockModule.activeSpies.set(vm, activeSpies); - } - ActiveSpySet* activeSpies = jsCast(globalObject->mockModule.activeSpies.get()); - activeSpies->add(vm, mock, mock); - } - - { - if (!globalObject->mockModule.activeMocks) { - ActiveSpySet* activeMocks = ActiveSpySet::create(vm, globalObject->mockModule.activeSpySetStructure.getInitializedOnMainThread(globalObject)); - globalObject->mockModule.activeMocks.set(vm, activeMocks); - } - ActiveSpySet* activeMocks = jsCast(globalObject->mockModule.activeMocks.get()); - activeMocks->add(vm, mock, mock); - } - - return JSValue::encode(mock); - } - - // hardmode: accessor property - throwVMError(globalObject, scope, "spyOn(target, prop) does not support accessor properties yet"_s); - return {}; -} - JSMockModule JSMockModule::create(JSC::JSGlobalObject* globalObject) { JSMockModule mock; @@ -1090,47 +934,6 @@ JSC_DEFINE_CUSTOM_GETTER(jsMockFunctionGetter_protoImpl, (JSC::JSGlobalObject * return JSValue::encode(jsUndefined()); } -extern "C" JSC::EncodedJSValue JSMock__jsMockFn(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callframe) -{ - auto& vm = lexicalGlobalObject->vm(); - auto* globalObject = jsCast(lexicalGlobalObject); - auto scope = DECLARE_THROW_SCOPE(vm); - - JSMockFunction* thisObject = JSMockFunction::create( - vm, - globalObject, - globalObject->mockModule.mockFunctionStructure.getInitializedOnMainThread(globalObject)); - - if (UNLIKELY(!thisObject)) { - throwOutOfMemoryError(globalObject, scope); - return {}; - } - - if (callframe->argumentCount() > 0) { - JSValue value = callframe->argument(0); - if (value.isCallable()) { - thisObject->copyNameAndLength(vm, lexicalGlobalObject, value); - pushImpl(thisObject, globalObject, JSMockImplementation::Kind::Call, value); - } else { - // jest doesn't support doing `jest.fn(10)`, but we support it. - pushImpl(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, value); - thisObject->setName("mockConstructor"_s); - } - } else { - thisObject->setName("mockConstructor"_s); - } - - if (!globalObject->mockModule.activeMocks) { - ActiveSpySet* activeMocks = ActiveSpySet::create(vm, globalObject->mockModule.activeSpySetStructure.getInitializedOnMainThread(globalObject)); - globalObject->mockModule.activeMocks.set(vm, activeMocks); - } - - ActiveSpySet* activeMocks = jsCast(globalObject->mockModule.activeMocks.get()); - activeMocks->add(vm, thisObject, thisObject); - - return JSValue::encode(thisObject); -} - extern "C" JSC::EncodedJSValue JSMockFunction__getCalls(EncodedJSValue encodedValue) { JSValue value = JSValue::decode(encodedValue); @@ -1529,3 +1332,213 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionWithImplementation, (JSC::JSGlobalObject return JSC::JSValue::encode(jsUndefined()); } } // namespace Bun + +using namespace Bun; +using namespace JSC; + +// This is a stub. Exists so that the same code can be run in Jest +BUN_DEFINE_HOST_FUNCTION(JSMock__jsUseFakeTimers, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + return JSValue::encode(callFrame->thisValue()); +} + +BUN_DEFINE_HOST_FUNCTION(JSMock__jsUseRealTimers, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + globalObject->overridenDateNow = -1; + return JSValue::encode(callFrame->thisValue()); +} + +BUN_DEFINE_HOST_FUNCTION(JSMock__jsNow, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + return JSValue::encode(jsNumber(globalObject->jsDateNow())); +} +BUN_DEFINE_HOST_FUNCTION(JSMock__jsSetSystemTime, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + JSValue argument0 = callFrame->argument(0); + + if (auto* dateInstance = jsDynamicCast(argument0)) { + if (std::isnormal(dateInstance->internalNumber())) { + globalObject->overridenDateNow = dateInstance->internalNumber(); + } + return JSValue::encode(callFrame->thisValue()); + } + + if (argument0.isNumber() && argument0.asNumber() > 0) { + globalObject->overridenDateNow = argument0.asNumber(); + } + + globalObject->overridenDateNow = -1; + return JSValue::encode(callFrame->thisValue()); +} + +BUN_DEFINE_HOST_FUNCTION(JSMock__jsRestoreAllMocks, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + JSMock__resetSpies(jsCast(globalObject)); + return JSValue::encode(jsUndefined()); +} + +BUN_DEFINE_HOST_FUNCTION(JSMock__jsClearAllMocks, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + JSMock__clearAllMocks(jsCast(globalObject)); + return JSValue::encode(jsUndefined()); +} + +BUN_DEFINE_HOST_FUNCTION(JSMock__jsSpyOn, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callframe)) +{ + auto& vm = lexicalGlobalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto* globalObject = jsDynamicCast(lexicalGlobalObject); + if (UNLIKELY(!globalObject)) { + throwVMError(globalObject, scope, "Cannot run spyOn from a different global context"_s); + return {}; + } + + JSValue objectValue = callframe->argument(0); + JSValue propertyKeyValue = callframe->argument(1); + + if (callframe->argumentCount() < 2 || !objectValue.isObject()) { + throwVMError(globalObject, scope, "spyOn(target, prop) expects a target object and a property key"_s); + return {}; + } + + PropertyName propertyKey = propertyKeyValue.toPropertyKey(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + + if (propertyKey.isNull()) { + throwVMError(globalObject, scope, "spyOn(target, prop) expects a property key"_s); + return {}; + } + + JSC::JSObject* object = objectValue.getObject(); + if (object->type() == JSC::JSType::GlobalProxyType) + object = jsCast(object)->target(); + + JSC::PropertySlot slot(object, JSC::PropertySlot::InternalMethodType::HasProperty); + bool hasValue = object->getPropertySlot(globalObject, propertyKey, slot); + + // easymode: regular property or missing property + if (!hasValue || slot.isValue()) { + JSValue value = jsUndefined(); + if (hasValue) { + if (UNLIKELY(slot.isTaintedByOpaqueObject())) { + // if it's a Proxy or JSModuleNamespaceObject + value = object->get(globalObject, propertyKey); + } else { + value = slot.getValue(globalObject, propertyKey); + } + + if (jsDynamicCast(value)) { + return JSValue::encode(value); + } + } + + auto* mock = JSMockFunction::create(vm, globalObject, globalObject->mockModule.mockFunctionStructure.getInitializedOnMainThread(globalObject), CallbackKind::GetterSetter); + mock->spyTarget = JSC::Weak(object, &weakValueHandleOwner(), nullptr); + mock->spyIdentifier = propertyKey.isSymbol() ? Identifier::fromUid(vm, propertyKey.uid()) : Identifier::fromString(vm, propertyKey.publicName()); + mock->spyAttributes = hasValue ? slot.attributes() : 0; + unsigned attributes = 0; + + if (hasValue && ((slot.attributes() & PropertyAttribute::Function) != 0 || (value.isCell() && value.isCallable()))) { + if (hasValue) + attributes = slot.attributes(); + + mock->copyNameAndLength(vm, globalObject, value); + + if (JSModuleNamespaceObject* moduleNamespaceObject = jsDynamicCast(object)) { + moduleNamespaceObject->overrideExportValue(globalObject, propertyKey, mock); + mock->spyAttributes |= JSMockFunction::SpyAttributeESModuleNamespace; + } else { + object->putDirect(vm, propertyKey, mock, attributes); + } + + RETURN_IF_EXCEPTION(scope, {}); + + pushImpl(mock, globalObject, JSMockImplementation::Kind::Call, value); + } else { + if (hasValue) + attributes = slot.attributes(); + + attributes |= PropertyAttribute::Accessor; + + if (JSModuleNamespaceObject* moduleNamespaceObject = jsDynamicCast(object)) { + moduleNamespaceObject->overrideExportValue(globalObject, propertyKey, mock); + mock->spyAttributes |= JSMockFunction::SpyAttributeESModuleNamespace; + } else { + object->putDirectAccessor(globalObject, propertyKey, JSC::GetterSetter::create(vm, globalObject, mock, mock), attributes); + } + + // mock->setName(propertyKey.publicName()); + RETURN_IF_EXCEPTION(scope, {}); + + pushImpl(mock, globalObject, JSMockImplementation::Kind::ReturnValue, value); + } + + mock->spyOriginal.set(vm, mock, value); + + { + if (!globalObject->mockModule.activeSpies) { + ActiveSpySet* activeSpies = ActiveSpySet::create(vm, globalObject->mockModule.activeSpySetStructure.getInitializedOnMainThread(globalObject)); + globalObject->mockModule.activeSpies.set(vm, activeSpies); + } + ActiveSpySet* activeSpies = jsCast(globalObject->mockModule.activeSpies.get()); + activeSpies->add(vm, mock, mock); + } + + { + if (!globalObject->mockModule.activeMocks) { + ActiveSpySet* activeMocks = ActiveSpySet::create(vm, globalObject->mockModule.activeSpySetStructure.getInitializedOnMainThread(globalObject)); + globalObject->mockModule.activeMocks.set(vm, activeMocks); + } + ActiveSpySet* activeMocks = jsCast(globalObject->mockModule.activeMocks.get()); + activeMocks->add(vm, mock, mock); + } + + return JSValue::encode(mock); + } + + // hardmode: accessor property + throwVMError(globalObject, scope, "spyOn(target, prop) does not support accessor properties yet"_s); + return {}; +} + +BUN_DEFINE_HOST_FUNCTION(JSMock__jsMockFn, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callframe)) +{ + auto& vm = lexicalGlobalObject->vm(); + auto* globalObject = jsCast(lexicalGlobalObject); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSMockFunction* thisObject = JSMockFunction::create( + vm, + globalObject, + globalObject->mockModule.mockFunctionStructure.getInitializedOnMainThread(globalObject)); + + if (UNLIKELY(!thisObject)) { + throwOutOfMemoryError(globalObject, scope); + return {}; + } + + if (callframe->argumentCount() > 0) { + JSValue value = callframe->argument(0); + if (value.isCallable()) { + thisObject->copyNameAndLength(vm, lexicalGlobalObject, value); + pushImpl(thisObject, globalObject, JSMockImplementation::Kind::Call, value); + } else { + // jest doesn't support doing `jest.fn(10)`, but we support it. + pushImpl(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, value); + thisObject->setName("mockConstructor"_s); + } + } else { + thisObject->setName("mockConstructor"_s); + } + + if (!globalObject->mockModule.activeMocks) { + ActiveSpySet* activeMocks = ActiveSpySet::create(vm, globalObject->mockModule.activeSpySetStructure.getInitializedOnMainThread(globalObject)); + globalObject->mockModule.activeMocks.set(vm, activeMocks); + } + + ActiveSpySet* activeMocks = jsCast(globalObject->mockModule.activeMocks.get()); + activeMocks->add(vm, thisObject, thisObject); + + return JSValue::encode(thisObject); +} \ No newline at end of file diff --git a/src/bun.js/bindings/JSStringDecoder.cpp b/src/bun.js/bindings/JSStringDecoder.cpp index 70feb31b72..27969cb895 100644 --- a/src/bun.js/bindings/JSStringDecoder.cpp +++ b/src/bun.js/bindings/JSStringDecoder.cpp @@ -458,7 +458,7 @@ static JSC_DEFINE_CUSTOM_GETTER(jsStringDecoder_lastChar, (JSGlobalObject * lexi } JSStringDecoder* thisObject = jsCast(stringDecoderValue); auto throwScope = DECLARE_THROW_SCOPE(vm); - auto buffer = ArrayBuffer::createFromBytes(thisObject->m_lastChar, 4, nullptr); + auto buffer = ArrayBuffer::create({ thisObject->m_lastChar, 4 }); auto* globalObject = reinterpret_cast(lexicalGlobalObject); JSC::JSUint8Array* uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, globalObject->JSBufferSubclassStructure(), WTFMove(buffer), 0, 4); RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(uint8Array)); diff --git a/src/bun.js/bindings/JSWrappingFunction.h b/src/bun.js/bindings/JSWrappingFunction.h index 39b00f2faf..ed3a925583 100644 --- a/src/bun.js/bindings/JSWrappingFunction.h +++ b/src/bun.js/bindings/JSWrappingFunction.h @@ -18,7 +18,7 @@ class JSGlobalObject; namespace Zig { -using NativeFunctionPtr = JSC::EncodedJSValue (*)(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); +using NativeFunctionPtr = SYSV_ABI JSC::EncodedJSValue (*)(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); /** * Subclass of JSC::JSFunction that holds an additional single native JSFunction as property. diff --git a/src/bun.js/bindings/KeyObject.cpp b/src/bun.js/bindings/KeyObject.cpp index b96b2de7dd..6c4b9dcaa6 100644 --- a/src/bun.js/bindings/KeyObject.cpp +++ b/src/bun.js/bindings/KeyObject.cpp @@ -69,6 +69,19 @@ using SourceOrigin = JSC::SourceOrigin; using JSObject = JSC::JSObject; using JSNonFinalObject = JSC::JSNonFinalObject; +JSC_DECLARE_HOST_FUNCTION(KeyObject__AsymmetricKeyType); +JSC_DECLARE_HOST_FUNCTION(KeyObject_AsymmetricKeyDetails); +JSC_DECLARE_HOST_FUNCTION(KeyObject__SymmetricKeySize); +JSC_DECLARE_HOST_FUNCTION(KeyObject__Equals); +JSC_DECLARE_HOST_FUNCTION(KeyObject__Exports); +JSC_DECLARE_HOST_FUNCTION(KeyObject__createSecretKey); +JSC_DECLARE_HOST_FUNCTION(KeyObject__createPublicKey); +JSC_DECLARE_HOST_FUNCTION(KeyObject__createPrivateKey); +JSC_DECLARE_HOST_FUNCTION(KeyObject__generateKeySync); +JSC_DECLARE_HOST_FUNCTION(KeyObject__generateKeyPairSync); +JSC_DECLARE_HOST_FUNCTION(KeyObject__Sign); +JSC_DECLARE_HOST_FUNCTION(KeyObject__Verify); + namespace WebCore { static bool KeyObject__IsASN1Sequence(const unsigned char* data, size_t size, @@ -304,7 +317,7 @@ AsymmetricKeyValueWithDER KeyObject__ParsePublicKeyPEM(const char* key_pem, return result; } -JSC::EncodedJSValue KeyObject__createPrivateKey(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +JSC_DEFINE_HOST_FUNCTION(KeyObject__createPrivateKey, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { auto count = callFrame->argumentCount(); @@ -766,14 +779,14 @@ static JSC::EncodedJSValue KeyObject__createOKPFromPrivate(JSC::JSGlobalObject* auto& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); - uint8_t public_key[ED25519_PUBLIC_KEY_LEN]; + Vector public_key(ED25519_PUBLIC_KEY_LEN); if (namedCurve == CryptoKeyOKP::NamedCurve::Ed25519) { - memcpy(public_key, keyData.data() + ED25519_PRIVATE_KEY_LEN, ED25519_PUBLIC_KEY_LEN); + memcpy(public_key.data(), keyData.data() + ED25519_PRIVATE_KEY_LEN, ED25519_PUBLIC_KEY_LEN); } else { - X25519_public_from_private(public_key, keyData.data()); + X25519_public_from_private(public_key.data(), keyData.data()); } - auto result = CryptoKeyOKP::create(alg, namedCurve, CryptoKeyType::Public, Vector(public_key), true, CryptoKeyUsageVerify); + auto result = CryptoKeyOKP::create(alg, namedCurve, CryptoKeyType::Public, WTFMove(public_key), true, CryptoKeyUsageVerify); if (UNLIKELY(result == nullptr)) { JSC::throwTypeError(globalObject, scope, "ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE: Failed to create a public key from private"_s); return JSValue::encode(JSC::jsUndefined()); @@ -841,7 +854,7 @@ static JSC::EncodedJSValue KeyObject__createPublicFromPrivate(JSC::JSGlobalObjec } } -JSC::EncodedJSValue KeyObject__createPublicKey(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +JSC_DEFINE_HOST_FUNCTION(KeyObject__createPublicKey, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { auto count = callFrame->argumentCount(); @@ -1234,7 +1247,7 @@ JSC::EncodedJSValue KeyObject__createPublicKey(JSC::JSGlobalObject* globalObject return JSValue::encode(JSC::jsUndefined()); } -JSC::EncodedJSValue KeyObject__createSecretKey(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) +JSC_DEFINE_HOST_FUNCTION(KeyObject__createSecretKey, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { JSValue bufferArg = callFrame->uncheckedArgument(0); auto& vm = lexicalGlobalObject->vm(); @@ -1347,7 +1360,7 @@ static ExceptionOr> KeyObject__GetBuffer(JSValue bufferArg) } return Exception { OperationError }; } -JSC::EncodedJSValue KeyObject__Sign(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +JSC_DEFINE_HOST_FUNCTION(KeyObject__Sign, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { auto count = callFrame->argumentCount(); auto& vm = globalObject->vm(); @@ -1556,7 +1569,7 @@ JSC::EncodedJSValue KeyObject__Sign(JSC::JSGlobalObject* globalObject, JSC::Call } } -JSC::EncodedJSValue KeyObject__Verify(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +JSC_DEFINE_HOST_FUNCTION(KeyObject__Verify, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { auto count = callFrame->argumentCount(); auto& vm = globalObject->vm(); @@ -1763,7 +1776,7 @@ JSC::EncodedJSValue KeyObject__Verify(JSC::JSGlobalObject* globalObject, JSC::Ca } } -JSC::EncodedJSValue KeyObject__Exports(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +JSC_DEFINE_HOST_FUNCTION(KeyObject__Exports, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { auto count = callFrame->argumentCount(); @@ -2348,7 +2361,7 @@ static char* bignum_to_string(const BIGNUM* bn) return ret; } -JSC::EncodedJSValue KeyObject_AsymmetricKeyDetails(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) +JSC_DEFINE_HOST_FUNCTION(KeyObject_AsymmetricKeyDetails, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { if (auto* key = jsDynamicCast(callFrame->argument(0))) { @@ -2473,7 +2486,7 @@ JSC::EncodedJSValue KeyObject_AsymmetricKeyDetails(JSC::JSGlobalObject* lexicalG return JSC::JSValue::encode(JSC::jsUndefined()); } -JSC::EncodedJSValue KeyObject__generateKeyPairSync(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) +JSC_DEFINE_HOST_FUNCTION(KeyObject__generateKeyPairSync, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { auto count = callFrame->argumentCount(); auto& vm = lexicalGlobalObject->vm(); @@ -2695,7 +2708,7 @@ JSC::EncodedJSValue KeyObject__generateKeyPairSync(JSC::JSGlobalObject* lexicalG } return JSValue::encode(JSC::jsUndefined()); } -JSC::EncodedJSValue KeyObject__generateKeySync(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) +JSC_DEFINE_HOST_FUNCTION(KeyObject__generateKeySync, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { auto count = callFrame->argumentCount(); auto& vm = lexicalGlobalObject->vm(); @@ -2757,7 +2770,7 @@ JSC::EncodedJSValue KeyObject__generateKeySync(JSC::JSGlobalObject* lexicalGloba } } -JSC::EncodedJSValue KeyObject__AsymmetricKeyType(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) +JSC_DEFINE_HOST_FUNCTION(KeyObject__AsymmetricKeyType, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { static const NeverDestroyed values[] = { MAKE_STATIC_STRING_IMPL("rsa"), @@ -2842,7 +2855,7 @@ static AsymmetricKeyValue GetInternalAsymmetricKey(WebCore::CryptoKey& key) } } -JSC::EncodedJSValue KeyObject__Equals(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) +JSC_DEFINE_HOST_FUNCTION(KeyObject__Equals, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { if (auto* key = jsDynamicCast(callFrame->argument(0))) { if (auto* key2 = jsDynamicCast(callFrame->argument(1))) { @@ -2886,7 +2899,7 @@ JSC::EncodedJSValue KeyObject__Equals(JSC::JSGlobalObject* lexicalGlobalObject, return JSC::JSValue::encode(jsBoolean(false)); } -JSC::EncodedJSValue KeyObject__SymmetricKeySize(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +JSC_DEFINE_HOST_FUNCTION(KeyObject__SymmetricKeySize, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { if (auto* key = jsDynamicCast(callFrame->argument(0))) { auto& wrapped = key->wrapped(); diff --git a/src/bun.js/bindings/KeyObject.h b/src/bun.js/bindings/KeyObject.h index d70ba80d5c..924ba9223f 100644 --- a/src/bun.js/bindings/KeyObject.h +++ b/src/bun.js/bindings/KeyObject.h @@ -6,19 +6,6 @@ namespace WebCore { -JSC::EncodedJSValue KeyObject__AsymmetricKeyType(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); -JSC::EncodedJSValue KeyObject_AsymmetricKeyDetails(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); -JSC::EncodedJSValue KeyObject__SymmetricKeySize(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); -JSC::EncodedJSValue KeyObject__Equals(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); -JSC::EncodedJSValue KeyObject__Exports(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); -JSC::EncodedJSValue KeyObject__createSecretKey(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); -JSC::EncodedJSValue KeyObject__createPublicKey(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); -JSC::EncodedJSValue KeyObject__createPrivateKey(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); -JSC::EncodedJSValue KeyObject__generateKeySync(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); -JSC::EncodedJSValue KeyObject__generateKeyPairSync(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); -JSC::EncodedJSValue KeyObject__Sign(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); -JSC::EncodedJSValue KeyObject__Verify(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); - JSC::JSValue createNodeCryptoBinding(Zig::GlobalObject* globalObject); } // namespace WebCore diff --git a/src/bun.js/bindings/ModuleLoader.cpp b/src/bun.js/bindings/ModuleLoader.cpp index dba0e84573..d5a27f3a8b 100644 --- a/src/bun.js/bindings/ModuleLoader.cpp +++ b/src/bun.js/bindings/ModuleLoader.cpp @@ -736,7 +736,7 @@ static JSValue fetchESMSourceCode( default: { if (tag & SyntheticModuleType::InternalModuleRegistryFlag) { constexpr auto mask = (SyntheticModuleType::InternalModuleRegistryFlag - 1); - auto source = JSC::SourceCode(JSC::SyntheticSourceProvider::create(generateInternalModuleSourceCode(globalObject, static_cast(tag & mask)), JSC::SourceOrigin(URL(makeString("builtins://", moduleKey))), moduleKey)); + auto source = JSC::SourceCode(JSC::SyntheticSourceProvider::create(generateInternalModuleSourceCode(globalObject, static_cast(tag & mask)), JSC::SourceOrigin(URL(makeString("builtins://"_s, moduleKey))), moduleKey)); return rejectOrResolve(JSSourceCode::create(vm, WTFMove(source))); } else { auto&& provider = Zig::SourceProvider::create(globalObject, res->result.value, JSC::SourceProviderSourceType::Module, true); @@ -844,7 +844,32 @@ static JSValue fetchESMSourceCode( JSC::SourceCode(Zig::SourceProvider::create(globalObject, res->result.value)))); } -extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultResolve(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +JSValue fetchESMSourceCodeSync( + Zig::GlobalObject* globalObject, + JSC::JSValue specifierJS, + ErrorableResolvedSource* res, + BunString* specifier, + BunString* referrer, + BunString* typeAttribute) +{ + return fetchESMSourceCode(globalObject, specifierJS, res, specifier, referrer, typeAttribute); +} + +JSValue fetchESMSourceCodeAsync( + Zig::GlobalObject* globalObject, + JSC::JSValue specifierJS, + ErrorableResolvedSource* res, + BunString* specifier, + BunString* referrer, + BunString* typeAttribute) +{ + return fetchESMSourceCode(globalObject, specifierJS, res, specifier, referrer, typeAttribute); +} +} + +using namespace Bun; + +BUN_DEFINE_HOST_FUNCTION(jsFunctionOnLoadObjectResultResolve, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { JSC::VM& vm = globalObject->vm(); ErrorableResolvedSource res = {}; @@ -882,7 +907,7 @@ extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultResolve(JSC::JSGlobal return JSValue::encode(jsUndefined()); } -extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultReject(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +BUN_DEFINE_HOST_FUNCTION(jsFunctionOnLoadObjectResultReject, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { JSC::VM& vm = globalObject->vm(); JSC::JSValue reason = callFrame->argument(0); @@ -896,26 +921,3 @@ extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultReject(JSC::JSGlobalO return JSValue::encode(reason); } - -JSValue fetchESMSourceCodeSync( - Zig::GlobalObject* globalObject, - JSC::JSValue specifierJS, - ErrorableResolvedSource* res, - BunString* specifier, - BunString* referrer, - BunString* typeAttribute) -{ - return fetchESMSourceCode(globalObject, specifierJS, res, specifier, referrer, typeAttribute); -} - -JSValue fetchESMSourceCodeAsync( - Zig::GlobalObject* globalObject, - JSC::JSValue specifierJS, - ErrorableResolvedSource* res, - BunString* specifier, - BunString* referrer, - BunString* typeAttribute) -{ - return fetchESMSourceCode(globalObject, specifierJS, res, specifier, referrer, typeAttribute); -} -} diff --git a/src/bun.js/bindings/ModuleLoader.h b/src/bun.js/bindings/ModuleLoader.h index 2212bab10c..6816c0fd0b 100644 --- a/src/bun.js/bindings/ModuleLoader.h +++ b/src/bun.js/bindings/ModuleLoader.h @@ -1,11 +1,13 @@ +#pragma once + #include "root.h" #include "headers-handwritten.h" #include #include "BunClientData.h" -extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultResolve(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); -extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultReject(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); +BUN_DECLARE_HOST_FUNCTION(jsFunctionOnLoadObjectResultResolve); +BUN_DECLARE_HOST_FUNCTION(jsFunctionOnLoadObjectResultReject); namespace Zig { class GlobalObject; diff --git a/src/bun.js/bindings/NodeTLS.cpp b/src/bun.js/bindings/NodeTLS.cpp index e908a55088..f1c5efa37d 100644 --- a/src/bun.js/bindings/NodeTLS.cpp +++ b/src/bun.js/bindings/NodeTLS.cpp @@ -11,7 +11,7 @@ namespace Bun { using namespace JSC; -extern "C" JSC::EncodedJSValue Bun__canonicalizeIP(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +BUN_DECLARE_HOST_FUNCTION(Bun__canonicalizeIP); JSC::JSValue createNodeTLSBinding(Zig::GlobalObject* globalObject) { diff --git a/src/bun.js/bindings/ZigGeneratedCode.cpp b/src/bun.js/bindings/ZigGeneratedCode.cpp index 777c6455ea..69723deab9 100644 --- a/src/bun.js/bindings/ZigGeneratedCode.cpp +++ b/src/bun.js/bindings/ZigGeneratedCode.cpp @@ -15,7 +15,7 @@ using namespace WebCore; /* -- BEGIN DOMCall DEFINITIONS -- */ -extern "C" JSC_DECLARE_HOST_FUNCTION(FFI__ptr__slowpathWrapper); +BUN_DECLARE_HOST_FUNCTION(FFI__ptr__slowpathWrapper); extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(FFI__ptr__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, JSC::JSUint8Array*)); JSC_DEFINE_JIT_OPERATION(FFI__ptr__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, JSC::JSUint8Array* arg1)) @@ -25,7 +25,7 @@ JSC_DEFINE_JIT_OPERATION(FFI__ptr__fastpathWrapper, EncodedJSValue, (JSC::JSGlob CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - return FFI__ptr__fastpath(lexicalGlobalObject, thisValue, arg1); + return { FFI__ptr__fastpath(lexicalGlobalObject, thisValue, arg1) }; } JSC_DEFINE_HOST_FUNCTION(FFI__ptr__slowpathWrapper, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* frame)) { @@ -54,7 +54,7 @@ extern "C" void FFI__ptr__put(JSC::JSGlobalObject* globalObject, JSC::EncodedJSV function); } -extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__u8__slowpathWrapper); +BUN_DECLARE_HOST_FUNCTION(Reader__u8__slowpathWrapper); extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(Reader__u8__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t, int32_t)); JSC_DEFINE_JIT_OPERATION(Reader__u8__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) @@ -64,7 +64,7 @@ JSC_DEFINE_JIT_OPERATION(Reader__u8__fastpathWrapper, EncodedJSValue, (JSC::JSGl CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - return Reader__u8__fastpath(lexicalGlobalObject, thisValue, arg1, arg2); + return { Reader__u8__fastpath(lexicalGlobalObject, thisValue, arg1, arg2) }; } JSC_DEFINE_HOST_FUNCTION(Reader__u8__slowpathWrapper, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* frame)) { @@ -94,7 +94,7 @@ extern "C" void Reader__u8__put(JSC::JSGlobalObject* globalObject, JSC::EncodedJ function); } -extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__u16__slowpathWrapper); +BUN_DECLARE_HOST_FUNCTION(Reader__u16__slowpathWrapper); extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(Reader__u16__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t, int32_t)); JSC_DEFINE_JIT_OPERATION(Reader__u16__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) @@ -104,7 +104,7 @@ JSC_DEFINE_JIT_OPERATION(Reader__u16__fastpathWrapper, EncodedJSValue, (JSC::JSG CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - return Reader__u16__fastpath(lexicalGlobalObject, thisValue, arg1, arg2); + return { Reader__u16__fastpath(lexicalGlobalObject, thisValue, arg1, arg2) }; } JSC_DEFINE_HOST_FUNCTION(Reader__u16__slowpathWrapper, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* frame)) { @@ -134,7 +134,7 @@ extern "C" void Reader__u16__put(JSC::JSGlobalObject* globalObject, JSC::Encoded function); } -extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__u32__slowpathWrapper); +BUN_DECLARE_HOST_FUNCTION(Reader__u32__slowpathWrapper); extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(Reader__u32__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t, int32_t)); JSC_DEFINE_JIT_OPERATION(Reader__u32__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) @@ -144,7 +144,7 @@ JSC_DEFINE_JIT_OPERATION(Reader__u32__fastpathWrapper, EncodedJSValue, (JSC::JSG CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - return Reader__u32__fastpath(lexicalGlobalObject, thisValue, arg1, arg2); + return { Reader__u32__fastpath(lexicalGlobalObject, thisValue, arg1, arg2) }; } JSC_DEFINE_HOST_FUNCTION(Reader__u32__slowpathWrapper, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* frame)) { @@ -174,7 +174,7 @@ extern "C" void Reader__u32__put(JSC::JSGlobalObject* globalObject, JSC::Encoded function); } -extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__ptr__slowpathWrapper); +BUN_DECLARE_HOST_FUNCTION(Reader__ptr__slowpathWrapper); extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(Reader__ptr__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t, int32_t)); JSC_DEFINE_JIT_OPERATION(Reader__ptr__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) @@ -184,7 +184,7 @@ JSC_DEFINE_JIT_OPERATION(Reader__ptr__fastpathWrapper, EncodedJSValue, (JSC::JSG CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - return Reader__ptr__fastpath(lexicalGlobalObject, thisValue, arg1, arg2); + return { Reader__ptr__fastpath(lexicalGlobalObject, thisValue, arg1, arg2) }; } JSC_DEFINE_HOST_FUNCTION(Reader__ptr__slowpathWrapper, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* frame)) { @@ -214,7 +214,7 @@ extern "C" void Reader__ptr__put(JSC::JSGlobalObject* globalObject, JSC::Encoded function); } -extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__i8__slowpathWrapper); +BUN_DECLARE_HOST_FUNCTION(Reader__i8__slowpathWrapper); extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(Reader__i8__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t, int32_t)); JSC_DEFINE_JIT_OPERATION(Reader__i8__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) @@ -224,7 +224,7 @@ JSC_DEFINE_JIT_OPERATION(Reader__i8__fastpathWrapper, EncodedJSValue, (JSC::JSGl CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - return Reader__i8__fastpath(lexicalGlobalObject, thisValue, arg1, arg2); + return { Reader__i8__fastpath(lexicalGlobalObject, thisValue, arg1, arg2) }; } JSC_DEFINE_HOST_FUNCTION(Reader__i8__slowpathWrapper, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* frame)) { @@ -254,7 +254,7 @@ extern "C" void Reader__i8__put(JSC::JSGlobalObject* globalObject, JSC::EncodedJ function); } -extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__i16__slowpathWrapper); +BUN_DECLARE_HOST_FUNCTION(Reader__i16__slowpathWrapper); extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(Reader__i16__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t, int32_t)); JSC_DEFINE_JIT_OPERATION(Reader__i16__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) @@ -264,7 +264,7 @@ JSC_DEFINE_JIT_OPERATION(Reader__i16__fastpathWrapper, EncodedJSValue, (JSC::JSG CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - return Reader__i16__fastpath(lexicalGlobalObject, thisValue, arg1, arg2); + return { Reader__i16__fastpath(lexicalGlobalObject, thisValue, arg1, arg2) }; } JSC_DEFINE_HOST_FUNCTION(Reader__i16__slowpathWrapper, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* frame)) { @@ -294,7 +294,7 @@ extern "C" void Reader__i16__put(JSC::JSGlobalObject* globalObject, JSC::Encoded function); } -extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__i32__slowpathWrapper); +BUN_DECLARE_HOST_FUNCTION(Reader__i32__slowpathWrapper); extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(Reader__i32__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t, int32_t)); JSC_DEFINE_JIT_OPERATION(Reader__i32__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) @@ -304,7 +304,7 @@ JSC_DEFINE_JIT_OPERATION(Reader__i32__fastpathWrapper, EncodedJSValue, (JSC::JSG CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - return Reader__i32__fastpath(lexicalGlobalObject, thisValue, arg1, arg2); + return { Reader__i32__fastpath(lexicalGlobalObject, thisValue, arg1, arg2) }; } JSC_DEFINE_HOST_FUNCTION(Reader__i32__slowpathWrapper, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* frame)) { @@ -334,7 +334,7 @@ extern "C" void Reader__i32__put(JSC::JSGlobalObject* globalObject, JSC::Encoded function); } -extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__i64__slowpathWrapper); +BUN_DECLARE_HOST_FUNCTION(Reader__i64__slowpathWrapper); extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(Reader__i64__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t, int32_t)); JSC_DEFINE_JIT_OPERATION(Reader__i64__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) @@ -344,7 +344,7 @@ JSC_DEFINE_JIT_OPERATION(Reader__i64__fastpathWrapper, EncodedJSValue, (JSC::JSG CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - return Reader__i64__fastpath(lexicalGlobalObject, thisValue, arg1, arg2); + return { Reader__i64__fastpath(lexicalGlobalObject, thisValue, arg1, arg2) }; } JSC_DEFINE_HOST_FUNCTION(Reader__i64__slowpathWrapper, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* frame)) { @@ -374,7 +374,7 @@ extern "C" void Reader__i64__put(JSC::JSGlobalObject* globalObject, JSC::Encoded function); } -extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__u64__slowpathWrapper); +BUN_DECLARE_HOST_FUNCTION(Reader__u64__slowpathWrapper); extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(Reader__u64__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t, int32_t)); JSC_DEFINE_JIT_OPERATION(Reader__u64__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) @@ -384,7 +384,7 @@ JSC_DEFINE_JIT_OPERATION(Reader__u64__fastpathWrapper, EncodedJSValue, (JSC::JSG CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - return Reader__u64__fastpath(lexicalGlobalObject, thisValue, arg1, arg2); + return { Reader__u64__fastpath(lexicalGlobalObject, thisValue, arg1, arg2) }; } JSC_DEFINE_HOST_FUNCTION(Reader__u64__slowpathWrapper, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* frame)) { @@ -414,7 +414,7 @@ extern "C" void Reader__u64__put(JSC::JSGlobalObject* globalObject, JSC::Encoded function); } -extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__intptr__slowpathWrapper); +BUN_DECLARE_HOST_FUNCTION(Reader__intptr__slowpathWrapper); extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(Reader__intptr__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t, int32_t)); JSC_DEFINE_JIT_OPERATION(Reader__intptr__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) @@ -424,7 +424,7 @@ JSC_DEFINE_JIT_OPERATION(Reader__intptr__fastpathWrapper, EncodedJSValue, (JSC:: CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - return Reader__intptr__fastpath(lexicalGlobalObject, thisValue, arg1, arg2); + return { Reader__intptr__fastpath(lexicalGlobalObject, thisValue, arg1, arg2) }; } JSC_DEFINE_HOST_FUNCTION(Reader__intptr__slowpathWrapper, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* frame)) { @@ -454,7 +454,7 @@ extern "C" void Reader__intptr__put(JSC::JSGlobalObject* globalObject, JSC::Enco function); } -extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__f32__slowpathWrapper); +BUN_DECLARE_HOST_FUNCTION(Reader__f32__slowpathWrapper); extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(Reader__f32__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t, int32_t)); JSC_DEFINE_JIT_OPERATION(Reader__f32__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) @@ -464,7 +464,7 @@ JSC_DEFINE_JIT_OPERATION(Reader__f32__fastpathWrapper, EncodedJSValue, (JSC::JSG CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - return Reader__f32__fastpath(lexicalGlobalObject, thisValue, arg1, arg2); + return { Reader__f32__fastpath(lexicalGlobalObject, thisValue, arg1, arg2) }; } JSC_DEFINE_HOST_FUNCTION(Reader__f32__slowpathWrapper, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* frame)) { @@ -494,7 +494,7 @@ extern "C" void Reader__f32__put(JSC::JSGlobalObject* globalObject, JSC::Encoded function); } -extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__f64__slowpathWrapper); +BUN_DECLARE_HOST_FUNCTION(Reader__f64__slowpathWrapper); extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(Reader__f64__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t, int32_t)); JSC_DEFINE_JIT_OPERATION(Reader__f64__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) @@ -504,7 +504,7 @@ JSC_DEFINE_JIT_OPERATION(Reader__f64__fastpathWrapper, EncodedJSValue, (JSC::JSG CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - return Reader__f64__fastpath(lexicalGlobalObject, thisValue, arg1, arg2); + return { Reader__f64__fastpath(lexicalGlobalObject, thisValue, arg1, arg2) }; } JSC_DEFINE_HOST_FUNCTION(Reader__f64__slowpathWrapper, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* frame)) { diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 42c2c056a3..4fb5144a3b 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -166,14 +166,12 @@ using namespace Bun; -extern "C" JSC__JSValue Bun__NodeUtil__jsParseArgs(JSC::JSGlobalObject*, JSC::CallFrame*); +BUN_DECLARE_HOST_FUNCTION(Bun__NodeUtil__jsParseArgs); +BUN_DECLARE_HOST_FUNCTION(Bun__fetch); +BUN_DECLARE_HOST_FUNCTION(BUN__HTTP2__getUnpackedSettings); +BUN_DECLARE_HOST_FUNCTION(BUN__HTTP2_getPackedSettings); -extern "C" JSC::EncodedJSValue Bun__fetch(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); -extern "C" JSC::EncodedJSValue H2FrameParser__getConstructor(Zig::GlobalObject* globalObject); -extern "C" JSC::EncodedJSValue BUN__HTTP2__getUnpackedSettings(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); -extern "C" JSC::EncodedJSValue BUN__HTTP2_getPackedSettings(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); -using JSGlobalObject - = JSC::JSGlobalObject; +using JSGlobalObject = JSC::JSGlobalObject; using Exception = JSC::Exception; using JSValue = JSC::JSValue; using JSString = JSC::JSString; @@ -280,7 +278,7 @@ static JSValue formatStackTraceToJSValue(JSC::VM& vm, Zig::GlobalObject* globalO auto* str = errorMessage.toString(lexicalGlobalObject); if (str->length() > 0) { sb.append("Error: "_s); - sb.append(str->value(lexicalGlobalObject)); + sb.append(str->value(lexicalGlobalObject).data); } else { sb.append("Error"_s); } @@ -1585,7 +1583,7 @@ extern "C" JSC__JSValue ArrayBuffer__fromSharedMemfd(int64_t fd, JSC::JSGlobalOb return JSC::JSValue::encode(JSC::JSValue {}); } - auto buffer = ArrayBuffer::createFromBytes(reinterpret_cast(ptr) + byteOffset, byteLength, createSharedTask([ptr, totalLength](void* p) { + auto buffer = ArrayBuffer::createFromBytes({ reinterpret_cast(reinterpret_cast(ptr) + byteOffset), byteLength }, createSharedTask([ptr, totalLength](void* p) { munmap(ptr, totalLength); })); @@ -1699,7 +1697,7 @@ static inline JSC::EncodedJSValue jsFunctionAddEventListenerBody(JSC::JSGlobalOb auto type = convert>(*lexicalGlobalObject, argument0.value()); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); - auto listener = convert>>(*lexicalGlobalObject, argument1.value(), *castedThis, [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeObjectError(lexicalGlobalObject, scope, 1, "listener", "EventTarget", "addEventListener"); }); + auto listener = convert>>(*lexicalGlobalObject, argument1.value(), *castedThis, [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeObjectError(lexicalGlobalObject, scope, 1, "listener"_s, "EventTarget"_s, "addEventListener"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument2 = callFrame->argument(2); auto options = argument2.value().isUndefined() ? false : convert, IDLBoolean>>(*lexicalGlobalObject, argument2.value()); @@ -1728,7 +1726,7 @@ static inline JSC::EncodedJSValue jsFunctionRemoveEventListenerBody(JSC::JSGloba auto type = convert>(*lexicalGlobalObject, argument0.value()); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); - auto listener = convert>>(*lexicalGlobalObject, argument1.value(), *castedThis, [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeObjectError(lexicalGlobalObject, scope, 1, "listener", "EventTarget", "removeEventListener"); }); + auto listener = convert>>(*lexicalGlobalObject, argument1.value(), *castedThis, [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeObjectError(lexicalGlobalObject, scope, 1, "listener"_s, "EventTarget"_s, "removeEventListener"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument2 = callFrame->argument(2); auto options = argument2.value().isUndefined() ? false : convert, IDLBoolean>>(*lexicalGlobalObject, argument2.value()); @@ -1754,7 +1752,7 @@ static inline JSC::EncodedJSValue jsFunctionDispatchEventBody(JSC::JSGlobalObjec if (UNLIKELY(callFrame->argumentCount() < 1)) return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); - auto event = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "event", "EventTarget", "dispatchEvent", "Event"); }); + auto event = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "event"_s, "EventTarget"_s, "dispatchEvent"_s, "Event"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); RELEASE_AND_RETURN(throwScope, JSValue::encode(WebCore::toJS(*lexicalGlobalObject, throwScope, impl.dispatchEventForBindings(*event)))); } @@ -3245,9 +3243,9 @@ JSC::GCClient::IsoSubspace* GlobalObject::subspaceForImpl(JSC::VM& vm) [](auto& server) -> JSC::HeapCellType& { return server.m_heapCellTypeForJSWorkerGlobalScope; }); } -extern "C" JSC::EncodedJSValue WebCore__alert(JSC::JSGlobalObject*, JSC::CallFrame*); -extern "C" JSC::EncodedJSValue WebCore__prompt(JSC::JSGlobalObject*, JSC::CallFrame*); -extern "C" JSC::EncodedJSValue WebCore__confirm(JSC::JSGlobalObject*, JSC::CallFrame*); +BUN_DECLARE_HOST_FUNCTION(WebCore__alert); +BUN_DECLARE_HOST_FUNCTION(WebCore__prompt); +BUN_DECLARE_HOST_FUNCTION(WebCore__confirm); JSValue GlobalObject_getPerformanceObject(VM& vm, JSObject* globalObject) { @@ -3693,7 +3691,7 @@ JSC::Identifier GlobalObject::moduleLoaderResolve(JSGlobalObject* jsGlobalObject BunString keyZ; if (key.isString()) { auto moduleName = jsCast(key)->value(globalObject); - if (moduleName.startsWith("file://"_s)) { + if (moduleName->startsWith("file://"_s)) { auto url = WTF::URL(moduleName); if (url.isValid() && !url.isEmpty()) { keyZ = Bun::toStringRef(url.fileSystemPath()); @@ -3765,7 +3763,7 @@ JSC::JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject* j ErrorableString resolved; BunString moduleNameZ; - auto moduleName = moduleNameValue->value(globalObject); + String moduleName = moduleNameValue->value(globalObject); #if BUN_DEBUG auto startRefCount = moduleName.impl()->refCount(); #endif @@ -3945,7 +3943,7 @@ JSC::JSValue EvalGlobalObject::moduleLoaderEvaluate(JSGlobalObject* lexicalGloba return result; } -GlobalObject::PromiseFunctions GlobalObject::promiseHandlerID(EncodedJSValue (*handler)(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1)) +GlobalObject::PromiseFunctions GlobalObject::promiseHandlerID(Zig::FFIFunction handler) { if (handler == Bun__HTTPRequestContext__onReject) { return GlobalObject::PromiseFunctions::Bun__HTTPRequestContext__onReject; diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h index 242b1917f0..f366a43d1a 100644 --- a/src/bun.js/bindings/ZigGlobalObject.h +++ b/src/bun.js/bindings/ZigGlobalObject.h @@ -344,9 +344,9 @@ public: }; static constexpr size_t promiseFunctionsSize = 24; - static PromiseFunctions promiseHandlerID(EncodedJSValue (*handler)(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1)); + static PromiseFunctions promiseHandlerID(SYSV_ABI EncodedJSValue (*handler)(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1)); - JSFunction* thenable(EncodedJSValue (*handler)(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1)) + JSFunction* thenable(SYSV_ABI EncodedJSValue (*handler)(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1)) { auto& barrier = this->m_thenables[static_cast(GlobalObject::promiseHandlerID(handler))]; if (JSFunction* func = barrier.get()) { diff --git a/src/bun.js/bindings/ZigGlobalObject.lut.txt b/src/bun.js/bindings/ZigGlobalObject.lut.txt index 389ceb03a5..1e57ace3f5 100644 --- a/src/bun.js/bindings/ZigGlobalObject.lut.txt +++ b/src/bun.js/bindings/ZigGlobalObject.lut.txt @@ -1,88 +1,88 @@ -// In a separate file because processing ZigGlobalObject.cpp takes 15+ seconds - -/* Source for ZigGlobalObject.lut.h -@begin bunGlobalObjectTable - addEventListener jsFunctionAddEventListener Function 2 - alert WebCore__alert Function 1 - atob functionATOB Function 1 - btoa functionBTOA Function 1 - clearImmediate functionClearTimeout Function 1 - clearInterval functionClearInterval Function 1 - clearTimeout functionClearTimeout Function 1 - confirm WebCore__confirm Function 1 - dispatchEvent jsFunctionDispatchEvent Function 1 - fetch Bun__fetch Function 2 - postMessage jsFunctionPostMessage Function 1 - prompt WebCore__prompt Function 1 - queueMicrotask functionQueueMicrotask Function 2 - removeEventListener jsFunctionRemoveEventListener Function 2 - reportError functionReportError Function 1 - setImmediate functionSetImmediate Function 1 - setInterval functionSetInterval Function 1 - setTimeout functionSetTimeout Function 1 - structuredClone functionStructuredClone Function 2 - - global GlobalObject_getGlobalThis PropertyCallback - EventSource getEventSourceConstructor PropertyCallback - - Bun GlobalObject::m_bunObject CellProperty|DontDelete|ReadOnly - File GlobalObject::m_JSDOMFileConstructor CellProperty - crypto GlobalObject::m_cryptoObject CellProperty - navigator GlobalObject::m_navigatorObject CellProperty - performance GlobalObject::m_performanceObject CellProperty - process GlobalObject::m_processObject CellProperty - - Blob GlobalObject::m_JSBlob ClassStructure - Buffer GlobalObject::m_JSBufferClassStructure ClassStructure - BuildError GlobalObject::m_JSBuildMessage ClassStructure - BuildMessage GlobalObject::m_JSBuildMessage ClassStructure - Crypto GlobalObject::m_JSCrypto ClassStructure - HTMLRewriter GlobalObject::m_JSHTMLRewriter ClassStructure - Request GlobalObject::m_JSRequest ClassStructure - ResolveError GlobalObject::m_JSResolveMessage ClassStructure - ResolveMessage GlobalObject::m_JSResolveMessage ClassStructure - Response GlobalObject::m_JSResponse ClassStructure - TextDecoder GlobalObject::m_JSTextDecoder ClassStructure - - AbortController AbortControllerConstructorCallback PropertyCallback - AbortSignal AbortSignalConstructorCallback PropertyCallback - BroadcastChannel BroadcastChannelConstructorCallback PropertyCallback - ByteLengthQueuingStrategy ByteLengthQueuingStrategyConstructorCallback PropertyCallback - CloseEvent CloseEventConstructorCallback PropertyCallback - CountQueuingStrategy CountQueuingStrategyConstructorCallback PropertyCallback - CryptoKey CryptoKeyConstructorCallback PropertyCallback - CustomEvent CustomEventConstructorCallback PropertyCallback - DOMException DOMExceptionConstructorCallback PropertyCallback - ErrorEvent ErrorEventConstructorCallback PropertyCallback - Event EventConstructorCallback PropertyCallback - EventTarget EventTargetConstructorCallback PropertyCallback - FormData DOMFormDataConstructorCallback PropertyCallback - Headers FetchHeadersConstructorCallback PropertyCallback - MessageChannel MessageChannelConstructorCallback PropertyCallback - MessageEvent MessageEventConstructorCallback PropertyCallback - MessagePort MessagePortConstructorCallback PropertyCallback - Performance PerformanceConstructorCallback PropertyCallback - PerformanceEntry PerformanceEntryConstructorCallback PropertyCallback - PerformanceMark PerformanceMarkConstructorCallback PropertyCallback - PerformanceMeasure PerformanceMeasureConstructorCallback PropertyCallback - PerformanceObserver PerformanceObserverConstructorCallback PropertyCallback - PerformanceObserverEntryList PerformanceObserverEntryListConstructorCallback PropertyCallback - ReadableByteStreamController ReadableByteStreamControllerConstructorCallback PropertyCallback - ReadableStream ReadableStreamConstructorCallback PropertyCallback - ReadableStreamBYOBReader ReadableStreamBYOBReaderConstructorCallback PropertyCallback - ReadableStreamBYOBRequest ReadableStreamBYOBRequestConstructorCallback PropertyCallback - ReadableStreamDefaultController ReadableStreamDefaultControllerConstructorCallback PropertyCallback - ReadableStreamDefaultReader ReadableStreamDefaultReaderConstructorCallback PropertyCallback - SubtleCrypto SubtleCryptoConstructorCallback PropertyCallback - TextEncoder TextEncoderConstructorCallback PropertyCallback - TransformStream TransformStreamConstructorCallback PropertyCallback - TransformStreamDefaultController TransformStreamDefaultControllerConstructorCallback PropertyCallback - URL DOMURLConstructorCallback PropertyCallback - URLSearchParams URLSearchParamsConstructorCallback PropertyCallback - WebSocket WebSocketConstructorCallback PropertyCallback - Worker WorkerConstructorCallback PropertyCallback - WritableStream WritableStreamConstructorCallback PropertyCallback - WritableStreamDefaultController WritableStreamDefaultControllerConstructorCallback PropertyCallback - WritableStreamDefaultWriter WritableStreamDefaultWriterConstructorCallback PropertyCallback -@end -*/ +// In a separate file because processing ZigGlobalObject.cpp takes 15+ seconds + +/* Source for ZigGlobalObject.lut.h +@begin bunGlobalObjectTable + addEventListener jsFunctionAddEventListener Function 2 + alert WebCore__alert Function 1 + atob functionATOB Function 1 + btoa functionBTOA Function 1 + clearImmediate functionClearTimeout Function 1 + clearInterval functionClearInterval Function 1 + clearTimeout functionClearTimeout Function 1 + confirm WebCore__confirm Function 1 + dispatchEvent jsFunctionDispatchEvent Function 1 + fetch Bun__fetch Function 2 + postMessage jsFunctionPostMessage Function 1 + prompt WebCore__prompt Function 1 + queueMicrotask functionQueueMicrotask Function 2 + removeEventListener jsFunctionRemoveEventListener Function 2 + reportError functionReportError Function 1 + setImmediate functionSetImmediate Function 1 + setInterval functionSetInterval Function 1 + setTimeout functionSetTimeout Function 1 + structuredClone functionStructuredClone Function 2 + + global GlobalObject_getGlobalThis PropertyCallback + EventSource getEventSourceConstructor PropertyCallback + + Bun GlobalObject::m_bunObject CellProperty|DontDelete|ReadOnly + File GlobalObject::m_JSDOMFileConstructor CellProperty + crypto GlobalObject::m_cryptoObject CellProperty + navigator GlobalObject::m_navigatorObject CellProperty + performance GlobalObject::m_performanceObject CellProperty + process GlobalObject::m_processObject CellProperty + + Blob GlobalObject::m_JSBlob ClassStructure + Buffer GlobalObject::m_JSBufferClassStructure ClassStructure + BuildError GlobalObject::m_JSBuildMessage ClassStructure + BuildMessage GlobalObject::m_JSBuildMessage ClassStructure + Crypto GlobalObject::m_JSCrypto ClassStructure + HTMLRewriter GlobalObject::m_JSHTMLRewriter ClassStructure + Request GlobalObject::m_JSRequest ClassStructure + ResolveError GlobalObject::m_JSResolveMessage ClassStructure + ResolveMessage GlobalObject::m_JSResolveMessage ClassStructure + Response GlobalObject::m_JSResponse ClassStructure + TextDecoder GlobalObject::m_JSTextDecoder ClassStructure + + AbortController AbortControllerConstructorCallback PropertyCallback + AbortSignal AbortSignalConstructorCallback PropertyCallback + BroadcastChannel BroadcastChannelConstructorCallback PropertyCallback + ByteLengthQueuingStrategy ByteLengthQueuingStrategyConstructorCallback PropertyCallback + CloseEvent CloseEventConstructorCallback PropertyCallback + CountQueuingStrategy CountQueuingStrategyConstructorCallback PropertyCallback + CryptoKey CryptoKeyConstructorCallback PropertyCallback + CustomEvent CustomEventConstructorCallback PropertyCallback + DOMException DOMExceptionConstructorCallback PropertyCallback + ErrorEvent ErrorEventConstructorCallback PropertyCallback + Event EventConstructorCallback PropertyCallback + EventTarget EventTargetConstructorCallback PropertyCallback + FormData DOMFormDataConstructorCallback PropertyCallback + Headers FetchHeadersConstructorCallback PropertyCallback + MessageChannel MessageChannelConstructorCallback PropertyCallback + MessageEvent MessageEventConstructorCallback PropertyCallback + MessagePort MessagePortConstructorCallback PropertyCallback + Performance PerformanceConstructorCallback PropertyCallback + PerformanceEntry PerformanceEntryConstructorCallback PropertyCallback + PerformanceMark PerformanceMarkConstructorCallback PropertyCallback + PerformanceMeasure PerformanceMeasureConstructorCallback PropertyCallback + PerformanceObserver PerformanceObserverConstructorCallback PropertyCallback + PerformanceObserverEntryList PerformanceObserverEntryListConstructorCallback PropertyCallback + ReadableByteStreamController ReadableByteStreamControllerConstructorCallback PropertyCallback + ReadableStream ReadableStreamConstructorCallback PropertyCallback + ReadableStreamBYOBReader ReadableStreamBYOBReaderConstructorCallback PropertyCallback + ReadableStreamBYOBRequest ReadableStreamBYOBRequestConstructorCallback PropertyCallback + ReadableStreamDefaultController ReadableStreamDefaultControllerConstructorCallback PropertyCallback + ReadableStreamDefaultReader ReadableStreamDefaultReaderConstructorCallback PropertyCallback + SubtleCrypto SubtleCryptoConstructorCallback PropertyCallback + TextEncoder TextEncoderConstructorCallback PropertyCallback + TransformStream TransformStreamConstructorCallback PropertyCallback + TransformStreamDefaultController TransformStreamDefaultControllerConstructorCallback PropertyCallback + URL DOMURLConstructorCallback PropertyCallback + URLSearchParams URLSearchParamsConstructorCallback PropertyCallback + WebSocket WebSocketConstructorCallback PropertyCallback + Worker WorkerConstructorCallback PropertyCallback + WritableStream WritableStreamConstructorCallback PropertyCallback + WritableStreamDefaultController WritableStreamDefaultControllerConstructorCallback PropertyCallback + WritableStreamDefaultWriter WritableStreamDefaultWriterConstructorCallback PropertyCallback +@end +*/ diff --git a/src/bun.js/bindings/ZigSourceProvider.cpp b/src/bun.js/bindings/ZigSourceProvider.cpp index 48ddef08ea..3d1c137bbe 100644 --- a/src/bun.js/bindings/ZigSourceProvider.cpp +++ b/src/bun.js/bindings/ZigSourceProvider.cpp @@ -35,11 +35,11 @@ SourceOrigin toSourceOrigin(const String& sourceURL, bool isBuiltin) if (isBuiltin) { if (sourceURL.startsWith("node:"_s)) { - return SourceOrigin(WTF::URL(makeString("builtin://node/", sourceURL.substring(5)))); + return SourceOrigin(WTF::URL(makeString("builtin://node/"_s, sourceURL.substring(5)))); } else if (sourceURL.startsWith("bun:"_s)) { - return SourceOrigin(WTF::URL(makeString("builtin://bun/", sourceURL.substring(4)))); + return SourceOrigin(WTF::URL(makeString("builtin://bun/"_s, sourceURL.substring(4)))); } else { - return SourceOrigin(WTF::URL(makeString("builtin://", sourceURL))); + return SourceOrigin(WTF::URL(makeString("builtin://"_s, sourceURL))); } } @@ -73,8 +73,8 @@ Ref SourceProvider::create( Zig::GlobalObject* globalObject, ResolvedSource& resolvedSource, JSC::SourceProviderSourceType sourceType, - bool isBuiltin -) { + bool isBuiltin) +{ auto string = resolvedSource.source_code.toWTFString(BunString::ZeroCopy); auto sourceURLString = resolvedSource.source_url.toWTFString(BunString::ZeroCopy); @@ -111,8 +111,9 @@ Ref SourceProvider::create( return provider; } -SourceProvider::~SourceProvider() { - if(m_resolvedSource.already_bundled) { +SourceProvider::~SourceProvider() +{ + if (m_resolvedSource.already_bundled) { BunString str = Bun::toString(sourceURL()); Bun__removeSourceProviderSourceMap(m_globalObject->bunVM(), this, &str); } @@ -156,7 +157,6 @@ void SourceProvider::cacheBytecode(const BytecodeCacheGenerator& generator) m_cachedBytecode->addGlobalUpdate(*update); } - void SourceProvider::commitCachedBytecode() { // if (!m_resolvedSource.bytecodecache_fd || !m_cachedBytecode || !m_cachedBytecode->hasUpdates()) @@ -245,7 +245,8 @@ int SourceProvider::readCache(JSC::VM& vm, const JSC::SourceCode& sourceCode) // } } -extern "C" BunString ZigSourceProvider__getSourceSlice(SourceProvider* provider) { +extern "C" BunString ZigSourceProvider__getSourceSlice(SourceProvider* provider) +{ return Bun::toStringView(provider->source()); } diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 900d8144b4..d0d29ee0f7 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -1,9 +1,13 @@ +#include "JSFFIFunction.h" #include "root.h" - +#include "JavaScriptCore/JSCast.h" +#include "JavaScriptCore/JSType.h" +#include "JavaScriptCore/NumberObject.h" #include "JavaScriptCore/JSCJSValue.h" #include "JavaScriptCore/JSGlobalObject.h" +#include "JavaScriptCore/JSPromiseConstructor.h" #include "JavaScriptCore/DeleteAllCodeEffort.h" - +#include "JavaScriptCore/BooleanObject.h" #include "headers.h" #include "BunClientData.h" @@ -195,7 +199,6 @@ static constexpr int FLAG_NOT = (1 << 2); #pragma clang diagnostic pop -extern "C" bool Expect_readFlagsAndProcessPromise(JSC__JSValue instanceValue, JSC__JSGlobalObject* globalObject, ExpectFlags* flags, JSC__JSValue* value); extern "C" bool ExpectCustomAsymmetricMatcher__execute(void* self, JSC__JSValue thisValue, JSC__JSGlobalObject* globalObject, JSC__JSValue leftValue); enum class AsymmetricMatcherResult : uint8_t { @@ -204,10 +207,85 @@ enum class AsymmetricMatcherResult : uint8_t { NOT_MATCHER, }; -bool readFlagsAndProcessPromise(JSValue& instanceValue, ExpectFlags& flags, JSGlobalObject* globalObject, JSValue& value) +enum class AsymmetricMatcherConstructorType : uint8_t { + none = 0, + Symbol = 1, + String = 2, + Object = 3, + Array = 4, + BigInt = 5, + Boolean = 6, + Number = 7, + Promise = 8, + InstanceOf = 9, +}; + +extern "C" bool Expect_readFlagsAndProcessPromise(JSC__JSValue instanceValue, JSC__JSGlobalObject* globalObject, ExpectFlags* flags, JSC__JSValue* value, AsymmetricMatcherConstructorType* constructorType); + +extern "C" uint8_t AsymmetricMatcherConstructorType__fromJS(JSC__JSGlobalObject* globalObject, JSC__JSValue encodedValue) +{ + JSValue value = JSValue::decode(encodedValue); + if (value.isObject()) { + JSObject* object = value.getObject(); + JSC::VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + if (globalObject->numberObjectConstructor() == object) { + return static_cast(AsymmetricMatcherConstructorType::Number); + } + + if (globalObject->booleanObjectConstructor() == object) { + return static_cast(AsymmetricMatcherConstructorType::Boolean); + } + + auto stringConstructorValue = globalObject->stringPrototype()->getIfPropertyExists(globalObject, vm.propertyNames->constructor); + RETURN_IF_EXCEPTION(scope, static_cast(AsymmetricMatcherConstructorType::none)); + + if (stringConstructorValue == object) { + return static_cast(AsymmetricMatcherConstructorType::String); + } + + auto symbolConstructorValue = globalObject->symbolPrototype()->getIfPropertyExists(globalObject, vm.propertyNames->constructor); + RETURN_IF_EXCEPTION(scope, static_cast(AsymmetricMatcherConstructorType::none)); + + if (symbolConstructorValue == object) { + return static_cast(AsymmetricMatcherConstructorType::Symbol); + } + + auto bigIntConstructorValue = globalObject->bigIntPrototype()->getIfPropertyExists(globalObject, vm.propertyNames->constructor); + RETURN_IF_EXCEPTION(scope, static_cast(AsymmetricMatcherConstructorType::none)); + + if (bigIntConstructorValue == object) { + return static_cast(AsymmetricMatcherConstructorType::BigInt); + } + + JSObject* promiseConstructor = globalObject->promiseConstructor(); + + if (promiseConstructor == object) { + return static_cast(AsymmetricMatcherConstructorType::Promise); + } + + JSObject* array = globalObject->arrayConstructor(); + + if (array == object) { + return static_cast(AsymmetricMatcherConstructorType::Array); + } + + JSObject* obj = globalObject->objectConstructor(); + + if (obj == object) { + return static_cast(AsymmetricMatcherConstructorType::Object); + } + + return static_cast(AsymmetricMatcherConstructorType::InstanceOf); + } + + return static_cast(AsymmetricMatcherConstructorType::none); +} + +bool readFlagsAndProcessPromise(JSValue& instanceValue, ExpectFlags& flags, JSGlobalObject* globalObject, JSValue& value, AsymmetricMatcherConstructorType& constructorType) { JSC::EncodedJSValue valueEncoded = JSValue::encode(value); - if (Expect_readFlagsAndProcessPromise(JSValue::encode(instanceValue), globalObject, &flags, &valueEncoded)) { + if (Expect_readFlagsAndProcessPromise(JSValue::encode(instanceValue), globalObject, &flags, &valueEncoded, &constructorType)) { value = JSValue::decode(valueEncoded); return true; } @@ -216,11 +294,11 @@ bool readFlagsAndProcessPromise(JSValue& instanceValue, ExpectFlags& flags, JSGl AsymmetricMatcherResult matchAsymmetricMatcherAndGetFlags(JSGlobalObject* globalObject, JSValue matcherProp, JSValue otherProp, ThrowScope* throwScope, ExpectFlags& flags) { - VM& vm = globalObject->vm(); JSCell* matcherPropCell = matcherProp.asCell(); + AsymmetricMatcherConstructorType constructorType = AsymmetricMatcherConstructorType::none; if (auto* expectAnything = jsDynamicCast(matcherPropCell)) { - if (!readFlagsAndProcessPromise(matcherProp, flags, globalObject, otherProp)) + if (!readFlagsAndProcessPromise(matcherProp, flags, globalObject, otherProp, constructorType)) return AsymmetricMatcherResult::FAIL; if (otherProp.isUndefinedOrNull()) { @@ -229,46 +307,95 @@ AsymmetricMatcherResult matchAsymmetricMatcherAndGetFlags(JSGlobalObject* global return AsymmetricMatcherResult::PASS; } else if (auto* expectAny = jsDynamicCast(matcherPropCell)) { - if (!readFlagsAndProcessPromise(matcherProp, flags, globalObject, otherProp)) + if (!readFlagsAndProcessPromise(matcherProp, flags, globalObject, otherProp, constructorType)) return AsymmetricMatcherResult::FAIL; JSValue constructorValue = expectAny->m_constructorValue.get(); JSObject* constructorObject = constructorValue.getObject(); - if (otherProp.isPrimitive()) { - if (otherProp.isNumber() && globalObject->numberObjectConstructor() == constructorObject) { + switch (constructorType) { + case AsymmetricMatcherConstructorType::Symbol: { + if (otherProp.isSymbol()) { return AsymmetricMatcherResult::PASS; - } else if (otherProp.isBoolean() && globalObject->booleanObjectConstructor() == constructorObject) { - return AsymmetricMatcherResult::PASS; - } else if (otherProp.isSymbol() && globalObject->symbolObjectConstructor() == constructorObject) { - return AsymmetricMatcherResult::PASS; - } else if (otherProp.isString()) { - if (auto* constructorFunction = jsDynamicCast(constructorObject)) { - String name = constructorFunction->name(vm); - if (name == "String"_s) { - return AsymmetricMatcherResult::PASS; - } - } else if (auto* internalConstructorFunction = jsDynamicCast(constructorObject)) { - String name = internalConstructorFunction->name(); - if (name == "String"_s) { - return AsymmetricMatcherResult::PASS; - } + } + break; + } + case AsymmetricMatcherConstructorType::String: { + if (otherProp.isCell()) { + JSCell* cell = otherProp.asCell(); + switch (cell->type()) { + case JSC::StringType: + case JSC::StringObjectType: + case JSC::DerivedStringObjectType: { + return AsymmetricMatcherResult::PASS; + } + default: { + break; } - } else if (otherProp.isBigInt()) { - if (auto* constructorFunction = jsDynamicCast(constructorObject)) { - String name = constructorFunction->name(vm); - if (name == "BigInt"_s) { - return AsymmetricMatcherResult::PASS; - } - } else if (auto* internalConstructorFunction = jsDynamicCast(constructorObject)) { - String name = internalConstructorFunction->name(); - if (name == "BigInt"_s) { - return AsymmetricMatcherResult::PASS; - } } } + break; + } - return AsymmetricMatcherResult::FAIL; + case AsymmetricMatcherConstructorType::BigInt: { + if (otherProp.isBigInt()) { + return AsymmetricMatcherResult::PASS; + } + break; + } + + case AsymmetricMatcherConstructorType::Boolean: { + if (otherProp.isBoolean()) { + return AsymmetricMatcherResult::PASS; + } + + if (auto* booleanObject = jsDynamicCast(otherProp)) { + return AsymmetricMatcherResult::PASS; + } + + break; + } + + case AsymmetricMatcherConstructorType::Number: { + if (otherProp.isNumber()) { + return AsymmetricMatcherResult::PASS; + } + + if (auto* numberObject = jsDynamicCast(otherProp)) { + return AsymmetricMatcherResult::PASS; + } + + break; + } + + case AsymmetricMatcherConstructorType::Promise: { + if (otherProp.isCell() && otherProp.asCell()->type() == JSPromiseType) { + return AsymmetricMatcherResult::PASS; + } + break; + } + + case AsymmetricMatcherConstructorType::Array: { + if (JSC::isArray(globalObject, otherProp)) { + return AsymmetricMatcherResult::PASS; + } + break; + } + + case AsymmetricMatcherConstructorType::Object: { + if (otherProp.isObject()) { + return AsymmetricMatcherResult::PASS; + } + break; + } + + case AsymmetricMatcherConstructorType::InstanceOf: { + break; + } + case AsymmetricMatcherConstructorType::none: { + ASSERT_NOT_REACHED_WITH_MESSAGE("Invalid constructor type"); + break; + } } if (constructorObject->hasInstance(globalObject, otherProp)) { @@ -277,7 +404,7 @@ AsymmetricMatcherResult matchAsymmetricMatcherAndGetFlags(JSGlobalObject* global return AsymmetricMatcherResult::FAIL; } else if (auto* expectStringContaining = jsDynamicCast(matcherPropCell)) { - if (!readFlagsAndProcessPromise(matcherProp, flags, globalObject, otherProp)) + if (!readFlagsAndProcessPromise(matcherProp, flags, globalObject, otherProp, constructorType)) return AsymmetricMatcherResult::FAIL; JSValue expectedSubstring = expectStringContaining->m_stringValue.get(); @@ -296,7 +423,7 @@ AsymmetricMatcherResult matchAsymmetricMatcherAndGetFlags(JSGlobalObject* global return AsymmetricMatcherResult::FAIL; } else if (auto* expectStringMatching = jsDynamicCast(matcherPropCell)) { - if (!readFlagsAndProcessPromise(matcherProp, flags, globalObject, otherProp)) + if (!readFlagsAndProcessPromise(matcherProp, flags, globalObject, otherProp, constructorType)) return AsymmetricMatcherResult::FAIL; JSValue expectedTestValue = expectStringMatching->m_testValue.get(); @@ -324,7 +451,7 @@ AsymmetricMatcherResult matchAsymmetricMatcherAndGetFlags(JSGlobalObject* global return AsymmetricMatcherResult::FAIL; } else if (auto* expectArrayContaining = jsDynamicCast(matcherPropCell)) { - if (!readFlagsAndProcessPromise(matcherProp, flags, globalObject, otherProp)) + if (!readFlagsAndProcessPromise(matcherProp, flags, globalObject, otherProp, constructorType)) return AsymmetricMatcherResult::FAIL; JSValue expectedArrayValue = expectArrayContaining->m_arrayValue.get(); @@ -369,7 +496,7 @@ AsymmetricMatcherResult matchAsymmetricMatcherAndGetFlags(JSGlobalObject* global return AsymmetricMatcherResult::FAIL; } else if (auto* expectObjectContaining = jsDynamicCast(matcherPropCell)) { - if (!readFlagsAndProcessPromise(matcherProp, flags, globalObject, otherProp)) + if (!readFlagsAndProcessPromise(matcherProp, flags, globalObject, otherProp, constructorType)) return AsymmetricMatcherResult::FAIL; JSValue patternObject = expectObjectContaining->m_objectValue.get(); @@ -384,7 +511,7 @@ AsymmetricMatcherResult matchAsymmetricMatcherAndGetFlags(JSGlobalObject* global return AsymmetricMatcherResult::FAIL; } else if (auto* expectCloseTo = jsDynamicCast(matcherPropCell)) { - if (!readFlagsAndProcessPromise(matcherProp, flags, globalObject, otherProp)) + if (!readFlagsAndProcessPromise(matcherProp, flags, globalObject, otherProp, constructorType)) return AsymmetricMatcherResult::FAIL; if (!otherProp.isNumber()) { @@ -412,7 +539,7 @@ AsymmetricMatcherResult matchAsymmetricMatcherAndGetFlags(JSGlobalObject* global return isClose ? AsymmetricMatcherResult::PASS : AsymmetricMatcherResult::FAIL; } } else if (auto* customMatcher = jsDynamicCast(matcherPropCell)) { - if (!readFlagsAndProcessPromise(matcherProp, flags, globalObject, otherProp)) + if (!readFlagsAndProcessPromise(matcherProp, flags, globalObject, otherProp, constructorType)) return AsymmetricMatcherResult::FAIL; // ignore the "not" flag here, because the custom matchers handle it themselves (accessing this.isNot) @@ -437,7 +564,7 @@ AsymmetricMatcherResult matchAsymmetricMatcher(JSGlobalObject* globalObject, JSV } template -static void handlePromise(PromiseType* promise, JSC__JSGlobalObject* globalObject, JSC::EncodedJSValue ctx, JSC__JSValue (*resolverFunction)(JSC__JSGlobalObject* arg0, JSC__CallFrame* callFrame), JSC__JSValue (*rejecterFunction)(JSC__JSGlobalObject* arg0, JSC__CallFrame* callFrame)) +static void handlePromise(PromiseType* promise, JSC__JSGlobalObject* globalObject, JSC::EncodedJSValue ctx, Zig::FFIFunction resolverFunction, Zig::FFIFunction rejecterFunction) { auto globalThis = reinterpret_cast(globalObject); @@ -2073,7 +2200,7 @@ JSC__JSPromise* JSC__JSPromise__create(JSC__JSGlobalObject* arg0) } // TODO: prevent this from allocating so much memory -void JSC__JSValue___then(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__JSValue arg2, JSC__JSValue (*ArgFn3)(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1), JSC__JSValue (*ArgFn4)(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1)) +void JSC__JSValue___then(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__JSValue arg2, Zig::FFIFunction ArgFn3, Zig::FFIFunction ArgFn4) { auto* cell = JSC::JSValue::decode(JSValue0).asCell(); @@ -2829,13 +2956,13 @@ void JSC__JSValue__toZigString(JSC__JSValue JSValue0, ZigString* arg1, JSC__JSGl auto str = strValue->value(arg2); - if (str.is8Bit()) { - arg1->ptr = str.span8().data(); + if (str->is8Bit()) { + arg1->ptr = str->span8().data(); } else { - arg1->ptr = Zig::taggedUTF16Ptr(str.span16().data()); + arg1->ptr = Zig::taggedUTF16Ptr(str->span16().data()); } - arg1->len = str.length(); + arg1->len = str->length(); } JSC__JSValue ZigString__external(const ZigString* arg0, JSC__JSGlobalObject* arg1, void* arg2, void (*ArgFn3)(void* arg0, void* arg1, size_t arg2)) diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index f55cac34c2..cbb465a3bb 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -2684,7 +2684,7 @@ pub const JSFunction = extern struct { pub fn create( global: *JSGlobalObject, fn_name: anytype, - implementation: *const JSHostFunctionType, + comptime implementation: JSHostFunctionType, function_length: u32, options: CreateJSFunctionOptions, ) JSValue { @@ -3236,7 +3236,7 @@ pub const JSGlobalObject = extern struct { }; }; -pub const JSNativeFn = *const fn (*JSGlobalObject, *CallFrame) callconv(.C) JSValue; +pub const JSNativeFn = JSHostFunctionPtr; pub const JSArrayIterator = struct { i: u32 = 0, @@ -4625,6 +4625,10 @@ pub const JSValue = enum(JSValueReprInt) { }; } + pub fn toJSString(globalObject: *JSC.JSGlobalObject, slice_: []const u8) JSC.JSValue { + return JSC.ZigString.init(slice_).withEncoding().toJS(globalObject); + } + pub fn asCell(this: JSValue) *JSCell { return cppFn("asCell", .{this}); } @@ -5975,6 +5979,34 @@ pub const CallFrame = opaque { pub const name = "JSC::CallFrame"; + pub fn format(frame: *CallFrame, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + const args = frame.argumentsPtr()[0..frame.argumentsCount()]; + + for (args[0..@min(args.len, 4)], 0..) |arg, i| { + if (i != 0) { + try writer.writeAll(", "); + } + switch (arg) { + .zero => try writer.writeAll(""), + .undefined => try writer.writeAll("undefined"), + .null => try writer.writeAll("null"), + .true => try writer.writeAll("true"), + .false => try writer.writeAll("false"), + else => { + if (arg.isNumber()) { + try writer.writeAll("number"); + } else { + try writer.writeAll(@tagName(arg.jsType())); + } + }, + } + } + + if (args.len > 4) { + try writer.print(", ... {d} more", .{args.len - 4}); + } + } + pub fn argumentsPtr(self: *const CallFrame) [*]const JSC.JSValue { return @as([*]align(alignment) const JSC.JSValue, @ptrCast(@alignCast(self))) + Sizes.Bun_CallFrame__firstArgument; } @@ -6059,8 +6091,44 @@ pub const EncodedJSValue = extern union { asPtr: ?*anyopaque, asDouble: f64, }; -pub const JSHostFunctionType = fn (*JSGlobalObject, *CallFrame) callconv(.C) JSValue; +pub const JSHostFunctionType = fn (*JSGlobalObject, *CallFrame) callconv(JSC.conv) JSValue; +pub const JSHostFunctionTypeWithCCallConvForAssertions = fn (*JSGlobalObject, *CallFrame) callconv(.C) JSValue; pub const JSHostFunctionPtr = *const JSHostFunctionType; +pub fn toJSHostFunction(comptime Function: anytype) JSC.JSHostFunctionType { + if (comptime @TypeOf(Function) == JSHostFunctionType) { + return Function; + } + + if (@TypeOf(Function) == fn (*JSGlobalObject, *CallFrame) JSValue) { + // These may coerce to both, but we want to force it to be this kind. + } else if (@TypeOf(Function) == *const fn (*JSGlobalObject, *CallFrame) JSValue) { + @compileLog(Function, "use JSC.toJSHostFunction(Function) instead of JSC.toJSHostFunction(&Function)"); + } + + return struct { + pub fn function( + globalThis: *JSC.JSGlobalObject, + callframe: *JSC.CallFrame, + ) callconv(JSC.conv) JSC.JSValue { + comptime { + const Fn = @TypeOf(Function); + var FnTypeInfo = @typeInfo(Fn); + if (FnTypeInfo == .Pointer) { + FnTypeInfo = @typeInfo(std.meta.Child(Fn)); + } + + if (bun.Environment.isWindows) { + if (FnTypeInfo.Fn.calling_convention == .C) { + @compileLog(Function, "use callconv(JSC.conv) instead of callconv(.C), or don't set a callconv on the function."); + } + } + } + + return @call(.always_inline, Function, .{ globalThis, callframe }); + } + }.function; +} + const DeinitFunction = *const fn (ctx: *anyopaque, buffer: [*]u8, len: usize) callconv(.C) void; pub const JSArray = opaque { @@ -6081,7 +6149,7 @@ const private = struct { *JSGlobalObject, ?*const ZigString, argCount: u32, - function: *const anyopaque, + function: JSHostFunctionPtr, strong: bool, data: *anyopaque, ) JSValue; @@ -6089,7 +6157,7 @@ const private = struct { globalObject: *JSGlobalObject, symbolName: ?*const ZigString, argCount: u32, - functionPointer: *const anyopaque, + functionPointer: JSHostFunctionPtr, strong: bool, ) *anyopaque; @@ -6111,28 +6179,23 @@ const private = struct { pub extern fn Bun__FFIFunction_setDataPtr(JSValue, ?*anyopaque) void; }; -pub fn NewFunctionPtr(globalObject: *JSGlobalObject, symbolName: ?*const ZigString, argCount: u32, comptime functionPointer: anytype, strong: bool) *anyopaque { - JSC.markBinding(@src()); - return private.Bun__CreateFFIFunction(globalObject, symbolName, argCount, @as(*const anyopaque, @ptrCast(&functionPointer)), strong); -} - pub fn NewFunction( globalObject: *JSGlobalObject, symbolName: ?*const ZigString, argCount: u32, - functionPointer: JSHostFunctionPtr, + comptime functionPointer: anytype, strong: bool, ) JSValue { - return NewRuntimeFunction(globalObject, symbolName, argCount, functionPointer, strong, false); + return NewRuntimeFunction(globalObject, symbolName, argCount, toJSHostFunction(functionPointer), strong, false); } pub fn createCallback( globalObject: *JSGlobalObject, symbolName: ?*const ZigString, argCount: u32, - functionPointer: JSHostFunctionPtr, + comptime functionPointer: anytype, ) JSValue { - return NewRuntimeFunction(globalObject, symbolName, argCount, functionPointer, false, false); + return NewRuntimeFunction(globalObject, symbolName, argCount, toJSHostFunction(functionPointer), false, false); } pub fn NewRuntimeFunction( @@ -6170,7 +6233,7 @@ pub fn NewFunctionWithData( globalObject, symbolName, argCount, - @as(*const anyopaque, @ptrCast(&functionPointer)), + toJSHostFunction(functionPointer), strong, data, ); @@ -6358,43 +6421,6 @@ pub const WTF = struct { } }; -pub const Callback = struct { - // zig: Value, -}; - -pub fn Thenable(comptime name: []const u8, comptime Then: type, comptime onResolve: fn (*Then, globalThis: *JSGlobalObject, result: JSValue) void, comptime onReject: fn (*Then, globalThis: *JSGlobalObject, result: JSValue) void) type { - return struct { - pub fn resolve( - globalThis: [*c]JSGlobalObject, - callframe: ?*JSC.CallFrame, - ) callconv(.C) void { - @setRuntimeSafety(false); - const args_list = callframe.?.arguments(8); - onResolve(@as(*Then, @ptrCast(@alignCast(args_list.ptr[args_list.len - 1].asEncoded().asPtr))), globalThis, args_list.ptr[0]); - } - - pub fn reject( - globalThis: [*c]JSGlobalObject, - callframe: ?*JSC.CallFrame, - ) callconv(.C) void { - @setRuntimeSafety(false); - const args_list = callframe.?.arguments(8); - onReject(@as(*Then, @ptrCast(@alignCast(args_list.ptr[args_list.len - 1].asEncoded().asPtr))), globalThis, args_list.ptr[0]); - } - - pub fn then(ctx: *Then, this: JSValue, globalThis: *JSGlobalObject) void { - this._then(globalThis, ctx, resolve, reject); - } - - comptime { - if (!JSC.is_bindgen) { - @export(resolve, name ++ "__resolve"); - @export(reject, name ++ "__reject"); - } - } - }; -} - pub usingnamespace @import("./JSPropertyIterator.zig"); // DOMCall Fields diff --git a/src/bun.js/bindings/blob.cpp b/src/bun.js/bindings/blob.cpp index dfd98d45ba..bfbdc1fd49 100644 --- a/src/bun.js/bindings/blob.cpp +++ b/src/bun.js/bindings/blob.cpp @@ -1,7 +1,7 @@ #include "blob.h" #include "ZigGeneratedClasses.h" -extern "C" JSC::EncodedJSValue Blob__create(JSC::JSGlobalObject* globalObject, void* impl); +extern "C" JSC::EncodedJSValue SYSV_ABI Blob__create(JSC::JSGlobalObject* globalObject, void* impl); extern "C" void* Blob__setAsFile(void* impl, BunString* filename); namespace WebCore { diff --git a/src/bun.js/bindings/headers.h b/src/bun.js/bindings/headers.h index 9eab2c22b4..e16e72b349 100644 --- a/src/bun.js/bindings/headers.h +++ b/src/bun.js/bindings/headers.h @@ -301,7 +301,7 @@ CPP_DECL void JSC__JSMap__set(JSC__JSMap* arg0, JSC__JSGlobalObject* arg1, JSC__ #pragma mark - JSC::JSValue -CPP_DECL void JSC__JSValue___then(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__JSValue JSValue2, JSC__JSValue(* ArgFn3)(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1), JSC__JSValue(* ArgFn4)(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1)); +CPP_DECL void JSC__JSValue___then(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__JSValue JSValue2, SYSV_ABI JSC__JSValue(* ArgFn3)(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1), SYSV_ABI JSC__JSValue(* ArgFn4)(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1)); CPP_DECL bool JSC__JSValue__asArrayBuffer_(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, Bun__ArrayBuffer* arg2); CPP_DECL unsigned char JSC__JSValue__asBigIntCompare(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__JSValue JSValue2); CPP_DECL JSC__JSCell* JSC__JSValue__asCell(JSC__JSValue JSValue0); @@ -461,104 +461,104 @@ CPP_DECL void FFI__ptr__put(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1); #ifdef __cplusplus -ZIG_DECL JSC__JSValue FFI__ptr__fastpath(JSC__JSGlobalObject* arg0, void* arg1, Uint8Array_alias* arg2); -ZIG_DECL JSC__JSValue FFI__ptr__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); +extern "C" JSC__JSValue SYSV_ABI FFI__ptr__fastpath(JSC__JSGlobalObject* arg0, void* arg1, Uint8Array_alias* arg2); +extern "C" JSC__JSValue SYSV_ABI FFI__ptr__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); #endif CPP_DECL void Reader__u8__put(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1); #ifdef __cplusplus -ZIG_DECL JSC__JSValue Reader__u8__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); -ZIG_DECL JSC__JSValue Reader__u8__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__u8__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__u8__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); #endif CPP_DECL void Reader__u16__put(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1); #ifdef __cplusplus -ZIG_DECL JSC__JSValue Reader__u16__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); -ZIG_DECL JSC__JSValue Reader__u16__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__u16__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__u16__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); #endif CPP_DECL void Reader__u32__put(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1); #ifdef __cplusplus -ZIG_DECL JSC__JSValue Reader__u32__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); -ZIG_DECL JSC__JSValue Reader__u32__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__u32__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__u32__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); #endif CPP_DECL void Reader__ptr__put(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1); #ifdef __cplusplus -ZIG_DECL JSC__JSValue Reader__ptr__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); -ZIG_DECL JSC__JSValue Reader__ptr__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__ptr__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__ptr__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); #endif CPP_DECL void Reader__i8__put(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1); #ifdef __cplusplus -ZIG_DECL JSC__JSValue Reader__i8__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); -ZIG_DECL JSC__JSValue Reader__i8__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__i8__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__i8__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); #endif CPP_DECL void Reader__i16__put(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1); #ifdef __cplusplus -ZIG_DECL JSC__JSValue Reader__i16__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); -ZIG_DECL JSC__JSValue Reader__i16__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__i16__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__i16__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); #endif CPP_DECL void Reader__i32__put(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1); #ifdef __cplusplus -ZIG_DECL JSC__JSValue Reader__i32__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); -ZIG_DECL JSC__JSValue Reader__i32__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__i32__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__i32__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); #endif CPP_DECL void Reader__f32__put(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1); #ifdef __cplusplus -ZIG_DECL JSC__JSValue Reader__f32__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); -ZIG_DECL JSC__JSValue Reader__f32__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__f32__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__f32__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); #endif CPP_DECL void Reader__f64__put(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1); #ifdef __cplusplus -ZIG_DECL JSC__JSValue Reader__f64__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); -ZIG_DECL JSC__JSValue Reader__f64__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__f64__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__f64__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); #endif CPP_DECL void Reader__i64__put(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1); #ifdef __cplusplus -ZIG_DECL JSC__JSValue Reader__i64__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); -ZIG_DECL JSC__JSValue Reader__i64__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__i64__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__i64__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); #endif CPP_DECL void Reader__u64__put(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1); #ifdef __cplusplus -ZIG_DECL JSC__JSValue Reader__u64__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); -ZIG_DECL JSC__JSValue Reader__u64__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__u64__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__u64__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); #endif CPP_DECL void Reader__intptr__put(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1); #ifdef __cplusplus -ZIG_DECL JSC__JSValue Reader__intptr__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); -ZIG_DECL JSC__JSValue Reader__intptr__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__intptr__fastpath(JSC__JSGlobalObject* arg0, void* arg1, int64_t arg2, int32_t arg3); +extern "C" JSC__JSValue SYSV_ABI Reader__intptr__slowpath(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue* arg2, size_t arg3); #endif @@ -581,17 +581,17 @@ ZIG_DECL void Zig__GlobalObject__resolve(ErrorableString* arg0, JSC__JSGlobalObj #ifdef __cplusplus -ZIG_DECL JSC__JSValue Bun__Path__basename(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); -ZIG_DECL JSC__JSValue Bun__Path__dirname(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); -ZIG_DECL JSC__JSValue Bun__Path__extname(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); -ZIG_DECL JSC__JSValue Bun__Path__format(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); -ZIG_DECL JSC__JSValue Bun__Path__isAbsolute(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); -ZIG_DECL JSC__JSValue Bun__Path__join(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); -ZIG_DECL JSC__JSValue Bun__Path__normalize(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); -ZIG_DECL JSC__JSValue Bun__Path__parse(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); -ZIG_DECL JSC__JSValue Bun__Path__relative(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); -ZIG_DECL JSC__JSValue Bun__Path__resolve(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); -ZIG_DECL JSC__JSValue Bun__Path__toNamespacedPath(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); +extern "C" JSC__JSValue SYSV_ABI Bun__Path__basename(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); +extern "C" JSC__JSValue SYSV_ABI Bun__Path__dirname(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); +extern "C" JSC__JSValue SYSV_ABI Bun__Path__extname(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); +extern "C" JSC__JSValue SYSV_ABI Bun__Path__format(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); +extern "C" JSC__JSValue SYSV_ABI Bun__Path__isAbsolute(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); +extern "C" JSC__JSValue SYSV_ABI Bun__Path__join(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); +extern "C" JSC__JSValue SYSV_ABI Bun__Path__normalize(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); +extern "C" JSC__JSValue SYSV_ABI Bun__Path__parse(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); +extern "C" JSC__JSValue SYSV_ABI Bun__Path__relative(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); +extern "C" JSC__JSValue SYSV_ABI Bun__Path__resolve(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); +extern "C" JSC__JSValue SYSV_ABI Bun__Path__toNamespacedPath(JSC__JSGlobalObject* arg0, bool arg1, JSC__JSValue* arg2, uint16_t arg3); #endif @@ -605,14 +605,14 @@ CPP_DECL void ArrayBufferSink__onReady(JSC__JSValue JSValue0, JSC__JSValue JSVal #ifdef __cplusplus ZIG_DECL JSC__JSValue ArrayBufferSink__close(JSC__JSGlobalObject* arg0, void* arg1); -ZIG_DECL JSC__JSValue ArrayBufferSink__construct(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue ArrayBufferSink__end(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue ArrayBufferSink__endWithSink(void* arg0, JSC__JSGlobalObject* arg1); +BUN_DECLARE_HOST_FUNCTION(ArrayBufferSink__construct); +BUN_DECLARE_HOST_FUNCTION(ArrayBufferSink__end); +ZIG_DECL JSC__JSValue SYSV_ABI ArrayBufferSink__endWithSink(void* arg0, JSC__JSGlobalObject* arg1); ZIG_DECL void ArrayBufferSink__finalize(void* arg0); -ZIG_DECL JSC__JSValue ArrayBufferSink__flush(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue ArrayBufferSink__start(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); +BUN_DECLARE_HOST_FUNCTION(ArrayBufferSink__flush); +BUN_DECLARE_HOST_FUNCTION(ArrayBufferSink__start); ZIG_DECL void ArrayBufferSink__updateRef(void* arg0, bool arg1); -ZIG_DECL JSC__JSValue ArrayBufferSink__write(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); +BUN_DECLARE_HOST_FUNCTION(ArrayBufferSink__write); #endif CPP_DECL JSC__JSValue HTTPSResponseSink__assignToStream(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, void* arg2, void** arg3); @@ -625,14 +625,14 @@ CPP_DECL void HTTPSResponseSink__onReady(JSC__JSValue JSValue0, JSC__JSValue JSV #ifdef __cplusplus ZIG_DECL JSC__JSValue HTTPSResponseSink__close(JSC__JSGlobalObject* arg0, void* arg1); -ZIG_DECL JSC__JSValue HTTPSResponseSink__construct(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue HTTPSResponseSink__end(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue HTTPSResponseSink__endWithSink(void* arg0, JSC__JSGlobalObject* arg1); +BUN_DECLARE_HOST_FUNCTION(HTTPSResponseSink__construct); +BUN_DECLARE_HOST_FUNCTION(HTTPSResponseSink__end); +ZIG_DECL JSC__JSValue SYSV_ABI HTTPSResponseSink__endWithSink(void* arg0, JSC__JSGlobalObject* arg1); ZIG_DECL void HTTPSResponseSink__finalize(void* arg0); -ZIG_DECL JSC__JSValue HTTPSResponseSink__flush(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue HTTPSResponseSink__start(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); +BUN_DECLARE_HOST_FUNCTION(HTTPSResponseSink__flush); +BUN_DECLARE_HOST_FUNCTION(HTTPSResponseSink__start); ZIG_DECL void HTTPSResponseSink__updateRef(void* arg0, bool arg1); -ZIG_DECL JSC__JSValue HTTPSResponseSink__write(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); +BUN_DECLARE_HOST_FUNCTION(HTTPSResponseSink__write); #endif CPP_DECL JSC__JSValue HTTPResponseSink__assignToStream(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, void* arg2, void** arg3); @@ -645,14 +645,14 @@ CPP_DECL void HTTPResponseSink__onReady(JSC__JSValue JSValue0, JSC__JSValue JSVa #ifdef __cplusplus ZIG_DECL JSC__JSValue HTTPResponseSink__close(JSC__JSGlobalObject* arg0, void* arg1); -ZIG_DECL JSC__JSValue HTTPResponseSink__construct(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue HTTPResponseSink__end(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue HTTPResponseSink__endWithSink(void* arg0, JSC__JSGlobalObject* arg1); +BUN_DECLARE_HOST_FUNCTION(HTTPResponseSink__construct); +BUN_DECLARE_HOST_FUNCTION(HTTPResponseSink__end); +ZIG_DECL JSC__JSValue SYSV_ABI SYSV_ABI HTTPResponseSink__endWithSink(void* arg0, JSC__JSGlobalObject* arg1); ZIG_DECL void HTTPResponseSink__finalize(void* arg0); -ZIG_DECL JSC__JSValue HTTPResponseSink__flush(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue HTTPResponseSink__start(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); +BUN_DECLARE_HOST_FUNCTION(HTTPResponseSink__flush); +BUN_DECLARE_HOST_FUNCTION(HTTPResponseSink__start); ZIG_DECL void HTTPResponseSink__updateRef(void* arg0, bool arg1); -ZIG_DECL JSC__JSValue HTTPResponseSink__write(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); +BUN_DECLARE_HOST_FUNCTION(HTTPResponseSink__write); #endif CPP_DECL JSC__JSValue FileSink__assignToStream(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, void* arg2, void** arg3); @@ -665,14 +665,14 @@ CPP_DECL void FileSink__onReady(JSC__JSValue JSValue0, JSC__JSValue JSValue1, JS #ifdef __cplusplus ZIG_DECL JSC__JSValue FileSink__close(JSC__JSGlobalObject* arg0, void* arg1); -ZIG_DECL JSC__JSValue FileSink__construct(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue FileSink__end(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue FileSink__endWithSink(void* arg0, JSC__JSGlobalObject* arg1); +BUN_DECLARE_HOST_FUNCTION(FileSink__construct); +BUN_DECLARE_HOST_FUNCTION(FileSink__end); +ZIG_DECL JSC__JSValue SYSV_ABI FileSink__endWithSink(void* arg0, JSC__JSGlobalObject* arg1); ZIG_DECL void FileSink__finalize(void* arg0); -ZIG_DECL JSC__JSValue FileSink__flush(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue FileSink__start(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); +BUN_DECLARE_HOST_FUNCTION(FileSink__flush); +BUN_DECLARE_HOST_FUNCTION(FileSink__start); ZIG_DECL void FileSink__updateRef(void* arg0, bool arg1); -ZIG_DECL JSC__JSValue FileSink__write(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); +BUN_DECLARE_HOST_FUNCTION(FileSink__write); #endif @@ -686,14 +686,14 @@ CPP_DECL void FileSink__onReady(JSC__JSValue JSValue0, JSC__JSValue JSValue1, JS #ifdef __cplusplus ZIG_DECL JSC__JSValue FileSink__close(JSC__JSGlobalObject* arg0, void* arg1); -ZIG_DECL JSC__JSValue FileSink__construct(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue FileSink__end(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue FileSink__endWithSink(void* arg0, JSC__JSGlobalObject* arg1); +BUN_DECLARE_HOST_FUNCTION(FileSink__construct); +BUN_DECLARE_HOST_FUNCTION(FileSink__end); +ZIG_DECL JSC__JSValue SYSV_ABI FileSink__endWithSink(void* arg0, JSC__JSGlobalObject* arg1); ZIG_DECL void FileSink__finalize(void* arg0); -ZIG_DECL JSC__JSValue FileSink__flush(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue FileSink__start(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); +BUN_DECLARE_HOST_FUNCTION(FileSink__flush); +BUN_DECLARE_HOST_FUNCTION(FileSink__start); ZIG_DECL void FileSink__updateRef(void* arg0, bool arg1); -ZIG_DECL JSC__JSValue FileSink__write(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); +BUN_DECLARE_HOST_FUNCTION(FileSink__write); #endif @@ -757,19 +757,19 @@ CPP_DECL ZigException ZigException__fromException(JSC__Exception* arg0); #ifdef __cplusplus -ZIG_DECL void Bun__ConsoleObject__count(void* arg0, JSC__JSGlobalObject* arg1, const unsigned char* arg2, size_t arg3); -ZIG_DECL void Bun__ConsoleObject__countReset(void* arg0, JSC__JSGlobalObject* arg1, const unsigned char* arg2, size_t arg3); -ZIG_DECL void Bun__ConsoleObject__messageWithTypeAndLevel(void* arg0, uint32_t MessageType1, uint32_t MessageLevel2, JSC__JSGlobalObject* arg3, JSC__JSValue* arg4, size_t arg5); -ZIG_DECL void Bun__ConsoleObject__profile(void* arg0, JSC__JSGlobalObject* arg1, const unsigned char* arg2, size_t arg3); -ZIG_DECL void Bun__ConsoleObject__profileEnd(void* arg0, JSC__JSGlobalObject* arg1, const unsigned char* arg2, size_t arg3); -ZIG_DECL void Bun__ConsoleObject__record(void* arg0, JSC__JSGlobalObject* arg1, ScriptArguments* arg2); -ZIG_DECL void Bun__ConsoleObject__recordEnd(void* arg0, JSC__JSGlobalObject* arg1, ScriptArguments* arg2); -ZIG_DECL void Bun__ConsoleObject__screenshot(void* arg0, JSC__JSGlobalObject* arg1, ScriptArguments* arg2); -ZIG_DECL void Bun__ConsoleObject__takeHeapSnapshot(void* arg0, JSC__JSGlobalObject* arg1, const unsigned char* arg2, size_t arg3); -ZIG_DECL void Bun__ConsoleObject__time(void* arg0, JSC__JSGlobalObject* arg1, const unsigned char* arg2, size_t arg3); -ZIG_DECL void Bun__ConsoleObject__timeEnd(void* arg0, JSC__JSGlobalObject* arg1, const unsigned char* arg2, size_t arg3); -ZIG_DECL void Bun__ConsoleObject__timeLog(void* arg0, JSC__JSGlobalObject* arg1, const unsigned char* arg2, size_t arg3, JSC__JSValue* arg4, size_t arg5); -ZIG_DECL void Bun__ConsoleObject__timeStamp(void* arg0, JSC__JSGlobalObject* arg1, ScriptArguments* arg2); +extern "C" SYSV_ABI void Bun__ConsoleObject__count(void* arg0, JSC__JSGlobalObject* arg1, const unsigned char* arg2, size_t arg3); +extern "C" SYSV_ABI void Bun__ConsoleObject__countReset(void* arg0, JSC__JSGlobalObject* arg1, const unsigned char* arg2, size_t arg3); +extern "C" SYSV_ABI void Bun__ConsoleObject__messageWithTypeAndLevel(void* arg0, uint32_t MessageType1, uint32_t MessageLevel2, JSC__JSGlobalObject* arg3, JSC__JSValue* arg4, size_t arg5); +extern "C" SYSV_ABI void Bun__ConsoleObject__profile(void* arg0, JSC__JSGlobalObject* arg1, const unsigned char* arg2, size_t arg3); +extern "C" SYSV_ABI void Bun__ConsoleObject__profileEnd(void* arg0, JSC__JSGlobalObject* arg1, const unsigned char* arg2, size_t arg3); +extern "C" SYSV_ABI void Bun__ConsoleObject__record(void* arg0, JSC__JSGlobalObject* arg1, ScriptArguments* arg2); +extern "C" SYSV_ABI void Bun__ConsoleObject__recordEnd(void* arg0, JSC__JSGlobalObject* arg1, ScriptArguments* arg2); +extern "C" SYSV_ABI void Bun__ConsoleObject__screenshot(void* arg0, JSC__JSGlobalObject* arg1, ScriptArguments* arg2); +extern "C" SYSV_ABI void Bun__ConsoleObject__takeHeapSnapshot(void* arg0, JSC__JSGlobalObject* arg1, const unsigned char* arg2, size_t arg3); +extern "C" SYSV_ABI void Bun__ConsoleObject__time(void* arg0, JSC__JSGlobalObject* arg1, const unsigned char* arg2, size_t arg3); +extern "C" SYSV_ABI void Bun__ConsoleObject__timeEnd(void* arg0, JSC__JSGlobalObject* arg1, const unsigned char* arg2, size_t arg3); +extern "C" SYSV_ABI void Bun__ConsoleObject__timeLog(void* arg0, JSC__JSGlobalObject* arg1, const unsigned char* arg2, size_t arg3, JSC__JSValue* arg4, size_t arg5); +extern "C" SYSV_ABI void Bun__ConsoleObject__timeStamp(void* arg0, JSC__JSGlobalObject* arg1, ScriptArguments* arg2); #endif @@ -788,37 +788,37 @@ ZIG_DECL JSC__JSValue Bun__Timer__setTimeout(JSC__JSGlobalObject* arg0, JSC__JSV #ifdef __cplusplus -ZIG_DECL JSC__JSValue Bun__HTTPRequestContext__onReject(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue Bun__HTTPRequestContext__onRejectStream(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue Bun__HTTPRequestContext__onResolve(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue Bun__HTTPRequestContext__onResolveStream(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); +BUN_DECLARE_HOST_FUNCTION(Bun__HTTPRequestContext__onReject); +BUN_DECLARE_HOST_FUNCTION(Bun__HTTPRequestContext__onRejectStream); +BUN_DECLARE_HOST_FUNCTION(Bun__HTTPRequestContext__onResolve); +BUN_DECLARE_HOST_FUNCTION(Bun__HTTPRequestContext__onResolveStream); #endif #ifdef __cplusplus -ZIG_DECL JSC__JSValue Bun__HTTPRequestContextTLS__onReject(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue Bun__HTTPRequestContextTLS__onRejectStream(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue Bun__HTTPRequestContextTLS__onResolve(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue Bun__HTTPRequestContextTLS__onResolveStream(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); +BUN_DECLARE_HOST_FUNCTION(Bun__HTTPRequestContextTLS__onReject); +BUN_DECLARE_HOST_FUNCTION(Bun__HTTPRequestContextTLS__onRejectStream); +BUN_DECLARE_HOST_FUNCTION(Bun__HTTPRequestContextTLS__onResolve); +BUN_DECLARE_HOST_FUNCTION(Bun__HTTPRequestContextTLS__onResolveStream); #endif #ifdef __cplusplus -ZIG_DECL JSC__JSValue Bun__HTTPRequestContextDebug__onReject(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue Bun__HTTPRequestContextDebug__onRejectStream(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue Bun__HTTPRequestContextDebug__onResolve(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue Bun__HTTPRequestContextDebug__onResolveStream(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); +BUN_DECLARE_HOST_FUNCTION(Bun__HTTPRequestContextDebug__onReject); +BUN_DECLARE_HOST_FUNCTION(Bun__HTTPRequestContextDebug__onRejectStream); +BUN_DECLARE_HOST_FUNCTION(Bun__HTTPRequestContextDebug__onResolve); +BUN_DECLARE_HOST_FUNCTION(Bun__HTTPRequestContextDebug__onResolveStream); #endif #ifdef __cplusplus -ZIG_DECL JSC__JSValue Bun__HTTPRequestContextDebugTLS__onReject(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue Bun__HTTPRequestContextDebugTLS__onRejectStream(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue Bun__HTTPRequestContextDebugTLS__onResolve(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue Bun__HTTPRequestContextDebugTLS__onResolveStream(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); +BUN_DECLARE_HOST_FUNCTION(Bun__HTTPRequestContextDebugTLS__onReject); +BUN_DECLARE_HOST_FUNCTION(Bun__HTTPRequestContextDebugTLS__onRejectStream); +BUN_DECLARE_HOST_FUNCTION(Bun__HTTPRequestContextDebugTLS__onResolve); +BUN_DECLARE_HOST_FUNCTION(Bun__HTTPRequestContextDebugTLS__onResolveStream); #endif @@ -827,15 +827,15 @@ ZIG_DECL JSC__JSValue Bun__HTTPRequestContextDebugTLS__onResolveStream(JSC__JSGl #ifdef __cplusplus -ZIG_DECL JSC__JSValue Bun__BodyValueBufferer__onRejectStream(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue Bun__BodyValueBufferer__onResolveStream(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); +BUN_DECLARE_HOST_FUNCTION(Bun__BodyValueBufferer__onRejectStream); +BUN_DECLARE_HOST_FUNCTION(Bun__BodyValueBufferer__onResolveStream); #endif #ifdef __cplusplus -ZIG_DECL JSC__JSValue Bun__TestScope__onReject(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -ZIG_DECL JSC__JSValue Bun__TestScope__onResolve(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); +BUN_DECLARE_HOST_FUNCTION(Bun__TestScope__onReject); +BUN_DECLARE_HOST_FUNCTION(Bun__TestScope__onResolve); #endif @@ -853,7 +853,7 @@ CPP_DECL bool JSC__CustomGetterSetter__isSetterNull(JSC__CustomGetterSetter *arg #ifdef __cplusplus -CPP_DECL JSC__JSValue Bun__onResolveEntryPointResult(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); -CPP_DECL JSC__JSValue Bun__onRejectEntryPointResult(JSC__JSGlobalObject* arg0, JSC__CallFrame* arg1); +BUN_DECLARE_HOST_FUNCTION(Bun__onResolveEntryPointResult); +BUN_DECLARE_HOST_FUNCTION(Bun__onRejectEntryPointResult); #endif \ No newline at end of file diff --git a/src/bun.js/bindings/headers.zig b/src/bun.js/bindings/headers.zig index 52a65a60c2..e718de6863 100644 --- a/src/bun.js/bindings/headers.zig +++ b/src/bun.js/bindings/headers.zig @@ -195,7 +195,7 @@ pub extern fn JSC__JSMap__get_(arg0: ?*bindings.JSMap, arg1: *bindings.JSGlobalO pub extern fn JSC__JSMap__has(arg0: ?*bindings.JSMap, arg1: *bindings.JSGlobalObject, JSValue2: JSC__JSValue) bool; pub extern fn JSC__JSMap__remove(arg0: ?*bindings.JSMap, arg1: *bindings.JSGlobalObject, JSValue2: JSC__JSValue) bool; pub extern fn JSC__JSMap__set(arg0: ?*bindings.JSMap, arg1: *bindings.JSGlobalObject, JSValue2: JSC__JSValue, JSValue3: JSC__JSValue) void; -pub extern fn JSC__JSValue___then(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject, JSValue2: JSC__JSValue, ArgFn3: ?*const fn (*bindings.JSGlobalObject, *bindings.CallFrame) callconv(.C) JSC__JSValue, ArgFn4: ?*const fn (*bindings.JSGlobalObject, *bindings.CallFrame) callconv(.C) JSC__JSValue) void; +pub extern fn JSC__JSValue___then(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject, JSValue2: JSC__JSValue, ArgFn3: ?bun.JSC.JSHostFunctionPtr, ArgFn4: ?bun.JSC.JSHostFunctionPtr) void; pub extern fn JSC__JSValue__asArrayBuffer_(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject, arg2: ?*Bun__ArrayBuffer) bool; pub extern fn JSC__JSValue__asBigIntCompare(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject, JSValue2: JSC__JSValue) u8; pub extern fn JSC__JSValue__asCell(JSValue0: JSC__JSValue) [*c]bindings.JSCell; diff --git a/src/bun.js/bindings/napi.cpp b/src/bun.js/bindings/napi.cpp index 69d77263e0..fe30f2538d 100644 --- a/src/bun.js/bindings/napi.cpp +++ b/src/bun.js/bindings/napi.cpp @@ -326,12 +326,12 @@ public: using Base = JSC::JSFunction; static constexpr unsigned StructureFlags = Base::StructureFlags; - static JSC::EncodedJSValue call(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe) + static JSC_HOST_CALL_ATTRIBUTES JSC::EncodedJSValue call(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe) { ASSERT(jsCast(callframe->jsCallee())); auto* function = static_cast(callframe->jsCallee()); auto* env = toNapi(globalObject); - auto* callback = reinterpret_cast(function->m_method.get()); + auto* callback = reinterpret_cast(function->m_method); JSC::VM& vm = globalObject->vm(); MarkedArgumentBufferWithSize<12> args; @@ -348,14 +348,14 @@ public: RELEASE_AND_RETURN(scope, JSC::JSValue::encode(toJS(result))); } - NAPIFunction(JSC::VM& vm, JSC::NativeExecutable* exec, JSGlobalObject* globalObject, Structure* structure, JSC::NativeFunction method, void* dataPtr) + NAPIFunction(JSC::VM& vm, JSC::NativeExecutable* exec, JSGlobalObject* globalObject, Structure* structure, Zig::CFFIFunction method, void* dataPtr) : Base(vm, exec, globalObject, structure) , m_method(method) , m_dataPtr(dataPtr) { } - static NAPIFunction* create(JSC::VM& vm, Zig::GlobalObject* globalObject, unsigned length, const WTF::String& name, JSC::NativeFunction method, void* dataPtr) + static NAPIFunction* create(JSC::VM& vm, Zig::GlobalObject* globalObject, unsigned length, const WTF::String& name, Zig::CFFIFunction method, void* dataPtr) { auto* structure = globalObject->NAPIFunctionStructure(); @@ -366,7 +366,7 @@ public: } void* m_dataPtr = nullptr; - JSC::NativeFunction m_method = nullptr; + Zig::CFFIFunction m_method = nullptr; template static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { @@ -430,7 +430,7 @@ static void defineNapiProperty(Zig::GlobalObject* globalObject, JSC::JSObject* t if (property.method) { JSC::JSValue value; - auto method = reinterpret_cast(property.method); + auto method = reinterpret_cast(property.method); auto* function = NAPIFunction::create(vm, globalObject, 1, propertyName.isSymbol() ? String() : propertyName.string(), method, dataPtr); value = JSC::JSValue(function); @@ -443,8 +443,8 @@ static void defineNapiProperty(Zig::GlobalObject* globalObject, JSC::JSObject* t JSC::JSObject* getter = nullptr; JSC::JSObject* setter = nullptr; - auto getterProperty = reinterpret_cast(property.getter); - auto setterProperty = reinterpret_cast(property.setter); + auto getterProperty = reinterpret_cast(property.getter); + auto setterProperty = reinterpret_cast(property.setter); if (getterProperty) { getter = NAPIFunction::create(vm, globalObject, 0, makeString("get "_s, propertyName.isSymbol() ? String() : propertyName.string()), getterProperty, dataPtr); @@ -1069,7 +1069,7 @@ extern "C" napi_status napi_create_function(napi_env env, const char* utf8name, name = WTF::String::fromUTF8({ utf8name, length == NAPI_AUTO_LENGTH ? strlen(utf8name) : length }); } - auto method = reinterpret_cast(cb); + auto method = reinterpret_cast(cb); auto* function = NAPIFunction::create(vm, globalObject, length, name, method, data); ASSERT(function->isCallable()); @@ -1815,7 +1815,7 @@ void NapiClass::finishCreation(VM& vm, NativeExecutable* executable, unsigned le { Base::finishCreation(vm, executable, length, name); ASSERT(inherits(info())); - this->m_constructor = reinterpret_cast(constructor); + this->m_constructor = reinterpret_cast(constructor); auto globalObject = reinterpret_cast(this->globalObject()); this->putDirect(vm, vm.propertyNames->name, jsString(vm, name), JSC::PropertyAttribute::DontEnum | 0); @@ -2023,7 +2023,7 @@ extern "C" napi_status napi_create_external_buffer(napi_env env, size_t length, Zig::GlobalObject* globalObject = toJS(env); - auto arrayBuffer = ArrayBuffer::createFromBytes(data, length, createSharedTask([globalObject, finalize_hint, finalize_cb](void* p) { + auto arrayBuffer = ArrayBuffer::createFromBytes({ reinterpret_cast(data), length }, createSharedTask([globalObject, finalize_hint, finalize_cb](void* p) { #if NAPI_VERBOSE printf("[napi] buffer finalize_callback\n"); #endif @@ -2051,7 +2051,7 @@ extern "C" napi_status napi_create_external_arraybuffer(napi_env env, void* exte Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); - auto arrayBuffer = ArrayBuffer::createFromBytes(external_data, byte_length, createSharedTask([globalObject, finalize_hint, finalize_cb](void* p) { + auto arrayBuffer = ArrayBuffer::createFromBytes({ reinterpret_cast(external_data), byte_length }, createSharedTask([globalObject, finalize_hint, finalize_cb](void* p) { #if NAPI_VERBOSE printf("[napi] arraybuffer finalize_callback\n"); #endif @@ -2127,8 +2127,7 @@ extern "C" napi_status napi_get_value_string_utf8(napi_env env, } size_t length = jsString->length(); - auto viewWithUnderlyingString = jsString->viewWithUnderlyingString(globalObject); - auto view = viewWithUnderlyingString.view; + String view = jsString->value(globalObject); if (buf == nullptr) { if (writtenPtr != nullptr) { diff --git a/src/bun.js/bindings/napi.h b/src/bun.js/bindings/napi.h index c011653738..76d2401be4 100644 --- a/src/bun.js/bindings/napi.h +++ b/src/bun.js/bindings/napi.h @@ -160,13 +160,13 @@ public: return Structure::create(vm, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), info()); } - FFIFunction constructor() + CFFIFunction constructor() { return m_constructor; } void* dataPtr = nullptr; - FFIFunction m_constructor = nullptr; + CFFIFunction m_constructor = nullptr; NapiRef* napiRef = nullptr; private: diff --git a/src/bun.js/bindings/root.h b/src/bun.js/bindings/root.h index 2bb8253a81..a87a830cfd 100644 --- a/src/bun.js/bindings/root.h +++ b/src/bun.js/bindings/root.h @@ -78,4 +78,12 @@ #define USE_OPENSSL 1 #define HAVE_RSA_PSS 1 +#if OS(WINDOWS) +#define BUN_DECLARE_HOST_FUNCTION(name) extern "C" __attribute__((visibility("default"))) JSC_DECLARE_HOST_FUNCTION(name) +#define BUN_DEFINE_HOST_FUNCTION(name, args) extern "C" __attribute__((visibility("default"))) JSC_DEFINE_HOST_FUNCTION(name, args) +#else +#define BUN_DECLARE_HOST_FUNCTION(name) extern "C" JSC_DECLARE_HOST_FUNCTION(name) +#define BUN_DEFINE_HOST_FUNCTION(name, args) extern "C" JSC_DEFINE_HOST_FUNCTION(name, args) +#endif + #endif \ No newline at end of file diff --git a/src/bun.js/bindings/shimmer.zig b/src/bun.js/bindings/shimmer.zig index 1c83268481..307294918e 100644 --- a/src/bun.js/bindings/shimmer.zig +++ b/src/bun.js/bindings/shimmer.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const bun = @import("root").bun; const StaticExport = @import("./static_export.zig"); const Sizes = @import("./sizes.zig"); pub const is_bindgen: bool = false; @@ -15,6 +16,14 @@ pub fn Shimmer(comptime _namespace: []const u8, comptime _name: []const u8, comp pub const namespace = _namespace; pub const name = _name; + pub fn assertJSFunction(comptime funcs: anytype) void { + inline for (funcs) |func| { + if (@typeInfo(@TypeOf(func)) != .Fn) { + @compileError("Expected " ++ @typeName(Parent) ++ "." ++ @typeName(func) ++ " to be a function but received " ++ @tagName(@typeInfo(@TypeOf(func)))); + } + } + } + pub fn ref() void { if (comptime @hasDecl(Parent, "Export")) { inline for (Parent.Export) |exp| { @@ -111,7 +120,9 @@ pub fn Shimmer(comptime _namespace: []const u8, comptime _name: []const u8, comp @compileError("Expected " ++ @typeName(Parent) ++ "." ++ @typeName(Function) ++ " to be a function but received " ++ @tagName(@typeInfo(Function))); } const Fn: std.builtin.Type.Fn = @typeInfo(Function).Fn; - if (Fn.calling_convention != .C) { + if (Function == bun.JSC.JSHostFunctionTypeWithCCallConvForAssertions and bun.JSC.conv != .C) { + @compileError("Expected " ++ bun.meta.typeName(Function) ++ " to have a JSC.conv Calling Convention."); + } else if (Function == bun.JSC.JSHostFunctionType) {} else if (Fn.calling_convention != .C) { @compileError("Expected " ++ @typeName(Parent) ++ "." ++ @typeName(Function) ++ " to have a C Calling Convention."); } diff --git a/src/bun.js/bindings/sqlite/JSSQLStatement.cpp b/src/bun.js/bindings/sqlite/JSSQLStatement.cpp index d330c3d7ef..d0a48b5f9e 100644 --- a/src/bun.js/bindings/sqlite/JSSQLStatement.cpp +++ b/src/bun.js/bindings/sqlite/JSSQLStatement.cpp @@ -193,6 +193,12 @@ static inline JSC::JSValue jsBigIntFromSQLite(JSC::JSGlobalObject* globalObject, return JSValue::encode(jsUndefined()); \ } +#define CHECK_PREPARED_JIT \ + if (UNLIKELY(castedThis->stmt == nullptr || castedThis->version_db == nullptr)) { \ + throwException(lexicalGlobalObject, scope, createError(lexicalGlobalObject, "Statement has finalized"_s)); \ + return {}; \ + } + class VersionSqlite3 { public: explicit VersionSqlite3(sqlite3* db) @@ -764,7 +770,7 @@ static inline bool rebindValue(JSC::JSGlobalObject* lexicalGlobalObject, sqlite3 return false; } - auto roped = str->tryGetValue(lexicalGlobalObject); + String roped = str->tryGetValue(lexicalGlobalObject); if (UNLIKELY(!roped)) { throwException(lexicalGlobalObject, scope, createError(lexicalGlobalObject, "Out of memory :("_s)); return false; @@ -863,7 +869,7 @@ static JSC::JSValue rebindObject(JSC::JSGlobalObject* globalObject, SQLiteBindin JSValue value = getValue(name, i); if (!value && !scope.exception()) { if (throwOnMissing) { - throwException(globalObject, scope, createError(globalObject, makeString("Missing parameter \""_s, name, "\""_s))); + throwException(globalObject, scope, createError(globalObject, makeString("Missing parameter \""_s, reinterpret_cast(name), "\""_s))); } else { continue; } @@ -2078,12 +2084,12 @@ JSC_DEFINE_JIT_OPERATION(jsSQLStatementExecuteStatementFunctionGetWithoutTypeChe auto scope = DECLARE_THROW_SCOPE(vm); auto* stmt = castedThis->stmt; - CHECK_PREPARED + CHECK_PREPARED_JIT int statusCode = sqlite3_reset(stmt); if (UNLIKELY(statusCode != SQLITE_OK)) { throwException(lexicalGlobalObject, scope, createSQLiteError(lexicalGlobalObject, castedThis->version_db->db)); - return JSValue::encode(jsUndefined()); + return { .value = 0 }; } int status = sqlite3_step(stmt); @@ -2107,11 +2113,11 @@ JSC_DEFINE_JIT_OPERATION(jsSQLStatementExecuteStatementFunctionGetWithoutTypeChe } if (status == SQLITE_DONE || status == SQLITE_OK) { - RELEASE_AND_RETURN(scope, JSValue::encode(result)); + RELEASE_AND_RETURN(scope, { JSValue::encode(result) }); } else { throwException(lexicalGlobalObject, scope, createSQLiteError(lexicalGlobalObject, castedThis->version_db->db)); sqlite3_reset(stmt); - return JSValue::encode(jsUndefined()); + return { JSValue::encode(jsUndefined()) }; } } diff --git a/src/bun.js/bindings/webcore/BufferSource.h b/src/bun.js/bindings/webcore/BufferSource.h index 3fed841d14..e764fc3169 100644 --- a/src/bun.js/bindings/webcore/BufferSource.h +++ b/src/bun.js/bindings/webcore/BufferSource.h @@ -103,12 +103,12 @@ std::optional BufferSource::decode(Decoder& decoder) const uint8_t* data = decoder.decodeFixedLengthReference(dataSize, alignof(uint8_t)); if (!data) return std::nullopt; - return BufferSource(JSC::ArrayBuffer::tryCreate(static_cast(data), dataSize.value())); + return BufferSource(JSC::ArrayBuffer::tryCreate({ static_cast(data), dataSize.value() })); } inline BufferSource toBufferSource(const uint8_t* data, size_t length) { - return BufferSource(JSC::ArrayBuffer::tryCreate(data, length)); + return BufferSource(JSC::ArrayBuffer::tryCreate({ data, length })); } } // namespace WebCore diff --git a/src/bun.js/bindings/webcore/Event.cpp b/src/bun.js/bindings/webcore/Event.cpp index f488f01066..e68c829d92 100644 --- a/src/bun.js/bindings/webcore/Event.cpp +++ b/src/bun.js/bindings/webcore/Event.cpp @@ -188,7 +188,7 @@ void Event::resetAfterDispatch() String Event::debugDescription() const { - return makeString(type(), " phase ", eventPhase(), bubbles() ? " bubbles " : " ", cancelable() ? "cancelable " : " ", "0x"_s, hex(reinterpret_cast(this), Lowercase)); + return makeString(type(), " phase "_s, eventPhase(), bubbles() ? " bubbles "_s : " "_s, cancelable() ? "cancelable "_s : " "_s, "0x"_s, hex(reinterpret_cast(this), Lowercase)); } TextStream& operator<<(TextStream& ts, const Event& event) diff --git a/src/bun.js/bindings/webcore/EventNames.cpp b/src/bun.js/bindings/webcore/EventNames.cpp index b98bfc2047..c97850e07e 100644 --- a/src/bun.js/bindings/webcore/EventNames.cpp +++ b/src/bun.js/bindings/webcore/EventNames.cpp @@ -27,7 +27,7 @@ namespace WebCore { #define INITIALIZE_EVENT_NAME(name) \ - name##Event(makeAtomString(#name)), + name##Event(makeAtomString(#name##_s)), EventNames::EventNames() : DOM_EVENT_NAMES_FOR_EACH(INITIALIZE_EVENT_NAME) dummy(0) diff --git a/src/bun.js/bindings/webcore/FetchHeaders.cpp b/src/bun.js/bindings/webcore/FetchHeaders.cpp index 02dbf7d572..95ff830fa6 100644 --- a/src/bun.js/bindings/webcore/FetchHeaders.cpp +++ b/src/bun.js/bindings/webcore/FetchHeaders.cpp @@ -44,7 +44,7 @@ static ExceptionOr canWriteHeader(const HTTPHeaderName name, const String& { ASSERT(value.isEmpty() || (!isHTTPSpace(value[0]) && !isHTTPSpace(value[value.length() - 1]))); if (!isValidHTTPHeaderValue((value))) - return Exception { TypeError, makeString("Header '", name, "' has invalid value: '", value, "'") }; + return Exception { TypeError, makeString("Header '"_s, name, "' has invalid value: '"_s, value, "'"_s) }; if (guard == FetchHeaders::Guard::Immutable) return Exception { TypeError, "Headers object's guard is 'immutable'"_s }; return true; @@ -53,10 +53,10 @@ static ExceptionOr canWriteHeader(const HTTPHeaderName name, const String& static ExceptionOr canWriteHeader(const String& name, const String& value, const String& combinedValue, FetchHeaders::Guard guard) { if (!isValidHTTPToken(name)) - return Exception { TypeError, makeString("Invalid header name: '", name, "'") }; + return Exception { TypeError, makeString("Invalid header name: '"_s, name, "'"_s) }; ASSERT(value.isEmpty() || (!isHTTPSpace(value[0]) && !isHTTPSpace(value[value.length() - 1]))); if (!isValidHTTPHeaderValue((value))) - return Exception { TypeError, makeString("Header '", name, "' has invalid value: '", value, "'") }; + return Exception { TypeError, makeString("Header '"_s, name, "' has invalid value: '"_s, value, "'"_s) }; if (guard == FetchHeaders::Guard::Immutable) return Exception { TypeError, "Headers object's guard is 'immutable'"_s }; return true; @@ -71,7 +71,7 @@ static ExceptionOr appendToHeaderMap(const String& name, const String& val if (headerName != HTTPHeaderName::SetCookie) { if (headers.contains(headerName)) { - combinedValue = makeString(headers.get(headerName), ", ", normalizedValue); + combinedValue = makeString(headers.get(headerName), ", "_s, normalizedValue); } } @@ -92,7 +92,7 @@ static ExceptionOr appendToHeaderMap(const String& name, const String& val } if (headers.contains(name)) - combinedValue = makeString(headers.get(name), ", ", normalizedValue); + combinedValue = makeString(headers.get(name), ", "_s, normalizedValue); auto canWriteResult = canWriteHeader(name, normalizedValue, combinedValue, guard); if (canWriteResult.hasException()) return canWriteResult.releaseException(); @@ -195,7 +195,7 @@ ExceptionOr FetchHeaders::append(const String& name, const String& value) ExceptionOr FetchHeaders::remove(const String& name) { if (!isValidHTTPToken(name)) - return Exception { TypeError, makeString("Invalid header name: '", name, "'") }; + return Exception { TypeError, makeString("Invalid header name: '"_s, name, "'"_s) }; if (m_guard == FetchHeaders::Guard::Immutable) return Exception { TypeError, "Headers object's guard is 'immutable'"_s }; if (m_guard == FetchHeaders::Guard::Request && isForbiddenHeaderName(name)) @@ -222,14 +222,14 @@ size_t FetchHeaders::memoryCost() const ExceptionOr FetchHeaders::get(const String& name) const { if (!isValidHTTPToken(name)) - return Exception { TypeError, makeString("Invalid header name: '", name, "'") }; + return Exception { TypeError, makeString("Invalid header name: '"_s, name, "'"_s) }; return m_headers.get(name); } ExceptionOr FetchHeaders::has(const String& name) const { if (!isValidHTTPToken(name)) - return Exception { TypeError, makeString("Invalid header name: '", name, "'") }; + return Exception { TypeError, makeString("Invalid header name: '"_s, name, '"') }; return m_headers.contains(name); } diff --git a/src/bun.js/bindings/webcore/HTTPHeaderMap.cpp b/src/bun.js/bindings/webcore/HTTPHeaderMap.cpp index c1a44ecb23..55beffbe66 100644 --- a/src/bun.js/bindings/webcore/HTTPHeaderMap.cpp +++ b/src/bun.js/bindings/webcore/HTTPHeaderMap.cpp @@ -174,7 +174,7 @@ void HTTPHeaderMap::add(const String& name, const String& value) if (index == notFound) m_uncommonHeaders.append(UncommonHeader { name, value }); else - m_uncommonHeaders[index].value = makeString(m_uncommonHeaders[index].value, ", ", value); + m_uncommonHeaders[index].value = makeString(m_uncommonHeaders[index].value, ", "_s, value); } void HTTPHeaderMap::append(const String& name, const String& value) @@ -303,7 +303,7 @@ void HTTPHeaderMap::add(HTTPHeaderName name, const String& value) return header.key == name; }); if (index != notFound) - m_commonHeaders[index].value = makeString(m_commonHeaders[index].value, ", ", value); + m_commonHeaders[index].value = makeString(m_commonHeaders[index].value, ", "_s, value); else m_commonHeaders.append(CommonHeader { name, value }); } diff --git a/src/bun.js/bindings/webcore/HTTPParsers.cpp b/src/bun.js/bindings/webcore/HTTPParsers.cpp index 7721f96e94..2bef4f365e 100644 --- a/src/bun.js/bindings/webcore/HTTPParsers.cpp +++ b/src/bun.js/bindings/webcore/HTTPParsers.cpp @@ -741,13 +741,13 @@ size_t parseHTTPHeader(const uint8_t* start, size_t length, String& failureReaso if (name.isEmpty()) { if (p + 1 < end && *(p + 1) == '\n') return (p + 2) - start; - failureReason = makeString("CR doesn't follow LF in header name at ", trimInputSample(p, end - p)); + failureReason = makeString("CR doesn't follow LF in header name at "_s, trimInputSample(p, end - p)); return 0; } - failureReason = makeString("Unexpected CR in header name at ", trimInputSample(name.data(), name.size())); + failureReason = makeString("Unexpected CR in header name at "_s, trimInputSample(name.data(), name.size())); return 0; case '\n': - failureReason = makeString("Unexpected LF in header name at ", trimInputSample(name.data(), name.size())); + failureReason = makeString("Unexpected LF in header name at "_s, trimInputSample(name.data(), name.size())); return 0; case ':': break; @@ -756,7 +756,7 @@ size_t parseHTTPHeader(const uint8_t* start, size_t length, String& failureReaso if (name.size() < 1) failureReason = "Unexpected start character in header name"_s; else - failureReason = makeString("Unexpected character in header name at ", trimInputSample(name.data(), name.size())); + failureReason = makeString("Unexpected character in header name at "_s, trimInputSample(name.data(), name.size())); return 0; } name.append(*p); @@ -784,7 +784,7 @@ size_t parseHTTPHeader(const uint8_t* start, size_t length, String& failureReaso break; case '\n': if (strict) { - failureReason = makeString("Unexpected LF in header value at ", trimInputSample(value.data(), value.size())); + failureReason = makeString("Unexpected LF in header value at "_s, trimInputSample(value.data(), value.size())); return 0; } break; @@ -797,7 +797,7 @@ size_t parseHTTPHeader(const uint8_t* start, size_t length, String& failureReaso } } if (p >= end || (strict && *p != '\n')) { - failureReason = makeString("CR doesn't follow LF after header value at ", trimInputSample(p, end - p)); + failureReason = makeString("CR doesn't follow LF after header value at "_s, trimInputSample(p, end - p)); return 0; } valueStr = String::fromUTF8({ value.data(), value.size() }); diff --git a/src/bun.js/bindings/webcore/JSAbortController.cpp b/src/bun.js/bindings/webcore/JSAbortController.cpp index 4685d34ea9..8a85c5ac4e 100644 --- a/src/bun.js/bindings/webcore/JSAbortController.cpp +++ b/src/bun.js/bindings/webcore/JSAbortController.cpp @@ -104,7 +104,7 @@ template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSAbortControllerDOMConstruct ASSERT(castedThis); auto* context = castedThis->scriptExecutionContext(); if (UNLIKELY(!context)) - return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "AbortController"); + return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "AbortController"_s); auto object = AbortController::create(*context); if constexpr (IsExceptionOr) RETURN_IF_EXCEPTION(throwScope, {}); @@ -294,18 +294,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj if constexpr (std::is_polymorphic_v) { #if ENABLE(BINDING_INTEGRITY) - const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // const void* actualVTablePointer = getVTablePointer(impl.ptr()); #if PLATFORM(WIN) void* expectedVTablePointer = __identifier("??_7AbortController@WebCore@@6B@"); #else - void* expectedVTablePointer = &_ZTVN7WebCore15AbortControllerE[2]; + // void* expectedVTablePointer = &_ZTVN7WebCore15AbortControllerE[2]; #endif // If you hit this assertion you either have a use after free bug, or // AbortController has subclasses. If AbortController has subclasses that get passed // to toJS() we currently require AbortController you to opt out of binding hardening // by adding the SkipVTableValidation attribute to the interface IDL definition - RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); #endif } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcore/JSAbortSignal.cpp b/src/bun.js/bindings/webcore/JSAbortSignal.cpp index 62ad867a38..cf2b1bf09f 100644 --- a/src/bun.js/bindings/webcore/JSAbortSignal.cpp +++ b/src/bun.js/bindings/webcore/JSAbortSignal.cpp @@ -405,18 +405,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj if constexpr (std::is_polymorphic_v) { #if ENABLE(BINDING_INTEGRITY) - const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // const void* actualVTablePointer = getVTablePointer(impl.ptr()); #if PLATFORM(WIN) void* expectedVTablePointer = __identifier("??_7AbortSignal@WebCore@@6B@"); #else - void* expectedVTablePointer = &_ZTVN7WebCore11AbortSignalE[2]; + // void* expectedVTablePointer = &_ZTVN7WebCore11AbortSignalE[2]; #endif // If you hit this assertion you either have a use after free bug, or // AbortSignal has subclasses. If AbortSignal has subclasses that get passed // to toJS() we currently require AbortSignal you to opt out of binding hardening // by adding the SkipVTableValidation attribute to the interface IDL definition - RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); #endif } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcore/JSBroadcastChannel.cpp b/src/bun.js/bindings/webcore/JSBroadcastChannel.cpp index feffce6477..61c7e8f6b2 100644 --- a/src/bun.js/bindings/webcore/JSBroadcastChannel.cpp +++ b/src/bun.js/bindings/webcore/JSBroadcastChannel.cpp @@ -112,7 +112,7 @@ template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSBroadcastChannelDOMCon return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); auto* context = castedThis->scriptExecutionContext(); if (UNLIKELY(!context)) - return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "BroadcastChannel"); + return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "BroadcastChannel"_s); EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); auto name = convert(*lexicalGlobalObject, argument0.value()); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); @@ -394,18 +394,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj if constexpr (std::is_polymorphic_v) { #if ENABLE(BINDING_INTEGRITY) - const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // const void* actualVTablePointer = getVTablePointer(impl.ptr()); #if PLATFORM(WIN) void* expectedVTablePointer = __identifier("??_7BroadcastChannel@WebCore@@6B@"); #else - void* expectedVTablePointer = &_ZTVN7WebCore16BroadcastChannelE[2]; + // void* expectedVTablePointer = &_ZTVN7WebCore16BroadcastChannelE[2]; #endif // If you hit this assertion you either have a use after free bug, or // BroadcastChannel has subclasses. If BroadcastChannel has subclasses that get passed // to toJS() we currently require BroadcastChannel you to opt out of binding hardening // by adding the SkipVTableValidation attribute to the interface IDL definition - RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); #endif } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcore/JSCallbackData.cpp b/src/bun.js/bindings/webcore/JSCallbackData.cpp index f634b48917..4b607fcb9c 100644 --- a/src/bun.js/bindings/webcore/JSCallbackData.cpp +++ b/src/bun.js/bindings/webcore/JSCallbackData.cpp @@ -73,7 +73,7 @@ JSValue JSCallbackData::invokeCallback(VM& vm, JSObject* callback, JSValue thisV callData = getCallData(function); if (callData.type == CallData::Type::None) { - returnedException = JSC::Exception::create(vm, createTypeError(lexicalGlobalObject, makeString("'", String(functionName.uid()), "' property of callback interface should be callable"))); + returnedException = JSC::Exception::create(vm, createTypeError(lexicalGlobalObject, makeString("'"_s, String(functionName.uid()), "' property of callback interface should be callable"_s))); return JSValue(); } diff --git a/src/bun.js/bindings/webcore/JSCloseEvent.cpp b/src/bun.js/bindings/webcore/JSCloseEvent.cpp index a302dcdfb3..4b297e6e41 100644 --- a/src/bun.js/bindings/webcore/JSCloseEvent.cpp +++ b/src/bun.js/bindings/webcore/JSCloseEvent.cpp @@ -330,7 +330,7 @@ void JSCloseEvent::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) auto* thisObject = jsCast(cell); analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); if (thisObject->scriptExecutionContext()) - analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + analyzer.setLabelForCell(cell, makeString("url "_s, thisObject->scriptExecutionContext()->url().string())); Base::analyzeHeap(cell, analyzer); } @@ -352,18 +352,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj if constexpr (std::is_polymorphic_v) { #if ENABLE(BINDING_INTEGRITY) - const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // const void* actualVTablePointer = getVTablePointer(impl.ptr()); #if PLATFORM(WIN) void* expectedVTablePointer = __identifier("??_7CloseEvent@WebCore@@6B@"); #else - void* expectedVTablePointer = &_ZTVN7WebCore10CloseEventE[2]; + // void* expectedVTablePointer = &_ZTVN7WebCore10CloseEventE[2]; #endif // If you hit this assertion you either have a use after free bug, or // CloseEvent has subclasses. If CloseEvent has subclasses that get passed // to toJS() we currently require CloseEvent you to opt out of binding hardening // by adding the SkipVTableValidation attribute to the interface IDL definition - RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); #endif } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcore/JSCustomEvent.cpp b/src/bun.js/bindings/webcore/JSCustomEvent.cpp index 2d5e3b9da3..1a88448182 100644 --- a/src/bun.js/bindings/webcore/JSCustomEvent.cpp +++ b/src/bun.js/bindings/webcore/JSCustomEvent.cpp @@ -333,7 +333,7 @@ void JSCustomEvent::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) auto* thisObject = jsCast(cell); analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); if (thisObject->scriptExecutionContext()) - analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + analyzer.setLabelForCell(cell, makeString("url "_s, thisObject->scriptExecutionContext()->url().string())); Base::analyzeHeap(cell, analyzer); } @@ -355,18 +355,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj // if constexpr (std::is_polymorphic_v) { // #if ENABLE(BINDING_INTEGRITY) - // const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // // const void* actualVTablePointer = getVTablePointer(impl.ptr()); // #if PLATFORM(WIN) // void* expectedVTablePointer = __identifier("??_7CustomEvent@WebCore@@6B@"); // #else - // void* expectedVTablePointer = &_ZTVN7WebCore11CustomEventE[2]; + // // void* expectedVTablePointer = &_ZTVN7WebCore11CustomEventE[2]; // #endif // // If you hit this assertion you either have a use after free bug, or // // CustomEvent has subclasses. If CustomEvent has subclasses that get passed // // to toJS() we currently require CustomEvent you to opt out of binding hardening // // by adding the SkipVTableValidation attribute to the interface IDL definition - // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); // #endif // } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcore/JSDOMConvertEnumeration.h b/src/bun.js/bindings/webcore/JSDOMConvertEnumeration.h index d458e4aa8c..224922f1b8 100644 --- a/src/bun.js/bindings/webcore/JSDOMConvertEnumeration.h +++ b/src/bun.js/bindings/webcore/JSDOMConvertEnumeration.h @@ -33,12 +33,11 @@ namespace WebCore { // Specialized by generated code for IDL enumeration conversion. template std::optional parseEnumeration(JSC::JSGlobalObject&, JSC::JSValue); -template const char* expectedEnumerationValues(); +template ASCIILiteral expectedEnumerationValues(); // Specialized by generated code for IDL enumeration conversion. template JSC::JSString* convertEnumerationToJS(JSC::JSGlobalObject&, T); - template struct Converter> : DefaultConverter> { template static T convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) @@ -47,11 +46,11 @@ template struct Converter> : DefaultConverter(lexicalGlobalObject, value); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); if (UNLIKELY(!result)) { exceptionThrower(lexicalGlobalObject, throwScope); - return { }; + return {}; } return result.value(); } diff --git a/src/bun.js/bindings/webcore/JSDOMConvertNumbers.cpp b/src/bun.js/bindings/webcore/JSDOMConvertNumbers.cpp index c417a37efd..d1c20179f3 100644 --- a/src/bun.js/bindings/webcore/JSDOMConvertNumbers.cpp +++ b/src/bun.js/bindings/webcore/JSDOMConvertNumbers.cpp @@ -43,7 +43,7 @@ static const int64_t kJSMaxInteger = 0x20000000000000LL - 1; // 2^53 - 1, larges static String rangeErrorString(double value, double min, double max) { - return makeString("Value ", value, " is outside the range [", min, ", ", max, ']'); + return makeString("Value "_s, value, " is outside the range ["_s, min, ", "_s, max, ']'); } static double enforceRange(JSGlobalObject& lexicalGlobalObject, double x, double minimum, double maximum) diff --git a/src/bun.js/bindings/webcore/JSDOMException.cpp b/src/bun.js/bindings/webcore/JSDOMException.cpp index 5176577550..0d6ca98497 100644 --- a/src/bun.js/bindings/webcore/JSDOMException.cpp +++ b/src/bun.js/bindings/webcore/JSDOMException.cpp @@ -306,7 +306,7 @@ void JSDOMException::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) auto* thisObject = jsCast(cell); analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); // if (thisObject->scriptExecutionContext()) - // analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + // analyzer.setLabelForCell(cell, makeString("url "_s, thisObject->scriptExecutionContext()->url().string())); Base::analyzeHeap(cell, analyzer); } @@ -343,18 +343,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj // if constexpr (std::is_polymorphic_v) { // #if ENABLE(BINDING_INTEGRITY) - // const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // // const void* actualVTablePointer = getVTablePointer(impl.ptr()); // #if PLATFORM(WIN) // void* expectedVTablePointer = __identifier("??_7DOMException@WebCore@@6B@"); // #else - // void* expectedVTablePointer = &_ZTVN7WebCore12DOMExceptionE[2]; + // // void* expectedVTablePointer = &_ZTVN7WebCore12DOMExceptionE[2]; // #endif // // If you hit this assertion you either have a use after free bug, or // // DOMException has subclasses. If DOMException has subclasses that get passed // // to toJS() we currently require DOMException you to opt out of binding hardening // // by adding the SkipVTableValidation attribute to the interface IDL definition - // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); // #endif // } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcore/JSDOMFormData.cpp b/src/bun.js/bindings/webcore/JSDOMFormData.cpp index 2bb7b0ff49..bb55ecd069 100644 --- a/src/bun.js/bindings/webcore/JSDOMFormData.cpp +++ b/src/bun.js/bindings/webcore/JSDOMFormData.cpp @@ -184,7 +184,7 @@ template<> JSValue JSDOMFormDataDOMConstructor::prototypeForStructure(JSC::VM& v return globalObject.functionPrototype(); } -extern "C" JSC::EncodedJSValue FormData__jsFunctionFromMultipartData(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe); +BUN_DECLARE_HOST_FUNCTION(FormData__jsFunctionFromMultipartData); template<> void JSDOMFormDataDOMConstructor::initializeProperties(VM& vm, JSDOMGlobalObject& globalObject) { @@ -695,7 +695,7 @@ void JSDOMFormData::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) auto* thisObject = jsCast(cell); analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); if (thisObject->scriptExecutionContext()) - analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + analyzer.setLabelForCell(cell, makeString("url "_s, thisObject->scriptExecutionContext()->url().string())); Base::analyzeHeap(cell, analyzer); } @@ -732,18 +732,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj if constexpr (std::is_polymorphic_v) { #if ENABLE(BINDING_INTEGRITY) - const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // const void* actualVTablePointer = getVTablePointer(impl.ptr()); #if PLATFORM(WIN) void* expectedVTablePointer = __identifier("??_7DOMFormData@WebCore@@6B@"); #else - void* expectedVTablePointer = &_ZTVN7WebCore11DOMFormDataE[2]; + // void* expectedVTablePointer = &_ZTVN7WebCore11DOMFormDataE[2]; #endif // If you hit this assertion you either have a use after free bug, or // DOMFormData has subclasses. If DOMFormData has subclasses that get passed // to toJS() we currently require DOMFormData you to opt out of binding hardening // by adding the SkipVTableValidation attribute to the interface IDL definition - RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); #endif } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcore/JSDOMPromiseDeferred.cpp b/src/bun.js/bindings/webcore/JSDOMPromiseDeferred.cpp index 1c63149944..f4ed3ef683 100644 --- a/src/bun.js/bindings/webcore/JSDOMPromiseDeferred.cpp +++ b/src/bun.js/bindings/webcore/JSDOMPromiseDeferred.cpp @@ -281,7 +281,7 @@ void fulfillPromiseWithArrayBuffer(Ref&& promise, ArrayBuffer* void fulfillPromiseWithArrayBuffer(Ref&& promise, const void* data, size_t length) { - fulfillPromiseWithArrayBuffer(WTFMove(promise), ArrayBuffer::tryCreate(data, length).get()); + fulfillPromiseWithArrayBuffer(WTFMove(promise), ArrayBuffer::tryCreate({ reinterpret_cast(data), length }).get()); } bool DeferredPromise::handleTerminationExceptionIfNeeded(CatchScope& scope, JSDOMGlobalObject& lexicalGlobalObject) diff --git a/src/bun.js/bindings/webcore/JSDOMURL.cpp b/src/bun.js/bindings/webcore/JSDOMURL.cpp index 755ab1bfe6..07d1e83a6a 100755 --- a/src/bun.js/bindings/webcore/JSDOMURL.cpp +++ b/src/bun.js/bindings/webcore/JSDOMURL.cpp @@ -69,8 +69,8 @@ static JSC_DECLARE_HOST_FUNCTION(jsDOMURLConstructorFunction_createObjectURL); static JSC_DECLARE_HOST_FUNCTION(jsDOMURLConstructorFunction_revokeObjectURL); static JSC_DECLARE_HOST_FUNCTION(jsDOMURLPrototypeFunction_toString); -extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__createObjectURL); -extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__revokeObjectURL); +BUN_DECLARE_HOST_FUNCTION(Bun__createObjectURL); +BUN_DECLARE_HOST_FUNCTION(Bun__revokeObjectURL); // Attributes @@ -830,18 +830,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj if constexpr (std::is_polymorphic_v) { #if ENABLE(BINDING_INTEGRITY) - const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // const void* actualVTablePointer = getVTablePointer(impl.ptr()); #if PLATFORM(WIN) void* expectedVTablePointer = __identifier("??_7DOMURL@WebCore@@6B@"); #else - void* expectedVTablePointer = &_ZTVN7WebCore6DOMURLE[2]; + // void* expectedVTablePointer = &_ZTVN7WebCore6DOMURLE[2]; #endif // If you hit this assertion you either have a use after free bug, or // DOMURL has subclasses. If DOMURL has subclasses that get passed // to toJS() we currently require DOMURL you to opt out of binding hardening // by adding the SkipVTableValidation attribute to the interface IDL definition - RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); #endif } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcore/JSErrorEvent.cpp b/src/bun.js/bindings/webcore/JSErrorEvent.cpp index 6dbf1ce8ef..6e80cddc1c 100644 --- a/src/bun.js/bindings/webcore/JSErrorEvent.cpp +++ b/src/bun.js/bindings/webcore/JSErrorEvent.cpp @@ -409,7 +409,7 @@ void JSErrorEvent::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) auto* thisObject = jsCast(cell); analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); if (thisObject->scriptExecutionContext()) - analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + analyzer.setLabelForCell(cell, makeString("url "_s, thisObject->scriptExecutionContext()->url().string())); Base::analyzeHeap(cell, analyzer); } @@ -431,18 +431,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj // if constexpr (std::is_polymorphic_v) { // #if ENABLE(BINDING_INTEGRITY) - // const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // // const void* actualVTablePointer = getVTablePointer(impl.ptr()); // #if PLATFORM(WIN) // void* expectedVTablePointer = __identifier("??_7ErrorEvent@WebCore@@6B@"); // #else - // void* expectedVTablePointer = &_ZTVN7WebCore10ErrorEventE[2]; + // // void* expectedVTablePointer = &_ZTVN7WebCore10ErrorEventE[2]; // #endif // // If you hit this assertion you either have a use after free bug, or // // ErrorEvent has subclasses. If ErrorEvent has subclasses that get passed // // to toJS() we currently require ErrorEvent you to opt out of binding hardening // // by adding the SkipVTableValidation attribute to the interface IDL definition - // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); // #endif return createWrapper(globalObject, WTFMove(impl)); } diff --git a/src/bun.js/bindings/webcore/JSEvent.cpp b/src/bun.js/bindings/webcore/JSEvent.cpp index 9acd2a25c5..988f87f73e 100644 --- a/src/bun.js/bindings/webcore/JSEvent.cpp +++ b/src/bun.js/bindings/webcore/JSEvent.cpp @@ -595,7 +595,7 @@ void JSEvent::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) auto* thisObject = jsCast(cell); analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); if (thisObject->scriptExecutionContext()) - analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + analyzer.setLabelForCell(cell, makeString("url "_s, thisObject->scriptExecutionContext()->url().string())); Base::analyzeHeap(cell, analyzer); } diff --git a/src/bun.js/bindings/webcore/JSEventEmitter.cpp b/src/bun.js/bindings/webcore/JSEventEmitter.cpp index 01d6b36ff0..964c7146d0 100644 --- a/src/bun.js/bindings/webcore/JSEventEmitter.cpp +++ b/src/bun.js/bindings/webcore/JSEventEmitter.cpp @@ -104,7 +104,7 @@ template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSEventEmitterDOMConstru ASSERT(castedThis); auto* context = castedThis->scriptExecutionContext(); if (UNLIKELY(!context)) - return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "EventEmitter"); + return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "EventEmitter"_s); auto object = EventEmitter::create(*context); if constexpr (IsExceptionOr) RETURN_IF_EXCEPTION(throwScope, {}); @@ -246,7 +246,7 @@ inline JSC::EncodedJSValue JSEventEmitter::addListener(JSC::JSGlobalObject* lexi RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); // then, add the listener - auto listener = convert>>(*lexicalGlobalObject, argument1.value(), *castedThis, [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeObjectError(lexicalGlobalObject, scope, 1, "listener", "EventEmitter", "addListener"); }); + auto listener = convert>>(*lexicalGlobalObject, argument1.value(), *castedThis, [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeObjectError(lexicalGlobalObject, scope, 1, "listener"_s, "EventEmitter"_s, "addListener"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.addListenerForBindings(WTFMove(eventType), WTFMove(listener), once, prepend); })); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); @@ -352,7 +352,7 @@ inline JSC::EncodedJSValue JSEventEmitter::removeListener(JSC::JSGlobalObject* l } EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); - auto listener = convert>>(*lexicalGlobalObject, argument1.value(), *castedThis, [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeObjectError(lexicalGlobalObject, scope, 1, "listener", "EventEmitter", "removeListener"); }); + auto listener = convert>>(*lexicalGlobalObject, argument1.value(), *castedThis, [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeObjectError(lexicalGlobalObject, scope, 1, "listener"_s, "EventEmitter"_s, "removeListener"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.removeListenerForBindings(WTFMove(eventType), WTFMove(listener)); })); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); @@ -506,7 +506,7 @@ void JSEventEmitter::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) auto* thisObject = jsCast(cell); analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); if (thisObject->scriptExecutionContext()) - analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + analyzer.setLabelForCell(cell, makeString("url "_s, thisObject->scriptExecutionContext()->url().string())); Base::analyzeHeap(cell, analyzer); } @@ -587,7 +587,7 @@ JSC_DEFINE_HOST_FUNCTION(Events_functionOnce, auto eventType = callFrame->uncheckedArgument(1).toPropertyKey(lexicalGlobalObject); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument2 = callFrame->uncheckedArgument(2); - auto listener = convert>>(*lexicalGlobalObject, argument2.value(), *argument0, [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeObjectError(lexicalGlobalObject, scope, 2, "listener", "EventEmitter", "removeListener"); }); + auto listener = convert>>(*lexicalGlobalObject, argument2.value(), *argument0, [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeObjectError(lexicalGlobalObject, scope, 2, "listener"_s, "EventEmitter"_s, "removeListener"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); vm.writeBarrier(argument0, argument2.value()); @@ -611,7 +611,7 @@ JSC_DEFINE_HOST_FUNCTION(Events_functionOn, auto eventType = callFrame->uncheckedArgument(1).toPropertyKey(lexicalGlobalObject); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument2 = callFrame->uncheckedArgument(2); - auto listener = convert>>(*lexicalGlobalObject, argument2.value(), *argument0, [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeObjectError(lexicalGlobalObject, scope, 2, "listener", "EventEmitter", "removeListener"); }); + auto listener = convert>>(*lexicalGlobalObject, argument2.value(), *argument0, [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeObjectError(lexicalGlobalObject, scope, 2, "listener"_s, "EventEmitter"_s, "removeListener"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); auto result = JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.addListenerForBindings(WTFMove(eventType), WTFMove(listener), false, false); })); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); diff --git a/src/bun.js/bindings/webcore/JSEventTarget.cpp b/src/bun.js/bindings/webcore/JSEventTarget.cpp index 34f2c5f82c..6a23f00f77 100644 --- a/src/bun.js/bindings/webcore/JSEventTarget.cpp +++ b/src/bun.js/bindings/webcore/JSEventTarget.cpp @@ -108,7 +108,7 @@ template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSEventTargetDOMConstruc ASSERT(castedThis); auto* context = castedThis->scriptExecutionContext(); if (UNLIKELY(!context)) - return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "EventTarget"); + return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "EventTarget"_s); auto object = EventTarget::create(*context); if constexpr (IsExceptionOr) RETURN_IF_EXCEPTION(throwScope, {}); @@ -218,7 +218,7 @@ static inline JSC::EncodedJSValue jsEventTargetPrototypeFunction_addEventListene auto type = convert>(*lexicalGlobalObject, argument0.value()); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); - auto listener = convert>>(*lexicalGlobalObject, argument1.value(), *castedThis, [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeObjectError(lexicalGlobalObject, scope, 1, "listener", "EventTarget", "addEventListener"); }); + auto listener = convert>>(*lexicalGlobalObject, argument1.value(), *castedThis, [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeObjectError(lexicalGlobalObject, scope, 1, "listener"_s, "EventTarget"_s, "addEventListener"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument2 = callFrame->argument(2); auto options = argument2.value().isUndefined() ? false : convert, IDLBoolean>>(*lexicalGlobalObject, argument2.value()); @@ -247,7 +247,7 @@ static inline JSC::EncodedJSValue jsEventTargetPrototypeFunction_removeEventList auto type = convert>(*lexicalGlobalObject, argument0.value()); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); - auto listener = convert>>(*lexicalGlobalObject, argument1.value(), *castedThis, [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeObjectError(lexicalGlobalObject, scope, 1, "listener", "EventTarget", "removeEventListener"); }); + auto listener = convert>>(*lexicalGlobalObject, argument1.value(), *castedThis, [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeObjectError(lexicalGlobalObject, scope, 1, "listener"_s, "EventTarget"_s, "removeEventListener"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument2 = callFrame->argument(2); auto options = argument2.value().isUndefined() ? false : convert, IDLBoolean>>(*lexicalGlobalObject, argument2.value()); @@ -273,7 +273,7 @@ static inline JSC::EncodedJSValue jsEventTargetPrototypeFunction_dispatchEventBo if (UNLIKELY(callFrame->argumentCount() < 1)) return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); - auto event = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "event", "EventTarget", "dispatchEvent", "Event"); }); + auto event = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "event"_s, "EventTarget"_s, "dispatchEvent"_s, "Event"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, impl.dispatchEventForBindings(*event)))); } @@ -320,7 +320,7 @@ void JSEventTarget::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) auto* thisObject = jsCast(cell); analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); if (thisObject->scriptExecutionContext()) - analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + analyzer.setLabelForCell(cell, makeString("url "_s, thisObject->scriptExecutionContext()->url().string())); Base::analyzeHeap(cell, analyzer); } diff --git a/src/bun.js/bindings/webcore/JSFetchHeaders.cpp b/src/bun.js/bindings/webcore/JSFetchHeaders.cpp index 0d163a0c28..f0b1cc7f5a 100644 --- a/src/bun.js/bindings/webcore/JSFetchHeaders.cpp +++ b/src/bun.js/bindings/webcore/JSFetchHeaders.cpp @@ -40,6 +40,7 @@ #include "JSDOMIterator.h" #include "JSDOMOperation.h" #include "JSDOMWrapperCache.h" +#include "JavaScriptCore/JSCJSValue.h" #include "ScriptExecutionContext.h" #include "WebCoreJSClientData.h" #include @@ -251,7 +252,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_getAll, (JSGlobalObject return JSValue::encode(array); } -JSC_DEFINE_HOST_FUNCTION(fetchHeadersGetSetCookie, (JSC::JSGlobalObject * lexicalGlobalObject, VM& vm, WebCore::FetchHeaders* impl)) +JSC::EncodedJSValue fetchHeadersGetSetCookie(JSC::JSGlobalObject* lexicalGlobalObject, VM& vm, WebCore::FetchHeaders* impl) { auto scope = DECLARE_THROW_SCOPE(vm); @@ -598,7 +599,7 @@ void JSFetchHeaders::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) auto* thisObject = jsCast(cell); analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); if (thisObject->scriptExecutionContext()) - analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + analyzer.setLabelForCell(cell, makeString("url "_s, thisObject->scriptExecutionContext()->url().string())); Base::analyzeHeap(cell, analyzer); } @@ -703,18 +704,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj { if constexpr (std::is_polymorphic_v) { #if ENABLE(BINDING_INTEGRITY) - const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // const void* actualVTablePointer = getVTablePointer(impl.ptr()); #if PLATFORM(WIN) void* expectedVTablePointer = __identifier("??_7FetchHeaders@WebCore@@6B@"); #else - void* expectedVTablePointer = &_ZTVN7WebCore12FetchHeadersE[2]; + // void* expectedVTablePointer = &_ZTVN7WebCore12FetchHeadersE[2]; #endif // If you hit this assertion you either have a use after free bug, or // FetchHeaders has subclasses. If FetchHeaders has subclasses that get passed // to toJS() we currently require FetchHeaders you to opt out of binding hardening // by adding the SkipVTableValidation attribute to the interface IDL definition - RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); #endif } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcore/JSMessageChannel.cpp b/src/bun.js/bindings/webcore/JSMessageChannel.cpp index fec8265084..316d8f808f 100644 --- a/src/bun.js/bindings/webcore/JSMessageChannel.cpp +++ b/src/bun.js/bindings/webcore/JSMessageChannel.cpp @@ -97,7 +97,7 @@ template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSMessageChannelDOMConst ASSERT(castedThis); auto* context = castedThis->scriptExecutionContext(); if (UNLIKELY(!context)) - return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "MessageChannel"); + return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "MessageChannel"_s); auto object = MessageChannel::create(*context); if constexpr (IsExceptionOr) RETURN_IF_EXCEPTION(throwScope, {}); @@ -287,18 +287,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj if constexpr (std::is_polymorphic_v) { #if ENABLE(BINDING_INTEGRITY) - const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // const void* actualVTablePointer = getVTablePointer(impl.ptr()); #if PLATFORM(WIN) void* expectedVTablePointer = __identifier("??_7MessageChannel@WebCore@@6B@"); #else - void* expectedVTablePointer = &_ZTVN7WebCore14MessageChannelE[2]; + // void* expectedVTablePointer = &_ZTVN7WebCore14MessageChannelE[2]; #endif // If you hit this assertion you either have a use after free bug, or // MessageChannel has subclasses. If MessageChannel has subclasses that get passed // to toJS() we currently require MessageChannel you to opt out of binding hardening // by adding the SkipVTableValidation attribute to the interface IDL definition - RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); #endif } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcore/JSMessageEvent.cpp b/src/bun.js/bindings/webcore/JSMessageEvent.cpp index 7d34c32ddd..7251b71e32 100644 --- a/src/bun.js/bindings/webcore/JSMessageEvent.cpp +++ b/src/bun.js/bindings/webcore/JSMessageEvent.cpp @@ -492,18 +492,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj if constexpr (std::is_polymorphic_v) { #if ENABLE(BINDING_INTEGRITY) - const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // const void* actualVTablePointer = getVTablePointer(impl.ptr()); #if PLATFORM(WIN) void* expectedVTablePointer = __identifier("??_7MessageEvent@WebCore@@6B@"); #else - void* expectedVTablePointer = &_ZTVN7WebCore12MessageEventE[2]; + // void* expectedVTablePointer = &_ZTVN7WebCore12MessageEventE[2]; #endif // If you hit this assertion you either have a use after free bug, or // MessageEvent has subclasses. If MessageEvent has subclasses that get passed // to toJS() we currently require MessageEvent you to opt out of binding hardening // by adding the SkipVTableValidation attribute to the interface IDL definition - RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); #endif } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcore/JSMessagePort.cpp b/src/bun.js/bindings/webcore/JSMessagePort.cpp index 5c4845d4ce..2e700a49b5 100644 --- a/src/bun.js/bindings/webcore/JSMessagePort.cpp +++ b/src/bun.js/bindings/webcore/JSMessagePort.cpp @@ -464,18 +464,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj if constexpr (std::is_polymorphic_v) { #if ENABLE(BINDING_INTEGRITY) - const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // const void* actualVTablePointer = getVTablePointer(impl.ptr()); #if PLATFORM(WIN) void* expectedVTablePointer = __identifier("??_7MessagePort@WebCore@@6B@"); #else - void* expectedVTablePointer = &_ZTVN7WebCore11MessagePortE[2]; + // void* expectedVTablePointer = &_ZTVN7WebCore11MessagePortE[2]; #endif // If you hit this assertion you either have a use after free bug, or // MessagePort has subclasses. If MessagePort has subclasses that get passed // to toJS() we currently require MessagePort you to opt out of binding hardening // by adding the SkipVTableValidation attribute to the interface IDL definition - RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); #endif } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcore/JSPerformance.cpp b/src/bun.js/bindings/webcore/JSPerformance.cpp index 4029dccae3..05808eab41 100644 --- a/src/bun.js/bindings/webcore/JSPerformance.cpp +++ b/src/bun.js/bindings/webcore/JSPerformance.cpp @@ -136,7 +136,7 @@ JSC_DEFINE_JIT_OPERATION(functionPerformanceNowWithoutTypeCheck, JSC::EncodedJSV CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - return functionPerformanceNowBody(lexicalGlobalObject); + return { functionPerformanceNowBody(lexicalGlobalObject) }; } // -- end copied -- @@ -641,18 +641,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj if constexpr (std::is_polymorphic_v) { #if ENABLE(BINDING_INTEGRITY) - const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // const void* actualVTablePointer = getVTablePointer(impl.ptr()); #if PLATFORM(WIN) void* expectedVTablePointer = __identifier("??_7Performance@WebCore@@6B@"); #else - void* expectedVTablePointer = &_ZTVN7WebCore11PerformanceE[2]; + // void* expectedVTablePointer = &_ZTVN7WebCore11PerformanceE[2]; #endif // If you hit this assertion you either have a use after free bug, or // Performance has subclasses. If Performance has subclasses that get passed // to toJS() we currently require Performance you to opt out of binding hardening // by adding the SkipVTableValidation attribute to the interface IDL definition - RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); #endif } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcore/JSPerformanceMark.cpp b/src/bun.js/bindings/webcore/JSPerformanceMark.cpp index 0976a04e8b..c9103dd312 100644 --- a/src/bun.js/bindings/webcore/JSPerformanceMark.cpp +++ b/src/bun.js/bindings/webcore/JSPerformanceMark.cpp @@ -46,7 +46,6 @@ #include #include - namespace WebCore { using namespace JSC; @@ -99,7 +98,7 @@ template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSPerformanceMarkDOMConstruct return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); auto* context = castedThis->scriptExecutionContext(); if (UNLIKELY(!context)) - return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "PerformanceMark"); + return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "PerformanceMark"_s); EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); auto markName = convert(*lexicalGlobalObject, argument0.value()); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); @@ -108,13 +107,13 @@ template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSPerformanceMarkDOMConstruct RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); auto object = PerformanceMark::create(*castedThis->globalObject(), *context, WTFMove(markName), WTFMove(markOptions)); if constexpr (IsExceptionOr) - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); static_assert(TypeOrExceptionOrUnderlyingType::isRef); auto jsValue = toJSNewlyCreated>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, WTFMove(object)); if constexpr (IsExceptionOr) - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); setSubclassStructureIfNeeded(lexicalGlobalObject, callFrame, asObject(jsValue)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); return JSValue::encode(jsValue); } JSC_ANNOTATE_HOST_FUNCTION(JSPerformanceMarkDOMConstructorConstruct, JSPerformanceMarkDOMConstructor::construct); @@ -137,8 +136,7 @@ template<> void JSPerformanceMarkDOMConstructor::initializeProperties(VM& vm, JS /* Hash table for prototype */ -static const HashTableValue JSPerformanceMarkPrototypeTableValues[] = -{ +static const HashTableValue JSPerformanceMarkPrototypeTableValues[] = { { "constructor"_s, static_cast(PropertyAttribute::DontEnum), NoIntrinsic, { HashTableValue::GetterSetterType, jsPerformanceMarkConstructor, 0 } }, { "detail"_s, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute, NoIntrinsic, { HashTableValue::GetterSetterType, jsPerformanceMark_detail, 0 } }, }; @@ -178,7 +176,7 @@ JSValue JSPerformanceMark::getConstructor(VM& vm, const JSGlobalObject* globalOb return getDOMConstructor(vm, *jsCast(globalObject)); } -JSC_DEFINE_CUSTOM_GETTER(jsPerformanceMarkConstructor, (JSGlobalObject* lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) +JSC_DEFINE_CUSTOM_GETTER(jsPerformanceMarkConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) { VM& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -196,24 +194,24 @@ static inline JSValue jsPerformanceMark_detailGetter(JSGlobalObject& lexicalGlob return cachedValue; auto& impl = thisObject.wrapped(); JSValue result = toJS(lexicalGlobalObject, throwScope, impl.detail(*jsCast(&lexicalGlobalObject))); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); thisObject.m_detail.set(JSC::getVM(&lexicalGlobalObject), &thisObject, result); return result; } -JSC_DEFINE_CUSTOM_GETTER(jsPerformanceMark_detail, (JSGlobalObject* lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +JSC_DEFINE_CUSTOM_GETTER(jsPerformanceMark_detail, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) { return IDLAttribute::get(*lexicalGlobalObject, thisValue, attributeName); } JSC::GCClient::IsoSubspace* JSPerformanceMark::subspaceForImpl(JSC::VM& vm) { - return WebCore::subspaceForImpl(vm, - [] (auto& spaces) { return spaces.m_clientSubspaceForPerformanceMark.get(); }, - [] (auto& spaces, auto&& space) { spaces.m_clientSubspaceForPerformanceMark = std::forward(space); }, - [] (auto& spaces) { return spaces.m_subspaceForPerformanceMark.get(); }, - [] (auto& spaces, auto&& space) { spaces.m_subspaceForPerformanceMark = std::forward(space); } - ); + return WebCore::subspaceForImpl( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForPerformanceMark.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForPerformanceMark = std::forward(space); }, + [](auto& spaces) { return spaces.m_subspaceForPerformanceMark.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForPerformanceMark = std::forward(space); }); } template @@ -238,10 +236,14 @@ void JSPerformanceMark::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) #if ENABLE(BINDING_INTEGRITY) #if PLATFORM(WIN) -#pragma warning(disable: 4483) -extern "C" { extern void (*const __identifier("??_7PerformanceMark@WebCore@@6B@")[])(); } +#pragma warning(disable : 4483) +extern "C" { +extern void (*const __identifier("??_7PerformanceMark@WebCore@@6B@")[])(); +} #else -extern "C" { extern void* _ZTVN7WebCore15PerformanceMarkE[]; } +extern "C" { +extern void* _ZTVN7WebCore15PerformanceMarkE[]; +} #endif #endif @@ -250,18 +252,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj if constexpr (std::is_polymorphic_v) { #if ENABLE(BINDING_INTEGRITY) - const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // const void* actualVTablePointer = getVTablePointer(impl.ptr()); #if PLATFORM(WIN) void* expectedVTablePointer = __identifier("??_7PerformanceMark@WebCore@@6B@"); #else - void* expectedVTablePointer = &_ZTVN7WebCore15PerformanceMarkE[2]; + // void* expectedVTablePointer = &_ZTVN7WebCore15PerformanceMarkE[2]; #endif // If you hit this assertion you either have a use after free bug, or // PerformanceMark has subclasses. If PerformanceMark has subclasses that get passed // to toJS() we currently require PerformanceMark you to opt out of binding hardening // by adding the SkipVTableValidation attribute to the interface IDL definition - RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); #endif } return createWrapper(globalObject, WTFMove(impl)); @@ -272,5 +274,4 @@ JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* g return wrap(lexicalGlobalObject, globalObject, impl); } - } diff --git a/src/bun.js/bindings/webcore/JSPerformanceObserver.cpp b/src/bun.js/bindings/webcore/JSPerformanceObserver.cpp index d266ff1e50..9068241421 100644 --- a/src/bun.js/bindings/webcore/JSPerformanceObserver.cpp +++ b/src/bun.js/bindings/webcore/JSPerformanceObserver.cpp @@ -54,7 +54,6 @@ #include #include - namespace WebCore { using namespace JSC; @@ -66,7 +65,7 @@ template<> PerformanceObserver::Init convertDictionary PerformanceObserver::Init convertDictionaryget(&lexicalGlobalObject, Identifier::fromString(vm, "buffered"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!bufferedValue.isUndefined()) { result.buffered = convert(lexicalGlobalObject, bufferedValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else result.buffered = false; JSValue entryTypesValue; @@ -86,22 +85,22 @@ template<> PerformanceObserver::Init convertDictionaryget(&lexicalGlobalObject, Identifier::fromString(vm, "entryTypes"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!entryTypesValue.isUndefined()) { result.entryTypes = convert>(lexicalGlobalObject, entryTypesValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } JSValue typeValue; if (isNullOrUndefined) typeValue = jsUndefined(); else { typeValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "type"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!typeValue.isUndefined()) { result.type = convert(lexicalGlobalObject, typeValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } return result; } @@ -153,8 +152,7 @@ using JSPerformanceObserverDOMConstructor = JSDOMConstructor(JSC::PropertyAttribute::ReadOnly), NoIntrinsic, { HashTableValue::GetterSetterType, jsPerformanceObserverConstructor_supportedEntryTypes, 0 } }, }; @@ -168,26 +166,25 @@ template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSPerformanceObserverDOMConst return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); auto* context = castedThis->scriptExecutionContext(); if (UNLIKELY(!context)) - return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "PerformanceObserver"); + return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "PerformanceObserver"_s); EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); auto callback = convert>( - *lexicalGlobalObject, - argument0.value(), - *castedThis->globalObject(), - [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { - throwArgumentMustBeFunctionError(lexicalGlobalObject, scope, 0, "callback", "PerformanceObserver", nullptr); - } - ); + *lexicalGlobalObject, + argument0.value(), + *castedThis->globalObject(), + [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { + throwArgumentMustBeFunctionError(lexicalGlobalObject, scope, 0, "callback"_s, "PerformanceObserver"_s, nullptr); + }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); auto object = PerformanceObserver::create(*context, callback.releaseNonNull()); if constexpr (IsExceptionOr) - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); static_assert(TypeOrExceptionOrUnderlyingType::isRef); auto jsValue = toJSNewlyCreated>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, WTFMove(object)); if constexpr (IsExceptionOr) - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); setSubclassStructureIfNeeded(lexicalGlobalObject, callFrame, asObject(jsValue)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); return JSValue::encode(jsValue); } JSC_ANNOTATE_HOST_FUNCTION(JSPerformanceObserverDOMConstructorConstruct, JSPerformanceObserverDOMConstructor::construct); @@ -212,8 +209,7 @@ template<> void JSPerformanceObserverDOMConstructor::initializeProperties(VM& vm /* Hash table for prototype */ -static const HashTableValue JSPerformanceObserverPrototypeTableValues[] = -{ +static const HashTableValue JSPerformanceObserverPrototypeTableValues[] = { { "constructor"_s, static_cast(PropertyAttribute::DontEnum), NoIntrinsic, { HashTableValue::GetterSetterType, jsPerformanceObserverConstructor, 0 } }, { "observe"_s, static_cast(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsPerformanceObserverPrototypeFunction_observe, 0 } }, { "disconnect"_s, static_cast(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsPerformanceObserverPrototypeFunction_disconnect, 0 } }, @@ -259,7 +255,7 @@ void JSPerformanceObserver::destroy(JSC::JSCell* cell) thisObject->JSPerformanceObserver::~JSPerformanceObserver(); } -JSC_DEFINE_CUSTOM_GETTER(jsPerformanceObserverConstructor, (JSGlobalObject* lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) +JSC_DEFINE_CUSTOM_GETTER(jsPerformanceObserverConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) { VM& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -279,7 +275,7 @@ static inline JSValue jsPerformanceObserverConstructor_supportedEntryTypesGetter RELEASE_AND_RETURN(throwScope, (toJS>(lexicalGlobalObject, *jsCast(&lexicalGlobalObject), throwScope, PerformanceObserver::supportedEntryTypes(*context)))); } -JSC_DEFINE_CUSTOM_GETTER(jsPerformanceObserverConstructor_supportedEntryTypes, (JSGlobalObject* lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +JSC_DEFINE_CUSTOM_GETTER(jsPerformanceObserverConstructor_supportedEntryTypes, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) { return IDLAttribute::getStatic(*lexicalGlobalObject, thisValue, attributeName); } @@ -297,7 +293,7 @@ static inline JSC::EncodedJSValue jsPerformanceObserverPrototypeFunction_observe RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.observe(WTFMove(options)); }))); } -JSC_DEFINE_HOST_FUNCTION(jsPerformanceObserverPrototypeFunction_observe, (JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)) +JSC_DEFINE_HOST_FUNCTION(jsPerformanceObserverPrototypeFunction_observe, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return IDLOperation::call(*lexicalGlobalObject, *callFrame, "observe"); } @@ -312,7 +308,7 @@ static inline JSC::EncodedJSValue jsPerformanceObserverPrototypeFunction_disconn RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.disconnect(); }))); } -JSC_DEFINE_HOST_FUNCTION(jsPerformanceObserverPrototypeFunction_disconnect, (JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)) +JSC_DEFINE_HOST_FUNCTION(jsPerformanceObserverPrototypeFunction_disconnect, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return IDLOperation::call(*lexicalGlobalObject, *callFrame, "disconnect"); } @@ -327,19 +323,19 @@ static inline JSC::EncodedJSValue jsPerformanceObserverPrototypeFunction_takeRec RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, impl.takeRecords()))); } -JSC_DEFINE_HOST_FUNCTION(jsPerformanceObserverPrototypeFunction_takeRecords, (JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)) +JSC_DEFINE_HOST_FUNCTION(jsPerformanceObserverPrototypeFunction_takeRecords, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return IDLOperation::call(*lexicalGlobalObject, *callFrame, "takeRecords"); } JSC::GCClient::IsoSubspace* JSPerformanceObserver::subspaceForImpl(JSC::VM& vm) { - return WebCore::subspaceForImpl(vm, - [] (auto& spaces) { return spaces.m_clientSubspaceForPerformanceObserver.get(); }, - [] (auto& spaces, auto&& space) { spaces.m_clientSubspaceForPerformanceObserver = std::forward(space); }, - [] (auto& spaces) { return spaces.m_subspaceForPerformanceObserver.get(); }, - [] (auto& spaces, auto&& space) { spaces.m_subspaceForPerformanceObserver = std::forward(space); } - ); + return WebCore::subspaceForImpl( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForPerformanceObserver.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForPerformanceObserver = std::forward(space); }, + [](auto& spaces) { return spaces.m_subspaceForPerformanceObserver.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForPerformanceObserver = std::forward(space); }); } template @@ -382,10 +378,14 @@ void JSPerformanceObserverOwner::finalize(JSC::Handle handle, void #if ENABLE(BINDING_INTEGRITY) #if PLATFORM(WIN) -#pragma warning(disable: 4483) -extern "C" { extern void (*const __identifier("??_7PerformanceObserver@WebCore@@6B@")[])(); } +#pragma warning(disable : 4483) +extern "C" { +extern void (*const __identifier("??_7PerformanceObserver@WebCore@@6B@")[])(); +} #else -extern "C" { extern void* _ZTVN7WebCore19PerformanceObserverE[]; } +extern "C" { +extern void* _ZTVN7WebCore19PerformanceObserverE[]; +} #endif #endif @@ -394,18 +394,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj if constexpr (std::is_polymorphic_v) { #if ENABLE(BINDING_INTEGRITY) - const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // const void* actualVTablePointer = getVTablePointer(impl.ptr()); #if PLATFORM(WIN) void* expectedVTablePointer = __identifier("??_7PerformanceObserver@WebCore@@6B@"); #else - void* expectedVTablePointer = &_ZTVN7WebCore19PerformanceObserverE[2]; + // void* expectedVTablePointer = &_ZTVN7WebCore19PerformanceObserverE[2]; #endif // If you hit this assertion you either have a use after free bug, or // PerformanceObserver has subclasses. If PerformanceObserver has subclasses that get passed // to toJS() we currently require PerformanceObserver you to opt out of binding hardening // by adding the SkipVTableValidation attribute to the interface IDL definition - RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); #endif } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcore/JSPerformanceObserverEntryList.cpp b/src/bun.js/bindings/webcore/JSPerformanceObserverEntryList.cpp index 69d9f998de..797d414656 100644 --- a/src/bun.js/bindings/webcore/JSPerformanceObserverEntryList.cpp +++ b/src/bun.js/bindings/webcore/JSPerformanceObserverEntryList.cpp @@ -282,18 +282,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj if constexpr (std::is_polymorphic_v) { #if ENABLE(BINDING_INTEGRITY) - const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // const void* actualVTablePointer = getVTablePointer(impl.ptr()); #if PLATFORM(WIN) void* expectedVTablePointer = __identifier("??_7PerformanceObserverEntryList@WebCore@@6B@"); #else - void* expectedVTablePointer = &_ZTVN7WebCore28PerformanceObserverEntryListE[2]; + // void* expectedVTablePointer = &_ZTVN7WebCore28PerformanceObserverEntryListE[2]; #endif // If you hit this assertion you either have a use after free bug, or // PerformanceObserverEntryList has subclasses. If PerformanceObserverEntryList has subclasses that get passed // to toJS() we currently require PerformanceObserverEntryList you to opt out of binding hardening // by adding the SkipVTableValidation attribute to the interface IDL definition - RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); #endif } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcore/JSPerformanceTiming.cpp b/src/bun.js/bindings/webcore/JSPerformanceTiming.cpp index 2e1c194ef9..9c2240cb8e 100644 --- a/src/bun.js/bindings/webcore/JSPerformanceTiming.cpp +++ b/src/bun.js/bindings/webcore/JSPerformanceTiming.cpp @@ -610,18 +610,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj if constexpr (std::is_polymorphic_v) { #if ENABLE(BINDING_INTEGRITY) - const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // const void* actualVTablePointer = getVTablePointer(impl.ptr()); #if PLATFORM(WIN) void* expectedVTablePointer = __identifier("??_7PerformanceTiming@WebCore@@6B@"); #else - void* expectedVTablePointer = &_ZTVN7WebCore17PerformanceTimingE[2]; + // void* expectedVTablePointer = &_ZTVN7WebCore17PerformanceTimingE[2]; #endif // If you hit this assertion you either have a use after free bug, or // PerformanceTiming has subclasses. If PerformanceTiming has subclasses that get passed // to toJS() we currently require PerformanceTiming you to opt out of binding hardening // by adding the SkipVTableValidation attribute to the interface IDL definition - RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); #endif } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcore/JSReadableStreamSink.cpp b/src/bun.js/bindings/webcore/JSReadableStreamSink.cpp index bd50b028d3..26e726660c 100644 --- a/src/bun.js/bindings/webcore/JSReadableStreamSink.cpp +++ b/src/bun.js/bindings/webcore/JSReadableStreamSink.cpp @@ -206,7 +206,7 @@ void JSReadableStreamSink::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) auto* thisObject = jsCast(cell); analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); if (thisObject->scriptExecutionContext()) - analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + analyzer.setLabelForCell(cell, makeString("url "_s, thisObject->scriptExecutionContext()->url().string())); Base::analyzeHeap(cell, analyzer); } diff --git a/src/bun.js/bindings/webcore/JSReadableStreamSource.cpp b/src/bun.js/bindings/webcore/JSReadableStreamSource.cpp index 860e5a770a..ff6aa2c30f 100644 --- a/src/bun.js/bindings/webcore/JSReadableStreamSource.cpp +++ b/src/bun.js/bindings/webcore/JSReadableStreamSource.cpp @@ -231,7 +231,7 @@ void JSReadableStreamSource::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) auto* thisObject = jsCast(cell); analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); if (thisObject->scriptExecutionContext()) - analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + analyzer.setLabelForCell(cell, makeString("url "_s, thisObject->scriptExecutionContext()->url().string())); Base::analyzeHeap(cell, analyzer); } diff --git a/src/bun.js/bindings/webcore/JSTextEncoder.cpp b/src/bun.js/bindings/webcore/JSTextEncoder.cpp index d35e463755..e617345166 100644 --- a/src/bun.js/bindings/webcore/JSTextEncoder.cpp +++ b/src/bun.js/bindings/webcore/JSTextEncoder.cpp @@ -257,7 +257,7 @@ JSC_DEFINE_JIT_OPERATION(jsTextEncoderEncodeWithoutTypeCheck, JSC::EncodedJSValu GCDeferralContext gcDeferralContext(vm); auto encodedValue = TextEncoder__encodeRopeString(lexicalGlobalObject, input); if (!JSC::JSValue::decode(encodedValue).isUndefined()) { - RELEASE_AND_RETURN(throwScope, encodedValue); + RELEASE_AND_RETURN(throwScope, { encodedValue }); } } @@ -270,10 +270,10 @@ JSC_DEFINE_JIT_OPERATION(jsTextEncoderEncodeWithoutTypeCheck, JSC::EncodedJSValu if (UNLIKELY(JSC::JSValue::decode(res).isObject() && JSC::JSValue::decode(res).getObject()->isErrorInstance())) { throwScope.throwException(lexicalGlobalObject, JSC::JSValue::decode(res)); - return encodedJSValue(); + return { encodedJSValue() }; } - RELEASE_AND_RETURN(throwScope, res); + RELEASE_AND_RETURN(throwScope, { res }); } JSC_DEFINE_JIT_OPERATION(jsTextEncoderPrototypeFunction_encodeIntoWithoutTypeCheck, JSC::EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, JSTextEncoder* castedThis, DOMJIT::IDLJSArgumentType sourceStr, DOMJIT::IDLJSArgumentType destination)) @@ -283,7 +283,7 @@ JSC_DEFINE_JIT_OPERATION(jsTextEncoderPrototypeFunction_encodeIntoWithoutTypeChe CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - auto source = sourceStr->value(lexicalGlobalObject); + String source = sourceStr->value(lexicalGlobalObject); size_t res = 0; if (!source.is8Bit()) { res = TextEncoder__encodeInto16(source.span16().data(), source.length(), destination->vector(), destination->byteLength()); @@ -296,7 +296,7 @@ JSC_DEFINE_JIT_OPERATION(jsTextEncoderPrototypeFunction_encodeIntoWithoutTypeChe result->putDirectOffset(vm, 0, JSC::jsNumber(static_cast(res))); result->putDirectOffset(vm, 1, JSC::jsNumber(static_cast(res >> 32))); - return JSValue::encode(result); + return { JSValue::encode(result) }; } const ClassInfo JSTextEncoderPrototype::s_info = { "TextEncoder"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTextEncoderPrototype) }; @@ -462,7 +462,7 @@ void JSTextEncoder::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) auto* thisObject = jsCast(cell); analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); if (thisObject->scriptExecutionContext()) - analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + analyzer.setLabelForCell(cell, makeString("url "_s, thisObject->scriptExecutionContext()->url().string())); Base::analyzeHeap(cell, analyzer); } @@ -499,18 +499,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj if constexpr (std::is_polymorphic_v) { #if ENABLE(BINDING_INTEGRITY) - const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // const void* actualVTablePointer = getVTablePointer(impl.ptr()); #if PLATFORM(WIN) void* expectedVTablePointer = __identifier("??_7TextEncoder@WebCore@@6B@"); #else - void* expectedVTablePointer = &_ZTVN7WebCore11TextEncoderE[2]; + // void* expectedVTablePointer = &_ZTVN7WebCore11TextEncoderE[2]; #endif // If you hit this assertion you either have a use after free bug, or // TextEncoder has subclasses. If TextEncoder has subclasses that get passed // to toJS() we currently require TextEncoder you to opt out of binding hardening // by adding the SkipVTableValidation attribute to the interface IDL definition - RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); #endif } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcore/JSURLSearchParams.cpp b/src/bun.js/bindings/webcore/JSURLSearchParams.cpp index 28ce146097..5189a2cfab 100644 --- a/src/bun.js/bindings/webcore/JSURLSearchParams.cpp +++ b/src/bun.js/bindings/webcore/JSURLSearchParams.cpp @@ -591,7 +591,7 @@ void JSURLSearchParams::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) auto* thisObject = jsCast(cell); analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); // if (thisObject->scriptExecutionContext()) - // analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + // analyzer.setLabelForCell(cell, makeString("url "_s, thisObject->scriptExecutionContext()->url().string())); Base::analyzeHeap(cell, analyzer); } @@ -628,18 +628,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj // if constexpr (std::is_polymorphic_v) { // #if ENABLE(BINDING_INTEGRITY) - // const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // // const void* actualVTablePointer = getVTablePointer(impl.ptr()); // #if PLATFORM(WIN) // void* expectedVTablePointer = __identifier("??_7URLSearchParams@WebCore@@6B@"); // #else - // void* expectedVTablePointer = &_ZTVN7WebCore15URLSearchParamsE[2]; + // // void* expectedVTablePointer = &_ZTVN7WebCore15URLSearchParamsE[2]; // #endif // // If you hit this assertion you either have a use after free bug, or // // URLSearchParams has subclasses. If URLSearchParams has subclasses that get passed // // to toJS() we currently require URLSearchParams you to opt out of binding hardening // // by adding the SkipVTableValidation attribute to the interface IDL definition - // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); // #endif // } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcore/JSWebSocket.cpp b/src/bun.js/bindings/webcore/JSWebSocket.cpp index fe5bd0edf9..8d9150036b 100644 --- a/src/bun.js/bindings/webcore/JSWebSocket.cpp +++ b/src/bun.js/bindings/webcore/JSWebSocket.cpp @@ -151,7 +151,7 @@ static inline JSC::EncodedJSValue constructJSWebSocket1(JSGlobalObject* lexicalG ASSERT(castedThis); auto* context = castedThis->scriptExecutionContext(); if (UNLIKELY(!context)) - return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "WebSocket"); + return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "WebSocket"_s); EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); auto url = convert(*lexicalGlobalObject, argument0.value()); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); @@ -178,7 +178,7 @@ static inline JSC::EncodedJSValue constructJSWebSocket2(JSGlobalObject* lexicalG ASSERT(castedThis); auto* context = castedThis->scriptExecutionContext(); if (UNLIKELY(!context)) - return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "WebSocket"); + return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "WebSocket"_s); EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); auto url = convert(*lexicalGlobalObject, argument0.value()); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); @@ -204,7 +204,7 @@ static inline JSC::EncodedJSValue constructJSWebSocket3(JSGlobalObject* lexicalG auto* globalObject = jsCast(lexicalGlobalObject); auto* context = globalObject->scriptExecutionContext(); if (UNLIKELY(!context)) - return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "WebSocket"); + return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "WebSocket"_s); auto url = convert(*lexicalGlobalObject, urlValue); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); @@ -602,7 +602,7 @@ static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_send1Body(JSC::JS UNUSED_PARAM(callFrame); auto& impl = castedThis->wrapped(); EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); - auto data = convert(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data", "WebSocket", "send", "ArrayBuffer"); }); + auto data = convert(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data"_s, "WebSocket"_s, "send"_s, "ArrayBuffer"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.send(*data); }))); } @@ -615,7 +615,7 @@ static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_send2Body(JSC::JS UNUSED_PARAM(callFrame); auto& impl = castedThis->wrapped(); EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); - auto data = convert(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data", "WebSocket", "send", "ArrayBufferView"); }); + auto data = convert(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data"_s, "WebSocket"_s, "send"_s, "ArrayBufferView"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.send(data.releaseNonNull()); }))); } @@ -628,7 +628,7 @@ static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_send2Body(JSC::JS // UNUSED_PARAM(callFrame); // auto& impl = castedThis->wrapped(); // EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); -// auto data = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data", "WebSocket", "send", "Blob"); }); +// auto data = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data"_s, "WebSocket"_s, "send"_s, "Blob"_s); }); // RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); // RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.send(*data); }))); // } @@ -710,7 +710,7 @@ static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_ping2Body(JSC::JS UNUSED_PARAM(callFrame); auto& impl = castedThis->wrapped(); EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); - auto data = convert(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data", "WebSocket", "ping", "ArrayBuffer"); }); + auto data = convert(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data"_s, "WebSocket"_s, "ping"_s, "ArrayBuffer"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.ping(*data); }))); } @@ -723,7 +723,7 @@ static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_ping3Body(JSC::JS UNUSED_PARAM(callFrame); auto& impl = castedThis->wrapped(); EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); - auto data = convert(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data", "WebSocket", "ping", "ArrayBufferView"); }); + auto data = convert(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data"_s, "WebSocket"_s, "ping"_s, "ArrayBufferView"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.ping(data.releaseNonNull()); }))); } @@ -736,7 +736,7 @@ static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_ping3Body(JSC::JS // UNUSED_PARAM(callFrame); // auto& impl = castedThis->wrapped(); // EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); -// auto data = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data", "WebSocket", "ping", "Blob"); }); +// auto data = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data"_s, "WebSocket"_s, "ping"_s, "Blob"_s); }); // RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); // RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.ping(*data); }))); // } @@ -799,7 +799,7 @@ static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_pong2Body(JSC::JS UNUSED_PARAM(callFrame); auto& impl = castedThis->wrapped(); EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); - auto data = convert(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data", "WebSocket", "pong", "ArrayBuffer"); }); + auto data = convert(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data"_s, "WebSocket"_s, "pong"_s, "ArrayBuffer"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.pong(*data); }))); } @@ -812,7 +812,7 @@ static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_pong3Body(JSC::JS UNUSED_PARAM(callFrame); auto& impl = castedThis->wrapped(); EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); - auto data = convert(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data", "WebSocket", "pong", "ArrayBufferView"); }); + auto data = convert(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data"_s, "WebSocket"_s, "pong"_s, "ArrayBufferView"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.pong(data.releaseNonNull()); }))); } @@ -825,7 +825,7 @@ static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_pong3Body(JSC::JS // UNUSED_PARAM(callFrame); // auto& impl = castedThis->wrapped(); // EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); -// auto data = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data", "WebSocket", "pong", "Blob"); }); +// auto data = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data"_s, "WebSocket"_s, "pong"_s, "Blob"_s); }); // RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); // RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.pong(*data); }))); // } @@ -900,7 +900,7 @@ void JSWebSocket::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) auto* thisObject = jsCast(cell); analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); if (thisObject->scriptExecutionContext()) - analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + analyzer.setLabelForCell(cell, makeString("url "_s, thisObject->scriptExecutionContext()->url().string())); Base::analyzeHeap(cell, analyzer); } @@ -948,18 +948,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj if constexpr (std::is_polymorphic_v) { #if ENABLE(BINDING_INTEGRITY) - const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // const void* actualVTablePointer = getVTablePointer(impl.ptr()); #if PLATFORM(WIN) void* expectedVTablePointer = __identifier("??_7WebSocket@WebCore@@6B@"); #else - void* expectedVTablePointer = &_ZTVN7WebCore9WebSocketE[2]; + // void* expectedVTablePointer = &_ZTVN7WebCore9WebSocketE[2]; #endif // If you hit this assertion you either have a use after free bug, or // WebSocket has subclasses. If WebSocket has subclasses that get passed // to toJS() we currently require WebSocket you to opt out of binding hardening // by adding the SkipVTableValidation attribute to the interface IDL definition - RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); #endif } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcore/JSWorker.cpp b/src/bun.js/bindings/webcore/JSWorker.cpp index c3e7ee16c2..968798e706 100644 --- a/src/bun.js/bindings/webcore/JSWorker.cpp +++ b/src/bun.js/bindings/webcore/JSWorker.cpp @@ -121,7 +121,7 @@ template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSWorkerDOMConstructor:: return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); auto* context = castedThis->scriptExecutionContext(); if (UNLIKELY(!context)) - return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "Worker"); + return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "Worker"_s); EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); auto scriptUrl = convert(*lexicalGlobalObject, argument0.value()); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); @@ -617,18 +617,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj if constexpr (std::is_polymorphic_v) { #if ENABLE(BINDING_INTEGRITY) - const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // const void* actualVTablePointer = getVTablePointer(impl.ptr()); #if PLATFORM(WIN) void* expectedVTablePointer = __identifier("??_7Worker@WebCore@@6B@"); #else - void* expectedVTablePointer = &_ZTVN7WebCore6WorkerE[2]; + // void* expectedVTablePointer = &_ZTVN7WebCore6WorkerE[2]; #endif // If you hit this assertion you either have a use after free bug, or // Worker has subclasses. If Worker has subclasses that get passed // to toJS() we currently require Worker you to opt out of binding hardening // by adding the SkipVTableValidation attribute to the interface IDL definition - RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); #endif } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcore/JSWritableStream.cpp b/src/bun.js/bindings/webcore/JSWritableStream.cpp index 7950c895e9..96fa7326e9 100644 --- a/src/bun.js/bindings/webcore/JSWritableStream.cpp +++ b/src/bun.js/bindings/webcore/JSWritableStream.cpp @@ -274,7 +274,7 @@ void JSWritableStream::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) auto* thisObject = jsCast(cell); analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); if (thisObject->scriptExecutionContext()) - analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + analyzer.setLabelForCell(cell, makeString("url "_s, thisObject->scriptExecutionContext()->url().string())); Base::analyzeHeap(cell, analyzer); } diff --git a/src/bun.js/bindings/webcore/JSWritableStreamSink.cpp b/src/bun.js/bindings/webcore/JSWritableStreamSink.cpp index d77165916d..617fa9b3f5 100644 --- a/src/bun.js/bindings/webcore/JSWritableStreamSink.cpp +++ b/src/bun.js/bindings/webcore/JSWritableStreamSink.cpp @@ -211,7 +211,7 @@ void JSWritableStreamSink::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) auto* thisObject = jsCast(cell); analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); if (thisObject->scriptExecutionContext()) - analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + analyzer.setLabelForCell(cell, makeString("url "_s, thisObject->scriptExecutionContext()->url().string())); Base::analyzeHeap(cell, analyzer); } diff --git a/src/bun.js/bindings/webcore/MessagePortChannel.h b/src/bun.js/bindings/webcore/MessagePortChannel.h index ebe27fd589..d50105badb 100644 --- a/src/bun.js/bindings/webcore/MessagePortChannel.h +++ b/src/bun.js/bindings/webcore/MessagePortChannel.h @@ -63,7 +63,7 @@ public: #if !LOG_DISABLED String logString() const { - return makeString(m_ports[0].logString(), ":", m_ports[1].logString()); + return makeString(m_ports[0].logString(), ":"_s, m_ports[1].logString()); } #endif diff --git a/src/bun.js/bindings/webcore/PerformanceUserTiming.cpp b/src/bun.js/bindings/webcore/PerformanceUserTiming.cpp index a375085bc4..0ea5967ec1 100644 --- a/src/bun.js/bindings/webcore/PerformanceUserTiming.cpp +++ b/src/bun.js/bindings/webcore/PerformanceUserTiming.cpp @@ -149,7 +149,7 @@ ExceptionOr PerformanceUserTiming::convertMarkToTimestamp(const String& if (iterator != m_marksMap.end()) return iterator->value.last()->startTime(); - return Exception { SyntaxError, makeString("No mark named '", mark, "' exists") }; + return Exception { SyntaxError, makeString("No mark named '"_s, mark, "' exists"_s) }; } ExceptionOr PerformanceUserTiming::convertMarkToTimestamp(double mark) const diff --git a/src/bun.js/bindings/webcore/SerializedScriptValue.cpp b/src/bun.js/bindings/webcore/SerializedScriptValue.cpp index 6d77a4cabc..e3843c0760 100644 --- a/src/bun.js/bindings/webcore/SerializedScriptValue.cpp +++ b/src/bun.js/bindings/webcore/SerializedScriptValue.cpp @@ -2420,7 +2420,7 @@ private: SerializationForStorage m_forStorage; }; -void SerializedScriptValue::writeBytesForBun(CloneSerializer* ctx, const uint8_t* data, uint32_t size) +SYSV_ABI void SerializedScriptValue::writeBytesForBun(CloneSerializer* ctx, const uint8_t* data, uint32_t size) { ctx->write(data, size); } @@ -3406,7 +3406,7 @@ private: return false; if (m_ptr + length > m_end) return false; - arrayBuffer = ArrayBuffer::tryCreate(m_ptr, length); + arrayBuffer = ArrayBuffer::tryCreate({ m_ptr, length }); if (!arrayBuffer) return false; m_ptr += length; @@ -4729,14 +4729,7 @@ private: fail(); return JSValue(); } - auto scope = DECLARE_THROW_SCOPE(m_lexicalGlobalObject->vm()); - JSValue result = JSC::JSWebAssemblyModule::createStub(m_lexicalGlobalObject->vm(), m_lexicalGlobalObject, m_globalObject->webAssemblyModuleStructure(), m_wasmModules->at(index)); - // Since we are cloning a JSWebAssemblyModule, it's impossible for that - // module to not have been a valid module. Therefore, createStub should - // not throw. - scope.releaseAssertNoException(); - m_gcBuffer.appendWithCrashOnOverflow(result); - return result; + return JSC::JSWebAssemblyModule::create(m_lexicalGlobalObject->vm(), m_globalObject->webAssemblyModuleStructure(), Ref { *m_wasmModules->at(index) }); } case WasmMemoryTag: { if (m_version >= 12) { @@ -5686,7 +5679,7 @@ Ref SerializedScriptValue::toArrayBuffer() this->ref(); auto arrayBuffer = ArrayBuffer::createFromBytes( - this->m_data.data(), this->m_data.size(), createSharedTask([protectedThis = Ref { *this }](void* p) { + { this->m_data.data(), this->m_data.size() }, createSharedTask([protectedThis = Ref { *this }](void* p) { protectedThis->deref(); })); diff --git a/src/bun.js/bindings/webcore/SerializedScriptValue.h b/src/bun.js/bindings/webcore/SerializedScriptValue.h index 5d5e93854b..3164abded7 100644 --- a/src/bun.js/bindings/webcore/SerializedScriptValue.h +++ b/src/bun.js/bindings/webcore/SerializedScriptValue.h @@ -85,7 +85,7 @@ class SerializedScriptValue : public ThreadSafeRefCounted WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(SerializedScriptValue); public: - static void writeBytesForBun(CloneSerializer*, const uint8_t*, uint32_t); + static SYSV_ABI void writeBytesForBun(CloneSerializer*, const uint8_t*, uint32_t); WEBCORE_EXPORT static ExceptionOr> create(JSC::JSGlobalObject&, JSC::JSValue, Vector>&& transfer, Vector>&, SerializationForStorage = SerializationForStorage::No, SerializationContext = SerializationContext::Default); // WEBCORE_EXPORT static ExceptionOr> create(JSC::JSGlobalObject&, JSC::JSValue, Vector>&& transfer, SerializationForStorage = SerializationForStorage::No, SerializationContext = SerializationContext::Default); diff --git a/src/bun.js/bindings/webcore/SharedBuffer.cpp b/src/bun.js/bindings/webcore/SharedBuffer.cpp index 587ed1993d..6c36f16b47 100644 --- a/src/bun.js/bindings/webcore/SharedBuffer.cpp +++ b/src/bun.js/bindings/webcore/SharedBuffer.cpp @@ -610,7 +610,7 @@ void SharedBufferBuilder::initialize(Ref&& buffer) RefPtr SharedBufferBuilder::tryCreateArrayBuffer() const { - return m_buffer ? m_buffer->tryCreateArrayBuffer() : ArrayBuffer::tryCreate(nullptr, 0); + return m_buffer ? m_buffer->tryCreateArrayBuffer() : ArrayBuffer::tryCreate({}); } Ref SharedBufferBuilder::take() @@ -626,7 +626,7 @@ Ref SharedBufferBuilder::takeAsContiguous() RefPtr SharedBufferBuilder::takeAsArrayBuffer() { if (!m_buffer) - return ArrayBuffer::tryCreate(nullptr, 0); + return ArrayBuffer::tryCreate({}); return take()->tryCreateArrayBuffer(); } diff --git a/src/bun.js/bindings/webcore/StructuredClone.cpp b/src/bun.js/bindings/webcore/StructuredClone.cpp index ec4119bb3d..088d9aa395 100644 --- a/src/bun.js/bindings/webcore/StructuredClone.cpp +++ b/src/bun.js/bindings/webcore/StructuredClone.cpp @@ -51,7 +51,7 @@ static JSC::EncodedJSValue cloneArrayBufferImpl(JSGlobalObject* lexicalGlobalObj if (!buffer) { auto scope = DECLARE_THROW_SCOPE(vm); throwDataCloneError(*lexicalGlobalObject, scope); - return { }; + return {}; } if (mode == CloneMode::Partial) { ASSERT(callFrame->argumentCount() == 3); @@ -59,15 +59,15 @@ static JSC::EncodedJSValue cloneArrayBufferImpl(JSGlobalObject* lexicalGlobalObj int srcLength = static_cast(callFrame->uncheckedArgument(2).toNumber(lexicalGlobalObject)); return JSValue::encode(JSArrayBuffer::create(lexicalGlobalObject->vm(), lexicalGlobalObject->arrayBufferStructure(ArrayBufferSharingMode::Default), buffer->slice(srcByteOffset, srcByteOffset + srcLength))); } - return JSValue::encode(JSArrayBuffer::create(lexicalGlobalObject->vm(), lexicalGlobalObject->arrayBufferStructure(ArrayBufferSharingMode::Default), ArrayBuffer::tryCreate(buffer->data(), buffer->byteLength()))); + return JSValue::encode(JSArrayBuffer::create(lexicalGlobalObject->vm(), lexicalGlobalObject->arrayBufferStructure(ArrayBufferSharingMode::Default), buffer->slice(0))); } -JSC_DEFINE_HOST_FUNCTION(cloneArrayBuffer, (JSGlobalObject* globalObject, CallFrame* callFrame)) +JSC_DEFINE_HOST_FUNCTION(cloneArrayBuffer, (JSGlobalObject * globalObject, CallFrame* callFrame)) { return cloneArrayBufferImpl(globalObject, callFrame, CloneMode::Partial); } -JSC_DEFINE_HOST_FUNCTION(structuredCloneForStream, (JSGlobalObject* globalObject, CallFrame* callFrame)) +JSC_DEFINE_HOST_FUNCTION(structuredCloneForStream, (JSGlobalObject * globalObject, CallFrame* callFrame)) { ASSERT(callFrame); ASSERT(callFrame->argumentCount()); @@ -87,16 +87,16 @@ JSC_DEFINE_HOST_FUNCTION(structuredCloneForStream, (JSGlobalObject* globalObject auto* buffer = bufferView->unsharedBuffer(); if (!buffer) { throwDataCloneError(*globalObject, scope); - return { }; + return {}; } - auto bufferClone = ArrayBuffer::tryCreate(buffer->data(), buffer->byteLength()); + auto bufferClone = buffer->slice(0); Structure* structure = bufferView->structure(); -#define CLONE_TYPED_ARRAY(name) \ - do { \ - if (bufferView->inherits()) \ - RELEASE_AND_RETURN(scope, JSValue::encode(JS##name##Array::create(globalObject, structure, WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length()))); \ - } while (0); +#define CLONE_TYPED_ARRAY(name) \ + do { \ + if (bufferView->inherits()) \ + RELEASE_AND_RETURN(scope, JSValue::encode(JS##name##Array::create(globalObject, structure, WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length()))); \ + } while (0); FOR_EACH_TYPED_ARRAY_TYPE_EXCLUDING_DATA_VIEW(CLONE_TYPED_ARRAY) @@ -107,7 +107,7 @@ JSC_DEFINE_HOST_FUNCTION(structuredCloneForStream, (JSGlobalObject* globalObject } throwTypeError(globalObject, scope, "structuredClone not implemented for non-ArrayBuffer / non-ArrayBufferView"_s); - return { }; + return {}; } } // namespace WebCore diff --git a/src/bun.js/bindings/webcore/WebSocket.cpp b/src/bun.js/bindings/webcore/WebSocket.cpp index d535e6df42..58b2d10494 100644 --- a/src/bun.js/bindings/webcore/WebSocket.cpp +++ b/src/bun.js/bindings/webcore/WebSocket.cpp @@ -125,7 +125,7 @@ static String encodeProtocolString(const String& protocol) StringBuilder builder; for (size_t i = 0; i < protocol.length(); i++) { if (protocol[i] < 0x20 || protocol[i] > 0x7E) - builder.append("\\u", hex(protocol[i], 4)); + builder.append("\\u"_s, hex(protocol[i], 4)); else if (protocol[i] == 0x5c) builder.append("\\\\"_s); else @@ -265,7 +265,7 @@ static String resourceName(const URL& url) auto path = url.path(); auto result = makeString( path, - path.isEmpty() ? "/" : "", + path.isEmpty() ? "/"_s : ""_s, url.queryWithLeadingQuestionMark()); ASSERT(!result.isEmpty()); ASSERT(!result.contains(' ')); @@ -1067,13 +1067,13 @@ void WebSocket::didReceiveBinaryData(const AtomString& eventName, const std::spa if (this->hasEventListeners(eventName)) { // the main reason for dispatching on a separate tick is to handle when you haven't yet attached an event listener this->incPendingActivityCount(); - dispatchEvent(MessageEvent::create(eventName, ArrayBuffer::create(binaryData.data(), binaryData.size()), m_url.string())); + dispatchEvent(MessageEvent::create(eventName, ArrayBuffer::create(binaryData), m_url.string())); this->decPendingActivityCount(); return; } if (auto* context = scriptExecutionContext()) { - auto arrayBuffer = JSC::ArrayBuffer::create(binaryData.data(), binaryData.size()); + auto arrayBuffer = JSC::ArrayBuffer::create(binaryData); this->incPendingActivityCount(); context->postTask([this, name = eventName, buffer = WTFMove(arrayBuffer), protectedThis = Ref { *this }](ScriptExecutionContext& context) { ASSERT(scriptExecutionContext()); @@ -1113,7 +1113,7 @@ void WebSocket::didReceiveBinaryData(const AtomString& eventName, const std::spa } if (auto* context = scriptExecutionContext()) { - auto arrayBuffer = JSC::ArrayBuffer::tryCreate(binaryData.data(), binaryData.size()); + auto arrayBuffer = JSC::ArrayBuffer::tryCreate(binaryData); this->incPendingActivityCount(); diff --git a/src/bun.js/bindings/webcore/Worker.cpp b/src/bun.js/bindings/webcore/Worker.cpp index 1c22437391..14b4d3c5f7 100644 --- a/src/bun.js/bindings/webcore/Worker.cpp +++ b/src/bun.js/bindings/webcore/Worker.cpp @@ -95,7 +95,7 @@ Worker::Worker(ScriptExecutionContext& context, WorkerOptions&& options) : EventTargetWithInlineData() , ContextDestructionObserver(&context) , m_options(WTFMove(options)) - , m_identifier("worker:" + Inspector::IdentifiersFactory::createIdentifier()) + , m_identifier(makeString("worker:"_s, Inspector::IdentifiersFactory::createIdentifier())) , m_clientIdentifier(ScriptExecutionContext::generateIdentifier()) { // static bool addedListener; diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyOKPOpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoKeyOKPOpenSSL.cpp index 462f97140a..5d5e3c2ff3 100644 --- a/src/bun.js/bindings/webcrypto/CryptoKeyOKPOpenSSL.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoKeyOKPOpenSSL.cpp @@ -46,19 +46,19 @@ std::optional CryptoKeyOKP::platformGeneratePair(CryptoAlgorithmI if (namedCurve != NamedCurve::Ed25519) return {}; - uint8_t public_key[ED25519_PUBLIC_KEY_LEN], private_key[ED25519_PRIVATE_KEY_LEN]; + Vector public_key(ED25519_PUBLIC_KEY_LEN), private_key(ED25519_PRIVATE_KEY_LEN); bool isEd25519 = identifier == CryptoAlgorithmIdentifier::Ed25519; if (isEd25519) { - ED25519_keypair(public_key, private_key); + ED25519_keypair(public_key.data(), private_key.data()); } else { - X25519_keypair(public_key, private_key); + X25519_keypair(public_key.data(), private_key.data()); } bool isPublicKeyExtractable = true; - auto publicKey = CryptoKeyOKP::create(identifier, namedCurve, CryptoKeyType::Public, Vector(public_key), isPublicKeyExtractable, usages); + auto publicKey = CryptoKeyOKP::create(identifier, namedCurve, CryptoKeyType::Public, WTFMove(public_key), isPublicKeyExtractable, usages); ASSERT(publicKey); - auto privateKey = CryptoKeyOKP::create(identifier, namedCurve, CryptoKeyType::Private, Vector(std::span { private_key, isEd25519 ? (unsigned int)ED25519_PRIVATE_KEY_LEN : (unsigned int)X25519_PRIVATE_KEY_LEN }), extractable, usages); + auto privateKey = CryptoKeyOKP::create(identifier, namedCurve, CryptoKeyType::Private, Vector(std::span { private_key.data(), isEd25519 ? (unsigned int)ED25519_PRIVATE_KEY_LEN : (unsigned int)X25519_PRIVATE_KEY_LEN }), extractable, usages); ASSERT(privateKey); return CryptoKeyPair { WTFMove(publicKey), WTFMove(privateKey) }; } diff --git a/src/bun.js/bindings/webcrypto/JSAesCbcCfbParams.cpp b/src/bun.js/bindings/webcrypto/JSAesCbcCfbParams.cpp index af0ddfda7d..04ee22b1f3 100644 --- a/src/bun.js/bindings/webcrypto/JSAesCbcCfbParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSAesCbcCfbParams.cpp @@ -30,7 +30,6 @@ #include #include - namespace WebCore { using namespace JSC; @@ -44,7 +43,7 @@ template<> CryptoAlgorithmAesCbcCfbParams convertDictionary CryptoAlgorithmAesCbcCfbParams convertDictionaryget(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "AesCbcCfbParams", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "AesCbcCfbParams"_s, "DOMString"_s); + return {}; } JSValue ivValue; if (isNullOrUndefined) ivValue = jsUndefined(); else { ivValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "iv"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!ivValue.isUndefined()) { result.iv = convert>(lexicalGlobalObject, ivValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "iv", "AesCbcCfbParams", "(ArrayBufferView or ArrayBuffer)"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "iv"_s, "AesCbcCfbParams"_s, "(ArrayBufferView or ArrayBuffer)"_s); + return {}; } return result; } diff --git a/src/bun.js/bindings/webcrypto/JSAesCtrParams.cpp b/src/bun.js/bindings/webcrypto/JSAesCtrParams.cpp index 97ce6322e4..de9ae1cd98 100644 --- a/src/bun.js/bindings/webcrypto/JSAesCtrParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSAesCtrParams.cpp @@ -31,7 +31,6 @@ #include #include - namespace WebCore { using namespace JSC; @@ -45,7 +44,7 @@ template<> CryptoAlgorithmAesCtrParams convertDictionary CryptoAlgorithmAesCtrParams convertDictionaryget(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "AesCtrParams", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "AesCtrParams"_s, "DOMString"_s); + return {}; } JSValue counterValue; if (isNullOrUndefined) counterValue = jsUndefined(); else { counterValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "counter"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!counterValue.isUndefined()) { result.counter = convert>(lexicalGlobalObject, counterValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "counter", "AesCtrParams", "(ArrayBufferView or ArrayBuffer)"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "counter"_s, "AesCtrParams"_s, "(ArrayBufferView or ArrayBuffer)"_s); + return {}; } JSValue lengthValue; if (isNullOrUndefined) lengthValue = jsUndefined(); else { lengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "length"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!lengthValue.isUndefined()) { result.length = convert>(lexicalGlobalObject, lengthValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "length", "AesCtrParams", "octet"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "length"_s, "AesCtrParams"_s, "octet"_s); + return {}; } return result; } diff --git a/src/bun.js/bindings/webcrypto/JSAesGcmParams.cpp b/src/bun.js/bindings/webcrypto/JSAesGcmParams.cpp index 7e13f82e97..02e7fd4125 100644 --- a/src/bun.js/bindings/webcrypto/JSAesGcmParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSAesGcmParams.cpp @@ -31,7 +31,6 @@ #include #include - namespace WebCore { using namespace JSC; @@ -45,7 +44,7 @@ template<> CryptoAlgorithmAesGcmParams convertDictionary CryptoAlgorithmAesGcmParams convertDictionaryget(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "AesGcmParams", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "AesGcmParams"_s, "DOMString"_s); + return {}; } JSValue additionalDataValue; if (isNullOrUndefined) additionalDataValue = jsUndefined(); else { additionalDataValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "additionalData"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!additionalDataValue.isUndefined()) { result.additionalData = convert>(lexicalGlobalObject, additionalDataValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } JSValue ivValue; if (isNullOrUndefined) ivValue = jsUndefined(); else { ivValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "iv"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!ivValue.isUndefined()) { result.iv = convert>(lexicalGlobalObject, ivValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "iv", "AesGcmParams", "(ArrayBufferView or ArrayBuffer)"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "iv"_s, "AesGcmParams"_s, "(ArrayBufferView or ArrayBuffer)"_s); + return {}; } JSValue tagLengthValue; if (isNullOrUndefined) tagLengthValue = jsUndefined(); else { tagLengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "tagLength"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!tagLengthValue.isUndefined()) { result.tagLength = convert>(lexicalGlobalObject, tagLengthValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } return result; } diff --git a/src/bun.js/bindings/webcrypto/JSAesKeyParams.cpp b/src/bun.js/bindings/webcrypto/JSAesKeyParams.cpp index 2437d14ea8..c1e84ea72f 100644 --- a/src/bun.js/bindings/webcrypto/JSAesKeyParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSAesKeyParams.cpp @@ -28,7 +28,6 @@ #include "JSDOMConvertStrings.h" #include - namespace WebCore { using namespace JSC; @@ -42,7 +41,7 @@ template<> CryptoAlgorithmAesKeyParams convertDictionary CryptoAlgorithmAesKeyParams convertDictionaryget(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "AesKeyParams", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "AesKeyParams"_s, "DOMString"_s); + return {}; } JSValue lengthValue; if (isNullOrUndefined) lengthValue = jsUndefined(); else { lengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "length"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!lengthValue.isUndefined()) { result.length = convert>(lexicalGlobalObject, lengthValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "length", "AesKeyParams", "unsigned short"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "length"_s, "AesKeyParams"_s, "unsigned short"_s); + return {}; } return result; } diff --git a/src/bun.js/bindings/webcrypto/JSCryptoAesKeyAlgorithm.cpp b/src/bun.js/bindings/webcrypto/JSCryptoAesKeyAlgorithm.cpp index 3f7568947b..64227c786d 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoAesKeyAlgorithm.cpp +++ b/src/bun.js/bindings/webcrypto/JSCryptoAesKeyAlgorithm.cpp @@ -30,7 +30,6 @@ #include #include - namespace WebCore { using namespace JSC; @@ -44,7 +43,7 @@ template<> CryptoAesKeyAlgorithm convertDictionary(JSGlob auto* object = isNullOrUndefined ? nullptr : value.getObject(); if (UNLIKELY(!isNullOrUndefined && !object)) { throwTypeError(&lexicalGlobalObject, throwScope); - return { }; + return {}; } CryptoAesKeyAlgorithm result; JSValue nameValue; @@ -52,28 +51,28 @@ template<> CryptoAesKeyAlgorithm convertDictionary(JSGlob nameValue = jsUndefined(); else { nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "CryptoAesKeyAlgorithm", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "CryptoAesKeyAlgorithm"_s, "DOMString"_s); + return {}; } JSValue lengthValue; if (isNullOrUndefined) lengthValue = jsUndefined(); else { lengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "length"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!lengthValue.isUndefined()) { result.length = convert(lexicalGlobalObject, lengthValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "length", "CryptoAesKeyAlgorithm", "unsigned short"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "length"_s, "CryptoAesKeyAlgorithm"_s, "unsigned short"_s); + return {}; } return result; } @@ -86,10 +85,10 @@ JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, J auto result = constructEmptyObject(&lexicalGlobalObject, globalObject.objectPrototype()); auto nameValue = toJS(lexicalGlobalObject, throwScope, dictionary.name); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); result->putDirect(vm, JSC::Identifier::fromString(vm, "name"_s), nameValue); auto lengthValue = toJS(lexicalGlobalObject, throwScope, dictionary.length); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); result->putDirect(vm, JSC::Identifier::fromString(vm, "length"_s), lengthValue); return result; } diff --git a/src/bun.js/bindings/webcrypto/JSCryptoAlgorithmParameters.cpp b/src/bun.js/bindings/webcrypto/JSCryptoAlgorithmParameters.cpp index 2ac46f90e7..93b9590340 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoAlgorithmParameters.cpp +++ b/src/bun.js/bindings/webcrypto/JSCryptoAlgorithmParameters.cpp @@ -54,7 +54,7 @@ template<> CryptoAlgorithmParameters convertDictionary(lexicalGlobalObject, nameValue); RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "CryptoAlgorithmParameters", "DOMString"); + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "CryptoAlgorithmParameters"_s, "DOMString"_s); return {}; } return result; diff --git a/src/bun.js/bindings/webcrypto/JSCryptoEcKeyAlgorithm.cpp b/src/bun.js/bindings/webcrypto/JSCryptoEcKeyAlgorithm.cpp index e63283c97e..dbf828497f 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoEcKeyAlgorithm.cpp +++ b/src/bun.js/bindings/webcrypto/JSCryptoEcKeyAlgorithm.cpp @@ -29,7 +29,6 @@ #include #include - namespace WebCore { using namespace JSC; @@ -43,7 +42,7 @@ template<> CryptoEcKeyAlgorithm convertDictionary(JSGlobal auto* object = isNullOrUndefined ? nullptr : value.getObject(); if (UNLIKELY(!isNullOrUndefined && !object)) { throwTypeError(&lexicalGlobalObject, throwScope); - return { }; + return {}; } CryptoEcKeyAlgorithm result; JSValue nameValue; @@ -51,28 +50,28 @@ template<> CryptoEcKeyAlgorithm convertDictionary(JSGlobal nameValue = jsUndefined(); else { nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "CryptoEcKeyAlgorithm", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "CryptoEcKeyAlgorithm"_s, "DOMString"_s); + return {}; } JSValue namedCurveValue; if (isNullOrUndefined) namedCurveValue = jsUndefined(); else { namedCurveValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "namedCurve"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!namedCurveValue.isUndefined()) { result.namedCurve = convert(lexicalGlobalObject, namedCurveValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "namedCurve", "CryptoEcKeyAlgorithm", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "namedCurve"_s, "CryptoEcKeyAlgorithm"_s, "DOMString"_s); + return {}; } return result; } @@ -85,10 +84,10 @@ JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, J auto result = constructEmptyObject(&lexicalGlobalObject, globalObject.objectPrototype()); auto nameValue = toJS(lexicalGlobalObject, throwScope, dictionary.name); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); result->putDirect(vm, JSC::Identifier::fromString(vm, "name"_s), nameValue); auto namedCurveValue = toJS(lexicalGlobalObject, throwScope, dictionary.namedCurve); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); result->putDirect(vm, JSC::Identifier::fromString(vm, "namedCurve"_s), namedCurveValue); return result; } diff --git a/src/bun.js/bindings/webcrypto/JSCryptoHmacKeyAlgorithm.cpp b/src/bun.js/bindings/webcrypto/JSCryptoHmacKeyAlgorithm.cpp index 850eeb2aa9..7a3f7811bf 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoHmacKeyAlgorithm.cpp +++ b/src/bun.js/bindings/webcrypto/JSCryptoHmacKeyAlgorithm.cpp @@ -31,7 +31,6 @@ #include #include - namespace WebCore { using namespace JSC; @@ -45,7 +44,7 @@ template<> CryptoHmacKeyAlgorithm convertDictionary(JSGl auto* object = isNullOrUndefined ? nullptr : value.getObject(); if (UNLIKELY(!isNullOrUndefined && !object)) { throwTypeError(&lexicalGlobalObject, throwScope); - return { }; + return {}; } CryptoHmacKeyAlgorithm result; JSValue nameValue; @@ -53,42 +52,42 @@ template<> CryptoHmacKeyAlgorithm convertDictionary(JSGl nameValue = jsUndefined(); else { nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "CryptoHmacKeyAlgorithm", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "CryptoHmacKeyAlgorithm"_s, "DOMString"_s); + return {}; } JSValue hashValue; if (isNullOrUndefined) hashValue = jsUndefined(); else { hashValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "hash"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!hashValue.isUndefined()) { result.hash = convert>(lexicalGlobalObject, hashValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash", "CryptoHmacKeyAlgorithm", "CryptoKeyAlgorithm"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash"_s, "CryptoHmacKeyAlgorithm"_s, "CryptoKeyAlgorithm"_s); + return {}; } JSValue lengthValue; if (isNullOrUndefined) lengthValue = jsUndefined(); else { lengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "length"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!lengthValue.isUndefined()) { result.length = convert(lexicalGlobalObject, lengthValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "length", "CryptoHmacKeyAlgorithm", "unsigned long"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "length"_s, "CryptoHmacKeyAlgorithm"_s, "unsigned long"_s); + return {}; } return result; } @@ -101,13 +100,13 @@ JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, J auto result = constructEmptyObject(&lexicalGlobalObject, globalObject.objectPrototype()); auto nameValue = toJS(lexicalGlobalObject, throwScope, dictionary.name); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); result->putDirect(vm, JSC::Identifier::fromString(vm, "name"_s), nameValue); auto hashValue = toJS>(lexicalGlobalObject, globalObject, throwScope, dictionary.hash); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); result->putDirect(vm, JSC::Identifier::fromString(vm, "hash"_s), hashValue); auto lengthValue = toJS(lexicalGlobalObject, throwScope, dictionary.length); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); result->putDirect(vm, JSC::Identifier::fromString(vm, "length"_s), lengthValue); return result; } diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKey.cpp b/src/bun.js/bindings/webcrypto/JSCryptoKey.cpp index cacea23e79..1d3d32e668 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoKey.cpp +++ b/src/bun.js/bindings/webcrypto/JSCryptoKey.cpp @@ -98,9 +98,9 @@ template<> std::optional parseEnumeration(JSGl return std::nullopt; } -template<> const char* expectedEnumerationValues() +template<> ASCIILiteral expectedEnumerationValues() { - return "\"public\", \"private\", \"secret\""; + return "\"public\", \"private\", \"secret\""_s; } // Attributes @@ -318,7 +318,7 @@ void JSCryptoKey::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) auto* thisObject = jsCast(cell); analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); if (thisObject->scriptExecutionContext()) - analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + analyzer.setLabelForCell(cell, makeString("url "_s, thisObject->scriptExecutionContext()->url().string())); Base::analyzeHeap(cell, analyzer); } diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKey.h b/src/bun.js/bindings/webcrypto/JSCryptoKey.h index 0a977f6f90..af09c01381 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoKey.h +++ b/src/bun.js/bindings/webcrypto/JSCryptoKey.h @@ -101,7 +101,7 @@ String convertEnumerationToString(CryptoKey::Type); template<> JSC::JSString* convertEnumerationToJS(JSC::JSGlobalObject&, CryptoKey::Type); template<> std::optional parseEnumeration(JSC::JSGlobalObject&, JSC::JSValue); -template<> const char* expectedEnumerationValues(); +template<> ASCIILiteral expectedEnumerationValues(); } // namespace WebCore diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKeyAlgorithm.cpp b/src/bun.js/bindings/webcrypto/JSCryptoKeyAlgorithm.cpp index c7009a16da..f192e0967a 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoKeyAlgorithm.cpp +++ b/src/bun.js/bindings/webcrypto/JSCryptoKeyAlgorithm.cpp @@ -29,7 +29,6 @@ #include #include - namespace WebCore { using namespace JSC; @@ -43,7 +42,7 @@ template<> CryptoKeyAlgorithm convertDictionary(JSGlobalObje auto* object = isNullOrUndefined ? nullptr : value.getObject(); if (UNLIKELY(!isNullOrUndefined && !object)) { throwTypeError(&lexicalGlobalObject, throwScope); - return { }; + return {}; } CryptoKeyAlgorithm result; JSValue nameValue; @@ -51,14 +50,14 @@ template<> CryptoKeyAlgorithm convertDictionary(JSGlobalObje nameValue = jsUndefined(); else { nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "CryptoKeyAlgorithm", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "CryptoKeyAlgorithm"_s, "DOMString"_s); + return {}; } return result; } @@ -71,7 +70,7 @@ JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, J auto result = constructEmptyObject(&lexicalGlobalObject, globalObject.objectPrototype()); auto nameValue = toJS(lexicalGlobalObject, throwScope, dictionary.name); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); result->putDirect(vm, JSC::Identifier::fromString(vm, "name"_s), nameValue); return result; } diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKeyUsage.cpp b/src/bun.js/bindings/webcrypto/JSCryptoKeyUsage.cpp index 2e5e36cae5..d749d879c2 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoKeyUsage.cpp +++ b/src/bun.js/bindings/webcrypto/JSCryptoKeyUsage.cpp @@ -80,9 +80,9 @@ template<> std::optional parseEnumeration(JSGlob return std::nullopt; } -template<> const char* expectedEnumerationValues() +template<> ASCIILiteral expectedEnumerationValues() { - return "\"encrypt\", \"decrypt\", \"sign\", \"verify\", \"deriveKey\", \"deriveBits\", \"wrapKey\", \"unwrapKey\""; + return "\"encrypt\", \"decrypt\", \"sign\", \"verify\", \"deriveKey\", \"deriveBits\", \"wrapKey\", \"unwrapKey\""_s; } } // namespace WebCore diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKeyUsage.h b/src/bun.js/bindings/webcrypto/JSCryptoKeyUsage.h index 7119cf1d12..1c2d280943 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoKeyUsage.h +++ b/src/bun.js/bindings/webcrypto/JSCryptoKeyUsage.h @@ -31,7 +31,7 @@ String convertEnumerationToString(CryptoKeyUsage); template<> JSC::JSString* convertEnumerationToJS(JSC::JSGlobalObject&, CryptoKeyUsage); template<> std::optional parseEnumeration(JSC::JSGlobalObject&, JSC::JSValue); -template<> const char* expectedEnumerationValues(); +template<> ASCIILiteral expectedEnumerationValues(); } // namespace WebCore diff --git a/src/bun.js/bindings/webcrypto/JSCryptoRsaHashedKeyAlgorithm.cpp b/src/bun.js/bindings/webcrypto/JSCryptoRsaHashedKeyAlgorithm.cpp index 2a2cdb8a23..11bc28258f 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoRsaHashedKeyAlgorithm.cpp +++ b/src/bun.js/bindings/webcrypto/JSCryptoRsaHashedKeyAlgorithm.cpp @@ -32,7 +32,6 @@ #include #include - namespace WebCore { using namespace JSC; @@ -46,7 +45,7 @@ template<> CryptoRsaHashedKeyAlgorithm convertDictionary CryptoRsaHashedKeyAlgorithm convertDictionaryget(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "CryptoRsaHashedKeyAlgorithm", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "CryptoRsaHashedKeyAlgorithm"_s, "DOMString"_s); + return {}; } JSValue modulusLengthValue; if (isNullOrUndefined) modulusLengthValue = jsUndefined(); else { modulusLengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "modulusLength"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!modulusLengthValue.isUndefined()) { result.modulusLength = convert(lexicalGlobalObject, modulusLengthValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "modulusLength", "CryptoRsaHashedKeyAlgorithm", "unsigned long"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "modulusLength"_s, "CryptoRsaHashedKeyAlgorithm"_s, "unsigned long"_s); + return {}; } JSValue publicExponentValue; if (isNullOrUndefined) publicExponentValue = jsUndefined(); else { publicExponentValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "publicExponent"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!publicExponentValue.isUndefined()) { result.publicExponent = convert(lexicalGlobalObject, publicExponentValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "publicExponent", "CryptoRsaHashedKeyAlgorithm", "Uint8Array"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "publicExponent"_s, "CryptoRsaHashedKeyAlgorithm"_s, "Uint8Array"_s); + return {}; } JSValue hashValue; if (isNullOrUndefined) hashValue = jsUndefined(); else { hashValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "hash"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!hashValue.isUndefined()) { result.hash = convert>(lexicalGlobalObject, hashValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash", "CryptoRsaHashedKeyAlgorithm", "CryptoKeyAlgorithm"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash"_s, "CryptoRsaHashedKeyAlgorithm"_s, "CryptoKeyAlgorithm"_s); + return {}; } return result; } @@ -116,16 +115,16 @@ JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, J auto result = constructEmptyObject(&lexicalGlobalObject, globalObject.objectPrototype()); auto nameValue = toJS(lexicalGlobalObject, throwScope, dictionary.name); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); result->putDirect(vm, JSC::Identifier::fromString(vm, "name"_s), nameValue); auto modulusLengthValue = toJS(lexicalGlobalObject, throwScope, dictionary.modulusLength); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); result->putDirect(vm, JSC::Identifier::fromString(vm, "modulusLength"_s), modulusLengthValue); auto publicExponentValue = toJS(lexicalGlobalObject, globalObject, throwScope, dictionary.publicExponent); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); result->putDirect(vm, JSC::Identifier::fromString(vm, "publicExponent"_s), publicExponentValue); auto hashValue = toJS>(lexicalGlobalObject, globalObject, throwScope, dictionary.hash); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); result->putDirect(vm, JSC::Identifier::fromString(vm, "hash"_s), hashValue); return result; } diff --git a/src/bun.js/bindings/webcrypto/JSCryptoRsaKeyAlgorithm.cpp b/src/bun.js/bindings/webcrypto/JSCryptoRsaKeyAlgorithm.cpp index 79407e27fb..7cee62daf9 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoRsaKeyAlgorithm.cpp +++ b/src/bun.js/bindings/webcrypto/JSCryptoRsaKeyAlgorithm.cpp @@ -31,7 +31,6 @@ #include #include - namespace WebCore { using namespace JSC; @@ -45,7 +44,7 @@ template<> CryptoRsaKeyAlgorithm convertDictionary(JSGlob auto* object = isNullOrUndefined ? nullptr : value.getObject(); if (UNLIKELY(!isNullOrUndefined && !object)) { throwTypeError(&lexicalGlobalObject, throwScope); - return { }; + return {}; } CryptoRsaKeyAlgorithm result; JSValue nameValue; @@ -53,42 +52,42 @@ template<> CryptoRsaKeyAlgorithm convertDictionary(JSGlob nameValue = jsUndefined(); else { nameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "CryptoRsaKeyAlgorithm", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "CryptoRsaKeyAlgorithm"_s, "DOMString"_s); + return {}; } JSValue modulusLengthValue; if (isNullOrUndefined) modulusLengthValue = jsUndefined(); else { modulusLengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "modulusLength"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!modulusLengthValue.isUndefined()) { result.modulusLength = convert(lexicalGlobalObject, modulusLengthValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "modulusLength", "CryptoRsaKeyAlgorithm", "unsigned long"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "modulusLength"_s, "CryptoRsaKeyAlgorithm"_s, "unsigned long"_s); + return {}; } JSValue publicExponentValue; if (isNullOrUndefined) publicExponentValue = jsUndefined(); else { publicExponentValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "publicExponent"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!publicExponentValue.isUndefined()) { result.publicExponent = convert(lexicalGlobalObject, publicExponentValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "publicExponent", "CryptoRsaKeyAlgorithm", "Uint8Array"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "publicExponent"_s, "CryptoRsaKeyAlgorithm"_s, "Uint8Array"_s); + return {}; } return result; } @@ -101,13 +100,13 @@ JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, J auto result = constructEmptyObject(&lexicalGlobalObject, globalObject.objectPrototype()); auto nameValue = toJS(lexicalGlobalObject, throwScope, dictionary.name); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); result->putDirect(vm, JSC::Identifier::fromString(vm, "name"_s), nameValue); auto modulusLengthValue = toJS(lexicalGlobalObject, throwScope, dictionary.modulusLength); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); result->putDirect(vm, JSC::Identifier::fromString(vm, "modulusLength"_s), modulusLengthValue); auto publicExponentValue = toJS(lexicalGlobalObject, globalObject, throwScope, dictionary.publicExponent); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); result->putDirect(vm, JSC::Identifier::fromString(vm, "publicExponent"_s), publicExponentValue); return result; } diff --git a/src/bun.js/bindings/webcrypto/JSEcKeyParams.cpp b/src/bun.js/bindings/webcrypto/JSEcKeyParams.cpp index 51fcfb966d..26d6b6f901 100644 --- a/src/bun.js/bindings/webcrypto/JSEcKeyParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSEcKeyParams.cpp @@ -27,7 +27,6 @@ #include "JSDOMConvertStrings.h" #include - namespace WebCore { using namespace JSC; @@ -41,7 +40,7 @@ template<> CryptoAlgorithmEcKeyParams convertDictionary CryptoAlgorithmEcKeyParams convertDictionaryget(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "EcKeyParams", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "EcKeyParams"_s, "DOMString"_s); + return {}; } JSValue namedCurveValue; if (isNullOrUndefined) namedCurveValue = jsUndefined(); else { namedCurveValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "namedCurve"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!namedCurveValue.isUndefined()) { result.namedCurve = convert(lexicalGlobalObject, namedCurveValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "namedCurve", "EcKeyParams", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "namedCurve"_s, "EcKeyParams"_s, "DOMString"_s); + return {}; } return result; } diff --git a/src/bun.js/bindings/webcrypto/JSEcdhKeyDeriveParams.cpp b/src/bun.js/bindings/webcrypto/JSEcdhKeyDeriveParams.cpp index 9005a34ff1..0bd0bf9d3e 100644 --- a/src/bun.js/bindings/webcrypto/JSEcdhKeyDeriveParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSEcdhKeyDeriveParams.cpp @@ -29,7 +29,6 @@ #include "JSDOMConvertStrings.h" #include - namespace WebCore { using namespace JSC; @@ -43,7 +42,7 @@ template<> CryptoAlgorithmEcdhKeyDeriveParams convertDictionary CryptoAlgorithmEcdhKeyDeriveParams convertDictionaryget(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "EcdhKeyDeriveParams", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "EcdhKeyDeriveParams"_s, "DOMString"_s); + return {}; } JSValue publicKeyValue; if (isNullOrUndefined) publicKeyValue = jsUndefined(); else { publicKeyValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "publicKey"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!publicKeyValue.isUndefined()) { result.publicKey = convert>(lexicalGlobalObject, publicKeyValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "publicKey", "EcdhKeyDeriveParams", "CryptoKey"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "publicKey"_s, "EcdhKeyDeriveParams"_s, "CryptoKey"_s); + return {}; } return result; } diff --git a/src/bun.js/bindings/webcrypto/JSEcdsaParams.cpp b/src/bun.js/bindings/webcrypto/JSEcdsaParams.cpp index 700b30e6ee..9fb39e31b1 100644 --- a/src/bun.js/bindings/webcrypto/JSEcdsaParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSEcdsaParams.cpp @@ -30,7 +30,6 @@ #include #include - namespace WebCore { using namespace JSC; @@ -44,7 +43,7 @@ template<> CryptoAlgorithmEcdsaParams convertDictionary CryptoAlgorithmEcdsaParams convertDictionaryget(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "EcdsaParams", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "EcdsaParams"_s, "DOMString"_s); + return {}; } JSValue hashValue; if (isNullOrUndefined) hashValue = jsUndefined(); else { hashValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "hash"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!hashValue.isUndefined()) { result.hash = convert>(lexicalGlobalObject, hashValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash", "EcdsaParams", "(object or DOMString)"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash"_s, "EcdsaParams"_s, "(object or DOMString)"_s); + return {}; } return result; } diff --git a/src/bun.js/bindings/webcrypto/JSHkdfParams.cpp b/src/bun.js/bindings/webcrypto/JSHkdfParams.cpp index 3b68fa3de4..1cde2096c6 100644 --- a/src/bun.js/bindings/webcrypto/JSHkdfParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSHkdfParams.cpp @@ -31,7 +31,6 @@ #include #include - namespace WebCore { using namespace JSC; @@ -45,7 +44,7 @@ template<> CryptoAlgorithmHkdfParams convertDictionary CryptoAlgorithmHkdfParams convertDictionaryget(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "HkdfParams", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "HkdfParams"_s, "DOMString"_s); + return {}; } JSValue hashValue; if (isNullOrUndefined) hashValue = jsUndefined(); else { hashValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "hash"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!hashValue.isUndefined()) { result.hash = convert>(lexicalGlobalObject, hashValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash", "HkdfParams", "(object or DOMString)"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash"_s, "HkdfParams"_s, "(object or DOMString)"_s); + return {}; } JSValue infoValue; if (isNullOrUndefined) infoValue = jsUndefined(); else { infoValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "info"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!infoValue.isUndefined()) { result.info = convert>(lexicalGlobalObject, infoValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "info", "HkdfParams", "(ArrayBufferView or ArrayBuffer)"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "info"_s, "HkdfParams"_s, "(ArrayBufferView or ArrayBuffer)"_s); + return {}; } JSValue saltValue; if (isNullOrUndefined) saltValue = jsUndefined(); else { saltValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "salt"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!saltValue.isUndefined()) { result.salt = convert>(lexicalGlobalObject, saltValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "salt", "HkdfParams", "(ArrayBufferView or ArrayBuffer)"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "salt"_s, "HkdfParams"_s, "(ArrayBufferView or ArrayBuffer)"_s); + return {}; } return result; } diff --git a/src/bun.js/bindings/webcrypto/JSHmacKeyParams.cpp b/src/bun.js/bindings/webcrypto/JSHmacKeyParams.cpp index 2debe24091..00318802c5 100644 --- a/src/bun.js/bindings/webcrypto/JSHmacKeyParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSHmacKeyParams.cpp @@ -31,7 +31,6 @@ #include #include - namespace WebCore { using namespace JSC; @@ -45,7 +44,7 @@ template<> CryptoAlgorithmHmacKeyParams convertDictionary CryptoAlgorithmHmacKeyParams convertDictionaryget(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "HmacKeyParams", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "HmacKeyParams"_s, "DOMString"_s); + return {}; } JSValue hashValue; if (isNullOrUndefined) hashValue = jsUndefined(); else { hashValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "hash"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!hashValue.isUndefined()) { result.hash = convert>(lexicalGlobalObject, hashValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash", "HmacKeyParams", "(object or DOMString)"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash"_s, "HmacKeyParams"_s, "(object or DOMString)"_s); + return {}; } JSValue lengthValue; if (isNullOrUndefined) lengthValue = jsUndefined(); else { lengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "length"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!lengthValue.isUndefined()) { result.length = convert>(lexicalGlobalObject, lengthValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } return result; } diff --git a/src/bun.js/bindings/webcrypto/JSJsonWebKey.cpp b/src/bun.js/bindings/webcrypto/JSJsonWebKey.cpp index 9bb2644b58..1f7847fc9d 100644 --- a/src/bun.js/bindings/webcrypto/JSJsonWebKey.cpp +++ b/src/bun.js/bindings/webcrypto/JSJsonWebKey.cpp @@ -161,7 +161,7 @@ template<> JsonWebKey convertDictionary(JSGlobalObject& lexicalGloba result.kty = convert(lexicalGlobalObject, ktyValue); RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "kty", "JsonWebKey", "DOMString"); + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "kty"_s, "JsonWebKey"_s, "DOMString"_s); return {}; } JSValue nValue; diff --git a/src/bun.js/bindings/webcrypto/JSPbkdf2Params.cpp b/src/bun.js/bindings/webcrypto/JSPbkdf2Params.cpp index 871d8ffd97..99f7d04a2b 100644 --- a/src/bun.js/bindings/webcrypto/JSPbkdf2Params.cpp +++ b/src/bun.js/bindings/webcrypto/JSPbkdf2Params.cpp @@ -32,7 +32,6 @@ #include #include - namespace WebCore { using namespace JSC; @@ -46,7 +45,7 @@ template<> CryptoAlgorithmPbkdf2Params convertDictionary CryptoAlgorithmPbkdf2Params convertDictionaryget(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "Pbkdf2Params", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "Pbkdf2Params"_s, "DOMString"_s); + return {}; } JSValue hashValue; if (isNullOrUndefined) hashValue = jsUndefined(); else { hashValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "hash"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!hashValue.isUndefined()) { result.hash = convert>(lexicalGlobalObject, hashValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash", "Pbkdf2Params", "(object or DOMString)"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash"_s, "Pbkdf2Params"_s, "(object or DOMString)"_s); + return {}; } JSValue iterationsValue; if (isNullOrUndefined) iterationsValue = jsUndefined(); else { iterationsValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "iterations"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!iterationsValue.isUndefined()) { result.iterations = convert>(lexicalGlobalObject, iterationsValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "iterations", "Pbkdf2Params", "unsigned long"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "iterations"_s, "Pbkdf2Params"_s, "unsigned long"_s); + return {}; } JSValue saltValue; if (isNullOrUndefined) saltValue = jsUndefined(); else { saltValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "salt"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!saltValue.isUndefined()) { result.salt = convert>(lexicalGlobalObject, saltValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "salt", "Pbkdf2Params", "(ArrayBufferView or ArrayBuffer)"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "salt"_s, "Pbkdf2Params"_s, "(ArrayBufferView or ArrayBuffer)"_s); + return {}; } return result; } diff --git a/src/bun.js/bindings/webcrypto/JSRsaHashedImportParams.cpp b/src/bun.js/bindings/webcrypto/JSRsaHashedImportParams.cpp index e48fba0fdf..9d9e5532b8 100644 --- a/src/bun.js/bindings/webcrypto/JSRsaHashedImportParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSRsaHashedImportParams.cpp @@ -30,7 +30,6 @@ #include #include - namespace WebCore { using namespace JSC; @@ -44,7 +43,7 @@ template<> CryptoAlgorithmRsaHashedImportParams convertDictionary CryptoAlgorithmRsaHashedImportParams convertDictionaryget(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "RsaHashedImportParams", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "RsaHashedImportParams"_s, "DOMString"_s); + return {}; } JSValue hashValue; if (isNullOrUndefined) hashValue = jsUndefined(); else { hashValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "hash"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!hashValue.isUndefined()) { result.hash = convert>(lexicalGlobalObject, hashValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash", "RsaHashedImportParams", "(object or DOMString)"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash"_s, "RsaHashedImportParams"_s, "(object or DOMString)"_s); + return {}; } return result; } diff --git a/src/bun.js/bindings/webcrypto/JSRsaHashedKeyGenParams.cpp b/src/bun.js/bindings/webcrypto/JSRsaHashedKeyGenParams.cpp index c5abfe52a3..f7f10165bf 100644 --- a/src/bun.js/bindings/webcrypto/JSRsaHashedKeyGenParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSRsaHashedKeyGenParams.cpp @@ -32,7 +32,6 @@ #include #include - namespace WebCore { using namespace JSC; @@ -46,7 +45,7 @@ template<> CryptoAlgorithmRsaHashedKeyGenParams convertDictionary CryptoAlgorithmRsaHashedKeyGenParams convertDictionaryget(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "RsaHashedKeyGenParams", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "RsaHashedKeyGenParams"_s, "DOMString"_s); + return {}; } JSValue modulusLengthValue; if (isNullOrUndefined) modulusLengthValue = jsUndefined(); else { modulusLengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "modulusLength"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!modulusLengthValue.isUndefined()) { result.modulusLength = convert>(lexicalGlobalObject, modulusLengthValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "modulusLength", "RsaHashedKeyGenParams", "unsigned long"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "modulusLength"_s, "RsaHashedKeyGenParams"_s, "unsigned long"_s); + return {}; } JSValue publicExponentValue; if (isNullOrUndefined) publicExponentValue = jsUndefined(); else { publicExponentValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "publicExponent"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!publicExponentValue.isUndefined()) { result.publicExponent = convert(lexicalGlobalObject, publicExponentValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "publicExponent", "RsaHashedKeyGenParams", "Uint8Array"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "publicExponent"_s, "RsaHashedKeyGenParams"_s, "Uint8Array"_s); + return {}; } JSValue hashValue; if (isNullOrUndefined) hashValue = jsUndefined(); else { hashValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "hash"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!hashValue.isUndefined()) { result.hash = convert>(lexicalGlobalObject, hashValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash", "RsaHashedKeyGenParams", "(object or DOMString)"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "hash"_s, "RsaHashedKeyGenParams"_s, "(object or DOMString)"_s); + return {}; } return result; } diff --git a/src/bun.js/bindings/webcrypto/JSRsaKeyGenParams.cpp b/src/bun.js/bindings/webcrypto/JSRsaKeyGenParams.cpp index 54644978ac..ff755e1656 100644 --- a/src/bun.js/bindings/webcrypto/JSRsaKeyGenParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSRsaKeyGenParams.cpp @@ -29,7 +29,6 @@ #include "JSDOMConvertStrings.h" #include - namespace WebCore { using namespace JSC; @@ -43,7 +42,7 @@ template<> CryptoAlgorithmRsaKeyGenParams convertDictionary CryptoAlgorithmRsaKeyGenParams convertDictionaryget(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "RsaKeyGenParams", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "RsaKeyGenParams"_s, "DOMString"_s); + return {}; } JSValue modulusLengthValue; if (isNullOrUndefined) modulusLengthValue = jsUndefined(); else { modulusLengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "modulusLength"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!modulusLengthValue.isUndefined()) { result.modulusLength = convert>(lexicalGlobalObject, modulusLengthValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "modulusLength", "RsaKeyGenParams", "unsigned long"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "modulusLength"_s, "RsaKeyGenParams"_s, "unsigned long"_s); + return {}; } JSValue publicExponentValue; if (isNullOrUndefined) publicExponentValue = jsUndefined(); else { publicExponentValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "publicExponent"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!publicExponentValue.isUndefined()) { result.publicExponent = convert(lexicalGlobalObject, publicExponentValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "publicExponent", "RsaKeyGenParams", "Uint8Array"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "publicExponent"_s, "RsaKeyGenParams"_s, "Uint8Array"_s); + return {}; } return result; } diff --git a/src/bun.js/bindings/webcrypto/JSRsaOaepParams.cpp b/src/bun.js/bindings/webcrypto/JSRsaOaepParams.cpp index 16264b7d9c..82daf491e1 100644 --- a/src/bun.js/bindings/webcrypto/JSRsaOaepParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSRsaOaepParams.cpp @@ -30,7 +30,6 @@ #include #include - namespace WebCore { using namespace JSC; @@ -44,7 +43,7 @@ template<> CryptoAlgorithmRsaOaepParams convertDictionary CryptoAlgorithmRsaOaepParams convertDictionaryget(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "RsaOaepParams", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "RsaOaepParams"_s, "DOMString"_s); + return {}; } JSValue labelValue; if (isNullOrUndefined) labelValue = jsUndefined(); else { labelValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "label"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!labelValue.isUndefined()) { result.label = convert>(lexicalGlobalObject, labelValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } return result; } diff --git a/src/bun.js/bindings/webcrypto/JSRsaOtherPrimesInfo.cpp b/src/bun.js/bindings/webcrypto/JSRsaOtherPrimesInfo.cpp index 420e17fb48..ce10023e6c 100644 --- a/src/bun.js/bindings/webcrypto/JSRsaOtherPrimesInfo.cpp +++ b/src/bun.js/bindings/webcrypto/JSRsaOtherPrimesInfo.cpp @@ -29,7 +29,6 @@ #include #include - namespace WebCore { using namespace JSC; @@ -43,7 +42,7 @@ template<> RsaOtherPrimesInfo convertDictionary(JSGlobalObje auto* object = isNullOrUndefined ? nullptr : value.getObject(); if (UNLIKELY(!isNullOrUndefined && !object)) { throwTypeError(&lexicalGlobalObject, throwScope); - return { }; + return {}; } RsaOtherPrimesInfo result; JSValue dValue; @@ -51,42 +50,42 @@ template<> RsaOtherPrimesInfo convertDictionary(JSGlobalObje dValue = jsUndefined(); else { dValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "d"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!dValue.isUndefined()) { result.d = convert(lexicalGlobalObject, dValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "d", "RsaOtherPrimesInfo", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "d"_s, "RsaOtherPrimesInfo"_s, "DOMString"_s); + return {}; } JSValue rValue; if (isNullOrUndefined) rValue = jsUndefined(); else { rValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "r"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!rValue.isUndefined()) { result.r = convert(lexicalGlobalObject, rValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "r", "RsaOtherPrimesInfo", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "r"_s, "RsaOtherPrimesInfo"_s, "DOMString"_s); + return {}; } JSValue tValue; if (isNullOrUndefined) tValue = jsUndefined(); else { tValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "t"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!tValue.isUndefined()) { result.t = convert(lexicalGlobalObject, tValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "t", "RsaOtherPrimesInfo", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "t"_s, "RsaOtherPrimesInfo"_s, "DOMString"_s); + return {}; } return result; } @@ -99,13 +98,13 @@ JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, J auto result = constructEmptyObject(&lexicalGlobalObject, globalObject.objectPrototype()); auto dValue = toJS(lexicalGlobalObject, throwScope, dictionary.d); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); result->putDirect(vm, JSC::Identifier::fromString(vm, "d"_s), dValue); auto rValue = toJS(lexicalGlobalObject, throwScope, dictionary.r); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); result->putDirect(vm, JSC::Identifier::fromString(vm, "r"_s), rValue); auto tValue = toJS(lexicalGlobalObject, throwScope, dictionary.t); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); result->putDirect(vm, JSC::Identifier::fromString(vm, "t"_s), tValue); return result; } diff --git a/src/bun.js/bindings/webcrypto/JSRsaPssParams.cpp b/src/bun.js/bindings/webcrypto/JSRsaPssParams.cpp index 3498ec0e90..372b60ef73 100644 --- a/src/bun.js/bindings/webcrypto/JSRsaPssParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSRsaPssParams.cpp @@ -28,7 +28,6 @@ #include "JSDOMConvertStrings.h" #include - namespace WebCore { using namespace JSC; @@ -42,7 +41,7 @@ template<> CryptoAlgorithmRsaPssParams convertDictionary CryptoAlgorithmRsaPssParams convertDictionaryget(&lexicalGlobalObject, Identifier::fromString(vm, "name"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!nameValue.isUndefined()) { result.name = convert(lexicalGlobalObject, nameValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name", "RsaPssParams", "DOMString"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "name"_s, "RsaPssParams"_s, "DOMString"_s); + return {}; } JSValue saltLengthValue; if (isNullOrUndefined) saltLengthValue = jsUndefined(); else { saltLengthValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "saltLength"_s)); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } if (!saltLengthValue.isUndefined()) { result.saltLength = convert>(lexicalGlobalObject, saltLengthValue); - RETURN_IF_EXCEPTION(throwScope, { }); + RETURN_IF_EXCEPTION(throwScope, {}); } else { - throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "saltLength", "RsaPssParams", "unsigned long"); - return { }; + throwRequiredMemberTypeError(lexicalGlobalObject, throwScope, "saltLength"_s, "RsaPssParams"_s, "unsigned long"_s); + return {}; } return result; } diff --git a/src/bun.js/bindings/webcrypto/JSSubtleCrypto.cpp b/src/bun.js/bindings/webcrypto/JSSubtleCrypto.cpp index de04487afc..d497ea8c9b 100644 --- a/src/bun.js/bindings/webcrypto/JSSubtleCrypto.cpp +++ b/src/bun.js/bindings/webcrypto/JSSubtleCrypto.cpp @@ -19,6 +19,7 @@ */ #include "config.h" +#include "wtf/Forward.h" #if ENABLE(WEB_CRYPTO) @@ -106,9 +107,9 @@ template<> std::optional parseEnumeration const char* expectedEnumerationValues() +template<> ASCIILiteral expectedEnumerationValues() { - return "\"raw\", \"spki\", \"pkcs8\", \"jwk\""; + return "\"raw\", \"spki\", \"pkcs8\", \"jwk\""_s; } // Functions @@ -269,7 +270,7 @@ static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_encryptBody(JS auto algorithm = convert>(*lexicalGlobalObject, argument0.value()); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); - auto key = convert>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "key", "SubtleCrypto", "encrypt", "CryptoKey"); }); + auto key = convert>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "key"_s, "SubtleCrypto"_s, "encrypt"_s, "CryptoKey"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument2 = callFrame->uncheckedArgument(2); auto data = convert>(*lexicalGlobalObject, argument2.value()); @@ -295,7 +296,7 @@ static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_decryptBody(JS auto algorithm = convert>(*lexicalGlobalObject, argument0.value()); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); - auto key = convert>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "key", "SubtleCrypto", "decrypt", "CryptoKey"); }); + auto key = convert>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "key"_s, "SubtleCrypto"_s, "decrypt"_s, "CryptoKey"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument2 = callFrame->uncheckedArgument(2); auto data = convert>(*lexicalGlobalObject, argument2.value()); @@ -321,7 +322,7 @@ static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_signBody(JSC:: auto algorithm = convert>(*lexicalGlobalObject, argument0.value()); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); - auto key = convert>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "key", "SubtleCrypto", "sign", "CryptoKey"); }); + auto key = convert>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "key"_s, "SubtleCrypto"_s, "sign"_s, "CryptoKey"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument2 = callFrame->uncheckedArgument(2); auto data = convert>(*lexicalGlobalObject, argument2.value()); @@ -347,7 +348,7 @@ static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_verifyBody(JSC auto algorithm = convert>(*lexicalGlobalObject, argument0.value()); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); - auto key = convert>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "key", "SubtleCrypto", "verify", "CryptoKey"); }); + auto key = convert>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "key"_s, "SubtleCrypto"_s, "verify"_s, "CryptoKey"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument2 = callFrame->uncheckedArgument(2); auto signature = convert>(*lexicalGlobalObject, argument2.value()); @@ -425,7 +426,7 @@ static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_deriveKeyBody( auto algorithm = convert>(*lexicalGlobalObject, argument0.value()); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); - auto baseKey = convert>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "baseKey", "SubtleCrypto", "deriveKey", "CryptoKey"); }); + auto baseKey = convert>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "baseKey"_s, "SubtleCrypto"_s, "deriveKey"_s, "CryptoKey"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument2 = callFrame->uncheckedArgument(2); auto derivedKeyType = convert>(*lexicalGlobalObject, argument2.value()); @@ -457,7 +458,7 @@ static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_deriveBitsBody auto algorithm = convert>(*lexicalGlobalObject, argument0.value()); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); - auto baseKey = convert>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "baseKey", "SubtleCrypto", "deriveBits", "CryptoKey"); }); + auto baseKey = convert>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "baseKey"_s, "SubtleCrypto"_s, "deriveBits"_s, "CryptoKey"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument2 = callFrame->uncheckedArgument(2); auto length = convert(*lexicalGlobalObject, argument2.value()); @@ -480,7 +481,7 @@ static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_importKeyBody( if (UNLIKELY(callFrame->argumentCount() < 5)) return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); - auto format = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeEnumError(lexicalGlobalObject, scope, 0, "format", "SubtleCrypto", "importKey", expectedEnumerationValues()); }); + auto format = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeEnumError(lexicalGlobalObject, scope, 0, "format"_s, "SubtleCrypto"_s, "importKey"_s, expectedEnumerationValues()); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); auto keyData = convert>>(*lexicalGlobalObject, argument1.value()); @@ -512,10 +513,10 @@ static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_exportKeyBody( if (UNLIKELY(callFrame->argumentCount() < 2)) return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); - auto format = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeEnumError(lexicalGlobalObject, scope, 0, "format", "SubtleCrypto", "exportKey", expectedEnumerationValues()); }); + auto format = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeEnumError(lexicalGlobalObject, scope, 0, "format"_s, "SubtleCrypto"_s, "exportKey"_s, expectedEnumerationValues()); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); - auto key = convert>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "key", "SubtleCrypto", "exportKey", "CryptoKey"); }); + auto key = convert>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "key"_s, "SubtleCrypto"_s, "exportKey"_s, "CryptoKey"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, [&]() -> decltype(auto) { return impl.exportKey(WTFMove(format), *key, WTFMove(promise)); @@ -537,13 +538,13 @@ static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_wrapKeyBody(JS if (UNLIKELY(callFrame->argumentCount() < 4)) return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); - auto format = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeEnumError(lexicalGlobalObject, scope, 0, "format", "SubtleCrypto", "wrapKey", expectedEnumerationValues()); }); + auto format = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeEnumError(lexicalGlobalObject, scope, 0, "format"_s, "SubtleCrypto"_s, "wrapKey"_s, expectedEnumerationValues()); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); - auto key = convert>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "key", "SubtleCrypto", "wrapKey", "CryptoKey"); }); + auto key = convert>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 1, "key"_s, "SubtleCrypto"_s, "wrapKey"_s, "CryptoKey"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument2 = callFrame->uncheckedArgument(2); - auto wrappingKey = convert>(*lexicalGlobalObject, argument2.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 2, "wrappingKey", "SubtleCrypto", "wrapKey", "CryptoKey"); }); + auto wrappingKey = convert>(*lexicalGlobalObject, argument2.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 2, "wrappingKey"_s, "SubtleCrypto"_s, "wrapKey"_s, "CryptoKey"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument3 = callFrame->uncheckedArgument(3); auto wrapAlgorithm = convert>(*lexicalGlobalObject, argument3.value()); @@ -566,13 +567,13 @@ static inline JSC::EncodedJSValue jsSubtleCryptoPrototypeFunction_unwrapKeyBody( if (UNLIKELY(callFrame->argumentCount() < 7)) return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); - auto format = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeEnumError(lexicalGlobalObject, scope, 0, "format", "SubtleCrypto", "unwrapKey", expectedEnumerationValues()); }); + auto format = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeEnumError(lexicalGlobalObject, scope, 0, "format"_s, "SubtleCrypto"_s, "unwrapKey"_s, expectedEnumerationValues()); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); auto wrappedKey = convert>(*lexicalGlobalObject, argument1.value()); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument2 = callFrame->uncheckedArgument(2); - auto unwrappingKey = convert>(*lexicalGlobalObject, argument2.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 2, "unwrappingKey", "SubtleCrypto", "unwrapKey", "CryptoKey"); }); + auto unwrappingKey = convert>(*lexicalGlobalObject, argument2.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 2, "unwrappingKey"_s, "SubtleCrypto"_s, "unwrapKey"_s, "CryptoKey"_s); }); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); EnsureStillAliveScope argument3 = callFrame->uncheckedArgument(3); auto unwrapAlgorithm = convert>(*lexicalGlobalObject, argument3.value()); @@ -609,7 +610,7 @@ void JSSubtleCrypto::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) auto* thisObject = jsCast(cell); analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); if (thisObject->scriptExecutionContext()) - analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + analyzer.setLabelForCell(cell, makeString("url "_s, thisObject->scriptExecutionContext()->url().string())); Base::analyzeHeap(cell, analyzer); } @@ -649,18 +650,18 @@ JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObj if constexpr (std::is_polymorphic_v) { #if ENABLE(BINDING_INTEGRITY) - const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // const void* actualVTablePointer = getVTablePointer(impl.ptr()); #if PLATFORM(WIN) void* expectedVTablePointer = __identifier("??_7SubtleCrypto@WebCore@@6B@"); #else - void* expectedVTablePointer = &_ZTVN7WebCore12SubtleCryptoE[2]; + // void* expectedVTablePointer = &_ZTVN7WebCore12SubtleCryptoE[2]; #endif // If you hit this assertion you either have a use after free bug, or // SubtleCrypto has subclasses. If SubtleCrypto has subclasses that get passed // to toJS() we currently require SubtleCrypto you to opt out of binding hardening // by adding the SkipVTableValidation attribute to the interface IDL definition - RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); #endif } return createWrapper(globalObject, WTFMove(impl)); diff --git a/src/bun.js/bindings/webcrypto/JSSubtleCrypto.h b/src/bun.js/bindings/webcrypto/JSSubtleCrypto.h index a4057c957e..b3a26c8727 100644 --- a/src/bun.js/bindings/webcrypto/JSSubtleCrypto.h +++ b/src/bun.js/bindings/webcrypto/JSSubtleCrypto.h @@ -97,7 +97,7 @@ String convertEnumerationToString(SubtleCrypto::KeyFormat); template<> JSC::JSString* convertEnumerationToJS(JSC::JSGlobalObject&, SubtleCrypto::KeyFormat); template<> std::optional parseEnumeration(JSC::JSGlobalObject&, JSC::JSValue); -template<> const char* expectedEnumerationValues(); +template<> ASCIILiteral expectedEnumerationValues(); } // namespace WebCore diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig index c94fb86d55..1438306b40 100644 --- a/src/bun.js/javascript.zig +++ b/src/bun.js/javascript.zig @@ -392,7 +392,7 @@ pub export fn Bun__GlobalObject__hasIPC(global: *JSC.JSGlobalObject) bool { pub export fn Bun__Process__send( globalObject: *JSGlobalObject, callFrame: *JSC.CallFrame, -) JSValue { +) callconv(JSC.conv) JSValue { JSC.markBinding(@src()); if (callFrame.argumentsCount() < 1) { globalObject.throwInvalidArguments("process.send requires at least one argument", .{}); @@ -415,7 +415,7 @@ pub export fn Bun__isBunMain(globalObject: *JSGlobalObject, str: *const bun.Stri pub export fn Bun__Process__disconnect( globalObject: *JSGlobalObject, callFrame: *JSC.CallFrame, -) JSValue { +) callconv(JSC.conv) JSValue { JSC.markBinding(@src()); _ = callFrame; _ = globalObject; @@ -2278,16 +2278,6 @@ pub const VirtualMachine = struct { res.* = ErrorableString.ok(bun.String.init(result.path)); } - // // This double prints - // pub fn promiseRejectionTracker(global: *JSGlobalObject, promise: *JSPromise, _: JSPromiseRejectionOperation) callconv(.C) JSValue { - // const result = promise.result(global.vm()); - // if (@intFromEnum(VirtualMachine.get().last_error_jsvalue) != @intFromEnum(result)) { - // VirtualMachine.get().runErrorHandler(result, null); - // } - - // return JSValue.jsUndefined(); - // } - pub const main_file_name: string = "bun:main"; pub fn drainMicrotasks(this: *VirtualMachine) void { diff --git a/src/bun.js/modules/BunJSCModule.h b/src/bun.js/modules/BunJSCModule.h index 994ccac390..0716f7c23e 100644 --- a/src/bun.js/modules/BunJSCModule.h +++ b/src/bun.js/modules/BunJSCModule.h @@ -91,8 +91,10 @@ JSC_DEFINE_HOST_FUNCTION(functionStartRemoteDebugger, if (!server.start(reinterpret_cast(host), port)) { throwVMError( globalObject, scope, - createError(globalObject, "Failed to start server \""_s + host + ":"_s + - port + "\". Is port already in use?"_s)); + createError(globalObject, + makeString("Failed to start server \""_s, + reinterpret_cast(host), + ":"_s, port, "\". Is port already in use?"_s))); return JSC::JSValue::encode(JSC::jsUndefined()); } diff --git a/src/bun.js/modules/NodeModuleModule.h b/src/bun.js/modules/NodeModuleModule.h index d8fecc60df..be6be2ee87 100644 --- a/src/bun.js/modules/NodeModuleModule.h +++ b/src/bun.js/modules/NodeModuleModule.h @@ -3,6 +3,8 @@ #include "CommonJSModuleRecord.h" #include "ImportMetaObject.h" +#include "JavaScriptCore/ArgList.h" +#include "JavaScriptCore/JSGlobalObjectInlines.h" #include "_NativeModule.h" #include "isBuiltinModule.h" #include @@ -120,7 +122,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionNodeModuleModuleConstructor, (JSC::JSGlobalOb idString = idValue.toString(globalObject); RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::jsUndefined())); - auto index = idString->tryGetValue().reverseFind('/', idString->length()); + auto index = idString->tryGetValue()->reverseFind('/', idString->length()); if (index != WTF::notFound) { dirname = JSC::jsSubstring(globalObject, idString, 0, index); @@ -208,7 +210,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionNodeModuleCreateRequire, scope, JSValue::encode(Bun::JSCommonJSModule::createBoundRequireFunction( vm, globalObject, val))); } -extern "C" JSC::EncodedJSValue Resolver__nodeModulePathsForJS(JSGlobalObject *, CallFrame *); +BUN_DECLARE_HOST_FUNCTION(Resolver__nodeModulePathsForJS); JSC_DEFINE_HOST_FUNCTION(jsFunctionFindSourceMap, (JSGlobalObject * globalObject, CallFrame *callFrame)) { auto &vm = globalObject->vm(); @@ -539,17 +541,15 @@ DEFINE_NATIVE_MODULE(NodeModule) { defaultObject->putDirect(vm, vm.propertyNames->prototype, prototype); - JSC::JSArray *builtinModules = JSC::JSArray::create( - vm, - globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), - countof(builtinModuleNames) - ); + MarkedArgumentBuffer args; + args.ensureCapacity(countof(builtinModuleNames)); for (unsigned i = 0; i < countof(builtinModuleNames); ++i) { - builtinModules->putDirectIndex(globalObject, i, JSC::jsString(vm, String(builtinModuleNames[i]))); + args.append(JSC::jsOwnedString(vm, String(builtinModuleNames[i]))); } - put(JSC::Identifier::fromString(vm, "builtinModules"_s), builtinModules); + + put(JSC::Identifier::fromString(vm, "builtinModules"_s), JSC::constructArray(globalObject, static_cast(nullptr), JSC::ArgList(args))); } } // namespace Zig diff --git a/src/bun.js/node/node_crypto_binding.zig b/src/bun.js/node/node_crypto_binding.zig index aad68932c1..93f13abeca 100644 --- a/src/bun.js/node/node_crypto_binding.zig +++ b/src/bun.js/node/node_crypto_binding.zig @@ -12,30 +12,25 @@ const EVP = Crypto.EVP; const PBKDF2 = EVP.PBKDF2; const JSValue = JSC.JSValue; -pub fn randomInt(global: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { - const S = struct { - fn cb(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { - const arguments = callframe.arguments(2).slice(); +fn randomInt(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { + const arguments = callframe.arguments(2).slice(); - var at_least: u52 = 0; - var at_most: u52 = std.math.maxInt(u52); + var at_least: u52 = 0; + var at_most: u52 = std.math.maxInt(u52); - //min, max - if (!arguments[0].isNumber()) return globalThis.throwInvalidArgumentTypeValue("min", "safe integer", arguments[0]); - if (!arguments[1].isNumber()) return globalThis.throwInvalidArgumentTypeValue("max", "safe integer", arguments[1]); - at_least = arguments[0].to(u52); - at_most = arguments[1].to(u52); + //min, max + if (!arguments[0].isNumber()) return globalThis.throwInvalidArgumentTypeValue("min", "safe integer", arguments[0]); + if (!arguments[1].isNumber()) return globalThis.throwInvalidArgumentTypeValue("max", "safe integer", arguments[1]); + at_least = arguments[0].to(u52); + at_most = arguments[1].to(u52); - return JSC.JSValue.jsNumberFromUint64(std.crypto.random.intRangeLessThan(u52, at_least, at_most)); - } - }; - return JSC.JSFunction.create(global, "randomInt", &S.cb, 2, .{}); + return JSC.JSValue.jsNumberFromUint64(std.crypto.random.intRangeLessThan(u52, at_least, at_most)); } -pub fn pbkdf2( +fn pbkdf2( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { const arguments = callframe.arguments(5); const data = PBKDF2.fromJS(globalThis, arguments.slice(), true) orelse { @@ -47,10 +42,10 @@ pub fn pbkdf2( return job.promise.value(); } -pub fn pbkdf2Sync( +fn pbkdf2Sync( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, -) callconv(.C) JSC.JSValue { +) JSC.JSValue { const arguments = callframe.arguments(5); var data = PBKDF2.fromJS(globalThis, arguments.slice(), false) orelse { @@ -80,12 +75,16 @@ pub fn pbkdf2Sync( return out_arraybuffer; } -pub fn createNodeCryptoBindingZig(global: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { +const jsPbkdf2 = JSC.toJSHostFunction(pbkdf2); +const jsPbkdf2Sync = JSC.toJSHostFunction(pbkdf2Sync); +const jsRandomInt = JSC.toJSHostFunction(randomInt); + +pub fn createNodeCryptoBindingZig(global: *JSC.JSGlobalObject) JSC.JSValue { const crypto = JSC.JSValue.createEmptyObject(global, 3); - crypto.put(global, bun.String.init("pbkdf2"), JSC.JSFunction.create(global, "pbkdf2", &pbkdf2, 5, .{})); - crypto.put(global, bun.String.init("pbkdf2Sync"), JSC.JSFunction.create(global, "pbkdf2Sync", &pbkdf2Sync, 5, .{})); - crypto.put(global, bun.String.init("randomInt"), randomInt(global)); + crypto.put(global, bun.String.init("pbkdf2"), JSC.JSFunction.create(global, "pbkdf2", jsPbkdf2, 5, .{})); + crypto.put(global, bun.String.init("pbkdf2Sync"), JSC.JSFunction.create(global, "pbkdf2Sync", jsPbkdf2Sync, 5, .{})); + crypto.put(global, bun.String.init("randomInt"), JSC.JSFunction.create(global, "randomInt", jsRandomInt, 2, .{})); return crypto; } diff --git a/src/bun.js/node/node_fs_binding.zig b/src/bun.js/node/node_fs_binding.zig index 9f7bca8c44..d475471e21 100644 --- a/src/bun.js/node/node_fs_binding.zig +++ b/src/bun.js/node/node_fs_binding.zig @@ -14,7 +14,7 @@ const NodeFSFunction = fn ( this: *JSC.Node.NodeJSFS, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, -) callconv(.C) JSC.JSValue; +) JSC.JSValue; const NodeFSFunctionEnum = std.meta.DeclEnum(JSC.Node.NodeFS); @@ -34,7 +34,7 @@ fn callSync(comptime FunctionEnum: NodeFSFunctionEnum) NodeFSFunction { this: *JSC.Node.NodeJSFS, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { var exceptionref: JSC.C.JSValueRef = null; var arguments = callframe.arguments(8); @@ -93,7 +93,7 @@ fn call(comptime FunctionEnum: NodeFSFunctionEnum) NodeFSFunction { _: *JSC.Node.NodeJSFS, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { var arguments = callframe.arguments(8); var slice = ArgumentsSlice.init(globalObject.bunVM(), arguments.slice()); @@ -144,12 +144,12 @@ pub const NodeJSFS = struct { pub usingnamespace JSC.Codegen.JSNodeJSFS; pub usingnamespace bun.New(@This()); - pub fn constructor(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) ?*@This() { + pub fn constructor(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) ?*@This() { globalObject.throw("Not a constructor", .{}); return null; } - pub fn finalize(this: *JSC.Node.NodeJSFS) callconv(.C) void { + pub fn finalize(this: *JSC.Node.NodeJSFS) void { if (this.node_fs.vm) |vm| { if (vm.node_fs == &this.node_fs) { return; @@ -241,11 +241,11 @@ pub const NodeJSFS = struct { pub const fdatasyncSync = callSync(.fdatasync); pub const fdatasync = call(.fdatasync); - pub fn getDirent(_: *NodeJSFS, globalThis: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getDirent(_: *NodeJSFS, globalThis: *JSC.JSGlobalObject) JSC.JSValue { return JSC.Node.Dirent.getConstructor(globalThis); } - pub fn getStats(_: *NodeJSFS, globalThis: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getStats(_: *NodeJSFS, globalThis: *JSC.JSGlobalObject) JSC.JSValue { return JSC.Node.StatsSmall.getConstructor(globalThis); } diff --git a/src/bun.js/node/node_fs_stat_watcher.zig b/src/bun.js/node/node_fs_stat_watcher.zig index 74f6717b49..ca41a378a0 100644 --- a/src/bun.js/node/node_fs_stat_watcher.zig +++ b/src/bun.js/node/node_fs_stat_watcher.zig @@ -309,7 +309,7 @@ pub const StatWatcher = struct { } }; - pub fn doRef(this: *StatWatcher, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn doRef(this: *StatWatcher, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { if (!this.closed and !this.persistent) { this.persistent = true; this.poll_ref.ref(this.ctx); @@ -317,7 +317,7 @@ pub const StatWatcher = struct { return JSC.JSValue.jsUndefined(); } - pub fn doUnref(this: *StatWatcher, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn doUnref(this: *StatWatcher, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { if (this.persistent) { this.persistent = false; this.poll_ref.unref(this.ctx); @@ -325,7 +325,7 @@ pub const StatWatcher = struct { return JSC.JSValue.jsUndefined(); } - pub fn hasPendingActivity(this: *StatWatcher) callconv(.C) bool { + pub fn hasPendingActivity(this: *StatWatcher) bool { @fence(.acquire); return this.used_by_scheduler_thread.load(.acquire); @@ -343,13 +343,13 @@ pub const StatWatcher = struct { this.last_jsvalue.clear(); } - pub fn doClose(this: *StatWatcher, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn doClose(this: *StatWatcher, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { this.close(); return JSC.JSValue.jsUndefined(); } /// If the scheduler is not using this, free instantly, otherwise mark for being freed. - pub fn finalize(this: *StatWatcher) callconv(.C) void { + pub fn finalize(this: *StatWatcher) void { log("Finalize\n", .{}); this.deinit(); } diff --git a/src/bun.js/node/node_fs_watcher.zig b/src/bun.js/node/node_fs_watcher.zig index 23d6a19672..54e9fdaced 100644 --- a/src/bun.js/node/node_fs_watcher.zig +++ b/src/bun.js/node/node_fs_watcher.zig @@ -610,7 +610,7 @@ pub const FSWatcher = struct { } } - pub fn doRef(this: *FSWatcher, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn doRef(this: *FSWatcher, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { if (!this.closed and !this.persistent) { this.persistent = true; this.poll_ref.ref(this.ctx); @@ -618,7 +618,7 @@ pub const FSWatcher = struct { return JSC.JSValue.jsUndefined(); } - pub fn doUnref(this: *FSWatcher, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn doUnref(this: *FSWatcher, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { if (this.persistent) { this.persistent = false; this.poll_ref.unref(this.ctx); @@ -626,7 +626,7 @@ pub const FSWatcher = struct { return JSC.JSValue.jsUndefined(); } - pub fn hasRef(this: *FSWatcher, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn hasRef(this: *FSWatcher, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { return JSC.JSValue.jsBoolean(this.persistent); } @@ -641,7 +641,7 @@ pub const FSWatcher = struct { return true; } - pub fn hasPendingActivity(this: *FSWatcher) callconv(.C) bool { + pub fn hasPendingActivity(this: *FSWatcher) bool { @fence(.acquire); return this.pending_activity_count.load(.acquire) > 0; } @@ -696,12 +696,12 @@ pub const FSWatcher = struct { this.js_this = .zero; } - pub fn doClose(this: *FSWatcher, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn doClose(this: *FSWatcher, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { this.close(); return JSC.JSValue.jsUndefined(); } - pub fn finalize(this: *FSWatcher) callconv(.C) void { + pub fn finalize(this: *FSWatcher) void { this.deinit(); } diff --git a/src/bun.js/node/node_net_binding.zig b/src/bun.js/node/node_net_binding.zig index ce38d71c44..8a4854261f 100644 --- a/src/bun.js/node/node_net_binding.zig +++ b/src/bun.js/node/node_net_binding.zig @@ -11,9 +11,9 @@ const ZigString = JSC.ZigString; pub var autoSelectFamilyDefault: bool = true; -pub fn getDefaultAutoSelectFamily(global: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { +pub fn getDefaultAutoSelectFamily(global: *JSC.JSGlobalObject) JSC.JSValue { return JSC.JSFunction.create(global, "getDefaultAutoSelectFamily", (struct { - fn getter(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + fn getter(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { _ = globalThis; _ = callframe; return JSC.jsBoolean(autoSelectFamilyDefault); @@ -21,9 +21,9 @@ pub fn getDefaultAutoSelectFamily(global: *JSC.JSGlobalObject) callconv(.C) JSC. }).getter, 0, .{}); } -pub fn setDefaultAutoSelectFamily(global: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { +pub fn setDefaultAutoSelectFamily(global: *JSC.JSGlobalObject) JSC.JSValue { return JSC.JSFunction.create(global, "setDefaultAutoSelectFamily", (struct { - fn setter(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + fn setter(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(1); if (arguments.len < 1) { globalThis.throw("missing argument", .{}); @@ -46,9 +46,9 @@ pub fn setDefaultAutoSelectFamily(global: *JSC.JSGlobalObject) callconv(.C) JSC. pub var autoSelectFamilyAttemptTimeoutDefault: u32 = 250; -pub fn getDefaultAutoSelectFamilyAttemptTimeout(global: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { +pub fn getDefaultAutoSelectFamilyAttemptTimeout(global: *JSC.JSGlobalObject) JSC.JSValue { return JSC.JSFunction.create(global, "getDefaultAutoSelectFamilyAttemptTimeout", (struct { - fn getter(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + fn getter(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { _ = globalThis; _ = callframe; return JSC.jsNumber(autoSelectFamilyAttemptTimeoutDefault); @@ -56,9 +56,9 @@ pub fn getDefaultAutoSelectFamilyAttemptTimeout(global: *JSC.JSGlobalObject) cal }).getter, 0, .{}); } -pub fn setDefaultAutoSelectFamilyAttemptTimeout(global: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { +pub fn setDefaultAutoSelectFamilyAttemptTimeout(global: *JSC.JSGlobalObject) JSC.JSValue { return JSC.JSFunction.create(global, "setDefaultAutoSelectFamilyAttemptTimeout", (struct { - fn setter(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + fn setter(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(1); if (arguments.len < 1) { globalThis.throw("missing argument", .{}); diff --git a/src/bun.js/node/node_os.zig b/src/bun.js/node/node_os.zig index 664ee2c951..9a153b93b1 100644 --- a/src/bun.js/node/node_os.zig +++ b/src/bun.js/node/node_os.zig @@ -11,7 +11,7 @@ const is_bindgen: bool = std.meta.globalOption("bindgen", bool) orelse false; const libuv = bun.windows.libuv; pub const OS = struct { - pub fn create(globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn create(globalObject: *JSC.JSGlobalObject) JSC.JSValue { const module = JSC.JSValue.createEmptyObject(globalObject, 16); module.put(globalObject, JSC.ZigString.static("cpus"), JSC.NewFunction(globalObject, JSC.ZigString.static("cpus"), 0, cpus, true)); @@ -51,7 +51,7 @@ pub const OS = struct { } }; - pub fn cpus(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn cpus(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { JSC.markBinding(@src()); return switch (Environment.os) { @@ -294,19 +294,19 @@ pub const OS = struct { return values; } - pub fn endianness(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn endianness(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { JSC.markBinding(@src()); return JSC.ZigString.init("LE").withEncoding().toJS(globalThis); } - pub fn freemem(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn freemem(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { JSC.markBinding(@src()); return JSC.JSValue.jsNumberFromUint64(C.getFreeMemory()); } - pub fn getPriority(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn getPriority(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { JSC.markBinding(@src()); var args_ = callframe.arguments(1); @@ -348,7 +348,7 @@ pub const OS = struct { return JSC.JSValue.jsNumberFromInt32(priority); } - pub fn homedir(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn homedir(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { JSC.markBinding(@src()); const dir: []const u8 = brk: { @@ -366,7 +366,7 @@ pub const OS = struct { return JSC.ZigString.init(dir).withEncoding().toJS(globalThis); } - pub fn hostname(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn hostname(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { JSC.markBinding(@src()); if (comptime Environment.isWindows) { @@ -394,7 +394,7 @@ pub const OS = struct { return JSC.ZigString.init(std.posix.gethostname(&name_buffer) catch "unknown").withEncoding().toJS(globalThis); } - pub fn loadavg(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn loadavg(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { JSC.markBinding(@src()); const result = C.getSystemLoadavg(); @@ -405,7 +405,7 @@ pub const OS = struct { }); } - pub fn networkInterfaces(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn networkInterfaces(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { return switch (Environment.os) { .windows => networkInterfacesWindows(globalThis), else => networkInterfacesPosix(globalThis), @@ -710,19 +710,19 @@ pub const OS = struct { return ret; } - pub fn platform(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn platform(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { JSC.markBinding(@src()); return JSC.ZigString.init(Global.os_name).withEncoding().toJS(globalThis); } - pub fn release(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn release(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { JSC.markBinding(@src()); var name_buffer: [bun.HOST_NAME_MAX]u8 = undefined; return JSC.ZigString.init(C.getRelease(&name_buffer)).withEncoding().toJS(globalThis); } - pub fn setPriority(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn setPriority(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { JSC.markBinding(@src()); var args_ = callframe.arguments(2); @@ -785,13 +785,13 @@ pub const OS = struct { return JSC.JSValue.jsUndefined(); } - pub fn totalmem(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn totalmem(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { JSC.markBinding(@src()); return JSC.JSValue.jsNumberFromUint64(C.getTotalMemory()); } - pub fn @"type"(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn @"type"(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { JSC.markBinding(@src()); if (comptime Environment.isWindows) @@ -804,7 +804,7 @@ pub const OS = struct { return JSC.ZigString.init(Global.os_name).withEncoding().toJS(globalThis); } - pub fn uptime(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn uptime(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { if (Environment.isWindows) { var uptime_value: f64 = undefined; const err = libuv.uv_uptime(&uptime_value); @@ -824,7 +824,7 @@ pub const OS = struct { return JSC.JSValue.jsNumberFromUint64(C.getSystemUptime()); } - pub fn userInfo(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn userInfo(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const result = JSC.JSValue.createEmptyObject(globalThis, 5); result.put(globalThis, JSC.ZigString.static("homedir"), homedir(globalThis, callframe)); @@ -847,7 +847,7 @@ pub const OS = struct { return result; } - pub fn version(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn version(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { JSC.markBinding(@src()); var name_buffer: [bun.HOST_NAME_MAX]u8 = undefined; return JSC.ZigString.init(C.getVersion(&name_buffer)).withEncoding().toJS(globalThis); @@ -868,7 +868,7 @@ pub const OS = struct { }; } - pub fn machine(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn machine(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { JSC.markBinding(@src()); return JSC.ZigString.static(comptime getMachineName()).toJS(globalThis); } diff --git a/src/bun.js/node/node_zlib_binding.zig b/src/bun.js/node/node_zlib_binding.zig index ee511d5167..18f9abc97c 100644 --- a/src/bun.js/node/node_zlib_binding.zig +++ b/src/bun.js/node/node_zlib_binding.zig @@ -5,11 +5,3 @@ const JSC = bun.JSC; const string = bun.string; const Output = bun.Output; const ZigString = JSC.ZigString; - -pub fn createBrotliEncoder(global: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { - return JSC.JSFunction.create(global, "createBrotliEncoder", bun.JSC.API.BrotliEncoder.create, 3, .{}); -} - -pub fn createBrotliDecoder(global: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { - return JSC.JSFunction.create(global, "createBrotliDecoder", bun.JSC.API.BrotliDecoder.create, 3, .{}); -} diff --git a/src/bun.js/node/path.zig b/src/bun.js/node/path.zig new file mode 100644 index 0000000000..c7f55ec9bc --- /dev/null +++ b/src/bun.js/node/path.zig @@ -0,0 +1,2944 @@ +const bun = @import("root").bun; +const JSC = bun.JSC; +const std = @import("std"); +const windows = bun.windows; + +const Path = @This(); +const typeBaseNameT = bun.meta.typeBaseNameT; +const validators = @import("./util/validators.zig"); +const validateObject = validators.validateObject; +const validateString = validators.validateString; +const stack_fallback_size_large = 32 * @sizeOf([]const u8); // up to 32 strings on the stack +const Syscall = bun.sys; +const strings = bun.strings; +const L = strings.literal; +const string = bun.string; +const Environment = bun.Environment; + +const PATH_MIN_WIDE = 4096; // 4 KB +const stack_fallback_size_small = switch (Environment.os) { + // Up to 4 KB, instead of MAX_PATH_BYTES which is 96 KB on Windows, ouch! + .windows => PATH_MIN_WIDE, + else => bun.MAX_PATH_BYTES, +}; + +/// Taken from Zig 0.11.0 zig/src/resinator/rc.zig +/// https://github.com/ziglang/zig/blob/776cd673f206099012d789fd5d05d49dd72b9faa/src/resinator/rc.zig#L266 +/// +/// Compares ASCII values case-insensitively, non-ASCII values are compared directly +fn eqlIgnoreCaseT(comptime T: type, a: []const T, b: []const T) bool { + if (T != u16) { + return bun.strings.eqlCaseInsensitiveASCII(a, b, true); + } +} + +/// Taken from Zig 0.11.0 zig/src/resinator/rc.zig +/// https://github.com/ziglang/zig/blob/776cd673f206099012d789fd5d05d49dd72b9faa/src/resinator/rc.zig#L266 +/// +/// Lowers ASCII values, non-ASCII values are returned directly +inline fn toLowerT(comptime T: type, a_c: T) T { + if (T != u16) { + return std.ascii.toLower(a_c); + } + return if (a_c < 128) @intCast(std.ascii.toLower(@intCast(a_c))) else a_c; +} + +fn MaybeBuf(comptime T: type) type { + return JSC.Node.Maybe([]T, Syscall.Error); +} + +fn MaybeSlice(comptime T: type) type { + return JSC.Node.Maybe([]const T, Syscall.Error); +} + +fn validatePathT(comptime T: type, comptime methodName: []const u8) void { + comptime switch (T) { + u8, u16 => return, + else => @compileError("Unsupported type for " ++ methodName ++ ": " ++ typeBaseNameT(T)), + }; +} + +const CHAR_BACKWARD_SLASH = '\\'; +const CHAR_COLON = ':'; +const CHAR_DOT = '.'; +const CHAR_FORWARD_SLASH = '/'; +const CHAR_QUESTION_MARK = '?'; + +const CHAR_STR_BACKWARD_SLASH = "\\"; +const CHAR_STR_FORWARD_SLASH = "/"; +const CHAR_STR_DOT = "."; + +const StringBuilder = @import("../../string_builder.zig"); + +const toJSString = JSC.JSValue.toJSString; + +/// Based on Node v21.6.1 path.parse: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L919 +/// The structs returned by parse methods. +fn PathParsed(comptime T: type) type { + return struct { + root: []const T = "", + dir: []const T = "", + base: []const T = "", + ext: []const T = "", + name: []const T = "", + pub fn toJSObject(this: @This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue { + var jsObject = JSC.JSValue.createEmptyObject(globalObject, 5); + jsObject.put(globalObject, JSC.ZigString.static("root"), toJSString(globalObject, this.root)); + jsObject.put(globalObject, JSC.ZigString.static("dir"), toJSString(globalObject, this.dir)); + jsObject.put(globalObject, JSC.ZigString.static("base"), toJSString(globalObject, this.base)); + jsObject.put(globalObject, JSC.ZigString.static("ext"), toJSString(globalObject, this.ext)); + jsObject.put(globalObject, JSC.ZigString.static("name"), toJSString(globalObject, this.name)); + return jsObject; + } + }; +} + +pub fn MAX_PATH_SIZE(comptime T: type) usize { + return if (T == u16) windows.PATH_MAX_WIDE else bun.MAX_PATH_BYTES; +} + +pub fn PATH_SIZE(comptime T: type) usize { + return if (T == u16) PATH_MIN_WIDE else bun.MAX_PATH_BYTES; +} + +const Shimmer = @import("../bindings/shimmer.zig").Shimmer; +pub const shim = Shimmer("Bun", "Path", @This()); +pub const name = "Bun__Path"; +pub const include = "Path.h"; +pub const namespace = shim.namespace; +pub const sep_posix = CHAR_FORWARD_SLASH; +pub const sep_windows = CHAR_BACKWARD_SLASH; +pub const sep_str_posix = CHAR_STR_FORWARD_SLASH; +pub const sep_str_windows = CHAR_STR_BACKWARD_SLASH; + +/// Based on Node v21.6.1 private helper formatExt: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L130C10-L130C19 +inline fn formatExtT(comptime T: type, ext: []const T, buf: []T) []const T { + const len = ext.len; + if (len == 0) { + return comptime L(T, ""); + } + if (ext[0] == CHAR_DOT) { + return ext; + } + const bufSize = len + 1; + buf[0] = CHAR_DOT; + @memcpy(buf[1..bufSize], ext); + return buf[0..bufSize]; +} + +/// Based on Node v21.6.1 private helper posixCwd: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1074 +inline fn posixCwdT(comptime T: type, buf: []T) MaybeBuf(T) { + const cwd = switch (getCwdT(T, buf)) { + .result => |r| r, + .err => |e| return MaybeBuf(T){ .err = e }, + }; + const len = cwd.len; + if (len == 0) { + return MaybeBuf(T){ .result = cwd }; + } + if (comptime Environment.isWindows) { + // Converts Windows' backslash path separators to POSIX forward slashes + // and truncates any drive indicator + + // Translated from the following JS code: + // const cwd = StringPrototypeReplace(process.cwd(), regexp, '/'); + for (0..len) |i| { + if (cwd[i] == CHAR_BACKWARD_SLASH) { + buf[i] = CHAR_FORWARD_SLASH; + } else { + buf[i] = cwd[i]; + } + } + var normalizedCwd = buf[0..len]; + + // Translated from the following JS code: + // return StringPrototypeSlice(cwd, StringPrototypeIndexOf(cwd, '/')); + const index = std.mem.indexOfScalar(T, normalizedCwd, CHAR_FORWARD_SLASH); + // Account for the -1 case of String#slice in JS land + if (index) |_index| { + return MaybeBuf(T){ .result = normalizedCwd[_index..len] }; + } + return MaybeBuf(T){ .result = normalizedCwd[len - 1 .. len] }; + } + + // We're already on POSIX, no need for any transformations + return MaybeBuf(T){ .result = cwd }; +} + +pub fn getCwdWindowsU8(buf: []u8) MaybeBuf(u8) { + const u16Buf: bun.WPathBuffer = undefined; + switch (getCwdWindowsU16(&u16Buf)) { + .result => |r| { + // Handles conversion from UTF-16 to UTF-8 including surrogates ;) + const result = strings.convertUTF16ToUTF8InBuffer(&buf, r) catch { + return MaybeBuf(u8).errnoSys(0, Syscall.Tag.getcwd).?; + }; + return MaybeBuf(u8){ .result = result }; + }, + .err => |e| return MaybeBuf(u8){ .err = e }, + } +} + +pub fn getCwdWindowsU16(buf: []u16) MaybeBuf(u16) { + const len: u32 = windows.GetCurrentDirectoryW(buf.len, &buf); + if (len == 0) { + // Indirectly calls std.os.windows.kernel32.GetLastError(). + return MaybeBuf(u16).errnoSys(0, Syscall.Tag.getcwd).?; + } + return MaybeBuf(u16){ .result = buf[0..len] }; +} + +pub fn getCwdWindowsT(comptime T: type, buf: []T) MaybeBuf(T) { + comptime validatePathT(T, "getCwdWindowsT"); + return if (T == u16) + getCwdWindowsU16(buf) + else + getCwdWindowsU8(buf); +} + +pub fn getCwdU8(buf: []u8) MaybeBuf(u8) { + const result = bun.getcwd(buf) catch { + return MaybeBuf(u8).errnoSys( + @as(c_int, 0), + Syscall.Tag.getcwd, + ).?; + }; + return MaybeBuf(u8){ .result = result }; +} + +pub fn getCwdU16(buf: []u16) MaybeBuf(u16) { + if (comptime Environment.isWindows) { + return getCwdWindowsU16(&buf); + } + const u8Buf: bun.PathBuffer = undefined; + const result = strings.convertUTF8toUTF16InBuffer(&buf, bun.getcwd(strings.convertUTF16ToUTF8InBuffer(&u8Buf, buf))) catch { + return MaybeBuf(u16).errnoSys(0, Syscall.Tag.getcwd).?; + }; + return MaybeBuf(u16){ .result = result }; +} + +pub fn getCwdT(comptime T: type, buf: []T) MaybeBuf(T) { + comptime validatePathT(T, "getCwdT"); + return if (T == u16) + getCwdU16(buf) + else + getCwdU8(buf); +} + +// Alias for naming consistency. +pub const getCwd = getCwdU8; + +/// Based on Node v21.6.1 path.posix.basename: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1309 +pub fn basenamePosixT(comptime T: type, path: []const T, suffix: ?[]const T) []const T { + comptime validatePathT(T, "basenamePosixT"); + + // validateString of `path` is performed in pub fn basename. + const len = path.len; + // Exit early for easier number type use. + if (len == 0) { + return comptime L(T, ""); + } + var start: usize = 0; + // We use an optional value instead of -1, as in Node code, for easier number type use. + var end: ?usize = null; + var matchedSlash: bool = true; + + const _suffix = if (suffix) |_s| _s else comptime L(T, ""); + const _suffixLen = _suffix.len; + if (suffix != null and _suffixLen > 0 and _suffixLen <= len) { + if (std.mem.eql(T, _suffix, path)) { + return comptime L(T, ""); + } + // We use an optional value instead of -1, as in Node code, for easier number type use. + var extIdx: ?usize = _suffixLen - 1; + // We use an optional value instead of -1, as in Node code, for easier number type use. + var firstNonSlashEnd: ?usize = null; + var i_i64 = @as(i64, @intCast(len - 1)); + while (i_i64 >= start) : (i_i64 -= 1) { + const i = @as(usize, @intCast(i_i64)); + const byte = path[i]; + if (byte == CHAR_FORWARD_SLASH) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + start = i + 1; + break; + } + } else { + if (firstNonSlashEnd == null) { + // We saw the first non-path separator, remember this index in case + // we need it if the extension ends up not matching + matchedSlash = false; + firstNonSlashEnd = i + 1; + } + if (extIdx) |_extIx| { + // Try to match the explicit extension + if (byte == _suffix[_extIx]) { + if (_extIx == 0) { + // We matched the extension, so mark this as the end of our path + // component + end = i; + extIdx = null; + } else { + extIdx = _extIx - 1; + } + } else { + // Extension does not match, so our result is the entire path + // component + extIdx = null; + end = firstNonSlashEnd; + } + } + } + } + + if (end) |_end| { + if (start == _end) { + return path[start..firstNonSlashEnd.?]; + } else { + return path[start.._end]; + } + } + return path[start..len]; + } + + var i_i64 = @as(i64, @intCast(len - 1)); + while (i_i64 > -1) : (i_i64 -= 1) { + const i = @as(usize, @intCast(i_i64)); + const byte = path[i]; + if (byte == CHAR_FORWARD_SLASH) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + start = i + 1; + break; + } + } else if (end == null) { + // We saw the first non-path separator, mark this as the end of our + // path component + matchedSlash = false; + end = i + 1; + } + } + + return if (end) |_end| + path[start.._end] + else + comptime L(T, ""); +} + +/// Based on Node v21.6.1 path.win32.basename: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L753 +pub fn basenameWindowsT(comptime T: type, path: []const T, suffix: ?[]const T) []const T { + comptime validatePathT(T, "basenameWindowsT"); + + // validateString of `path` is performed in pub fn basename. + const len = path.len; + // Exit early for easier number type use. + if (len == 0) { + return comptime L(T, ""); + } + + const isSepT = isSepWindowsT; + + var start: usize = 0; + // We use an optional value instead of -1, as in Node code, for easier number type use. + var end: ?usize = null; + var matchedSlash: bool = true; + + // Check for a drive letter prefix so as not to mistake the following + // path separator as an extra separator at the end of the path that can be + // disregarded + if (len >= 2 and isWindowsDeviceRootT(T, path[0]) and path[1] == CHAR_COLON) { + start = 2; + } + + const _suffix = if (suffix) |_s| _s else comptime L(T, ""); + const _suffixLen = _suffix.len; + if (suffix != null and _suffixLen > 0 and _suffixLen <= len) { + if (std.mem.eql(T, _suffix, path)) { + return comptime L(T, ""); + } + // We use an optional value instead of -1, as in Node code, for easier number type use. + var extIdx: ?usize = _suffixLen - 1; + // We use an optional value instead of -1, as in Node code, for easier number type use. + var firstNonSlashEnd: ?usize = null; + var i_i64 = @as(i64, @intCast(len - 1)); + while (i_i64 >= start) : (i_i64 -= 1) { + const i = @as(usize, @intCast(i_i64)); + const byte = path[i]; + if (isSepT(T, byte)) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + start = i + 1; + break; + } + } else { + if (firstNonSlashEnd == null) { + // We saw the first non-path separator, remember this index in case + // we need it if the extension ends up not matching + matchedSlash = false; + firstNonSlashEnd = i + 1; + } + if (extIdx) |_extIx| { + // Try to match the explicit extension + if (byte == _suffix[_extIx]) { + if (_extIx == 0) { + // We matched the extension, so mark this as the end of our path + // component + end = i; + extIdx = null; + } else { + extIdx = _extIx - 1; + } + } else { + // Extension does not match, so our result is the entire path + // component + extIdx = null; + end = firstNonSlashEnd; + } + } + } + } + + if (end) |_end| { + if (start == _end) { + return path[start..firstNonSlashEnd.?]; + } else { + return path[start.._end]; + } + } + return path[start..len]; + } + + var i_i64 = @as(i64, @intCast(len - 1)); + while (i_i64 >= start) : (i_i64 -= 1) { + const i = @as(usize, @intCast(i_i64)); + const byte = path[i]; + if (isSepT(T, byte)) { + if (!matchedSlash) { + start = i + 1; + break; + } + } else if (end == null) { + matchedSlash = false; + end = i + 1; + } + } + + return if (end) |_end| + path[start.._end] + else + comptime L(T, ""); +} + +pub inline fn basenamePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T, suffix: ?[]const T) JSC.JSValue { + return toJSString(globalObject, basenamePosixT(T, path, suffix)); +} + +pub inline fn basenameWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T, suffix: ?[]const T) JSC.JSValue { + return toJSString(globalObject, basenameWindowsT(T, path, suffix)); +} + +pub inline fn basenameJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, isWindows: bool, path: []const T, suffix: ?[]const T) JSC.JSValue { + return if (isWindows) + basenameWindowsJS_T(T, globalObject, path, suffix) + else + basenamePosixJS_T(T, globalObject, path, suffix); +} + +pub fn basename(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { + const suffix_ptr: ?JSC.JSValue = if (args_len > 1) args_ptr[1] else null; + + if (suffix_ptr) |_suffix_ptr| { + // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. + validateString(globalObject, _suffix_ptr, "ext", .{}) catch { + // Returning .zero translates to a nullprt JSC.JSValue. + return .zero; + }; + } + + const path_ptr = if (args_len > 0) args_ptr[0] else JSC.JSValue.jsUndefined(); + // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. + validateString(globalObject, path_ptr, "path", .{}) catch { + return .zero; + }; + + const pathZStr = path_ptr.getZigString(globalObject); + if (pathZStr.len == 0) return path_ptr; + + var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, JSC.getAllocator(globalObject)); + const allocator = stack_fallback.get(); + + const pathZSlice = pathZStr.toSlice(allocator); + defer pathZSlice.deinit(); + + var suffixZSlice: ?JSC.ZigString.Slice = null; + if (suffix_ptr) |_suffix_ptr| { + const suffixZStr = _suffix_ptr.getZigString(globalObject); + if (suffixZStr.len > 0 and suffixZStr.len <= pathZStr.len) { + suffixZSlice = suffixZStr.toSlice(allocator); + } + } + defer if (suffixZSlice) |_s| _s.deinit(); + return basenameJS_T(u8, globalObject, isWindows, pathZSlice.slice(), if (suffixZSlice) |_s| _s.slice() else null); +} + +pub fn create(globalObject: *JSC.JSGlobalObject, isWindows: bool) callconv(JSC.conv) JSC.JSValue { + return shim.cppFn("create", .{ globalObject, isWindows }); +} + +/// Based on Node v21.6.1 path.posix.dirname: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1278 +pub fn dirnamePosixT(comptime T: type, path: []const T) []const T { + comptime validatePathT(T, "dirnamePosixT"); + + // validateString of `path` is performed in pub fn dirname. + const len = path.len; + if (len == 0) { + return comptime L(T, CHAR_STR_DOT); + } + + const hasRoot = path[0] == CHAR_FORWARD_SLASH; + // We use an optional value instead of -1, as in Node code, for easier number type use. + var end: ?usize = null; + var matchedSlash: bool = true; + var i: usize = len - 1; + while (i >= 1) : (i -= 1) { + if (path[i] == CHAR_FORWARD_SLASH) { + if (!matchedSlash) { + end = i; + break; + } + } else { + // We saw the first non-path separator + matchedSlash = false; + } + } + + if (end) |_end| { + return if (hasRoot and _end == 1) + comptime L(T, "//") + else + path[0.._end]; + } + return if (hasRoot) + comptime L(T, CHAR_STR_FORWARD_SLASH) + else + comptime L(T, CHAR_STR_DOT); +} + +/// Based on Node v21.6.1 path.win32.dirname: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L657 +pub fn dirnameWindowsT(comptime T: type, path: []const T) []const T { + comptime validatePathT(T, "dirnameWindowsT"); + + // validateString of `path` is performed in pub fn dirname. + const len = path.len; + if (len == 0) { + return comptime L(T, CHAR_STR_DOT); + } + + const isSepT = isSepWindowsT; + + // We use an optional value instead of -1, as in Node code, for easier number type use. + var rootEnd: ?usize = null; + var offset: usize = 0; + const byte0 = path[0]; + + if (len == 1) { + // `path` contains just a path separator, exit early to avoid + // unnecessary work or a dot. + return if (isSepT(T, byte0)) path else comptime L(T, CHAR_STR_DOT); + } + + // Try to match a root + if (isSepT(T, byte0)) { + // Possible UNC root + + rootEnd = 1; + offset = 1; + + if (isSepT(T, path[1])) { + // Matched double path separator at the beginning + var j: usize = 2; + var last: usize = j; + + // Match 1 or more non-path separators + while (j < len and !isSepT(T, path[j])) { + j += 1; + } + + if (j < len and j != last) { + // Matched! + last = j; + + // Match 1 or more path separators + while (j < len and isSepT(T, path[j])) { + j += 1; + } + + if (j < len and j != last) { + // Matched! + last = j; + + // Match 1 or more non-path separators + while (j < len and !isSepT(T, path[j])) { + j += 1; + } + + if (j == len) { + // We matched a UNC root only + return path; + } + + if (j != last) { + // We matched a UNC root with leftovers + + // Offset by 1 to include the separator after the UNC root to + // treat it as a "normal root" on top of a (UNC) root + offset = j + 1; + rootEnd = offset; + } + } + } + } + // Possible device root + } else if (isWindowsDeviceRootT(T, byte0) and path[1] == CHAR_COLON) { + offset = if (len > 2 and isSepT(T, path[2])) 3 else 2; + rootEnd = offset; + } + + // We use an optional value instead of -1, as in Node code, for easier number type use. + var end: ?usize = null; + var matchedSlash: bool = true; + + var i_i64 = @as(i64, @intCast(len - 1)); + while (i_i64 >= offset) : (i_i64 -= 1) { + const i = @as(usize, @intCast(i_i64)); + if (isSepT(T, path[i])) { + if (!matchedSlash) { + end = i; + break; + } + } else { + // We saw the first non-path separator + matchedSlash = false; + } + } + + if (end) |_end| { + return path[0.._end]; + } + + return if (rootEnd) |_rootEnd| + path[0.._rootEnd] + else + comptime L(T, CHAR_STR_DOT); +} + +pub inline fn dirnamePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) JSC.JSValue { + return toJSString(globalObject, dirnamePosixT(T, path)); +} + +pub inline fn dirnameWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) JSC.JSValue { + return toJSString(globalObject, dirnameWindowsT(T, path)); +} + +pub inline fn dirnameJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, isWindows: bool, path: []const T) JSC.JSValue { + return if (isWindows) + dirnameWindowsJS_T(T, globalObject, path) + else + dirnamePosixJS_T(T, globalObject, path); +} + +pub fn dirname(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { + const path_ptr = if (args_len > 0) args_ptr[0] else JSC.JSValue.jsUndefined(); + // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. + validateString(globalObject, path_ptr, "path", .{}) catch { + // Returning .zero translates to a nullprt JSC.JSValue. + return .zero; + }; + + const pathZStr = path_ptr.getZigString(globalObject); + if (pathZStr.len == 0) return toJSString(globalObject, CHAR_STR_DOT); + + var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, JSC.getAllocator(globalObject)); + const allocator = stack_fallback.get(); + + const pathZSlice = pathZStr.toSlice(allocator); + defer pathZSlice.deinit(); + return dirnameJS_T(u8, globalObject, isWindows, pathZSlice.slice()); +} + +/// Based on Node v21.6.1 path.posix.extname: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1278 +pub fn extnamePosixT(comptime T: type, path: []const T) []const T { + comptime validatePathT(T, "extnamePosixT"); + + // validateString of `path` is performed in pub fn extname. + const len = path.len; + // Exit early for easier number type use. + if (len == 0) { + return comptime L(T, ""); + } + // We use an optional value instead of -1, as in Node code, for easier number type use. + var startDot: ?usize = null; + var startPart: usize = 0; + // We use an optional value instead of -1, as in Node code, for easier number type use. + var end: ?usize = null; + var matchedSlash: bool = true; + // Track the state of characters (if any) we see before our first dot and + // after any path separator we find + + // We use an optional value instead of -1, as in Node code, for easier number type use. + var preDotState: ?usize = 0; + + var i_i64 = @as(i64, @intCast(len - 1)); + while (i_i64 > -1) : (i_i64 -= 1) { + const i = @as(usize, @intCast(i_i64)); + const byte = path[i]; + if (byte == CHAR_FORWARD_SLASH) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + startPart = i + 1; + break; + } + continue; + } + + if (end == null) { + // We saw the first non-path separator, mark this as the end of our + // extension + matchedSlash = false; + end = i + 1; + } + + if (byte == CHAR_DOT) { + // If this is our first dot, mark it as the start of our extension + if (startDot == null) { + startDot = i; + } else if (preDotState != null and preDotState.? != 1) { + preDotState = 1; + } + } else if (startDot != null) { + // We saw a non-dot and non-path separator before our dot, so we should + // have a good chance at having a non-empty extension + preDotState = null; + } + } + + const _end = if (end) |_e| _e else 0; + const _preDotState = if (preDotState) |_p| _p else 0; + const _startDot = if (startDot) |_s| _s else 0; + if (startDot == null or + end == null or + // We saw a non-dot character immediately before the dot + (preDotState != null and _preDotState == 0) or + // The (right-most) trimmed path component is exactly '..' + (_preDotState == 1 and + _startDot == _end - 1 and + _startDot == startPart + 1)) + { + return comptime L(T, ""); + } + + return path[_startDot.._end]; +} + +/// Based on Node v21.6.1 path.win32.extname: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L840 +pub fn extnameWindowsT(comptime T: type, path: []const T) []const T { + comptime validatePathT(T, "extnameWindowsT"); + + // validateString of `path` is performed in pub fn extname. + const len = path.len; + // Exit early for easier number type use. + if (len == 0) { + return comptime L(T, ""); + } + var start: usize = 0; + // We use an optional value instead of -1, as in Node code, for easier number type use. + var startDot: ?usize = null; + var startPart: usize = 0; + // We use an optional value instead of -1, as in Node code, for easier number type use. + var end: ?usize = null; + var matchedSlash: bool = true; + // Track the state of characters (if any) we see before our first dot and + // after any path separator we find + + // We use an optional value instead of -1, as in Node code, for easier number type use. + var preDotState: ?usize = 0; + + // Check for a drive letter prefix so as not to mistake the following + // path separator as an extra separator at the end of the path that can be + // disregarded + + if (len >= 2 and + path[1] == CHAR_COLON and + isWindowsDeviceRootT(T, path[0])) + { + start = 2; + startPart = start; + } + + var i_i64 = @as(i64, @intCast(len - 1)); + while (i_i64 >= start) : (i_i64 -= 1) { + const i = @as(usize, @intCast(i_i64)); + const byte = path[i]; + if (isSepWindowsT(T, byte)) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + startPart = i + 1; + break; + } + continue; + } + if (end == null) { + // We saw the first non-path separator, mark this as the end of our + // extension + matchedSlash = false; + end = i + 1; + } + if (byte == CHAR_DOT) { + // If this is our first dot, mark it as the start of our extension + if (startDot == null) { + startDot = i; + } else if (preDotState) |_preDotState| { + if (_preDotState != 1) { + preDotState = 1; + } + } + } else if (startDot != null) { + // We saw a non-dot and non-path separator before our dot, so we should + // have a good chance at having a non-empty extension + preDotState = null; + } + } + + const _end = if (end) |_e| _e else 0; + const _preDotState = if (preDotState) |_p| _p else 0; + const _startDot = if (startDot) |_s| _s else 0; + if (startDot == null or + end == null or + // We saw a non-dot character immediately before the dot + (preDotState != null and _preDotState == 0) or + // The (right-most) trimmed path component is exactly '..' + (_preDotState == 1 and + _startDot == _end - 1 and + _startDot == startPart + 1)) + { + return comptime L(T, ""); + } + + return path[_startDot.._end]; +} + +pub inline fn extnamePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) JSC.JSValue { + return toJSString(globalObject, extnamePosixT(T, path)); +} + +pub inline fn extnameWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) JSC.JSValue { + return toJSString(globalObject, extnameWindowsT(T, path)); +} + +pub inline fn extnameJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, isWindows: bool, path: []const T) JSC.JSValue { + return if (isWindows) + extnameWindowsJS_T(T, globalObject, path) + else + extnamePosixJS_T(T, globalObject, path); +} + +pub fn extname(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { + const path_ptr = if (args_len > 0) args_ptr[0] else JSC.JSValue.jsUndefined(); + // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. + validateString(globalObject, path_ptr, "path", .{}) catch { + // Returning .zero translates to a nullprt JSC.JSValue. + return .zero; + }; + + const pathZStr = path_ptr.getZigString(globalObject); + if (pathZStr.len == 0) return path_ptr; + + var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, JSC.getAllocator(globalObject)); + const allocator = stack_fallback.get(); + + const pathZSlice = pathZStr.toSlice(allocator); + defer pathZSlice.deinit(); + return extnameJS_T(u8, globalObject, isWindows, pathZSlice.slice()); +} + +/// Based on Node v21.6.1 private helper _format: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L145 +fn _formatT(comptime T: type, pathObject: PathParsed(T), sep: T, buf: []T) []const T { + comptime validatePathT(T, "_formatT"); + + // validateObject of `pathObject` is performed in pub fn format. + const root = pathObject.root; + const dir = pathObject.dir; + const base = pathObject.base; + const ext = pathObject.ext; + // Prefix with _ to avoid shadowing the identifier in the outer scope. + const _name = pathObject.name; + + // Translated from the following JS code: + // const dir = pathObject.dir || pathObject.root; + const dirIsRoot = dir.len == 0 or std.mem.eql(u8, dir, root); + const dirOrRoot = if (dirIsRoot) root else dir; + const dirLen = dirOrRoot.len; + + var bufOffset: usize = 0; + var bufSize: usize = 0; + + // Translated from the following JS code: + // const base = pathObject.base || + // `${pathObject.name || ''}${formatExt(pathObject.ext)}`; + var baseLen = base.len; + var baseOrNameExt = base; + if (baseLen > 0) { + @memcpy(buf[0..baseLen], base); + } else { + const formattedExt = formatExtT(T, ext, buf); + const nameLen = _name.len; + const extLen = formattedExt.len; + bufOffset = nameLen; + bufSize = bufOffset + extLen; + if (extLen > 0) { + // Move all bytes to the right by _name.len. + // Use bun.copy because formattedExt and buf overlap. + bun.copy(T, buf[bufOffset..bufSize], formattedExt); + } + if (nameLen > 0) { + @memcpy(buf[0..nameLen], _name); + } + if (bufSize > 0) { + baseOrNameExt = buf[0..bufSize]; + } + } + + // Translated from the following JS code: + // if (!dir) { + // return base; + // } + if (dirLen == 0) { + return baseOrNameExt; + } + + // Translated from the following JS code: + // return dir === pathObject.root ? `${dir}${base}` : `${dir}${sep}${base}`; + baseLen = baseOrNameExt.len; + if (baseLen > 0) { + bufOffset = if (dirIsRoot) dirLen else dirLen + 1; + bufSize = bufOffset + baseLen; + // Move all bytes to the right by dirLen + (maybe 1 for the separator). + // Use bun.copy because baseOrNameExt and buf overlap. + bun.copy(T, buf[bufOffset..bufSize], baseOrNameExt); + } + @memcpy(buf[0..dirLen], dirOrRoot); + bufSize = dirLen + baseLen; + if (!dirIsRoot) { + bufSize += 1; + buf[dirLen] = sep; + } + return buf[0..bufSize]; +} + +pub inline fn formatPosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, pathObject: PathParsed(T), buf: []T) JSC.JSValue { + return toJSString(globalObject, _formatT(T, pathObject, CHAR_FORWARD_SLASH, buf)); +} + +pub inline fn formatWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, pathObject: PathParsed(T), buf: []T) JSC.JSValue { + return toJSString(globalObject, _formatT(T, pathObject, CHAR_BACKWARD_SLASH, buf)); +} + +pub fn formatJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, pathObject: PathParsed(T)) JSC.JSValue { + const baseLen = pathObject.base.len; + const dirLen = pathObject.dir.len; + // Add one for the possible separator. + const bufLen: usize = @max(1 + + (if (dirLen > 0) dirLen else pathObject.root.len) + + (if (baseLen > 0) baseLen else pathObject.name.len + pathObject.ext.len), PATH_SIZE(T)); + const buf = allocator.alloc(T, bufLen) catch bun.outOfMemory(); + defer allocator.free(buf); + return if (isWindows) formatWindowsJS_T(T, globalObject, pathObject, buf) else formatPosixJS_T(T, globalObject, pathObject, buf); +} + +pub fn format(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { + const pathObject_ptr = if (args_len > 0) args_ptr[0] else JSC.JSValue.jsUndefined(); + // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. + validateObject(globalObject, pathObject_ptr, "pathObject", .{}, .{}) catch { + // Returning .zero translates to a nullprt JSC.JSValue. + return .zero; + }; + + var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, JSC.getAllocator(globalObject)); + const allocator = stack_fallback.get(); + + var root: []const u8 = ""; + if (pathObject_ptr.getTruthy(globalObject, "root")) |jsValue| { + root = jsValue.toSlice(globalObject, allocator).slice(); + } + var dir: []const u8 = ""; + if (pathObject_ptr.getTruthy(globalObject, "dir")) |jsValue| { + dir = jsValue.toSlice(globalObject, allocator).slice(); + } + var base: []const u8 = ""; + if (pathObject_ptr.getTruthy(globalObject, "base")) |jsValue| { + base = jsValue.toSlice(globalObject, allocator).slice(); + } + // Prefix with _ to avoid shadowing the identifier in the outer scope. + var _name: []const u8 = ""; + if (pathObject_ptr.getTruthy(globalObject, "name")) |jsValue| { + _name = jsValue.toSlice(globalObject, allocator).slice(); + } + var ext: []const u8 = ""; + if (pathObject_ptr.getTruthy(globalObject, "ext")) |jsValue| { + ext = jsValue.toSlice(globalObject, allocator).slice(); + } + return formatJS_T(u8, globalObject, allocator, isWindows, .{ .root = root, .dir = dir, .base = base, .ext = ext, .name = _name }); +} + +/// Based on Node v21.6.1 path.posix.isAbsolute: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1159 +pub inline fn isAbsolutePosixT(comptime T: type, path: []const T) bool { + // validateString of `path` is performed in pub fn isAbsolute. + return path.len > 0 and path[0] == CHAR_FORWARD_SLASH; +} + +/// Based on Node v21.6.1 path.win32.isAbsolute: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L406 +pub fn isAbsoluteWindowsT(comptime T: type, path: []const T) bool { + // validateString of `path` is performed in pub fn isAbsolute. + const len = path.len; + if (len == 0) + return false; + + const byte0 = path[0]; + return isSepWindowsT(T, byte0) or + // Possible device root + (len > 2 and + isWindowsDeviceRootT(T, byte0) and + path[1] == CHAR_COLON and + isSepWindowsT(T, path[2])); +} + +pub fn isAbsolutePosixZigString(pathZStr: JSC.ZigString) bool { + const pathZStrTrunc = pathZStr.trunc(1); + return if (pathZStrTrunc.len > 0 and pathZStrTrunc.is16Bit()) + isAbsolutePosixT(u16, pathZStrTrunc.utf16SliceAligned()) + else + isAbsolutePosixT(u8, pathZStrTrunc.slice()); +} + +pub fn isAbsoluteWindowsZigString(pathZStr: JSC.ZigString) bool { + return if (pathZStr.len > 0 and pathZStr.is16Bit()) + isAbsoluteWindowsT(u16, @alignCast(pathZStr.utf16Slice())) + else + isAbsoluteWindowsT(u8, pathZStr.slice()); +} + +pub fn isAbsolute(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { + const path_ptr = if (args_len > 0) args_ptr[0] else JSC.JSValue.jsUndefined(); + // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. + validateString(globalObject, path_ptr, "path", .{}) catch { + // Returning .zero translates to a nullprt JSC.JSValue. + return .zero; + }; + + const pathZStr = path_ptr.getZigString(globalObject); + if (pathZStr.len == 0) return JSC.JSValue.jsBoolean(false); + if (isWindows) return JSC.JSValue.jsBoolean(isAbsoluteWindowsZigString(pathZStr)); + return JSC.JSValue.jsBoolean(isAbsolutePosixZigString(pathZStr)); +} + +pub inline fn isSepPosixT(comptime T: type, byte: T) bool { + return byte == CHAR_FORWARD_SLASH; +} + +pub inline fn isSepWindowsT(comptime T: type, byte: T) bool { + return byte == CHAR_FORWARD_SLASH or byte == CHAR_BACKWARD_SLASH; +} + +/// Based on Node v21.6.1 private helper isWindowsDeviceRoot: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L60C10-L60C29 +pub inline fn isWindowsDeviceRootT(comptime T: type, byte: T) bool { + return (byte >= 'A' and byte <= 'Z') or (byte >= 'a' and byte <= 'z'); +} + +/// Based on Node v21.6.1 path.posix.join: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1169 +pub inline fn joinPosixT(comptime T: type, paths: []const []const T, buf: []T, buf2: []T) []const T { + comptime validatePathT(T, "joinPosixT"); + + if (paths.len == 0) { + return comptime L(T, CHAR_STR_DOT); + } + + var bufSize: usize = 0; + var bufOffset: usize = 0; + + // Back joined by expandable buf2 in case it is long. + var joined: []const T = comptime L(T, ""); + + for (paths) |path| { + // validateString of `path is performed in pub fn join. + // Back our virtual "joined" string by expandable buf2 in + // case it is long. + const len = path.len; + if (len > 0) { + // Translated from the following JS code: + // if (joined === undefined) + // joined = arg; + // else + // joined += `/${arg}`; + if (bufSize != 0) { + bufOffset = bufSize; + bufSize += 1; + buf2[bufOffset] = CHAR_FORWARD_SLASH; + } + bufOffset = bufSize; + bufSize += len; + @memcpy(buf2[bufOffset..bufSize], path); + + joined = buf2[0..bufSize]; + } + } + if (bufSize == 0) { + return comptime L(T, CHAR_STR_DOT); + } + return normalizePosixT(T, joined, buf); +} + +/// Based on Node v21.6.1 path.win32.join: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L425 +pub fn joinWindowsT(comptime T: type, paths: []const []const T, buf: []T, buf2: []T) []const T { + comptime validatePathT(T, "joinWindowsT"); + + if (paths.len == 0) { + return comptime L(T, CHAR_STR_DOT); + } + + const isSepT = isSepWindowsT; + + var bufSize: usize = 0; + var bufOffset: usize = 0; + + // Backed by expandable buf2 in case it is long. + var joined: []const T = comptime L(T, ""); + var firstPart: []const T = comptime L(T, ""); + + for (paths) |path| { + // validateString of `path` is performed in pub fn join. + const len = path.len; + if (len > 0) { + // Translated from the following JS code: + // if (joined === undefined) + // joined = firstPart = arg; + // else + // joined += `\\${arg}`; + bufOffset = bufSize; + if (bufSize == 0) { + bufSize = len; + @memcpy(buf2[0..bufSize], path); + + joined = buf2[0..bufSize]; + firstPart = joined; + } else { + bufOffset = bufSize; + bufSize += 1; + buf2[bufOffset] = CHAR_BACKWARD_SLASH; + bufOffset = bufSize; + bufSize += len; + @memcpy(buf2[bufOffset..bufSize], path); + + joined = buf2[0..bufSize]; + } + } + } + if (bufSize == 0) { + return comptime L(T, CHAR_STR_DOT); + } + + // Make sure that the joined path doesn't start with two slashes, because + // normalize() will mistake it for a UNC path then. + // + // This step is skipped when it is very clear that the user actually + // intended to point at a UNC path. This is assumed when the first + // non-empty string arguments starts with exactly two slashes followed by + // at least one more non-slash character. + // + // Note that for normalize() to treat a path as a UNC path it needs to + // have at least 2 components, so we don't filter for that here. + // This means that the user can use join to construct UNC paths from + // a server name and a share name; for example: + // path.join('//server', 'share') -> '\\\\server\\share\\') + var needsReplace: bool = true; + var slashCount: usize = 0; + if (isSepT(T, firstPart[0])) { + slashCount += 1; + const firstLen = firstPart.len; + if (firstLen > 1 and + isSepT(T, firstPart[1])) + { + slashCount += 1; + if (firstLen > 2) { + if (isSepT(T, firstPart[2])) { + slashCount += 1; + } else { + // We matched a UNC path in the first part + needsReplace = false; + } + } + } + } + if (needsReplace) { + // Find any more consecutive slashes we need to replace + while (slashCount < bufSize and + isSepT(T, joined[slashCount])) + { + slashCount += 1; + } + // Replace the slashes if needed + if (slashCount >= 2) { + // Translated from the following JS code: + // joined = `\\${StringPrototypeSlice(joined, slashCount)}`; + bufOffset = 1; + bufSize = bufOffset + (bufSize - slashCount); + // Move all bytes to the right by slashCount - 1. + // Use bun.copy because joined and buf2 overlap. + bun.copy(u8, buf2[bufOffset..bufSize], joined[slashCount..]); + // Prepend the separator. + buf2[0] = CHAR_BACKWARD_SLASH; + + joined = buf2[0..bufSize]; + } + } + return normalizeWindowsT(T, joined, buf); +} + +pub inline fn joinPosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, paths: []const []const T, buf: []T, buf2: []T) JSC.JSValue { + return toJSString(globalObject, joinPosixT(T, paths, buf, buf2)); +} + +pub inline fn joinWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, paths: []const []const T, buf: []T, buf2: []T) JSC.JSValue { + return toJSString(globalObject, joinWindowsT(T, paths, buf, buf2)); +} + +pub fn joinJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, paths: []const []const T) JSC.JSValue { + // Adding 8 bytes when Windows for the possible UNC root. + var bufLen: usize = if (isWindows) 8 else 0; + for (paths) |path| bufLen += if (bufLen > 0 and path.len > 0) path.len + 1 else path.len; + bufLen = @max(bufLen, PATH_SIZE(T)); + const buf = allocator.alloc(T, bufLen) catch bun.outOfMemory(); + defer allocator.free(buf); + const buf2 = allocator.alloc(T, bufLen) catch bun.outOfMemory(); + defer allocator.free(buf2); + return if (isWindows) joinWindowsJS_T(T, globalObject, paths, buf, buf2) else joinPosixJS_T(T, globalObject, paths, buf, buf2); +} + +pub fn join(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { + if (args_len == 0) return toJSString(globalObject, CHAR_STR_DOT); + + var arena = bun.ArenaAllocator.init(bun.default_allocator); + defer arena.deinit(); + + var stack_fallback = std.heap.stackFallback(stack_fallback_size_large, arena.allocator()); + const allocator = stack_fallback.get(); + + var paths = allocator.alloc(string, args_len) catch bun.outOfMemory(); + defer allocator.free(paths); + + for (0..args_len, args_ptr) |i, path_ptr| { + // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. + validateString(globalObject, path_ptr, "paths[{d}]", .{i}) catch { + // Returning .zero translates to a nullprt JSC.JSValue. + return .zero; + }; + const pathZStr = path_ptr.getZigString(globalObject); + paths[i] = if (pathZStr.len > 0) pathZStr.toSlice(allocator).slice() else ""; + } + return joinJS_T(u8, globalObject, allocator, isWindows, paths); +} + +/// Based on Node v21.6.1 private helper normalizeString: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L65C1-L66C77 +/// +/// Resolves . and .. elements in a path with directory names +fn normalizeStringT(comptime T: type, path: []const T, allowAboveRoot: bool, separator: T, comptime platform: bun.path.Platform, buf: []T) []const T { + const len = path.len; + const isSepT = + if (platform == .posix) + isSepPosixT + else + isSepWindowsT; + + var bufOffset: usize = 0; + var bufSize: usize = 0; + + var res: []const T = comptime L(T, ""); + var lastSegmentLength: usize = 0; + // We use an optional value instead of -1, as in Node code, for easier number type use. + var lastSlash: ?usize = null; + // We use an optional value instead of -1, as in Node code, for easier number type use. + var dots: ?usize = 0; + var byte: T = 0; + + var i: usize = 0; + while (i <= len) : (i += 1) { + if (i < len) { + byte = path[i]; + } else if (isSepT(T, byte)) { + break; + } else { + byte = CHAR_FORWARD_SLASH; + } + + if (isSepT(T, byte)) { + // Translated from the following JS code: + // if (lastSlash === i - 1 || dots === 1) { + if ((lastSlash == null and i == 0) or + (lastSlash != null and i > 0 and lastSlash.? == i - 1) or + (dots != null and dots.? == 1)) + { + // NOOP + } else if (dots != null and dots.? == 2) { + if (bufSize < 2 or + lastSegmentLength != 2 or + buf[bufSize - 1] != CHAR_DOT or + buf[bufSize - 2] != CHAR_DOT) + { + if (bufSize > 2) { + const lastSlashIndex = std.mem.lastIndexOfScalar(T, buf[0..bufSize], separator); + if (lastSlashIndex == null) { + res = comptime L(T, ""); + bufSize = 0; + lastSegmentLength = 0; + } else { + bufSize = lastSlashIndex.?; + res = buf[0..bufSize]; + // Translated from the following JS code: + // lastSegmentLength = + // res.length - 1 - StringPrototypeLastIndexOf(res, separator); + const lastIndexOfSep = std.mem.lastIndexOfScalar(T, buf[0..bufSize], separator); + if (lastIndexOfSep == null) { + // Yes (>ლ), Node relies on the -1 result of + // StringPrototypeLastIndexOf(res, separator). + // A - -1 is a positive 1. + // So the code becomes + // lastSegmentLength = res.length - 1 + 1; + // or + // lastSegmentLength = res.length; + lastSegmentLength = bufSize; + } else { + lastSegmentLength = bufSize - 1 - lastIndexOfSep.?; + } + } + lastSlash = i; + dots = 0; + continue; + } else if (bufSize != 0) { + res = comptime L(T, ""); + bufSize = 0; + lastSegmentLength = 0; + lastSlash = i; + dots = 0; + continue; + } + } + if (allowAboveRoot) { + // Translated from the following JS code: + // res += res.length > 0 ? `${separator}..` : '..'; + if (bufSize > 0) { + bufOffset = bufSize; + bufSize += 1; + buf[bufOffset] = separator; + bufOffset = bufSize; + bufSize += 2; + buf[bufOffset] = CHAR_DOT; + buf[bufOffset + 1] = CHAR_DOT; + } else { + bufSize = 2; + buf[0] = CHAR_DOT; + buf[1] = CHAR_DOT; + } + + res = buf[0..bufSize]; + lastSegmentLength = 2; + } + } else { + // Translated from the following JS code: + // if (res.length > 0) + // res += `${separator}${StringPrototypeSlice(path, lastSlash + 1, i)}`; + // else + // res = StringPrototypeSlice(path, lastSlash + 1, i); + if (bufSize > 0) { + bufOffset = bufSize; + bufSize += 1; + buf[bufOffset] = separator; + } + const sliceStart = if (lastSlash != null) lastSlash.? + 1 else 0; + const slice = path[sliceStart..i]; + + bufOffset = bufSize; + bufSize += slice.len; + @memcpy(buf[bufOffset..bufSize], slice); + + res = buf[0..bufSize]; + + // Translated from the following JS code: + // lastSegmentLength = i - lastSlash - 1; + const subtract = if (lastSlash != null) lastSlash.? + 1 else 2; + lastSegmentLength = if (i >= subtract) i - subtract else 0; + } + lastSlash = i; + dots = 0; + continue; + } else if (byte == CHAR_DOT and dots != null) { + dots = if (dots != null) dots.? + 1 else 0; + continue; + } else { + dots = null; + } + } + + return res; +} + +/// Based on Node v21.6.1 path.posix.normalize +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1130 +pub fn normalizePosixT(comptime T: type, path: []const T, buf: []T) []const T { + comptime validatePathT(T, "normalizePosixT"); + + // validateString of `path` is performed in pub fn normalize. + const len = path.len; + if (len == 0) { + return comptime L(T, CHAR_STR_DOT); + } + + // Prefix with _ to avoid shadowing the identifier in the outer scope. + const _isAbsolute = path[0] == CHAR_FORWARD_SLASH; + const trailingSeparator = path[len - 1] == CHAR_FORWARD_SLASH; + + // Normalize the path + var normalizedPath = normalizeStringT(T, path, !_isAbsolute, CHAR_FORWARD_SLASH, .posix, buf); + + var bufSize: usize = normalizedPath.len; + if (bufSize == 0) { + if (_isAbsolute) { + return comptime L(T, CHAR_STR_FORWARD_SLASH); + } + return if (trailingSeparator) + comptime L(T, "./") + else + comptime L(T, CHAR_STR_DOT); + } + + var bufOffset: usize = 0; + + // Translated from the following JS code: + // if (trailingSeparator) + // path += '/'; + if (trailingSeparator) { + bufOffset = bufSize; + bufSize += 1; + buf[bufOffset] = CHAR_FORWARD_SLASH; + normalizedPath = buf[0..bufSize]; + } + + // Translated from the following JS code: + // return isAbsolute ? `/${path}` : path; + if (_isAbsolute) { + bufOffset = 1; + bufSize += 1; + // Move all bytes to the right by 1 for the separator. + // Use bun.copy because normalizedPath and buf overlap. + bun.copy(T, buf[bufOffset..bufSize], normalizedPath); + // Prepend the separator. + buf[0] = CHAR_FORWARD_SLASH; + normalizedPath = buf[0..bufSize]; + } + return normalizedPath[0..bufSize]; +} + +/// Based on Node v21.6.1 path.win32.normalize +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L308 +pub fn normalizeWindowsT(comptime T: type, path: []const T, buf: []T) []const T { + comptime validatePathT(T, "normalizeWindowsT"); + + // validateString of `path` is performed in pub fn normalize. + const len = path.len; + if (len == 0) { + return comptime L(T, CHAR_STR_DOT); + } + + const isSepT = isSepWindowsT; + + // Moved `rootEnd`, `device`, and `_isAbsolute` initialization after + // the `if (len == 1)` check. + const byte0: T = path[0]; + + // Try to match a root + if (len == 1) { + // `path` contains just a single char, exit early to avoid + // unnecessary work + return if (isSepT(T, byte0)) comptime L(T, CHAR_STR_BACKWARD_SLASH) else path; + } + + var rootEnd: usize = 0; + // Backed by buf. + var device: ?[]const T = null; + // Prefix with _ to avoid shadowing the identifier in the outer scope. + var _isAbsolute: bool = false; + + var bufOffset: usize = 0; + var bufSize: usize = 0; + + if (isSepT(T, byte0)) { + // Possible UNC root + + // If we started with a separator, we know we at least have an absolute + // path of some kind (UNC or otherwise) + _isAbsolute = true; + + if (isSepT(T, path[1])) { + // Matched double path separator at beginning + var j: usize = 2; + var last: usize = j; + // Match 1 or more non-path separators + while (j < len and + !isSepT(T, path[j])) + { + j += 1; + } + if (j < len and j != last) { + const firstPart: []const u8 = path[last..j]; + // Matched! + last = j; + // Match 1 or more path separators + while (j < len and + isSepT(T, path[j])) + { + j += 1; + } + if (j < len and j != last) { + // Matched! + last = j; + // Match 1 or more non-path separators + while (j < len and + !isSepT(T, path[j])) + { + j += 1; + } + if (j == len) { + // We matched a UNC root only + // Return the normalized version of the UNC root since there + // is nothing left to process + + // Translated from the following JS code: + // return `\\\\${firstPart}\\${StringPrototypeSlice(path, last)}\\`; + bufSize = 2; + buf[0] = CHAR_BACKWARD_SLASH; + buf[1] = CHAR_BACKWARD_SLASH; + bufOffset = bufSize; + bufSize += firstPart.len; + @memcpy(buf[bufOffset..bufSize], firstPart); + bufOffset = bufSize; + bufSize += 1; + buf[bufOffset] = CHAR_BACKWARD_SLASH; + bufOffset = bufSize; + bufSize += len - last; + @memcpy(buf[bufOffset..bufSize], path[last..len]); + bufOffset = bufSize; + bufSize += 1; + buf[bufOffset] = CHAR_BACKWARD_SLASH; + return buf[0..bufSize]; + } + if (j != last) { + // We matched a UNC root with leftovers + + // Translated from the following JS code: + // device = + // `\\\\${firstPart}\\${StringPrototypeSlice(path, last, j)}`; + // rootEnd = j; + bufSize = 2; + buf[0] = CHAR_BACKWARD_SLASH; + buf[1] = CHAR_BACKWARD_SLASH; + bufOffset = bufSize; + bufSize += firstPart.len; + @memcpy(buf[bufOffset..bufSize], firstPart); + bufOffset = bufSize; + bufSize += 1; + buf[bufOffset] = CHAR_BACKWARD_SLASH; + bufOffset = bufSize; + bufSize += j - last; + @memcpy(buf[bufOffset..bufSize], path[last..j]); + + device = buf[0..bufSize]; + rootEnd = j; + } + } + } + } else { + rootEnd = 1; + } + } else if (isWindowsDeviceRootT(T, byte0) and + path[1] == CHAR_COLON) + { + // Possible device root + buf[0] = byte0; + buf[1] = CHAR_COLON; + device = buf[0..2]; + rootEnd = 2; + if (len > 2 and isSepT(T, path[2])) { + // Treat separator following drive name as an absolute path + // indicator + _isAbsolute = true; + rootEnd = 3; + } + } + + bufOffset = (if (device) |_d| _d.len else 0) + @intFromBool(_isAbsolute); + // Backed by buf at an offset of device.len + 1 if _isAbsolute is true. + var tailLen = if (rootEnd < len) normalizeStringT(T, path[rootEnd..len], !_isAbsolute, CHAR_BACKWARD_SLASH, .windows, buf[bufOffset..]).len else 0; + if (tailLen == 0 and !_isAbsolute) { + buf[bufOffset] = CHAR_DOT; + tailLen = 1; + } + + if (tailLen > 0 and + isSepT(T, path[len - 1])) + { + // Translated from the following JS code: + // tail += '\\'; + buf[bufOffset + tailLen] = CHAR_BACKWARD_SLASH; + tailLen += 1; + } + + bufSize = bufOffset + tailLen; + // Translated from the following JS code: + // if (device === undefined) { + // return isAbsolute ? `\\${tail}` : tail; + // } + // return isAbsolute ? `${device}\\${tail}` : `${device}${tail}`; + if (_isAbsolute) { + bufOffset -= 1; + // Prepend the separator. + buf[bufOffset] = CHAR_BACKWARD_SLASH; + } + return buf[0..bufSize]; +} + +pub fn normalizeT(comptime T: type, path: []const T, buf: []T) []const T { + return switch (Environment.os) { + .windows => normalizeWindowsT(T, path, buf), + else => normalizePosixT(T, path, buf), + }; +} + +pub inline fn normalizePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T, buf: []T) JSC.JSValue { + return toJSString(globalObject, normalizePosixT(T, path, buf)); +} + +pub inline fn normalizeWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T, buf: []T) JSC.JSValue { + return toJSString(globalObject, normalizeWindowsT(T, path, buf)); +} + +pub fn normalizeJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, path: []const T) JSC.JSValue { + const bufLen = @max(path.len, PATH_SIZE(T)); + const buf = allocator.alloc(T, bufLen) catch bun.outOfMemory(); + defer allocator.free(buf); + return if (isWindows) normalizeWindowsJS_T(T, globalObject, path, buf) else normalizePosixJS_T(T, globalObject, path, buf); +} + +pub fn normalize(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { + const path_ptr = if (args_len > 0) args_ptr[0] else JSC.JSValue.jsUndefined(); + // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. + validateString(globalObject, path_ptr, "path", .{}) catch { + // Returning .zero translates to a nullprt JSC.JSValue. + return .zero; + }; + const pathZStr = path_ptr.getZigString(globalObject); + const len = pathZStr.len; + if (len == 0) return toJSString(globalObject, CHAR_STR_DOT); + + var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, JSC.getAllocator(globalObject)); + const allocator = stack_fallback.get(); + + const pathZSlice = pathZStr.toSlice(allocator); + defer pathZSlice.deinit(); + return normalizeJS_T(u8, globalObject, allocator, isWindows, pathZSlice.slice()); +} + +// Based on Node v21.6.1 path.posix.parse +// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1452 +pub fn parsePosixT(comptime T: type, path: []const T) PathParsed(T) { + comptime validatePathT(T, "parsePosixT"); + + // validateString of `path` is performed in pub fn parse. + const len = path.len; + if (len == 0) { + return .{}; + } + + var root: []const T = comptime L(T, ""); + var dir: []const T = comptime L(T, ""); + var base: []const T = comptime L(T, ""); + var ext: []const T = comptime L(T, ""); + // Prefix with _ to avoid shadowing the identifier in the outer scope. + var _name: []const T = comptime L(T, ""); + // Prefix with _ to avoid shadowing the identifier in the outer scope. + const _isAbsolute = path[0] == CHAR_FORWARD_SLASH; + var start: usize = 0; + if (_isAbsolute) { + root = comptime L(T, CHAR_STR_FORWARD_SLASH); + start = 1; + } + + // We use an optional value instead of -1, as in Node code, for easier number type use. + var startDot: ?usize = null; + var startPart: usize = 0; + // We use an optional value instead of -1, as in Node code, for easier number type use. + var end: ?usize = null; + var matchedSlash = true; + var i_i64 = @as(i64, @intCast(len - 1)); + + // Track the state of characters (if any) we see before our first dot and + // after any path separator we find + + // We use an optional value instead of -1, as in Node code, for easier number type use. + var preDotState: ?usize = 0; + + // Get non-dir info + while (i_i64 >= start) : (i_i64 -= 1) { + const i = @as(usize, @intCast(i_i64)); + const byte = path[i]; + if (byte == CHAR_FORWARD_SLASH) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + startPart = i + 1; + break; + } + continue; + } + if (end == null) { + // We saw the first non-path separator, mark this as the end of our + // extension + matchedSlash = false; + end = i + 1; + } + if (byte == CHAR_DOT) { + // If this is our first dot, mark it as the start of our extension + if (startDot == null) { + startDot = i; + } else if (preDotState) |_preDotState| { + if (_preDotState != 1) { + preDotState = 1; + } + } + } else if (startDot != null) { + // We saw a non-dot and non-path separator before our dot, so we should + // have a good chance at having a non-empty extension + preDotState = null; + } + } + + if (end) |_end| { + const _preDotState = if (preDotState) |_p| _p else 0; + const _startDot = if (startDot) |_s| _s else 0; + start = if (startPart == 0 and _isAbsolute) 1 else startPart; + if (startDot == null or + // We saw a non-dot character immediately before the dot + (preDotState != null and _preDotState == 0) or + // The (right-most) trimmed path component is exactly '..' + (_preDotState == 1 and + _startDot == _end - 1 and + _startDot == startPart + 1)) + { + _name = path[start.._end]; + base = _name; + } else { + _name = path[start.._startDot]; + base = path[start.._end]; + ext = path[_startDot.._end]; + } + } + + if (startPart > 0) { + dir = path[0..(startPart - 1)]; + } else if (_isAbsolute) { + dir = comptime L(T, CHAR_STR_FORWARD_SLASH); + } + + return .{ .root = root, .dir = dir, .base = base, .ext = ext, .name = _name }; +} + +// Based on Node v21.6.1 path.win32.parse +// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L916 +pub fn parseWindowsT(comptime T: type, path: []const T) PathParsed(T) { + comptime validatePathT(T, "parseWindowsT"); + + // validateString of `path` is performed in pub fn parse. + var root: []const T = comptime L(T, ""); + var dir: []const T = comptime L(T, ""); + var base: []const T = comptime L(T, ""); + var ext: []const T = comptime L(T, ""); + // Prefix with _ to avoid shadowing the identifier in the outer scope. + var _name: []const T = comptime L(T, ""); + + const len = path.len; + if (len == 0) { + return .{ .root = root, .dir = dir, .base = base, .ext = ext, .name = _name }; + } + + const isSepT = isSepWindowsT; + + var rootEnd: usize = 0; + var byte = path[0]; + + if (len == 1) { + if (isSepT(T, byte)) { + // `path` contains just a path separator, exit early to avoid + // unnecessary work + root = path; + dir = path; + } else { + base = path; + _name = path; + } + return .{ .root = root, .dir = dir, .base = base, .ext = ext, .name = _name }; + } + + // Try to match a root + if (isSepT(T, byte)) { + // Possible UNC root + + rootEnd = 1; + if (isSepT(T, path[1])) { + // Matched double path separator at the beginning + var j: usize = 2; + var last: usize = j; + // Match 1 or more non-path separators + while (j < len and + !isSepT(T, path[j])) + { + j += 1; + } + if (j < len and j != last) { + // Matched! + last = j; + // Match 1 or more path separators + while (j < len and + isSepT(T, path[j])) + { + j += 1; + } + if (j < len and j != last) { + // Matched! + last = j; + // Match 1 or more non-path separators + while (j < len and + !isSepT(T, path[j])) + { + j += 1; + } + if (j == len) { + // We matched a UNC root only + rootEnd = j; + } else if (j != last) { + // We matched a UNC root with leftovers + rootEnd = j + 1; + } + } + } + } + } else if (isWindowsDeviceRootT(T, byte) and + path[1] == CHAR_COLON) + { + // Possible device root + if (len <= 2) { + // `path` contains just a drive root, exit early to avoid + // unnecessary work + root = path; + dir = path; + return .{ .root = root, .dir = dir, .base = base, .ext = ext, .name = _name }; + } + rootEnd = 2; + if (isSepT(T, path[2])) { + if (len == 3) { + // `path` contains just a drive root, exit early to avoid + // unnecessary work + root = path; + dir = path; + return .{ .root = root, .dir = dir, .base = base, .ext = ext, .name = _name }; + } + rootEnd = 3; + } + } + if (rootEnd > 0) { + root = path[0..rootEnd]; + } + + // We use an optional value instead of -1, as in Node code, for easier number type use. + var startDot: ?usize = null; + var startPart = rootEnd; + // We use an optional value instead of -1, as in Node code, for easier number type use. + var end: ?usize = null; + var matchedSlash = true; + var i_i64 = @as(i64, @intCast(len - 1)); + + // Track the state of characters (if any) we see before our first dot and + // after any path separator we find + + // We use an optional value instead of -1, as in Node code, for easier number type use. + var preDotState: ?usize = 0; + + // Get non-dir info + while (i_i64 >= rootEnd) : (i_i64 -= 1) { + const i = @as(usize, @intCast(i_i64)); + byte = path[i]; + if (isSepT(T, byte)) { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) { + startPart = i + 1; + break; + } + continue; + } + if (end == null) { + // We saw the first non-path separator, mark this as the end of our + // extension + matchedSlash = false; + end = i + 1; + } + if (byte == CHAR_DOT) { + // If this is our first dot, mark it as the start of our extension + if (startDot == null) { + startDot = i; + } else if (preDotState) |_preDotState| { + if (_preDotState != 1) { + preDotState = 1; + } + } + } else if (startDot != null) { + // We saw a non-dot and non-path separator before our dot, so we should + // have a good chance at having a non-empty extension + preDotState = null; + } + } + + if (end) |_end| { + const _preDotState = if (preDotState) |_p| _p else 0; + const _startDot = if (startDot) |_s| _s else 0; + if (startDot == null or + // We saw a non-dot character immediately before the dot + (preDotState != null and _preDotState == 0) or + // The (right-most) trimmed path component is exactly '..' + (_preDotState == 1 and + _startDot == _end - 1 and + _startDot == startPart + 1)) + { + // Prefix with _ to avoid shadowing the identifier in the outer scope. + _name = path[startPart.._end]; + base = _name; + } else { + _name = path[startPart.._startDot]; + base = path[startPart.._end]; + ext = path[_startDot.._end]; + } + } + + // If the directory is the root, use the entire root as the `dir` including + // the trailing slash if any (`C:\abc` -> `C:\`). Otherwise, strip out the + // trailing slash (`C:\abc\def` -> `C:\abc`). + if (startPart > 0 and startPart != rootEnd) { + dir = path[0..(startPart - 1)]; + } else { + dir = root; + } + + return .{ .root = root, .dir = dir, .base = base, .ext = ext, .name = _name }; +} + +pub inline fn parsePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) JSC.JSValue { + return parsePosixT(T, path).toJSObject(globalObject); +} + +pub inline fn parseWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) JSC.JSValue { + return parseWindowsT(T, path).toJSObject(globalObject); +} + +pub inline fn parseJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, isWindows: bool, path: []const T) JSC.JSValue { + return if (isWindows) parseWindowsJS_T(T, globalObject, path) else parsePosixJS_T(T, globalObject, path); +} + +pub fn parse(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { + const path_ptr = if (args_len > 0) args_ptr[0] else JSC.JSValue.jsUndefined(); + // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. + validateString(globalObject, path_ptr, "path", .{}) catch { + // Returning .zero translates to a nullprt JSC.JSValue. + return .zero; + }; + + const pathZStr = path_ptr.getZigString(globalObject); + if (pathZStr.len == 0) return (PathParsed(u8){}).toJSObject(globalObject); + + var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, JSC.getAllocator(globalObject)); + const allocator = stack_fallback.get(); + + const pathZSlice = pathZStr.toSlice(allocator); + defer pathZSlice.deinit(); + return parseJS_T(u8, globalObject, isWindows, pathZSlice.slice()); +} + +/// Based on Node v21.6.1 path.posix.relative: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1193 +pub fn relativePosixT(comptime T: type, from: []const T, to: []const T, buf: []T, buf2: []T, buf3: []T) MaybeSlice(T) { + comptime validatePathT(T, "relativePosixT"); + + // validateString of `from` and `to` are performed in pub fn relative. + if (std.mem.eql(T, from, to)) { + return MaybeSlice(T){ .result = comptime L(T, "") }; + } + + // Trim leading forward slashes. + // Backed by expandable buf2 because fromOrig may be long. + const fromOrig = switch (resolvePosixT(T, &.{from}, buf2, buf3)) { + .result => |r| r, + .err => |e| return MaybeSlice(T){ .err = e }, + }; + const fromOrigLen = fromOrig.len; + // Backed by buf. + const toOrig = switch (resolvePosixT(T, &.{to}, buf, buf3)) { + .result => |r| r, + .err => |e| return MaybeSlice(T){ .err = e }, + }; + + if (std.mem.eql(T, fromOrig, toOrig)) { + return MaybeSlice(T){ .result = comptime L(T, "") }; + } + + const fromStart = 1; + const fromEnd = fromOrigLen; + const fromLen = fromEnd - fromStart; + const toOrigLen = toOrig.len; + var toStart: usize = 1; + const toLen = toOrigLen - toStart; + + // Compare paths to find the longest common path from root + const smallestLength = @min(fromLen, toLen); + // We use an optional value instead of -1, as in Node code, for easier number type use. + var lastCommonSep: ?usize = null; + + var matchesAllOfSmallest = false; + // Add a block to isolate `i`. + { + var i: usize = 0; + while (i < smallestLength) : (i += 1) { + const fromByte = fromOrig[fromStart + i]; + if (fromByte != toOrig[toStart + i]) { + break; + } else if (fromByte == CHAR_FORWARD_SLASH) { + lastCommonSep = i; + } + } + matchesAllOfSmallest = i == smallestLength; + } + if (matchesAllOfSmallest) { + if (toLen > smallestLength) { + if (toOrig[toStart + smallestLength] == CHAR_FORWARD_SLASH) { + // We get here if `from` is the exact base path for `to`. + // For example: from='/foo/bar'; to='/foo/bar/baz' + return MaybeSlice(T){ .result = toOrig[toStart + smallestLength + 1 .. toOrigLen] }; + } + if (smallestLength == 0) { + // We get here if `from` is the root + // For example: from='/'; to='/foo' + return MaybeSlice(T){ .result = toOrig[toStart + smallestLength .. toOrigLen] }; + } + } else if (fromLen > smallestLength) { + if (fromOrig[fromStart + smallestLength] == CHAR_FORWARD_SLASH) { + // We get here if `to` is the exact base path for `from`. + // For example: from='/foo/bar/baz'; to='/foo/bar' + lastCommonSep = smallestLength; + } else if (smallestLength == 0) { + // We get here if `to` is the root. + // For example: from='/foo/bar'; to='/' + lastCommonSep = 0; + } + } + } + + var bufOffset: usize = 0; + var bufSize: usize = 0; + + // Backed by buf3. + var out: []const T = comptime L(T, ""); + // Add a block to isolate `i`. + { + // Generate the relative path based on the path difference between `to` + // and `from`. + + // Translated from the following JS code: + // for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) { + var i: usize = fromStart + (if (lastCommonSep != null) lastCommonSep.? + 1 else 0); + while (i <= fromEnd) : (i += 1) { + if (i == fromEnd or fromOrig[i] == CHAR_FORWARD_SLASH) { + // Translated from the following JS code: + // out += out.length === 0 ? '..' : '/..'; + if (out.len > 0) { + bufOffset = bufSize; + bufSize += 3; + buf3[bufOffset] = CHAR_FORWARD_SLASH; + buf3[bufOffset + 1] = CHAR_DOT; + buf3[bufOffset + 2] = CHAR_DOT; + } else { + bufSize = 2; + buf3[0] = CHAR_DOT; + buf3[1] = CHAR_DOT; + } + out = buf3[0..bufSize]; + } + } + } + + // Lastly, append the rest of the destination (`to`) path that comes after + // the common path parts. + + // Translated from the following JS code: + // return `${out}${StringPrototypeSlice(to, toStart + lastCommonSep)}`; + toStart = if (lastCommonSep != null) toStart + lastCommonSep.? else 0; + const sliceSize = toOrigLen - toStart; + const outLen = out.len; + bufSize = outLen; + if (sliceSize > 0) { + bufOffset = bufSize; + bufSize += sliceSize; + // Use bun.copy because toOrig and buf overlap. + bun.copy(T, buf[bufOffset..bufSize], toOrig[toStart..toOrigLen]); + } + if (outLen > 0) { + @memcpy(buf[0..outLen], out); + } + return MaybeSlice(T){ .result = buf[0..bufSize] }; +} + +/// Based on Node v21.6.1 path.win32.relative: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L500 +pub fn relativeWindowsT(comptime T: type, from: []const T, to: []const T, buf: []T, buf2: []T, buf3: []T) MaybeSlice(T) { + comptime validatePathT(T, "relativeWindowsT"); + + // validateString of `from` and `to` are performed in pub fn relative. + if (std.mem.eql(T, from, to)) { + return MaybeSlice(T){ .result = comptime L(T, "") }; + } + + // Backed by expandable buf2 because fromOrig may be long. + const fromOrig = switch (resolveWindowsT(T, &.{from}, buf2, buf3)) { + .result => |r| r, + .err => |e| return MaybeSlice(T){ .err = e }, + }; + const fromOrigLen = fromOrig.len; + // Backed by buf. + const toOrig = switch (resolveWindowsT(T, &.{to}, buf, buf3)) { + .result => |r| r, + .err => |e| return MaybeSlice(T){ .err = e }, + }; + + if (std.mem.eql(T, fromOrig, toOrig) or + eqlIgnoreCaseT(T, fromOrig, toOrig)) + { + return MaybeSlice(T){ .result = comptime L(T, "") }; + } + + const toOrigLen = toOrig.len; + + // Trim leading backslashes + var fromStart: usize = 0; + while (fromStart < fromOrigLen and + fromOrig[fromStart] == CHAR_BACKWARD_SLASH) + { + fromStart += 1; + } + + // Trim trailing backslashes (applicable to UNC paths only) + var fromEnd = fromOrigLen; + while (fromEnd - 1 > fromStart and + fromOrig[fromEnd - 1] == CHAR_BACKWARD_SLASH) + { + fromEnd -= 1; + } + + const fromLen = fromEnd - fromStart; + + // Trim leading backslashes + var toStart: usize = 0; + while (toStart < toOrigLen and + toOrig[toStart] == CHAR_BACKWARD_SLASH) + { + toStart = toStart + 1; + } + + // Trim trailing backslashes (applicable to UNC paths only) + var toEnd = toOrigLen; + while (toEnd - 1 > toStart and + toOrig[toEnd - 1] == CHAR_BACKWARD_SLASH) + { + toEnd -= 1; + } + + const toLen = toEnd - toStart; + + // Compare paths to find the longest common path from root + const smallestLength = @min(fromLen, toLen); + // We use an optional value instead of -1, as in Node code, for easier number type use. + var lastCommonSep: ?usize = null; + + var matchesAllOfSmallest = false; + // Add a block to isolate `i`. + { + var i: usize = 0; + while (i < smallestLength) : (i += 1) { + const fromByte = fromOrig[fromStart + i]; + if (toLowerT(T, fromByte) != toLowerT(T, toOrig[toStart + i])) { + break; + } else if (fromByte == CHAR_BACKWARD_SLASH) { + lastCommonSep = i; + } + } + matchesAllOfSmallest = i == smallestLength; + } + + // We found a mismatch before the first common path separator was seen, so + // return the original `to`. + if (!matchesAllOfSmallest) { + if (lastCommonSep == null) { + return MaybeSlice(T){ .result = toOrig }; + } + } else { + if (toLen > smallestLength) { + if (toOrig[toStart + smallestLength] == CHAR_BACKWARD_SLASH) { + // We get here if `from` is the exact base path for `to`. + // For example: from='C:\foo\bar'; to='C:\foo\bar\baz' + return MaybeSlice(T){ .result = toOrig[toStart + smallestLength + 1 .. toOrigLen] }; + } + if (smallestLength == 2) { + // We get here if `from` is the device root. + // For example: from='C:\'; to='C:\foo' + return MaybeSlice(T){ .result = toOrig[toStart + smallestLength .. toOrigLen] }; + } + } + if (fromLen > smallestLength) { + if (fromOrig[fromStart + smallestLength] == CHAR_BACKWARD_SLASH) { + // We get here if `to` is the exact base path for `from`. + // For example: from='C:\foo\bar'; to='C:\foo' + lastCommonSep = smallestLength; + } else if (smallestLength == 2) { + // We get here if `to` is the device root. + // For example: from='C:\foo\bar'; to='C:\' + lastCommonSep = 3; + } + } + if (lastCommonSep == null) { + lastCommonSep = 0; + } + } + + var bufOffset: usize = 0; + var bufSize: usize = 0; + + // Backed by buf3. + var out: []const T = comptime L(T, ""); + // Add a block to isolate `i`. + { + // Generate the relative path based on the path difference between `to` + // and `from`. + var i: usize = fromStart + (if (lastCommonSep != null) lastCommonSep.? + 1 else 0); + while (i <= fromEnd) : (i += 1) { + if (i == fromEnd or fromOrig[i] == CHAR_BACKWARD_SLASH) { + // Translated from the following JS code: + // out += out.length === 0 ? '..' : '\\..'; + if (out.len > 0) { + bufOffset = bufSize; + bufSize += 3; + buf3[bufOffset] = CHAR_BACKWARD_SLASH; + buf3[bufOffset + 1] = CHAR_DOT; + buf3[bufOffset + 2] = CHAR_DOT; + } else { + bufSize = 2; + buf3[0] = CHAR_DOT; + buf3[1] = CHAR_DOT; + } + out = buf3[0..bufSize]; + } + } + } + + // Translated from the following JS code: + // toStart += lastCommonSep; + if (lastCommonSep == null) { + // If toStart would go negative make it toOrigLen - 1 to + // mimic String#slice with a negative start. + toStart = if (toStart > 0) toStart - 1 else toOrigLen - 1; + } else { + toStart += lastCommonSep.?; + } + + // Lastly, append the rest of the destination (`to`) path that comes after + // the common path parts + const outLen = out.len; + if (outLen > 0) { + const sliceSize = toEnd - toStart; + bufSize = outLen; + if (sliceSize > 0) { + bufOffset = bufSize; + bufSize += sliceSize; + // Use bun.copy because toOrig and buf overlap. + bun.copy(T, buf[bufOffset..bufSize], toOrig[toStart..toEnd]); + } + @memcpy(buf[0..outLen], out); + return MaybeSlice(T){ .result = buf[0..bufSize] }; + } + + if (toOrig[toStart] == CHAR_BACKWARD_SLASH) { + toStart += 1; + } + return MaybeSlice(T){ .result = toOrig[toStart..toEnd] }; +} + +pub inline fn relativePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, from: []const T, to: []const T, buf: []T, buf2: []T, buf3: []T) JSC.JSValue { + return switch (relativePosixT(T, from, to, buf, buf2, buf3)) { + .result => |r| toJSString(globalObject, r), + .err => |e| e.toJSC(globalObject), + }; +} + +pub inline fn relativeWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, from: []const T, to: []const T, buf: []T, buf2: []T, buf3: []T) JSC.JSValue { + return switch (relativeWindowsT(T, from, to, buf, buf2, buf3)) { + .result => |r| toJSString(globalObject, r), + .err => |e| e.toJSC(globalObject), + }; +} + +pub fn relativeJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, from: []const T, to: []const T) JSC.JSValue { + const bufLen = @max(from.len + to.len, PATH_SIZE(T)); + const buf = allocator.alloc(T, bufLen) catch bun.outOfMemory(); + defer allocator.free(buf); + const buf2 = allocator.alloc(T, bufLen) catch bun.outOfMemory(); + defer allocator.free(buf2); + const buf3 = allocator.alloc(T, bufLen) catch bun.outOfMemory(); + defer allocator.free(buf3); + return if (isWindows) relativeWindowsJS_T(T, globalObject, from, to, buf, buf2, buf3) else relativePosixJS_T(T, globalObject, from, to, buf, buf2, buf3); +} + +pub fn relative(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { + const from_ptr = if (args_len > 0) args_ptr[0] else JSC.JSValue.jsUndefined(); + // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. + validateString(globalObject, from_ptr, "from", .{}) catch { + // Returning .zero translates to a nullprt JSC.JSValue. + return .zero; + }; + const to_ptr = if (args_len > 1) args_ptr[1] else JSC.JSValue.jsUndefined(); + // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. + validateString(globalObject, to_ptr, "to", .{}) catch { + return .zero; + }; + + const fromZigStr = from_ptr.getZigString(globalObject); + const toZigStr = to_ptr.getZigString(globalObject); + if ((fromZigStr.len + toZigStr.len) == 0) return from_ptr; + + var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, JSC.getAllocator(globalObject)); + const allocator = stack_fallback.get(); + + var fromZigSlice = fromZigStr.toSlice(allocator); + defer fromZigSlice.deinit(); + var toZigSlice = toZigStr.toSlice(allocator); + defer toZigSlice.deinit(); + return relativeJS_T(u8, globalObject, allocator, isWindows, fromZigSlice.slice(), toZigSlice.slice()); +} + +/// Based on Node v21.6.1 path.posix.resolve: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1095 +pub fn resolvePosixT(comptime T: type, paths: []const []const T, buf: []T, buf2: []T) MaybeSlice(T) { + comptime validatePathT(T, "resolvePosixT"); + + // Backed by expandable buf2 because resolvedPath may be long. + // We use buf2 here because resolvePosixT is called by other methods and using + // buf2 here avoids stepping on others' toes. + var resolvedPath: []const T = comptime L(T, ""); + var resolvedPathLen: usize = 0; + var resolvedAbsolute: bool = false; + + var bufOffset: usize = 0; + var bufSize: usize = 0; + + var i_i64: i64 = if (paths.len == 0) -1 else @as(i64, @intCast(paths.len - 1)); + while (i_i64 > -2 and !resolvedAbsolute) : (i_i64 -= 1) { + var path: []const T = comptime L(T, ""); + if (i_i64 >= 0) { + path = paths[@as(usize, @intCast(i_i64))]; + } else { + // cwd is limited to MAX_PATH_BYTES. + var tmpBuf: [MAX_PATH_SIZE(T)]T = undefined; + path = switch (posixCwdT(T, &tmpBuf)) { + .result => |r| r, + .err => |e| return MaybeSlice(T){ .err = e }, + }; + } + // validateString of `path` is performed in pub fn resolve. + const len = path.len; + + // Skip empty paths. + if (len == 0) { + continue; + } + + // Translated from the following JS code: + // resolvedPath = `${path}/${resolvedPath}`; + if (resolvedPathLen > 0) { + bufOffset = len + 1; + bufSize = bufOffset + resolvedPathLen; + // Move all bytes to the right by path.len + 1 for the separator. + // Use bun.copy because resolvedPath and buf2 overlap. + bun.copy(u8, buf2[bufOffset..bufSize], resolvedPath); + } + bufSize = len; + @memcpy(buf2[0..bufSize], path); + bufSize += 1; + buf2[len] = CHAR_FORWARD_SLASH; + bufSize += resolvedPathLen; + + resolvedPath = buf2[0..bufSize]; + resolvedPathLen = bufSize; + resolvedAbsolute = path[0] == CHAR_FORWARD_SLASH; + } + + // Exit early for empty path. + if (resolvedPathLen == 0) { + return MaybeSlice(T){ .result = comptime L(T, CHAR_STR_DOT) }; + } + + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + + // Normalize the path + resolvedPath = normalizeStringT(T, resolvedPath, !resolvedAbsolute, CHAR_FORWARD_SLASH, .posix, buf); + // resolvedPath is now backed by buf. + resolvedPathLen = resolvedPath.len; + + // Translated from the following JS code: + // if (resolvedAbsolute) { + // return `/${resolvedPath}`; + // } + if (resolvedAbsolute) { + bufSize = resolvedPathLen + 1; + // Use bun.copy because resolvedPath and buf overlap. + bun.copy(T, buf[1..bufSize], resolvedPath); + buf[0] = CHAR_FORWARD_SLASH; + return MaybeSlice(T){ .result = buf[0..bufSize] }; + } + // Translated from the following JS code: + // return resolvedPath.length > 0 ? resolvedPath : '.'; + return MaybeSlice(T){ .result = if (resolvedPathLen > 0) resolvedPath else comptime L(T, CHAR_STR_DOT) }; +} + +/// Based on Node v21.6.1 path.win32.resolve: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L162 +pub fn resolveWindowsT(comptime T: type, paths: []const []const T, buf: []T, buf2: []T) MaybeSlice(T) { + comptime validatePathT(T, "resolveWindowsT"); + + const isSepT = isSepWindowsT; + var tmpBuf: [MAX_PATH_SIZE(T)]T = undefined; + + // Backed by tmpBuf. + var resolvedDevice: []const T = comptime L(T, ""); + var resolvedDeviceLen: usize = 0; + // Backed by expandable buf2 because resolvedTail may be long. + // We use buf2 here because resolvePosixT is called by other methods and using + // buf2 here avoids stepping on others' toes. + var resolvedTail: []const T = comptime L(T, ""); + var resolvedTailLen: usize = 0; + var resolvedAbsolute: bool = false; + + var bufOffset: usize = 0; + var bufSize: usize = 0; + var envPath: ?[]const T = null; + + var i_i64: i64 = if (paths.len == 0) -1 else @as(i64, @intCast(paths.len - 1)); + while (i_i64 > -2) : (i_i64 -= 1) { + // Backed by expandable buf2, to not conflict with buf2 backed resolvedTail, + // because path may be long. + var path: []const T = comptime L(T, ""); + if (i_i64 >= 0) { + path = paths[@as(usize, @intCast(i_i64))]; + // validateString of `path` is performed in pub fn resolve. + + // Skip empty paths. + if (path.len == 0) { + continue; + } + } else if (resolvedDeviceLen == 0) { + // cwd is limited to MAX_PATH_BYTES. + path = switch (getCwdT(T, &tmpBuf)) { + .result => |r| r, + .err => |e| return MaybeSlice(T){ .err = e }, + }; + } else { + // Translated from the following JS code: + // path = process.env[`=${resolvedDevice}`] || process.cwd(); + if (comptime Environment.isWindows) { + // Windows has the concept of drive-specific current working + // directories. If we've resolved a drive letter but not yet an + // absolute path, get cwd for that drive, or the process cwd if + // the drive cwd is not available. We're sure the device is not + // a UNC path at this points, because UNC paths are always absolute. + + // Translated from the following JS code: + // process.env[`=${resolvedDevice}`] + const key_w: [*:0]const u16 = brk: { + if (resolvedDeviceLen == 2 and resolvedDevice[1] == CHAR_COLON) { + // Fast path for device roots + break :brk &[3:0]u16{ '=', resolvedDevice[0], CHAR_COLON }; + } + bufSize = 1; + // Reuse buf2 for the env key because it's used to get the path. + buf2[0] = '='; + bufOffset = bufSize; + bufSize += resolvedDeviceLen; + @memcpy(buf2[bufOffset..bufSize], resolvedDevice); + if (T == u16) { + break :brk buf2[0..bufSize]; + } else { + var u16Buf: bun.WPathBuffer = undefined; + bufSize = std.unicode.utf8ToUtf16Le(&u16Buf, buf2[0..bufSize]) catch { + return MaybeSlice(T).errnoSys(0, Syscall.Tag.getenv).?; + }; + break :brk u16Buf[0..bufSize :0]; + } + }; + // Zig's std.posix.getenvW has logic to support keys like `=${resolvedDevice}`: + // https://github.com/ziglang/zig/blob/7bd8b35a3dfe61e59ffea39d464e84fbcdead29a/lib/std/os.zig#L2126-L2130 + // + // TODO: Enable test once spawnResult.stdout works on Windows. + // test/js/node/path/resolve.test.js + if (std.process.getenvW(key_w)) |r| { + if (T == u16) { + bufSize = r.len; + @memcpy(buf2[0..bufSize], r); + } else { + // Reuse buf2 because it's used for path. + bufSize = std.unicode.utf16leToUtf8(buf2, r) catch { + return MaybeSlice(T).errnoSys(0, Syscall.Tag.getcwd).?; + }; + } + envPath = buf2[0..bufSize]; + } + } + if (envPath) |_envPath| { + path = _envPath; + } else { + // cwd is limited to MAX_PATH_BYTES. + path = switch (getCwdT(T, &tmpBuf)) { + .result => |r| r, + .err => |e| return MaybeSlice(T){ .err = e }, + }; + // We must set envPath here so that it doesn't hit the null check just below. + envPath = path; + } + + // Verify that a cwd was found and that it actually points + // to our drive. If not, default to the drive's root. + + // Translated from the following JS code: + // if (path === undefined || + // (StringPrototypeToLowerCase(StringPrototypeSlice(path, 0, 2)) !== + // StringPrototypeToLowerCase(resolvedDevice) && + // StringPrototypeCharCodeAt(path, 2) === CHAR_BACKWARD_SLASH)) { + if (envPath == null or + (path[2] == CHAR_BACKWARD_SLASH and + !eqlIgnoreCaseT(T, path[0..2], resolvedDevice))) + { + // Translated from the following JS code: + // path = `${resolvedDevice}\\`; + bufSize = resolvedDeviceLen; + @memcpy(buf2[0..bufSize], resolvedDevice); + bufOffset = bufSize; + bufSize += 1; + buf2[bufOffset] = CHAR_BACKWARD_SLASH; + path = buf2[0..bufSize]; + } + } + + const len = path.len; + var rootEnd: usize = 0; + // Backed by tmpBuf or an anonymous buffer. + var device: []const T = comptime L(T, ""); + // Prefix with _ to avoid shadowing the identifier in the outer scope. + var _isAbsolute: bool = false; + const byte0 = if (len > 0) path[0] else 0; + + // Try to match a root + if (len == 1) { + if (isSepT(T, byte0)) { + // `path` contains just a path separator + rootEnd = 1; + _isAbsolute = true; + } + } else if (isSepT(T, byte0)) { + // Possible UNC root + + // If we started with a separator, we know we at least have an + // absolute path of some kind (UNC or otherwise) + _isAbsolute = true; + + if (isSepT(T, path[1])) { + // Matched double path separator at the beginning + var j: usize = 2; + var last: usize = j; + // Match 1 or more non-path separators + while (j < len and + !isSepT(T, path[j])) + { + j += 1; + } + if (j < len and j != last) { + const firstPart = path[last..j]; + // Matched! + last = j; + // Match 1 or more path separators + while (j < len and + isSepT(T, path[j])) + { + j += 1; + } + if (j < len and j != last) { + // Matched! + last = j; + // Match 1 or more non-path separators + while (j < len and + !isSepT(T, path[j])) + { + j += 1; + } + if (j == len or j != last) { + // We matched a UNC root + + // Translated from the following JS code: + // device = + // `\\\\${firstPart}\\${StringPrototypeSlice(path, last, j)}`; + // rootEnd = j; + bufSize = 2; + tmpBuf[0] = CHAR_BACKWARD_SLASH; + tmpBuf[1] = CHAR_BACKWARD_SLASH; + bufOffset = bufSize; + bufSize += firstPart.len; + @memcpy(tmpBuf[bufOffset..bufSize], firstPart); + bufOffset = bufSize; + bufSize += 1; + tmpBuf[bufOffset] = CHAR_BACKWARD_SLASH; + const slice = path[last..j]; + bufOffset = bufSize; + bufSize += slice.len; + @memcpy(tmpBuf[bufOffset..bufSize], slice); + + device = tmpBuf[0..bufSize]; + rootEnd = j; + } + } + } + } else { + rootEnd = 1; + } + } else if (isWindowsDeviceRootT(T, byte0) and + path[1] == CHAR_COLON) + { + // Possible device root + device = &[2]T{ byte0, CHAR_COLON }; + rootEnd = 2; + if (len > 2 and isSepT(T, path[2])) { + // Treat separator following the drive name as an absolute path + // indicator + _isAbsolute = true; + rootEnd = 3; + } + } + + const deviceLen = device.len; + if (deviceLen > 0) { + if (resolvedDeviceLen > 0) { + // Translated from the following JS code: + // if (StringPrototypeToLowerCase(device) !== + // StringPrototypeToLowerCase(resolvedDevice)) + if (!eqlIgnoreCaseT(T, device, resolvedDevice)) { + // This path points to another device, so it is not applicable + continue; + } + } else { + // Translated from the following JS code: + // resolvedDevice = device; + bufSize = device.len; + // Copy device over if it's backed by an anonymous buffer. + if (device.ptr != tmpBuf[0..].ptr) { + @memcpy(tmpBuf[0..bufSize], device); + } + resolvedDevice = tmpBuf[0..bufSize]; + resolvedDeviceLen = bufSize; + } + } + + if (resolvedAbsolute) { + if (resolvedDeviceLen > 0) { + break; + } + } else { + // Translated from the following JS code: + // resolvedTail = `${StringPrototypeSlice(path, rootEnd)}\\${resolvedTail}`; + const sliceLen = len - rootEnd; + if (resolvedTailLen > 0) { + bufOffset = sliceLen + 1; + bufSize = bufOffset + resolvedTailLen; + // Move all bytes to the right by path slice.len + 1 for the separator + // Use bun.copy because resolvedTail and buf2 overlap. + bun.copy(u8, buf2[bufOffset..bufSize], resolvedTail); + } + bufSize = sliceLen; + if (sliceLen > 0) { + @memcpy(buf2[0..bufSize], path[rootEnd..len]); + } + bufOffset = bufSize; + bufSize += 1; + buf2[bufOffset] = CHAR_BACKWARD_SLASH; + bufSize += resolvedTailLen; + + resolvedTail = buf2[0..bufSize]; + resolvedTailLen = bufSize; + resolvedAbsolute = _isAbsolute; + + if (_isAbsolute and resolvedDeviceLen > 0) { + break; + } + } + } + + // Exit early for empty path. + if (resolvedTailLen == 0) { + return MaybeSlice(T){ .result = comptime L(T, CHAR_STR_DOT) }; + } + + // At this point, the path should be resolved to a full absolute path, + // but handle relative paths to be safe (might happen when std.process.cwdAlloc() + // fails) + + // Normalize the tail path + resolvedTail = normalizeStringT(T, resolvedTail, !resolvedAbsolute, CHAR_BACKWARD_SLASH, .windows, buf); + // resolvedTail is now backed by buf. + resolvedTailLen = resolvedTail.len; + + // Translated from the following JS code: + // resolvedAbsolute ? `${resolvedDevice}\\${resolvedTail}` + if (resolvedAbsolute) { + bufOffset = resolvedDeviceLen + 1; + bufSize = bufOffset + resolvedTailLen; + // Use bun.copy because resolvedTail and buf overlap. + bun.copy(T, buf[bufOffset..bufSize], resolvedTail); + buf[resolvedDeviceLen] = CHAR_BACKWARD_SLASH; + @memcpy(buf[0..resolvedDeviceLen], resolvedDevice); + return MaybeSlice(T){ .result = buf[0..bufSize] }; + } + // Translated from the following JS code: + // : `${resolvedDevice}${resolvedTail}` || '.' + if ((resolvedDeviceLen + resolvedTailLen) > 0) { + bufOffset = resolvedDeviceLen; + bufSize = bufOffset + resolvedTailLen; + // Use bun.copy because resolvedTail and buf overlap. + bun.copy(T, buf[bufOffset..bufSize], resolvedTail); + @memcpy(buf[0..resolvedDeviceLen], resolvedDevice); + return MaybeSlice(T){ .result = buf[0..bufSize] }; + } + return MaybeSlice(T){ .result = comptime L(T, CHAR_STR_DOT) }; +} + +pub inline fn resolvePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, paths: []const []const T, buf: []T, buf2: []T) JSC.JSValue { + return switch (resolvePosixT(T, paths, buf, buf2)) { + .result => |r| toJSString(globalObject, r), + .err => |e| e.toJSC(globalObject), + }; +} + +pub inline fn resolveWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, paths: []const []const T, buf: []T, buf2: []T) JSC.JSValue { + return switch (resolveWindowsT(T, paths, buf, buf2)) { + .result => |r| toJSString(globalObject, r), + .err => |e| e.toJSC(globalObject), + }; +} + +pub fn resolveJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, paths: []const []const T) JSC.JSValue { + // Adding 8 bytes when Windows for the possible UNC root. + var bufLen: usize = if (isWindows) 8 else 0; + for (paths) |path| bufLen += if (bufLen > 0 and path.len > 0) path.len + 1 else path.len; + bufLen = @max(bufLen, PATH_SIZE(T)); + const buf = allocator.alloc(T, bufLen) catch bun.outOfMemory(); + defer allocator.free(buf); + const buf2 = allocator.alloc(T, bufLen) catch bun.outOfMemory(); + defer allocator.free(buf2); + return if (isWindows) resolveWindowsJS_T(T, globalObject, paths, buf, buf2) else resolvePosixJS_T(T, globalObject, paths, buf, buf2); +} + +pub fn resolve(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { + var arena = bun.ArenaAllocator.init(bun.default_allocator); + defer arena.deinit(); + + var stack_fallback = std.heap.stackFallback(stack_fallback_size_large, arena.allocator()); + const allocator = stack_fallback.get(); + + var paths = allocator.alloc(string, args_len) catch bun.outOfMemory(); + defer allocator.free(paths); + + for (0..args_len, args_ptr) |i, path_ptr| { + // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. + validateString(globalObject, path_ptr, "paths[{d}]", .{i}) catch { + // Returning .zero translates to a nullprt JSC.JSValue. + return .zero; + }; + const pathZStr = path_ptr.getZigString(globalObject); + paths[i] = if (pathZStr.len > 0) pathZStr.toSlice(allocator).slice() else ""; + } + return resolveJS_T(u8, globalObject, allocator, isWindows, paths); +} + +/// Based on Node v21.6.1 path.win32.toNamespacedPath: +/// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L622 +pub fn toNamespacedPathWindowsT(comptime T: type, path: []const T, buf: []T, buf2: []T) MaybeSlice(T) { + comptime validatePathT(T, "toNamespacedPathWindowsT"); + + // validateString of `path` is performed in pub fn toNamespacedPath. + // Backed by buf. + const resolvedPath = switch (resolveWindowsT(T, &.{path}, buf, buf2)) { + .result => |r| r, + .err => |e| return MaybeSlice(T){ .err = e }, + }; + + const len = resolvedPath.len; + if (len <= 2) { + return MaybeSlice(T){ .result = path }; + } + + var bufOffset: usize = 0; + var bufSize: usize = 0; + + const byte0 = resolvedPath[0]; + if (byte0 == CHAR_BACKWARD_SLASH) { + // Possible UNC root + if (resolvedPath[1] == CHAR_BACKWARD_SLASH) { + const byte2 = resolvedPath[2]; + if (byte2 != CHAR_QUESTION_MARK and byte2 != CHAR_DOT) { + // Matched non-long UNC root, convert the path to a long UNC path + + // Translated from the following JS code: + // return `\\\\?\\UNC\\${StringPrototypeSlice(resolvedPath, 2)}`; + bufOffset = 6; + bufSize = len + 6; + // Move all bytes to the right by 6 so that the first two bytes are + // overwritten by "\\\\?\\UNC\\" which is 8 bytes long. + // Use bun.copy because resolvedPath and buf overlap. + bun.copy(T, buf[bufOffset..bufSize], resolvedPath); + // Equiv to std.os.windows.NamespacePrefix.verbatim + // https://github.com/ziglang/zig/blob/dcaf43674e35372e1d28ab12c4c4ff9af9f3d646/lib/std/os/windows.zig#L2358-L2374 + buf[0] = CHAR_BACKWARD_SLASH; + buf[1] = CHAR_BACKWARD_SLASH; + buf[2] = CHAR_QUESTION_MARK; + buf[3] = CHAR_BACKWARD_SLASH; + buf[4] = 'U'; + buf[5] = 'N'; + buf[6] = 'C'; + buf[7] = CHAR_BACKWARD_SLASH; + return MaybeSlice(T){ .result = buf[0..bufSize] }; + } + } + } else if (isWindowsDeviceRootT(T, byte0) and + resolvedPath[1] == CHAR_COLON and + resolvedPath[2] == CHAR_BACKWARD_SLASH) + { + // Matched device root, convert the path to a long UNC path + + // Translated from the following JS code: + // return `\\\\?\\${resolvedPath}` + bufOffset = 4; + bufSize = len + 4; + // Move all bytes to the right by 4 + // Use bun.copy because resolvedPath and buf overlap. + bun.copy(T, buf[bufOffset..bufSize], resolvedPath); + // Equiv to std.os.windows.NamespacePrefix.verbatim + // https://github.com/ziglang/zig/blob/dcaf43674e35372e1d28ab12c4c4ff9af9f3d646/lib/std/os/windows.zig#L2358-L2374 + buf[0] = CHAR_BACKWARD_SLASH; + buf[1] = CHAR_BACKWARD_SLASH; + buf[2] = CHAR_QUESTION_MARK; + buf[3] = CHAR_BACKWARD_SLASH; + return MaybeSlice(T){ .result = buf[0..bufSize] }; + } + return MaybeSlice(T){ .result = resolvedPath }; +} + +pub inline fn toNamespacedPathWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T, buf: []T, buf2: []T) JSC.JSValue { + return switch (toNamespacedPathWindowsT(T, path, buf, buf2)) { + .result => |r| toJSString(globalObject, r), + .err => |e| e.toJSC(globalObject), + }; +} + +pub fn toNamespacedPathJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, path: []const T) JSC.JSValue { + if (!isWindows or path.len == 0) return toJSString(globalObject, path); + const bufLen = @max(path.len, PATH_SIZE(T)); + const buf = allocator.alloc(T, bufLen) catch bun.outOfMemory(); + defer allocator.free(buf); + const buf2 = allocator.alloc(T, bufLen) catch bun.outOfMemory(); + defer allocator.free(buf2); + return toNamespacedPathWindowsJS_T(T, globalObject, path, buf, buf2); +} + +pub fn toNamespacedPath(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { + if (args_len == 0) return JSC.JSValue.jsUndefined(); + var path_ptr = args_ptr[0]; + + // Based on Node v21.6.1 path.win32.toNamespacedPath and path.posix.toNamespacedPath: + // https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L624 + // https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1269 + // + // Act as an identity function for non-string values and non-Windows platforms. + if (!isWindows or !path_ptr.isString()) return path_ptr; + const pathZStr = path_ptr.getZigString(globalObject); + const len = pathZStr.len; + if (len == 0) return path_ptr; + + var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, JSC.getAllocator(globalObject)); + const allocator = stack_fallback.get(); + + const pathZSlice = pathZStr.toSlice(allocator); + defer pathZSlice.deinit(); + return toNamespacedPathJS_T(u8, globalObject, allocator, isWindows, pathZSlice.slice()); +} + +pub const Extern = [_][]const u8{"create"}; + +comptime { + @export(Path.basename, .{ .name = shim.symbolName("basename") }); + @export(Path.dirname, .{ .name = shim.symbolName("dirname") }); + @export(Path.extname, .{ .name = shim.symbolName("extname") }); + @export(Path.format, .{ .name = shim.symbolName("format") }); + @export(Path.isAbsolute, .{ .name = shim.symbolName("isAbsolute") }); + @export(Path.join, .{ .name = shim.symbolName("join") }); + @export(Path.normalize, .{ .name = shim.symbolName("normalize") }); + @export(Path.parse, .{ .name = shim.symbolName("parse") }); + @export(Path.relative, .{ .name = shim.symbolName("relative") }); + @export(Path.resolve, .{ .name = shim.symbolName("resolve") }); + @export(Path.toNamespacedPath, .{ .name = shim.symbolName("toNamespacedPath") }); +} diff --git a/src/bun.js/node/types.zig b/src/bun.js/node/types.zig index 334edde1d4..5749457ddf 100644 --- a/src/bun.js/node/types.zig +++ b/src/bun.js/node/types.zig @@ -11,9 +11,6 @@ const posix = std.posix; const path_handler = bun.path; const strings = bun.strings; const string = bun.string; -const validators = @import("./util/validators.zig"); -const validateObject = validators.validateObject; -const validateString = validators.validateString; const C = bun.C; const L = strings.literal; @@ -27,68 +24,12 @@ const Syscall = bun.sys; const URL = @import("../../url.zig").URL; const Value = std.json.Value; -const PATH_MIN_WIDE = 4096; // 4 KB - -const stack_fallback_size_small = switch (Environment.os) { - // Up to 4 KB, instead of MAX_PATH_BYTES which is 96 KB on Windows, ouch! - .windows => PATH_MIN_WIDE, - else => bun.MAX_PATH_BYTES, -}; - -const stack_fallback_size_large = 32 * @sizeOf(string); // up to 32 strings on the stack - -/// Taken from Zig 0.11.0 zig/src/resinator/rc.zig -/// https://github.com/ziglang/zig/blob/776cd673f206099012d789fd5d05d49dd72b9faa/src/resinator/rc.zig#L266 -/// -/// Compares ASCII values case-insensitively, non-ASCII values are compared directly -fn eqlIgnoreCaseT(comptime T: type, a: []const T, b: []const T) bool { - if (T != u16) { - return std.ascii.eqlIgnoreCase(a, b); - } - if (a.len != b.len) return false; - for (a, b) |a_c, b_c| { - if (a_c < 128) { - if (std.ascii.toLower(@intCast(a_c)) != std.ascii.toLower(@intCast(b_c))) return false; - } else { - if (a_c != b_c) return false; - } - } - return true; -} - -/// Taken from Zig 0.11.0 zig/src/resinator/rc.zig -/// https://github.com/ziglang/zig/blob/776cd673f206099012d789fd5d05d49dd72b9faa/src/resinator/rc.zig#L266 -/// -/// Lowers ASCII values, non-ASCII values are returned directly -inline fn toLowerT(comptime T: type, a_c: T) T { - if (T != u16) { - return std.ascii.toLower(a_c); - } - return if (a_c < 128) @intCast(std.ascii.toLower(@intCast(a_c))) else a_c; -} - -inline fn toJSString(globalObject: *JSC.JSGlobalObject, slice: []const u8) JSC.JSValue { - return if (slice.len > 0) - JSC.ZigString.init(slice).withEncoding().toJS(globalObject) - else - JSC.JSValue.jsEmptyString(globalObject); -} - -inline fn toUTF8JSString(globalObject: *JSC.JSGlobalObject, slice: []const u8) JSC.JSValue { - return JSC.ZigString.initUTF8(slice).toJS(globalObject); -} +pub const Path = @import("./path.zig"); fn typeBaseNameT(comptime T: type) []const u8 { return meta.typeBaseName(@typeName(T)); } -fn validatePathT(comptime T: type, comptime methodName: []const u8) void { - comptime switch (T) { - inline u8, u16 => return, - else => @compileError("Unsupported type for " ++ methodName ++ ": " ++ typeBaseNameT(T)), - }; -} - pub const Buffer = JSC.MarkedArrayBuffer; /// On windows, this is what libuv expects @@ -297,14 +238,6 @@ pub fn Maybe(comptime ReturnTypeT: type, comptime ErrorTypeT: type) type { }; } -inline fn MaybeBuf(comptime T: type) type { - return Maybe([]T, Syscall.Error); -} - -inline fn MaybeSlice(comptime T: type) type { - return Maybe([]const T, Syscall.Error); -} - fn translateToErrInt(err: anytype) bun.sys.Error.Int { return switch (@TypeOf(err)) { bun.windows.NTSTATUS => @intFromEnum(bun.windows.translateNTStatusToErrno(err)), @@ -1501,11 +1434,11 @@ pub fn StatType(comptime Big: bool) type { } } - const PropertyGetter = fn (this: *This, globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue; + const PropertyGetter = fn (this: *This, globalObject: *JSC.JSGlobalObject) JSC.JSValue; fn getter(comptime field: meta.FieldEnum(This)) PropertyGetter { return struct { - pub fn callback(this: *This, globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn callback(this: *This, globalObject: *JSC.JSGlobalObject) JSC.JSValue { const value = @field(this, @tagName(field)); if (comptime (Big and @typeInfo(@TypeOf(value)) == .Int)) { return JSC.JSValue.fromInt64NoTruncate(globalObject, @intCast(value)); @@ -1517,7 +1450,7 @@ pub fn StatType(comptime Big: bool) type { fn dateGetter(comptime field: meta.FieldEnum(This)) PropertyGetter { return struct { - pub fn callback(this: *This, globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn callback(this: *This, globalObject: *JSC.JSGlobalObject) JSC.JSValue { const value = @field(this, @tagName(field)); // Doing `Date{ ... }` here shouldn't actually change the memory layout of `value` // but it will tell comptime code how to convert the i64/f64 to a JS Date. @@ -1545,13 +1478,13 @@ pub fn StatType(comptime Big: bool) type { const DOMCallFn = fn ( *This, *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue; + ) callconv(JSC.conv) JSC.JSValue; fn domCall(comptime decl: meta.DeclEnum(This)) DOMCallFn { return struct { pub fn run( this: *This, _: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) callconv(JSC.conv) JSC.JSValue { return @field(This, @tagName(decl))(this); } }.run; @@ -1661,7 +1594,7 @@ pub fn StatType(comptime Big: bool) type { return this; } - pub fn constructor(globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) ?*This { + pub fn constructor(globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(JSC.conv) ?*This { if (Big) { globalObject.throwInvalidArguments("BigIntStats is not a constructor", .{}); return null; @@ -1766,7 +1699,7 @@ pub const Dirent = struct { pub const Kind = std.fs.File.Kind; pub usingnamespace JSC.Codegen.JSDirent; - pub fn constructor(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) ?*Dirent { + pub fn constructor(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(JSC.conv) ?*Dirent { globalObject.throw("Dirent is not a constructor", .{}); return null; } @@ -1776,11 +1709,11 @@ pub const Dirent = struct { return out.toJS(globalObject); } - pub fn getName(this: *Dirent, globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getName(this: *Dirent, globalObject: *JSC.JSGlobalObject) JSC.JSValue { return this.name.toJS(globalObject); } - pub fn getPath(this: *Dirent, globalThis: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getPath(this: *Dirent, globalThis: *JSC.JSGlobalObject) JSC.JSValue { return this.path.toJS(globalThis); } @@ -1788,49 +1721,49 @@ pub const Dirent = struct { this: *Dirent, _: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return JSC.JSValue.jsBoolean(this.kind == std.fs.File.Kind.block_device); } pub fn isCharacterDevice( this: *Dirent, _: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return JSC.JSValue.jsBoolean(this.kind == std.fs.File.Kind.character_device); } pub fn isDirectory( this: *Dirent, _: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return JSC.JSValue.jsBoolean(this.kind == std.fs.File.Kind.directory); } pub fn isFIFO( this: *Dirent, _: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return JSC.JSValue.jsBoolean(this.kind == std.fs.File.Kind.named_pipe or this.kind == std.fs.File.Kind.event_port); } pub fn isFile( this: *Dirent, _: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return JSC.JSValue.jsBoolean(this.kind == std.fs.File.Kind.file); } pub fn isSocket( this: *Dirent, _: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return JSC.JSValue.jsBoolean(this.kind == std.fs.File.Kind.unix_domain_socket); } pub fn isSymbolicLink( this: *Dirent, _: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return JSC.JSValue.jsBoolean(this.kind == std.fs.File.Kind.sym_link); } @@ -1943,2940 +1876,6 @@ pub const Emitter = struct { } }; -pub const Path = struct { - const CHAR_BACKWARD_SLASH = '\\'; - const CHAR_COLON = ':'; - const CHAR_DOT = '.'; - const CHAR_FORWARD_SLASH = '/'; - const CHAR_QUESTION_MARK = '?'; - - const CHAR_STR_BACKWARD_SLASH = "\\"; - const CHAR_STR_FORWARD_SLASH = "/"; - const CHAR_STR_DOT = "."; - - const StringBuilder = @import("../../string_builder.zig"); - - /// Based on Node v21.6.1 path.parse: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L919 - /// The structs returned by parse methods. - fn PathParsed(comptime T: type) type { - return struct { - root: []const T = "", - dir: []const T = "", - base: []const T = "", - ext: []const T = "", - name: []const T = "", - pub fn toJSObject(this: @This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue { - var jsObject = JSC.JSValue.createEmptyObject(globalObject, 5); - jsObject.put(globalObject, JSC.ZigString.static("root"), toJSString(globalObject, this.root)); - jsObject.put(globalObject, JSC.ZigString.static("dir"), toJSString(globalObject, this.dir)); - jsObject.put(globalObject, JSC.ZigString.static("base"), toJSString(globalObject, this.base)); - jsObject.put(globalObject, JSC.ZigString.static("ext"), toJSString(globalObject, this.ext)); - jsObject.put(globalObject, JSC.ZigString.static("name"), toJSString(globalObject, this.name)); - return jsObject; - } - }; - } - - pub fn MAX_PATH_SIZE(comptime T: type) usize { - return if (T == u16) windows.PATH_MAX_WIDE else bun.MAX_PATH_BYTES; - } - - pub fn PATH_SIZE(comptime T: type) usize { - return if (T == u16) PATH_MIN_WIDE else bun.MAX_PATH_BYTES; - } - - pub const shim = Shimmer("Bun", "Path", @This()); - pub const name = "Bun__Path"; - pub const include = "Path.h"; - pub const namespace = shim.namespace; - pub const sep_posix = CHAR_FORWARD_SLASH; - pub const sep_windows = CHAR_BACKWARD_SLASH; - pub const sep_str_posix = CHAR_STR_FORWARD_SLASH; - pub const sep_str_windows = CHAR_STR_BACKWARD_SLASH; - - /// Based on Node v21.6.1 private helper formatExt: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L130C10-L130C19 - inline fn formatExtT(comptime T: type, ext: []const T, buf: []T) []const T { - const len = ext.len; - if (len == 0) { - return comptime L(T, ""); - } - if (ext[0] == CHAR_DOT) { - return ext; - } - const bufSize = len + 1; - buf[0] = CHAR_DOT; - @memcpy(buf[1..bufSize], ext); - return buf[0..bufSize]; - } - - /// Based on Node v21.6.1 private helper posixCwd: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1074 - inline fn posixCwdT(comptime T: type, buf: []T) MaybeBuf(T) { - const cwd = switch (getCwdT(T, buf)) { - .result => |r| r, - .err => |e| return MaybeBuf(T){ .err = e }, - }; - const len = cwd.len; - if (len == 0) { - return MaybeBuf(T){ .result = cwd }; - } - if (comptime Environment.isWindows) { - // Converts Windows' backslash path separators to POSIX forward slashes - // and truncates any drive indicator - - // Translated from the following JS code: - // const cwd = StringPrototypeReplace(process.cwd(), regexp, '/'); - for (0..len) |i| { - if (cwd[i] == CHAR_BACKWARD_SLASH) { - buf[i] = CHAR_FORWARD_SLASH; - } else { - buf[i] = cwd[i]; - } - } - var normalizedCwd = buf[0..len]; - - // Translated from the following JS code: - // return StringPrototypeSlice(cwd, StringPrototypeIndexOf(cwd, '/')); - const index = std.mem.indexOfScalar(T, normalizedCwd, CHAR_FORWARD_SLASH); - // Account for the -1 case of String#slice in JS land - if (index) |_index| { - return MaybeBuf(T){ .result = normalizedCwd[_index..len] }; - } - return MaybeBuf(T){ .result = normalizedCwd[len - 1 .. len] }; - } - - // We're already on POSIX, no need for any transformations - return MaybeBuf(T){ .result = cwd }; - } - - pub fn getCwdWindowsU8(buf: []u8) MaybeBuf(u8) { - const u16Buf: bun.WPathBuffer = undefined; - switch (getCwdWindowsU16(&u16Buf)) { - .result => |r| { - // Handles conversion from UTF-16 to UTF-8 including surrogates ;) - const result = strings.convertUTF16ToUTF8InBuffer(&buf, r) catch { - return MaybeBuf(u8).errnoSys(0, Syscall.Tag.getcwd).?; - }; - return MaybeBuf(u8){ .result = result }; - }, - .err => |e| return MaybeBuf(u8){ .err = e }, - } - } - - pub fn getCwdWindowsU16(buf: []u16) MaybeBuf(u16) { - const len: u32 = kernel32.GetCurrentDirectoryW(buf.len, &buf); - if (len == 0) { - // Indirectly calls std.os.windows.kernel32.GetLastError(). - return MaybeBuf(u16).errnoSys(0, Syscall.Tag.getcwd).?; - } - return MaybeBuf(u16){ .result = buf[0..len] }; - } - - pub fn getCwdWindowsT(comptime T: type, buf: []T) MaybeBuf(T) { - comptime validatePathT(T, "getCwdWindowsT"); - return if (T == u16) - getCwdWindowsU16(buf) - else - getCwdWindowsU8(buf); - } - - pub fn getCwdU8(buf: []u8) MaybeBuf(u8) { - const result = bun.getcwd(buf) catch { - return MaybeBuf(u8).errnoSys( - @as(c_int, 0), - Syscall.Tag.getcwd, - ).?; - }; - return MaybeBuf(u8){ .result = result }; - } - - pub fn getCwdU16(buf: []u16) MaybeBuf(u16) { - if (comptime Environment.isWindows) { - return getCwdWindowsU16(&buf); - } - const u8Buf: bun.PathBuffer = undefined; - const result = strings.convertUTF8toUTF16InBuffer(&buf, bun.getcwd(strings.convertUTF16ToUTF8InBuffer(&u8Buf, buf))) catch { - return MaybeBuf(u16).errnoSys(0, Syscall.Tag.getcwd).?; - }; - return MaybeBuf(u16){ .result = result }; - } - - pub fn getCwdT(comptime T: type, buf: []T) MaybeBuf(T) { - comptime validatePathT(T, "getCwdT"); - return if (T == u16) - getCwdU16(buf) - else - getCwdU8(buf); - } - - // Alias for naming consistency. - pub const getCwd = getCwdU8; - - /// Based on Node v21.6.1 path.posix.basename: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1309 - pub fn basenamePosixT(comptime T: type, path: []const T, suffix: ?[]const T) []const T { - comptime validatePathT(T, "basenamePosixT"); - - // validateString of `path` is performed in pub fn basename. - const len = path.len; - // Exit early for easier number type use. - if (len == 0) { - return comptime L(T, ""); - } - var start: usize = 0; - // We use an optional value instead of -1, as in Node code, for easier number type use. - var end: ?usize = null; - var matchedSlash: bool = true; - - const _suffix = if (suffix) |_s| _s else comptime L(T, ""); - const _suffixLen = _suffix.len; - if (suffix != null and _suffixLen > 0 and _suffixLen <= len) { - if (std.mem.eql(T, _suffix, path)) { - return comptime L(T, ""); - } - // We use an optional value instead of -1, as in Node code, for easier number type use. - var extIdx: ?usize = _suffixLen - 1; - // We use an optional value instead of -1, as in Node code, for easier number type use. - var firstNonSlashEnd: ?usize = null; - var i_i64 = @as(i64, @intCast(len - 1)); - while (i_i64 >= start) : (i_i64 -= 1) { - const i = @as(usize, @intCast(i_i64)); - const byte = path[i]; - if (byte == CHAR_FORWARD_SLASH) { - // If we reached a path separator that was not part of a set of path - // separators at the end of the string, stop now - if (!matchedSlash) { - start = i + 1; - break; - } - } else { - if (firstNonSlashEnd == null) { - // We saw the first non-path separator, remember this index in case - // we need it if the extension ends up not matching - matchedSlash = false; - firstNonSlashEnd = i + 1; - } - if (extIdx) |_extIx| { - // Try to match the explicit extension - if (byte == _suffix[_extIx]) { - if (_extIx == 0) { - // We matched the extension, so mark this as the end of our path - // component - end = i; - extIdx = null; - } else { - extIdx = _extIx - 1; - } - } else { - // Extension does not match, so our result is the entire path - // component - extIdx = null; - end = firstNonSlashEnd; - } - } - } - } - - if (end) |_end| { - if (start == _end) { - return path[start..firstNonSlashEnd.?]; - } else { - return path[start.._end]; - } - } - return path[start..len]; - } - - var i_i64 = @as(i64, @intCast(len - 1)); - while (i_i64 > -1) : (i_i64 -= 1) { - const i = @as(usize, @intCast(i_i64)); - const byte = path[i]; - if (byte == CHAR_FORWARD_SLASH) { - // If we reached a path separator that was not part of a set of path - // separators at the end of the string, stop now - if (!matchedSlash) { - start = i + 1; - break; - } - } else if (end == null) { - // We saw the first non-path separator, mark this as the end of our - // path component - matchedSlash = false; - end = i + 1; - } - } - - return if (end) |_end| - path[start.._end] - else - comptime L(T, ""); - } - - /// Based on Node v21.6.1 path.win32.basename: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L753 - pub fn basenameWindowsT(comptime T: type, path: []const T, suffix: ?[]const T) []const T { - comptime validatePathT(T, "basenameWindowsT"); - - // validateString of `path` is performed in pub fn basename. - const len = path.len; - // Exit early for easier number type use. - if (len == 0) { - return comptime L(T, ""); - } - - const isSepT = isSepWindowsT; - - var start: usize = 0; - // We use an optional value instead of -1, as in Node code, for easier number type use. - var end: ?usize = null; - var matchedSlash: bool = true; - - // Check for a drive letter prefix so as not to mistake the following - // path separator as an extra separator at the end of the path that can be - // disregarded - if (len >= 2 and isWindowsDeviceRootT(T, path[0]) and path[1] == CHAR_COLON) { - start = 2; - } - - const _suffix = if (suffix) |_s| _s else comptime L(T, ""); - const _suffixLen = _suffix.len; - if (suffix != null and _suffixLen > 0 and _suffixLen <= len) { - if (std.mem.eql(T, _suffix, path)) { - return comptime L(T, ""); - } - // We use an optional value instead of -1, as in Node code, for easier number type use. - var extIdx: ?usize = _suffixLen - 1; - // We use an optional value instead of -1, as in Node code, for easier number type use. - var firstNonSlashEnd: ?usize = null; - var i_i64 = @as(i64, @intCast(len - 1)); - while (i_i64 >= start) : (i_i64 -= 1) { - const i = @as(usize, @intCast(i_i64)); - const byte = path[i]; - if (isSepT(T, byte)) { - // If we reached a path separator that was not part of a set of path - // separators at the end of the string, stop now - if (!matchedSlash) { - start = i + 1; - break; - } - } else { - if (firstNonSlashEnd == null) { - // We saw the first non-path separator, remember this index in case - // we need it if the extension ends up not matching - matchedSlash = false; - firstNonSlashEnd = i + 1; - } - if (extIdx) |_extIx| { - // Try to match the explicit extension - if (byte == _suffix[_extIx]) { - if (_extIx == 0) { - // We matched the extension, so mark this as the end of our path - // component - end = i; - extIdx = null; - } else { - extIdx = _extIx - 1; - } - } else { - // Extension does not match, so our result is the entire path - // component - extIdx = null; - end = firstNonSlashEnd; - } - } - } - } - - if (end) |_end| { - if (start == _end) { - return path[start..firstNonSlashEnd.?]; - } else { - return path[start.._end]; - } - } - return path[start..len]; - } - - var i_i64 = @as(i64, @intCast(len - 1)); - while (i_i64 >= start) : (i_i64 -= 1) { - const i = @as(usize, @intCast(i_i64)); - const byte = path[i]; - if (isSepT(T, byte)) { - if (!matchedSlash) { - start = i + 1; - break; - } - } else if (end == null) { - matchedSlash = false; - end = i + 1; - } - } - - return if (end) |_end| - path[start.._end] - else - comptime L(T, ""); - } - - pub inline fn basenamePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T, suffix: ?[]const T) JSC.JSValue { - return toJSString(globalObject, basenamePosixT(T, path, suffix)); - } - - pub inline fn basenameWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T, suffix: ?[]const T) JSC.JSValue { - return toJSString(globalObject, basenameWindowsT(T, path, suffix)); - } - - pub inline fn basenameJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, isWindows: bool, path: []const T, suffix: ?[]const T) JSC.JSValue { - return if (isWindows) - basenameWindowsJS_T(T, globalObject, path, suffix) - else - basenamePosixJS_T(T, globalObject, path, suffix); - } - - pub fn basename(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue { - if (comptime is_bindgen) return JSC.JSValue.jsUndefined(); - const suffix_ptr: ?JSC.JSValue = if (args_len > 1) args_ptr[1] else null; - - if (suffix_ptr) |_suffix_ptr| { - // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, _suffix_ptr, "ext", .{}) catch { - // Returning .zero translates to a nullprt JSC.JSValue. - return .zero; - }; - } - - const path_ptr = if (args_len > 0) args_ptr[0] else JSC.JSValue.jsUndefined(); - // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, path_ptr, "path", .{}) catch { - return .zero; - }; - - const pathZStr = path_ptr.getZigString(globalObject); - if (pathZStr.len == 0) return path_ptr; - - var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, JSC.getAllocator(globalObject)); - const allocator = stack_fallback.get(); - - const pathZSlice = pathZStr.toSlice(allocator); - defer pathZSlice.deinit(); - - var suffixZSlice: ?JSC.ZigString.Slice = null; - if (suffix_ptr) |_suffix_ptr| { - const suffixZStr = _suffix_ptr.getZigString(globalObject); - if (suffixZStr.len > 0 and suffixZStr.len <= pathZStr.len) { - suffixZSlice = suffixZStr.toSlice(allocator); - } - } - defer if (suffixZSlice) |_s| _s.deinit(); - return basenameJS_T(u8, globalObject, isWindows, pathZSlice.slice(), if (suffixZSlice) |_s| _s.slice() else null); - } - - pub fn create(globalObject: *JSC.JSGlobalObject, isWindows: bool) callconv(.C) JSC.JSValue { - return shim.cppFn("create", .{ globalObject, isWindows }); - } - - /// Based on Node v21.6.1 path.posix.dirname: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1278 - pub fn dirnamePosixT(comptime T: type, path: []const T) []const T { - comptime validatePathT(T, "dirnamePosixT"); - - // validateString of `path` is performed in pub fn dirname. - const len = path.len; - if (len == 0) { - return comptime L(T, CHAR_STR_DOT); - } - - const hasRoot = path[0] == CHAR_FORWARD_SLASH; - // We use an optional value instead of -1, as in Node code, for easier number type use. - var end: ?usize = null; - var matchedSlash: bool = true; - var i: usize = len - 1; - while (i >= 1) : (i -= 1) { - if (path[i] == CHAR_FORWARD_SLASH) { - if (!matchedSlash) { - end = i; - break; - } - } else { - // We saw the first non-path separator - matchedSlash = false; - } - } - - if (end) |_end| { - return if (hasRoot and _end == 1) - comptime L(T, "//") - else - path[0.._end]; - } - return if (hasRoot) - comptime L(T, CHAR_STR_FORWARD_SLASH) - else - comptime L(T, CHAR_STR_DOT); - } - - /// Based on Node v21.6.1 path.win32.dirname: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L657 - pub fn dirnameWindowsT(comptime T: type, path: []const T) []const T { - comptime validatePathT(T, "dirnameWindowsT"); - - // validateString of `path` is performed in pub fn dirname. - const len = path.len; - if (len == 0) { - return comptime L(T, CHAR_STR_DOT); - } - - const isSepT = isSepWindowsT; - - // We use an optional value instead of -1, as in Node code, for easier number type use. - var rootEnd: ?usize = null; - var offset: usize = 0; - const byte0 = path[0]; - - if (len == 1) { - // `path` contains just a path separator, exit early to avoid - // unnecessary work or a dot. - return if (isSepT(T, byte0)) path else comptime L(T, CHAR_STR_DOT); - } - - // Try to match a root - if (isSepT(T, byte0)) { - // Possible UNC root - - rootEnd = 1; - offset = 1; - - if (isSepT(T, path[1])) { - // Matched double path separator at the beginning - var j: usize = 2; - var last: usize = j; - - // Match 1 or more non-path separators - while (j < len and !isSepT(T, path[j])) { - j += 1; - } - - if (j < len and j != last) { - // Matched! - last = j; - - // Match 1 or more path separators - while (j < len and isSepT(T, path[j])) { - j += 1; - } - - if (j < len and j != last) { - // Matched! - last = j; - - // Match 1 or more non-path separators - while (j < len and !isSepT(T, path[j])) { - j += 1; - } - - if (j == len) { - // We matched a UNC root only - return path; - } - - if (j != last) { - // We matched a UNC root with leftovers - - // Offset by 1 to include the separator after the UNC root to - // treat it as a "normal root" on top of a (UNC) root - offset = j + 1; - rootEnd = offset; - } - } - } - } - // Possible device root - } else if (isWindowsDeviceRootT(T, byte0) and path[1] == CHAR_COLON) { - offset = if (len > 2 and isSepT(T, path[2])) 3 else 2; - rootEnd = offset; - } - - // We use an optional value instead of -1, as in Node code, for easier number type use. - var end: ?usize = null; - var matchedSlash: bool = true; - - var i_i64 = @as(i64, @intCast(len - 1)); - while (i_i64 >= offset) : (i_i64 -= 1) { - const i = @as(usize, @intCast(i_i64)); - if (isSepT(T, path[i])) { - if (!matchedSlash) { - end = i; - break; - } - } else { - // We saw the first non-path separator - matchedSlash = false; - } - } - - if (end) |_end| { - return path[0.._end]; - } - - return if (rootEnd) |_rootEnd| - path[0.._rootEnd] - else - comptime L(T, CHAR_STR_DOT); - } - - pub inline fn dirnamePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) JSC.JSValue { - return toJSString(globalObject, dirnamePosixT(T, path)); - } - - pub inline fn dirnameWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) JSC.JSValue { - return toJSString(globalObject, dirnameWindowsT(T, path)); - } - - pub inline fn dirnameJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, isWindows: bool, path: []const T) JSC.JSValue { - return if (isWindows) - dirnameWindowsJS_T(T, globalObject, path) - else - dirnamePosixJS_T(T, globalObject, path); - } - - pub fn dirname(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue { - if (comptime is_bindgen) return JSC.JSValue.jsUndefined(); - const path_ptr = if (args_len > 0) args_ptr[0] else JSC.JSValue.jsUndefined(); - // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, path_ptr, "path", .{}) catch { - // Returning .zero translates to a nullprt JSC.JSValue. - return .zero; - }; - - const pathZStr = path_ptr.getZigString(globalObject); - if (pathZStr.len == 0) return toUTF8JSString(globalObject, CHAR_STR_DOT); - - var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, JSC.getAllocator(globalObject)); - const allocator = stack_fallback.get(); - - const pathZSlice = pathZStr.toSlice(allocator); - defer pathZSlice.deinit(); - return dirnameJS_T(u8, globalObject, isWindows, pathZSlice.slice()); - } - - /// Based on Node v21.6.1 path.posix.extname: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1278 - pub fn extnamePosixT(comptime T: type, path: []const T) []const T { - comptime validatePathT(T, "extnamePosixT"); - - // validateString of `path` is performed in pub fn extname. - const len = path.len; - // Exit early for easier number type use. - if (len == 0) { - return comptime L(T, ""); - } - // We use an optional value instead of -1, as in Node code, for easier number type use. - var startDot: ?usize = null; - var startPart: usize = 0; - // We use an optional value instead of -1, as in Node code, for easier number type use. - var end: ?usize = null; - var matchedSlash: bool = true; - // Track the state of characters (if any) we see before our first dot and - // after any path separator we find - - // We use an optional value instead of -1, as in Node code, for easier number type use. - var preDotState: ?usize = 0; - - var i_i64 = @as(i64, @intCast(len - 1)); - while (i_i64 > -1) : (i_i64 -= 1) { - const i = @as(usize, @intCast(i_i64)); - const byte = path[i]; - if (byte == CHAR_FORWARD_SLASH) { - // If we reached a path separator that was not part of a set of path - // separators at the end of the string, stop now - if (!matchedSlash) { - startPart = i + 1; - break; - } - continue; - } - - if (end == null) { - // We saw the first non-path separator, mark this as the end of our - // extension - matchedSlash = false; - end = i + 1; - } - - if (byte == CHAR_DOT) { - // If this is our first dot, mark it as the start of our extension - if (startDot == null) { - startDot = i; - } else if (preDotState != null and preDotState.? != 1) { - preDotState = 1; - } - } else if (startDot != null) { - // We saw a non-dot and non-path separator before our dot, so we should - // have a good chance at having a non-empty extension - preDotState = null; - } - } - - const _end = if (end) |_e| _e else 0; - const _preDotState = if (preDotState) |_p| _p else 0; - const _startDot = if (startDot) |_s| _s else 0; - if (startDot == null or - end == null or - // We saw a non-dot character immediately before the dot - (preDotState != null and _preDotState == 0) or - // The (right-most) trimmed path component is exactly '..' - (_preDotState == 1 and - _startDot == _end - 1 and - _startDot == startPart + 1)) - { - return comptime L(T, ""); - } - - return path[_startDot.._end]; - } - - /// Based on Node v21.6.1 path.win32.extname: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L840 - pub fn extnameWindowsT(comptime T: type, path: []const T) []const T { - comptime validatePathT(T, "extnameWindowsT"); - - // validateString of `path` is performed in pub fn extname. - const len = path.len; - // Exit early for easier number type use. - if (len == 0) { - return comptime L(T, ""); - } - var start: usize = 0; - // We use an optional value instead of -1, as in Node code, for easier number type use. - var startDot: ?usize = null; - var startPart: usize = 0; - // We use an optional value instead of -1, as in Node code, for easier number type use. - var end: ?usize = null; - var matchedSlash: bool = true; - // Track the state of characters (if any) we see before our first dot and - // after any path separator we find - - // We use an optional value instead of -1, as in Node code, for easier number type use. - var preDotState: ?usize = 0; - - // Check for a drive letter prefix so as not to mistake the following - // path separator as an extra separator at the end of the path that can be - // disregarded - - if (len >= 2 and - path[1] == CHAR_COLON and - isWindowsDeviceRootT(T, path[0])) - { - start = 2; - startPart = start; - } - - var i_i64 = @as(i64, @intCast(len - 1)); - while (i_i64 >= start) : (i_i64 -= 1) { - const i = @as(usize, @intCast(i_i64)); - const byte = path[i]; - if (isSepWindowsT(T, byte)) { - // If we reached a path separator that was not part of a set of path - // separators at the end of the string, stop now - if (!matchedSlash) { - startPart = i + 1; - break; - } - continue; - } - if (end == null) { - // We saw the first non-path separator, mark this as the end of our - // extension - matchedSlash = false; - end = i + 1; - } - if (byte == CHAR_DOT) { - // If this is our first dot, mark it as the start of our extension - if (startDot == null) { - startDot = i; - } else if (preDotState) |_preDotState| { - if (_preDotState != 1) { - preDotState = 1; - } - } - } else if (startDot != null) { - // We saw a non-dot and non-path separator before our dot, so we should - // have a good chance at having a non-empty extension - preDotState = null; - } - } - - const _end = if (end) |_e| _e else 0; - const _preDotState = if (preDotState) |_p| _p else 0; - const _startDot = if (startDot) |_s| _s else 0; - if (startDot == null or - end == null or - // We saw a non-dot character immediately before the dot - (preDotState != null and _preDotState == 0) or - // The (right-most) trimmed path component is exactly '..' - (_preDotState == 1 and - _startDot == _end - 1 and - _startDot == startPart + 1)) - { - return comptime L(T, ""); - } - - return path[_startDot.._end]; - } - - pub inline fn extnamePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) JSC.JSValue { - return toJSString(globalObject, extnamePosixT(T, path)); - } - - pub inline fn extnameWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) JSC.JSValue { - return toJSString(globalObject, extnameWindowsT(T, path)); - } - - pub inline fn extnameJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, isWindows: bool, path: []const T) JSC.JSValue { - return if (isWindows) - extnameWindowsJS_T(T, globalObject, path) - else - extnamePosixJS_T(T, globalObject, path); - } - - pub fn extname(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue { - if (comptime is_bindgen) return JSC.JSValue.jsUndefined(); - const path_ptr = if (args_len > 0) args_ptr[0] else JSC.JSValue.jsUndefined(); - // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, path_ptr, "path", .{}) catch { - // Returning .zero translates to a nullprt JSC.JSValue. - return .zero; - }; - - const pathZStr = path_ptr.getZigString(globalObject); - if (pathZStr.len == 0) return path_ptr; - - var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, JSC.getAllocator(globalObject)); - const allocator = stack_fallback.get(); - - const pathZSlice = pathZStr.toSlice(allocator); - defer pathZSlice.deinit(); - return extnameJS_T(u8, globalObject, isWindows, pathZSlice.slice()); - } - - /// Based on Node v21.6.1 private helper _format: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L145 - fn _formatT(comptime T: type, pathObject: PathParsed(T), sep: T, buf: []T) []const T { - comptime validatePathT(T, "_formatT"); - - // validateObject of `pathObject` is performed in pub fn format. - const root = pathObject.root; - const dir = pathObject.dir; - const base = pathObject.base; - const ext = pathObject.ext; - // Prefix with _ to avoid shadowing the identifier in the outer scope. - const _name = pathObject.name; - - // Translated from the following JS code: - // const dir = pathObject.dir || pathObject.root; - const dirIsRoot = dir.len == 0 or std.mem.eql(u8, dir, root); - const dirOrRoot = if (dirIsRoot) root else dir; - const dirLen = dirOrRoot.len; - - var bufOffset: usize = 0; - var bufSize: usize = 0; - - // Translated from the following JS code: - // const base = pathObject.base || - // `${pathObject.name || ''}${formatExt(pathObject.ext)}`; - var baseLen = base.len; - var baseOrNameExt = base; - if (baseLen > 0) { - @memcpy(buf[0..baseLen], base); - } else { - const formattedExt = formatExtT(T, ext, buf); - const nameLen = _name.len; - const extLen = formattedExt.len; - bufOffset = nameLen; - bufSize = bufOffset + extLen; - if (extLen > 0) { - // Move all bytes to the right by _name.len. - // Use bun.copy because formattedExt and buf overlap. - bun.copy(T, buf[bufOffset..bufSize], formattedExt); - } - if (nameLen > 0) { - @memcpy(buf[0..nameLen], _name); - } - if (bufSize > 0) { - baseOrNameExt = buf[0..bufSize]; - } - } - - // Translated from the following JS code: - // if (!dir) { - // return base; - // } - if (dirLen == 0) { - return baseOrNameExt; - } - - // Translated from the following JS code: - // return dir === pathObject.root ? `${dir}${base}` : `${dir}${sep}${base}`; - baseLen = baseOrNameExt.len; - if (baseLen > 0) { - bufOffset = if (dirIsRoot) dirLen else dirLen + 1; - bufSize = bufOffset + baseLen; - // Move all bytes to the right by dirLen + (maybe 1 for the separator). - // Use bun.copy because baseOrNameExt and buf overlap. - bun.copy(T, buf[bufOffset..bufSize], baseOrNameExt); - } - @memcpy(buf[0..dirLen], dirOrRoot); - bufSize = dirLen + baseLen; - if (!dirIsRoot) { - bufSize += 1; - buf[dirLen] = sep; - } - return buf[0..bufSize]; - } - - pub inline fn formatPosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, pathObject: PathParsed(T), buf: []T) JSC.JSValue { - return toJSString(globalObject, _formatT(T, pathObject, CHAR_FORWARD_SLASH, buf)); - } - - pub inline fn formatWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, pathObject: PathParsed(T), buf: []T) JSC.JSValue { - return toJSString(globalObject, _formatT(T, pathObject, CHAR_BACKWARD_SLASH, buf)); - } - - pub fn formatJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, pathObject: PathParsed(T)) JSC.JSValue { - const baseLen = pathObject.base.len; - const dirLen = pathObject.dir.len; - // Add one for the possible separator. - const bufLen: usize = @max(1 + - (if (dirLen > 0) dirLen else pathObject.root.len) + - (if (baseLen > 0) baseLen else pathObject.name.len + pathObject.ext.len), PATH_SIZE(T)); - const buf = allocator.alloc(T, bufLen) catch bun.outOfMemory(); - defer allocator.free(buf); - return if (isWindows) formatWindowsJS_T(T, globalObject, pathObject, buf) else formatPosixJS_T(T, globalObject, pathObject, buf); - } - - pub fn format(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue { - if (comptime is_bindgen) return JSC.JSValue.jsUndefined(); - const pathObject_ptr = if (args_len > 0) args_ptr[0] else JSC.JSValue.jsUndefined(); - // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateObject(globalObject, pathObject_ptr, "pathObject", .{}, .{}) catch { - // Returning .zero translates to a nullprt JSC.JSValue. - return .zero; - }; - - var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, JSC.getAllocator(globalObject)); - const allocator = stack_fallback.get(); - - var root: []const u8 = ""; - if (pathObject_ptr.getTruthy(globalObject, "root")) |jsValue| { - root = jsValue.toSlice(globalObject, allocator).slice(); - } - var dir: []const u8 = ""; - if (pathObject_ptr.getTruthy(globalObject, "dir")) |jsValue| { - dir = jsValue.toSlice(globalObject, allocator).slice(); - } - var base: []const u8 = ""; - if (pathObject_ptr.getTruthy(globalObject, "base")) |jsValue| { - base = jsValue.toSlice(globalObject, allocator).slice(); - } - // Prefix with _ to avoid shadowing the identifier in the outer scope. - var _name: []const u8 = ""; - if (pathObject_ptr.getTruthy(globalObject, "name")) |jsValue| { - _name = jsValue.toSlice(globalObject, allocator).slice(); - } - var ext: []const u8 = ""; - if (pathObject_ptr.getTruthy(globalObject, "ext")) |jsValue| { - ext = jsValue.toSlice(globalObject, allocator).slice(); - } - return formatJS_T(u8, globalObject, allocator, isWindows, .{ .root = root, .dir = dir, .base = base, .ext = ext, .name = _name }); - } - - /// Based on Node v21.6.1 path.posix.isAbsolute: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1159 - pub inline fn isAbsolutePosixT(comptime T: type, path: []const T) bool { - // validateString of `path` is performed in pub fn isAbsolute. - return path.len > 0 and path[0] == CHAR_FORWARD_SLASH; - } - - /// Based on Node v21.6.1 path.win32.isAbsolute: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L406 - pub fn isAbsoluteWindowsT(comptime T: type, path: []const T) bool { - // validateString of `path` is performed in pub fn isAbsolute. - const len = path.len; - if (len == 0) - return false; - - const byte0 = path[0]; - return isSepWindowsT(T, byte0) or - // Possible device root - (len > 2 and - isWindowsDeviceRootT(T, byte0) and - path[1] == CHAR_COLON and - isSepWindowsT(T, path[2])); - } - - pub fn isAbsolutePosixZigString(pathZStr: JSC.ZigString) bool { - const pathZStrTrunc = pathZStr.trunc(1); - return if (pathZStrTrunc.len > 0 and pathZStrTrunc.is16Bit()) - isAbsolutePosixT(u16, pathZStrTrunc.utf16SliceAligned()) - else - isAbsolutePosixT(u8, pathZStrTrunc.slice()); - } - - pub fn isAbsoluteWindowsZigString(pathZStr: JSC.ZigString) bool { - return if (pathZStr.len > 0 and pathZStr.is16Bit()) - isAbsoluteWindowsT(u16, @alignCast(pathZStr.utf16Slice())) - else - isAbsoluteWindowsT(u8, pathZStr.slice()); - } - - pub fn isAbsolute(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue { - if (comptime is_bindgen) return JSC.JSValue.jsUndefined(); - const path_ptr = if (args_len > 0) args_ptr[0] else JSC.JSValue.jsUndefined(); - // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, path_ptr, "path", .{}) catch { - // Returning .zero translates to a nullprt JSC.JSValue. - return .zero; - }; - - const pathZStr = path_ptr.getZigString(globalObject); - if (pathZStr.len == 0) return JSC.JSValue.jsBoolean(false); - if (isWindows) return JSC.JSValue.jsBoolean(isAbsoluteWindowsZigString(pathZStr)); - return JSC.JSValue.jsBoolean(isAbsolutePosixZigString(pathZStr)); - } - - pub inline fn isSepPosixT(comptime T: type, byte: T) bool { - return byte == CHAR_FORWARD_SLASH; - } - - pub inline fn isSepWindowsT(comptime T: type, byte: T) bool { - return byte == CHAR_FORWARD_SLASH or byte == CHAR_BACKWARD_SLASH; - } - - /// Based on Node v21.6.1 private helper isWindowsDeviceRoot: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L60C10-L60C29 - pub inline fn isWindowsDeviceRootT(comptime T: type, byte: T) bool { - return (byte >= 'A' and byte <= 'Z') or (byte >= 'a' and byte <= 'z'); - } - - /// Based on Node v21.6.1 path.posix.join: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1169 - pub inline fn joinPosixT(comptime T: type, paths: []const []const T, buf: []T, buf2: []T) []const T { - comptime validatePathT(T, "joinPosixT"); - - if (paths.len == 0) { - return comptime L(T, CHAR_STR_DOT); - } - - var bufSize: usize = 0; - var bufOffset: usize = 0; - - // Back joined by expandable buf2 in case it is long. - var joined: []const T = comptime L(T, ""); - - for (paths) |path| { - // validateString of `path is performed in pub fn join. - // Back our virtual "joined" string by expandable buf2 in - // case it is long. - const len = path.len; - if (len > 0) { - // Translated from the following JS code: - // if (joined === undefined) - // joined = arg; - // else - // joined += `/${arg}`; - if (bufSize != 0) { - bufOffset = bufSize; - bufSize += 1; - buf2[bufOffset] = CHAR_FORWARD_SLASH; - } - bufOffset = bufSize; - bufSize += len; - @memcpy(buf2[bufOffset..bufSize], path); - - joined = buf2[0..bufSize]; - } - } - if (bufSize == 0) { - return comptime L(T, CHAR_STR_DOT); - } - return normalizePosixT(T, joined, buf); - } - - /// Based on Node v21.6.1 path.win32.join: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L425 - pub fn joinWindowsT(comptime T: type, paths: []const []const T, buf: []T, buf2: []T) []const T { - comptime validatePathT(T, "joinWindowsT"); - - if (paths.len == 0) { - return comptime L(T, CHAR_STR_DOT); - } - - const isSepT = isSepWindowsT; - - var bufSize: usize = 0; - var bufOffset: usize = 0; - - // Backed by expandable buf2 in case it is long. - var joined: []const T = comptime L(T, ""); - var firstPart: []const T = comptime L(T, ""); - - for (paths) |path| { - // validateString of `path` is performed in pub fn join. - const len = path.len; - if (len > 0) { - // Translated from the following JS code: - // if (joined === undefined) - // joined = firstPart = arg; - // else - // joined += `\\${arg}`; - bufOffset = bufSize; - if (bufSize == 0) { - bufSize = len; - @memcpy(buf2[0..bufSize], path); - - joined = buf2[0..bufSize]; - firstPart = joined; - } else { - bufOffset = bufSize; - bufSize += 1; - buf2[bufOffset] = CHAR_BACKWARD_SLASH; - bufOffset = bufSize; - bufSize += len; - @memcpy(buf2[bufOffset..bufSize], path); - - joined = buf2[0..bufSize]; - } - } - } - if (bufSize == 0) { - return comptime L(T, CHAR_STR_DOT); - } - - // Make sure that the joined path doesn't start with two slashes, because - // normalize() will mistake it for a UNC path then. - // - // This step is skipped when it is very clear that the user actually - // intended to point at a UNC path. This is assumed when the first - // non-empty string arguments starts with exactly two slashes followed by - // at least one more non-slash character. - // - // Note that for normalize() to treat a path as a UNC path it needs to - // have at least 2 components, so we don't filter for that here. - // This means that the user can use join to construct UNC paths from - // a server name and a share name; for example: - // path.join('//server', 'share') -> '\\\\server\\share\\') - var needsReplace: bool = true; - var slashCount: usize = 0; - if (isSepT(T, firstPart[0])) { - slashCount += 1; - const firstLen = firstPart.len; - if (firstLen > 1 and - isSepT(T, firstPart[1])) - { - slashCount += 1; - if (firstLen > 2) { - if (isSepT(T, firstPart[2])) { - slashCount += 1; - } else { - // We matched a UNC path in the first part - needsReplace = false; - } - } - } - } - if (needsReplace) { - // Find any more consecutive slashes we need to replace - while (slashCount < bufSize and - isSepT(T, joined[slashCount])) - { - slashCount += 1; - } - // Replace the slashes if needed - if (slashCount >= 2) { - // Translated from the following JS code: - // joined = `\\${StringPrototypeSlice(joined, slashCount)}`; - bufOffset = 1; - bufSize = bufOffset + (bufSize - slashCount); - // Move all bytes to the right by slashCount - 1. - // Use bun.copy because joined and buf2 overlap. - bun.copy(u8, buf2[bufOffset..bufSize], joined[slashCount..]); - // Prepend the separator. - buf2[0] = CHAR_BACKWARD_SLASH; - - joined = buf2[0..bufSize]; - } - } - return normalizeWindowsT(T, joined, buf); - } - - pub inline fn joinPosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, paths: []const []const T, buf: []T, buf2: []T) JSC.JSValue { - return toJSString(globalObject, joinPosixT(T, paths, buf, buf2)); - } - - pub inline fn joinWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, paths: []const []const T, buf: []T, buf2: []T) JSC.JSValue { - return toJSString(globalObject, joinWindowsT(T, paths, buf, buf2)); - } - - pub fn joinJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, paths: []const []const T) JSC.JSValue { - // Adding 8 bytes when Windows for the possible UNC root. - var bufLen: usize = if (isWindows) 8 else 0; - for (paths) |path| bufLen += if (bufLen > 0 and path.len > 0) path.len + 1 else path.len; - bufLen = @max(bufLen, PATH_SIZE(T)); - const buf = allocator.alloc(T, bufLen) catch bun.outOfMemory(); - defer allocator.free(buf); - const buf2 = allocator.alloc(T, bufLen) catch bun.outOfMemory(); - defer allocator.free(buf2); - return if (isWindows) joinWindowsJS_T(T, globalObject, paths, buf, buf2) else joinPosixJS_T(T, globalObject, paths, buf, buf2); - } - - pub fn join(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue { - if (comptime is_bindgen) return JSC.JSValue.jsUndefined(); - if (args_len == 0) return toUTF8JSString(globalObject, CHAR_STR_DOT); - - var arena = bun.ArenaAllocator.init(heap_allocator); - defer arena.deinit(); - - var stack_fallback = std.heap.stackFallback(stack_fallback_size_large, arena.allocator()); - const allocator = stack_fallback.get(); - - var paths = allocator.alloc(string, args_len) catch bun.outOfMemory(); - defer allocator.free(paths); - - for (0..args_len, args_ptr) |i, path_ptr| { - // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, path_ptr, "paths[{d}]", .{i}) catch { - // Returning .zero translates to a nullprt JSC.JSValue. - return .zero; - }; - const pathZStr = path_ptr.getZigString(globalObject); - paths[i] = if (pathZStr.len > 0) pathZStr.toSlice(allocator).slice() else ""; - } - return joinJS_T(u8, globalObject, allocator, isWindows, paths); - } - - /// Based on Node v21.6.1 private helper normalizeString: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L65C1-L66C77 - /// - /// Resolves . and .. elements in a path with directory names - fn normalizeStringT(comptime T: type, path: []const T, allowAboveRoot: bool, separator: T, comptime platform: path_handler.Platform, buf: []T) []const T { - const len = path.len; - const isSepT = - if (platform == .posix) - isSepPosixT - else - isSepWindowsT; - - var bufOffset: usize = 0; - var bufSize: usize = 0; - - var res: []const T = comptime L(T, ""); - var lastSegmentLength: usize = 0; - // We use an optional value instead of -1, as in Node code, for easier number type use. - var lastSlash: ?usize = null; - // We use an optional value instead of -1, as in Node code, for easier number type use. - var dots: ?usize = 0; - var byte: T = 0; - - var i: usize = 0; - while (i <= len) : (i += 1) { - if (i < len) { - byte = path[i]; - } else if (isSepT(T, byte)) { - break; - } else { - byte = CHAR_FORWARD_SLASH; - } - - if (isSepT(T, byte)) { - // Translated from the following JS code: - // if (lastSlash === i - 1 || dots === 1) { - if ((lastSlash == null and i == 0) or - (lastSlash != null and i > 0 and lastSlash.? == i - 1) or - (dots != null and dots.? == 1)) - { - // NOOP - } else if (dots != null and dots.? == 2) { - if (bufSize < 2 or - lastSegmentLength != 2 or - buf[bufSize - 1] != CHAR_DOT or - buf[bufSize - 2] != CHAR_DOT) - { - if (bufSize > 2) { - const lastSlashIndex = std.mem.lastIndexOfScalar(T, buf[0..bufSize], separator); - if (lastSlashIndex == null) { - res = comptime L(T, ""); - bufSize = 0; - lastSegmentLength = 0; - } else { - bufSize = lastSlashIndex.?; - res = buf[0..bufSize]; - // Translated from the following JS code: - // lastSegmentLength = - // res.length - 1 - StringPrototypeLastIndexOf(res, separator); - const lastIndexOfSep = std.mem.lastIndexOfScalar(T, buf[0..bufSize], separator); - if (lastIndexOfSep == null) { - // Yes (>ლ), Node relies on the -1 result of - // StringPrototypeLastIndexOf(res, separator). - // A - -1 is a positive 1. - // So the code becomes - // lastSegmentLength = res.length - 1 + 1; - // or - // lastSegmentLength = res.length; - lastSegmentLength = bufSize; - } else { - lastSegmentLength = bufSize - 1 - lastIndexOfSep.?; - } - } - lastSlash = i; - dots = 0; - continue; - } else if (bufSize != 0) { - res = comptime L(T, ""); - bufSize = 0; - lastSegmentLength = 0; - lastSlash = i; - dots = 0; - continue; - } - } - if (allowAboveRoot) { - // Translated from the following JS code: - // res += res.length > 0 ? `${separator}..` : '..'; - if (bufSize > 0) { - bufOffset = bufSize; - bufSize += 1; - buf[bufOffset] = separator; - bufOffset = bufSize; - bufSize += 2; - buf[bufOffset] = CHAR_DOT; - buf[bufOffset + 1] = CHAR_DOT; - } else { - bufSize = 2; - buf[0] = CHAR_DOT; - buf[1] = CHAR_DOT; - } - - res = buf[0..bufSize]; - lastSegmentLength = 2; - } - } else { - // Translated from the following JS code: - // if (res.length > 0) - // res += `${separator}${StringPrototypeSlice(path, lastSlash + 1, i)}`; - // else - // res = StringPrototypeSlice(path, lastSlash + 1, i); - if (bufSize > 0) { - bufOffset = bufSize; - bufSize += 1; - buf[bufOffset] = separator; - } - const sliceStart = if (lastSlash != null) lastSlash.? + 1 else 0; - const slice = path[sliceStart..i]; - - bufOffset = bufSize; - bufSize += slice.len; - @memcpy(buf[bufOffset..bufSize], slice); - - res = buf[0..bufSize]; - - // Translated from the following JS code: - // lastSegmentLength = i - lastSlash - 1; - const subtract = if (lastSlash != null) lastSlash.? + 1 else 2; - lastSegmentLength = if (i >= subtract) i - subtract else 0; - } - lastSlash = i; - dots = 0; - continue; - } else if (byte == CHAR_DOT and dots != null) { - dots = if (dots != null) dots.? + 1 else 0; - continue; - } else { - dots = null; - } - } - - return res; - } - - /// Based on Node v21.6.1 path.posix.normalize - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1130 - pub fn normalizePosixT(comptime T: type, path: []const T, buf: []T) []const T { - comptime validatePathT(T, "normalizePosixT"); - - // validateString of `path` is performed in pub fn normalize. - const len = path.len; - if (len == 0) { - return comptime L(T, CHAR_STR_DOT); - } - - // Prefix with _ to avoid shadowing the identifier in the outer scope. - const _isAbsolute = path[0] == CHAR_FORWARD_SLASH; - const trailingSeparator = path[len - 1] == CHAR_FORWARD_SLASH; - - // Normalize the path - var normalizedPath = normalizeStringT(T, path, !_isAbsolute, CHAR_FORWARD_SLASH, .posix, buf); - - var bufSize: usize = normalizedPath.len; - if (bufSize == 0) { - if (_isAbsolute) { - return comptime L(T, CHAR_STR_FORWARD_SLASH); - } - return if (trailingSeparator) - comptime L(T, "./") - else - comptime L(T, CHAR_STR_DOT); - } - - var bufOffset: usize = 0; - - // Translated from the following JS code: - // if (trailingSeparator) - // path += '/'; - if (trailingSeparator) { - bufOffset = bufSize; - bufSize += 1; - buf[bufOffset] = CHAR_FORWARD_SLASH; - normalizedPath = buf[0..bufSize]; - } - - // Translated from the following JS code: - // return isAbsolute ? `/${path}` : path; - if (_isAbsolute) { - bufOffset = 1; - bufSize += 1; - // Move all bytes to the right by 1 for the separator. - // Use bun.copy because normalizedPath and buf overlap. - bun.copy(T, buf[bufOffset..bufSize], normalizedPath); - // Prepend the separator. - buf[0] = CHAR_FORWARD_SLASH; - normalizedPath = buf[0..bufSize]; - } - return normalizedPath[0..bufSize]; - } - - /// Based on Node v21.6.1 path.win32.normalize - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L308 - pub fn normalizeWindowsT(comptime T: type, path: []const T, buf: []T) []const T { - comptime validatePathT(T, "normalizeWindowsT"); - - // validateString of `path` is performed in pub fn normalize. - const len = path.len; - if (len == 0) { - return comptime L(T, CHAR_STR_DOT); - } - - const isSepT = isSepWindowsT; - - // Moved `rootEnd`, `device`, and `_isAbsolute` initialization after - // the `if (len == 1)` check. - const byte0: T = path[0]; - - // Try to match a root - if (len == 1) { - // `path` contains just a single char, exit early to avoid - // unnecessary work - return if (isSepT(T, byte0)) comptime L(T, CHAR_STR_BACKWARD_SLASH) else path; - } - - var rootEnd: usize = 0; - // Backed by buf. - var device: ?[]const T = null; - // Prefix with _ to avoid shadowing the identifier in the outer scope. - var _isAbsolute: bool = false; - - var bufOffset: usize = 0; - var bufSize: usize = 0; - - if (isSepT(T, byte0)) { - // Possible UNC root - - // If we started with a separator, we know we at least have an absolute - // path of some kind (UNC or otherwise) - _isAbsolute = true; - - if (isSepT(T, path[1])) { - // Matched double path separator at beginning - var j: usize = 2; - var last: usize = j; - // Match 1 or more non-path separators - while (j < len and - !isSepT(T, path[j])) - { - j += 1; - } - if (j < len and j != last) { - const firstPart: []const u8 = path[last..j]; - // Matched! - last = j; - // Match 1 or more path separators - while (j < len and - isSepT(T, path[j])) - { - j += 1; - } - if (j < len and j != last) { - // Matched! - last = j; - // Match 1 or more non-path separators - while (j < len and - !isSepT(T, path[j])) - { - j += 1; - } - if (j == len) { - // We matched a UNC root only - // Return the normalized version of the UNC root since there - // is nothing left to process - - // Translated from the following JS code: - // return `\\\\${firstPart}\\${StringPrototypeSlice(path, last)}\\`; - bufSize = 2; - buf[0] = CHAR_BACKWARD_SLASH; - buf[1] = CHAR_BACKWARD_SLASH; - bufOffset = bufSize; - bufSize += firstPart.len; - @memcpy(buf[bufOffset..bufSize], firstPart); - bufOffset = bufSize; - bufSize += 1; - buf[bufOffset] = CHAR_BACKWARD_SLASH; - bufOffset = bufSize; - bufSize += len - last; - @memcpy(buf[bufOffset..bufSize], path[last..len]); - bufOffset = bufSize; - bufSize += 1; - buf[bufOffset] = CHAR_BACKWARD_SLASH; - return buf[0..bufSize]; - } - if (j != last) { - // We matched a UNC root with leftovers - - // Translated from the following JS code: - // device = - // `\\\\${firstPart}\\${StringPrototypeSlice(path, last, j)}`; - // rootEnd = j; - bufSize = 2; - buf[0] = CHAR_BACKWARD_SLASH; - buf[1] = CHAR_BACKWARD_SLASH; - bufOffset = bufSize; - bufSize += firstPart.len; - @memcpy(buf[bufOffset..bufSize], firstPart); - bufOffset = bufSize; - bufSize += 1; - buf[bufOffset] = CHAR_BACKWARD_SLASH; - bufOffset = bufSize; - bufSize += j - last; - @memcpy(buf[bufOffset..bufSize], path[last..j]); - - device = buf[0..bufSize]; - rootEnd = j; - } - } - } - } else { - rootEnd = 1; - } - } else if (isWindowsDeviceRootT(T, byte0) and - path[1] == CHAR_COLON) - { - // Possible device root - buf[0] = byte0; - buf[1] = CHAR_COLON; - device = buf[0..2]; - rootEnd = 2; - if (len > 2 and isSepT(T, path[2])) { - // Treat separator following drive name as an absolute path - // indicator - _isAbsolute = true; - rootEnd = 3; - } - } - - bufOffset = (if (device) |_d| _d.len else 0) + @intFromBool(_isAbsolute); - // Backed by buf at an offset of device.len + 1 if _isAbsolute is true. - var tailLen = if (rootEnd < len) normalizeStringT(T, path[rootEnd..len], !_isAbsolute, CHAR_BACKWARD_SLASH, .windows, buf[bufOffset..]).len else 0; - if (tailLen == 0 and !_isAbsolute) { - buf[bufOffset] = CHAR_DOT; - tailLen = 1; - } - - if (tailLen > 0 and - isSepT(T, path[len - 1])) - { - // Translated from the following JS code: - // tail += '\\'; - buf[bufOffset + tailLen] = CHAR_BACKWARD_SLASH; - tailLen += 1; - } - - bufSize = bufOffset + tailLen; - // Translated from the following JS code: - // if (device === undefined) { - // return isAbsolute ? `\\${tail}` : tail; - // } - // return isAbsolute ? `${device}\\${tail}` : `${device}${tail}`; - if (_isAbsolute) { - bufOffset -= 1; - // Prepend the separator. - buf[bufOffset] = CHAR_BACKWARD_SLASH; - } - return buf[0..bufSize]; - } - - pub fn normalizeT(comptime T: type, path: []const T, buf: []T) []const T { - return switch (Environment.os) { - .windows => normalizeWindowsT(T, path, buf), - else => normalizePosixT(T, path, buf), - }; - } - - pub inline fn normalizePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T, buf: []T) JSC.JSValue { - return toJSString(globalObject, normalizePosixT(T, path, buf)); - } - - pub inline fn normalizeWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T, buf: []T) JSC.JSValue { - return toJSString(globalObject, normalizeWindowsT(T, path, buf)); - } - - pub fn normalizeJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, path: []const T) JSC.JSValue { - const bufLen = @max(path.len, PATH_SIZE(T)); - const buf = allocator.alloc(T, bufLen) catch bun.outOfMemory(); - defer allocator.free(buf); - return if (isWindows) normalizeWindowsJS_T(T, globalObject, path, buf) else normalizePosixJS_T(T, globalObject, path, buf); - } - - pub fn normalize(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue { - if (comptime is_bindgen) return JSC.JSValue.jsUndefined(); - const path_ptr = if (args_len > 0) args_ptr[0] else JSC.JSValue.jsUndefined(); - // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, path_ptr, "path", .{}) catch { - // Returning .zero translates to a nullprt JSC.JSValue. - return .zero; - }; - const pathZStr = path_ptr.getZigString(globalObject); - const len = pathZStr.len; - if (len == 0) return toUTF8JSString(globalObject, CHAR_STR_DOT); - - var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, JSC.getAllocator(globalObject)); - const allocator = stack_fallback.get(); - - const pathZSlice = pathZStr.toSlice(allocator); - defer pathZSlice.deinit(); - return normalizeJS_T(u8, globalObject, allocator, isWindows, pathZSlice.slice()); - } - - // Based on Node v21.6.1 path.posix.parse - // https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1452 - pub fn parsePosixT(comptime T: type, path: []const T) PathParsed(T) { - comptime validatePathT(T, "parsePosixT"); - - // validateString of `path` is performed in pub fn parse. - const len = path.len; - if (len == 0) { - return .{}; - } - - var root: []const T = comptime L(T, ""); - var dir: []const T = comptime L(T, ""); - var base: []const T = comptime L(T, ""); - var ext: []const T = comptime L(T, ""); - // Prefix with _ to avoid shadowing the identifier in the outer scope. - var _name: []const T = comptime L(T, ""); - // Prefix with _ to avoid shadowing the identifier in the outer scope. - const _isAbsolute = path[0] == CHAR_FORWARD_SLASH; - var start: usize = 0; - if (_isAbsolute) { - root = comptime L(T, CHAR_STR_FORWARD_SLASH); - start = 1; - } - - // We use an optional value instead of -1, as in Node code, for easier number type use. - var startDot: ?usize = null; - var startPart: usize = 0; - // We use an optional value instead of -1, as in Node code, for easier number type use. - var end: ?usize = null; - var matchedSlash = true; - var i_i64 = @as(i64, @intCast(len - 1)); - - // Track the state of characters (if any) we see before our first dot and - // after any path separator we find - - // We use an optional value instead of -1, as in Node code, for easier number type use. - var preDotState: ?usize = 0; - - // Get non-dir info - while (i_i64 >= start) : (i_i64 -= 1) { - const i = @as(usize, @intCast(i_i64)); - const byte = path[i]; - if (byte == CHAR_FORWARD_SLASH) { - // If we reached a path separator that was not part of a set of path - // separators at the end of the string, stop now - if (!matchedSlash) { - startPart = i + 1; - break; - } - continue; - } - if (end == null) { - // We saw the first non-path separator, mark this as the end of our - // extension - matchedSlash = false; - end = i + 1; - } - if (byte == CHAR_DOT) { - // If this is our first dot, mark it as the start of our extension - if (startDot == null) { - startDot = i; - } else if (preDotState) |_preDotState| { - if (_preDotState != 1) { - preDotState = 1; - } - } - } else if (startDot != null) { - // We saw a non-dot and non-path separator before our dot, so we should - // have a good chance at having a non-empty extension - preDotState = null; - } - } - - if (end) |_end| { - const _preDotState = if (preDotState) |_p| _p else 0; - const _startDot = if (startDot) |_s| _s else 0; - start = if (startPart == 0 and _isAbsolute) 1 else startPart; - if (startDot == null or - // We saw a non-dot character immediately before the dot - (preDotState != null and _preDotState == 0) or - // The (right-most) trimmed path component is exactly '..' - (_preDotState == 1 and - _startDot == _end - 1 and - _startDot == startPart + 1)) - { - _name = path[start.._end]; - base = _name; - } else { - _name = path[start.._startDot]; - base = path[start.._end]; - ext = path[_startDot.._end]; - } - } - - if (startPart > 0) { - dir = path[0..(startPart - 1)]; - } else if (_isAbsolute) { - dir = comptime L(T, CHAR_STR_FORWARD_SLASH); - } - - return .{ .root = root, .dir = dir, .base = base, .ext = ext, .name = _name }; - } - - // Based on Node v21.6.1 path.win32.parse - // https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L916 - pub fn parseWindowsT(comptime T: type, path: []const T) PathParsed(T) { - comptime validatePathT(T, "parseWindowsT"); - - // validateString of `path` is performed in pub fn parse. - var root: []const T = comptime L(T, ""); - var dir: []const T = comptime L(T, ""); - var base: []const T = comptime L(T, ""); - var ext: []const T = comptime L(T, ""); - // Prefix with _ to avoid shadowing the identifier in the outer scope. - var _name: []const T = comptime L(T, ""); - - const len = path.len; - if (len == 0) { - return .{ .root = root, .dir = dir, .base = base, .ext = ext, .name = _name }; - } - - const isSepT = isSepWindowsT; - - var rootEnd: usize = 0; - var byte = path[0]; - - if (len == 1) { - if (isSepT(T, byte)) { - // `path` contains just a path separator, exit early to avoid - // unnecessary work - root = path; - dir = path; - } else { - base = path; - _name = path; - } - return .{ .root = root, .dir = dir, .base = base, .ext = ext, .name = _name }; - } - - // Try to match a root - if (isSepT(T, byte)) { - // Possible UNC root - - rootEnd = 1; - if (isSepT(T, path[1])) { - // Matched double path separator at the beginning - var j: usize = 2; - var last: usize = j; - // Match 1 or more non-path separators - while (j < len and - !isSepT(T, path[j])) - { - j += 1; - } - if (j < len and j != last) { - // Matched! - last = j; - // Match 1 or more path separators - while (j < len and - isSepT(T, path[j])) - { - j += 1; - } - if (j < len and j != last) { - // Matched! - last = j; - // Match 1 or more non-path separators - while (j < len and - !isSepT(T, path[j])) - { - j += 1; - } - if (j == len) { - // We matched a UNC root only - rootEnd = j; - } else if (j != last) { - // We matched a UNC root with leftovers - rootEnd = j + 1; - } - } - } - } - } else if (isWindowsDeviceRootT(T, byte) and - path[1] == CHAR_COLON) - { - // Possible device root - if (len <= 2) { - // `path` contains just a drive root, exit early to avoid - // unnecessary work - root = path; - dir = path; - return .{ .root = root, .dir = dir, .base = base, .ext = ext, .name = _name }; - } - rootEnd = 2; - if (isSepT(T, path[2])) { - if (len == 3) { - // `path` contains just a drive root, exit early to avoid - // unnecessary work - root = path; - dir = path; - return .{ .root = root, .dir = dir, .base = base, .ext = ext, .name = _name }; - } - rootEnd = 3; - } - } - if (rootEnd > 0) { - root = path[0..rootEnd]; - } - - // We use an optional value instead of -1, as in Node code, for easier number type use. - var startDot: ?usize = null; - var startPart = rootEnd; - // We use an optional value instead of -1, as in Node code, for easier number type use. - var end: ?usize = null; - var matchedSlash = true; - var i_i64 = @as(i64, @intCast(len - 1)); - - // Track the state of characters (if any) we see before our first dot and - // after any path separator we find - - // We use an optional value instead of -1, as in Node code, for easier number type use. - var preDotState: ?usize = 0; - - // Get non-dir info - while (i_i64 >= rootEnd) : (i_i64 -= 1) { - const i = @as(usize, @intCast(i_i64)); - byte = path[i]; - if (isSepT(T, byte)) { - // If we reached a path separator that was not part of a set of path - // separators at the end of the string, stop now - if (!matchedSlash) { - startPart = i + 1; - break; - } - continue; - } - if (end == null) { - // We saw the first non-path separator, mark this as the end of our - // extension - matchedSlash = false; - end = i + 1; - } - if (byte == CHAR_DOT) { - // If this is our first dot, mark it as the start of our extension - if (startDot == null) { - startDot = i; - } else if (preDotState) |_preDotState| { - if (_preDotState != 1) { - preDotState = 1; - } - } - } else if (startDot != null) { - // We saw a non-dot and non-path separator before our dot, so we should - // have a good chance at having a non-empty extension - preDotState = null; - } - } - - if (end) |_end| { - const _preDotState = if (preDotState) |_p| _p else 0; - const _startDot = if (startDot) |_s| _s else 0; - if (startDot == null or - // We saw a non-dot character immediately before the dot - (preDotState != null and _preDotState == 0) or - // The (right-most) trimmed path component is exactly '..' - (_preDotState == 1 and - _startDot == _end - 1 and - _startDot == startPart + 1)) - { - // Prefix with _ to avoid shadowing the identifier in the outer scope. - _name = path[startPart.._end]; - base = _name; - } else { - _name = path[startPart.._startDot]; - base = path[startPart.._end]; - ext = path[_startDot.._end]; - } - } - - // If the directory is the root, use the entire root as the `dir` including - // the trailing slash if any (`C:\abc` -> `C:\`). Otherwise, strip out the - // trailing slash (`C:\abc\def` -> `C:\abc`). - if (startPart > 0 and startPart != rootEnd) { - dir = path[0..(startPart - 1)]; - } else { - dir = root; - } - - return .{ .root = root, .dir = dir, .base = base, .ext = ext, .name = _name }; - } - - pub inline fn parsePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) JSC.JSValue { - return parsePosixT(T, path).toJSObject(globalObject); - } - - pub inline fn parseWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) JSC.JSValue { - return parseWindowsT(T, path).toJSObject(globalObject); - } - - pub inline fn parseJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, isWindows: bool, path: []const T) JSC.JSValue { - return if (isWindows) parseWindowsJS_T(T, globalObject, path) else parsePosixJS_T(T, globalObject, path); - } - - pub fn parse(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue { - if (comptime is_bindgen) return JSC.JSValue.jsUndefined(); - const path_ptr = if (args_len > 0) args_ptr[0] else JSC.JSValue.jsUndefined(); - // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, path_ptr, "path", .{}) catch { - // Returning .zero translates to a nullprt JSC.JSValue. - return .zero; - }; - - const pathZStr = path_ptr.getZigString(globalObject); - if (pathZStr.len == 0) return (PathParsed(u8){}).toJSObject(globalObject); - - var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, JSC.getAllocator(globalObject)); - const allocator = stack_fallback.get(); - - const pathZSlice = pathZStr.toSlice(allocator); - defer pathZSlice.deinit(); - return parseJS_T(u8, globalObject, isWindows, pathZSlice.slice()); - } - - /// Based on Node v21.6.1 path.posix.relative: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1193 - pub fn relativePosixT(comptime T: type, from: []const T, to: []const T, buf: []T, buf2: []T, buf3: []T) MaybeSlice(T) { - comptime validatePathT(T, "relativePosixT"); - - // validateString of `from` and `to` are performed in pub fn relative. - if (std.mem.eql(T, from, to)) { - return MaybeSlice(T){ .result = comptime L(T, "") }; - } - - // Trim leading forward slashes. - // Backed by expandable buf2 because fromOrig may be long. - const fromOrig = switch (resolvePosixT(T, &.{from}, buf2, buf3)) { - .result => |r| r, - .err => |e| return MaybeSlice(T){ .err = e }, - }; - const fromOrigLen = fromOrig.len; - // Backed by buf. - const toOrig = switch (resolvePosixT(T, &.{to}, buf, buf3)) { - .result => |r| r, - .err => |e| return MaybeSlice(T){ .err = e }, - }; - - if (std.mem.eql(T, fromOrig, toOrig)) { - return MaybeSlice(T){ .result = comptime L(T, "") }; - } - - const fromStart = 1; - const fromEnd = fromOrigLen; - const fromLen = fromEnd - fromStart; - const toOrigLen = toOrig.len; - var toStart: usize = 1; - const toLen = toOrigLen - toStart; - - // Compare paths to find the longest common path from root - const smallestLength = @min(fromLen, toLen); - // We use an optional value instead of -1, as in Node code, for easier number type use. - var lastCommonSep: ?usize = null; - - var matchesAllOfSmallest = false; - // Add a block to isolate `i`. - { - var i: usize = 0; - while (i < smallestLength) : (i += 1) { - const fromByte = fromOrig[fromStart + i]; - if (fromByte != toOrig[toStart + i]) { - break; - } else if (fromByte == CHAR_FORWARD_SLASH) { - lastCommonSep = i; - } - } - matchesAllOfSmallest = i == smallestLength; - } - if (matchesAllOfSmallest) { - if (toLen > smallestLength) { - if (toOrig[toStart + smallestLength] == CHAR_FORWARD_SLASH) { - // We get here if `from` is the exact base path for `to`. - // For example: from='/foo/bar'; to='/foo/bar/baz' - return MaybeSlice(T){ .result = toOrig[toStart + smallestLength + 1 .. toOrigLen] }; - } - if (smallestLength == 0) { - // We get here if `from` is the root - // For example: from='/'; to='/foo' - return MaybeSlice(T){ .result = toOrig[toStart + smallestLength .. toOrigLen] }; - } - } else if (fromLen > smallestLength) { - if (fromOrig[fromStart + smallestLength] == CHAR_FORWARD_SLASH) { - // We get here if `to` is the exact base path for `from`. - // For example: from='/foo/bar/baz'; to='/foo/bar' - lastCommonSep = smallestLength; - } else if (smallestLength == 0) { - // We get here if `to` is the root. - // For example: from='/foo/bar'; to='/' - lastCommonSep = 0; - } - } - } - - var bufOffset: usize = 0; - var bufSize: usize = 0; - - // Backed by buf3. - var out: []const T = comptime L(T, ""); - // Add a block to isolate `i`. - { - // Generate the relative path based on the path difference between `to` - // and `from`. - - // Translated from the following JS code: - // for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) { - var i: usize = fromStart + (if (lastCommonSep != null) lastCommonSep.? + 1 else 0); - while (i <= fromEnd) : (i += 1) { - if (i == fromEnd or fromOrig[i] == CHAR_FORWARD_SLASH) { - // Translated from the following JS code: - // out += out.length === 0 ? '..' : '/..'; - if (out.len > 0) { - bufOffset = bufSize; - bufSize += 3; - buf3[bufOffset] = CHAR_FORWARD_SLASH; - buf3[bufOffset + 1] = CHAR_DOT; - buf3[bufOffset + 2] = CHAR_DOT; - } else { - bufSize = 2; - buf3[0] = CHAR_DOT; - buf3[1] = CHAR_DOT; - } - out = buf3[0..bufSize]; - } - } - } - - // Lastly, append the rest of the destination (`to`) path that comes after - // the common path parts. - - // Translated from the following JS code: - // return `${out}${StringPrototypeSlice(to, toStart + lastCommonSep)}`; - toStart = if (lastCommonSep != null) toStart + lastCommonSep.? else 0; - const sliceSize = toOrigLen - toStart; - const outLen = out.len; - bufSize = outLen; - if (sliceSize > 0) { - bufOffset = bufSize; - bufSize += sliceSize; - // Use bun.copy because toOrig and buf overlap. - bun.copy(T, buf[bufOffset..bufSize], toOrig[toStart..toOrigLen]); - } - if (outLen > 0) { - @memcpy(buf[0..outLen], out); - } - return MaybeSlice(T){ .result = buf[0..bufSize] }; - } - - /// Based on Node v21.6.1 path.win32.relative: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L500 - pub fn relativeWindowsT(comptime T: type, from: []const T, to: []const T, buf: []T, buf2: []T, buf3: []T) MaybeSlice(T) { - comptime validatePathT(T, "relativeWindowsT"); - - // validateString of `from` and `to` are performed in pub fn relative. - if (std.mem.eql(T, from, to)) { - return MaybeSlice(T){ .result = comptime L(T, "") }; - } - - // Backed by expandable buf2 because fromOrig may be long. - const fromOrig = switch (resolveWindowsT(T, &.{from}, buf2, buf3)) { - .result => |r| r, - .err => |e| return MaybeSlice(T){ .err = e }, - }; - const fromOrigLen = fromOrig.len; - // Backed by buf. - const toOrig = switch (resolveWindowsT(T, &.{to}, buf, buf3)) { - .result => |r| r, - .err => |e| return MaybeSlice(T){ .err = e }, - }; - - if (std.mem.eql(T, fromOrig, toOrig) or - eqlIgnoreCaseT(T, fromOrig, toOrig)) - { - return MaybeSlice(T){ .result = comptime L(T, "") }; - } - - const toOrigLen = toOrig.len; - - // Trim leading backslashes - var fromStart: usize = 0; - while (fromStart < fromOrigLen and - fromOrig[fromStart] == CHAR_BACKWARD_SLASH) - { - fromStart += 1; - } - - // Trim trailing backslashes (applicable to UNC paths only) - var fromEnd = fromOrigLen; - while (fromEnd - 1 > fromStart and - fromOrig[fromEnd - 1] == CHAR_BACKWARD_SLASH) - { - fromEnd -= 1; - } - - const fromLen = fromEnd - fromStart; - - // Trim leading backslashes - var toStart: usize = 0; - while (toStart < toOrigLen and - toOrig[toStart] == CHAR_BACKWARD_SLASH) - { - toStart = toStart + 1; - } - - // Trim trailing backslashes (applicable to UNC paths only) - var toEnd = toOrigLen; - while (toEnd - 1 > toStart and - toOrig[toEnd - 1] == CHAR_BACKWARD_SLASH) - { - toEnd -= 1; - } - - const toLen = toEnd - toStart; - - // Compare paths to find the longest common path from root - const smallestLength = @min(fromLen, toLen); - // We use an optional value instead of -1, as in Node code, for easier number type use. - var lastCommonSep: ?usize = null; - - var matchesAllOfSmallest = false; - // Add a block to isolate `i`. - { - var i: usize = 0; - while (i < smallestLength) : (i += 1) { - const fromByte = fromOrig[fromStart + i]; - if (toLowerT(T, fromByte) != toLowerT(T, toOrig[toStart + i])) { - break; - } else if (fromByte == CHAR_BACKWARD_SLASH) { - lastCommonSep = i; - } - } - matchesAllOfSmallest = i == smallestLength; - } - - // We found a mismatch before the first common path separator was seen, so - // return the original `to`. - if (!matchesAllOfSmallest) { - if (lastCommonSep == null) { - return MaybeSlice(T){ .result = toOrig }; - } - } else { - if (toLen > smallestLength) { - if (toOrig[toStart + smallestLength] == CHAR_BACKWARD_SLASH) { - // We get here if `from` is the exact base path for `to`. - // For example: from='C:\foo\bar'; to='C:\foo\bar\baz' - return MaybeSlice(T){ .result = toOrig[toStart + smallestLength + 1 .. toOrigLen] }; - } - if (smallestLength == 2) { - // We get here if `from` is the device root. - // For example: from='C:\'; to='C:\foo' - return MaybeSlice(T){ .result = toOrig[toStart + smallestLength .. toOrigLen] }; - } - } - if (fromLen > smallestLength) { - if (fromOrig[fromStart + smallestLength] == CHAR_BACKWARD_SLASH) { - // We get here if `to` is the exact base path for `from`. - // For example: from='C:\foo\bar'; to='C:\foo' - lastCommonSep = smallestLength; - } else if (smallestLength == 2) { - // We get here if `to` is the device root. - // For example: from='C:\foo\bar'; to='C:\' - lastCommonSep = 3; - } - } - if (lastCommonSep == null) { - lastCommonSep = 0; - } - } - - var bufOffset: usize = 0; - var bufSize: usize = 0; - - // Backed by buf3. - var out: []const T = comptime L(T, ""); - // Add a block to isolate `i`. - { - // Generate the relative path based on the path difference between `to` - // and `from`. - var i: usize = fromStart + (if (lastCommonSep != null) lastCommonSep.? + 1 else 0); - while (i <= fromEnd) : (i += 1) { - if (i == fromEnd or fromOrig[i] == CHAR_BACKWARD_SLASH) { - // Translated from the following JS code: - // out += out.length === 0 ? '..' : '\\..'; - if (out.len > 0) { - bufOffset = bufSize; - bufSize += 3; - buf3[bufOffset] = CHAR_BACKWARD_SLASH; - buf3[bufOffset + 1] = CHAR_DOT; - buf3[bufOffset + 2] = CHAR_DOT; - } else { - bufSize = 2; - buf3[0] = CHAR_DOT; - buf3[1] = CHAR_DOT; - } - out = buf3[0..bufSize]; - } - } - } - - // Translated from the following JS code: - // toStart += lastCommonSep; - if (lastCommonSep == null) { - // If toStart would go negative make it toOrigLen - 1 to - // mimic String#slice with a negative start. - toStart = if (toStart > 0) toStart - 1 else toOrigLen - 1; - } else { - toStart += lastCommonSep.?; - } - - // Lastly, append the rest of the destination (`to`) path that comes after - // the common path parts - const outLen = out.len; - if (outLen > 0) { - const sliceSize = toEnd - toStart; - bufSize = outLen; - if (sliceSize > 0) { - bufOffset = bufSize; - bufSize += sliceSize; - // Use bun.copy because toOrig and buf overlap. - bun.copy(T, buf[bufOffset..bufSize], toOrig[toStart..toEnd]); - } - @memcpy(buf[0..outLen], out); - return MaybeSlice(T){ .result = buf[0..bufSize] }; - } - - if (toOrig[toStart] == CHAR_BACKWARD_SLASH) { - toStart += 1; - } - return MaybeSlice(T){ .result = toOrig[toStart..toEnd] }; - } - - pub inline fn relativePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, from: []const T, to: []const T, buf: []T, buf2: []T, buf3: []T) JSC.JSValue { - return switch (relativePosixT(T, from, to, buf, buf2, buf3)) { - .result => |r| toJSString(globalObject, r), - .err => |e| e.toJSC(globalObject), - }; - } - - pub inline fn relativeWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, from: []const T, to: []const T, buf: []T, buf2: []T, buf3: []T) JSC.JSValue { - return switch (relativeWindowsT(T, from, to, buf, buf2, buf3)) { - .result => |r| toJSString(globalObject, r), - .err => |e| e.toJSC(globalObject), - }; - } - - pub fn relativeJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, from: []const T, to: []const T) JSC.JSValue { - const bufLen = @max(from.len + to.len, PATH_SIZE(T)); - const buf = allocator.alloc(T, bufLen) catch bun.outOfMemory(); - defer allocator.free(buf); - const buf2 = allocator.alloc(T, bufLen) catch bun.outOfMemory(); - defer allocator.free(buf2); - const buf3 = allocator.alloc(T, bufLen) catch bun.outOfMemory(); - defer allocator.free(buf3); - return if (isWindows) relativeWindowsJS_T(T, globalObject, from, to, buf, buf2, buf3) else relativePosixJS_T(T, globalObject, from, to, buf, buf2, buf3); - } - - pub fn relative(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue { - if (comptime is_bindgen) return JSC.JSValue.jsUndefined(); - const from_ptr = if (args_len > 0) args_ptr[0] else JSC.JSValue.jsUndefined(); - // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, from_ptr, "from", .{}) catch { - // Returning .zero translates to a nullprt JSC.JSValue. - return .zero; - }; - const to_ptr = if (args_len > 1) args_ptr[1] else JSC.JSValue.jsUndefined(); - // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, to_ptr, "to", .{}) catch { - return .zero; - }; - - const fromZigStr = from_ptr.getZigString(globalObject); - const toZigStr = to_ptr.getZigString(globalObject); - if ((fromZigStr.len + toZigStr.len) == 0) return from_ptr; - - var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, JSC.getAllocator(globalObject)); - const allocator = stack_fallback.get(); - - var fromZigSlice = fromZigStr.toSlice(allocator); - defer fromZigSlice.deinit(); - var toZigSlice = toZigStr.toSlice(allocator); - defer toZigSlice.deinit(); - return relativeJS_T(u8, globalObject, allocator, isWindows, fromZigSlice.slice(), toZigSlice.slice()); - } - - /// Based on Node v21.6.1 path.posix.resolve: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1095 - pub fn resolvePosixT(comptime T: type, paths: []const []const T, buf: []T, buf2: []T) MaybeSlice(T) { - comptime validatePathT(T, "resolvePosixT"); - - // Backed by expandable buf2 because resolvedPath may be long. - // We use buf2 here because resolvePosixT is called by other methods and using - // buf2 here avoids stepping on others' toes. - var resolvedPath: []const T = comptime L(T, ""); - var resolvedPathLen: usize = 0; - var resolvedAbsolute: bool = false; - - var bufOffset: usize = 0; - var bufSize: usize = 0; - - var i_i64: i64 = if (paths.len == 0) -1 else @as(i64, @intCast(paths.len - 1)); - while (i_i64 > -2 and !resolvedAbsolute) : (i_i64 -= 1) { - var path: []const T = comptime L(T, ""); - if (i_i64 >= 0) { - path = paths[@as(usize, @intCast(i_i64))]; - } else { - // cwd is limited to MAX_PATH_BYTES. - var tmpBuf: [MAX_PATH_SIZE(T)]T = undefined; - path = switch (posixCwdT(T, &tmpBuf)) { - .result => |r| r, - .err => |e| return MaybeSlice(T){ .err = e }, - }; - } - // validateString of `path` is performed in pub fn resolve. - const len = path.len; - - // Skip empty paths. - if (len == 0) { - continue; - } - - // Translated from the following JS code: - // resolvedPath = `${path}/${resolvedPath}`; - if (resolvedPathLen > 0) { - bufOffset = len + 1; - bufSize = bufOffset + resolvedPathLen; - // Move all bytes to the right by path.len + 1 for the separator. - // Use bun.copy because resolvedPath and buf2 overlap. - bun.copy(u8, buf2[bufOffset..bufSize], resolvedPath); - } - bufSize = len; - @memcpy(buf2[0..bufSize], path); - bufSize += 1; - buf2[len] = CHAR_FORWARD_SLASH; - bufSize += resolvedPathLen; - - resolvedPath = buf2[0..bufSize]; - resolvedPathLen = bufSize; - resolvedAbsolute = path[0] == CHAR_FORWARD_SLASH; - } - - // Exit early for empty path. - if (resolvedPathLen == 0) { - return MaybeSlice(T){ .result = comptime L(T, CHAR_STR_DOT) }; - } - - // At this point the path should be resolved to a full absolute path, but - // handle relative paths to be safe (might happen when process.cwd() fails) - - // Normalize the path - resolvedPath = normalizeStringT(T, resolvedPath, !resolvedAbsolute, CHAR_FORWARD_SLASH, .posix, buf); - // resolvedPath is now backed by buf. - resolvedPathLen = resolvedPath.len; - - // Translated from the following JS code: - // if (resolvedAbsolute) { - // return `/${resolvedPath}`; - // } - if (resolvedAbsolute) { - bufSize = resolvedPathLen + 1; - // Use bun.copy because resolvedPath and buf overlap. - bun.copy(T, buf[1..bufSize], resolvedPath); - buf[0] = CHAR_FORWARD_SLASH; - return MaybeSlice(T){ .result = buf[0..bufSize] }; - } - // Translated from the following JS code: - // return resolvedPath.length > 0 ? resolvedPath : '.'; - return MaybeSlice(T){ .result = if (resolvedPathLen > 0) resolvedPath else comptime L(T, CHAR_STR_DOT) }; - } - - /// Based on Node v21.6.1 path.win32.resolve: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L162 - pub fn resolveWindowsT(comptime T: type, paths: []const []const T, buf: []T, buf2: []T) MaybeSlice(T) { - comptime validatePathT(T, "resolveWindowsT"); - - const isSepT = isSepWindowsT; - var tmpBuf: [MAX_PATH_SIZE(T)]T = undefined; - - // Backed by tmpBuf. - var resolvedDevice: []const T = comptime L(T, ""); - var resolvedDeviceLen: usize = 0; - // Backed by expandable buf2 because resolvedTail may be long. - // We use buf2 here because resolvePosixT is called by other methods and using - // buf2 here avoids stepping on others' toes. - var resolvedTail: []const T = comptime L(T, ""); - var resolvedTailLen: usize = 0; - var resolvedAbsolute: bool = false; - - var bufOffset: usize = 0; - var bufSize: usize = 0; - var envPath: ?[]const T = null; - - var i_i64: i64 = if (paths.len == 0) -1 else @as(i64, @intCast(paths.len - 1)); - while (i_i64 > -2) : (i_i64 -= 1) { - // Backed by expandable buf2, to not conflict with buf2 backed resolvedTail, - // because path may be long. - var path: []const T = comptime L(T, ""); - if (i_i64 >= 0) { - path = paths[@as(usize, @intCast(i_i64))]; - // validateString of `path` is performed in pub fn resolve. - - // Skip empty paths. - if (path.len == 0) { - continue; - } - } else if (resolvedDeviceLen == 0) { - // cwd is limited to MAX_PATH_BYTES. - path = switch (getCwdT(T, &tmpBuf)) { - .result => |r| r, - .err => |e| return MaybeSlice(T){ .err = e }, - }; - } else { - // Translated from the following JS code: - // path = process.env[`=${resolvedDevice}`] || process.cwd(); - if (comptime Environment.isWindows) { - // Windows has the concept of drive-specific current working - // directories. If we've resolved a drive letter but not yet an - // absolute path, get cwd for that drive, or the process cwd if - // the drive cwd is not available. We're sure the device is not - // a UNC path at this points, because UNC paths are always absolute. - - // Translated from the following JS code: - // process.env[`=${resolvedDevice}`] - const key_w: [*:0]const u16 = brk: { - if (resolvedDeviceLen == 2 and resolvedDevice[1] == CHAR_COLON) { - // Fast path for device roots - break :brk &[3:0]u16{ '=', resolvedDevice[0], CHAR_COLON }; - } - bufSize = 1; - // Reuse buf2 for the env key because it's used to get the path. - buf2[0] = '='; - bufOffset = bufSize; - bufSize += resolvedDeviceLen; - @memcpy(buf2[bufOffset..bufSize], resolvedDevice); - if (T == u16) { - break :brk buf2[0..bufSize]; - } else { - var u16Buf: bun.WPathBuffer = undefined; - bufSize = std.unicode.utf8ToUtf16Le(&u16Buf, buf2[0..bufSize]) catch { - return MaybeSlice(T).errnoSys(0, Syscall.Tag.getenv).?; - }; - break :brk u16Buf[0..bufSize :0]; - } - }; - // Zig's std.posix.getenvW has logic to support keys like `=${resolvedDevice}`: - // https://github.com/ziglang/zig/blob/7bd8b35a3dfe61e59ffea39d464e84fbcdead29a/lib/std/os.zig#L2126-L2130 - // - // TODO: Enable test once spawnResult.stdout works on Windows. - // test/js/node/path/resolve.test.js - if (std.process.getenvW(key_w)) |r| { - if (T == u16) { - bufSize = r.len; - @memcpy(buf2[0..bufSize], r); - } else { - // Reuse buf2 because it's used for path. - bufSize = std.unicode.utf16leToUtf8(buf2, r) catch { - return MaybeSlice(T).errnoSys(0, Syscall.Tag.getcwd).?; - }; - } - envPath = buf2[0..bufSize]; - } - } - if (envPath) |_envPath| { - path = _envPath; - } else { - // cwd is limited to MAX_PATH_BYTES. - path = switch (getCwdT(T, &tmpBuf)) { - .result => |r| r, - .err => |e| return MaybeSlice(T){ .err = e }, - }; - // We must set envPath here so that it doesn't hit the null check just below. - envPath = path; - } - - // Verify that a cwd was found and that it actually points - // to our drive. If not, default to the drive's root. - - // Translated from the following JS code: - // if (path === undefined || - // (StringPrototypeToLowerCase(StringPrototypeSlice(path, 0, 2)) !== - // StringPrototypeToLowerCase(resolvedDevice) && - // StringPrototypeCharCodeAt(path, 2) === CHAR_BACKWARD_SLASH)) { - if (envPath == null or - (path[2] == CHAR_BACKWARD_SLASH and - !eqlIgnoreCaseT(T, path[0..2], resolvedDevice))) - { - // Translated from the following JS code: - // path = `${resolvedDevice}\\`; - bufSize = resolvedDeviceLen; - @memcpy(buf2[0..bufSize], resolvedDevice); - bufOffset = bufSize; - bufSize += 1; - buf2[bufOffset] = CHAR_BACKWARD_SLASH; - path = buf2[0..bufSize]; - } - } - - const len = path.len; - var rootEnd: usize = 0; - // Backed by tmpBuf or an anonymous buffer. - var device: []const T = comptime L(T, ""); - // Prefix with _ to avoid shadowing the identifier in the outer scope. - var _isAbsolute: bool = false; - const byte0 = if (len > 0) path[0] else 0; - - // Try to match a root - if (len == 1) { - if (isSepT(T, byte0)) { - // `path` contains just a path separator - rootEnd = 1; - _isAbsolute = true; - } - } else if (isSepT(T, byte0)) { - // Possible UNC root - - // If we started with a separator, we know we at least have an - // absolute path of some kind (UNC or otherwise) - _isAbsolute = true; - - if (isSepT(T, path[1])) { - // Matched double path separator at the beginning - var j: usize = 2; - var last: usize = j; - // Match 1 or more non-path separators - while (j < len and - !isSepT(T, path[j])) - { - j += 1; - } - if (j < len and j != last) { - const firstPart = path[last..j]; - // Matched! - last = j; - // Match 1 or more path separators - while (j < len and - isSepT(T, path[j])) - { - j += 1; - } - if (j < len and j != last) { - // Matched! - last = j; - // Match 1 or more non-path separators - while (j < len and - !isSepT(T, path[j])) - { - j += 1; - } - if (j == len or j != last) { - // We matched a UNC root - - // Translated from the following JS code: - // device = - // `\\\\${firstPart}\\${StringPrototypeSlice(path, last, j)}`; - // rootEnd = j; - bufSize = 2; - tmpBuf[0] = CHAR_BACKWARD_SLASH; - tmpBuf[1] = CHAR_BACKWARD_SLASH; - bufOffset = bufSize; - bufSize += firstPart.len; - @memcpy(tmpBuf[bufOffset..bufSize], firstPart); - bufOffset = bufSize; - bufSize += 1; - tmpBuf[bufOffset] = CHAR_BACKWARD_SLASH; - const slice = path[last..j]; - bufOffset = bufSize; - bufSize += slice.len; - @memcpy(tmpBuf[bufOffset..bufSize], slice); - - device = tmpBuf[0..bufSize]; - rootEnd = j; - } - } - } - } else { - rootEnd = 1; - } - } else if (isWindowsDeviceRootT(T, byte0) and - path[1] == CHAR_COLON) - { - // Possible device root - device = &[2]T{ byte0, CHAR_COLON }; - rootEnd = 2; - if (len > 2 and isSepT(T, path[2])) { - // Treat separator following the drive name as an absolute path - // indicator - _isAbsolute = true; - rootEnd = 3; - } - } - - const deviceLen = device.len; - if (deviceLen > 0) { - if (resolvedDeviceLen > 0) { - // Translated from the following JS code: - // if (StringPrototypeToLowerCase(device) !== - // StringPrototypeToLowerCase(resolvedDevice)) - if (!eqlIgnoreCaseT(T, device, resolvedDevice)) { - // This path points to another device, so it is not applicable - continue; - } - } else { - // Translated from the following JS code: - // resolvedDevice = device; - bufSize = device.len; - // Copy device over if it's backed by an anonymous buffer. - if (device.ptr != tmpBuf[0..].ptr) { - @memcpy(tmpBuf[0..bufSize], device); - } - resolvedDevice = tmpBuf[0..bufSize]; - resolvedDeviceLen = bufSize; - } - } - - if (resolvedAbsolute) { - if (resolvedDeviceLen > 0) { - break; - } - } else { - // Translated from the following JS code: - // resolvedTail = `${StringPrototypeSlice(path, rootEnd)}\\${resolvedTail}`; - const sliceLen = len - rootEnd; - if (resolvedTailLen > 0) { - bufOffset = sliceLen + 1; - bufSize = bufOffset + resolvedTailLen; - // Move all bytes to the right by path slice.len + 1 for the separator - // Use bun.copy because resolvedTail and buf2 overlap. - bun.copy(u8, buf2[bufOffset..bufSize], resolvedTail); - } - bufSize = sliceLen; - if (sliceLen > 0) { - @memcpy(buf2[0..bufSize], path[rootEnd..len]); - } - bufOffset = bufSize; - bufSize += 1; - buf2[bufOffset] = CHAR_BACKWARD_SLASH; - bufSize += resolvedTailLen; - - resolvedTail = buf2[0..bufSize]; - resolvedTailLen = bufSize; - resolvedAbsolute = _isAbsolute; - - if (_isAbsolute and resolvedDeviceLen > 0) { - break; - } - } - } - - // Exit early for empty path. - if (resolvedTailLen == 0) { - return MaybeSlice(T){ .result = comptime L(T, CHAR_STR_DOT) }; - } - - // At this point, the path should be resolved to a full absolute path, - // but handle relative paths to be safe (might happen when std.process.cwdAlloc() - // fails) - - // Normalize the tail path - resolvedTail = normalizeStringT(T, resolvedTail, !resolvedAbsolute, CHAR_BACKWARD_SLASH, .windows, buf); - // resolvedTail is now backed by buf. - resolvedTailLen = resolvedTail.len; - - // Translated from the following JS code: - // resolvedAbsolute ? `${resolvedDevice}\\${resolvedTail}` - if (resolvedAbsolute) { - bufOffset = resolvedDeviceLen + 1; - bufSize = bufOffset + resolvedTailLen; - // Use bun.copy because resolvedTail and buf overlap. - bun.copy(T, buf[bufOffset..bufSize], resolvedTail); - buf[resolvedDeviceLen] = CHAR_BACKWARD_SLASH; - @memcpy(buf[0..resolvedDeviceLen], resolvedDevice); - return MaybeSlice(T){ .result = buf[0..bufSize] }; - } - // Translated from the following JS code: - // : `${resolvedDevice}${resolvedTail}` || '.' - if ((resolvedDeviceLen + resolvedTailLen) > 0) { - bufOffset = resolvedDeviceLen; - bufSize = bufOffset + resolvedTailLen; - // Use bun.copy because resolvedTail and buf overlap. - bun.copy(T, buf[bufOffset..bufSize], resolvedTail); - @memcpy(buf[0..resolvedDeviceLen], resolvedDevice); - return MaybeSlice(T){ .result = buf[0..bufSize] }; - } - return MaybeSlice(T){ .result = comptime L(T, CHAR_STR_DOT) }; - } - - pub inline fn resolvePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, paths: []const []const T, buf: []T, buf2: []T) JSC.JSValue { - return switch (resolvePosixT(T, paths, buf, buf2)) { - .result => |r| toJSString(globalObject, r), - .err => |e| e.toJSC(globalObject), - }; - } - - pub inline fn resolveWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, paths: []const []const T, buf: []T, buf2: []T) JSC.JSValue { - return switch (resolveWindowsT(T, paths, buf, buf2)) { - .result => |r| toJSString(globalObject, r), - .err => |e| e.toJSC(globalObject), - }; - } - - pub fn resolveJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, paths: []const []const T) JSC.JSValue { - // Adding 8 bytes when Windows for the possible UNC root. - var bufLen: usize = if (isWindows) 8 else 0; - for (paths) |path| bufLen += if (bufLen > 0 and path.len > 0) path.len + 1 else path.len; - bufLen = @max(bufLen, PATH_SIZE(T)); - const buf = allocator.alloc(T, bufLen) catch bun.outOfMemory(); - defer allocator.free(buf); - const buf2 = allocator.alloc(T, bufLen) catch bun.outOfMemory(); - defer allocator.free(buf2); - return if (isWindows) resolveWindowsJS_T(T, globalObject, paths, buf, buf2) else resolvePosixJS_T(T, globalObject, paths, buf, buf2); - } - - pub fn resolve(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue { - if (comptime is_bindgen) return JSC.JSValue.jsUndefined(); - - var arena = bun.ArenaAllocator.init(heap_allocator); - defer arena.deinit(); - - var stack_fallback = std.heap.stackFallback(stack_fallback_size_large, arena.allocator()); - const allocator = stack_fallback.get(); - - var paths = allocator.alloc(string, args_len) catch bun.outOfMemory(); - defer allocator.free(paths); - - for (0..args_len, args_ptr) |i, path_ptr| { - // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, path_ptr, "paths[{d}]", .{i}) catch { - // Returning .zero translates to a nullprt JSC.JSValue. - return .zero; - }; - const pathZStr = path_ptr.getZigString(globalObject); - paths[i] = if (pathZStr.len > 0) pathZStr.toSlice(allocator).slice() else ""; - } - return resolveJS_T(u8, globalObject, allocator, isWindows, paths); - } - - /// Based on Node v21.6.1 path.win32.toNamespacedPath: - /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L622 - pub fn toNamespacedPathWindowsT(comptime T: type, path: []const T, buf: []T, buf2: []T) MaybeSlice(T) { - comptime validatePathT(T, "toNamespacedPathWindowsT"); - - // validateString of `path` is performed in pub fn toNamespacedPath. - // Backed by buf. - const resolvedPath = switch (resolveWindowsT(T, &.{path}, buf, buf2)) { - .result => |r| r, - .err => |e| return MaybeSlice(T){ .err = e }, - }; - - const len = resolvedPath.len; - if (len <= 2) { - return MaybeSlice(T){ .result = path }; - } - - var bufOffset: usize = 0; - var bufSize: usize = 0; - - const byte0 = resolvedPath[0]; - if (byte0 == CHAR_BACKWARD_SLASH) { - // Possible UNC root - if (resolvedPath[1] == CHAR_BACKWARD_SLASH) { - const byte2 = resolvedPath[2]; - if (byte2 != CHAR_QUESTION_MARK and byte2 != CHAR_DOT) { - // Matched non-long UNC root, convert the path to a long UNC path - - // Translated from the following JS code: - // return `\\\\?\\UNC\\${StringPrototypeSlice(resolvedPath, 2)}`; - bufOffset = 6; - bufSize = len + 6; - // Move all bytes to the right by 6 so that the first two bytes are - // overwritten by "\\\\?\\UNC\\" which is 8 bytes long. - // Use bun.copy because resolvedPath and buf overlap. - bun.copy(T, buf[bufOffset..bufSize], resolvedPath); - // Equiv to std.os.windows.NamespacePrefix.verbatim - // https://github.com/ziglang/zig/blob/dcaf43674e35372e1d28ab12c4c4ff9af9f3d646/lib/std/os/windows.zig#L2358-L2374 - buf[0] = CHAR_BACKWARD_SLASH; - buf[1] = CHAR_BACKWARD_SLASH; - buf[2] = CHAR_QUESTION_MARK; - buf[3] = CHAR_BACKWARD_SLASH; - buf[4] = 'U'; - buf[5] = 'N'; - buf[6] = 'C'; - buf[7] = CHAR_BACKWARD_SLASH; - return MaybeSlice(T){ .result = buf[0..bufSize] }; - } - } - } else if (isWindowsDeviceRootT(T, byte0) and - resolvedPath[1] == CHAR_COLON and - resolvedPath[2] == CHAR_BACKWARD_SLASH) - { - // Matched device root, convert the path to a long UNC path - - // Translated from the following JS code: - // return `\\\\?\\${resolvedPath}` - bufOffset = 4; - bufSize = len + 4; - // Move all bytes to the right by 4 - // Use bun.copy because resolvedPath and buf overlap. - bun.copy(T, buf[bufOffset..bufSize], resolvedPath); - // Equiv to std.os.windows.NamespacePrefix.verbatim - // https://github.com/ziglang/zig/blob/dcaf43674e35372e1d28ab12c4c4ff9af9f3d646/lib/std/os/windows.zig#L2358-L2374 - buf[0] = CHAR_BACKWARD_SLASH; - buf[1] = CHAR_BACKWARD_SLASH; - buf[2] = CHAR_QUESTION_MARK; - buf[3] = CHAR_BACKWARD_SLASH; - return MaybeSlice(T){ .result = buf[0..bufSize] }; - } - return MaybeSlice(T){ .result = resolvedPath }; - } - - pub inline fn toNamespacedPathWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T, buf: []T, buf2: []T) JSC.JSValue { - return switch (toNamespacedPathWindowsT(T, path, buf, buf2)) { - .result => |r| toJSString(globalObject, r), - .err => |e| e.toJSC(globalObject), - }; - } - - pub fn toNamespacedPathJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, path: []const T) JSC.JSValue { - if (!isWindows or path.len == 0) return toJSString(globalObject, path); - const bufLen = @max(path.len, PATH_SIZE(T)); - const buf = allocator.alloc(T, bufLen) catch bun.outOfMemory(); - defer allocator.free(buf); - const buf2 = allocator.alloc(T, bufLen) catch bun.outOfMemory(); - defer allocator.free(buf2); - return toNamespacedPathWindowsJS_T(T, globalObject, path, buf, buf2); - } - - pub fn toNamespacedPath(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue { - if (comptime is_bindgen) return JSC.JSValue.jsUndefined(); - if (args_len == 0) return JSC.JSValue.jsUndefined(); - var path_ptr = args_ptr[0]; - - // Based on Node v21.6.1 path.win32.toNamespacedPath and path.posix.toNamespacedPath: - // https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L624 - // https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1269 - // - // Act as an identity function for non-string values and non-Windows platforms. - if (!isWindows or !path_ptr.isString()) return path_ptr; - const pathZStr = path_ptr.getZigString(globalObject); - const len = pathZStr.len; - if (len == 0) return path_ptr; - - var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, JSC.getAllocator(globalObject)); - const allocator = stack_fallback.get(); - - const pathZSlice = pathZStr.toSlice(allocator); - defer pathZSlice.deinit(); - return toNamespacedPathJS_T(u8, globalObject, allocator, isWindows, pathZSlice.slice()); - } - - pub const Export = shim.exportFunctions(.{ - .basename = basename, - .dirname = dirname, - .extname = extname, - .format = format, - .isAbsolute = isAbsolute, - .join = join, - .normalize = normalize, - .parse = parse, - .relative = relative, - .resolve = resolve, - .toNamespacedPath = toNamespacedPath, - }); - - pub const Extern = [_][]const u8{"create"}; - - comptime { - if (!is_bindgen) { - @export(Path.basename, .{ - .name = Export[0].symbol_name, - }); - @export(Path.dirname, .{ - .name = Export[1].symbol_name, - }); - @export(Path.extname, .{ - .name = Export[2].symbol_name, - }); - @export(Path.format, .{ - .name = Export[3].symbol_name, - }); - @export(Path.isAbsolute, .{ - .name = Export[4].symbol_name, - }); - @export(Path.join, .{ - .name = Export[5].symbol_name, - }); - @export(Path.normalize, .{ - .name = Export[6].symbol_name, - }); - @export(Path.parse, .{ - .name = Export[7].symbol_name, - }); - @export(Path.relative, .{ - .name = Export[8].symbol_name, - }); - @export(Path.resolve, .{ - .name = Export[9].symbol_name, - }); - @export(Path.toNamespacedPath, .{ - .name = Export[10].symbol_name, - }); - } - } -}; - pub const Process = struct { pub fn getArgv0(globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { return JSC.ZigString.fromUTF8(bun.argv[0]).toJS(globalObject); @@ -5027,7 +2026,7 @@ pub const Process = struct { pub fn getCwd(globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { var buf: bun.PathBuffer = undefined; return switch (Path.getCwd(&buf)) { - .result => |r| toJSString(globalObject, r), + .result => |r| JSC.ZigString.init(r).withEncoding().toJS(globalObject), .err => |e| e.toJSC(globalObject), }; } @@ -5099,5 +2098,4 @@ pub const Process = struct { comptime { std.testing.refAllDecls(Process); - std.testing.refAllDecls(Path); } diff --git a/src/bun.js/node/util/parse_args.zig b/src/bun.js/node/util/parse_args.zig index ac21dbbc57..78f1bbd9e6 100644 --- a/src/bun.js/node/util/parse_args.zig +++ b/src/bun.js/node/util/parse_args.zig @@ -652,7 +652,7 @@ const ParseArgsState = struct { pub fn parseArgs( globalThis: *JSGlobalObject, callframe: *JSC.CallFrame, -) callconv(.C) JSValue { +) JSValue { JSC.markBinding(@src()); const arguments = callframe.arguments(1).slice(); const config = if (arguments.len > 0) arguments[0] else JSValue.undefined; @@ -665,6 +665,11 @@ pub fn parseArgs( }; } +comptime { + const parseArgsFn = JSC.toJSHostFunction(parseArgs); + @export(parseArgsFn, .{ .name = "Bun__NodeUtil__jsParseArgs" }); +} + pub fn parseArgsImpl(globalThis: *JSGlobalObject, config_obj: JSValue) !JSValue { // // Phase 0: parse the config object diff --git a/src/bun.js/test/expect.zig b/src/bun.js/test/expect.zig index 6ce8d5a0fc..0e1e17621c 100644 --- a/src/bun.js/test/expect.zig +++ b/src/bun.js/test/expect.zig @@ -93,7 +93,27 @@ pub const Expect = struct { not: bool = false, - _: u5 = undefined, // padding + // This was originally padding. + // We don't use all the bits in the u5, so if you need to reuse this elsewhere, you could. + asymmetric_matcher_constructor_type: AsymmetricMatcherConstructorType = .none, + + pub const AsymmetricMatcherConstructorType = enum(u5) { + none = 0, + Symbol = 1, + String = 2, + Object = 3, + Array = 4, + BigInt = 5, + Boolean = 6, + Number = 7, + Promise = 8, + InstanceOf = 9, + + extern fn AsymmetricMatcherConstructorType__fromJS(globalObject: *JSGlobalObject, value: JSValue) u8; + pub fn fromJS(globalObject: *JSGlobalObject, value: JSValue) AsymmetricMatcherConstructorType { + return @enumFromInt(AsymmetricMatcherConstructorType__fromJS(globalObject, value)); + } + }; pub const FlagsCppType = u8; comptime { @@ -146,12 +166,12 @@ pub const Expect = struct { } } - pub fn getNot(this: *Expect, thisValue: JSValue, _: *JSGlobalObject) callconv(.C) JSValue { + pub fn getNot(this: *Expect, thisValue: JSValue, _: *JSGlobalObject) JSValue { this.flags.not = !this.flags.not; return thisValue; } - pub fn getResolves(this: *Expect, thisValue: JSValue, globalThis: *JSGlobalObject) callconv(.C) JSValue { + pub fn getResolves(this: *Expect, thisValue: JSValue, globalThis: *JSGlobalObject) JSValue { this.flags.promise = switch (this.flags.promise) { .resolves, .none => .resolves, .rejects => { @@ -163,7 +183,7 @@ pub const Expect = struct { return thisValue; } - pub fn getRejects(this: *Expect, thisValue: JSValue, globalThis: *JSGlobalObject) callconv(.C) JSValue { + pub fn getRejects(this: *Expect, thisValue: JSValue, globalThis: *JSGlobalObject) JSValue { this.flags.promise = switch (this.flags.promise) { .none, .rejects => .rejects, .resolves => { @@ -247,11 +267,12 @@ pub const Expect = struct { } /// Called by C++ when matching with asymmetric matchers - fn readFlagsAndProcessPromise(instanceValue: JSValue, globalThis: *JSGlobalObject, outFlags: *Expect.Flags.FlagsCppType, value: *JSValue) callconv(.C) bool { + fn readFlagsAndProcessPromise(instanceValue: JSValue, globalThis: *JSGlobalObject, outFlags: *Expect.Flags.FlagsCppType, value: *JSValue, any_constructor_type: *u8) callconv(.C) bool { const flags: Expect.Flags = flags: { if (ExpectCustomAsymmetricMatcher.fromJS(instanceValue)) |instance| { break :flags instance.flags; } else if (ExpectAny.fromJS(instanceValue)) |instance| { + any_constructor_type.* = @intFromEnum(instance.flags.asymmetric_matcher_constructor_type); break :flags instance.flags; } else if (ExpectAnything.fromJS(instanceValue)) |instance| { break :flags instance.flags; @@ -332,9 +353,9 @@ pub const Expect = struct { VirtualMachine.get().allocator.destroy(this); } - pub fn call(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn call(globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { const arguments = callframe.arguments(2).slice(); - const value = if (arguments.len < 1) JSC.JSValue.jsUndefined() else arguments[0]; + const value = if (arguments.len < 1) JSValue.jsUndefined() else arguments[0]; var custom_label = bun.String.empty; if (arguments.len > 1) { @@ -373,7 +394,7 @@ pub const Expect = struct { return expect_js_value; } - pub fn throw(this: *Expect, globalThis: *JSC.JSGlobalObject, comptime signature: string, comptime fmt: string, args: anytype) void { + pub fn throw(this: *Expect, globalThis: *JSGlobalObject, comptime signature: string, comptime fmt: string, args: anytype) void { if (this.custom_label.isEmpty()) { globalThis.throwPretty(comptime signature ++ fmt, args); } else { @@ -382,9 +403,9 @@ pub const Expect = struct { } pub fn constructor( - globalThis: *JSC.JSGlobalObject, - _: *JSC.CallFrame, - ) callconv(.C) ?*Expect { + globalThis: *JSGlobalObject, + _: *CallFrame, + ) ?*Expect { globalThis.throw("expect() cannot be called with new", .{}); return null; } @@ -392,9 +413,9 @@ pub const Expect = struct { // pass here has a leading underscore to avoid name collision with the pass variable in other functions pub fn _pass( this: *Expect, - globalThis: *JSC.JSGlobalObject, - callFrame: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + globalThis: *JSGlobalObject, + callFrame: *CallFrame, + ) JSValue { defer this.postMatch(globalThis); const arguments_ = callFrame.arguments(1); @@ -439,9 +460,9 @@ pub const Expect = struct { pub fn fail( this: *Expect, - globalThis: *JSC.JSGlobalObject, - callFrame: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + globalThis: *JSGlobalObject, + callFrame: *CallFrame, + ) JSValue { defer this.postMatch(globalThis); const arguments_ = callFrame.arguments(1); @@ -482,9 +503,9 @@ pub const Expect = struct { /// Object.is() pub fn toBe( this: *Expect, - globalThis: *JSC.JSGlobalObject, - callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + globalThis: *JSGlobalObject, + callframe: *CallFrame, + ) JSValue { defer this.postMatch(globalThis); const thisValue = callframe.this(); const arguments_ = callframe.arguments(2); @@ -549,9 +570,9 @@ pub const Expect = struct { pub fn toHaveLength( this: *Expect, - globalThis: *JSC.JSGlobalObject, - callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + globalThis: *JSGlobalObject, + callframe: *CallFrame, + ) JSValue { defer this.postMatch(globalThis); const thisValue = callframe.this(); const arguments_ = callframe.arguments(1); @@ -624,9 +645,9 @@ pub const Expect = struct { pub fn toBeOneOf( this: *Expect, - globalThis: *JSC.JSGlobalObject, - callFrame: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + globalThis: *JSGlobalObject, + callFrame: *CallFrame, + ) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); const arguments_ = callFrame.arguments(1); @@ -646,7 +667,7 @@ pub const Expect = struct { var pass = false; const ExpectedEntry = struct { - globalThis: *JSC.JSGlobalObject, + globalThis: *JSGlobalObject, expected: JSValue, pass: *bool, }; @@ -710,9 +731,9 @@ pub const Expect = struct { pub fn toContain( this: *Expect, - globalThis: *JSC.JSGlobalObject, - callFrame: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + globalThis: *JSGlobalObject, + callFrame: *CallFrame, + ) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); const arguments_ = callFrame.arguments(1); @@ -733,7 +754,7 @@ pub const Expect = struct { var pass = false; const ExpectedEntry = struct { - globalThis: *JSC.JSGlobalObject, + globalThis: *JSGlobalObject, expected: JSValue, pass: *bool, }; @@ -808,9 +829,9 @@ pub const Expect = struct { pub fn toContainKey( this: *Expect, - globalThis: *JSC.JSGlobalObject, - callFrame: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + globalThis: *JSGlobalObject, + callFrame: *CallFrame, + ) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); const arguments_ = callFrame.arguments(1); @@ -868,9 +889,9 @@ pub const Expect = struct { pub fn toContainKeys( this: *Expect, - globalThis: *JSC.JSGlobalObject, - callFrame: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + globalThis: *JSGlobalObject, + callFrame: *CallFrame, + ) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); const arguments_ = callFrame.arguments(1); @@ -941,9 +962,9 @@ pub const Expect = struct { pub fn toContainAllKeys( this: *Expect, - globalObject: *JSC.JSGlobalObject, - callFrame: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + globalObject: *JSGlobalObject, + callFrame: *CallFrame, + ) JSValue { defer this.postMatch(globalObject); const thisValue = callFrame.this(); const arguments_ = callFrame.arguments(1); @@ -1009,9 +1030,9 @@ pub const Expect = struct { pub fn toContainAnyKeys( this: *Expect, - globalThis: *JSC.JSGlobalObject, - callFrame: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + globalThis: *JSGlobalObject, + callFrame: *CallFrame, + ) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); const arguments_ = callFrame.arguments(1); @@ -1077,9 +1098,9 @@ pub const Expect = struct { pub fn toContainValue( this: *Expect, - globalObject: *JSC.JSGlobalObject, - callFrame: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + globalObject: *JSGlobalObject, + callFrame: *CallFrame, + ) JSValue { defer this.postMatch(globalObject); const thisValue = callFrame.this(); const arguments_ = callFrame.arguments(1); @@ -1134,9 +1155,9 @@ pub const Expect = struct { pub fn toContainValues( this: *Expect, - globalObject: *JSC.JSGlobalObject, - callFrame: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + globalObject: *JSGlobalObject, + callFrame: *CallFrame, + ) JSValue { defer this.postMatch(globalObject); const thisValue = callFrame.this(); const arguments_ = callFrame.arguments(1); @@ -1201,9 +1222,9 @@ pub const Expect = struct { pub fn toContainAllValues( this: *Expect, - globalObject: *JSC.JSGlobalObject, - callFrame: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + globalObject: *JSGlobalObject, + callFrame: *CallFrame, + ) JSValue { defer this.postMatch(globalObject); const thisValue = callFrame.this(); const arguments_ = callFrame.arguments(1); @@ -1274,9 +1295,9 @@ pub const Expect = struct { pub fn toContainAnyValues( this: *Expect, - globalObject: *JSC.JSGlobalObject, - callFrame: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + globalObject: *JSGlobalObject, + callFrame: *CallFrame, + ) JSValue { defer this.postMatch(globalObject); const thisValue = callFrame.this(); const arguments_ = callFrame.arguments(1); @@ -1341,9 +1362,9 @@ pub const Expect = struct { pub fn toContainEqual( this: *Expect, - globalThis: *JSC.JSGlobalObject, - callFrame: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + globalThis: *JSGlobalObject, + callFrame: *CallFrame, + ) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); const arguments_ = callFrame.arguments(1); @@ -1364,7 +1385,7 @@ pub const Expect = struct { var pass = false; const ExpectedEntry = struct { - globalThis: *JSC.JSGlobalObject, + globalThis: *JSGlobalObject, expected: JSValue, pass: *bool, }; @@ -1445,7 +1466,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeTruthy(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn toBeTruthy(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); const value: JSValue = this.getValue(globalThis, thisValue, "toBeTruthy", "") orelse return .zero; @@ -1477,7 +1498,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeUndefined(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn toBeUndefined(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); const value: JSValue = this.getValue(globalThis, thisValue, "toBeUndefined", "") orelse return .zero; @@ -1507,7 +1528,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeNaN(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn toBeNaN(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -1541,7 +1562,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeNull(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn toBeNull(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -1570,7 +1591,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeDefined(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn toBeDefined(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -1599,7 +1620,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeFalsy(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn toBeFalsy(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -1633,7 +1654,7 @@ pub const Expect = struct { return .zero; } - pub fn toEqual(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn toEqual(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -1675,7 +1696,7 @@ pub const Expect = struct { return .zero; } - pub fn toStrictEqual(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn toStrictEqual(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -1712,7 +1733,7 @@ pub const Expect = struct { return .zero; } - pub fn toHaveProperty(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn toHaveProperty(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -1807,7 +1828,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeEven(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn toBeEven(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -1861,7 +1882,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeGreaterThan(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn toBeGreaterThan(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -1924,7 +1945,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeGreaterThanOrEqual(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn toBeGreaterThanOrEqual(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -1987,7 +2008,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeLessThan(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn toBeLessThan(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -2050,7 +2071,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeLessThanOrEqual(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn toBeLessThanOrEqual(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -2113,7 +2134,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeCloseTo(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn toBeCloseTo(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -2196,7 +2217,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeOdd(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn toBeOdd(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -2248,7 +2269,7 @@ pub const Expect = struct { return .zero; } - pub fn toThrow(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn toThrow(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -2425,7 +2446,7 @@ pub const Expect = struct { const _received_message: ?JSValue = if (result.isObject()) result.get(globalThis, "message") else if (result.toStringOrNull(globalThis)) |js_str| - JSC.JSValue.fromCell(js_str) + JSValue.fromCell(js_str) else null; @@ -2585,7 +2606,7 @@ pub const Expect = struct { return .zero; } - pub fn toMatchSnapshot(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn toMatchSnapshot(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); const _arguments = callFrame.arguments(2); @@ -2700,7 +2721,7 @@ pub const Expect = struct { return .undefined; } - pub fn toBeEmpty(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn toBeEmpty(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -2778,7 +2799,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeEmptyObject(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toBeEmptyObject(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -2806,7 +2827,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeNil(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toBeNil(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -2833,7 +2854,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeArray(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toBeArray(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -2860,7 +2881,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeArrayOfSize(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toBeArrayOfSize(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -2904,7 +2925,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeBoolean(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toBeBoolean(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -2931,7 +2952,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeTypeOf(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toBeTypeOf(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3008,7 +3029,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeTrue(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toBeTrue(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3035,7 +3056,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeFalse(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toBeFalse(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3062,7 +3083,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeNumber(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toBeNumber(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3089,7 +3110,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeInteger(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toBeInteger(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3116,7 +3137,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeObject(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toBeObject(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3143,7 +3164,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeFinite(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toBeFinite(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3176,7 +3197,7 @@ pub const Expect = struct { return .zero; } - pub fn toBePositive(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toBePositive(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3209,7 +3230,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeNegative(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toBeNegative(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3242,7 +3263,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeWithin(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toBeWithin(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3305,7 +3326,7 @@ pub const Expect = struct { return .zero; } - pub fn toEqualIgnoringWhitespace(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toEqualIgnoringWhitespace(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3387,7 +3408,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeSymbol(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toBeSymbol(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3414,7 +3435,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeFunction(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toBeFunction(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3441,7 +3462,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeDate(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toBeDate(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3468,7 +3489,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeValidDate(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toBeValidDate(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3496,7 +3517,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeString(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toBeString(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3523,7 +3544,7 @@ pub const Expect = struct { return .zero; } - pub fn toInclude(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toInclude(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3580,7 +3601,7 @@ pub const Expect = struct { return .zero; } - pub fn toIncludeRepeated(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toIncludeRepeated(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3691,7 +3712,7 @@ pub const Expect = struct { return .zero; } - pub fn toSatisfy(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toSatisfy(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3755,7 +3776,7 @@ pub const Expect = struct { return .zero; } - pub fn toStartWith(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toStartWith(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3812,7 +3833,7 @@ pub const Expect = struct { return .zero; } - pub fn toEndWith(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + pub fn toEndWith(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3869,7 +3890,7 @@ pub const Expect = struct { return .zero; } - pub fn toBeInstanceOf(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn toBeInstanceOf(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer this.postMatch(globalThis); const thisValue = callFrame.this(); @@ -3916,7 +3937,7 @@ pub const Expect = struct { return .zero; } - pub fn toMatch(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn toMatch(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { JSC.markBinding(@src()); defer this.postMatch(globalThis); @@ -3980,7 +4001,7 @@ pub const Expect = struct { return .zero; } - pub fn toHaveBeenCalled(this: *Expect, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn toHaveBeenCalled(this: *Expect, globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { JSC.markBinding(@src()); const thisValue = callframe.this(); defer this.postMatch(globalThis); @@ -4013,7 +4034,7 @@ pub const Expect = struct { return .zero; } - pub fn toHaveBeenCalledTimes(this: *Expect, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn toHaveBeenCalledTimes(this: *Expect, globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { JSC.markBinding(@src()); const thisValue = callframe.this(); @@ -4056,7 +4077,7 @@ pub const Expect = struct { return .zero; } - pub fn toMatchObject(this: *Expect, globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn toMatchObject(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { JSC.markBinding(@src()); defer this.postMatch(globalThis); @@ -4120,7 +4141,7 @@ pub const Expect = struct { return .zero; } - pub fn toHaveBeenCalledWith(this: *Expect, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn toHaveBeenCalledWith(this: *Expect, globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { JSC.markBinding(@src()); const thisValue = callframe.this(); @@ -4183,7 +4204,7 @@ pub const Expect = struct { return .zero; } - pub fn toHaveBeenLastCalledWith(this: *Expect, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn toHaveBeenLastCalledWith(this: *Expect, globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { JSC.markBinding(@src()); const thisValue = callframe.this(); @@ -4245,7 +4266,7 @@ pub const Expect = struct { return .zero; } - pub fn toHaveBeenNthCalledWith(this: *Expect, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn toHaveBeenNthCalledWith(this: *Expect, globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { JSC.markBinding(@src()); const thisValue = callframe.this(); @@ -4321,7 +4342,7 @@ pub const Expect = struct { pub const Map = bun.ComptimeEnumMap(ReturnStatus); }; - inline fn toHaveReturnedTimesFn(this: *Expect, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, comptime known_index: ?i32) JSC.JSValue { + inline fn toHaveReturnedTimesFn(this: *Expect, globalThis: *JSGlobalObject, callframe: *CallFrame, comptime known_index: ?i32) JSValue { JSC.markBinding(@src()); const thisValue = callframe.this(); @@ -4408,11 +4429,11 @@ pub const Expect = struct { } } - pub fn toHaveReturned(this: *Expect, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn toHaveReturned(this: *Expect, globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { return toHaveReturnedTimesFn(this, globalThis, callframe, 1); } - pub fn toHaveReturnedTimes(this: *Expect, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn toHaveReturnedTimes(this: *Expect, globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { return toHaveReturnedTimesFn(this, globalThis, callframe, null); } @@ -4423,48 +4444,48 @@ pub const Expect = struct { pub const toThrowErrorMatchingSnapshot = notImplementedJSCFn; pub const toThrowErrorMatchingInlineSnapshot = notImplementedJSCFn; - pub fn getStaticNot(globalThis: *JSGlobalObject, _: JSValue, _: JSValue) callconv(.C) JSValue { + pub fn getStaticNot(globalThis: *JSGlobalObject, _: JSValue, _: JSValue) JSValue { return ExpectStatic.create(globalThis, .{ .not = true }); } - pub fn getStaticResolvesTo(globalThis: *JSGlobalObject, _: JSValue, _: JSValue) callconv(.C) JSValue { + pub fn getStaticResolvesTo(globalThis: *JSGlobalObject, _: JSValue, _: JSValue) JSValue { return ExpectStatic.create(globalThis, .{ .promise = .resolves }); } - pub fn getStaticRejectsTo(globalThis: *JSGlobalObject, _: JSValue, _: JSValue) callconv(.C) JSValue { + pub fn getStaticRejectsTo(globalThis: *JSGlobalObject, _: JSValue, _: JSValue) JSValue { return ExpectStatic.create(globalThis, .{ .promise = .rejects }); } - pub fn any(globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn any(globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { return ExpectAny.call(globalThis, callFrame); } - pub fn anything(globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn anything(globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { return ExpectAnything.call(globalThis, callFrame); } - pub fn closeTo(globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn closeTo(globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { return ExpectCloseTo.call(globalThis, callFrame); } - pub fn objectContaining(globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn objectContaining(globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { return ExpectObjectContaining.call(globalThis, callFrame); } - pub fn stringContaining(globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn stringContaining(globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { return ExpectStringContaining.call(globalThis, callFrame); } - pub fn stringMatching(globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn stringMatching(globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { return ExpectStringMatching.call(globalThis, callFrame); } - pub fn arrayContaining(globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn arrayContaining(globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { return ExpectArrayContaining.call(globalThis, callFrame); } /// Implements `expect.extend({ ... })` - pub fn extend(globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn extend(globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { const args = callFrame.arguments(1).slice(); if (args.len == 0 or !args[0].isObject()) { @@ -4497,7 +4518,7 @@ pub const Expect = struct { // Even though they point to the same native functions for all matchers, // multiple instances are created because each instance will hold the matcher_fn as a property - const wrapper_fn = Bun__JSWrappingFunction__create(globalThis, matcher_name, &Expect.applyCustomMatcher, matcher_fn, true); + const wrapper_fn = Bun__JSWrappingFunction__create(globalThis, matcher_name, Expect.applyCustomMatcher, matcher_fn, true); expect_proto.put(globalThis, matcher_name, wrapper_fn); expect_constructor.put(globalThis, matcher_name, wrapper_fn); @@ -4512,7 +4533,7 @@ pub const Expect = struct { const CustomMatcherParamsFormatter = struct { colors: bool, - globalThis: *JSC.JSGlobalObject, + globalThis: *JSGlobalObject, matcher_fn: JSValue, pub fn format(this: CustomMatcherParamsFormatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { @@ -4557,7 +4578,7 @@ pub const Expect = struct { } }; - fn throwInvalidMatcherError(globalThis: *JSC.JSGlobalObject, matcher_name: bun.String, result: JSValue) void { + fn throwInvalidMatcherError(globalThis: *JSGlobalObject, matcher_name: bun.String, result: JSValue) void { @setCold(true); var formatter = JSC.ConsoleObject.Formatter{ @@ -4580,7 +4601,7 @@ pub const Expect = struct { /// Execute the custom matcher for the given args (the left value + the args passed to the matcher call). /// This function is called both for symmetric and asymmetric matching. /// If silent=false, throws an exception in JS if the matcher result didn't result in a pass (or if the matcher result is invalid). - pub fn executeCustomMatcher(globalThis: *JSC.JSGlobalObject, matcher_name: bun.String, matcher_fn: JSValue, args: []const JSValue, flags: Expect.Flags, silent: bool) bool { + pub fn executeCustomMatcher(globalThis: *JSGlobalObject, matcher_name: bun.String, matcher_fn: JSValue, args: []const JSValue, flags: Expect.Flags, silent: bool) bool { // prepare the this object const matcher_context = globalThis.bunVM().allocator.create(ExpectMatcherContext) catch { globalThis.throwOutOfMemory(); @@ -4695,7 +4716,7 @@ pub const Expect = struct { /// Function that is run for either `expect.myMatcher()` call or `expect().myMatcher` call, /// and we can known which case it is based on if the `callFrame.this()` value is an instance of Expect - pub fn applyCustomMatcher(globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn applyCustomMatcher(globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(JSC.conv) JSValue { defer globalThis.bunVM().autoGarbageCollect(); // retrieve the user-provided matcher function (matcher_fn) @@ -4757,7 +4778,7 @@ pub const Expect = struct { pub const addSnapshotSerializer = notImplementedStaticFn; - pub fn hasAssertions(globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn hasAssertions(globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { _ = callFrame; defer globalThis.bunVM().autoGarbageCollect(); @@ -4766,7 +4787,7 @@ pub const Expect = struct { return .undefined; } - pub fn assertions(globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn assertions(globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { defer globalThis.bunVM().autoGarbageCollect(); const arguments_ = callFrame.arguments(1); @@ -4800,32 +4821,32 @@ pub const Expect = struct { return .undefined; } - pub fn notImplementedJSCFn(_: *Expect, globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn notImplementedJSCFn(_: *Expect, globalThis: *JSGlobalObject, _: *CallFrame) JSValue { globalThis.throw("Not implemented", .{}); return .zero; } - pub fn notImplementedStaticFn(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn notImplementedStaticFn(globalThis: *JSGlobalObject, _: *CallFrame) JSValue { globalThis.throw("Not implemented", .{}); return .zero; } - pub fn notImplementedJSCProp(_: *Expect, _: JSC.JSValue, globalThis: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn notImplementedJSCProp(_: *Expect, _: JSValue, globalThis: *JSGlobalObject) JSValue { globalThis.throw("Not implemented", .{}); return .zero; } - pub fn notImplementedStaticProp(globalThis: *JSC.JSGlobalObject, _: JSC.JSValue, _: JSC.JSValue) callconv(.C) JSC.JSValue { + pub fn notImplementedStaticProp(globalThis: *JSGlobalObject, _: JSValue, _: JSValue) JSValue { globalThis.throw("Not implemented", .{}); return .zero; } - pub fn postMatch(_: *Expect, globalThis: *JSC.JSGlobalObject) void { + pub fn postMatch(_: *Expect, globalThis: *JSGlobalObject) void { var vm = globalThis.bunVM(); vm.autoGarbageCollect(); } - pub fn doUnreachable(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn doUnreachable(globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { const arg = callframe.arguments(1).ptr[0]; if (arg.isEmptyOrUndefinedOrNull()) { @@ -4860,7 +4881,7 @@ pub const ExpectStatic = struct { VirtualMachine.get().allocator.destroy(this); } - pub fn create(globalThis: *JSC.JSGlobalObject, flags: Expect.Flags) JSValue { + pub fn create(globalThis: *JSGlobalObject, flags: Expect.Flags) JSValue { var expect = globalThis.bunVM().allocator.create(ExpectStatic) catch { globalThis.throwOutOfMemory(); return .zero; @@ -4872,20 +4893,20 @@ pub const ExpectStatic = struct { return value; } - pub fn getNot(this: *ExpectStatic, _: JSValue, globalThis: *JSGlobalObject) callconv(.C) JSValue { + pub fn getNot(this: *ExpectStatic, _: JSValue, globalThis: *JSGlobalObject) JSValue { var flags = this.flags; flags.not = !this.flags.not; return create(globalThis, flags); } - pub fn getResolvesTo(this: *ExpectStatic, _: JSValue, globalThis: *JSGlobalObject) callconv(.C) JSValue { + pub fn getResolvesTo(this: *ExpectStatic, _: JSValue, globalThis: *JSGlobalObject) JSValue { var flags = this.flags; if (flags.promise != .none) return asyncChainingError(globalThis, flags, "resolvesTo"); flags.promise = .resolves; return create(globalThis, flags); } - pub fn getRejectsTo(this: *ExpectStatic, _: JSValue, globalThis: *JSGlobalObject) callconv(.C) JSValue { + pub fn getRejectsTo(this: *ExpectStatic, _: JSValue, globalThis: *JSGlobalObject) JSValue { var flags = this.flags; if (flags.promise != .none) return asyncChainingError(globalThis, flags, "rejectsTo"); flags.promise = .rejects; @@ -4903,7 +4924,7 @@ pub const ExpectStatic = struct { return .zero; } - fn createAsymmetricMatcherWithFlags(T: anytype, this: *ExpectStatic, globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) JSValue { + fn createAsymmetricMatcherWithFlags(T: anytype, this: *ExpectStatic, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { //const this: *ExpectStatic = ExpectStatic.fromJS(callFrame.this()); const instance_jsvalue = T.call(globalThis, callFrame); if (!instance_jsvalue.isEmpty() and !instance_jsvalue.isAnyError()) { @@ -4916,31 +4937,31 @@ pub const ExpectStatic = struct { return instance_jsvalue; } - pub fn anything(this: *ExpectStatic, globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn anything(this: *ExpectStatic, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { return createAsymmetricMatcherWithFlags(ExpectAnything, this, globalThis, callFrame); } - pub fn any(this: *ExpectStatic, globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn any(this: *ExpectStatic, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { return createAsymmetricMatcherWithFlags(ExpectAny, this, globalThis, callFrame); } - pub fn arrayContaining(this: *ExpectStatic, globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn arrayContaining(this: *ExpectStatic, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { return createAsymmetricMatcherWithFlags(ExpectArrayContaining, this, globalThis, callFrame); } - pub fn closeTo(this: *ExpectStatic, globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn closeTo(this: *ExpectStatic, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { return createAsymmetricMatcherWithFlags(ExpectCloseTo, this, globalThis, callFrame); } - pub fn objectContaining(this: *ExpectStatic, globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn objectContaining(this: *ExpectStatic, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { return createAsymmetricMatcherWithFlags(ExpectObjectContaining, this, globalThis, callFrame); } - pub fn stringContaining(this: *ExpectStatic, globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn stringContaining(this: *ExpectStatic, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { return createAsymmetricMatcherWithFlags(ExpectStringContaining, this, globalThis, callFrame); } - pub fn stringMatching(this: *ExpectStatic, globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn stringMatching(this: *ExpectStatic, globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { return createAsymmetricMatcherWithFlags(ExpectStringMatching, this, globalThis, callFrame); } }; @@ -4956,7 +4977,7 @@ pub const ExpectAnything = struct { VirtualMachine.get().allocator.destroy(this); } - pub fn call(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSValue { + pub fn call(globalThis: *JSGlobalObject, _: *CallFrame) JSValue { const anything = globalThis.bunVM().allocator.create(ExpectAnything) catch { globalThis.throwOutOfMemory(); return .zero; @@ -4984,7 +5005,7 @@ pub const ExpectStringMatching = struct { VirtualMachine.get().allocator.destroy(this); } - pub fn call(globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn call(globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { const args = callFrame.arguments(1).slice(); if (args.len == 0 or (!args[0].isString() and !args[0].isRegExp())) { @@ -5021,7 +5042,7 @@ pub const ExpectCloseTo = struct { VirtualMachine.get().allocator.destroy(this); } - pub fn call(globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn call(globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { const args = callFrame.arguments(2).slice(); if (args.len == 0 or !args[0].isNumber()) { @@ -5068,7 +5089,7 @@ pub const ExpectObjectContaining = struct { VirtualMachine.get().allocator.destroy(this); } - pub fn call(globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn call(globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { const args = callFrame.arguments(1).slice(); if (args.len == 0 or !args[0].isObject()) { @@ -5105,7 +5126,7 @@ pub const ExpectStringContaining = struct { VirtualMachine.get().allocator.destroy(this); } - pub fn call(globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn call(globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { const args = callFrame.arguments(1).slice(); if (args.len == 0 or !args[0].isString()) { @@ -5142,7 +5163,7 @@ pub const ExpectAny = struct { VirtualMachine.get().allocator.destroy(this); } - pub fn call(globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn call(globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { const _arguments = callFrame.arguments(1); const arguments: []const JSValue = _arguments.ptr[0.._arguments.len]; @@ -5159,11 +5180,22 @@ pub const ExpectAny = struct { return .zero; } + const asymmetric_matcher_constructor_type = Expect.Flags.AsymmetricMatcherConstructorType.fromJS(globalThis, constructor); + + // I don't think this case is possible, but just in case! + if (globalThis.hasException()) { + return .zero; + } + var any = globalThis.bunVM().allocator.create(ExpectAny) catch { globalThis.throwOutOfMemory(); return .zero; }; - any.* = .{}; + any.* = .{ + .flags = .{ + .asymmetric_matcher_constructor_type = asymmetric_matcher_constructor_type, + }, + }; const any_js_value = any.toJS(globalThis); any_js_value.ensureStillAlive(); @@ -5188,7 +5220,7 @@ pub const ExpectArrayContaining = struct { VirtualMachine.get().allocator.destroy(this); } - pub fn call(globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn call(globalThis: *JSGlobalObject, callFrame: *CallFrame) JSValue { const args = callFrame.arguments(1).slice(); if (args.len == 0 or !args[0].jsType().isArray()) { @@ -5232,7 +5264,7 @@ pub const ExpectCustomAsymmetricMatcher = struct { /// Implements the static call of the custom matcher (`expect.myCustomMatcher()`), /// which creates an asymmetric matcher instance (`ExpectCustomAsymmetricMatcher`). /// This will not run the matcher, but just capture the args etc. - pub fn create(globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame, matcher_fn: JSValue) callconv(.C) JSValue { + pub fn create(globalThis: *JSGlobalObject, callFrame: *CallFrame, matcher_fn: JSValue) JSValue { var flags: Expect.Flags = undefined; // try to retrieve the ExpectStatic instance (to get the flags) @@ -5274,7 +5306,7 @@ pub const ExpectCustomAsymmetricMatcher = struct { } /// Function called by c++ function "matchAsymmetricMatcher" to execute the custom matcher against the provided leftValue - pub fn execute(this: *ExpectCustomAsymmetricMatcher, thisValue: JSValue, globalThis: *JSC.JSGlobalObject, received: JSValue) callconv(.C) bool { + pub fn execute(this: *ExpectCustomAsymmetricMatcher, thisValue: JSValue, globalThis: *JSGlobalObject, received: JSValue) callconv(.C) bool { // retrieve the user-provided matcher implementation function (the function passed to expect.extend({ ... })) const matcher_fn: JSValue = ExpectCustomAsymmetricMatcher.matcherFnGetCached(thisValue) orelse { globalThis.throw("Internal consistency error: the ExpectCustomAsymmetricMatcher(matcherFn) was garbage collected but it should not have been!", .{}); @@ -5312,15 +5344,15 @@ pub const ExpectCustomAsymmetricMatcher = struct { return Expect.executeCustomMatcher(globalThis, matcher_name, matcher_fn, matcher_args.items, this.flags, true); } - pub fn asymmetricMatch(this: *ExpectCustomAsymmetricMatcher, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn asymmetricMatch(this: *ExpectCustomAsymmetricMatcher, globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { const arguments = callframe.arguments(1).slice(); - const received_value = if (arguments.len < 1) JSC.JSValue.jsUndefined() else arguments[0]; + const received_value = if (arguments.len < 1) JSValue.jsUndefined() else arguments[0]; const matched = execute(this, callframe.this(), globalThis, received_value); return JSValue.jsBoolean(matched); } /// Calls a custom implementation (if provided) to stringify this asymmetric matcher, and returns true if it was provided and it succeed - pub fn customPrint(_: *ExpectCustomAsymmetricMatcher, thisValue: JSValue, globalThis: *JSC.JSGlobalObject, writer: anytype, comptime dontThrow: bool) !bool { + pub fn customPrint(_: *ExpectCustomAsymmetricMatcher, thisValue: JSValue, globalThis: *JSGlobalObject, writer: anytype, comptime dontThrow: bool) !bool { const matcher_fn: JSValue = ExpectCustomAsymmetricMatcher.matcherFnGetCached(thisValue) orelse return false; if (matcher_fn.get(globalThis, "toAsymmetricMatcher")) |fn_value| { if (fn_value.jsType().isFunction()) { @@ -5348,7 +5380,7 @@ pub const ExpectCustomAsymmetricMatcher = struct { return false; } - pub fn toAsymmetricMatcher(this: *ExpectCustomAsymmetricMatcher, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn toAsymmetricMatcher(this: *ExpectCustomAsymmetricMatcher, globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { var stack_fallback = std.heap.stackFallback(512, globalThis.allocator()); var mutable_string = bun.MutableString.init2048(stack_fallback.get()) catch { globalThis.throwOutOfMemory(); @@ -5379,15 +5411,15 @@ pub const ExpectMatcherContext = struct { VirtualMachine.get().allocator.destroy(this); } - pub fn getUtils(_: *ExpectMatcherContext, globalThis: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getUtils(_: *ExpectMatcherContext, globalThis: *JSGlobalObject) JSValue { return ExpectMatcherUtils__getSingleton(globalThis); } - pub fn getIsNot(this: *ExpectMatcherContext, _: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getIsNot(this: *ExpectMatcherContext, _: *JSGlobalObject) JSValue { return JSValue.jsBoolean(this.flags.not); } - pub fn getPromise(this: *ExpectMatcherContext, globalThis: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getPromise(this: *ExpectMatcherContext, globalThis: *JSGlobalObject) JSValue { return switch (this.flags.promise) { .rejects => bun.String.static("rejects").toJS(globalThis), .resolves => bun.String.static("resolves").toJS(globalThis), @@ -5395,13 +5427,13 @@ pub const ExpectMatcherContext = struct { }; } - pub fn getExpand(_: *ExpectMatcherContext, globalThis: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getExpand(_: *ExpectMatcherContext, globalThis: *JSGlobalObject) JSValue { _ = globalThis; // TODO: this should return whether running tests in verbose mode or not (jest flag --expand), but bun currently doesn't have this switch return JSValue.false; } - pub fn equals(_: *ExpectMatcherContext, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn equals(_: *ExpectMatcherContext, globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { var arguments = callframe.arguments(3); if (arguments.len < 2) { globalThis.throw("expect.extends matcher: this.util.equals expects at least 2 arguments", .{}); @@ -5416,7 +5448,7 @@ pub const ExpectMatcherContext = struct { pub const ExpectMatcherUtils = struct { pub usingnamespace JSC.Codegen.JSExpectMatcherUtils; - fn createSingleton(globalThis: *JSC.JSGlobalObject) callconv(.C) JSValue { + fn createSingleton(globalThis: *JSGlobalObject) callconv(.C) JSValue { var instance = globalThis.bunVM().allocator.create(ExpectMatcherUtils) catch { globalThis.throwOutOfMemory(); return .zero; @@ -5430,7 +5462,7 @@ pub const ExpectMatcherUtils = struct { VirtualMachine.get().allocator.destroy(this); } - fn printValue(globalThis: *JSC.JSGlobalObject, value: JSValue, comptime color_or_null: ?[]const u8) !JSValue { + fn printValue(globalThis: *JSGlobalObject, value: JSValue, comptime color_or_null: ?[]const u8) !JSValue { var stack_fallback = std.heap.stackFallback(512, globalThis.allocator()); var mutable_string = try bun.MutableString.init2048(stack_fallback.get()); defer mutable_string.deinit(); @@ -5463,32 +5495,32 @@ pub const ExpectMatcherUtils = struct { return str.toJS(globalThis); } - inline fn printValueCatched(globalThis: *JSC.JSGlobalObject, value: JSValue, comptime color_or_null: ?[]const u8) JSValue { + inline fn printValueCatched(globalThis: *JSGlobalObject, value: JSValue, comptime color_or_null: ?[]const u8) JSValue { return printValue(globalThis, value, color_or_null) catch { globalThis.throwOutOfMemory(); return .zero; }; } - pub fn stringify(_: *ExpectMatcherUtils, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn stringify(_: *ExpectMatcherUtils, globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { const arguments = callframe.arguments(1).slice(); - const value = if (arguments.len < 1) JSC.JSValue.jsUndefined() else arguments[0]; + const value = if (arguments.len < 1) JSValue.jsUndefined() else arguments[0]; return printValueCatched(globalThis, value, null); } - pub fn printExpected(_: *ExpectMatcherUtils, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn printExpected(_: *ExpectMatcherUtils, globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { const arguments = callframe.arguments(1).slice(); - const value = if (arguments.len < 1) JSC.JSValue.jsUndefined() else arguments[0]; + const value = if (arguments.len < 1) JSValue.jsUndefined() else arguments[0]; return printValueCatched(globalThis, value, ""); } - pub fn printReceived(_: *ExpectMatcherUtils, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn printReceived(_: *ExpectMatcherUtils, globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { const arguments = callframe.arguments(1).slice(); - const value = if (arguments.len < 1) JSC.JSValue.jsUndefined() else arguments[0]; + const value = if (arguments.len < 1) JSValue.jsUndefined() else arguments[0]; return printValueCatched(globalThis, value, ""); } - pub fn matcherHint(_: *ExpectMatcherUtils, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn matcherHint(_: *ExpectMatcherUtils, globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { const arguments = callframe.arguments(4).slice(); if (arguments.len == 0 or !arguments[0].isString()) { @@ -5569,13 +5601,13 @@ extern fn JSMockFunction__getCalls(JSValue) JSValue; /// If there were no calls, it returns an empty JSArray* extern fn JSMockFunction__getReturns(JSValue) JSValue; -extern fn Bun__JSWrappingFunction__create(globalThis: *JSC.JSGlobalObject, symbolName: *const bun.String, functionPointer: JSC.JSHostFunctionPtr, wrappedFn: JSValue, strong: bool) JSValue; -extern fn Bun__JSWrappingFunction__getWrappedFunction(this: JSC.JSValue, globalThis: *JSC.JSGlobalObject) JSValue; +extern fn Bun__JSWrappingFunction__create(globalThis: *JSGlobalObject, symbolName: *const bun.String, functionPointer: JSC.JSHostFunctionPtr, wrappedFn: JSValue, strong: bool) JSValue; +extern fn Bun__JSWrappingFunction__getWrappedFunction(this: JSValue, globalThis: *JSGlobalObject) JSValue; -extern fn ExpectMatcherUtils__getSingleton(globalThis: *JSC.JSGlobalObject) JSC.JSValue; +extern fn ExpectMatcherUtils__getSingleton(globalThis: *JSGlobalObject) JSValue; -extern fn Expect__getPrototype(globalThis: *JSC.JSGlobalObject) JSC.JSValue; -extern fn ExpectStatic__getPrototype(globalThis: *JSC.JSGlobalObject) JSC.JSValue; +extern fn Expect__getPrototype(globalThis: *JSGlobalObject) JSValue; +extern fn ExpectStatic__getPrototype(globalThis: *JSGlobalObject) JSValue; comptime { @export(ExpectMatcherUtils.createSingleton, .{ .name = "ExpectMatcherUtils_createSigleton" }); diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig index 50c7d2cbc4..02b3ce1764 100644 --- a/src/bun.js/test/jest.zig +++ b/src/bun.js/test/jest.zig @@ -92,10 +92,10 @@ pub const TestRunner = struct { test_options: *const bun.CLI.Command.TestOptions = undefined, global_callbacks: struct { - beforeAll: std.ArrayListUnmanaged(JSC.JSValue) = .{}, - beforeEach: std.ArrayListUnmanaged(JSC.JSValue) = .{}, - afterEach: std.ArrayListUnmanaged(JSC.JSValue) = .{}, - afterAll: std.ArrayListUnmanaged(JSC.JSValue) = .{}, + beforeAll: std.ArrayListUnmanaged(JSValue) = .{}, + beforeEach: std.ArrayListUnmanaged(JSValue) = .{}, + afterEach: std.ArrayListUnmanaged(JSValue) = .{}, + afterAll: std.ArrayListUnmanaged(JSValue) = .{}, } = .{}, // Used for --test-name-pattern to reduce allocations @@ -274,9 +274,9 @@ pub const Jest = struct { fn globalHook(comptime name: string) JSC.JSHostFunctionType { return struct { pub fn appendGlobalFunctionCallback( - globalThis: *JSC.JSGlobalObject, - callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + globalThis: *JSGlobalObject, + callframe: *CallFrame, + ) callconv(JSC.conv) JSValue { const the_runner = runner orelse { globalThis.throw("Cannot use " ++ name ++ "() outside of the test runner. Run \"bun test\" to run tests.", .{}); return .zero; @@ -304,26 +304,26 @@ pub const Jest = struct { bun.default_allocator, function, ) catch unreachable; - return JSC.JSValue.jsUndefined(); + return JSValue.jsUndefined(); } }.appendGlobalFunctionCallback; } - pub fn Bun__Jest__createTestModuleObject(globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn Bun__Jest__createTestModuleObject(globalObject: *JSGlobalObject) callconv(.C) JSValue { return createTestModule(globalObject, false); } - pub fn Bun__Jest__createTestPreloadObject(globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn Bun__Jest__createTestPreloadObject(globalObject: *JSGlobalObject) callconv(.C) JSValue { return createTestModule(globalObject, true); } - pub fn createTestModule(globalObject: *JSC.JSGlobalObject, comptime outside_of_test: bool) JSC.JSValue { + pub fn createTestModule(globalObject: *JSGlobalObject, comptime outside_of_test: bool) JSValue { const ThisTestScope, const ThisDescribeScope = if (outside_of_test) .{ WrappedTestScope, WrappedDescribeScope } else .{ TestScope, DescribeScope }; - const module = JSC.JSValue.createEmptyObject(globalObject, 14); + const module = JSValue.createEmptyObject(globalObject, 14); const test_fn = JSC.NewFunction(globalObject, ZigString.static("test"), 2, ThisTestScope.call, false); module.put( @@ -419,13 +419,12 @@ pub const Jest = struct { const function = if (outside_of_test) JSC.NewFunction(globalObject, null, 1, globalHook(name), false) else - JSC.NewRuntimeFunction( + JSC.NewFunction( globalObject, ZigString.static(name), 1, @field(DescribeScope, name), false, - false, ); module.put(globalObject, ZigString.static(name), function); function.ensureStillAlive(); @@ -448,7 +447,7 @@ pub const Jest = struct { return module; } - fn createMockObjects(globalObject: *JSGlobalObject, module: JSC.JSValue) void { + fn createMockObjects(globalObject: *JSGlobalObject, module: JSValue) void { const setSystemTime = JSC.NewFunction(globalObject, ZigString.static("setSystemTime"), 0, JSMock__jsSetSystemTime, false); module.put( globalObject, @@ -507,22 +506,22 @@ pub const Jest = struct { module.put(globalObject, ZigString.static("vi"), vi); } - extern fn Bun__Jest__testPreloadObject(*JSC.JSGlobalObject) JSC.JSValue; - extern fn Bun__Jest__testModuleObject(*JSC.JSGlobalObject) JSC.JSValue; - extern fn JSMock__jsMockFn(*JSC.JSGlobalObject, *JSC.CallFrame) JSC.JSValue; - extern fn JSMock__jsModuleMock(*JSC.JSGlobalObject, *JSC.CallFrame) JSC.JSValue; - extern fn JSMock__jsNow(*JSC.JSGlobalObject, *JSC.CallFrame) JSC.JSValue; - extern fn JSMock__jsSetSystemTime(*JSC.JSGlobalObject, *JSC.CallFrame) JSC.JSValue; - extern fn JSMock__jsRestoreAllMocks(*JSC.JSGlobalObject, *JSC.CallFrame) JSC.JSValue; - extern fn JSMock__jsClearAllMocks(*JSC.JSGlobalObject, *JSC.CallFrame) JSC.JSValue; - extern fn JSMock__jsSpyOn(*JSC.JSGlobalObject, *JSC.CallFrame) JSC.JSValue; - extern fn JSMock__jsUseFakeTimers(*JSC.JSGlobalObject, *JSC.CallFrame) JSC.JSValue; - extern fn JSMock__jsUseRealTimers(*JSC.JSGlobalObject, *JSC.CallFrame) JSC.JSValue; + extern fn Bun__Jest__testPreloadObject(*JSGlobalObject) JSValue; + extern fn Bun__Jest__testModuleObject(*JSGlobalObject) JSValue; + extern fn JSMock__jsMockFn(*JSGlobalObject, *CallFrame) callconv(JSC.conv) JSValue; + extern fn JSMock__jsModuleMock(*JSGlobalObject, *CallFrame) callconv(JSC.conv) JSValue; + extern fn JSMock__jsNow(*JSGlobalObject, *CallFrame) callconv(JSC.conv) JSValue; + extern fn JSMock__jsSetSystemTime(*JSGlobalObject, *CallFrame) callconv(JSC.conv) JSValue; + extern fn JSMock__jsRestoreAllMocks(*JSGlobalObject, *CallFrame) callconv(JSC.conv) JSValue; + extern fn JSMock__jsClearAllMocks(*JSGlobalObject, *CallFrame) callconv(JSC.conv) JSValue; + extern fn JSMock__jsSpyOn(*JSGlobalObject, *CallFrame) callconv(JSC.conv) JSValue; + extern fn JSMock__jsUseFakeTimers(*JSGlobalObject, *CallFrame) callconv(JSC.conv) JSValue; + extern fn JSMock__jsUseRealTimers(*JSGlobalObject, *CallFrame) callconv(JSC.conv) JSValue; pub fn call( - globalObject: *JSC.JSGlobalObject, - callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + globalObject: *JSGlobalObject, + callframe: *CallFrame, + ) JSValue { const vm = globalObject.bunVM(); if (vm.is_in_preload or runner == null) { return Bun__Jest__testPreloadObject(globalObject); @@ -550,7 +549,7 @@ pub const Jest = struct { return Bun__Jest__testModuleObject(globalObject); } - fn jsSetDefaultTimeout(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + fn jsSetDefaultTimeout(globalObject: *JSGlobalObject, callframe: *CallFrame) JSValue { const arguments = callframe.arguments(1).slice(); if (arguments.len < 1 or !arguments[0].isNumber()) { globalObject.throw("setTimeout() expects a number (milliseconds)", .{}); @@ -578,8 +577,8 @@ pub const TestScope = struct { label: string = "", parent: *DescribeScope, - func: JSC.JSValue, - func_arg: []JSC.JSValue, + func: JSValue, + func_arg: []JSValue, func_has_callback: bool = false, id: TestRunner.Test.ID = 0, @@ -600,39 +599,39 @@ pub const TestScope = struct { actual: u32 = 0, }; - pub fn call(globalThis: *JSGlobalObject, callframe: *CallFrame) callconv(.C) JSValue { + pub fn call(globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { return createScope(globalThis, callframe, "test()", true, .pass); } - pub fn only(globalThis: *JSGlobalObject, callframe: *CallFrame) callconv(.C) JSValue { + pub fn only(globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { return createScope(globalThis, callframe, "test.only()", true, .only); } - pub fn skip(globalThis: *JSGlobalObject, callframe: *CallFrame) callconv(.C) JSValue { + pub fn skip(globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { return createScope(globalThis, callframe, "test.skip()", true, .skip); } - pub fn todo(globalThis: *JSGlobalObject, callframe: *CallFrame) callconv(.C) JSValue { + pub fn todo(globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { return createScope(globalThis, callframe, "test.todo()", true, .todo); } - pub fn each(globalThis: *JSGlobalObject, callframe: *CallFrame) callconv(.C) JSValue { + pub fn each(globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { return createEach(globalThis, callframe, "test.each()", "each", true); } - pub fn callIf(globalThis: *JSGlobalObject, callframe: *CallFrame) callconv(.C) JSValue { + pub fn callIf(globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { return createIfScope(globalThis, callframe, "test.if()", "if", TestScope, .pass); } - pub fn skipIf(globalThis: *JSGlobalObject, callframe: *CallFrame) callconv(.C) JSValue { + pub fn skipIf(globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { return createIfScope(globalThis, callframe, "test.skipIf()", "skipIf", TestScope, .skip); } - pub fn todoIf(globalThis: *JSGlobalObject, callframe: *CallFrame) callconv(.C) JSValue { + pub fn todoIf(globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { return createIfScope(globalThis, callframe, "test.todoIf()", "todoIf", TestScope, .todo); } - pub fn onReject(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn onReject(globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { debug("onReject", .{}); const arguments = callframe.arguments(2); const err = arguments.ptr[0]; @@ -642,8 +641,9 @@ pub const TestScope = struct { globalThis.bunVM().autoGarbageCollect(); return JSValue.jsUndefined(); } + const jsOnReject = JSC.toJSHostFunction(onReject); - pub fn onResolve(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn onResolve(globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { debug("onResolve", .{}); const arguments = callframe.arguments(2); var task: *TestRunnerTask = arguments.ptr[1].asPromisePtr(TestRunnerTask); @@ -651,11 +651,12 @@ pub const TestScope = struct { globalThis.bunVM().autoGarbageCollect(); return JSValue.jsUndefined(); } + const jsOnResolve = JSC.toJSHostFunction(onResolve); pub fn onDone( - globalThis: *JSC.JSGlobalObject, - callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + globalThis: *JSGlobalObject, + callframe: *CallFrame, + ) JSValue { const function = callframe.callee(); const args = callframe.arguments(1); defer globalThis.bunVM().autoGarbageCollect(); @@ -772,7 +773,7 @@ pub const TestScope = struct { task.promise_state = .pending; switch (promise) { .Normal => |p| { - _ = p.asValue(vm.global).then(vm.global, task, onResolve, onReject); + _ = p.asValue(vm.global).then(vm.global, task, jsOnResolve, jsOnReject); return .{ .pending = {} }; }, else => unreachable, @@ -801,29 +802,23 @@ pub const TestScope = struct { pub const name = "TestScope"; pub const shim = JSC.Shimmer("Bun", name, @This()); - pub const Export = shim.exportFunctions(.{ - .onResolve = onResolve, - .onReject = onReject, - }); comptime { - if (!JSC.is_bindgen) { - @export(onResolve, .{ - .name = Export[0].symbol_name, - }); - @export(onReject, .{ - .name = Export[1].symbol_name, - }); - } + @export(jsOnResolve, .{ + .name = shim.symbolName("onResolve"), + }); + @export(jsOnReject, .{ + .name = shim.symbolName("onReject"), + }); } }; pub const DescribeScope = struct { label: string = "", parent: ?*DescribeScope = null, - beforeAll: std.ArrayListUnmanaged(JSC.JSValue) = .{}, - beforeEach: std.ArrayListUnmanaged(JSC.JSValue) = .{}, - afterEach: std.ArrayListUnmanaged(JSC.JSValue) = .{}, - afterAll: std.ArrayListUnmanaged(JSC.JSValue) = .{}, + beforeAll: std.ArrayListUnmanaged(JSValue) = .{}, + beforeEach: std.ArrayListUnmanaged(JSValue) = .{}, + afterEach: std.ArrayListUnmanaged(JSValue) = .{}, + afterAll: std.ArrayListUnmanaged(JSValue) = .{}, test_id_start: TestRunner.Test.ID = 0, test_id_len: TestRunner.Test.ID = 0, tests: std.ArrayListUnmanaged(TestScope) = .{}, @@ -890,17 +885,14 @@ pub const DescribeScope = struct { pub threadlocal var active: ?*DescribeScope = null; - const CallbackFn = fn ( - *JSC.JSGlobalObject, - *JSC.CallFrame, - ) callconv(.C) JSC.JSValue; + const CallbackFn = JSC.JSHostFunctionType; fn createCallback(comptime hook: LifecycleHook) CallbackFn { return struct { pub fn run( - globalThis: *JSC.JSGlobalObject, - callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + globalThis: *JSGlobalObject, + callframe: *CallFrame, + ) callconv(JSC.conv) JSValue { const arguments = callframe.arguments(2); if (arguments.len < 1) { globalThis.throwNotEnoughArguments("callback", 1, arguments.len); @@ -915,15 +907,15 @@ pub const DescribeScope = struct { cb.protect(); @field(DescribeScope.active.?, @tagName(hook)).append(getAllocator(globalThis), cb) catch unreachable; - return JSC.JSValue.jsBoolean(true); + return JSValue.jsBoolean(true); } }.run; } pub fn onDone( ctx: js.JSContextRef, - callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + callframe: *CallFrame, + ) JSValue { const function = callframe.callee(); const args = callframe.arguments(1); defer ctx.bunVM().autoGarbageCollect(); @@ -948,7 +940,7 @@ pub const DescribeScope = struct { pub const beforeAll = createCallback(.beforeAll); pub const beforeEach = createCallback(.beforeEach); - pub fn execCallback(this: *DescribeScope, globalObject: *JSC.JSGlobalObject, comptime hook: LifecycleHook) ?JSValue { + pub fn execCallback(this: *DescribeScope, globalObject: *JSGlobalObject, comptime hook: LifecycleHook) ?JSValue { var hooks = &@field(this, @tagName(hook)); defer { if (comptime hook == .beforeAll or hook == .afterAll) { @@ -968,7 +960,7 @@ pub const DescribeScope = struct { } const vm = VirtualMachine.get(); - var result: JSC.JSValue = switch (cb.getLength(globalObject)) { + var result: JSValue = switch (cb.getLength(globalObject)) { 0 => callJSFunctionForTestRunner(vm, globalObject, cb, &.{}), else => brk: { this.done = false; @@ -1004,7 +996,7 @@ pub const DescribeScope = struct { return null; } - pub fn runGlobalCallbacks(globalThis: *JSC.JSGlobalObject, comptime hook: LifecycleHook) ?JSValue { + pub fn runGlobalCallbacks(globalThis: *JSGlobalObject, comptime hook: LifecycleHook) ?JSValue { // global callbacks var hooks = &@field(Jest.runner.?.global_callbacks, @tagName(hook)); defer { @@ -1026,7 +1018,7 @@ pub const DescribeScope = struct { const vm = VirtualMachine.get(); // note: we do not support "done" callback in global hooks in the first release. - var result: JSC.JSValue = callJSFunctionForTestRunner(vm, globalThis, cb, &.{}); + var result: JSValue = callJSFunctionForTestRunner(vm, globalThis, cb, &.{}); if (result.asAnyPromise()) |promise| { if (promise.status(globalThis.vm()) == .Pending) { @@ -1044,7 +1036,7 @@ pub const DescribeScope = struct { return null; } - fn runBeforeCallbacks(this: *DescribeScope, globalObject: *JSC.JSGlobalObject, comptime hook: LifecycleHook) ?JSValue { + fn runBeforeCallbacks(this: *DescribeScope, globalObject: *JSGlobalObject, comptime hook: LifecycleHook) ?JSValue { if (this.parent) |scope| { if (scope.runBeforeCallbacks(globalObject, hook)) |err| { return err; @@ -1053,7 +1045,7 @@ pub const DescribeScope = struct { return this.execCallback(globalObject, hook); } - pub fn runCallback(this: *DescribeScope, globalObject: *JSC.JSGlobalObject, comptime hook: LifecycleHook) ?JSValue { + pub fn runCallback(this: *DescribeScope, globalObject: *JSGlobalObject, comptime hook: LifecycleHook) ?JSValue { if (comptime hook == .afterAll or hook == .afterEach) { var parent: ?*DescribeScope = this; while (parent) |scope| { @@ -1077,39 +1069,39 @@ pub const DescribeScope = struct { return null; } - pub fn call(globalThis: *JSGlobalObject, callframe: *CallFrame) callconv(.C) JSValue { + pub fn call(globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { return createScope(globalThis, callframe, "describe()", false, .pass); } - pub fn only(globalThis: *JSGlobalObject, callframe: *CallFrame) callconv(.C) JSValue { + pub fn only(globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { return createScope(globalThis, callframe, "describe.only()", false, .only); } - pub fn skip(globalThis: *JSGlobalObject, callframe: *CallFrame) callconv(.C) JSValue { + pub fn skip(globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { return createScope(globalThis, callframe, "describe.skip()", false, .skip); } - pub fn todo(globalThis: *JSGlobalObject, callframe: *CallFrame) callconv(.C) JSValue { + pub fn todo(globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { return createScope(globalThis, callframe, "describe.todo()", false, .todo); } - pub fn each(globalThis: *JSGlobalObject, callframe: *CallFrame) callconv(.C) JSValue { + pub fn each(globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { return createEach(globalThis, callframe, "describe.each()", "each", false); } - pub fn callIf(globalThis: *JSGlobalObject, callframe: *CallFrame) callconv(.C) JSValue { + pub fn callIf(globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { return createIfScope(globalThis, callframe, "describe.if()", "if", DescribeScope, .pass); } - pub fn skipIf(globalThis: *JSGlobalObject, callframe: *CallFrame) callconv(.C) JSValue { + pub fn skipIf(globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { return createIfScope(globalThis, callframe, "describe.skipIf()", "skipIf", DescribeScope, .skip); } - pub fn todoIf(globalThis: *JSGlobalObject, callframe: *CallFrame) callconv(.C) JSValue { + pub fn todoIf(globalThis: *JSGlobalObject, callframe: *CallFrame) JSValue { return createIfScope(globalThis, callframe, "describe.todoIf()", "todoIf", DescribeScope, .todo); } - pub fn run(this: *DescribeScope, globalObject: *JSC.JSGlobalObject, callback: JSC.JSValue, args: []const JSC.JSValue) JSC.JSValue { + pub fn run(this: *DescribeScope, globalObject: *JSGlobalObject, callback: JSValue, args: []const JSValue) JSValue { if (comptime is_bindgen) return undefined; callback.protect(); defer callback.unprotect(); @@ -1145,7 +1137,7 @@ pub const DescribeScope = struct { return .undefined; } - pub fn runTests(this: *DescribeScope, globalObject: *JSC.JSGlobalObject) void { + pub fn runTests(this: *DescribeScope, globalObject: *JSGlobalObject) void { // Step 1. Initialize the test block globalObject.clearTerminationException(); @@ -1202,7 +1194,7 @@ pub const DescribeScope = struct { } } - pub fn onTestComplete(this: *DescribeScope, globalThis: *JSC.JSGlobalObject, test_id: TestRunner.Test.ID, skipped: bool) void { + pub fn onTestComplete(this: *DescribeScope, globalThis: *JSGlobalObject, test_id: TestRunner.Test.ID, skipped: bool) void { // invalidate it this.current_test_id = std.math.maxInt(TestRunner.Test.ID); if (test_id != std.math.maxInt(TestRunner.Test.ID)) this.pending_tests.unset(test_id); @@ -1249,9 +1241,9 @@ pub const DescribeScope = struct { }; -pub fn wrapTestFunction(comptime name: []const u8, comptime func: DescribeScope.CallbackFn) DescribeScope.CallbackFn { +pub fn wrapTestFunction(comptime name: []const u8, comptime func: anytype) DescribeScope.CallbackFn { return struct { - pub fn wrapped(globalThis: *JSGlobalObject, callframe: *CallFrame) callconv(.C) JSValue { + pub fn wrapped(globalThis: *JSGlobalObject, callframe: *CallFrame) callconv(JSC.conv) JSValue { if (Jest.runner == null) { globalThis.throw("Cannot use " ++ name ++ "() outside of the test runner. Run \"bun test\" to run tests.", .{}); return .zero; @@ -1292,7 +1284,7 @@ pub const WrappedDescribeScope = struct { pub const TestRunnerTask = struct { test_id: TestRunner.Test.ID, describe: *DescribeScope, - globalThis: *JSC.JSGlobalObject, + globalThis: *JSGlobalObject, source_file_path: string = "", needs_before_each: bool = true, ref: JSC.Ref = JSC.Ref.init(), @@ -1309,7 +1301,7 @@ pub const TestRunnerTask = struct { fulfilled, }; - pub fn onUnhandledRejection(jsc_vm: *VirtualMachine, globalObject: *JSC.JSGlobalObject, rejection: JSC.JSValue) void { + pub fn onUnhandledRejection(jsc_vm: *VirtualMachine, globalObject: *JSGlobalObject, rejection: JSValue) void { var deduped = false; const is_unhandled = jsc_vm.onUnhandledRejectionCtx == null; @@ -1518,7 +1510,7 @@ pub const TestRunnerTask = struct { processTestResult(this, this.globalThis, result, test_, test_id, describe); } - fn processTestResult(this: *TestRunnerTask, globalThis: *JSC.JSGlobalObject, result: Result, test_: TestScope, test_id: u32, describe: *DescribeScope) void { + fn processTestResult(this: *TestRunnerTask, globalThis: *JSGlobalObject, result: Result, test_: TestScope, test_id: u32, describe: *DescribeScope) void { switch (result.forceTODO(test_.tag == .todo)) { .pass => |count| Jest.runner.?.reportPass( test_id, @@ -1718,7 +1710,7 @@ inline fn createScope( has_callback = true; arg_size = 1; } - const function_args = allocator.alloc(JSC.JSValue, arg_size) catch unreachable; + const function_args = allocator.alloc(JSValue, arg_size) catch unreachable; parent.tests.append(allocator, TestScope{ .label = label, @@ -1763,25 +1755,26 @@ inline fn createIfScope( const name = ZigString.static(property); const value = args[0].toBooleanSlow(globalThis); - const truthy_falsey: [2]JSC.JSHostFunctionPtr = switch (tag) { - .pass => .{ Scope.call, Scope.skip }, + const truthy_falsey = comptime switch (tag) { + .pass => .{ Scope.skip, Scope.call }, .fail => @compileError("unreachable"), .only => @compileError("unreachable"), - .skip => .{ Scope.skip, Scope.call }, - .todo => .{ Scope.todo, Scope.call }, + .skip => .{ Scope.call, Scope.skip }, + .todo => .{ Scope.call, Scope.todo }, }; - const call = truthy_falsey[if (value) 0 else 1]; - return JSC.NewFunction(globalThis, name, 2, call, false); + switch (@intFromBool(value)) { + inline else => |index| return JSC.NewFunction(globalThis, name, 2, truthy_falsey[index], false), + } } fn consumeArg( - globalThis: *JSC.JSGlobalObject, + globalThis: *JSGlobalObject, should_write: bool, str_idx: *usize, args_idx: *usize, array_list: *std.ArrayListUnmanaged(u8), - arg: *const JSC.JSValue, + arg: *const JSValue, fallback: []const u8, ) !void { const allocator = getAllocator(globalThis); @@ -1797,7 +1790,7 @@ fn consumeArg( } // Generate test label by positionally injecting parameters with printf formatting -fn formatLabel(globalThis: *JSC.JSGlobalObject, label: string, function_args: []JSC.JSValue, test_idx: usize) !string { +fn formatLabel(globalThis: *JSGlobalObject, label: string, function_args: []JSValue, test_idx: usize) !string { const allocator = getAllocator(globalThis); var idx: usize = 0; var args_idx: usize = 0; @@ -1869,7 +1862,7 @@ pub const EachData = struct { strong: JSC.Strong, is_test: bool }; fn eachBind( globalThis: *JSGlobalObject, callframe: *CallFrame, -) callconv(.C) JSValue { +) JSValue { const signature = "eachBind"; const callee = callframe.callee(); const arguments = callframe.arguments(3); @@ -1953,7 +1946,7 @@ fn eachBind( arg_size += 1; } - var function_args = allocator.alloc(JSC.JSValue, arg_size) catch @panic("can't create function_args"); + var function_args = allocator.alloc(JSValue, arg_size) catch @panic("can't create function_args"); var idx: u32 = 0; if (item_is_array) { @@ -2069,7 +2062,7 @@ inline fn createEach( return JSC.NewFunctionWithData(globalThis, name, 3, eachBind, true, each_data); } -fn callJSFunctionForTestRunner(vm: *JSC.VirtualMachine, globalObject: *JSC.JSGlobalObject, function: JSC.JSValue, args: []const JSC.JSValue) JSC.JSValue { +fn callJSFunctionForTestRunner(vm: *JSC.VirtualMachine, globalObject: *JSGlobalObject, function: JSValue, args: []const JSValue) JSValue { vm.eventLoop().enter(); defer { vm.eventLoop().exit(); diff --git a/src/bun.js/webcore.zig b/src/bun.js/webcore.zig index 6e594b9e14..2f4f15f51c 100644 --- a/src/bun.js/webcore.zig +++ b/src/bun.js/webcore.zig @@ -22,7 +22,7 @@ pub const Lifetime = enum { }; /// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-alert -fn alert(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { +fn alert(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(1).slice(); var output = bun.Output.writer(); const has_message = arguments.len != 0; @@ -72,7 +72,7 @@ fn alert(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv( return .undefined; } -fn confirm(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { +fn confirm(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(1).slice(); var output = bun.Output.writer(); const has_message = arguments.len != 0; @@ -210,7 +210,7 @@ pub const Prompt = struct { pub fn call( globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(3).slice(); var state = std.heap.stackFallback(2048, bun.default_allocator); const allocator = state.get(); @@ -565,7 +565,7 @@ pub const Crypto = struct { _: *@This(), globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const arguments = callframe.arguments(2).slice(); if (arguments.len < 2) { @@ -598,7 +598,7 @@ pub const Crypto = struct { globalThis: *JSC.JSGlobalObject, array_a: *JSC.JSUint8Array, array_b: *JSC.JSUint8Array, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const a = array_a.slice(); const b = array_b.slice(); @@ -615,7 +615,7 @@ pub const Crypto = struct { _: *@This(), globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const arguments = callframe.arguments(1).slice(); if (arguments.len == 0) { globalThis.throwInvalidArguments("Expected typed array but got nothing", .{}); @@ -637,7 +637,7 @@ pub const Crypto = struct { _: *@This(), globalThis: *JSC.JSGlobalObject, array: *JSC.JSUint8Array, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const slice = array.slice(); randomData(globalThis, slice.ptr, slice.len); return @as(JSC.JSValue, @enumFromInt(@as(i64, @bitCast(@intFromPtr(array))))); @@ -666,7 +666,7 @@ pub const Crypto = struct { _: *@This(), globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const str, var bytes = bun.String.createUninitialized(.latin1, 36); defer str.deref(); @@ -679,7 +679,7 @@ pub const Crypto = struct { pub fn randomUUIDWithoutTypeChecks( _: *Crypto, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const str, var bytes = bun.String.createUninitialized(.latin1, 36); defer str.deref(); @@ -691,7 +691,7 @@ pub const Crypto = struct { return str.toJS(globalThis); } - pub fn constructor(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) ?*Crypto { + pub fn constructor(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(JSC.conv) ?*Crypto { globalThis.throw("Crypto is not constructable", .{}); return null; } diff --git a/src/bun.js/webcore/ObjectURLRegistry.zig b/src/bun.js/webcore/ObjectURLRegistry.zig index 9eef7476db..6a2807860d 100644 --- a/src/bun.js/webcore/ObjectURLRegistry.zig +++ b/src/bun.js/webcore/ObjectURLRegistry.zig @@ -83,7 +83,7 @@ pub fn has(this: *ObjectURLRegistry, pathname: []const u8) bool { return this.map.contains(uuid); } -export fn Bun__createObjectURL(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { +export fn Bun__createObjectURL(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(1); if (arguments.len < 1) { globalObject.throwNotEnoughArguments("createObjectURL", 1, arguments.len); @@ -99,7 +99,7 @@ export fn Bun__createObjectURL(globalObject: *JSC.JSGlobalObject, callframe: *JS return str.transferToJS(globalObject); } -export fn Bun__revokeObjectURL(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { +export fn Bun__revokeObjectURL(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const arguments = callframe.arguments(1); if (arguments.len < 1) { globalObject.throwNotEnoughArguments("revokeObjectURL", 1, arguments.len); diff --git a/src/bun.js/webcore/blob.zig b/src/bun.js/webcore/blob.zig index a6820ed275..3c95dbe916 100644 --- a/src/bun.js/webcore/blob.zig +++ b/src/bun.js/webcore/blob.zig @@ -310,7 +310,7 @@ pub const Blob = struct { const StructuredCloneWriter = struct { ctx: *anyopaque, - impl: *const fn (*anyopaque, ptr: [*]const u8, len: u32) callconv(.C) void, + impl: *const fn (*anyopaque, ptr: [*]const u8, len: u32) callconv(JSC.conv) void, pub const WriteError = error{}; pub fn write(this: StructuredCloneWriter, bytes: []const u8) WriteError!usize { @@ -352,8 +352,8 @@ pub const Blob = struct { this: *Blob, globalThis: *JSC.JSGlobalObject, ctx: *anyopaque, - writeBytes: *const fn (*anyopaque, ptr: [*]const u8, len: u32) callconv(.C) void, - ) callconv(.C) void { + writeBytes: *const fn (*anyopaque, ptr: [*]const u8, len: u32) callconv(JSC.conv) void, + ) void { _ = globalThis; const Writer = std.io.Writer(StructuredCloneWriter, StructuredCloneWriter.WriteError, StructuredCloneWriter.write); @@ -372,7 +372,7 @@ pub const Blob = struct { globalThis: *JSC.JSGlobalObject, ctx: *anyopaque, write: *const fn (*anyopaque, ptr: [*]const u8, len: usize) callconv(.C) void, - ) callconv(.C) void { + ) void { _ = write; _ = ctx; _ = this; @@ -515,7 +515,7 @@ pub const Blob = struct { globalThis: *JSC.JSGlobalObject, ptr: [*]u8, end: [*]u8, - ) callconv(.C) JSValue { + ) JSValue { const total_length: usize = @intFromPtr(end) - @intFromPtr(ptr); var buffer_stream = std.io.fixedBufferStream(ptr[0..total_length]); const reader = buffer_stream.reader(); @@ -920,7 +920,7 @@ pub const Blob = struct { pub fn writeFile( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const arguments = callframe.arguments(3).slice(); var args = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments); defer args.deinit(); @@ -1377,7 +1377,7 @@ pub const Blob = struct { return JSC.JSPromise.resolvedPromiseValue(globalThis, JSC.JSValue.jsNumber(written)); } - pub export fn JSDOMFile__hasInstance(_: JSC.JSValue, _: *JSC.JSGlobalObject, value: JSC.JSValue) callconv(.C) bool { + pub export fn JSDOMFile__hasInstance(_: JSC.JSValue, _: *JSC.JSGlobalObject, value: JSC.JSValue) callconv(JSC.conv) bool { JSC.markBinding(@src()); const blob = value.as(Blob) orelse return false; return blob.is_jsdom_file; @@ -1386,7 +1386,7 @@ pub const Blob = struct { pub export fn JSDOMFile__construct( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) ?*Blob { + ) callconv(JSC.conv) ?*Blob { JSC.markBinding(@src()); const allocator = bun.default_allocator; var blob: Blob = undefined; @@ -1496,7 +1496,7 @@ pub const Blob = struct { this.reported_estimated_size = size + (this.content_type.len * @intFromBool(this.content_type_allocated)); } - pub fn estimatedSize(this: *Blob) callconv(.C) usize { + pub fn estimatedSize(this: *Blob) usize { return this.reported_estimated_size; } @@ -1510,7 +1510,7 @@ pub const Blob = struct { pub fn constructBunFile( globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { var vm = globalObject.bunVM(); const arguments = callframe.arguments(2).slice(); var args = JSC.Node.ArgumentsSlice.init(vm, arguments); @@ -2843,7 +2843,7 @@ pub const Blob = struct { this: *Blob, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const thisValue = callframe.this(); if (Blob.streamGetCached(thisValue)) |cached| { return cached; @@ -2886,7 +2886,7 @@ pub const Blob = struct { pub fn toStreamWithOffset( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const this = callframe.this().as(Blob) orelse @panic("this is not a Blob"); const args = callframe.arguments(1).slice(); @@ -2908,7 +2908,7 @@ pub const Blob = struct { this: *Blob, globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const store = this.store; if (store) |st| st.ref(); defer if (store) |st| st.deref(); @@ -2929,7 +2929,7 @@ pub const Blob = struct { this: *Blob, globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const store = this.store; if (store) |st| st.ref(); defer if (store) |st| st.deref(); @@ -2952,7 +2952,7 @@ pub const Blob = struct { this: *Blob, globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { const store = this.store; if (store) |st| st.ref(); defer if (store) |st| st.deref(); @@ -2963,7 +2963,7 @@ pub const Blob = struct { this: *Blob, globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { const store = this.store; if (store) |st| st.ref(); defer if (store) |st| st.deref(); @@ -2974,7 +2974,7 @@ pub const Blob = struct { this: *Blob, globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { const store = this.store; if (store) |st| st.ref(); defer if (store) |st| st.deref(); @@ -3006,7 +3006,7 @@ pub const Blob = struct { this: *Blob, globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { return JSC.JSPromise.resolvedPromiseValue(globalThis, this.getExistsSync()); } @@ -3014,7 +3014,7 @@ pub const Blob = struct { this: *Blob, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { var arguments_ = callframe.arguments(1); var arguments = arguments_.ptr[0..arguments_.len]; @@ -3151,7 +3151,7 @@ pub const Blob = struct { this: *Blob, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const allocator = bun.default_allocator; var arguments_ = callframe.arguments(3); var args = arguments_.ptr[0..arguments_.len]; @@ -3278,7 +3278,7 @@ pub const Blob = struct { pub fn getType( this: *Blob, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (this.content_type.len > 0) { if (this.content_type_allocated) { return ZigString.init(this.content_type).toJS(globalThis); @@ -3298,7 +3298,7 @@ pub const Blob = struct { this: *Blob, _: JSC.JSValue, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (this.name.tag != .Dead) return this.name.toJS(globalThis); if (this.getFileName()) |path| { @@ -3315,7 +3315,7 @@ pub const Blob = struct { jsThis: JSC.JSValue, globalThis: *JSC.JSGlobalObject, value: JSValue, - ) callconv(.C) bool { + ) callconv(JSC.conv) bool { // by default we don't have a name so lets allow it to be set undefined if (value.isEmptyOrUndefinedOrNull()) { this.name.deref(); @@ -3356,7 +3356,7 @@ pub const Blob = struct { pub fn getLastModified( this: *Blob, _: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { if (this.store) |store| { if (store.data == .file) { // last_modified can be already set during read. @@ -3403,7 +3403,7 @@ pub const Blob = struct { } } - pub fn getSize(this: *Blob, _: *JSC.JSGlobalObject) callconv(.C) JSValue { + pub fn getSize(this: *Blob, _: *JSC.JSGlobalObject) JSValue { if (this.size == Blob.max_size) { this.resolveSize(); if (this.size == Blob.max_size and this.store != null) { @@ -3490,7 +3490,7 @@ pub const Blob = struct { pub fn constructor( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) ?*Blob { + ) ?*Blob { const allocator = bun.default_allocator; var blob: Blob = undefined; var arguments = callframe.arguments(2); diff --git a/src/bun.js/webcore/body.zig b/src/bun.js/webcore/body.zig index 632bce1609..3d766e14a5 100644 --- a/src/bun.js/webcore/body.zig +++ b/src/bun.js/webcore/body.zig @@ -986,7 +986,7 @@ pub fn BodyMixin(comptime Type: type) type { this: *Type, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { var value: *Body.Value = this.getBodyValue(); if (value.* == .Used) { return handleBodyAlreadyUsed(globalObject); @@ -1007,7 +1007,7 @@ pub fn BodyMixin(comptime Type: type) type { pub fn getBody( this: *Type, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { var body: *Body.Value = this.getBodyValue(); if (body.* == .Used) { @@ -1020,7 +1020,7 @@ pub fn BodyMixin(comptime Type: type) type { pub fn getBodyUsed( this: *Type, globalObject: *JSC.JSGlobalObject, - ) callconv(.C) JSValue { + ) JSValue { return JSValue.jsBoolean( switch (this.getBodyValue().*) { .Used => true, @@ -1040,7 +1040,7 @@ pub fn BodyMixin(comptime Type: type) type { this: *Type, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { var value: *Body.Value = this.getBodyValue(); if (value.* == .Used) { return handleBodyAlreadyUsed(globalObject); @@ -1070,7 +1070,7 @@ pub fn BodyMixin(comptime Type: type) type { this: *Type, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { var value: *Body.Value = this.getBodyValue(); if (value.* == .Used) { @@ -1093,7 +1093,7 @@ pub fn BodyMixin(comptime Type: type) type { this: *Type, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { var value: *Body.Value = this.getBodyValue(); if (value.* == .Used) { @@ -1116,7 +1116,7 @@ pub fn BodyMixin(comptime Type: type) type { this: *Type, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { var value: *Body.Value = this.getBodyValue(); if (value.* == .Used) { @@ -1172,7 +1172,7 @@ pub fn BodyMixin(comptime Type: type) type { this: *Type, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return this.getBlobWithoutCallFrame(globalObject); } @@ -1357,14 +1357,14 @@ pub const BodyValueBufferer = struct { } } - pub fn onResolveStream(_: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn onResolveStream(_: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSValue { var args = callframe.arguments(2); var sink: *@This() = args.ptr[args.len - 1].asPromisePtr(@This()); sink.handleResolveStream(true); return JSValue.jsUndefined(); } - pub fn onRejectStream(_: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn onRejectStream(_: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSValue { const args = callframe.arguments(2); var sink = args.ptr[args.len - 1].asPromisePtr(@This()); const err = args.ptr[0]; diff --git a/src/bun.js/webcore/encoding.zig b/src/bun.js/webcore/encoding.zig index 8ce40b4025..f8f800ff2b 100644 --- a/src/bun.js/webcore/encoding.zig +++ b/src/bun.js/webcore/encoding.zig @@ -413,7 +413,7 @@ pub const TextDecoder = struct { fatal: bool = false, encoding: EncodingLabel = EncodingLabel.@"UTF-8", - pub fn finalize(this: *TextDecoder) callconv(.C) void { + pub fn finalize(this: *TextDecoder) void { bun.default_allocator.destroy(this); } @@ -422,13 +422,13 @@ pub const TextDecoder = struct { pub fn getIgnoreBOM( this: *TextDecoder, _: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return JSC.JSValue.jsBoolean(this.ignore_bom); } // pub fn setIgnoreBOM( // this: *TextDecoder, // _: *JSC.JSGlobalObject, - // ) callconv(.C) JSC.JSValue { + // ) JSC.JSValue { // this.ignore_bom = JSValue.fromRef(this.ignore_bom).toBoolean(); // return true; // } @@ -447,7 +447,7 @@ pub const TextDecoder = struct { pub fn getFatal( this: *TextDecoder, _: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return JSC.JSValue.jsBoolean(this.fatal); } @@ -455,7 +455,7 @@ pub const TextDecoder = struct { pub fn getEncoding( this: *TextDecoder, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return ZigString.init(EncodingLabel.label.get(this.encoding).?).toJS(globalThis); } const Vector16 = std.meta.Vector(16, u16); @@ -585,7 +585,7 @@ pub const TextDecoder = struct { return out.toJS(ctx.ptr()); } - pub fn decode(this: *TextDecoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn decode(this: *TextDecoder, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSValue { const arguments_ = callframe.arguments(2); const arguments = arguments_.ptr[0..arguments_.len]; @@ -613,7 +613,7 @@ pub const TextDecoder = struct { return this.decodeSlice(globalThis, array_buffer.slice(), false); } - pub fn decodeWithoutTypeChecks(this: *TextDecoder, globalThis: *JSC.JSGlobalObject, uint8array: *JSC.JSUint8Array) callconv(.C) JSValue { + pub fn decodeWithoutTypeChecks(this: *TextDecoder, globalThis: *JSC.JSGlobalObject, uint8array: *JSC.JSUint8Array) JSValue { return this.decodeSlice(globalThis, uint8array.slice(), false); } @@ -703,7 +703,7 @@ pub const TextDecoder = struct { pub fn constructor( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) ?*TextDecoder { + ) ?*TextDecoder { var args_ = callframe.arguments(2); var arguments: []const JSC.JSValue = args_.ptr[0..args_.len]; diff --git a/src/bun.js/webcore/request.zig b/src/bun.js/webcore/request.zig index d0f78285ce..ca654a56f8 100644 --- a/src/bun.js/webcore/request.zig +++ b/src/bun.js/webcore/request.zig @@ -232,30 +232,30 @@ pub const Request = struct { pub fn getCache( _: *Request, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return ZigString.init(Properties.UTF8.default).toJS(globalThis); } pub fn getCredentials( _: *Request, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return ZigString.init(Properties.UTF8.include).toJS(globalThis); } pub fn getDestination( _: *Request, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return ZigString.init("").toJS(globalThis); } pub fn getIntegrity( _: *Request, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return ZigString.Empty.toJS(globalThis); } - pub fn getSignal(this: *Request, globalThis: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getSignal(this: *Request, globalThis: *JSC.JSGlobalObject) JSC.JSValue { // Already have an C++ instance if (this.signal) |signal| { return signal.toJS(globalThis); @@ -273,14 +273,14 @@ pub const Request = struct { pub fn getMethod( this: *Request, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return bun.String.static(@tagName(this.method)).toJS(globalThis); } pub fn getMode( _: *Request, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return ZigString.init(Properties.UTF8.navigate).toJS(globalThis); } @@ -308,13 +308,13 @@ pub const Request = struct { pub fn getRedirect( _: *Request, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return ZigString.init(Properties.UTF8.follow).toJS(globalThis); } pub fn getReferrer( this: *Request, globalObject: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { if (this._headers) |headers_ref| { if (headers_ref.get("referrer", globalObject)) |referrer| { return ZigString.init(referrer).toJS(globalObject); @@ -326,13 +326,13 @@ pub const Request = struct { pub fn getReferrerPolicy( _: *Request, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return ZigString.init("").toJS(globalThis); } pub fn getUrl( this: *Request, globalObject: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { this.ensureURL() catch { globalObject.throw("Failed to join URL", .{}); return .zero; @@ -708,7 +708,7 @@ pub const Request = struct { pub fn constructor( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) ?*Request { + ) ?*Request { const arguments_ = callframe.arguments(2); const arguments = arguments_.ptr[0..arguments_.len]; @@ -732,7 +732,7 @@ pub const Request = struct { this: *Request, globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { var cloned = this.clone(getAllocator(globalThis), globalThis); return cloned.toJS(globalThis); } @@ -796,7 +796,7 @@ pub const Request = struct { pub fn getHeaders( this: *Request, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return this.ensureFetchHeaders(globalThis).toJS(globalThis); } diff --git a/src/bun.js/webcore/response.zig b/src/bun.js/webcore/response.zig index 4d71adf921..496737f1c7 100644 --- a/src/bun.js/webcore/response.zig +++ b/src/bun.js/webcore/response.zig @@ -196,7 +196,7 @@ pub const Response = struct { pub fn getURL( this: *Response, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { // https://developer.mozilla.org/en-US/docs/Web/API/Response/url return this.url.toJS(globalThis); } @@ -204,7 +204,7 @@ pub const Response = struct { pub fn getResponseType( this: *Response, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { if (this.init.status_code < 200) { return ZigString.init("error").toJS(globalThis); } @@ -215,7 +215,7 @@ pub const Response = struct { pub fn getStatusText( this: *Response, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { // https://developer.mozilla.org/en-US/docs/Web/API/Response/statusText return this.init.status_text.toJS(globalThis); } @@ -223,7 +223,7 @@ pub const Response = struct { pub fn getRedirected( this: *Response, _: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { // https://developer.mozilla.org/en-US/docs/Web/API/Response/redirected return JSValue.jsBoolean(this.redirected); } @@ -231,7 +231,7 @@ pub const Response = struct { pub fn getOK( this: *Response, _: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { // https://developer.mozilla.org/en-US/docs/Web/API/Response/ok return JSValue.jsBoolean(this.isOK()); } @@ -254,7 +254,7 @@ pub const Response = struct { pub fn getHeaders( this: *Response, globalThis: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { return this.getOrCreateHeaders(globalThis).toJS(globalThis); } @@ -262,7 +262,7 @@ pub const Response = struct { this: *Response, globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { const cloned = this.clone(globalThis); return Response.makeMaybePooled(globalThis, cloned); } @@ -290,7 +290,7 @@ pub const Response = struct { pub fn getStatus( this: *Response, _: *JSC.JSGlobalObject, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { // https://developer.mozilla.org/en-US/docs/Web/API/Response/status return JSValue.jsNumber(this.init.status_code); } @@ -342,7 +342,7 @@ pub const Response = struct { pub fn constructJSON( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { const args_list = callframe.arguments(2); // https://github.com/remix-run/remix/blob/db2c31f64affb2095e4286b91306b96435967969/packages/remix-server-runtime/responses.ts#L4 var args = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), args_list.ptr[0..args_list.len]); @@ -399,7 +399,7 @@ pub const Response = struct { pub fn constructRedirect( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { var args_list = callframe.arguments(4); // https://github.com/remix-run/remix/blob/db2c31f64affb2095e4286b91306b96435967969/packages/remix-server-runtime/responses.ts#L4 var args = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), args_list.ptr[0..args_list.len]); @@ -444,7 +444,7 @@ pub const Response = struct { pub fn constructError( globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { const response = bun.new( Response, Response{ @@ -463,7 +463,7 @@ pub const Response = struct { pub fn constructor( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) ?*Response { + ) ?*Response { const args_list = brk: { var args = callframe.arguments(2); if (args.len > 1 and args.ptr[1].isEmptyOrUndefinedOrNull()) { @@ -1706,7 +1706,7 @@ pub const Fetch = struct { fetch_options: FetchOptions, promise: JSC.JSPromise.Strong, ) !*FetchTasklet { - try http.HTTPThread.init(); + http.HTTPThread.init(); var node = try get( allocator, global, @@ -1839,7 +1839,7 @@ pub const Fetch = struct { pub export fn Bun__fetch( ctx: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) callconv(JSC.conv) JSC.JSValue { JSC.markBinding(@src()); const globalThis = ctx.ptr(); const arguments = callframe.arguments(2); diff --git a/src/bun.js/webcore/streams.zig b/src/bun.js/webcore/streams.zig index 6d0486a5c3..4151d10064 100644 --- a/src/bun.js/webcore/streams.zig +++ b/src/bun.js/webcore/streams.zig @@ -1621,7 +1621,7 @@ pub fn NewJSSink(comptime SinkType: type, comptime name_: []const u8) type { return shim.cppFn("setDestroyCallback", .{ value, callback }); } - pub fn construct(globalThis: *JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSValue { + pub fn construct(globalThis: *JSGlobalObject, _: *JSC.CallFrame) callconv(JSC.conv) JSValue { JSC.markBinding(@src()); if (comptime !@hasDecl(SinkType, "construct")) { @@ -1670,7 +1670,7 @@ pub fn NewJSSink(comptime SinkType: type, comptime name_: []const u8) type { shim.cppFn("detachPtr", .{ptr}); } - fn getThis(globalThis: *JSGlobalObject, callframe: *const JSC.CallFrame) ?*ThisSink { + inline fn getThis(globalThis: *JSGlobalObject, callframe: *const JSC.CallFrame) ?*ThisSink { return @as( *ThisSink, @ptrCast(@alignCast( @@ -1693,7 +1693,7 @@ pub fn NewJSSink(comptime SinkType: type, comptime name_: []const u8) type { } - pub fn write(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn write(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSValue { JSC.markBinding(@src()); var this = getThis(globalThis, callframe) orelse return invalidThis(globalThis); @@ -1762,7 +1762,7 @@ pub fn NewJSSink(comptime SinkType: type, comptime name_: []const u8) type { return this.sink.writeLatin1(.{ .temporary = bun.ByteList.initConst(str.slice()) }).toJS(globalThis); } - pub fn writeUTF8(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn writeUTF8(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSValue { JSC.markBinding(@src()); var this = getThis(globalThis, callframe) orelse return invalidThis(globalThis); @@ -1815,7 +1815,7 @@ pub fn NewJSSink(comptime SinkType: type, comptime name_: []const u8) type { return this.sink.end(null).toJS(globalThis); } - pub fn flush(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn flush(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSValue { JSC.markBinding(@src()); var this = getThis(globalThis, callframe) orelse return invalidThis(globalThis); @@ -1850,7 +1850,7 @@ pub fn NewJSSink(comptime SinkType: type, comptime name_: []const u8) type { return this.sink.flush().toJS(globalThis); } - pub fn start(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn start(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSValue { JSC.markBinding(@src()); var this = getThis(globalThis, callframe) orelse return invalidThis(globalThis); @@ -1883,7 +1883,7 @@ pub fn NewJSSink(comptime SinkType: type, comptime name_: []const u8) type { ).toJS(globalThis); } - pub fn end(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn end(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSValue { JSC.markBinding(@src()); var this = getThis(globalThis, callframe) orelse return invalidThis(globalThis); @@ -1906,7 +1906,7 @@ pub fn NewJSSink(comptime SinkType: type, comptime name_: []const u8) type { return this.sink.endFromJS(globalThis).toJS(globalThis); } - pub fn endWithSink(ptr: *anyopaque, globalThis: *JSGlobalObject) callconv(.C) JSValue { + pub fn endWithSink(ptr: *anyopaque, globalThis: *JSGlobalObject) callconv(JSC.conv) JSValue { JSC.markBinding(@src()); var this = @as(*ThisSink, @ptrCast(@alignCast(ptr))); @@ -1925,18 +1925,6 @@ pub fn NewJSSink(comptime SinkType: type, comptime name_: []const u8) type { return shim.cppFn("assignToStream", .{ globalThis, stream, ptr, jsvalue_ptr }); } - pub const Export = shim.exportFunctions(.{ - .finalize = finalize, - .write = write, - .close = close, - .flush = flush, - .start = start, - .end = end, - .construct = construct, - .endWithSink = endWithSink, - .updateRef = updateRef, - }); - pub fn updateRef(ptr: *anyopaque, value: bool) callconv(.C) void { JSC.markBinding(@src()); var this = bun.cast(*ThisSink, ptr); @@ -1945,17 +1933,23 @@ pub fn NewJSSink(comptime SinkType: type, comptime name_: []const u8) type { } comptime { - if (!JSC.is_bindgen) { - @export(finalize, .{ .name = Export[0].symbol_name }); - @export(write, .{ .name = Export[1].symbol_name }); - @export(close, .{ .name = Export[2].symbol_name }); - @export(flush, .{ .name = Export[3].symbol_name }); - @export(start, .{ .name = Export[4].symbol_name }); - @export(end, .{ .name = Export[5].symbol_name }); - @export(construct, .{ .name = Export[6].symbol_name }); - @export(endWithSink, .{ .name = Export[7].symbol_name }); - @export(updateRef, .{ .name = Export[8].symbol_name }); - } + @export(finalize, .{ .name = shim.symbolName("finalize") }); + @export(write, .{ .name = shim.symbolName("write") }); + @export(close, .{ .name = shim.symbolName("close") }); + @export(flush, .{ .name = shim.symbolName("flush") }); + @export(start, .{ .name = shim.symbolName("start") }); + @export(end, .{ .name = shim.symbolName("end") }); + @export(construct, .{ .name = shim.symbolName("construct") }); + @export(endWithSink, .{ .name = shim.symbolName("endWithSink") }); + @export(updateRef, .{ .name = shim.symbolName("updateRef") }); + + shim.assertJSFunction(.{ + write, + close, + flush, + start, + end, + }); } pub const Extern = [_][]const u8{ "createObject", "fromJS", "assignToStream", "onReady", "onClose", "detachPtr" }; @@ -1969,7 +1963,7 @@ pub fn NewJSSink(comptime SinkType: type, comptime name_: []const u8) type { // socket: Socket, -// pub fn connect(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { +// pub fn connect(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) JSValue { // JSC.markBinding(@src()); // var this = @ptrCast(*ThisSocket, @alignCast( fromJS(globalThis, callframe.this()) orelse { @@ -2727,7 +2721,7 @@ pub fn ReadableStreamSource( return ReadableStream.fromNative(globalThis, out_value); } - pub fn setRawModeFromJS(this: *ReadableStreamSourceType, global: *JSC.JSGlobalObject, call_frame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn setRawModeFromJS(this: *ReadableStreamSourceType, global: *JSC.JSGlobalObject, call_frame: *JSC.CallFrame) JSValue { if (@hasDecl(Context, "setRawMode")) { const flag = call_frame.argument(0); if (Environment.allow_assert) { @@ -2758,13 +2752,13 @@ pub fn ReadableStreamSource( pub const construct = JSReadableStreamSource.construct; pub const getIsClosedFromJS = JSReadableStreamSource.isClosed; pub const JSReadableStreamSource = struct { - pub fn construct(globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) ?*ReadableStreamSourceType { + pub fn construct(globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) ?*ReadableStreamSourceType { _ = callFrame; // autofix globalThis.throw("Cannot construct ReadableStreamSource", .{}); return null; } - pub fn pull(this: *ReadableStreamSourceType, globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn pull(this: *ReadableStreamSourceType, globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) JSC.JSValue { JSC.markBinding(@src()); const this_jsvalue = callFrame.this(); const arguments = callFrame.arguments(2); @@ -2780,7 +2774,7 @@ pub fn ReadableStreamSource( ); } - pub fn start(this: *ReadableStreamSourceType, globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn start(this: *ReadableStreamSourceType, globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) JSC.JSValue { JSC.markBinding(@src()); this.globalThis = globalThis; this.this_jsvalue = callFrame.this(); @@ -2798,7 +2792,7 @@ pub fn ReadableStreamSource( } } - pub fn isClosed(this: *ReadableStreamSourceType, globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn isClosed(this: *ReadableStreamSourceType, globalObject: *JSC.JSGlobalObject) JSC.JSValue { _ = globalObject; // autofix return JSC.JSValue.jsBoolean(this.is_closed); } @@ -2829,7 +2823,7 @@ pub fn ReadableStreamSource( } } - pub fn cancel(this: *ReadableStreamSourceType, globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn cancel(this: *ReadableStreamSourceType, globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) JSC.JSValue { _ = globalObject; // autofix JSC.markBinding(@src()); this.this_jsvalue = callFrame.this(); @@ -2837,7 +2831,7 @@ pub fn ReadableStreamSource( return JSC.JSValue.jsUndefined(); } - pub fn setOnCloseFromJS(this: *ReadableStreamSourceType, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) callconv(.C) bool { + pub fn setOnCloseFromJS(this: *ReadableStreamSourceType, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) bool { JSC.markBinding(@src()); this.close_handler = JSReadableStreamSource.onClose; this.globalThis = globalObject; @@ -2856,7 +2850,7 @@ pub fn ReadableStreamSource( return true; } - pub fn setOnDrainFromJS(this: *ReadableStreamSourceType, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) callconv(.C) bool { + pub fn setOnDrainFromJS(this: *ReadableStreamSourceType, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) bool { JSC.markBinding(@src()); this.globalThis = globalObject; @@ -2874,7 +2868,7 @@ pub fn ReadableStreamSource( return true; } - pub fn getOnCloseFromJS(this: *ReadableStreamSourceType, globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getOnCloseFromJS(this: *ReadableStreamSourceType, globalObject: *JSC.JSGlobalObject) JSC.JSValue { _ = globalObject; // autofix JSC.markBinding(@src()); @@ -2882,7 +2876,7 @@ pub fn ReadableStreamSource( return this.close_jsvalue.get() orelse .undefined; } - pub fn getOnDrainFromJS(this: *ReadableStreamSourceType, globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { + pub fn getOnDrainFromJS(this: *ReadableStreamSourceType, globalObject: *JSC.JSGlobalObject) JSC.JSValue { _ = globalObject; // autofix JSC.markBinding(@src()); @@ -2894,7 +2888,7 @@ pub fn ReadableStreamSource( return .undefined; } - pub fn updateRef(this: *ReadableStreamSourceType, globalObject: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn updateRef(this: *ReadableStreamSourceType, globalObject: *JSGlobalObject, callFrame: *JSC.CallFrame) JSC.JSValue { JSC.markBinding(@src()); this.this_jsvalue = callFrame.this(); const ref_or_unref = callFrame.argument(0).toBooleanSlow(globalObject); @@ -2913,13 +2907,13 @@ pub fn ReadableStreamSource( this.close_jsvalue.clear(); } - pub fn finalize(this: *ReadableStreamSourceType) callconv(.C) void { + pub fn finalize(this: *ReadableStreamSourceType) void { this.this_jsvalue = .zero; _ = this.decrementCount(); } - pub fn drain(this: *ReadableStreamSourceType, globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn drain(this: *ReadableStreamSourceType, globalThis: *JSGlobalObject, callFrame: *JSC.CallFrame) JSC.JSValue { JSC.markBinding(@src()); this.this_jsvalue = callFrame.this(); var list = this.drain(); diff --git a/src/bun.zig b/src/bun.zig index bb83f5c351..97998d0ad1 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -801,7 +801,7 @@ pub fn getenvZ(key: [:0]const u8) ?[]const u8 { for (std.os.environ) |lineZ| { const line = sliceTo(lineZ, 0); const key_end = strings.indexOfCharUsize(line, '=') orelse line.len; - if (strings.eqlInsensitive(line[0..key_end], key)) { + if (strings.eqlCaseInsensitiveASCII(line[0..key_end], key, true)) { return line[@min(key_end + 1, line.len)..]; } } diff --git a/src/bun_js.zig b/src/bun_js.zig index 1147d08d72..1568fa5777 100644 --- a/src/bun_js.zig +++ b/src/bun_js.zig @@ -437,7 +437,7 @@ pub const Run = struct { } }; -pub export fn Bun__onResolveEntryPointResult(global: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) noreturn { +pub export fn Bun__onResolveEntryPointResult(global: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) noreturn { const arguments = callframe.arguments(1).slice(); const result = arguments[0]; result.print(global, .Log, .Log); @@ -445,7 +445,7 @@ pub export fn Bun__onResolveEntryPointResult(global: *JSC.JSGlobalObject, callfr return .undefined; } -pub export fn Bun__onRejectEntryPointResult(global: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) noreturn { +pub export fn Bun__onRejectEntryPointResult(global: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(JSC.conv) noreturn { const arguments = callframe.arguments(1).slice(); const result = arguments[0]; result.print(global, .Log, .Log); diff --git a/src/cli/create_command.zig b/src/cli/create_command.zig index 91d8d8801c..d1a324a7ed 100644 --- a/src/cli/create_command.zig +++ b/src/cli/create_command.zig @@ -241,7 +241,7 @@ pub const CreateCommand = struct { @setCold(true); Global.configureAllocator(.{ .long_running = false }); - try HTTP.HTTPThread.init(); + HTTP.HTTPThread.init(); var create_options = try CreateOptions.parse(ctx); const positionals = create_options.positionals; @@ -1999,7 +1999,7 @@ pub const Example = struct { var is_expected_content_type = false; var content_type: string = ""; for (response.headers) |header| { - if (strings.eqlInsensitive(header.name, "content-type")) { + if (strings.eqlCaseInsensitiveASCII(header.name, "content-type", true)) { content_type = header.value; if (strings.eqlComptime(header.value, "application/x-gzip")) { diff --git a/src/cli/test_command.zig b/src/cli/test_command.zig index 8fc3508aa7..d12e877767 100644 --- a/src/cli/test_command.zig +++ b/src/cli/test_command.zig @@ -741,7 +741,7 @@ pub const TestCommand = struct { break :brk loader; }; bun.JSC.initialize(); - HTTPThread.init() catch {}; + HTTPThread.init(); var snapshot_file_buf = std.ArrayList(u8).init(ctx.allocator); var snapshot_values = Snapshots.ValuesHashMap.init(ctx.allocator); diff --git a/src/cli/upgrade_command.zig b/src/cli/upgrade_command.zig index de498e7c14..eeaac8b226 100644 --- a/src/cli/upgrade_command.zig +++ b/src/cli/upgrade_command.zig @@ -133,7 +133,7 @@ pub const UpgradeCheckerThread = struct { std.time.sleep(std.time.ns_per_ms * delay); Output.Source.configureThread(); - try HTTP.HTTPThread.init(); + HTTP.HTTPThread.init(); defer { js_ast.Expr.Data.Store.deinit(); @@ -442,7 +442,7 @@ pub const UpgradeCommand = struct { } fn _exec(ctx: Command.Context) !void { - try HTTP.HTTPThread.init(); + HTTP.HTTPThread.init(); var filesystem = try fs.FileSystem.init(null); var env_loader: DotEnv.Loader = brk: { @@ -1000,7 +1000,7 @@ pub const upgrade_js_bindings = struct { /// For testing upgrades when the temp directory has an open handle without FILE_SHARE_DELETE. /// Windows only - pub fn jsOpenTempDirWithoutSharingDelete(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) bun.JSC.JSValue { + pub fn jsOpenTempDirWithoutSharingDelete(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSC.JSValue { if (comptime !Environment.isWindows) return .undefined; const w = std.os.windows; @@ -1054,7 +1054,7 @@ pub const upgrade_js_bindings = struct { return .undefined; } - pub fn jsCloseTempDirHandle(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSValue { + pub fn jsCloseTempDirHandle(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSValue { if (comptime !Environment.isWindows) return .undefined; if (tempdir_fd) |fd| { diff --git a/src/codegen/bundle-functions.ts b/src/codegen/bundle-functions.ts index 1fcf46189a..dfc66b8368 100644 --- a/src/codegen/bundle-functions.ts +++ b/src/codegen/bundle-functions.ts @@ -14,7 +14,7 @@ import { sliceSourceCode } from "./builtin-parser"; import { applyGlobalReplacements, define } from "./replacements"; import { cap, fmtCPPCharArray, low, writeIfNotChanged } from "./helpers"; import { createAssertClientJS, createLogClientJS } from "./client-js"; -import { getJS2NativeDTS } from "./js2native-generator"; +import { getJS2NativeDTS } from "./generate-js2native"; const PARALLEL = false; const KEEP_TMP = true; diff --git a/src/codegen/bundle-modules.ts b/src/codegen/bundle-modules.ts index 0be71f3b92..59b72320bf 100644 --- a/src/codegen/bundle-modules.ts +++ b/src/codegen/bundle-modules.ts @@ -17,7 +17,7 @@ import { createAssertClientJS, createLogClientJS } from "./client-js"; import { builtinModules } from "node:module"; import { define } from "./replacements"; import { createInternalModuleRegistry } from "./internal-module-registry-scanner"; -import { getJS2NativeCPP, getJS2NativeZig } from "./js2native-generator"; +import { getJS2NativeCPP, getJS2NativeZig } from "./generate-js2native"; const BASE = path.join(import.meta.dir, "../js"); const debug = process.argv[2] === "--debug=ON"; diff --git a/src/codegen/create-hash-table.ts b/src/codegen/create-hash-table.ts index a94dc3d7c2..e47c1d036f 100644 --- a/src/codegen/create-hash-table.ts +++ b/src/codegen/create-hash-table.ts @@ -43,6 +43,7 @@ str = str.replaceAll(/^\/\/.*$/gm, ""); str = str.replaceAll(/^#include.*$/gm, ""); str = str.replaceAll(`namespace JSC {`, ""); str = str.replaceAll(`} // namespace JSC`, ""); -str = "// File generated via `static-hash-table.ts`\n" + str.trim() + "\n"; +str = str.replaceAll(/NativeFunctionType,\s([a-zA-Z0-99_]+)/gm, "NativeFunctionType, &$1"); +str = "#pragma once" + "\n" + "// File generated via `create-hash-table.ts`\n" + str.trim() + "\n"; writeIfNotChanged(output, str); diff --git a/src/codegen/generate-classes.ts b/src/codegen/generate-classes.ts index eabc3583a6..64d9beeba9 100644 --- a/src/codegen/generate-classes.ts +++ b/src/codegen/generate-classes.ts @@ -9,7 +9,7 @@ if (process.env.BUN_SILENT === "1") { const files = process.argv.slice(2); const outBase = files.pop(); - +let externs = ""; const CommonIdentifiers = { "name": true, }; @@ -87,10 +87,14 @@ function ZigDOMJITArgType(type) { }[type]; } +function ZigDOMJITArgTypeDefinition(type, index) { + return `arg${index}: ${ZigDOMJITArgType(type)}`; +} + function ZigDOMJITFunctionType(thisName, { args, returns }) { return `fn (*${thisName}, *JSC.JSGlobalObject, ${args .map(ZigDOMJITArgType) - .join(", ")}) callconv(.C) ${ZigDOMJITArgType("JSValue")}`; + .join(", ")}) callconv(JSC.conv) ${ZigDOMJITArgType("JSValue")}`; } function DOMJITReturnType(type) { @@ -107,13 +111,16 @@ function DOMJITFunctionDeclaration(jsClassName, fnName, symName, { args, returns const argNames = args.map((arg, i) => `${argTypeName(arg)} arg${i}`); const formattedArgs = argNames.length > 0 ? `, ${argNames.join(", ")}` : ""; const domJITArgs = args.length > 0 ? `, ${args.map(DOMJITType).join(", ")}` : ""; - return ` - extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(${DOMJITName( - fnName, - )}Wrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue${formattedArgs})); - extern "C" EncodedJSValue ${DOMJITName(symName)}(void* ptr, JSC::JSGlobalObject * lexicalGlobalObject${formattedArgs}); + externs += ` +extern JSC_CALLCONV JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES ${DOMJITName(symName)}(void* ptr, JSC::JSGlobalObject * lexicalGlobalObject${formattedArgs}); + `; - static const JSC::DOMJIT::Signature DOMJITSignatureFor${fnName}(${DOMJITName(fnName)}Wrapper, + return ( + ` +extern JSC_CALLCONV JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(${DOMJITName( + fnName, + )}Wrapper, JSC::EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue${formattedArgs})); +static const JSC::DOMJIT::Signature DOMJITSignatureFor${fnName}(${DOMJITName(fnName)}Wrapper, ${jsClassName}::info(), ${ pure @@ -121,7 +128,8 @@ function DOMJITFunctionDeclaration(jsClassName, fnName, symName, { args, returns : "JSC::DOMJIT::Effect::forReadWrite(JSC::DOMJIT::HeapRange::top(), JSC::DOMJIT::HeapRange::top())" }, ${returns === "JSString" ? "JSC::SpecString" : DOMJITType("JSValue")}${domJITArgs}); -`.trim(); +`.trim() + "\n" + ); } function DOMJITFunctionDefinition(jsClassName, fnName, symName, { args }) { @@ -132,20 +140,26 @@ function DOMJITFunctionDefinition(jsClassName, fnName, symName, { args }) { return ` JSC_DEFINE_JIT_OPERATION(${DOMJITName( fnName, - )}Wrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue${formattedArgs})) + )}Wrapper, JSC::EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue${formattedArgs})) { VM& vm = JSC::getVM(lexicalGlobalObject); IGNORE_WARNINGS_BEGIN("frame-address") CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - return ${DOMJITName(symName)}(reinterpret_cast<${jsClassName}*>(thisValue)->wrapped(), lexicalGlobalObject${retArgs}); + return {${DOMJITName(symName)}(reinterpret_cast<${jsClassName}*>(thisValue)->wrapped(), lexicalGlobalObject${retArgs})}; } -`; +`.trim(); } -function appendSymbols(to: Map, symbolName: (name: string) => string, prop) { +function zigExportName(to: Map, symbolName: (name: string) => string, prop) { var { defaultValue, getter, setter, accessor, fn, DOMJIT, cache } = prop; + const exportNames = { + getter: "", + setter: "", + fn: "", + DOMJIT: "", + }; if (accessor) { getter = accessor.getter; @@ -153,19 +167,21 @@ function appendSymbols(to: Map, symbolName: (name: string) => st } if (getter && !to.get(getter)) { - to.set(getter, symbolName(getter)); + to.set(getter, (exportNames.getter = symbolName(getter))); } if (setter && !to.get(setter)) { - to.set(setter, symbolName(setter)); + to.set(setter, (exportNames.setter = symbolName(setter))); } if (fn && !to.get(fn)) { if (DOMJIT) { - to.set(DOMJITName(fn), symbolName(DOMJITName(fn))); + to.set(DOMJITName(fn), (exportNames.DOMJIT = symbolName(DOMJITName(fn)))); } - to.set(fn, symbolName(fn)); + to.set(fn, (exportNames.fn = symbolName(fn))); } + + return exportNames; } function propRow( symbolName: (a: string, b: string) => string, @@ -320,6 +336,36 @@ function generatePrototype(typeName, obj) { var staticPrototypeValues = ""; + if (obj.construct) { + externs += ` +extern JSC_CALLCONV void* JSC_HOST_CALL_ATTRIBUTES ${classSymbolName(typeName, "construct")}(JSC::JSGlobalObject*, JSC::CallFrame*); +JSC_DECLARE_CUSTOM_GETTER(js${typeName}Constructor); +`; + } + + if (obj.structuredClone) { + externs += + `extern JSC_CALLCONV void JSC_HOST_CALL_ATTRIBUTES ${symbolName( + typeName, + "onStructuredCloneSerialize", + )}(void*, JSC::JSGlobalObject*, WebCore::CloneSerializer*, SYSV_ABI void (*) (WebCore::CloneSerializer*, const uint8_t*, uint32_t));` + + "\n"; + + externs += + `extern JSC_CALLCONV JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES ${symbolName( + typeName, + "onStructuredCloneDeserialize", + )}(JSC::JSGlobalObject*, const uint8_t*, const uint8_t*);` + "\n"; + } + if (obj.finalize) { + externs += + `extern JSC_CALLCONV void JSC_HOST_CALL_ATTRIBUTES ${classSymbolName(typeName, "finalize")}(void*);` + "\n"; + } + + if (obj.call) { + externs += `extern JSC_CALLCONV JSC_DECLARE_HOST_FUNCTION(${classSymbolName(typeName, "call")}) SYSV_ABI;` + "\n"; + } + for (const name in protoFields) { if ("value" in protoFields[name]) { const { value } = protoFields[name]; @@ -358,34 +404,6 @@ function generatePrototype(typeName, obj) { } return ` -${ - obj.construct - ? `extern "C" void* ${classSymbolName(typeName, "construct")}(JSC::JSGlobalObject*, JSC::CallFrame*); -JSC_DECLARE_CUSTOM_GETTER(js${typeName}Constructor);` - : "" -} - -${ - obj.structuredClone - ? `extern "C" void ${symbolName( - typeName, - "onStructuredCloneSerialize", - )}(void*, JSC::JSGlobalObject*, void*, void (*) (CloneSerializer*, const uint8_t*, uint32_t));` - : "" -} - -${ - obj.structuredClone - ? `extern "C" JSC::EncodedJSValue ${symbolName( - typeName, - "onStructuredCloneDeserialize", - )}(JSC::JSGlobalObject*, const uint8_t*, const uint8_t*);` - : "" -} - -${"finalize" in obj ? `extern "C" void ${classSymbolName(typeName, "finalize")}(void*);` : ""} -${obj.call ? `extern "C" JSC_DECLARE_HOST_FUNCTION(${classSymbolName(typeName, "call")});` : ""} - ${renderDecls(protoSymbolName, typeName, protoFields, obj.supportsObjectCreate || false)} STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(${proto}, ${proto}::Base); @@ -424,37 +442,38 @@ function generatePrototypeHeader(typename) { const proto = prototypeName(typename); return ` - class ${proto} final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; +class ${proto} final : public JSC::JSNonFinalObject { + public: + using Base = JSC::JSNonFinalObject; - static ${proto}* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - ${proto}* ptr = new (NotNull, JSC::allocateCell<${proto}>(vm)) ${proto}(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } + static ${proto}* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) + { + ${proto}* ptr = new (NotNull, JSC::allocateCell<${proto}>(vm)) ${proto}(vm, globalObject, structure); + ptr->finishCreation(vm, globalObject); + return ptr; + } - DECLARE_INFO; - template - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(${proto}, Base); - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } + DECLARE_INFO; + template + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(${proto}, Base); + return &vm.plainObjectSpace(); + } + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } - private: - ${proto}(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } + private: + ${proto}(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) + : Base(vm, structure) + { + } - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - };`; + void finishCreation(JSC::VM&, JSC::JSGlobalObject*); +}; +`; } function generateConstructorHeader(typeName) { @@ -462,49 +481,51 @@ function generateConstructorHeader(typeName) { // we use a single shared isosubspace for constructors since they will rarely // ever be created multiple times per VM and have no fields themselves - return ` - class ${name} final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static ${name}* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, ${prototypeName( - typeName, - )}* prototype); + return ( + ` +class ${name} final : public JSC::InternalFunction { + public: + using Base = JSC::InternalFunction; + static ${name}* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, ${prototypeName( + typeName, + )}* prototype); - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; + static constexpr unsigned StructureFlags = Base::StructureFlags; + static constexpr bool needsDestruction = false; - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); + } - template static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; + template static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; - return WebCore::subspaceForImpl<${name}, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.${clientSubspaceFor("BunClass")}Constructor.get(); }, - [](auto& spaces, auto&& space) { spaces.${clientSubspaceFor("BunClass")}Constructor = std::forward(space); }, - [](auto& spaces) { return spaces.${subspaceFor("BunClass")}Constructor.get(); }, - [](auto& spaces, auto&& space) { spaces.${subspaceFor("BunClass")}Constructor = std::forward(space); }); - } + return WebCore::subspaceForImpl<${name}, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.${clientSubspaceFor("BunClass")}Constructor.get(); }, + [](auto& spaces, auto&& space) { spaces.${clientSubspaceFor("BunClass")}Constructor = std::forward(space); }, + [](auto& spaces) { return spaces.${subspaceFor("BunClass")}Constructor.get(); }, + [](auto& spaces, auto&& space) { spaces.${subspaceFor("BunClass")}Constructor = std::forward(space); }); + } - void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, ${prototypeName(typeName)}* prototype); + void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, ${prototypeName(typeName)}* prototype); - // Must be defined for each specialization class. - static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); - static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES call(JSC::JSGlobalObject*, JSC::CallFrame*); + // Must be defined for each specialization class. + static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); + static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES call(JSC::JSGlobalObject*, JSC::CallFrame*); - DECLARE_EXPORT_INFO; - private: - ${name}(JSC::VM& vm, JSC::Structure* structure); - void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, ${prototypeName(typeName)}* prototype); - }; + DECLARE_EXPORT_INFO; + private: + ${name}(JSC::VM& vm, JSC::Structure* structure); + void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, ${prototypeName(typeName)}* prototype); +}; - `; + `.trim() + "\n" + ); } function generateConstructorImpl(typeName, obj: ClassDefinition) { @@ -514,8 +535,11 @@ function generateConstructorImpl(typeName, obj: ClassDefinition) { Object.keys(fields).length > 0 ? generateHashTable(name, classSymbolName, typeName, obj, fields, false) : ""; const hashTableIdentifier = hashTable.length ? `${name}TableValues` : ""; + if (obj.estimatedSize) { + externs += `extern JSC_CALLCONV size_t ${symbolName(typeName, "estimatedSize")}(void* ptr);` + "\n"; + } + return ` -${obj.estimatedSize ? `extern "C" size_t ${symbolName(typeName, "estimatedSize")}(void* ptr);` : ""} ${renderStaticDecls(classSymbolName, typeName, fields, obj.supportsObjectCreate || false)} ${hashTable} @@ -616,7 +640,7 @@ const ClassInfo ${name}::s_info = { "Function"_s, &Base::s_info, nullptr, nullpt ${ !obj.noConstructor ? ` - extern "C" EncodedJSValue ${typeName}__getConstructor(Zig::GlobalObject* globalObject) { + extern JSC_CALLCONV JSC::EncodedJSValue ${typeName}__getConstructor(Zig::GlobalObject* globalObject) { return JSValue::encode(globalObject->${className(typeName)}Constructor()); }` : "" @@ -662,12 +686,12 @@ function renderCallbacksCppImpl(typeName, callbacks: Record) { for (const name in callbacks) { rows.push( ` - extern "C" EncodedJSValue ${symbolName(typeName, "_callback_get_" + name)}(JSC::EncodedJSValue encodedThisValue) { + extern JSC_CALLCONV JSC::EncodedJSValue ${symbolName(typeName, "_callback_get_" + name)}(JSC::EncodedJSValue encodedThisValue) { auto* thisObject = jsCast<${className(typeName)}*>(JSValue::decode(encodedThisValue)); return JSValue::encode(thisObject->m_callback_${name}.get()); } - extern "C" void ${symbolName(typeName, "_callback_set_" + name)}(JSC::EncodedJSValue encodedThisValue, JSC::EncodedJSValue encodedCallback) { + extern JSC_CALLCONV void ${symbolName(typeName, "_callback_set_" + name)}(JSC::EncodedJSValue encodedThisValue, JSC::EncodedJSValue encodedCallback) { auto* thisObject = jsCast<${className(typeName)}*>(JSValue::decode(encodedThisValue)); JSValue callback = JSValue::decode(encodedCallback); #if ASSERT_ENABLED @@ -687,7 +711,7 @@ function renderCallbacksCppImpl(typeName, callbacks: Record) { } rows.push(` - extern "C" void ${symbolName(typeName, "_setAllCallbacks")}(JSC::EncodedJSValue encodedThisValue, ${Object.keys( + extern JSC_CALLCONV void ${symbolName(typeName, "_setAllCallbacks")}(JSC::EncodedJSValue encodedThisValue, ${Object.keys( callbacks, ) .map((_, i) => `JSC::EncodedJSValue encodedCallback${i}`) @@ -707,7 +731,7 @@ function renderCallbacksCppImpl(typeName, callbacks: Record) { `); - return rows.join("\n"); + return rows.map(a => a.trim()).join("\n"); } function renderCallbacksZig(typeName, callbacks: Record) { @@ -723,8 +747,8 @@ function renderCallbacksZig(typeName, callbacks: Record) { const get = symbolName(typeName, "_callback_get_" + name); const set = symbolName(typeName, "_callback_set_" + name); out += ` - extern fn ${get}(JSC.JSValue) JSC.JSValue; - extern fn ${set}(JSC.JSValue, JSC.JSValue) void; + extern fn ${get}(JSC.JSValue) callconv(JSC.conv) JSC.JSValue; + extern fn ${set}(JSC.JSValue, JSC.JSValue) callconv(JSC.conv) void; pub const ${pascalCase(name)}Callback = JSC.Codegen.CallbackWrapper(${get}, ${set}); pub fn ${camelCase(name)}(cb: @This(), thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, args: []const JSC.JSValue) ?JSC.JSValue { return ${pascalCase(name)}Callback.call(.{.instance = cb.instance}, thisValue, globalObject, args); @@ -737,7 +761,7 @@ function renderCallbacksZig(typeName, callbacks: Record) { out += ` extern fn ${symbolName(typeName, "_setAllCallbacks")}(JSC.JSValue, ${Object.keys(callbacks) .map((a, i) => `callback${i}: JSC.JSValue`) - .join(", ")}) void; + .join(", ")}) callconv(JSC.conv) void; pub inline fn set(this: @This(), values: struct { ${Object.keys(callbacks) @@ -768,13 +792,15 @@ function renderDecls(symbolName, typeName, proto, supportsObjectCreate = false) for (const name in proto) { if ("getter" in proto[name] || ("accessor" in proto[name] && proto[name].getter)) { - rows.push( - `extern "C" JSC::EncodedJSValue ${symbolName( + externs += + `extern JSC_CALLCONV JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES ${symbolName( typeName, proto[name].getter || proto[name].accessor.getter, )}(void* ptr,${ !!proto[name].this ? " JSC::EncodedJSValue thisValue, " : "" - } JSC::JSGlobalObject* lexicalGlobalObject);`, + } JSC::JSGlobalObject* lexicalGlobalObject);` + "\n"; + + rows.push( ` JSC_DECLARE_CUSTOM_GETTER(${symbolName(typeName, name)}GetterWrap); ${proto[name].writable ? `JSC_DECLARE_CUSTOM_SETTER(${symbolName(typeName, name)}SetterWrap);` : ""} @@ -788,10 +814,11 @@ function renderDecls(symbolName, typeName, proto, supportsObjectCreate = false) } if ("setter" in proto[name] || ("accessor" in proto[name] && proto[name].setter)) { - rows.push( - `extern "C" bool ${symbolName(typeName, proto[name].setter || proto[name].accessor.setter)}(void* ptr,${ + externs += + `extern JSC_CALLCONV bool JSC_HOST_CALL_ATTRIBUTES ${symbolName(typeName, proto[name].setter || proto[name].accessor.setter)}(void* ptr,${ !!proto[name].this ? " JSC::EncodedJSValue thisValue, " : "" - } JSC::JSGlobalObject* lexicalGlobalObject, JSC::EncodedJSValue value);`, + } JSC::JSGlobalObject* lexicalGlobalObject, JSC::EncodedJSValue value);` + "\n"; + rows.push( ` static JSC_DECLARE_CUSTOM_SETTER(${symbolName(typeName, name)}SetterWrap); `.trim(), @@ -800,12 +827,12 @@ function renderDecls(symbolName, typeName, proto, supportsObjectCreate = false) } if ("fn" in proto[name]) { - rows.push( - `extern "C" EncodedJSValue ${symbolName( + externs += + `extern JSC_CALLCONV JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES ${symbolName( typeName, proto[name].fn, - )}(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);`, - + )}(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);` + "\n"; + rows.push( ` JSC_DECLARE_HOST_FUNCTION(${symbolName(typeName, name)}Callback); `.trim(), @@ -831,7 +858,7 @@ function renderDecls(symbolName, typeName, proto, supportsObjectCreate = false) } } - return rows.join("\n"); + return rows.map(a => a.trim()).join("\n"); } function renderStaticDecls(symbolName, typeName, fields, supportsObjectCreate = false) { @@ -839,25 +866,24 @@ function renderStaticDecls(symbolName, typeName, fields, supportsObjectCreate = for (const name in fields) { if ("getter" in fields[name] || ("accessor" in fields[name] && fields[name].getter)) { - rows.push( - `extern "C" JSC_DECLARE_CUSTOM_GETTER(${symbolName( + externs += + `extern JSC_CALLCONV JSC_DECLARE_CUSTOM_GETTER(${symbolName( typeName, fields[name].getter || fields[name].accessor.getter, - )});`, - ); + )});` + "\n"; } if ("setter" in fields[name] || ("accessor" in fields[name] && fields[name].setter)) { - rows.push( - `extern "C" JSC_DECLARE_CUSTOM_SETTER(${symbolName( + externs += + `extern JSC_CALLCONV JSC_DECLARE_CUSTOM_SETTER(${symbolName( typeName, fields[name].setter || fields[name].accessor.setter, - )});`, - ); + )});` + "\n"; } if ("fn" in fields[name]) { - rows.push(`extern "C" JSC_DECLARE_HOST_FUNCTION(${symbolName(typeName, fields[name].fn)});`); + externs += + `extern JSC_CALLCONV JSC_DECLARE_HOST_FUNCTION(${symbolName(typeName, fields[name].fn)}) SYSV_ABI;` + "\n"; } } @@ -866,20 +892,20 @@ function renderStaticDecls(symbolName, typeName, fields, supportsObjectCreate = function writeBarrier(symbolName, typeName, name, cacheName) { return ` - extern "C" void ${symbolName(typeName, name)}SetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject *globalObject, JSC::EncodedJSValue value) - { - auto& vm = globalObject->vm(); - auto* thisObject = jsCast<${className(typeName)}*>(JSValue::decode(thisValue)); - thisObject->${cacheName}.set(vm, thisObject, JSValue::decode(value)); - } - - extern "C" EncodedJSValue ${symbolName(typeName, name)}GetCachedValue(JSC::EncodedJSValue thisValue) - { +extern JSC_CALLCONV void ${symbolName(typeName, name)}SetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject *globalObject, JSC::EncodedJSValue value) +{ + auto& vm = globalObject->vm(); auto* thisObject = jsCast<${className(typeName)}*>(JSValue::decode(thisValue)); - return JSValue::encode(thisObject->${cacheName}.get()); - } + thisObject->${cacheName}.set(vm, thisObject, JSValue::decode(value)); +} - `; +extern JSC_CALLCONV JSC::EncodedJSValue ${symbolName(typeName, name)}GetCachedValue(JSC::EncodedJSValue thisValue) +{ + auto* thisObject = jsCast<${className(typeName)}*>(JSValue::decode(thisValue)); + return JSValue::encode(thisObject->${cacheName}.get()); +} + + `.trim(); } function renderFieldsImpl( symbolName: (typeName: string, name: string) => string, @@ -893,7 +919,8 @@ function renderFieldsImpl( const supportsObjectCreate = obj.supportsObjectCreate || false; if (obj.construct) { - rows.push(` + rows.push( + ` JSC_DEFINE_CUSTOM_GETTER(js${typeName}Constructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) { @@ -907,7 +934,8 @@ JSC_DEFINE_CUSTOM_GETTER(js${typeName}Constructor, (JSGlobalObject * lexicalGlob return JSValue::encode(globalObject->${className(typeName)}Constructor()); } -`); +`.trim(), + ); } for (const name in proto) { @@ -915,7 +943,8 @@ JSC_DEFINE_CUSTOM_GETTER(js${typeName}Constructor, (JSGlobalObject * lexicalGlob const cacheName = typeof proto[name].cache === "string" ? `m_${proto[name].cache}` : `m_${name}`; if ("cache" in proto[name]) { if (!supportsObjectCreate) { - rows.push(` + rows.push( + ` JSC_DEFINE_CUSTOM_GETTER(${symbolName(typeName, name)}GetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue encodedThisValue, PropertyName attributeName)) { auto& vm = lexicalGlobalObject->vm(); @@ -935,44 +964,50 @@ JSC_DEFINE_CUSTOM_GETTER(${symbolName(typeName, name)}GetterWrap, (JSGlobalObjec RETURN_IF_EXCEPTION(throwScope, {}); thisObject->${cacheName}.set(vm, thisObject, result); RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); -}`); +}`.trim(), + ); if (proto[name].writable) { - rows.push(` - JSC_DEFINE_CUSTOM_SETTER(${symbolName(typeName, name)}SetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue encodedThisValue, EncodedJSValue encodedValue, PropertyName attributeName)) - { - auto& vm = lexicalGlobalObject->vm(); - auto throwScope = DECLARE_THROW_SCOPE(vm); - ${className(typeName)}* thisObject = jsCast<${className(typeName)}*>(JSValue::decode(encodedThisValue)); - JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); - thisObject->${cacheName}.set(vm, thisObject, JSValue::decode(encodedValue)); - RELEASE_AND_RETURN(throwScope, true); - }`); + rows.push( + ` +JSC_DEFINE_CUSTOM_SETTER(${symbolName(typeName, name)}SetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue encodedThisValue, EncodedJSValue encodedValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + ${className(typeName)}* thisObject = jsCast<${className(typeName)}*>(JSValue::decode(encodedThisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + thisObject->${cacheName}.set(vm, thisObject, JSValue::decode(encodedValue)); + RELEASE_AND_RETURN(throwScope, true); +}`.trim(), + ); } } else { - rows.push(` - JSC_DEFINE_CUSTOM_GETTER(${symbolName(typeName, name)}GetterWrap, (JSGlobalObject * globalObject, EncodedJSValue encodedThisValue, PropertyName attributeName)) - { - auto& vm = globalObject->vm(); - auto throwScope = DECLARE_THROW_SCOPE(vm); - ${className(typeName)}* thisObject = jsDynamicCast<${className(typeName)}*>(JSValue::decode(encodedThisValue)); - if (UNLIKELY(!thisObject)) { - return JSValue::encode(jsUndefined()); - } + rows.push( + ` +JSC_DEFINE_CUSTOM_GETTER(${symbolName(typeName, name)}GetterWrap, (JSGlobalObject * globalObject, EncodedJSValue encodedThisValue, PropertyName attributeName)) +{ + auto& vm = globalObject->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + ${className(typeName)}* thisObject = jsDynamicCast<${className(typeName)}*>(JSValue::decode(encodedThisValue)); + if (UNLIKELY(!thisObject)) { + return JSValue::encode(jsUndefined()); + } - JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); - - if (JSValue cachedValue = thisObject->${cacheName}.get()) - return JSValue::encode(cachedValue); - - JSC::JSValue result = JSC::JSValue::decode( - ${symbolName(typeName, proto[name].getter)}(thisObject->wrapped(),${ - proto[name].this!! ? " thisValue, " : "" - } globalObject) - ); - RETURN_IF_EXCEPTION(throwScope, {}); - thisObject->${cacheName}.set(vm, thisObject, result); - RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); - }`); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + if (JSValue cachedValue = thisObject->${cacheName}.get()) + return JSValue::encode(cachedValue); + + JSC::JSValue result = JSC::JSValue::decode( + ${symbolName(typeName, proto[name].getter)}(thisObject->wrapped(),${ + proto[name].this!! ? " thisValue, " : "" + } globalObject) + ); + RETURN_IF_EXCEPTION(throwScope, {}); + thisObject->${cacheName}.set(vm, thisObject, result); + RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); +} +`.trim(), + ); } } rows.push(writeBarrier(symbolName, typeName, name, cacheName)); @@ -995,22 +1030,22 @@ JSC_DEFINE_CUSTOM_GETTER(${symbolName(typeName, name)}GetterWrap, (JSGlobalObjec `); } else { rows.push(` - JSC_DEFINE_CUSTOM_GETTER(${symbolName(typeName, name)}GetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue encodedThisValue, PropertyName attributeName)) - { - auto& vm = lexicalGlobalObject->vm(); - Zig::GlobalObject *globalObject = reinterpret_cast(lexicalGlobalObject); - auto throwScope = DECLARE_THROW_SCOPE(vm); - ${className(typeName)}* thisObject = jsDynamicCast<${className(typeName)}*>(JSValue::decode(encodedThisValue)); - if (UNLIKELY(!thisObject)) { - return JSValue::encode(jsUndefined()); - } - JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); - JSC::EncodedJSValue result = ${symbolName(typeName, proto[name].getter)}(thisObject->wrapped(),${ - !!proto[name].this ? " encodedThisValue, " : "" - } globalObject); - RETURN_IF_EXCEPTION(throwScope, {}); - RELEASE_AND_RETURN(throwScope, result); - } +JSC_DEFINE_CUSTOM_GETTER(${symbolName(typeName, name)}GetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue encodedThisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject *globalObject = reinterpret_cast(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + ${className(typeName)}* thisObject = jsDynamicCast<${className(typeName)}*>(JSValue::decode(encodedThisValue)); + if (UNLIKELY(!thisObject)) { + return JSValue::encode(jsUndefined()); + } + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + JSC::EncodedJSValue result = ${symbolName(typeName, proto[name].getter)}(thisObject->wrapped(),${ + !!proto[name].this ? " encodedThisValue, " : "" + } globalObject); + RETURN_IF_EXCEPTION(throwScope, {}); + RELEASE_AND_RETURN(throwScope, result); +} `); } } @@ -1035,58 +1070,59 @@ JSC_DEFINE_CUSTOM_SETTER(${symbolName(typeName, name)}SetterWrap, (JSGlobalObjec } else if (supportsObjectCreate) { rows.push( ` - JSC_DEFINE_CUSTOM_SETTER(${symbolName(typeName, name)}SetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue encodedThisValue, EncodedJSValue encodedValue, PropertyName attributeName)) - { - auto& vm = lexicalGlobalObject->vm(); - auto throwScope = DECLARE_THROW_SCOPE(vm); - JSValue thisValue = JSValue::decode(encodedThisValue); - if (!thisValue.isObject()) { - return false; - } +JSC_DEFINE_CUSTOM_SETTER(${symbolName(typeName, name)}SetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue encodedThisValue, EncodedJSValue encodedValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = JSValue::decode(encodedThisValue); + if (!thisValue.isObject()) { + return false; + } - JSObject *thisObject = asObject(thisValue); - thisObject->putDirect(vm, attributeName, JSValue::decode(encodedValue), 0); - return true; - } + JSObject *thisObject = asObject(thisValue); + thisObject->putDirect(vm, attributeName, JSValue::decode(encodedValue), 0); + return true; +} `, ); } if ("fn" in proto[name]) { rows.push(` - JSC_DEFINE_HOST_FUNCTION(${symbolName(typeName, name)}Callback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) - { - auto& vm = lexicalGlobalObject->vm(); +JSC_DEFINE_HOST_FUNCTION(${symbolName(typeName, name)}Callback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); - ${className(typeName)}* thisObject = jsDynamicCast<${className(typeName)}*>(callFrame->thisValue()); + ${className(typeName)}* thisObject = jsDynamicCast<${className(typeName)}*>(callFrame->thisValue()); - if (UNLIKELY(!thisObject)) { - auto throwScope = DECLARE_THROW_SCOPE(vm); - throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof ${typeName}"_s); - return JSValue::encode({}); - } + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof ${typeName}"_s); + return JSValue::encode({}); + } - JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); - #ifdef BUN_DEBUG - /** View the file name of the JS file that called this function - * from a debugger */ - SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm); - const char* fileName = sourceOrigin.string().utf8().data(); - static const char* lastFileName = nullptr; - if (lastFileName != fileName) { - lastFileName = fileName; - } - - JSC::EncodedJSValue result = ${symbolName(typeName, proto[name].fn)}(thisObject->wrapped(), lexicalGlobalObject, callFrame); - - ASSERT_WITH_MESSAGE(!JSValue::decode(result).isEmpty() or DECLARE_CATCH_SCOPE(vm).exception() != 0, \"${typeName}.${proto[name].fn} returned an empty value without an exception\"); - - return result; - #endif - - return ${symbolName(typeName, proto[name].fn)}(thisObject->wrapped(), lexicalGlobalObject, callFrame); +#ifdef BUN_DEBUG + /** View the file name of the JS file that called this function + * from a debugger */ + SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm); + const char* fileName = sourceOrigin.string().utf8().data(); + static const char* lastFileName = nullptr; + if (lastFileName != fileName) { + lastFileName = fileName; } + + JSC::EncodedJSValue result = ${symbolName(typeName, proto[name].fn)}(thisObject->wrapped(), lexicalGlobalObject, callFrame); + + ASSERT_WITH_MESSAGE(!JSValue::decode(result).isEmpty() or DECLARE_CATCH_SCOPE(vm).exception() != 0, \"${typeName}.${proto[name].fn} returned an empty value without an exception\"); + + return result; +#endif + + return ${symbolName(typeName, proto[name].fn)}(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + `); } } @@ -1097,7 +1133,7 @@ JSC_DEFINE_CUSTOM_SETTER(${symbolName(typeName, name)}SetterWrap, (JSGlobalObjec } } - return rows.join("\n"); + return rows.map(a => a.trim()).join("\n"); } var extraIncludes = []; @@ -1236,7 +1272,7 @@ function generateClassHeader(typeName, obj: ClassDefinition) { ${callbacks ? renderCallbacksHeader(typeName, obj.callbacks) : ""} }; ${suffix} - `; + `.trim(); } function generateClassImpl(typeName, obj: ClassDefinition) { @@ -1326,8 +1362,10 @@ ${renderCallbacksCppImpl(typeName, callbacks)} } if (hasPendingActivity) { + externs += + `extern JSC_CALLCONV bool JSC_HOST_CALL_ATTRIBUTES ${symbolName(typeName, "hasPendingActivity")}(void* ptr);` + + "\n"; output += ` - extern "C" bool ${symbolName(typeName, "hasPendingActivity")}(void* ptr); bool ${name}::hasPendingActivity(void* ctx) { return ${symbolName(typeName, "hasPendingActivity")}(ctx); } @@ -1335,9 +1373,8 @@ ${renderCallbacksCppImpl(typeName, callbacks)} } if (getInternalProperties) { + externs += `extern JSC_CALLCONV JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES ${symbolName(typeName, "getInternalProperties")}(void* ptr, JSC::JSGlobalObject *globalObject, JSC::EncodedJSValue thisValue);`; output += ` - extern "C" EncodedJSValue ${symbolName(typeName, "getInternalProperties")}(void* ptr, JSC::JSGlobalObject *globalObject, EncodedJSValue thisValue); - JSC::JSValue getInternalProperties(JSC::VM &, JSC::JSGlobalObject *globalObject, ${name}* castedThis) { return JSValue::decode(${symbolName(typeName, "getInternalProperties")}(castedThis->impl(), globalObject, JSValue::encode(castedThis))); @@ -1387,7 +1424,7 @@ ${name}* ${name}::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::St return ptr; } -extern "C" void* ${typeName}__fromJS(JSC::EncodedJSValue value) { +extern JSC_CALLCONV void* JSC_HOST_CALL_ATTRIBUTES ${typeName}__fromJS(JSC::EncodedJSValue value) { JSC::JSValue decodedValue = JSC::JSValue::decode(value); if (decodedValue.isEmpty() || !decodedValue.isCell()) return nullptr; @@ -1401,7 +1438,7 @@ extern "C" void* ${typeName}__fromJS(JSC::EncodedJSValue value) { return object->wrapped(); } -extern "C" void* ${typeName}__fromJSDirect(JSC::EncodedJSValue value) { +extern JSC_CALLCONV void* JSC_HOST_CALL_ATTRIBUTES ${typeName}__fromJSDirect(JSC::EncodedJSValue value) { JSC::JSValue decodedValue = JSC::JSValue::decode(value); ASSERT(decodedValue.isCell()); @@ -1420,7 +1457,7 @@ extern "C" void* ${typeName}__fromJSDirect(JSC::EncodedJSValue value) { return object->wrapped(); } -extern "C" bool ${typeName}__dangerouslySetPtr(JSC::EncodedJSValue value, void* ptr) { +extern JSC_CALLCONV bool JSC_HOST_CALL_ATTRIBUTES ${typeName}__dangerouslySetPtr(JSC::EncodedJSValue value, void* ptr) { ${className(typeName)}* object = JSC::jsDynamicCast<${className(typeName)}*>(JSValue::decode(value)); if (!object) return false; @@ -1460,7 +1497,7 @@ JSObject* ${name}::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) return ${prototypeName(typeName)}::create(vm, globalObject, structure); } -extern "C" EncodedJSValue ${typeName}__create(Zig::GlobalObject* globalObject, void* ptr) { +extern JSC_CALLCONV JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES ${typeName}__create(Zig::GlobalObject* globalObject, void* ptr) { auto &vm = globalObject->vm(); JSC::Structure* structure = globalObject->${className(typeName)}Structure(); ${className(typeName)}* instance = ${className(typeName)}::create(vm, globalObject, structure, ptr); @@ -1522,27 +1559,9 @@ function generateZig( ) { const exports = new Map(); - if (construct && !noConstructor) { - exports.set(`constructor`, classSymbolName(typeName, "construct")); - } - - if (call) { - exports.set(`call`, classSymbolName(typeName, "call")); - } - - if (finalize) { - exports.set(`finalize`, classSymbolName(typeName, "finalize")); - } - - if (estimatedSize) { - exports.set(`estimatedSize`, symbolName(typeName, "estimatedSize")); - } - if (hasPendingActivity) { exports.set("hasPendingActivity", symbolName(typeName, "hasPendingActivity")); } - Object.values(klass).map(a => appendSymbols(exports, name => classSymbolName(typeName, name), a)); - Object.values(proto).map(a => appendSymbols(exports, name => protoSymbolName(typeName, name), a)); if (getInternalProperties) { exports.set("getInternalProperties", symbolName(typeName, "getInternalProperties")); @@ -1565,9 +1584,9 @@ function generateZig( .filter(([name, { cache, internal }]) => (cache && typeof cache !== "string") || internal) .map( ([name]) => - `extern fn ${protoSymbolName(typeName, name)}SetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; + `extern fn ${protoSymbolName(typeName, name)}SetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) callconv(JSC.conv) void; - extern fn ${protoSymbolName(typeName, name)}GetCachedValue(JSC.JSValue) JSC.JSValue; + extern fn ${protoSymbolName(typeName, name)}GetCachedValue(JSC.JSValue) callconv(JSC.conv) JSC.JSValue; /// \`${typeName}.${name}\` setter /// This value will be visited by the garbage collector. @@ -1595,168 +1614,216 @@ function generateZig( renderedCallbacks = renderCallbacksZig(typeName, callbacks); } - function typeCheck() { - var output = ""; + function renderMethods() { + const exports = new Map(); + var output = ` +const JavaScriptCoreBindings = struct { + +`; if (estimatedSize) { + exports.set("estimatedSize", symbolName(typeName, "estimatedSize")); output += ` - if (@TypeOf(${typeName}.estimatedSize) != (fn(*${typeName}) callconv(.C) usize)) { - @compileLog("${typeName}.estimatedSize is not a size function"); + pub fn ${symbolName(typeName, "estimatedSize")}(thisValue: *${typeName}) callconv(JSC.conv) usize { + return @call(.always_inline, ${typeName}.estimatedSize, .{thisValue}); } `; } - if (structuredClone) { + if (hasPendingActivity) { + exports.set("hasPendingActivity", symbolName(typeName, "hasPendingActivity")); output += ` - if (@TypeOf(${typeName}.onStructuredCloneSerialize) != (fn(*${typeName}, globalThis: *JSC.JSGlobalObject, ctx: *anyopaque, writeBytes: *const fn(*anyopaque, ptr: [*]const u8, len: u32) callconv(.C) void) callconv(.C) void)) { - @compileLog("${typeName}.onStructuredCloneSerialize is not a structured clone serialize function"); - } - `; - - if (getInternalProperties) { - output += ` - if (@TypeOf(${typeName}.getInternalProperties) != (fn(*${typeName}, globalThis: *JSC.JSGlobalObject, JSC.JSValue thisValue) callconv(.C) JSC.JSValue { - @compileLog("${typeName}.getInternalProperties is not a getInternalProperties function"); - } - `; - } - - if (structuredClone === "transferable") { - exports.set("structuredClone", symbolName(typeName, "onTransferableStructuredClone")); - output += ` - if (@TypeOf(${typeName}.onStructuredCloneTransfer) != (fn(*${typeName}, globalThis: *JSC.JSGlobalObject, ctx: *anyopaque, write: *const fn(*anyopaque, ptr: [*]const u8, len: usize) callconv(.C) void) callconv(.C) void)) { - @compileLog("${typeName}.onStructuredCloneTransfer is not a structured clone transfer function"); - } - `; - } - - output += ` - if (@TypeOf(${typeName}.onStructuredCloneDeserialize) != (fn(globalThis: *JSC.JSGlobalObject, ptr: [*]u8, end: [*]u8) callconv(.C) JSC.JSValue)) { - @compileLog("${typeName}.onStructuredCloneDeserialize is not a structured clone deserialize function"); - } - `; - } - - if (construct && !noConstructor) { - output += ` - if (@TypeOf(${typeName}.constructor) != (fn(*JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) ?*${typeName})) { - @compileLog("${typeName}.constructor is not a constructor"); + pub fn ${symbolName(typeName, "hasPendingActivity")}(thisValue: *${typeName}) callconv(JSC.conv) bool { + return @call(.always_inline, ${typeName}.hasPendingActivity, .{thisValue}); } `; } if (finalize) { + exports.set("finalize", classSymbolName(typeName, "finalize")); output += ` - if (@TypeOf(${typeName}.finalize) != (fn(*${typeName}) callconv(.C) void)) { - @compileLog("${typeName}.finalize is not a finalizer"); + pub fn ${classSymbolName(typeName, "finalize")}(thisValue: *${typeName}) callconv(JSC.conv) void { + if (comptime Environment.enable_logs) zig("~${typeName} 0x{x:8}", .{@intFromPtr(thisValue)}); + @call(.always_inline, ${typeName}.finalize, .{thisValue}); } `; } - [...Object.values(proto)].forEach(({ getter, setter, accessor, fn, this: thisValue = false, cache, DOMJIT }) => { - if (accessor) { - getter = accessor.getter; - setter = accessor.setter; - } - - if (getter) { - if (thisValue) { - output += ` - if (@TypeOf(${typeName}.${getter}) != GetterTypeWithThisValue) - @compileLog("Expected ${typeName}.${getter} to be a getter with thisValue");`; - } else { - output += ` - if (@TypeOf(${typeName}.${getter}) != GetterType) - @compileLog( - "Expected ${typeName}.${getter} to be a getter" - ); -`; - } - } - - if (setter) { - if (thisValue) { - output += ` - if (@TypeOf(${typeName}.${setter}) != SetterTypeWithThisValue) - @compileLog("Expected ${typeName}.${setter} to be a setter with thisValue");`; - } else { - output += ` - if (@TypeOf(${typeName}.${setter}) != SetterType) - @compileLog( - "Expected ${typeName}.${setter} to be a setter" - );`; - } - } - - if (fn) { - if (DOMJIT) { - output += ` - if (@TypeOf(${typeName}.${DOMJITName(fn)}) != ${ZigDOMJITFunctionType(typeName, DOMJIT)}) - @compileLog( - "Expected ${typeName}.${DOMJITName(fn)} to be a DOMJIT function" - );`; - } - - output += ` - if (@TypeOf(${typeName}.${fn}) != CallbackType) - @compileLog( - "Expected ${typeName}.${fn} to be a callback but received " ++ @typeName(@TypeOf(${typeName}.${fn})) - );`; - } - }); - - [...Object.values(klass)].forEach(({ getter, setter, accessor, fn }) => { - if (accessor) { - getter = accessor.getter; - setter = accessor.setter; - } - - if (getter) { - output += ` - if (@TypeOf(${typeName}.${getter}) != StaticGetterType) - @compileLog( - "Expected ${typeName}.${getter} to be a static getter" - ); -`; - } - - if (setter) { - output += ` - if (@TypeOf(${typeName}.${setter}) != StaticSetterType) - @compileLog( - "Expected ${typeName}.${setter} to be a static setter" - );`; - } - - if (fn) { - output += ` - if (@TypeOf(${typeName}.${fn}) != StaticCallbackType) - @compileLog( - "Expected ${typeName}.${fn} to be a static callback" - );`; - } - }); - - if (!!call) { + if (construct && !noConstructor) { + exports.set("construct", classSymbolName(typeName, "construct")); output += ` - if (@TypeOf(${typeName}.call) != StaticCallbackType) - @compileLog( - "Expected ${typeName}.call to be a static callback" - );`; + pub fn ${classSymbolName(typeName, "construct")}(globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(JSC.conv) ?*${typeName} { + if (comptime Environment.enable_logs) zig("new ${typeName}({})", .{callFrame}); + return @call(.always_inline, ${typeName}.constructor, .{globalObject, callFrame}); + } + `; } - return output; + if (call) { + exports.set("call", classSymbolName(typeName, "call")); + output += ` + pub fn ${classSymbolName(typeName, "call")}(globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { + if (comptime Environment.enable_logs) zig("${typeName}({})", .{callFrame}); + return @call(.always_inline, ${typeName}.call, .{globalObject, callFrame}); + } + `; + } + + if (getInternalProperties) { + exports.set("getInternalProperties", classSymbolName(typeName, "getInternalProperties")); + output += ` + pub fn ${classSymbolName(typeName, "getInternalProperties")}(thisValue: *${typeName}, globalObject: *JSC.JSGlobalObject, thisValue: JSC.JSValue) callconv(JSC.conv) JSC.JSValue { + if (comptime Environment.enable_logs) JSC.markBinding(@src()); + return @call(.always_inline, ${typeName}.getInternalProperties, .{thisValue, globalObject, thisValue}); + } + `; + } + + { + const exportNames = name => zigExportName(exports, name => protoSymbolName(typeName, name), proto[name]); + for (const name in proto) { + const { getter, setter, accessor, fn, this: thisValue = false, cache, DOMJIT } = proto[name]; + const names = exportNames(name); + if (names.getter) { + output += ` + pub fn ${names.getter}(this: *${typeName}, ${thisValue ? "thisValue: JSC.JSValue," : ""} globalObject: *JSC.JSGlobalObject) callconv(JSC.conv) JSC.JSValue { + if (comptime Environment.enable_logs) zig("get ${typeName}.${name}", .{}); + return @call(.always_inline, ${typeName}.${getter}, .{this, ${thisValue ? "thisValue," : ""} globalObject}); + } + `; + } + + if (names.setter) { + output += ` + pub fn ${names.setter}(this: *${typeName}, ${thisValue ? "thisValue: JSC.JSValue," : ""} globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) callconv(JSC.conv) bool { + if (comptime Environment.enable_logs) zig("set ${typeName}.${name} = {}", .{value}); + return @call(.always_inline, ${typeName}.${setter}, .{this, ${thisValue ? "thisValue," : ""} globalObject, value}); + } + `; + } + + if (names.fn) { + if (names.DOMJIT) { + const { args, returns } = DOMJIT; + output += ` + pub fn ${names.DOMJIT}(thisValue: *${typeName}, globalObject: *JSC.JSGlobalObject, ${args + .map(ZigDOMJITArgTypeDefinition) + .join(", ")}) callconv(JSC.conv) JSC.JSValue { + return @call(.always_inline, ${typeName}.${DOMJITName(fn)}, .{thisValue, globalObject, ${args.map((_, i) => `arg${i}`).join(", ")}}); + } + `; + } + + output += ` + pub fn ${names.fn}(thisValue: *${typeName}, globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { + if (comptime Environment.enable_logs) zig("${typeName}.${name}({})", .{callFrame}); + return @call(.always_inline, ${typeName}.${fn}, .{thisValue, globalObject, callFrame}); + } + `; + } + } + } + + { + const exportNames = name => zigExportName(exports, name => classSymbolName(typeName, name), klass[name]); + for (const name in klass) { + const { getter, setter, accessor, fn, this: thisValue = true, cache, DOMJIT } = klass[name]; + const names = exportNames(name); + if (names.getter) { + output += ` + pub fn ${names.getter}(globalObject: *JSC.JSGlobalObject, ${thisValue ? "thisValue: JSC.JSValue," : ""} propertyName: JSC.JSValue) callconv(JSC.conv) JSC.JSValue { + if (comptime Environment.enable_logs) JSC.markBinding(@src()); + return @call(.always_inline, ${typeName}.${getter}, .{globalObject, ${thisValue ? "thisValue," : ""} propertyName}); + } + `; + } + + if (names.setter) { + output += ` + pub fn ${names.setter}(globalObject: *JSC.JSGlobalObject, thisValue: JSC.JSValue, target: JSC.JSValue) callconv(JSC.conv) bool { + if (comptime Environment.enable_logs) JSC.markBinding(@src()); + return @call(.always_inline, ${typeName}.${setter || accessor.setter}, .{thisValue, globalObject, target}); + } + `; + } + + if (names.fn) { + if (DOMJIT) { + const { args, returns } = DOMJIT; + + output += ` + pub fn ${names.DOMJIT}(globalObject: *JSC.JSGlobalObject, thisValue: JSC.JSValue, ${args + .map(ZigDOMJITArgTypeDefinition) + .join(", ")}) callconv(JSC.conv) JSC.JSValue { + if (comptime Environment.enable_logs) JSC.markBinding(@src()); + return @call(.always_inline, ${typeName}.${DOMJITName(fn)}, .{thisValue, globalObject, ${args.map((_, i) => `arg${i}`).join(", ")}}); + } + `; + } + + output += ` + pub fn ${names.fn}(globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { + if (comptime Environment.enable_logs) JSC.markBinding(@src()); + return @call(.always_inline, ${typeName}.${fn}, .{globalObject, callFrame}); + } + `; + } + } + } + + if (structuredClone) { + exports.set("structuredClone", symbolName(typeName, "onStructuredCloneSerialize")); + output += ` + pub fn ${symbolName(typeName, "onStructuredCloneSerialize")}(thisValue: *${typeName}, globalObject: *JSC.JSGlobalObject, ctx: *anyopaque, writeBytes: WriteBytesFn) callconv(JSC.conv) void { + if (comptime Environment.enable_logs) JSC.markBinding(@src()); + @call(.always_inline, ${typeName}.onStructuredCloneSerialize, .{thisValue, globalObject, ctx, writeBytes}); + } + `; + + if (structuredClone === "transferable") { + exports.set("structuredClone_transferable", symbolName(typeName, "onStructuredCloneTransfer")); + output += ` + pub fn ${exports.get("structuredClone_transferable")}(thisValue: *${typeName}, globalObject: *JSC.JSGlobalObject, ctx: *anyopaque, write: WriteBytesFn) callconv(JSC.conv) void { + if (comptime Environment.enable_logs) JSC.markBinding(@src()); + @call(.always_inline, ${typeName}.onStructuredCloneTransfer, .{thisValue, globalObject, ctx, write}); + } + `; + } + + exports.set("structuredCloneDeserialize", symbolName(typeName, "onStructuredCloneDeserialize")); + + output += ` + pub fn ${symbolName(typeName, "onStructuredCloneDeserialize")}(globalObject: *JSC.JSGlobalObject, ptr: [*]u8, end: [*]u8) callconv(JSC.conv) JSC.JSValue { + if (comptime Environment.enable_logs) JSC.markBinding(@src()); + return @call(.always_inline, ${typeName}.onStructuredCloneDeserialize, .{globalObject, ptr, end}); + } + `; + } else { + output += ` + pub fn ${symbolName(typeName, "onStructuredCloneSerialize")}(thisValue: *${typeName}, globalObject: *JSC.JSGlobalObject, ctx: *anyopaque, writeBytes: WriteBytesFn) callconv(JSC.conv) void { + _ = thisValue; + _ = globalObject; + _ = ctx; + _ = writeBytes; + @compileLog("onStructuredCloneSerialize not implemented for ${typeName}"); + } + `; + } + + return ( + output.trim() + + ` + }; + comptime { +${[...exports.values()].map(name => ` @export(JavaScriptCoreBindings.${name}, .{ .name = "${name}" });`).join("\n")} + }` + ); } return ` pub const ${className(typeName)} = struct { const ${typeName} = Classes.${typeName}; - const GetterType = fn(*${typeName}, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue; - const GetterTypeWithThisValue = fn(*${typeName}, JSC.JSValue, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue; - const SetterType = fn(*${typeName}, *JSC.JSGlobalObject, JSC.JSValue) callconv(.C) bool; - const SetterTypeWithThisValue = fn(*${typeName}, JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) callconv(.C) bool; - const CallbackType = fn(*${typeName}, *JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) JSC.JSValue; /// Return the pointer to the wrapped object. /// If the object does not match the type, return null. @@ -1818,31 +1885,20 @@ pub const ${className(typeName)} = struct { bun.assert(${symbolName(typeName, "dangerouslySetPtr")}(value, null)); } - extern fn ${symbolName(typeName, "fromJS")}(JSC.JSValue) ?*${typeName}; - extern fn ${symbolName(typeName, "fromJSDirect")}(JSC.JSValue) ?*${typeName}; - extern fn ${symbolName(typeName, "getConstructor")}(*JSC.JSGlobalObject) JSC.JSValue; - - extern fn ${symbolName(typeName, "create")}(globalObject: *JSC.JSGlobalObject, ptr: ?*${typeName}) JSC.JSValue; + extern fn ${symbolName(typeName, "fromJS")}(JSC.JSValue) callconv(JSC.conv) ?*${typeName}; + extern fn ${symbolName(typeName, "fromJSDirect")}(JSC.JSValue) callconv(JSC.conv) ?*${typeName}; + extern fn ${symbolName(typeName, "getConstructor")}(*JSC.JSGlobalObject) callconv(JSC.conv) JSC.JSValue; + extern fn ${symbolName(typeName, "create")}(globalObject: *JSC.JSGlobalObject, ptr: ?*${typeName}) callconv(JSC.conv) JSC.JSValue; /// Create a new instance of ${typeName} without validating it works. pub const toJSUnchecked = ${symbolName(typeName, "create")}; - extern fn ${typeName}__dangerouslySetPtr(JSC.JSValue, ?*${typeName}) bool; + extern fn ${typeName}__dangerouslySetPtr(JSC.JSValue, ?*${typeName}) callconv(JSC.conv) bool; - ${renderedCallbacks} +${renderMethods()} - comptime { - ${typeCheck()} - if (!JSC.is_bindgen) { -${[...exports] - .sort(([a], [b]) => a.localeCompare(b)) - .map(([internalName, externalName]) => `@export(${typeName}.${internalName}, .{.name = "${externalName}"});`) - .join("\n ")} - } - } }; - `; } @@ -1903,7 +1959,7 @@ using namespace JSC; `, ]; -const GENERATED_CLASSES_IMPL_HEADER = ` +const GENERATED_CLASSES_IMPL_HEADER_PRE = ` // GENERATED CODE - DO NOT MODIFY BY HAND // Generated by make codegen #include "root.h" @@ -1928,14 +1984,20 @@ const GENERATED_CLASSES_IMPL_HEADER = ` #include "JSDOMConvertBufferSource.h" #include "ZigGeneratedClasses.h" +#if !OS(WINDOWS) +#define JSC_CALLCONV "C" +#else +#define JSC_CALLCONV "C" SYSV_ABI +#endif +`; +const GENERATED_CLASSES_IMPL_HEADER_POST = ` namespace WebCore { using namespace JSC; using namespace Zig; - `; const GENERATED_CLASSES_IMPL_FOOTER = ` @@ -1987,10 +2049,12 @@ const JSC = bun.JSC; const Classes = JSC.GeneratedClassesList; const Environment = bun.Environment; const std = @import("std"); +const zig = bun.Output.scoped(.zig, true); -pub const StaticGetterType = fn(*JSC.JSGlobalObject, JSC.JSValue, JSC.JSValue) callconv(.C) JSC.JSValue; -pub const StaticSetterType = fn(*JSC.JSGlobalObject, JSC.JSValue, JSC.JSValue, JSC.JSValue) callconv(.C) bool; -pub const StaticCallbackType = fn(*JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) JSC.JSValue; +pub const StaticGetterType = fn(*JSC.JSGlobalObject, JSC.JSValue, JSC.JSValue) callconv(JSC.conv) JSC.JSValue; +pub const StaticSetterType = fn(*JSC.JSGlobalObject, JSC.JSValue, JSC.JSValue, JSC.JSValue) callconv(JSC.conv) bool; +pub const StaticCallbackType = JSC.JSHostFunctionType; +pub const WriteBytesFn = *const fn(*anyopaque, ptr: [*]const u8, len: u32) callconv(JSC.conv) void; `; @@ -2023,12 +2087,13 @@ for (const obj of classes) { const GENERATED_CLASSES_FOOTER = ` +typedef SYSV_ABI void (*CppStructuredCloneableSerializeFunction)(CloneSerializer*, const uint8_t*, uint32_t); +typedef SYSV_ABI void (*ZigStructuredCloneableSerializeFunction)(void*, JSC::JSGlobalObject*, CloneSerializer*, CppStructuredCloneableSerializeFunction); + class StructuredCloneableSerialize { public: - - void (*cppWriteBytes)(CloneSerializer*, const uint8_t*, uint32_t); - - std::function zigFunction; + CppStructuredCloneableSerializeFunction cppWriteBytes; + ZigStructuredCloneableSerializeFunction zigFunction; uint8_t tag; @@ -2117,9 +2182,13 @@ if (!process.env.ONLY_ZIG) { ...allHeaders, GENERATED_CLASSES_FOOTER, ]); + + const allImpls = classes.map(a => generateImpl(a.name, a)); await writeIfNotChanged(`${outBase}/ZigGeneratedClasses.cpp`, [ - GENERATED_CLASSES_IMPL_HEADER, - ...classes.map(a => generateImpl(a.name, a)), + GENERATED_CLASSES_IMPL_HEADER_PRE, + externs.trim(), + GENERATED_CLASSES_IMPL_HEADER_POST, + allImpls.join("\n"), writeCppSerializers(classes), GENERATED_CLASSES_IMPL_FOOTER, ]); diff --git a/src/codegen/js2native-generator.ts b/src/codegen/generate-js2native.ts similarity index 71% rename from src/codegen/js2native-generator.ts rename to src/codegen/generate-js2native.ts index 09c71f8217..4aefabe81e 100644 --- a/src/codegen/js2native-generator.ts +++ b/src/codegen/generate-js2native.ts @@ -114,39 +114,53 @@ export function getJS2NativeCPP() { ...new Set(nativeCalls.filter(x => x.filename.endsWith(".cpp")).map(x => x.filename.replace(/.cpp$/, ".h"))), ]; + const externs: string[] = []; + + const nativeCallStrings = nativeCalls + .filter(x => x.type === "zig") + .flatMap( + call => ( + externs.push(`extern "C" SYSV_ABI JSC::EncodedJSValue ${symbol(call)}_workaround(Zig::GlobalObject*);` + "\n"), + [ + `JSC::JSValue ${symbol(call)}(Zig::GlobalObject* global) {`, + ` return JSValue::decode(${symbol(call)}_workaround(global));`, + `}` + "\n\n", + ] + ), + ); + + const wrapperCallStrings = wrapperCalls.map(x => { + if (x.wrap_kind === "new-function") { + return [ + (x.type === "zig" && + externs.push( + `BUN_DECLARE_HOST_FUNCTION(${symbol({ + type: "zig", + symbol: x.symbol_taget, + })});`, + ), + "") || "", + `JSC::JSValue ${x.symbol_generated}(Zig::GlobalObject* globalObject) {`, + ` return JSC::JSFunction::create(globalObject->vm(), globalObject, ${x.call_length}, ${JSON.stringify( + x.display_name, + )}_s, ${symbol({ type: x.type, symbol: x.symbol_taget })}, JSC::ImplementationVisibility::Public);`, + `}`, + ].join("\n"); + } + throw new Error(`Unknown wrap kind ${x.wrap_kind}`); + }); + return [ `#pragma once`, + `#include "root.h"`, ...files.map(filename => `#include ${JSON.stringify(filename)}`), - "namespace JS2NativeGenerated {", + ...externs, + "\n" + "namespace JS2NativeGenerated {", "using namespace Bun;", "using namespace JSC;", - "using namespace WebCore;", - ...nativeCalls - .filter(x => x.type === "zig") - .flatMap(call => [ - `extern "C" JSC::EncodedJSValue ${symbol(call)}_workaround(Zig::GlobalObject*);`, - `JSC::JSValue ${symbol(call)}(Zig::GlobalObject* global) {`, - ` return JSValue::decode(${symbol(call)}_workaround(global));`, - `}`, - ]), - ...wrapperCalls.map(x => { - if (x.wrap_kind === "new-function") { - return [ - x.type === "zig" - ? `extern "C" JSC::EncodedJSValue ${symbol({ - type: "zig", - symbol: x.symbol_taget, - })}(JSC::JSGlobalObject*, JSC::CallFrame*);` - : "", - `JSC::JSValue ${x.symbol_generated}(Zig::GlobalObject* globalObject) {`, - ` return JSC::JSFunction::create(globalObject->vm(), globalObject, ${x.call_length}, ${JSON.stringify( - x.display_name, - )}_s, ${symbol({ type: x.type, symbol: x.symbol_taget })}, JSC::ImplementationVisibility::Public);`, - `}`, - ].join("\n"); - } - throw new Error(`Unknown wrap kind ${x.wrap_kind}`); - }), + "using namespace WebCore;" + "\n", + ...nativeCallStrings, + ...wrapperCallStrings, `typedef JSC::JSValue (*JS2NativeFunction)(Zig::GlobalObject*);`, `static JS2NativeFunction js2nativePointers[] = {`, ...nativeCalls.map(x => ` ${cppPointer(x)},`), @@ -158,15 +172,15 @@ export function getJS2NativeCPP() { export function getJS2NativeZig(gs2NativeZigPath: string) { return [ - "//! This file is generated by src/codegen/js2native-generator.ts based on seen calls to the $zig() JS macro", + "//! This file is generated by src/codegen/generate-js2native.ts based on seen calls to the $zig() JS macro", `const JSC = @import("root").bun.JSC;`, ...nativeCalls .filter(x => x.type === "zig") .flatMap(call => [ - `export fn ${symbol(call)}_workaround(global: u64) callconv(.C) JSC.JSValue {`, + `export fn ${symbol(call)}_workaround(global: *JSC.JSGlobalObject) callconv(JSC.conv) JSC.JSValue {`, ` return @import(${JSON.stringify(path.relative(path.dirname(gs2NativeZigPath), call.filename))}).${ call.symbol - }(@ptrFromInt(global));`, + }(global);`, "}", ]), ...wrapperCalls @@ -175,10 +189,10 @@ export function getJS2NativeZig(gs2NativeZigPath: string) { `export fn ${symbol({ type: "zig", symbol: x.symbol_taget, - })}(global: *JSC.JSGlobalObject, call_frame: *JSC.CallFrame) callconv(.C) JSC.JSValue {`, - ` return @import(${JSON.stringify(path.relative(path.dirname(gs2NativeZigPath), x.filename))}).${ - x.symbol_taget - }(global, call_frame);`, + })}(global: *JSC.JSGlobalObject, call_frame: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue {`, + ` + const function = @import(${JSON.stringify(path.relative(path.dirname(gs2NativeZigPath), x.filename))}); + return @call(.always_inline, function.${x.symbol_taget}, .{global, call_frame});`, "}", ]), "comptime {", diff --git a/src/codegen/helpers.ts b/src/codegen/helpers.ts index ab4a51668c..04f436c25f 100644 --- a/src/codegen/helpers.ts +++ b/src/codegen/helpers.ts @@ -79,6 +79,10 @@ export function writeIfNotChanged(file: string, contents: string) { fs.mkdirSync(path.dirname(file), { recursive: true }); fs.writeFileSync(file, contents); } + + if (fs.readFileSync(file, "utf8") !== contents) { + throw new Error(`Failed to write file ${file}`); + } } export function readdirRecursiveWithExclusionsAndExtensionsSync( diff --git a/src/codegen/replacements.ts b/src/codegen/replacements.ts index 79500c57db..35b005aea9 100644 --- a/src/codegen/replacements.ts +++ b/src/codegen/replacements.ts @@ -1,6 +1,6 @@ import { LoaderKeys } from "../api/schema"; import { sliceSourceCode } from "./builtin-parser"; -import { registerNativeCall } from "./js2native-generator"; +import { registerNativeCall } from "./generate-js2native"; // This is a list of extra syntax replacements to do. Kind of like macros // These are only run on code itself, not string contents or comments. diff --git a/src/compile_target.zig b/src/compile_target.zig index 240c824bcc..fb7328b909 100644 --- a/src/compile_target.zig +++ b/src/compile_target.zig @@ -137,7 +137,7 @@ const HTTP = bun.http; const MutableString = bun.MutableString; const Global = bun.Global; pub fn downloadToPath(this: *const CompileTarget, env: *bun.DotEnv.Loader, allocator: std.mem.Allocator, dest_z: [:0]const u8) !void { - try HTTP.HTTPThread.init(); + HTTP.HTTPThread.init(); var refresher = bun.Progress{}; { diff --git a/src/crash_handler.zig b/src/crash_handler.zig index 644159b424..3bdc961b9c 100644 --- a/src/crash_handler.zig +++ b/src/crash_handler.zig @@ -1488,17 +1488,17 @@ pub const js_bindings = struct { return obj; } - pub fn jsGetMachOImageZeroOffset(_: *bun.JSC.JSGlobalObject, _: *bun.JSC.CallFrame) callconv(.C) bun.JSC.JSValue { + pub fn jsGetMachOImageZeroOffset(_: *bun.JSC.JSGlobalObject, _: *bun.JSC.CallFrame) JSValue { if (!bun.Environment.isMac) return .undefined; const header = std.c._dyld_get_image_header(0) orelse return .undefined; const base_address = @intFromPtr(header); const vmaddr_slide = std.c._dyld_get_image_vmaddr_slide(0); - return bun.JSC.JSValue.jsNumber(base_address - vmaddr_slide); + return JSValue.jsNumber(base_address - vmaddr_slide); } - pub fn jsSegfault(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn jsSegfault(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { @setRuntimeSafety(false); const ptr: [*]align(1) u64 = @ptrFromInt(0xDEADBEEF); ptr[0] = 0xDEADBEEF; @@ -1506,19 +1506,19 @@ pub const js_bindings = struct { return .undefined; } - pub fn jsPanic(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn jsPanic(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { bun.crash_handler.panicImpl("invoked crashByPanic() handler", null, null); } - pub fn jsRootError(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn jsRootError(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { bun.crash_handler.handleRootError(error.Test, null); } - pub fn jsOutOfMemory(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn jsOutOfMemory(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { bun.outOfMemory(); } - pub fn jsGetFeaturesAsVLQ(global: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn jsGetFeaturesAsVLQ(global: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { const bits = bun.Analytics.packedFeatures(); var buf = std.BoundedArray(u8, 16){}; writeU64AsTwoVLQs(buf.writer(), @bitCast(bits)) catch { @@ -1528,7 +1528,7 @@ pub const js_bindings = struct { return bun.String.createLatin1(buf.slice()).toJS(global); } - pub fn jsGetFeatureData(global: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn jsGetFeatureData(global: *JSC.JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { const obj = JSValue.createEmptyObject(global, 5); const list = bun.Analytics.packed_features_list; const array = JSValue.createEmptyArray(global, list.len); @@ -1539,7 +1539,7 @@ pub const js_bindings = struct { obj.put(global, JSC.ZigString.static("version"), bun.String.init(Global.package_json_version).toJS(global)); obj.put(global, JSC.ZigString.static("is_canary"), JSC.JSValue.jsBoolean(bun.Environment.is_canary)); obj.put(global, JSC.ZigString.static("revision"), bun.String.init(bun.Environment.git_sha).toJS(global)); - obj.put(global, JSC.ZigString.static("generated_at"), bun.JSC.JSValue.jsNumberFromInt64(@max(std.time.milliTimestamp(), 0))); + obj.put(global, JSC.ZigString.static("generated_at"), JSValue.jsNumberFromInt64(@max(std.time.milliTimestamp(), 0))); return obj; } }; diff --git a/src/deps/c_ares.zig b/src/deps/c_ares.zig index cf5501b18b..06871361cc 100644 --- a/src/deps/c_ares.zig +++ b/src/deps/c_ares.zig @@ -1557,7 +1557,7 @@ pub const ares_addr_port_node = struct_ares_addr_port_node; pub export fn Bun__canonicalizeIP( ctx: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, -) callconv(.C) JSC.JSValue { +) callconv(JSC.conv) JSC.JSValue { JSC.markBinding(@src()); const globalThis = ctx.ptr(); diff --git a/src/fmt.zig b/src/fmt.zig index f4d9ccde8a..8bb95896be 100644 --- a/src/fmt.zig +++ b/src/fmt.zig @@ -946,7 +946,7 @@ pub const QuickAndDirtyJavaScriptSyntaxHighlighter = struct { } /// Function for testing in highlighter.test.ts - pub fn jsFunctionSyntaxHighlight(globalThis: *bun.JSC.JSGlobalObject, callframe: *bun.JSC.CallFrame) callconv(.C) bun.JSC.JSValue { + pub fn jsFunctionSyntaxHighlight(globalThis: *bun.JSC.JSGlobalObject, callframe: *bun.JSC.CallFrame) callconv(bun.JSC.conv) bun.JSC.JSValue { const args = callframe.arguments(1); if (args.len < 1) { globalThis.throwNotEnoughArguments("code", 1, 0); diff --git a/src/generated_versions_list.zig b/src/generated_versions_list.zig index c6354e9c4c..bfc73aaff6 100644 --- a/src/generated_versions_list.zig +++ b/src/generated_versions_list.zig @@ -4,7 +4,7 @@ pub const boringssl = "29a2cd359458c9384694b75456026e4b57e3e567"; pub const libarchive = "313aa1fa10b657de791e3202c168a6c833bc3543"; pub const mimalloc = "4c283af60cdae205df5a872530c77e2a6a307d43"; pub const picohttpparser = "066d2b1e9ab820703db0837a7255d92d30f0c9f5"; -pub const webkit = "64d04ec1a65d91326c5f2298b9c7d05b56125252"; +pub const webkit = "00e8a32b3ca72cefae683cd65140428ff1d4ff09"; pub const zig = @import("std").fmt.comptimePrint("{}", .{@import("builtin").zig_version}); pub const zlib = "886098f3f339617b4243b286f5ed364b9989e245"; pub const tinycc = "ab631362d839333660a265d3084d8ff060b96753"; diff --git a/src/http.zig b/src/http.zig index e320919b4f..026abdb844 100644 --- a/src/http.zig +++ b/src/http.zig @@ -748,8 +748,6 @@ const Queue = UnboundedQueue(AsyncHTTP, .next); const ShutdownQueue = UnboundedQueue(AsyncHTTP, .next); pub const HTTPThread = struct { - var http_thread_loaded: std.atomic.Value(bool) = std.atomic.Value(bool).init(false); - loop: *JSC.MiniEventLoop, http_context: NewHTTPContext(false), https_context: NewHTTPContext(true), @@ -769,11 +767,7 @@ pub const HTTPThread = struct { const threadlog = Output.scoped(.HTTPThread, true); - pub fn init() !void { - if (http_thread_loaded.swap(true, .seq_cst)) { - return; - } - + fn initOnce() void { http_thread = .{ .loop = undefined, .http_context = .{ @@ -785,15 +779,20 @@ pub const HTTPThread = struct { .timer = std.time.Timer.start() catch unreachable, }; - const thread = try std.Thread.spawn( + const thread = std.Thread.spawn( .{ .stack_size = bun.default_thread_stack_size, }, onStart, .{}, - ); + ) catch |err| Output.panic("Failed to start HTTP Client thread: {s}", .{@errorName(err)}); thread.detach(); } + var init_once = std.once(initOnce); + + pub fn init() void { + init_once.call(); + } pub fn onStart() void { Output.Source.configureNamedThread("HTTP Client"); @@ -2045,7 +2044,7 @@ pub const AsyncHTTP = struct { } pub fn sendSync(this: *AsyncHTTP, comptime _: bool) anyerror!picohttp.Response { - try HTTPThread.init(); + HTTPThread.init(); var ctx = try bun.default_allocator.create(SingleHTTPChannel); ctx.* = SingleHTTPChannel.init(); diff --git a/src/install/install.zig b/src/install/install.zig index b35b2c7bc9..8ea43afecb 100644 --- a/src/install/install.zig +++ b/src/install/install.zig @@ -8196,7 +8196,7 @@ pub const PackageManager = struct { comptime subcommand: Subcommand, ) !*PackageManager { // assume that spawning a thread will take a lil so we do that asap - try HTTP.HTTPThread.init(); + HTTP.HTTPThread.init(); if (cli.global) { var explicit_global_dir: string = ""; @@ -14195,7 +14195,7 @@ pub const bun_install_js_bindings = struct { return obj; } - pub fn jsParseLockfile(globalObject: *JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue { + pub fn jsParseLockfile(globalObject: *JSGlobalObject, callFrame: *JSC.CallFrame) JSValue { const allocator = bun.default_allocator; var log = logger.Log.init(allocator); defer log.deinit(); diff --git a/src/install/semver.zig b/src/install/semver.zig index 3edd2fca55..7f4ca1861c 100644 --- a/src/install/semver.zig +++ b/src/install/semver.zig @@ -2497,7 +2497,7 @@ pub const SemverObject = struct { pub fn order( globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { var arena = std.heap.ArenaAllocator.init(bun.default_allocator); defer arena.deinit(); var stack_fallback = std.heap.stackFallback(512, arena.allocator()); @@ -2549,7 +2549,7 @@ pub const SemverObject = struct { pub fn satisfies( globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { var arena = std.heap.ArenaAllocator.init(bun.default_allocator); defer arena.deinit(); var stack_fallback = std.heap.stackFallback(512, arena.allocator()); diff --git a/src/io/io.zig b/src/io/io.zig index 240eba96ec..db39594351 100644 --- a/src/io/io.zig +++ b/src/io/io.zig @@ -25,40 +25,43 @@ pub const Loop = struct { active: usize = 0, var loop: Loop = undefined; - var has_loaded_loop: bool = false; + + fn load() void { + loop = Loop{ + .waker = bun.Async.Waker.init() catch @panic("failed to initialize waker"), + }; + if (comptime Environment.isLinux) { + loop.epoll_fd = bun.toFD(std.posix.epoll_create1(std.os.linux.EPOLL.CLOEXEC | 0) catch @panic("Failed to create epoll file descriptor")); + + { + var epoll = std.mem.zeroes(std.os.linux.epoll_event); + epoll.events = std.os.linux.EPOLL.IN | std.os.linux.EPOLL.ERR | std.os.linux.EPOLL.HUP; + epoll.data.ptr = @intFromPtr(&loop); + const rc = std.os.linux.epoll_ctl(loop.epoll_fd.cast(), std.os.linux.EPOLL.CTL_ADD, loop.waker.getFd().cast(), &epoll); + + switch (bun.C.getErrno(rc)) { + .SUCCESS => {}, + else => |err| bun.Output.panic("Failed to wait on epoll {s}", .{@tagName(err)}), + } + } + } + var thread = std.Thread.spawn(.{ + .allocator = bun.default_allocator, + + // smaller thread, since it's not doing much. + .stack_size = 1024 * 1024 * 2, + }, onSpawnIOThread, .{}) catch @panic("Failed to spawn IO watcher thread"); + thread.detach(); + } + var once = std.once(load); pub fn get() *Loop { if (Environment.isWindows) { @panic("Do not use this API on windows"); } - if (!@atomicRmw(bool, &has_loaded_loop, std.builtin.AtomicRmwOp.Xchg, true, .monotonic)) { - loop = Loop{ - .waker = bun.Async.Waker.init() catch @panic("failed to initialize waker"), - }; - if (comptime Environment.isLinux) { - loop.epoll_fd = bun.toFD(std.posix.epoll_create1(std.os.linux.EPOLL.CLOEXEC | 0) catch @panic("Failed to create epoll file descriptor")); + once.call(); - { - var epoll = std.mem.zeroes(std.os.linux.epoll_event); - epoll.events = std.os.linux.EPOLL.IN | std.os.linux.EPOLL.ERR | std.os.linux.EPOLL.HUP; - epoll.data.ptr = @intFromPtr(&loop); - const rc = std.os.linux.epoll_ctl(loop.epoll_fd.cast(), std.os.linux.EPOLL.CTL_ADD, loop.waker.getFd().cast(), &epoll); - - switch (bun.C.getErrno(rc)) { - .SUCCESS => {}, - else => |err| bun.Output.panic("Failed to wait on epoll {s}", .{@tagName(err)}), - } - } - } - var thread = std.Thread.spawn(.{ - .allocator = bun.default_allocator, - - // smaller thread, since it's not doing much. - .stack_size = 1024 * 1024 * 2, - }, onSpawnIOThread, .{}) catch @panic("Failed to spawn IO watcher thread"); - thread.detach(); - } return &loop; } diff --git a/src/io/io_darwin.cpp b/src/io/io_darwin.cpp index 05f7a0d943..3f4744454c 100644 --- a/src/io/io_darwin.cpp +++ b/src/io/io_darwin.cpp @@ -96,7 +96,7 @@ extern "C" bool io_darwin_schedule_wakeup(mach_port_t waker) { ); switch (kr) { - case KERN_SUCCESS: { + case MACH_MSG_SUCCESS: { return true; } @@ -112,7 +112,7 @@ extern "C" bool io_darwin_schedule_wakeup(mach_port_t waker) { } default: { - ASSERT_NOT_REACHED_WITH_MESSAGE("mach_msg failed with %d", kr); + ASSERT_NOT_REACHED_WITH_MESSAGE("mach_msg failed with %x", kr); return false; } } diff --git a/src/js/node/zlib.ts b/src/js/node/zlib.ts index 65a57448b9..81eef500ac 100644 --- a/src/js/node/zlib.ts +++ b/src/js/node/zlib.ts @@ -4,8 +4,8 @@ const stream = require("node:stream"); const ObjectSetPrototypeOf = Object.setPrototypeOf; -const createBrotliEncoder = $zig("node_zlib_binding.zig", "createBrotliEncoder"); -const createBrotliDecoder = $zig("node_zlib_binding.zig", "createBrotliDecoder"); +const createBrotliEncoder = $newZigFunction("js_brotli.zig", "BrotliEncoder.create", 2); +const createBrotliDecoder = $newZigFunction("js_brotli.zig", "BrotliDecoder.create", 2); function brotliCompress(buffer, opts, callback) { if (typeof opts === "function") { diff --git a/src/jsc.zig b/src/jsc.zig index 872a47e5f6..842adb4c93 100644 --- a/src/jsc.zig +++ b/src/jsc.zig @@ -49,8 +49,8 @@ pub const API = struct { pub const UDPSocket = @import("./bun.js/api/bun/udp_socket.zig").UDPSocket; pub const Listener = @import("./bun.js/api/bun/socket.zig").Listener; pub const H2FrameParser = @import("./bun.js/api/bun/h2_frame_parser.zig").H2FrameParser; - pub const BrotliEncoder = @import("./bun.js/api/brotli.zig").BrotliEncoder; - pub const BrotliDecoder = @import("./bun.js/api/brotli.zig").BrotliDecoder; + pub const BrotliEncoder = @import("./bun.js/api/js_brotli.zig").BrotliEncoder; + pub const BrotliDecoder = @import("./bun.js/api/js_brotli.zig").BrotliDecoder; }; pub const DNS = @import("./bun.js/api/bun/dns_resolver.zig"); pub const FFI = @import("./bun.js/api/ffi.zig").FFI; @@ -67,12 +67,6 @@ pub const Node = struct { }; }; -comptime { - if (!is_bindgen) { - @export(Node.Util.parseArgs, .{ .name = "Bun__NodeUtil__jsParseArgs" }); - } -} - const std = @import("std"); const Syscall = @import("./sys.zig"); const Output = @import("./output.zig"); @@ -90,10 +84,6 @@ pub inline fn markBinding(src: std.builtin.SourceLocation) void { pub const Subprocess = API.Bun.Subprocess; pub const ResourceUsage = API.Bun.ResourceUsage; -/// Generated code! To regenerate, run: -/// -/// make codegen -/// /// This file is generated by: /// 1. `bun src/bun.js/scripts/generate-classes.ts` /// 2. Scan for **/*.classes.ts files in src/bun.js/src @@ -114,3 +104,9 @@ pub const Codegen = struct { pub const GeneratedClassesList = @import("./bun.js/bindings/generated_classes_list.zig").Classes; pub const RuntimeTranspilerCache = @import("./bun.js/RuntimeTranspilerCache.zig").RuntimeTranspilerCache; + +/// The calling convention used for JavaScript functions <> Native +pub const conv = if (@import("root").bun.Environment.isWindows and @import("root").bun.Environment.isX64) + std.builtin.CallingConvention.SysV +else + std.builtin.CallingConvention.C; diff --git a/src/output.zig b/src/output.zig index 9ddaddc3d6..9ed0aac8e0 100644 --- a/src/output.zig +++ b/src/output.zig @@ -867,8 +867,6 @@ pub const DebugTimer = struct { if (comptime Environment.isDebug) { var timer = self.timer; w.print("{d:.3}ms", .{@as(f64, @floatFromInt(timer.read())) / std.time.ns_per_ms}) catch unreachable; - } else { - @compileError("DebugTimer.format() should only be called in debug mode"); } } }; diff --git a/src/patch.zig b/src/patch.zig index 950ab014c4..ab19217262 100644 --- a/src/patch.zig +++ b/src/patch.zig @@ -1091,7 +1091,7 @@ const PatchLinesParser = struct { }; pub const TestingAPIs = struct { - pub fn makeDiff(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn makeDiff(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const arguments_ = callframe.arguments(2); var arguments = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments_.slice()); @@ -1143,7 +1143,7 @@ pub const TestingAPIs = struct { } } }; - pub fn apply(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn apply(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { var args = switch (parseApplyArgs(globalThis, callframe)) { .err => |e| return e, .result => |a| a, @@ -1158,7 +1158,7 @@ pub const TestingAPIs = struct { return .true; } /// Used in JS tests, see `internal-for-testing.ts` and patch tests. - pub fn parse(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn parse(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const arguments_ = callframe.arguments(2); var arguments = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments_.slice()); diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index e9da354bfa..0ec56a6a7c 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -563,7 +563,7 @@ pub const Resolver = struct { pub fn getPackageManager(this: *Resolver) *PackageManager { return this.package_manager orelse brk: { - bun.HTTPThread.init() catch unreachable; + bun.HTTPThread.init(); const pm = PackageManager.initWithRuntime( this.log, this.opts.install, @@ -3333,7 +3333,7 @@ pub const Resolver = struct { }; } - pub export fn Resolver__nodeModulePathsForJS(globalThis: *bun.JSC.JSGlobalObject, callframe: *bun.JSC.CallFrame) callconv(.C) bun.JSC.JSValue { + pub export fn Resolver__nodeModulePathsForJS(globalThis: *bun.JSC.JSGlobalObject, callframe: *bun.JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { bun.JSC.markBinding(@src()); const argument: bun.JSC.JSValue = callframe.argument(0); @@ -3348,7 +3348,7 @@ pub const Resolver = struct { return nodeModulePathsJSValue(r, in_str, globalThis); } - pub export fn Resolver__propForRequireMainPaths(globalThis: *bun.JSC.JSGlobalObject) callconv(.C) bun.JSC.JSValue { + pub export fn Resolver__propForRequireMainPaths(globalThis: *bun.JSC.JSGlobalObject) callconv(.C) JSC.JSValue { bun.JSC.markBinding(@src()); const in_str = bun.String.createUTF8("."); diff --git a/src/shell/interpreter.zig b/src/shell/interpreter.zig index 33bad59d53..b61f7e8d18 100644 --- a/src/shell/interpreter.zig +++ b/src/shell/interpreter.zig @@ -664,7 +664,7 @@ pub const ParsedShellScript = struct { pub fn finalize( this: *ParsedShellScript, - ) callconv(.C) void { + ) void { this.this_jsvalue = .zero; log("ParsedShellScript(0x{x}) finalize", .{@intFromPtr(this)}); if (this.export_env) |*env| env.deinit(); @@ -676,7 +676,7 @@ pub const ParsedShellScript = struct { bun.destroy(this); } - pub fn setCwd(this: *ParsedShellScript, globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn setCwd(this: *ParsedShellScript, globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const arguments_ = callframe.arguments(2); var arguments = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments_.slice()); const str_js = arguments.nextEat() orelse { @@ -688,13 +688,13 @@ pub const ParsedShellScript = struct { return .undefined; } - pub fn setQuiet(this: *ParsedShellScript, _: *JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn setQuiet(this: *ParsedShellScript, _: *JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { log("Interpreter(0x{x}) setQuiet()", .{@intFromPtr(this)}); this.quiet = true; return .undefined; } - pub fn setEnv(this: *ParsedShellScript, globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn setEnv(this: *ParsedShellScript, globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { var env = if (this.export_env) |*env| brk: { @@ -741,7 +741,7 @@ pub const ParsedShellScript = struct { pub fn createParsedShellScript( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { var shargs = ShellArgs.init(); const arguments_ = callframe.arguments(2); @@ -1159,7 +1159,7 @@ pub const Interpreter = struct { pub fn createShellInterpreter( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSValue { + ) JSValue { const allocator = bun.default_allocator; const arguments_ = callframe.arguments(3); var arguments = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments_.slice()); @@ -1603,7 +1603,7 @@ pub const Interpreter = struct { return Maybe(void).success; } - pub fn runFromJS(this: *ThisInterpreter, globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn runFromJS(this: *ThisInterpreter, globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) JSValue { _ = callframe; // autofix if (this.setupIOBeforeRun().asErr()) |e| { @@ -1727,13 +1727,13 @@ pub const Interpreter = struct { this.allocator.destroy(this); } - pub fn setQuiet(this: *ThisInterpreter, _: *JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn setQuiet(this: *ThisInterpreter, _: *JSGlobalObject, _: *JSC.CallFrame) JSC.JSValue { log("Interpreter(0x{x}) setQuiet()", .{@intFromPtr(this)}); this.flags.quiet = true; return .undefined; } - pub fn setCwd(this: *ThisInterpreter, globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn setCwd(this: *ThisInterpreter, globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const value = callframe.argument(0); const str = bun.String.fromJS(value, globalThis); @@ -1749,7 +1749,7 @@ pub const Interpreter = struct { return .undefined; } - pub fn setEnv(this: *ThisInterpreter, globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn setEnv(this: *ThisInterpreter, globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { const value1 = callframe.argument(0); if (!value1.isObject()) { globalThis.throwInvalidArguments("env must be an object", .{}); @@ -1790,7 +1790,7 @@ pub const Interpreter = struct { this: *ThisInterpreter, globalThis: *JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { _ = globalThis; // autofix _ = callframe; // autofix @@ -1801,7 +1801,7 @@ pub const Interpreter = struct { this: *ThisInterpreter, globalThis: *JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { _ = globalThis; // autofix _ = callframe; // autofix @@ -1824,12 +1824,12 @@ pub const Interpreter = struct { pub fn finalize( this: *ThisInterpreter, - ) callconv(.C) void { + ) void { log("Interpreter(0x{x}) finalize", .{@intFromPtr(this)}); this.deinitFromFinalizer(); } - pub fn hasPendingActivity(this: *ThisInterpreter) callconv(.C) bool { + pub fn hasPendingActivity(this: *ThisInterpreter) bool { @fence(.seq_cst); return this.has_pending_activity.load(.seq_cst) > 0; } diff --git a/src/shell/shell.zig b/src/shell/shell.zig index a8358bfe6f..500b3ee83e 100644 --- a/src/shell/shell.zig +++ b/src/shell/shell.zig @@ -4369,7 +4369,7 @@ pub fn SmolList(comptime T: type, comptime INLINED_MAX: comptime_int) type { /// Used in JS tests, see `internal-for-testing.ts` and shell tests. pub const TestingAPIs = struct { - pub fn disabledOnThisPlatform(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub fn disabledOnThisPlatform(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue { if (comptime bun.Environment.isWindows) return JSValue.false; const arguments_ = callframe.arguments(1); @@ -4395,7 +4395,7 @@ pub const TestingAPIs = struct { pub fn shellLex( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const arguments_ = callframe.arguments(2); var arguments = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments_.slice()); const string_args = arguments.nextEat() orelse { @@ -4485,7 +4485,7 @@ pub const TestingAPIs = struct { pub fn shellParse( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) JSC.JSValue { const arguments_ = callframe.arguments(2); var arguments = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments_.slice()); const string_args = arguments.nextEat() orelse { diff --git a/src/string.zig b/src/string.zig index d6814ca0f5..acfeae64b4 100644 --- a/src/string.zig +++ b/src/string.zig @@ -1231,7 +1231,7 @@ pub const String = extern struct { return try concat(strings.len, allocator, strings); } - pub export fn jsGetStringWidth(globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + pub export fn jsGetStringWidth(globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(JSC.conv) JSC.JSValue { const args = callFrame.arguments(1).slice(); if (args.len == 0 or !args.ptr[0].isString()) { diff --git a/src/string_immutable.zig b/src/string_immutable.zig index 89715d846e..7d7b4111a8 100644 --- a/src/string_immutable.zig +++ b/src/string_immutable.zig @@ -749,10 +749,6 @@ pub fn eql(self: string, other: anytype) bool { return true; } -pub inline fn eqlInsensitive(self: string, other: anytype) bool { - return std.ascii.eqlIgnoreCase(self, other); -} - pub fn eqlComptime(self: string, comptime alt: anytype) bool { return eqlComptimeCheckLenWithType(u8, self, alt, true); } diff --git a/src/url.zig b/src/url.zig index 30513299e7..9f4614b3b2 100644 --- a/src/url.zig +++ b/src/url.zig @@ -980,7 +980,7 @@ pub const FormData = struct { pub fn jsFunctionFromMultipartData( globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, - ) callconv(.C) JSC.JSValue { + ) callconv(JSC.conv) JSC.JSValue { JSC.markBinding(@src()); const args_ = callframe.arguments(2); diff --git a/test/js/bun/ffi/ffi-test.c b/test/js/bun/ffi/ffi-test.c index 0fe2273852..a71021423d 100644 --- a/test/js/bun/ffi/ffi-test.c +++ b/test/js/bun/ffi/ffi-test.c @@ -3,60 +3,67 @@ #include #include -bool returns_true(); -bool returns_false(); -char returns_42_char(); -float returns_42_float(); -double returns_42_double(); -uint8_t returns_42_uint8_t(); -int8_t returns_neg_42_int8_t(); -uint16_t returns_42_uint16_t(); -uint32_t returns_42_uint32_t(); -uint64_t returns_42_uint64_t(); -int16_t returns_neg_42_int16_t(); -int32_t returns_neg_42_int32_t(); -int64_t returns_neg_42_int64_t(); +#ifdef _WIN32 +#define FFI_EXPORT __declspec(dllexport) +#else +#define FFI_EXPORT __attribute__((visibility("default"))) +#endif -bool cb_identity_true(bool (*cb)()); -bool cb_identity_false(bool (*cb)()); -char cb_identity_42_char(char (*cb)()); -float cb_identity_42_float(float (*cb)()); -double cb_identity_42_double(double (*cb)()); -uint8_t cb_identity_42_uint8_t(uint8_t (*cb)()); -int8_t cb_identity_neg_42_int8_t(int8_t (*cb)()); -uint16_t cb_identity_42_uint16_t(uint16_t (*cb)()); -uint32_t cb_identity_42_uint32_t(uint32_t (*cb)()); -uint64_t cb_identity_42_uint64_t(uint64_t (*cb)()); -int16_t cb_identity_neg_42_int16_t(int16_t (*cb)()); -int32_t cb_identity_neg_42_int32_t(int32_t (*cb)()); -int64_t cb_identity_neg_42_int64_t(int64_t (*cb)()); +FFI_EXPORT bool returns_true(); +FFI_EXPORT bool returns_false(); +FFI_EXPORT char returns_42_char(); +FFI_EXPORT float returns_42_float(); +FFI_EXPORT double returns_42_double(); +FFI_EXPORT uint8_t returns_42_uint8_t(); +FFI_EXPORT int8_t returns_neg_42_int8_t(); +FFI_EXPORT uint16_t returns_42_uint16_t(); +FFI_EXPORT uint32_t returns_42_uint32_t(); +FFI_EXPORT uint64_t returns_42_uint64_t(); +FFI_EXPORT int16_t returns_neg_42_int16_t(); +FFI_EXPORT int32_t returns_neg_42_int32_t(); +FFI_EXPORT int64_t returns_neg_42_int64_t(); -bool identity_bool_true(); -bool identity_bool_false(); -char identity_char(char a); -float identity_float(float a); -bool identity_bool(bool ident); -double identity_double(double a); -int8_t identity_int8_t(int8_t a); -int16_t identity_int16_t(int16_t a); -int32_t identity_int32_t(int32_t a); -int64_t identity_int64_t(int64_t a); -uint8_t identity_uint8_t(uint8_t a); -uint16_t identity_uint16_t(uint16_t a); -uint32_t identity_uint32_t(uint32_t a); -uint64_t identity_uint64_t(uint64_t a); +FFI_EXPORT bool cb_identity_true(bool (*cb)()); +FFI_EXPORT bool cb_identity_false(bool (*cb)()); +FFI_EXPORT char cb_identity_42_char(char (*cb)()); +FFI_EXPORT float cb_identity_42_float(float (*cb)()); +FFI_EXPORT double cb_identity_42_double(double (*cb)()); +FFI_EXPORT uint8_t cb_identity_42_uint8_t(uint8_t (*cb)()); +FFI_EXPORT int8_t cb_identity_neg_42_int8_t(int8_t (*cb)()); +FFI_EXPORT uint16_t cb_identity_42_uint16_t(uint16_t (*cb)()); +FFI_EXPORT uint32_t cb_identity_42_uint32_t(uint32_t (*cb)()); +FFI_EXPORT uint64_t cb_identity_42_uint64_t(uint64_t (*cb)()); +FFI_EXPORT int16_t cb_identity_neg_42_int16_t(int16_t (*cb)()); +FFI_EXPORT int32_t cb_identity_neg_42_int32_t(int32_t (*cb)()); +FFI_EXPORT int64_t cb_identity_neg_42_int64_t(int64_t (*cb)()); -char add_char(char a, char b); -float add_float(float a, float b); -double add_double(double a, double b); -int8_t add_int8_t(int8_t a, int8_t b); -int16_t add_int16_t(int16_t a, int16_t b); -int32_t add_int32_t(int32_t a, int32_t b); -int64_t add_int64_t(int64_t a, int64_t b); -uint8_t add_uint8_t(uint8_t a, uint8_t b); -uint16_t add_uint16_t(uint16_t a, uint16_t b); -uint32_t add_uint32_t(uint32_t a, uint32_t b); -uint64_t add_uint64_t(uint64_t a, uint64_t b); +FFI_EXPORT bool identity_bool_true(); +FFI_EXPORT bool identity_bool_false(); +FFI_EXPORT char identity_char(char a); +FFI_EXPORT float identity_float(float a); +FFI_EXPORT bool identity_bool(bool ident); +FFI_EXPORT double identity_double(double a); +FFI_EXPORT int8_t identity_int8_t(int8_t a); +FFI_EXPORT int16_t identity_int16_t(int16_t a); +FFI_EXPORT int32_t identity_int32_t(int32_t a); +FFI_EXPORT int64_t identity_int64_t(int64_t a); +FFI_EXPORT uint8_t identity_uint8_t(uint8_t a); +FFI_EXPORT uint16_t identity_uint16_t(uint16_t a); +FFI_EXPORT uint32_t identity_uint32_t(uint32_t a); +FFI_EXPORT uint64_t identity_uint64_t(uint64_t a); +FFI_EXPORT void *identity_ptr(void *ident); + +FFI_EXPORT char add_char(char a, char b); +FFI_EXPORT float add_float(float a, float b); +FFI_EXPORT double add_double(double a, double b); +FFI_EXPORT int8_t add_int8_t(int8_t a, int8_t b); +FFI_EXPORT int16_t add_int16_t(int16_t a, int16_t b); +FFI_EXPORT int32_t add_int32_t(int32_t a, int32_t b); +FFI_EXPORT int64_t add_int64_t(int64_t a, int64_t b); +FFI_EXPORT uint8_t add_uint8_t(uint8_t a, uint8_t b); +FFI_EXPORT uint16_t add_uint16_t(uint16_t a, uint16_t b); +FFI_EXPORT uint32_t add_uint32_t(uint32_t a, uint32_t b); +FFI_EXPORT uint64_t add_uint64_t(uint64_t a, uint64_t b); bool returns_false() { return false; } bool returns_true() { return true; } @@ -98,7 +105,8 @@ uint16_t add_uint16_t(uint16_t a, uint16_t b) { return a + b; } uint32_t add_uint32_t(uint32_t a, uint32_t b) { return a + b; } uint64_t add_uint64_t(uint64_t a, uint64_t b) { return a + b; } -void *ptr_should_point_to_42_as_int32_t(); +FFI_EXPORT void *ptr_should_point_to_42_as_int32_t(); + void *ptr_should_point_to_42_as_int32_t() { int32_t *ptr = malloc(sizeof(int32_t)); *ptr = 42; @@ -107,37 +115,37 @@ void *ptr_should_point_to_42_as_int32_t() { static uint8_t buffer_with_deallocator[128]; static int deallocatorCalled; -void deallocator(void *ptr, void *userData) { deallocatorCalled++; } -void *getDeallocatorCallback() { +FFI_EXPORT void deallocator(void *ptr, void *userData) { deallocatorCalled++; } +FFI_EXPORT void *getDeallocatorCallback() { deallocatorCalled = 0; return &deallocator; } -void *getDeallocatorBuffer() { +FFI_EXPORT void *getDeallocatorBuffer() { deallocatorCalled = 0; return &buffer_with_deallocator; } -int getDeallocatorCalledCount() { return deallocatorCalled; } +FFI_EXPORT int getDeallocatorCalledCount() { return deallocatorCalled; } -bool is_null(int32_t *ptr) { return ptr == NULL; } -bool does_pointer_equal_42_as_int32_t(int32_t *ptr); +FFI_EXPORT bool is_null(int32_t *ptr) { return ptr == NULL; } +FFI_EXPORT bool does_pointer_equal_42_as_int32_t(int32_t *ptr); bool does_pointer_equal_42_as_int32_t(int32_t *ptr) { return *ptr == 42; } -void *return_a_function_ptr_to_function_that_returns_true(); +FFI_EXPORT void *return_a_function_ptr_to_function_that_returns_true(); void *return_a_function_ptr_to_function_that_returns_true() { return (void *)&returns_true; } -bool cb_identity_true(bool (*cb)()) { return cb(); } +FFI_EXPORT bool cb_identity_true(bool (*cb)()) { return cb(); } -bool cb_identity_false(bool (*cb)()) { return cb(); } -char cb_identity_42_char(char (*cb)()) { return cb(); } -float cb_identity_42_float(float (*cb)()) { return cb(); } -double cb_identity_42_double(double (*cb)()) { return cb(); } -uint8_t cb_identity_42_uint8_t(uint8_t (*cb)()) { return cb(); } -int8_t cb_identity_neg_42_int8_t(int8_t (*cb)()) { return cb(); } -uint16_t cb_identity_42_uint16_t(uint16_t (*cb)()) { return cb(); } -uint32_t cb_identity_42_uint32_t(uint32_t (*cb)()) { return cb(); } -uint64_t cb_identity_42_uint64_t(uint64_t (*cb)()) { return cb(); } -int16_t cb_identity_neg_42_int16_t(int16_t (*cb)()) { return cb(); } -int32_t cb_identity_neg_42_int32_t(int32_t (*cb)()) { return cb(); } -int64_t cb_identity_neg_42_int64_t(int64_t (*cb)()) { return cb(); } \ No newline at end of file +FFI_EXPORT bool cb_identity_false(bool (*cb)()) { return cb(); } +FFI_EXPORT char cb_identity_42_char(char (*cb)()) { return cb(); } +FFI_EXPORT float cb_identity_42_float(float (*cb)()) { return cb(); } +FFI_EXPORT double cb_identity_42_double(double (*cb)()) { return cb(); } +FFI_EXPORT uint8_t cb_identity_42_uint8_t(uint8_t (*cb)()) { return cb(); } +FFI_EXPORT int8_t cb_identity_neg_42_int8_t(int8_t (*cb)()) { return cb(); } +FFI_EXPORT uint16_t cb_identity_42_uint16_t(uint16_t (*cb)()) { return cb(); } +FFI_EXPORT uint32_t cb_identity_42_uint32_t(uint32_t (*cb)()) { return cb(); } +FFI_EXPORT uint64_t cb_identity_42_uint64_t(uint64_t (*cb)()) { return cb(); } +FFI_EXPORT int16_t cb_identity_neg_42_int16_t(int16_t (*cb)()) { return cb(); } +FFI_EXPORT int32_t cb_identity_neg_42_int32_t(int32_t (*cb)()) { return cb(); } +FFI_EXPORT int64_t cb_identity_neg_42_int64_t(int64_t (*cb)()) { return cb(); } \ No newline at end of file diff --git a/test/js/bun/io/bun-write.test.js b/test/js/bun/io/bun-write.test.js index 7ab28c887c..04376b9a8e 100644 --- a/test/js/bun/io/bun-write.test.js +++ b/test/js/bun/io/bun-write.test.js @@ -495,4 +495,4 @@ test("timed output should work", async () => { await Bun.sleep(1000); } expect(text).toBe("0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n"); -}); +}, 25000); diff --git a/test/js/bun/util/fileUrl.test.js b/test/js/bun/util/fileUrl.test.js index 7d156b1f88..06c239c164 100644 --- a/test/js/bun/util/fileUrl.test.js +++ b/test/js/bun/util/fileUrl.test.js @@ -42,4 +42,10 @@ describe("fileURLToPath", () => { const url = pathToFileURL("foo.txt"); expect(url.href).toBe(`${pathToFileURL(process.cwd())}/foo.txt`); }); + + it("should roundtrip", () => { + const url = pathToFileURL(import.meta.path); + expect(fileURLToPath(url)).toBe(import.meta.path); + expect(fileURLToPath(import.meta.url)).toBe(import.meta.path); + }); }); diff --git a/test/js/web/fetch/fetch-gzip.test.ts b/test/js/web/fetch/fetch-gzip.test.ts index b4ee4df9a4..46cd1987ab 100644 --- a/test/js/web/fetch/fetch-gzip.test.ts +++ b/test/js/web/fetch/fetch-gzip.test.ts @@ -1,6 +1,14 @@ import { Socket } from "bun"; -import { it, expect } from "bun:test"; +import { it, expect, beforeAll } from "bun:test"; import { gcTick } from "harness"; +import path from "path"; + +const gzipped = path.join(import.meta.dir, "fixture.html.gz"); +const html = path.join(import.meta.dir, "fixture.html"); +let htmlText: string; +beforeAll(async () => { + htmlText = (await Bun.file(html).text()).replace(/\r\n/g, "\n"); +}); it("fetch() with a buffered gzip response works (one chunk)", async () => { using server = Bun.serve({ @@ -8,7 +16,7 @@ it("fetch() with a buffered gzip response works (one chunk)", async () => { async fetch(req) { gcTick(true); - return new Response(require("fs").readFileSync(import.meta.dir + "/fixture.html.gz"), { + return new Response(require("fs").readFileSync(gzipped), { headers: { "Content-Encoding": "gzip", "Content-Type": "text/html; charset=utf-8", @@ -24,7 +32,7 @@ it("fetch() with a buffered gzip response works (one chunk)", async () => { const clone = new Buffer(arrayBuffer); gcTick(true); await (async function () { - const second = new Buffer(await Bun.file(import.meta.dir + "/fixture.html").arrayBuffer()); + const second = Buffer.from(htmlText); gcTick(true); expect(second.equals(clone)).toBe(true); })(); @@ -37,7 +45,7 @@ it("fetch() with a redirect that returns a buffered gzip response works (one chu async fetch(req) { if (req.url.endsWith("/redirect")) - return new Response(await Bun.file(import.meta.dir + "/fixture.html.gz").arrayBuffer(), { + return new Response(await Bun.file(gzipped).arrayBuffer(), { headers: { "Content-Encoding": "gzip", "Content-Type": "text/html; charset=utf-8", @@ -50,10 +58,8 @@ it("fetch() with a redirect that returns a buffered gzip response works (one chu const url = new URL("hey", server.url); const res = await fetch(url, { verbose: true }); - const arrayBuffer = await res.arrayBuffer(); - expect( - new Buffer(arrayBuffer).equals(new Buffer(await Bun.file(import.meta.dir + "/fixture.html").arrayBuffer())), - ).toBe(true); + const text = (await res.text()).replace(/\r\n/g, "\n"); + expect(text).toEqual(htmlText); }); it("fetch() with a protocol-relative redirect that returns a buffered gzip response works (one chunk)", async () => { @@ -62,7 +68,7 @@ it("fetch() with a protocol-relative redirect that returns a buffered gzip respo async fetch(req, server) { if (req.url.endsWith("/redirect")) - return new Response(await Bun.file(import.meta.dir + "/fixture.html.gz").arrayBuffer(), { + return new Response(await Bun.file(gzipped).arrayBuffer(), { headers: { "Content-Encoding": "gzip", "Content-Type": "text/html; charset=utf-8", @@ -78,10 +84,8 @@ it("fetch() with a protocol-relative redirect that returns a buffered gzip respo expect(new URL(res.url)).toEqual(new URL("redirect", server.url)); expect(res.redirected).toBe(true); expect(res.status).toBe(200); - const arrayBuffer = await res.arrayBuffer(); - expect( - new Buffer(arrayBuffer).equals(new Buffer(await Bun.file(import.meta.dir + "/fixture.html").arrayBuffer())), - ).toBe(true); + const text = (await res.text()).replace(/\r\n/g, "\n"); + expect(text).toEqual(htmlText); }); it("fetch() with a gzip response works (one chunk, streamed, with a delay)", async () => { @@ -112,41 +116,85 @@ it("fetch() with a gzip response works (one chunk, streamed, with a delay)", asy }); const res = await fetch(server.url); - const arrayBuffer = await res.arrayBuffer(); - expect( - new Buffer(arrayBuffer).equals(new Buffer(await Bun.file(import.meta.dir + "/fixture.html").arrayBuffer())), - ).toBe(true); + const text = (await res.text()).replace(/\r\n/g, "\n"); + expect(text).toEqual(htmlText); }); it("fetch() with a gzip response works (multiple chunks, TCP server)", async done => { - const compressed = await Bun.file(import.meta.dir + "/fixture.html.gz").arrayBuffer(); + const compressed = await Bun.file(gzipped).arrayBuffer(); var socketToClose!: Socket; + let pending, + pendingChunks = []; const server = Bun.listen({ hostname: "localhost", port: 0, socket: { + drain(socket) { + if (pending) { + while (pendingChunks.length) { + const chunk = pendingChunks.shift(); + const written = socket.write(chunk); + + if (written < chunk.length) { + pendingChunks.push(chunk.slice(written)); + return; + } + } + const resolv = pending; + pending = null; + resolv(); + } + }, async open(socket) { socketToClose = socket; var corked: any[] = []; var cork = true; + let written = 0; + let pendingChunks = []; async function write(chunk: any) { - await new Promise((resolve, reject) => { - if (cork) { - corked.push(chunk); + let defer = Promise.withResolvers(); + + if (cork) { + corked.push(chunk); + } + + if (!cork && corked.length) { + const toWrite = corked.join(""); + const wrote = socket.write(toWrite); + if (wrote !== toWrite.length) { + pendingChunks.push(toWrite.slice(wrote)); + } + corked.length = 0; + } + + if (!cork) { + if (pendingChunks.length) { + pendingChunks.push(chunk); + pending = defer.resolve; + await defer.promise; + defer = Promise.withResolvers(); + pending = defer.resolve; } - if (!cork && corked.length) { - socket.write(corked.join("")); - corked.length = 0; + const written = socket.write(chunk); + if (written < chunk.length) { + console.log("written", written); + pendingChunks.push(chunk.slice(written)); + pending = defer.resolve; + await defer.promise; + defer = Promise.withResolvers(); + pending = defer.resolve; } + } - if (!cork) { - socket.write(chunk); - } - - resolve(); - }); + const promise = defer.promise; + if (pendingChunks.length) { + pending = promise; + await promise; + } else { + pending = null; + } } await write("HTTP/1.1 200 OK\r\n"); await write("Content-Encoding: gzip\r\n"); @@ -159,6 +207,8 @@ it("fetch() with a gzip response works (multiple chunks, TCP server)", async don await write(compressed.slice(i - 100, i)); } await write(compressed.slice(i - 100)); + await write("\r\n"); + socket.flush(); }, drain(socket) {}, @@ -167,10 +217,8 @@ it("fetch() with a gzip response works (multiple chunks, TCP server)", async don await 1; const res = await fetch(`http://${server.hostname}:${server.port}`); - const arrayBuffer = await res.arrayBuffer(); - expect( - new Buffer(arrayBuffer).equals(new Buffer(await Bun.file(import.meta.dir + "/fixture.html").arrayBuffer())), - ).toBe(true); + const text = (await res.text()).replace(/\r\n/g, "\n"); + expect(text).toEqual(htmlText); socketToClose.end(); server.stop(); done();