aboutsummaryrefslogtreecommitdiff
path: root/src/javascript/jsc/api/ffi.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/javascript/jsc/api/ffi.zig')
-rw-r--r--src/javascript/jsc/api/ffi.zig1436
1 files changed, 0 insertions, 1436 deletions
diff --git a/src/javascript/jsc/api/ffi.zig b/src/javascript/jsc/api/ffi.zig
deleted file mode 100644
index 864a5d889..000000000
--- a/src/javascript/jsc/api/ffi.zig
+++ /dev/null
@@ -1,1436 +0,0 @@
-const Bun = @This();
-const default_allocator = @import("../../../global.zig").default_allocator;
-const bun = @import("../../../global.zig");
-const Environment = bun.Environment;
-const NetworkThread = @import("http").NetworkThread;
-const Global = bun.Global;
-const strings = bun.strings;
-const string = bun.string;
-const Output = @import("../../../global.zig").Output;
-const MutableString = @import("../../../global.zig").MutableString;
-const std = @import("std");
-const Allocator = std.mem.Allocator;
-const IdentityContext = @import("../../../identity_context.zig").IdentityContext;
-const Fs = @import("../../../fs.zig");
-const Resolver = @import("../../../resolver/resolver.zig");
-const ast = @import("../../../import_record.zig");
-const NodeModuleBundle = @import("../../../node_module_bundle.zig").NodeModuleBundle;
-const MacroEntryPoint = @import("../../../bundler.zig").MacroEntryPoint;
-const logger = @import("../../../logger.zig");
-const Api = @import("../../../api/schema.zig").Api;
-const options = @import("../../../options.zig");
-const Bundler = @import("../../../bundler.zig").Bundler;
-const ServerEntryPoint = @import("../../../bundler.zig").ServerEntryPoint;
-const js_printer = @import("../../../js_printer.zig");
-const js_parser = @import("../../../js_parser.zig");
-const js_ast = @import("../../../js_ast.zig");
-const hash_map = @import("../../../hash_map.zig");
-const http = @import("../../../http.zig");
-const NodeFallbackModules = @import("../../../node_fallbacks.zig");
-const ImportKind = ast.ImportKind;
-const Analytics = @import("../../../analytics/analytics_thread.zig");
-const ZigString = @import("../../../jsc.zig").ZigString;
-const Runtime = @import("../../../runtime.zig");
-const Router = @import("./router.zig");
-const ImportRecord = ast.ImportRecord;
-const DotEnv = @import("../../../env_loader.zig");
-const ParseResult = @import("../../../bundler.zig").ParseResult;
-const PackageJSON = @import("../../../resolver/package_json.zig").PackageJSON;
-const MacroRemap = @import("../../../resolver/package_json.zig").MacroMap;
-const WebCore = @import("../../../jsc.zig").WebCore;
-const Request = WebCore.Request;
-const Response = WebCore.Response;
-const Headers = WebCore.Headers;
-const Fetch = WebCore.Fetch;
-const FetchEvent = WebCore.FetchEvent;
-const js = @import("../../../jsc.zig").C;
-const JSC = @import("../../../jsc.zig");
-const JSError = @import("../base.zig").JSError;
-const d = @import("../base.zig").d;
-const MarkedArrayBuffer = @import("../base.zig").MarkedArrayBuffer;
-const getAllocator = @import("../base.zig").getAllocator;
-const JSValue = @import("../../../jsc.zig").JSValue;
-const NewClass = @import("../base.zig").NewClass;
-const Microtask = @import("../../../jsc.zig").Microtask;
-const JSGlobalObject = @import("../../../jsc.zig").JSGlobalObject;
-const ExceptionValueRef = @import("../../../jsc.zig").ExceptionValueRef;
-const JSPrivateDataPtr = @import("../../../jsc.zig").JSPrivateDataPtr;
-const ZigConsoleClient = @import("../../../jsc.zig").ZigConsoleClient;
-const Node = @import("../../../jsc.zig").Node;
-const ZigException = @import("../../../jsc.zig").ZigException;
-const ZigStackTrace = @import("../../../jsc.zig").ZigStackTrace;
-const ErrorableResolvedSource = @import("../../../jsc.zig").ErrorableResolvedSource;
-const ResolvedSource = @import("../../../jsc.zig").ResolvedSource;
-const JSPromise = @import("../../../jsc.zig").JSPromise;
-const JSInternalPromise = @import("../../../jsc.zig").JSInternalPromise;
-const JSModuleLoader = @import("../../../jsc.zig").JSModuleLoader;
-const JSPromiseRejectionOperation = @import("../../../jsc.zig").JSPromiseRejectionOperation;
-const Exception = @import("../../../jsc.zig").Exception;
-const ErrorableZigString = @import("../../../jsc.zig").ErrorableZigString;
-const ZigGlobalObject = @import("../../../jsc.zig").ZigGlobalObject;
-const VM = @import("../../../jsc.zig").VM;
-const JSFunction = @import("../../../jsc.zig").JSFunction;
-const Config = @import("../config.zig");
-const URL = @import("../../../url.zig").URL;
-const Transpiler = @import("./transpiler.zig");
-const VirtualMachine = @import("../javascript.zig").VirtualMachine;
-const IOTask = JSC.IOTask;
-const ComptimeStringMap = @import("../../../comptime_string_map.zig").ComptimeStringMap;
-
-const TCC = @import("../../../tcc.zig");
-
-pub const FFI = struct {
- dylib: ?std.DynLib = null,
- functions: std.StringArrayHashMapUnmanaged(Function) = .{},
- closed: bool = false,
-
- pub const Class = JSC.NewClass(
- FFI,
- .{ .name = "class" },
- .{ .call = JSC.wrapWithHasContainer(FFI, "close", false, true, true) },
- .{},
- );
-
- pub fn callback(globalThis: *JSGlobalObject, interface: JSC.JSValue, js_callback: JSC.JSValue) JSValue {
- if (!interface.isObject()) {
- return JSC.toInvalidArguments("Expected object", .{}, globalThis.ref());
- }
-
- if (js_callback.isEmptyOrUndefinedOrNull() or !js_callback.isCallable(globalThis.vm())) {
- return JSC.toInvalidArguments("Expected callback function", .{}, globalThis.ref());
- }
-
- const allocator = VirtualMachine.vm.allocator;
- var function: Function = .{};
- var func = &function;
-
- if (generateSymbolForFunction(globalThis, allocator, interface, func) catch ZigString.init("Out of memory").toErrorInstance(globalThis)) |val| {
- return val;
- }
-
- // TODO: WeakRefHandle that automatically frees it?
- JSC.C.JSValueProtect(globalThis.ref(), js_callback.asObjectRef());
- func.base_name = "";
-
- func.compileCallback(allocator, globalThis, js_callback.asObjectRef().?) catch return ZigString.init("Out of memory").toErrorInstance(globalThis);
- switch (func.step) {
- .failed => |err| {
- JSC.C.JSValueUnprotect(globalThis.ref(), js_callback.asObjectRef());
- const message = ZigString.init(err.msg).toErrorInstance(globalThis);
-
- func.deinit(allocator);
-
- return message;
- },
- .pending => {
- JSC.C.JSValueUnprotect(globalThis.ref(), js_callback.asObjectRef());
- func.deinit(allocator);
- return ZigString.init("Failed to compile, but not sure why. Please report this bug").toErrorInstance(globalThis);
- },
- .compiled => {
- var function_ = bun.default_allocator.create(Function) catch unreachable;
- function_.* = func.*;
- return JSC.JSValue.jsNumber(@bitCast(f64, @as(usize, @ptrToInt(function_.step.compiled.ptr))));
- },
- }
- }
-
- pub fn close(this: *FFI) JSValue {
- if (this.closed) {
- return JSC.JSValue.jsUndefined();
- }
- this.closed = true;
- if (this.dylib) |*dylib| {
- dylib.close();
- this.dylib = null;
- }
-
- const allocator = VirtualMachine.vm.allocator;
-
- for (this.functions.values()) |*val| {
- val.deinit(allocator);
- }
- this.functions.deinit(allocator);
-
- return JSC.JSValue.jsUndefined();
- }
-
- pub fn printCallback(global: *JSGlobalObject, object: JSC.JSValue) JSValue {
- const allocator = VirtualMachine.vm.allocator;
-
- if (object.isEmptyOrUndefinedOrNull() or !object.isObject()) {
- return JSC.toInvalidArguments("Expected an object", .{}, global.ref());
- }
-
- var function: Function = .{};
- if (generateSymbolForFunction(global, allocator, object, &function) catch ZigString.init("Out of memory").toErrorInstance(global)) |val| {
- return val;
- }
-
- var arraylist = std.ArrayList(u8).init(allocator);
- defer arraylist.deinit();
- var writer = arraylist.writer();
-
- function.base_name = "my_callback_function";
-
- function.printCallbackSourceCode(&writer) catch {
- return ZigString.init("Error while printing code").toErrorInstance(global);
- };
- return ZigString.init(arraylist.items).toValueGC(global);
- }
-
- pub fn print(global: *JSGlobalObject, object: JSC.JSValue, is_callback_val: ?JSC.JSValue) JSValue {
- const allocator = VirtualMachine.vm.allocator;
- if (is_callback_val) |is_callback| {
- if (is_callback.toBoolean()) {
- return printCallback(global, object);
- }
- }
-
- if (object.isEmptyOrUndefinedOrNull() or !object.isObject()) {
- return JSC.toInvalidArguments("Expected an options object with symbol names", .{}, global.ref());
- }
-
- var symbols = std.StringArrayHashMapUnmanaged(Function){};
- if (generateSymbols(global, &symbols, object) catch JSC.JSValue.zero) |val| {
- // an error while validating symbols
- for (symbols.keys()) |key| {
- allocator.free(bun.constStrToU8(key));
- }
- symbols.clearAndFree(allocator);
- return val;
- }
-
- var zig_strings = allocator.alloc(ZigString, symbols.count()) catch unreachable;
- for (symbols.values()) |*function, i| {
- var arraylist = std.ArrayList(u8).init(allocator);
- var writer = arraylist.writer();
- function.printSourceCode(&writer) catch {
- // an error while generating source code
- for (symbols.keys()) |key| {
- allocator.free(bun.constStrToU8(key));
- }
- for (zig_strings) |zig_string| {
- allocator.free(bun.constStrToU8(zig_string.slice()));
- }
- for (symbols.values()) |*function_| {
- function_.arg_types.deinit(allocator);
- }
-
- symbols.clearAndFree(allocator);
- return ZigString.init("Error while printing code").toErrorInstance(global);
- };
- zig_strings[i] = ZigString.init(arraylist.items);
- }
-
- const ret = JSC.JSValue.createStringArray(global, zig_strings.ptr, zig_strings.len, true);
-
- for (symbols.keys()) |key| {
- allocator.free(bun.constStrToU8(key));
- }
- for (zig_strings) |zig_string| {
- allocator.free(bun.constStrToU8(zig_string.slice()));
- }
- for (symbols.values()) |*function_| {
- function_.arg_types.deinit(allocator);
- if (function_.step == .compiled) {
- allocator.free(function_.step.compiled.buf);
- }
- }
- symbols.clearAndFree(allocator);
-
- return ret;
- }
-
- // pub fn dlcompile(global: *JSGlobalObject, object: JSC.JSValue) JSValue {
- // const allocator = VirtualMachine.vm.allocator;
-
- // if (object.isEmptyOrUndefinedOrNull() or !object.isObject()) {
- // return JSC.toInvalidArguments("Expected an options object with symbol names", .{}, global.ref());
- // }
-
- // var symbols = std.StringArrayHashMapUnmanaged(Function){};
- // if (generateSymbols(global, &symbols, object) catch JSC.JSValue.zero) |val| {
- // // an error while validating symbols
- // for (symbols.keys()) |key| {
- // allocator.free(bun.constStrToU8(key));
- // }
- // symbols.clearAndFree(allocator);
- // return val;
- // }
-
- // }
-
- pub fn open(global: *JSGlobalObject, name_str: ZigString, object: JSC.JSValue) JSC.JSValue {
- const allocator = VirtualMachine.vm.allocator;
- var name_slice = name_str.toSlice(allocator);
- defer name_slice.deinit();
-
- if (name_slice.len == 0) {
- return JSC.toInvalidArguments("Invalid library name", .{}, global.ref());
- }
-
- if (object.isEmptyOrUndefinedOrNull() or !object.isObject()) {
- return JSC.toInvalidArguments("Expected an options object with symbol names", .{}, global.ref());
- }
-
- const name = name_slice.sliceZ();
- var symbols = std.StringArrayHashMapUnmanaged(Function){};
- if (generateSymbols(global, &symbols, object) catch JSC.JSValue.zero) |val| {
- // an error while validating symbols
- for (symbols.keys()) |key| {
- allocator.free(bun.constStrToU8(key));
- }
- symbols.clearAndFree(allocator);
- return val;
- }
- if (symbols.count() == 0) {
- return JSC.toInvalidArguments("Expected at least one symbol", .{}, global.ref());
- }
-
- var dylib = std.DynLib.open(name) catch {
- return JSC.toInvalidArguments("Failed to open library", .{}, global.ref());
- };
-
- var obj = JSC.JSValue.c(JSC.C.JSObjectMake(global.ref(), null, null));
- JSC.C.JSValueProtect(global.ref(), obj.asObjectRef());
- defer JSC.C.JSValueUnprotect(global.ref(), obj.asObjectRef());
- for (symbols.values()) |*function| {
- const function_name = function.base_name.?;
-
- // optional if the user passed "ptr"
- if (function.symbol_from_dynamic_library == null) {
- var resolved_symbol = dylib.lookup(*anyopaque, function_name) orelse {
- const ret = JSC.toInvalidArguments("Symbol \"{s}\" not found in \"{s}\"", .{ std.mem.span(function_name), name_slice.slice() }, global.ref());
- for (symbols.values()) |*value| {
- allocator.free(bun.constStrToU8(std.mem.span(value.base_name.?)));
- value.arg_types.clearAndFree(allocator);
- }
- symbols.clearAndFree(allocator);
- dylib.close();
- return ret;
- };
-
- function.symbol_from_dynamic_library = resolved_symbol;
- }
-
- function.compile(allocator) catch |err| {
- const ret = JSC.toInvalidArguments("{s} when compiling symbol \"{s}\" in \"{s}\"", .{
- std.mem.span(@errorName(err)),
- std.mem.span(function_name),
- name_slice.slice(),
- }, global.ref());
- for (symbols.values()) |*value| {
- allocator.free(bun.constStrToU8(std.mem.span(value.base_name.?)));
- value.arg_types.clearAndFree(allocator);
- }
- symbols.clearAndFree(allocator);
- dylib.close();
- return ret;
- };
- switch (function.step) {
- .failed => |err| {
- for (symbols.values()) |*value| {
- allocator.free(bun.constStrToU8(std.mem.span(value.base_name.?)));
- value.arg_types.clearAndFree(allocator);
- }
-
- const res = ZigString.init(err.msg).toErrorInstance(global);
- function.deinit(allocator);
- symbols.clearAndFree(allocator);
- dylib.close();
- return res;
- },
- .pending => {
- for (symbols.values()) |*value| {
- allocator.free(bun.constStrToU8(std.mem.span(value.base_name.?)));
- value.arg_types.clearAndFree(allocator);
- }
- symbols.clearAndFree(allocator);
- dylib.close();
- return ZigString.init("Failed to compile (nothing happend!)").toErrorInstance(global);
- },
- .compiled => |compiled| {
- var cb = JSC.NewFunctionPtr(
- global,
- &ZigString.init(std.mem.span(function_name)),
- @intCast(u32, function.arg_types.items.len),
- compiled.ptr,
- );
-
- obj.put(global, &ZigString.init(std.mem.span(function_name)), JSC.JSValue.cast(cb));
- },
- }
- }
-
- var lib = allocator.create(FFI) catch unreachable;
- lib.* = .{
- .dylib = dylib,
- .functions = symbols,
- };
-
- var close_object = JSC.JSValue.c(Class.make(global.ref(), lib));
-
- return JSC.JSValue.createObject2(global, &ZigString.init("close"), &ZigString.init("symbols"), close_object, obj);
- }
-
- pub fn linkSymbols(global: *JSGlobalObject, object: JSC.JSValue) JSC.JSValue {
- const allocator = VirtualMachine.vm.allocator;
-
- if (object.isEmptyOrUndefinedOrNull() or !object.isObject()) {
- return JSC.toInvalidArguments("Expected an options object with symbol names", .{}, global.ref());
- }
-
- var symbols = std.StringArrayHashMapUnmanaged(Function){};
- if (generateSymbols(global, &symbols, object) catch JSC.JSValue.zero) |val| {
- // an error while validating symbols
- for (symbols.keys()) |key| {
- allocator.free(bun.constStrToU8(key));
- }
- symbols.clearAndFree(allocator);
- return val;
- }
- if (symbols.count() == 0) {
- return JSC.toInvalidArguments("Expected at least one symbol", .{}, global.ref());
- }
-
- var obj = JSC.JSValue.c(JSC.C.JSObjectMake(global.ref(), null, null));
- JSC.C.JSValueProtect(global.ref(), obj.asObjectRef());
- defer JSC.C.JSValueUnprotect(global.ref(), obj.asObjectRef());
- for (symbols.values()) |*function| {
- const function_name = function.base_name.?;
-
- if (function.symbol_from_dynamic_library == null) {
- const ret = JSC.toInvalidArguments("Symbol for \"{s}\" not found", .{std.mem.span(function_name)}, global.ref());
- for (symbols.values()) |*value| {
- allocator.free(bun.constStrToU8(std.mem.span(value.base_name.?)));
- value.arg_types.clearAndFree(allocator);
- }
- symbols.clearAndFree(allocator);
- return ret;
- }
-
- function.compile(allocator) catch |err| {
- const ret = JSC.toInvalidArguments("{s} when compiling symbol \"{s}\"", .{
- std.mem.span(@errorName(err)),
- std.mem.span(function_name),
- }, global.ref());
- for (symbols.values()) |*value| {
- allocator.free(bun.constStrToU8(std.mem.span(value.base_name.?)));
- value.arg_types.clearAndFree(allocator);
- }
- symbols.clearAndFree(allocator);
- return ret;
- };
- switch (function.step) {
- .failed => |err| {
- for (symbols.values()) |*value| {
- allocator.free(bun.constStrToU8(std.mem.span(value.base_name.?)));
- value.arg_types.clearAndFree(allocator);
- }
-
- const res = ZigString.init(err.msg).toErrorInstance(global);
- function.deinit(allocator);
- symbols.clearAndFree(allocator);
- return res;
- },
- .pending => {
- for (symbols.values()) |*value| {
- allocator.free(bun.constStrToU8(std.mem.span(value.base_name.?)));
- value.arg_types.clearAndFree(allocator);
- }
- symbols.clearAndFree(allocator);
- return ZigString.init("Failed to compile (nothing happend!)").toErrorInstance(global);
- },
- .compiled => |compiled| {
- var cb = JSC.NewFunctionPtr(
- global,
- &ZigString.init(std.mem.span(function_name)),
- @intCast(u32, function.arg_types.items.len),
- compiled.ptr,
- );
-
- obj.put(global, &ZigString.init(std.mem.span(function_name)), JSC.JSValue.cast(cb));
- },
- }
- }
-
- var lib = allocator.create(FFI) catch unreachable;
- lib.* = .{
- .dylib = null,
- .functions = symbols,
- };
-
- var close_object = JSC.JSValue.c(Class.make(global.ref(), lib));
-
- return JSC.JSValue.createObject2(global, &ZigString.init("close"), &ZigString.init("symbols"), close_object, obj);
- }
- pub fn generateSymbolForFunction(global: *JSGlobalObject, allocator: std.mem.Allocator, value: JSC.JSValue, function: *Function) !?JSValue {
- var abi_types = std.ArrayListUnmanaged(ABIType){};
-
- if (value.get(global, "args")) |args| {
- if (args.isEmptyOrUndefinedOrNull() or !args.jsType().isArray()) {
- return ZigString.init("Expected an object with \"args\" as an array").toErrorInstance(global);
- }
-
- var array = args.arrayIterator(global);
-
- try abi_types.ensureTotalCapacityPrecise(allocator, array.len);
- while (array.next()) |val| {
- if (val.isEmptyOrUndefinedOrNull()) {
- abi_types.clearAndFree(allocator);
- return ZigString.init("param must be a string (type name) or number").toErrorInstance(global);
- }
-
- if (val.isAnyInt()) {
- const int = val.toInt32();
- switch (int) {
- 0...14 => {
- abi_types.appendAssumeCapacity(@intToEnum(ABIType, int));
- continue;
- },
- else => {
- abi_types.clearAndFree(allocator);
- return ZigString.init("invalid ABI type").toErrorInstance(global);
- },
- }
- }
-
- if (!val.jsType().isStringLike()) {
- abi_types.clearAndFree(allocator);
- return ZigString.init("param must be a string (type name) or number").toErrorInstance(global);
- }
-
- var type_name = val.toSlice(global, allocator);
- defer type_name.deinit();
- abi_types.appendAssumeCapacity(ABIType.label.get(type_name.slice()) orelse {
- abi_types.clearAndFree(allocator);
- return JSC.toTypeError(JSC.Node.ErrorCode.ERR_INVALID_ARG_VALUE, "Unknown type {s}", .{type_name.slice()}, global.ref());
- });
- }
- }
- // var function
- var return_type = ABIType.@"void";
-
- if (value.get(global, "returns")) |ret_value| brk: {
- if (ret_value.isAnyInt()) {
- const int = ret_value.toInt32();
- switch (int) {
- 0...14 => {
- return_type = @intToEnum(ABIType, int);
- break :brk;
- },
- else => {
- abi_types.clearAndFree(allocator);
- return ZigString.init("invalid ABI type").toErrorInstance(global);
- },
- }
- }
-
- var ret_slice = ret_value.toSlice(global, allocator);
- defer ret_slice.deinit();
- return_type = ABIType.label.get(ret_slice.slice()) orelse {
- abi_types.clearAndFree(allocator);
- return JSC.toTypeError(JSC.Node.ErrorCode.ERR_INVALID_ARG_VALUE, "Unknown return type {s}", .{ret_slice.slice()}, global.ref());
- };
- }
-
- function.* = Function{
- .base_name = null,
- .arg_types = abi_types,
- .return_type = return_type,
- };
-
- if (value.get(global, "ptr")) |ptr| {
- if (ptr.isNumber()) {
- const num = @bitCast(usize, ptr.asNumber());
- if (num > 0)
- function.symbol_from_dynamic_library = @intToPtr(*anyopaque, num);
- } else {
- const num = ptr.toUInt64NoTruncate();
- if (num > 0) {
- function.symbol_from_dynamic_library = @intToPtr(*anyopaque, num);
- }
- }
- }
-
- return null;
- }
- pub fn generateSymbols(global: *JSGlobalObject, symbols: *std.StringArrayHashMapUnmanaged(Function), object: JSC.JSValue) !?JSValue {
- const allocator = VirtualMachine.vm.allocator;
-
- var keys = JSC.C.JSObjectCopyPropertyNames(global.ref(), object.asObjectRef());
- defer JSC.C.JSPropertyNameArrayRelease(keys);
- const count = JSC.C.JSPropertyNameArrayGetCount(keys);
-
- try symbols.ensureTotalCapacity(allocator, count);
-
- var i: usize = 0;
- while (i < count) : (i += 1) {
- var property_name_ref = JSC.C.JSPropertyNameArrayGetNameAtIndex(keys, i);
- defer JSC.C.JSStringRelease(property_name_ref);
- const len = JSC.C.JSStringGetLength(property_name_ref);
- if (len == 0) continue;
- var prop = JSC.C.JSStringGetCharacters8Ptr(property_name_ref)[0..len];
-
- var value = JSC.JSValue.c(JSC.C.JSObjectGetProperty(global.ref(), object.asObjectRef(), property_name_ref, null));
- if (value.isEmptyOrUndefinedOrNull()) {
- return JSC.toTypeError(JSC.Node.ErrorCode.ERR_INVALID_ARG_VALUE, "Expected an object for key \"{s}\"", .{prop}, global.ref());
- }
-
- var function: Function = .{};
- if (try generateSymbolForFunction(global, allocator, value, &function)) |val| {
- return val;
- }
- function.base_name = try allocator.dupeZ(u8, prop);
-
- symbols.putAssumeCapacity(std.mem.span(function.base_name.?), function);
- }
-
- return null;
- }
-
- pub const Function = struct {
- symbol_from_dynamic_library: ?*anyopaque = null,
- base_name: ?[:0]const u8 = null,
- state: ?*TCC.TCCState = null,
-
- return_type: ABIType = ABIType.@"void",
- arg_types: std.ArrayListUnmanaged(ABIType) = .{},
- step: Step = Step{ .pending = {} },
-
- pub var lib_dirZ: [*:0]const u8 = "";
-
- pub fn deinit(val: *Function, allocator: std.mem.Allocator) void {
- if (val.base_name) |base_name| {
- if (std.mem.span(base_name).len > 0) {
- allocator.free(bun.constStrToU8(std.mem.span(base_name)));
- }
- }
-
- val.arg_types.clearAndFree(allocator);
-
- if (val.state) |state| {
- TCC.tcc_delete(state);
- val.state = null;
- }
-
- if (val.step == .compiled) {
- // allocator.free(val.step.compiled.buf);
- if (val.step.compiled.js_function) |js_function| {
- JSC.C.JSValueUnprotect(@ptrCast(JSC.C.JSContextRef, val.step.compiled.js_context.?), @ptrCast(JSC.C.JSObjectRef, js_function));
- }
- }
-
- if (val.step == .failed and val.step.failed.allocated) {
- allocator.free(val.step.failed.msg);
- }
- }
-
- pub const Step = union(enum) {
- pending: void,
- compiled: struct {
- ptr: *anyopaque,
- buf: []u8,
- js_function: ?*anyopaque = null,
- js_context: ?*anyopaque = null,
- },
- failed: struct {
- msg: []const u8,
- allocated: bool = false,
- },
- };
-
- const FFI_HEADER: string = @embedFile("./FFI.h");
- pub inline fn ffiHeader() string {
- if (comptime Environment.isDebug) {
- var dirpath = std.fs.path.dirname(@src().file).?;
- var env = std.process.getEnvMap(default_allocator) catch unreachable;
-
- const dir = std.mem.replaceOwned(
- u8,
- default_allocator,
- dirpath,
- "jarred",
- env.get("USER").?,
- ) catch unreachable;
- var runtime_path = std.fs.path.join(default_allocator, &[_]string{ dir, "FFI.h" }) catch unreachable;
- const file = std.fs.openFileAbsolute(runtime_path, .{}) catch @panic("Missing bun/src/javascript/jsc/api/FFI.h.");
- defer file.close();
- return file.readToEndAlloc(default_allocator, (file.stat() catch unreachable).size) catch unreachable;
- } else {
- return FFI_HEADER;
- }
- }
-
- pub fn handleTCCError(ctx: ?*anyopaque, message: [*c]const u8) callconv(.C) void {
- var this = bun.cast(*Function, ctx.?);
- var msg = std.mem.span(message);
- if (msg.len > 0) {
- var offset: usize = 0;
- // the message we get from TCC sometimes has garbage in it
- // i think because we're doing in-memory compilation
- while (offset < msg.len) : (offset += 1) {
- if (msg[offset] > 0x20 and msg[offset] < 0x7f) break;
- }
- msg = msg[offset..];
- }
-
- this.step = .{ .failed = .{ .msg = VirtualMachine.vm.allocator.dupe(u8, msg) catch unreachable, .allocated = true } };
- }
-
- extern fn pthread_jit_write_protect_np(enable: bool) callconv(.C) void;
-
- const MyFunctionSStructWorkAround = struct {
- JSVALUE_TO_INT64: fn (JSValue0: JSC.JSValue) callconv(.C) i64,
- JSVALUE_TO_UINT64: fn (JSValue0: JSC.JSValue) callconv(.C) u64,
- INT64_TO_JSVALUE: fn (arg0: [*c]JSC.JSGlobalObject, arg1: i64) callconv(.C) JSC.JSValue,
- UINT64_TO_JSVALUE: fn (arg0: [*c]JSC.JSGlobalObject, arg1: u64) callconv(.C) JSC.JSValue,
- bun_call: *const @TypeOf(JSC.C.JSObjectCallAsFunction),
- };
- const headers = @import("../bindings/headers.zig");
-
- var workaround: MyFunctionSStructWorkAround = .{
- .JSVALUE_TO_INT64 = headers.JSC__JSValue__toInt64,
- .JSVALUE_TO_UINT64 = headers.JSC__JSValue__toUInt64NoTruncate,
- .INT64_TO_JSVALUE = headers.JSC__JSValue__fromInt64NoTruncate,
- .UINT64_TO_JSVALUE = headers.JSC__JSValue__fromUInt64NoTruncate,
- .bun_call = &JSC.C.JSObjectCallAsFunction,
- };
-
- const tcc_options = "-std=c11 -nostdlib -Wl,--export-all-symbols" ++ if (Environment.isDebug) " -g" else "";
-
- pub fn compile(
- this: *Function,
- allocator: std.mem.Allocator,
- ) !void {
- var source_code = std.ArrayList(u8).init(allocator);
- var source_code_writer = source_code.writer();
- try this.printSourceCode(&source_code_writer);
-
- try source_code.append(0);
- defer source_code.deinit();
-
- var state = TCC.tcc_new() orelse return error.TCCMissing;
- TCC.tcc_set_options(state, tcc_options);
- // addSharedLibPaths(state);
- TCC.tcc_set_error_func(state, this, handleTCCError);
- this.state = state;
- defer {
- if (this.step == .failed) {
- TCC.tcc_delete(state);
- this.state = null;
- }
- }
-
- _ = TCC.tcc_set_output_type(state, TCC.TCC_OUTPUT_MEMORY);
- const Sizes = @import("../bindings/sizes.zig");
-
- var symbol_buf: [256]u8 = undefined;
- TCC.tcc_define_symbol(
- state,
- "Bun_FFI_PointerOffsetToArgumentsList",
- std.fmt.bufPrintZ(&symbol_buf, "{d}", .{Sizes.Bun_FFI_PointerOffsetToArgumentsList}) catch unreachable,
- );
- CompilerRT.define(state);
-
- // TCC.tcc_define_symbol(
- // state,
- // "Bun_FFI_PointerOffsetToArgumentsCount",
- // std.fmt.bufPrintZ(symbol_buf[8..], "{d}", .{Bun_FFI_PointerOffsetToArgumentsCount}) catch unreachable,
- // );
-
- const compilation_result = TCC.tcc_compile_string(
- state,
- source_code.items.ptr,
- );
- // did tcc report an error?
- if (this.step == .failed) {
- return;
- }
-
- // did tcc report failure but never called the error callback?
- if (compilation_result == -1) {
- this.step = .{ .failed = .{ .msg = "tcc returned -1, which means it failed" } };
- return;
- }
- CompilerRT.inject(state);
- _ = TCC.tcc_add_symbol(state, this.base_name.?, this.symbol_from_dynamic_library.?);
-
- if (this.step == .failed) {
- return;
- }
-
- var relocation_size = TCC.tcc_relocate(state, null);
- if (this.step == .failed) {
- return;
- }
-
- if (relocation_size < 0) {
- this.step = .{ .failed = .{ .msg = "tcc_relocate returned a negative value" } };
- return;
- }
-
- var bytes: []u8 = try allocator.rawAlloc(@intCast(usize, relocation_size), 16, 16, 0);
- defer {
- if (this.step == .failed) {
- allocator.free(bytes);
- }
- }
-
- if (comptime Environment.isAarch64 and Environment.isMac) {
- pthread_jit_write_protect_np(false);
- }
- _ = TCC.tcc_relocate(state, bytes.ptr);
- if (comptime Environment.isAarch64 and Environment.isMac) {
- pthread_jit_write_protect_np(true);
- }
-
- var symbol = TCC.tcc_get_symbol(state, "JSFunctionCall") orelse {
- this.step = .{ .failed = .{ .msg = "missing generated symbol in source code" } };
-
- return;
- };
-
- this.step = .{
- .compiled = .{
- .ptr = symbol,
- .buf = bytes,
- },
- };
- return;
- }
- const CompilerRT = struct {
- noinline fn memset(
- dest: [*]u8,
- c: u8,
- byte_count: usize,
- ) callconv(.C) void {
- @memset(dest, c, byte_count);
- }
-
- noinline fn memcpy(
- noalias dest: [*]u8,
- noalias source: [*]const u8,
- byte_count: usize,
- ) callconv(.C) void {
- @memcpy(dest, source, byte_count);
- }
-
- pub fn define(state: *TCC.TCCState) void {
- if (comptime Environment.isX64) {
- _ = TCC.tcc_define_symbol(state, "NEEDS_COMPILER_RT_FUNCTIONS", "1");
- // there
- _ = TCC.tcc_compile_string(state, @embedFile(("libtcc1.c")));
- }
- }
-
- pub fn inject(state: *TCC.TCCState) void {
- _ = TCC.tcc_add_symbol(state, "memset", &memset);
- _ = TCC.tcc_add_symbol(state, "memcpy", &memcpy);
-
- _ = TCC.tcc_add_symbol(
- state,
- "JSVALUE_TO_INT64_SLOW",
- workaround.JSVALUE_TO_INT64,
- );
- _ = TCC.tcc_add_symbol(
- state,
- "JSVALUE_TO_UINT64_SLOW",
- workaround.JSVALUE_TO_UINT64,
- );
- std.mem.doNotOptimizeAway(headers.JSC__JSValue__toUInt64NoTruncate);
- std.mem.doNotOptimizeAway(headers.JSC__JSValue__toInt64);
- std.mem.doNotOptimizeAway(headers.JSC__JSValue__fromInt64NoTruncate);
- std.mem.doNotOptimizeAway(headers.JSC__JSValue__fromUInt64NoTruncate);
- _ = TCC.tcc_add_symbol(
- state,
- "INT64_TO_JSVALUE_SLOW",
- workaround.INT64_TO_JSVALUE,
- );
- _ = TCC.tcc_add_symbol(
- state,
- "UINT64_TO_JSVALUE_SLOW",
- workaround.UINT64_TO_JSVALUE,
- );
- }
- };
-
- pub fn compileCallback(
- this: *Function,
- allocator: std.mem.Allocator,
- js_context: *anyopaque,
- js_function: *anyopaque,
- ) !void {
- Output.debug("welcome", .{});
- var source_code = std.ArrayList(u8).init(allocator);
- var source_code_writer = source_code.writer();
- try this.printCallbackSourceCode(&source_code_writer);
- Output.debug("helllooo", .{});
- try source_code.append(0);
- // defer source_code.deinit();
- var state = TCC.tcc_new() orelse return error.TCCMissing;
- TCC.tcc_set_options(state, tcc_options);
- TCC.tcc_set_error_func(state, this, handleTCCError);
- this.state = state;
- defer {
- if (this.step == .failed) {
- TCC.tcc_delete(state);
- this.state = null;
- }
- }
-
- _ = TCC.tcc_set_output_type(state, TCC.TCC_OUTPUT_MEMORY);
-
- CompilerRT.define(state);
-
- const compilation_result = TCC.tcc_compile_string(
- state,
- source_code.items.ptr,
- );
- Output.debug("compile", .{});
- // did tcc report an error?
- if (this.step == .failed) {
- return;
- }
-
- // did tcc report failure but never called the error callback?
- if (compilation_result == -1) {
- this.step = .{ .failed = .{ .msg = "tcc returned -1, which means it failed" } };
-
- return;
- }
-
- CompilerRT.inject(state);
- Output.debug("here", .{});
- _ = TCC.tcc_add_symbol(state, "bun_call", workaround.bun_call.*);
- _ = TCC.tcc_add_symbol(state, "cachedJSContext", js_context);
- _ = TCC.tcc_add_symbol(state, "cachedCallbackFunction", js_function);
-
- var relocation_size = TCC.tcc_relocate(state, null);
- if (relocation_size == 0) return;
- var bytes: []u8 = try allocator.rawAlloc(@intCast(usize, relocation_size), 16, 16, 0);
- defer {
- if (this.step == .failed) {
- allocator.free(bytes);
- }
- }
-
- if (comptime Environment.isAarch64 and Environment.isMac) {
- pthread_jit_write_protect_np(false);
- }
- _ = TCC.tcc_relocate(state, bytes.ptr);
- if (comptime Environment.isAarch64 and Environment.isMac) {
- pthread_jit_write_protect_np(true);
- }
-
- var symbol = TCC.tcc_get_symbol(state, "my_callback_function") orelse {
- this.step = .{ .failed = .{ .msg = "missing generated symbol in source code" } };
-
- return;
- };
-
- this.step = .{
- .compiled = .{
- .ptr = symbol,
- .buf = bytes,
- .js_function = js_function,
- .js_context = js_context,
- },
- };
- }
-
- pub fn printSourceCode(
- this: *Function,
- writer: anytype,
- ) !void {
- if (this.arg_types.items.len > 0) {
- try writer.writeAll("#define HAS_ARGUMENTS\n");
- }
-
- brk: {
- if (this.return_type.isFloatingPoint()) {
- try writer.writeAll("#define USES_FLOAT 1\n");
- break :brk;
- }
-
- for (this.arg_types.items) |arg| {
- // conditionally include math.h
- if (arg.isFloatingPoint()) {
- try writer.writeAll("#define USES_FLOAT 1\n");
- break;
- }
- }
- }
-
- if (comptime Environment.isRelease) {
- try writer.writeAll(std.mem.span(FFI_HEADER));
- } else {
- try writer.writeAll(ffiHeader());
- }
-
- // -- Generate the FFI function symbol
- try writer.writeAll("/* --- The Function To Call */\n");
- try this.return_type.typename(writer);
- try writer.writeAll(" ");
- try writer.writeAll(std.mem.span(this.base_name.?));
- try writer.writeAll("(");
- var first = true;
- for (this.arg_types.items) |arg, i| {
- if (!first) {
- try writer.writeAll(", ");
- }
- first = false;
- try arg.typename(writer);
- try writer.print(" arg{d}", .{i});
- }
- try writer.writeAll(
- \\);
- \\
- \\
- \\/* ---- Your Wrapper Function ---- */
- \\void* JSFunctionCall(void* globalObject, void* callFrame) {
- \\
- );
-
- if (this.arg_types.items.len > 0) {
- try writer.writeAll(
- \\ LOAD_ARGUMENTS_FROM_CALL_FRAME;
- \\
- );
- for (this.arg_types.items) |arg, i| {
- if (arg.needsACastInC()) {
- if (i < this.arg_types.items.len - 1) {
- try writer.print(
- \\ EncodedJSValue arg{d};
- \\ arg{d}.asInt64 = *argsPtr++;
- \\
- ,
- .{
- i,
- i,
- },
- );
- } else {
- try writer.print(
- \\ EncodedJSValue arg{d};
- \\ arg{d}.asInt64 = *argsPtr;
- \\
- ,
- .{
- i,
- i,
- },
- );
- }
- } else {
- if (i < this.arg_types.items.len - 1) {
- try writer.print(
- \\ int64_t arg{d} = *argsPtr++;
- \\
- ,
- .{
- i,
- },
- );
- } else {
- try writer.print(
- \\ int64_t arg{d} = *argsPtr;
- \\
- ,
- .{
- i,
- },
- );
- }
- }
- }
- }
-
- // try writer.writeAll(
- // "(JSContext ctx, void* function, void* thisObject, size_t argumentCount, const EncodedJSValue arguments[], void* exception);\n\n",
- // );
-
- var arg_buf: [512]u8 = undefined;
-
- try writer.writeAll(" ");
- if (!(this.return_type == .void)) {
- try this.return_type.typename(writer);
- try writer.writeAll(" return_value = ");
- }
- try writer.print("{s}(", .{std.mem.span(this.base_name.?)});
- first = true;
- arg_buf[0..3].* = "arg".*;
- for (this.arg_types.items) |arg, i| {
- if (!first) {
- try writer.writeAll(", ");
- }
- first = false;
-
- try writer.writeAll(" ");
- const lengthBuf = std.fmt.bufPrintIntToSlice(arg_buf["arg".len..], i, 10, .lower, .{});
- const argName = arg_buf[0 .. 3 + lengthBuf.len];
- if (arg.needsACastInC()) {
- try writer.print("{}", .{arg.toC(argName)});
- } else {
- try writer.writeAll(argName);
- }
- }
- try writer.writeAll(");\n");
-
- if (!first) try writer.writeAll("\n");
-
- try writer.writeAll(" ");
-
- try writer.writeAll("return ");
-
- if (!(this.return_type == .void)) {
- try writer.print("{}.asPtr", .{this.return_type.toJS("return_value")});
- } else {
- try writer.writeAll("ValueUndefined.asPtr");
- }
-
- try writer.writeAll(";\n}\n\n");
- }
-
- pub fn printCallbackSourceCode(
- this: *Function,
- writer: anytype,
- ) !void {
- try writer.writeAll("#define IS_CALLBACK 1\n");
-
- brk: {
- if (this.return_type.isFloatingPoint()) {
- try writer.writeAll("#define USES_FLOAT 1\n");
- break :brk;
- }
-
- for (this.arg_types.items) |arg| {
- // conditionally include math.h
- if (arg.isFloatingPoint()) {
- try writer.writeAll("#define USES_FLOAT 1\n");
- break;
- }
- }
- }
-
- if (comptime Environment.isRelease) {
- try writer.writeAll(std.mem.span(FFI_HEADER));
- } else {
- try writer.writeAll(ffiHeader());
- }
-
- // -- Generate the FFI function symbol
- try writer.writeAll("\n \n/* --- The Callback Function */\n");
- try writer.writeAll("/* --- The Callback Function */\n");
- try this.return_type.typename(writer);
- try writer.writeAll(" my_callback_function");
- try writer.writeAll("(");
- var first = true;
- for (this.arg_types.items) |arg, i| {
- if (!first) {
- try writer.writeAll(", ");
- }
- first = false;
- try arg.typename(writer);
- try writer.print(" arg{d}", .{i});
- }
- try writer.writeAll(");\n\n");
-
- first = true;
- try this.return_type.typename(writer);
-
- try writer.writeAll(" my_callback_function");
- try writer.writeAll("(");
- for (this.arg_types.items) |arg, i| {
- if (!first) {
- try writer.writeAll(", ");
- }
- first = false;
- try arg.typename(writer);
- try writer.print(" arg{d}", .{i});
- }
- try writer.writeAll(") {\n");
-
- if (comptime Environment.isDebug) {
- try writer.writeAll("#ifdef INJECT_BEFORE\n");
- try writer.writeAll("INJECT_BEFORE;\n");
- try writer.writeAll("#endif\n");
- }
-
- first = true;
-
- if (this.arg_types.items.len > 0) {
- try writer.print(" EncodedJSValue arguments[{d}] = {{\n", .{this.arg_types.items.len});
-
- var arg_buf: [512]u8 = undefined;
- arg_buf[0.."arg".len].* = "arg".*;
- for (this.arg_types.items) |arg, i| {
- const printed = std.fmt.bufPrintIntToSlice(arg_buf["arg".len..], i, 10, .lower, .{});
- const arg_name = arg_buf[0 .. "arg".len + printed.len];
- try writer.print(" {}", .{arg.toJS(arg_name)});
- if (i < this.arg_types.items.len - 1) {
- try writer.writeAll(",\n");
- }
- }
- try writer.writeAll("\n };\n");
- } else {
- try writer.writeAll(" EncodedJSValue arguments[1] = {{0}};\n");
- }
-
- try writer.writeAll(" ");
- if (!(this.return_type == .void)) {
- try writer.writeAll("EncodedJSValue return_value = {");
- }
- // JSC.C.JSObjectCallAsFunction(
- // ctx,
- // object,
- // thisObject,
- // argumentCount,
- // arguments,
- // exception,
- // );
- try writer.writeAll("bun_call(cachedJSContext, cachedCallbackFunction, (void*)0, ");
- if (this.arg_types.items.len > 0) {
- try writer.print("{d}, &arguments[0], (void*)0)", .{this.arg_types.items.len});
- } else {
- try writer.writeAll("0, &arguments[0], (void*)0)");
- }
-
- if (this.return_type != .void) {
- try writer.print("}};\n return {}", .{this.return_type.toC("return_value")});
- }
-
- try writer.writeAll(";\n}\n\n");
- }
- };
-
- pub const ABIType = enum(i32) {
- char = 0,
-
- int8_t = 1,
- uint8_t = 2,
-
- int16_t = 3,
- uint16_t = 4,
-
- int32_t = 5,
- uint32_t = 6,
-
- int64_t = 7,
- uint64_t = 8,
-
- double = 9,
- float = 10,
-
- bool = 11,
-
- ptr = 12,
-
- @"void" = 13,
-
- cstring = 14,
-
- i64_fast = 15,
- u64_fast = 16,
-
- /// Types that we can directly pass through as an `int64_t`
- pub fn needsACastInC(this: ABIType) bool {
- return switch (this) {
- .char, .int8_t, .uint8_t, .int16_t, .uint16_t, .int32_t, .uint32_t => false,
- else => true,
- };
- }
-
- const map = .{
- .{ "bool", ABIType.bool },
- .{ "c_int", ABIType.int32_t },
- .{ "c_uint", ABIType.uint32_t },
- .{ "char", ABIType.char },
- .{ "char*", ABIType.ptr },
- .{ "double", ABIType.double },
- .{ "f32", ABIType.float },
- .{ "f64", ABIType.double },
- .{ "float", ABIType.float },
- .{ "i16", ABIType.int16_t },
- .{ "i32", ABIType.int32_t },
- .{ "i64", ABIType.int64_t },
- .{ "i8", ABIType.int8_t },
- .{ "int", ABIType.int32_t },
- .{ "int16_t", ABIType.int16_t },
- .{ "int32_t", ABIType.int32_t },
- .{ "int64_t", ABIType.int64_t },
- .{ "int8_t", ABIType.int8_t },
- .{ "isize", ABIType.int64_t },
- .{ "u16", ABIType.uint16_t },
- .{ "u32", ABIType.uint32_t },
- .{ "u64", ABIType.uint64_t },
- .{ "u8", ABIType.uint8_t },
- .{ "uint16_t", ABIType.uint16_t },
- .{ "uint32_t", ABIType.uint32_t },
- .{ "uint64_t", ABIType.uint64_t },
- .{ "uint8_t", ABIType.uint8_t },
- .{ "usize", ABIType.uint64_t },
- .{ "void*", ABIType.ptr },
- .{ "ptr", ABIType.ptr },
- .{ "pointer", ABIType.ptr },
- .{ "void", ABIType.@"void" },
- .{ "cstring", ABIType.@"cstring" },
- .{ "i64_fast", ABIType.i64_fast },
- .{ "u64_fast", ABIType.u64_fast },
- };
- pub const label = ComptimeStringMap(ABIType, map);
- const EnumMapFormatter = struct {
- name: []const u8,
- entry: ABIType,
- pub fn format(self: EnumMapFormatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
- try writer.writeAll("['");
- // these are not all valid identifiers
- try writer.writeAll(self.name);
- try writer.writeAll("']:");
- try std.fmt.formatInt(@enumToInt(self.entry), 10, .lower, .{}, writer);
- try writer.writeAll(",'");
- try std.fmt.formatInt(@enumToInt(self.entry), 10, .lower, .{}, writer);
- try writer.writeAll("':");
- try std.fmt.formatInt(@enumToInt(self.entry), 10, .lower, .{}, writer);
- }
- };
- pub const map_to_js_object = brk: {
- var count: usize = 2;
- for (map) |item, i| {
- var fmt = EnumMapFormatter{ .name = item.@"0", .entry = item.@"1" };
- count += std.fmt.count("{}", .{fmt});
- count += @boolToInt(i > 0);
- }
-
- var buf: [count]u8 = undefined;
- buf[0] = '{';
- buf[buf.len - 1] = '}';
- var end: usize = 1;
- for (map) |item, i| {
- var fmt = EnumMapFormatter{ .name = item.@"0", .entry = item.@"1" };
- if (i > 0) {
- buf[end] = ',';
- end += 1;
- }
- end += (std.fmt.bufPrint(buf[end..], "{}", .{fmt}) catch unreachable).len;
- }
-
- break :brk buf;
- };
-
- pub fn isFloatingPoint(this: ABIType) bool {
- return switch (this) {
- .double, .float => true,
- else => false,
- };
- }
-
- const ToCFormatter = struct {
- symbol: string,
- tag: ABIType,
-
- pub fn format(self: ToCFormatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
- switch (self.tag) {
- .void => {},
- .bool => {
- try writer.print("JSVALUE_TO_BOOL({s})", .{self.symbol});
- },
- .char, .int8_t, .uint8_t, .int16_t, .uint16_t, .int32_t, .uint32_t => {
- try writer.print("JSVALUE_TO_INT32({s})", .{self.symbol});
- },
- .i64_fast, .int64_t => {
- try writer.print("JSVALUE_TO_INT64({s})", .{self.symbol});
- },
- .u64_fast, .uint64_t => {
- try writer.print("JSVALUE_TO_UINT64(globalObject, {s})", .{self.symbol});
- },
- .cstring, .ptr => {
- try writer.print("JSVALUE_TO_PTR({s})", .{self.symbol});
- },
- .double => {
- try writer.print("JSVALUE_TO_DOUBLE({s})", .{self.symbol});
- },
- .float => {
- try writer.print("JSVALUE_TO_FLOAT({s})", .{self.symbol});
- },
- }
- }
- };
-
- const ToJSFormatter = struct {
- symbol: []const u8,
- tag: ABIType,
-
- pub fn format(self: ToJSFormatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
- switch (self.tag) {
- .void => {},
- .bool => {
- try writer.print("BOOLEAN_TO_JSVALUE({s})", .{self.symbol});
- },
- .char, .int8_t, .uint8_t, .int16_t, .uint16_t, .int32_t, .uint32_t => {
- try writer.print("INT32_TO_JSVALUE({s})", .{self.symbol});
- },
- .i64_fast => {
- try writer.print("INT64_TO_JSVALUE(globalObject, {s})", .{self.symbol});
- },
- .int64_t => {
- try writer.print("INT64_TO_JSVALUE_SLOW(globalObject, {s})", .{self.symbol});
- },
- .u64_fast => {
- try writer.print("UINT64_TO_JSVALUE(globalObject, {s})", .{self.symbol});
- },
- .uint64_t => {
- try writer.print("UINT64_TO_JSVALUE_SLOW(globalObject, {s})", .{self.symbol});
- },
- .cstring, .ptr => {
- try writer.print("PTR_TO_JSVALUE({s})", .{self.symbol});
- },
- .double => {
- try writer.print("DOUBLE_TO_JSVALUE({s})", .{self.symbol});
- },
- .float => {
- try writer.print("FLOAT_TO_JSVALUE({s})", .{self.symbol});
- },
- }
- }
- };
-
- pub fn toC(this: ABIType, symbol: string) ToCFormatter {
- return ToCFormatter{ .tag = this, .symbol = symbol };
- }
-
- pub fn toJS(
- this: ABIType,
- symbol: string,
- ) ToJSFormatter {
- return ToJSFormatter{
- .tag = this,
- .symbol = symbol,
- };
- }
-
- pub fn typename(this: ABIType, writer: anytype) !void {
- try writer.writeAll(this.typenameLabel());
- }
-
- pub fn typenameLabel(this: ABIType) []const u8 {
- return switch (this) {
- .cstring, .ptr => "void*",
- .bool => "bool",
- .int8_t => "int8_t",
- .uint8_t => "uint8_t",
- .int16_t => "int16_t",
- .uint16_t => "uint16_t",
- .int32_t => "int32_t",
- .uint32_t => "uint32_t",
- .i64_fast, .int64_t => "int64_t",
- .u64_fast, .uint64_t => "uint64_t",
- .double => "double",
- .float => "float",
- .char => "char",
- .void => "void",
- };
- }
- };
-};