aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile8
-rw-r--r--bench/ffi/ffi-overhead.js419
-rw-r--r--bench/ffi/noop.c5
-rwxr-xr-xbench/ffi/noop.dylibbin0 -> 16759 bytes
-rw-r--r--bench/ffi/noop.js16
-rw-r--r--integration/bunjs-only-snippets/ffi.test.fixture.callback.c211
-rw-r--r--integration/bunjs-only-snippets/ffi.test.fixture.receiver.c211
-rw-r--r--integration/bunjs-only-snippets/ffi.test.js11
-rw-r--r--package.json1
-rw-r--r--src/javascript/jsc/api/FFI.h8
-rw-r--r--src/javascript/jsc/api/ffi.zig90
-rw-r--r--src/javascript/jsc/bindings/Buffer.h1
-rw-r--r--src/javascript/jsc/bindings/JSBuffer.cpp35
-rw-r--r--src/javascript/jsc/bindings/JSBufferConstructorBuiltins.h1
-rw-r--r--src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.cpp13
-rw-r--r--src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.h9
-rw-r--r--src/javascript/jsc/bindings/header-gen.zig2
-rw-r--r--src/javascript/jsc/bindings/headers-cpp.h64
-rw-r--r--src/javascript/jsc/bindings/headers.h2
-rw-r--r--src/javascript/jsc/javascript.zig2
-rw-r--r--types/bun/ffi.d.ts29
21 files changed, 1051 insertions, 87 deletions
diff --git a/Makefile b/Makefile
index f25006370..0e19242cc 100644
--- a/Makefile
+++ b/Makefile
@@ -373,6 +373,12 @@ generate-builtins:
$(shell which python || which python2) $(realpath $(WEBKIT_DIR)/Source/JavaScriptCore/Scripts/generate-js-builtins.py) -i $(realpath src/javascript/jsc/bindings/builtins/js) -o $(realpath src/javascript/jsc/bindings) --framework WebCore --force
$(shell which python || which python2) $(realpath $(WEBKIT_DIR)/Source/JavaScriptCore/Scripts/generate-js-builtins.py) -i $(realpath src/javascript/jsc/bindings/builtins/js) -o $(realpath src/javascript/jsc/bindings) --framework WebCore --wrappers-only
echo '//clang-format off' > /tmp/1.h
+ cat src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.h >> /tmp/1.h
+ cat /tmp/1.h > src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.h
+ echo '//clang-format off' > /tmp/1.h
+ cat src/javascript/jsc/bindings/JSBufferConstructorBuiltins.h >> /tmp/1.h
+ cat /tmp/1.h > src/javascript/jsc/bindings/JSBufferConstructorBuiltins.h
+ echo '//clang-format off' > /tmp/1.h
echo 'namespace Zig { class GlobalObject; }' >> /tmp/1.h
cat /tmp/1.h src/javascript/jsc/bindings/WebCoreJSBuiltinInternals.h > src/javascript/jsc/bindings/WebCoreJSBuiltinInternals.h.1
mv src/javascript/jsc/bindings/WebCoreJSBuiltinInternals.h.1 src/javascript/jsc/bindings/WebCoreJSBuiltinInternals.h
@@ -900,6 +906,8 @@ test-dev: test-dev-with-hmr
jsc-copy-headers:
cp $(WEBKIT_DIR)/Source/JavaScriptCore/heap/WeakHandleOwner.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/WeakHandleOwner.h
+ cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/LazyClassStructureInlines.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/LazyClassStructureInlines.h
+ cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/LazyPropertyInlines.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/LazyPropertyInlines.h
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/JSTypedArrayViewPrototype.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/JSTypedArrayViewPrototype.h
cp $(WEBKIT_DIR)/Source/JavaScriptCore/runtime/JSTypedArrayPrototypes.h $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/JSTypedArrayPrototypes.h
find $(WEBKIT_RELEASE_DIR)/JavaScriptCore/Headers/JavaScriptCore/ -name "*.h" -exec cp {} $(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders/JavaScriptCore/ \;
diff --git a/bench/ffi/ffi-overhead.js b/bench/ffi/ffi-overhead.js
new file mode 100644
index 000000000..841c59992
--- /dev/null
+++ b/bench/ffi/ffi-overhead.js
@@ -0,0 +1,419 @@
+import {
+ viewSource,
+ dlopen,
+ CString,
+ ptr,
+ toBuffer,
+ toArrayBuffer,
+ FFIType,
+ callback,
+} from "bun:ffi";
+import { bench, group, run } from "mitata";
+
+const types = {
+ returns_true: {
+ return_type: "bool",
+ args: [],
+ },
+ returns_false: {
+ return_type: "bool",
+ args: [],
+ },
+ returns_42_char: {
+ return_type: "char",
+ args: [],
+ },
+ // returns_42_float: {
+ // return_type: "float",
+ // args: [],
+ // },
+ // returns_42_double: {
+ // return_type: "double",
+ // args: [],
+ // },
+ returns_42_uint8_t: {
+ return_type: "uint8_t",
+ args: [],
+ },
+ returns_neg_42_int8_t: {
+ return_type: "int8_t",
+ args: [],
+ },
+ returns_42_uint16_t: {
+ return_type: "uint16_t",
+ args: [],
+ },
+ returns_42_uint32_t: {
+ return_type: "uint32_t",
+ args: [],
+ },
+ // // returns_42_uint64_t: {
+ // // return_type: "uint64_t",
+ // // args: [],
+ // // },
+ returns_neg_42_int16_t: {
+ return_type: "int16_t",
+ args: [],
+ },
+ returns_neg_42_int32_t: {
+ return_type: "int32_t",
+ args: [],
+ },
+ // returns_neg_42_int64_t: {
+ // return_type: "int64_t",
+ // args: [],
+ // },
+
+ identity_char: {
+ return_type: "char",
+ args: ["char"],
+ },
+ // identity_float: {
+ // return_type: "float",
+ // args: ["float"],
+ // },
+ identity_bool: {
+ return_type: "bool",
+ args: ["bool"],
+ },
+ // identity_double: {
+ // return_type: "double",
+ // args: ["double"],
+ // },
+ identity_int8_t: {
+ return_type: "int8_t",
+ args: ["int8_t"],
+ },
+ identity_int16_t: {
+ return_type: "int16_t",
+ args: ["int16_t"],
+ },
+ identity_int32_t: {
+ return_type: "int32_t",
+ args: ["int32_t"],
+ },
+ // identity_int64_t: {
+ // return_type: "int64_t",
+ // args: ["int64_t"],
+ // },
+ identity_uint8_t: {
+ return_type: "uint8_t",
+ args: ["uint8_t"],
+ },
+ identity_uint16_t: {
+ return_type: "uint16_t",
+ args: ["uint16_t"],
+ },
+ identity_uint32_t: {
+ return_type: "uint32_t",
+ args: ["uint32_t"],
+ },
+ // identity_uint64_t: {
+ // return_type: "uint64_t",
+ // args: ["uint64_t"],
+ // },
+
+ add_char: {
+ return_type: "char",
+ args: ["char", "char"],
+ },
+ add_float: {
+ return_type: "float",
+ args: ["float", "float"],
+ },
+ add_double: {
+ return_type: "double",
+ args: ["double", "double"],
+ },
+ add_int8_t: {
+ return_type: "int8_t",
+ args: ["int8_t", "int8_t"],
+ },
+ add_int16_t: {
+ return_type: "int16_t",
+ args: ["int16_t", "int16_t"],
+ },
+ add_int32_t: {
+ return_type: "int32_t",
+ args: ["int32_t", "int32_t"],
+ },
+ // add_int64_t: {
+ // return_type: "int64_t",
+ // args: ["int64_t", "int64_t"],
+ // },
+ add_uint8_t: {
+ return_type: "uint8_t",
+ args: ["uint8_t", "uint8_t"],
+ },
+ add_uint16_t: {
+ return_type: "uint16_t",
+ args: ["uint16_t", "uint16_t"],
+ },
+ add_uint32_t: {
+ return_type: "uint32_t",
+ args: ["uint32_t", "uint32_t"],
+ },
+
+ does_pointer_equal_42_as_int32_t: {
+ return_type: "bool",
+ args: ["ptr"],
+ },
+
+ ptr_should_point_to_42_as_int32_t: {
+ return_type: "ptr",
+ args: [],
+ },
+ identity_ptr: {
+ return_type: "ptr",
+ args: ["ptr"],
+ },
+ // add_uint64_t: {
+ // return_type: "uint64_t",
+ // args: ["uint64_t", "uint64_t"],
+ // },
+
+ cb_identity_true: {
+ return_type: "bool",
+ args: ["ptr"],
+ },
+ cb_identity_false: {
+ return_type: "bool",
+ args: ["ptr"],
+ },
+ cb_identity_42_char: {
+ return_type: "char",
+ args: ["ptr"],
+ },
+ // cb_identity_42_float: {
+ // return_type: "float",
+ // args: ["ptr"],
+ // },
+ // cb_identity_42_double: {
+ // return_type: "double",
+ // args: ["ptr"],
+ // },
+ cb_identity_42_uint8_t: {
+ return_type: "uint8_t",
+ args: ["ptr"],
+ },
+ cb_identity_neg_42_int8_t: {
+ return_type: "int8_t",
+ args: ["ptr"],
+ },
+ cb_identity_42_uint16_t: {
+ return_type: "uint16_t",
+ args: ["ptr"],
+ },
+ cb_identity_42_uint32_t: {
+ return_type: "uint32_t",
+ args: ["ptr"],
+ },
+ // cb_identity_42_uint64_t: {
+ // return_type: "uint64_t",
+ // args: ["ptr"],
+ // },
+ cb_identity_neg_42_int16_t: {
+ return_type: "int16_t",
+ args: ["ptr"],
+ },
+ cb_identity_neg_42_int32_t: {
+ return_type: "int32_t",
+ args: ["ptr"],
+ },
+ // cb_identity_neg_42_int64_t: {
+ // return_type: "int64_t",
+ // args: ["ptr"],
+ // },
+
+ return_a_function_ptr_to_function_that_returns_true: {
+ return_type: "ptr",
+ args: [],
+ },
+};
+
+const {
+ symbols: {
+ returns_true,
+ returns_false,
+ return_a_function_ptr_to_function_that_returns_true,
+ returns_42_char,
+ returns_42_float,
+ returns_42_double,
+ returns_42_uint8_t,
+ returns_neg_42_int8_t,
+ returns_42_uint16_t,
+ returns_42_uint32_t,
+ returns_42_uint64_t,
+ returns_neg_42_int16_t,
+ returns_neg_42_int32_t,
+ returns_neg_42_int64_t,
+ identity_char,
+ identity_float,
+ identity_bool,
+ identity_double,
+ identity_int8_t,
+ identity_int16_t,
+ identity_int32_t,
+ identity_int64_t,
+ identity_uint8_t,
+ identity_uint16_t,
+ identity_uint32_t,
+ identity_uint64_t,
+ add_char,
+ add_float,
+ add_double,
+ add_int8_t,
+ add_int16_t,
+ add_int32_t,
+ add_int64_t,
+ add_uint8_t,
+ add_uint16_t,
+ identity_ptr,
+ add_uint32_t,
+ add_uint64_t,
+ does_pointer_equal_42_as_int32_t,
+ ptr_should_point_to_42_as_int32_t,
+ cb_identity_true,
+ cb_identity_false,
+ cb_identity_42_char,
+ cb_identity_42_float,
+ cb_identity_42_double,
+ cb_identity_42_uint8_t,
+ cb_identity_neg_42_int8_t,
+ cb_identity_42_uint16_t,
+ cb_identity_42_uint32_t,
+ cb_identity_42_uint64_t,
+ cb_identity_neg_42_int16_t,
+ cb_identity_neg_42_int32_t,
+ cb_identity_neg_42_int64_t,
+ },
+ close,
+} = dlopen("/tmp/bun-ffi-test.dylib", types);
+
+group("add_char", () => {
+ bench("add_char (raw)", () => raw_add_char(1, 1));
+ bench("add_char", () => add_char(1, 1));
+});
+group("add_int16_t", () => {
+ bench("add_int16_t (raw)", () => raw_add_int16_t(1, 1));
+ bench("add_int16_t", () => add_int16_t(1, 1));
+});
+group("add_int32_t", () => {
+ bench("add_int32_t (raw)", () => raw_add_int32_t(1, 1));
+ bench("add_int32_t", () => add_int32_t(1, 1));
+});
+group("add_int8_t", () => {
+ bench("add_int8_t (raw)", () => raw_add_int8_t(1, 1));
+ bench("add_int8_t", () => add_int8_t(1, 1));
+});
+group("add_uint16_t", () => {
+ bench("add_uint16_t (raw)", () => raw_add_uint16_t(1, 1));
+ bench("add_uint16_t", () => add_uint16_t(1, 1));
+});
+group("add_uint32_t", () => {
+ bench("add_uint32_t (raw)", () => raw_add_uint32_t(1, 1));
+ bench("add_uint32_t", () => add_uint32_t(1, 1));
+});
+group("add_uint8_t", () => {
+ bench("add_uint8_t (raw)", () => raw_add_uint8_t(1, 1));
+ bench("add_uint8_t", () => add_uint8_t(1, 1));
+});
+group("identity_bool", () => {
+ bench("identity_bool (raw)", () => raw_identity_bool(false));
+ bench("identity_bool", () => identity_bool(true));
+});
+group("identity_char", () => {
+ bench("identity_char (raw)", () => raw_identity_char(10));
+ bench("identity_char", () => identity_char(10));
+});
+group("identity_int16_t", () => {
+ bench("identity_int16_t (raw)", () => raw_identity_int16_t(10));
+ bench("identity_int16_t", () => identity_int16_t(10));
+});
+group("identity_int32_t", () => {
+ bench("identity_int32_t (raw)", () => raw_identity_int32_t(10));
+ bench("identity_int32_t", () => identity_int32_t(10));
+});
+group("identity_int8_t", () => {
+ bench("identity_int8_t (raw)", () => raw_identity_int8_t(10));
+ bench("identity_int8_t", () => identity_int8_t(10));
+});
+group("identity_uint16_t", () => {
+ bench("identity_uint16_t (raw)", () => raw_identity_uint16_t(10));
+ bench("identity_uint16_t", () => identity_uint16_t(10));
+});
+group("identity_uint32_t", () => {
+ bench("identity_uint32_t (raw)", () => raw_identity_uint32_t(10));
+ bench("identity_uint32_t", () => identity_uint32_t(10));
+});
+group("identity_uint8_t", () => {
+ bench("identity_uint8_t (raw)", () => raw_identity_uint8_t(10));
+ bench("identity_uint8_t", () => identity_uint8_t(10));
+});
+group("returns_42_char", () => {
+ bench("returns_42_char (raw)", () => raw_returns_42_char());
+ bench("returns_42_char", () => returns_42_char());
+});
+group("returns_42_uint16_t", () => {
+ bench("returns_42_uint16_t (raw)", () => raw_returns_42_uint16_t());
+ bench("returns_42_uint16_t", () => returns_42_uint16_t());
+});
+group("returns_42_uint32_t", () => {
+ bench("returns_42_uint32_t (raw)", () => raw_returns_42_uint32_t());
+ bench("returns_42_uint32_t", () => returns_42_uint32_t());
+});
+group("returns_42_uint8_t", () => {
+ bench("returns_42_uint8_t (raw)", () => raw_returns_42_uint8_t());
+ bench("returns_42_uint8_t", () => returns_42_uint8_t());
+});
+group("returns_false", () => {
+ bench("returns_false (raw)", () => raw_returns_false());
+ bench("returns_false", () => returns_false());
+});
+group("returns_neg_42_int16_t", () => {
+ bench("returns_neg_42_int16_t (raw)", () => raw_returns_neg_42_int16_t());
+ bench("returns_neg_42_int16_t", () => returns_neg_42_int16_t());
+});
+group("returns_neg_42_int32_t", () => {
+ bench("returns_neg_42_int32_t (raw)", () => raw_returns_neg_42_int32_t());
+ bench("returns_neg_42_int32_t", () => returns_neg_42_int32_t());
+});
+group("returns_neg_42_int8_t", () => {
+ bench("returns_neg_42_int8_t (raw)", () => raw_returns_neg_42_int8_t());
+ bench("returns_neg_42_int8_t", () => returns_neg_42_int8_t());
+});
+group("returns_true", () => {
+ bench("returns_true (raw)", () => raw_returns_true());
+ bench("returns_true", () => returns_true());
+});
+
+var raw_returns_true = returns_true.native ?? returns_true;
+var raw_returns_false = returns_false.native ?? returns_false;
+var raw_returns_42_char = returns_42_char.native ?? returns_42_char;
+var raw_returns_42_uint8_t = returns_42_uint8_t.native ?? returns_42_uint8_t;
+var raw_returns_neg_42_int8_t =
+ returns_neg_42_int8_t.native ?? returns_neg_42_int8_t;
+var raw_returns_42_uint16_t = returns_42_uint16_t.native ?? returns_42_uint16_t;
+var raw_returns_42_uint32_t = returns_42_uint32_t.native ?? returns_42_uint32_t;
+var raw_returns_neg_42_int16_t =
+ returns_neg_42_int16_t.native ?? returns_neg_42_int16_t;
+var raw_returns_neg_42_int32_t =
+ returns_neg_42_int32_t.native ?? returns_neg_42_int32_t;
+var raw_identity_char = identity_char.native ?? identity_char;
+var raw_identity_bool = identity_bool.native ?? identity_bool;
+var raw_identity_bool = identity_bool.native ?? identity_bool;
+var raw_identity_int8_t = identity_int8_t.native ?? identity_int8_t;
+var raw_identity_int16_t = identity_int16_t.native ?? identity_int16_t;
+var raw_identity_int32_t = identity_int32_t.native ?? identity_int32_t;
+var raw_identity_uint8_t = identity_uint8_t.native ?? identity_uint8_t;
+var raw_identity_uint16_t = identity_uint16_t.native ?? identity_uint16_t;
+var raw_identity_uint32_t = identity_uint32_t.native ?? identity_uint32_t;
+var raw_add_char = add_char.native ?? add_char;
+var raw_add_int8_t = add_int8_t.native ?? add_int8_t;
+var raw_add_int16_t = add_int16_t.native ?? add_int16_t;
+var raw_add_int32_t = add_int32_t.native ?? add_int32_t;
+var raw_add_uint8_t = add_uint8_t.native ?? add_uint8_t;
+var raw_add_uint16_t = add_uint16_t.native ?? add_uint16_t;
+var raw_add_uint32_t = add_uint32_t.native ?? add_uint32_t;
+
+run({ collect: false, percentiles: true });
diff --git a/bench/ffi/noop.c b/bench/ffi/noop.c
new file mode 100644
index 000000000..6b93beeaf
--- /dev/null
+++ b/bench/ffi/noop.c
@@ -0,0 +1,5 @@
+// clang -O3 -shared -undefined dynamic_lookup ./noop.c -o noop.dylib
+
+int noop();
+
+int noop() { return 1; } \ No newline at end of file
diff --git a/bench/ffi/noop.dylib b/bench/ffi/noop.dylib
new file mode 100755
index 000000000..74a1d3155
--- /dev/null
+++ b/bench/ffi/noop.dylib
Binary files differ
diff --git a/bench/ffi/noop.js b/bench/ffi/noop.js
new file mode 100644
index 000000000..e28ea0629
--- /dev/null
+++ b/bench/ffi/noop.js
@@ -0,0 +1,16 @@
+import { dlopen } from "bun:ffi";
+import { bench, run } from "mitata";
+
+const {
+ symbols: { noop },
+} = dlopen("./noop.dylib", {
+ noop: {
+ args: [],
+ return_type: "i32",
+ },
+});
+var raw = Object.keys(noop);
+bench("noop", () => {
+ raw();
+});
+run({ collect: false, percentiles: true });
diff --git a/integration/bunjs-only-snippets/ffi.test.fixture.callback.c b/integration/bunjs-only-snippets/ffi.test.fixture.callback.c
new file mode 100644
index 000000000..a428926ef
--- /dev/null
+++ b/integration/bunjs-only-snippets/ffi.test.fixture.callback.c
@@ -0,0 +1,211 @@
+#define IS_CALLBACK 1
+// This file is part of Bun!
+// You can find the original source:
+// https://github.com/Jarred-Sumner/bun/blob/main/src/javascript/jsc/api/FFI.h#L2
+//
+// clang-format off
+// This file is only compatible with 64 bit CPUs
+// It must be kept in sync with JSCJSValue.h
+// https://github.com/Jarred-Sumner/WebKit/blob/72c2052b781cbfd4af867ae79ac9de460e392fba/Source/JavaScriptCore/runtime/JSCJSValue.h#L455-L458
+#ifdef IS_CALLBACK
+// #define INJECT_BEFORE printf("bun_call %p cachedJSContext %p cachedCallbackFunction %p\n", &bun_call, cachedJSContext, cachedCallbackFunction);
+#endif
+
+#define IS_BIG_ENDIAN 0
+#define USE_JSVALUE64 1
+#define USE_JSVALUE32_64 0
+
+// #include <stdint.h>
+#ifdef INJECT_BEFORE
+// #include <stdio.h>
+#endif
+// #include <tcclib.h>
+
+// // /* 7.18.1.1 Exact-width integer types */
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+typedef short int16_t;
+typedef unsigned short uint16_t;
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+typedef uint64_t size_t;
+typedef long intptr_t;
+typedef uint64_t uintptr_t;
+typedef _Bool bool;
+
+#define true 1
+#define false 0
+
+#ifdef USES_FLOAT
+// https://git.musl-libc.org/cgit/musl/tree/src/math/trunc.c
+double trunc(double x);
+double trunc(double x)
+{
+ union {double f; uint64_t i;} u = {x};
+ int e = (int)(u.i >> 52 & 0x7ff) - 0x3ff + 12;
+ uint64_t m;
+
+ if (e >= 52 + 12)
+ return x;
+ if (e < 12)
+ e = 1;
+ m = -1ULL >> e;
+ if ((u.i & m) == 0)
+ return x;
+ x + 0x1p120f;
+ u.i &= ~m;
+ return u.f;
+}
+#endif
+
+
+// This value is 2^49, used to encode doubles such that the encoded value will
+// begin with a 15-bit pattern within the range 0x0002..0xFFFC.
+#define DoubleEncodeOffsetBit 49
+#define DoubleEncodeOffset (1ll << DoubleEncodeOffsetBit)
+#define OtherTag 0x2
+#define BoolTag 0x4
+#define UndefinedTag 0x8
+#define TagValueFalse (OtherTag | BoolTag | false)
+#define TagValueTrue (OtherTag | BoolTag | true)
+#define TagValueUndefined (OtherTag | UndefinedTag)
+#define TagValueNull (OtherTag)
+
+// If all bits in the mask are set, this indicates an integer number,
+// if any but not all are set this value is a double precision number.
+#define NumberTag 0xfffe000000000000ll
+
+typedef void* JSCell;
+
+typedef union EncodedJSValue {
+ int64_t asInt64;
+#if USE_JSVALUE32_64
+ double asDouble;
+#elif USE_JSVALUE64
+ JSCell *ptr;
+#endif
+
+#if IS_BIG_ENDIAN
+ struct {
+ int32_t tag;
+ int32_t payload;
+ } asBits;
+#else
+ struct {
+ int32_t payload;
+ int32_t tag;
+ } asBits;
+#endif
+
+ void* asPtr;
+} EncodedJSValue;
+
+EncodedJSValue ValueUndefined = { TagValueUndefined };
+EncodedJSValue ValueTrue = { TagValueTrue };
+
+typedef void* JSContext;
+
+#define LOAD_ARGUMENTS_FROM_CALL_FRAME EncodedJSValue* args = (EncodedJSValue*)((size_t*)callFrame + Bun_FFI_PointerOffsetToArgumentsList);
+
+
+#ifdef IS_CALLBACK
+extern int64_t bun_call(JSContext, void* func, void* thisValue, size_t len, const EncodedJSValue args[], void* exception);
+JSContext cachedJSContext;
+void* cachedCallbackFunction;
+#endif
+
+static EncodedJSValue INT32_TO_JSVALUE(int32_t val) __attribute__((__always_inline__));
+static EncodedJSValue DOUBLE_TO_JSVALUE(double val) __attribute__((__always_inline__));
+static EncodedJSValue FLOAT_TO_JSVALUE(float val) __attribute__((__always_inline__));
+static EncodedJSValue BOOLEAN_TO_JSVALUE(bool val) __attribute__((__always_inline__));
+static EncodedJSValue PTR_TO_JSVALUE(void* ptr) __attribute__((__always_inline__));
+
+static void* JSVALUE_TO_PTR(EncodedJSValue val) __attribute__((__always_inline__));
+static int32_t JSVALUE_TO_INT32(EncodedJSValue val) __attribute__((__always_inline__));
+static float JSVALUE_TO_FLOAT(EncodedJSValue val) __attribute__((__always_inline__));
+static double JSVALUE_TO_DOUBLE(EncodedJSValue val) __attribute__((__always_inline__));
+static bool JSVALUE_TO_BOOL(EncodedJSValue val) __attribute__((__always_inline__));
+
+static void* JSVALUE_TO_PTR(EncodedJSValue val) {
+ // must be a double
+ return (void*)(val.asInt64 - DoubleEncodeOffset);
+}
+
+static EncodedJSValue PTR_TO_JSVALUE(void* ptr) {
+ EncodedJSValue val;
+ val.asInt64 = (int64_t)ptr + DoubleEncodeOffset;
+ return val;
+}
+
+static int32_t JSVALUE_TO_INT32(EncodedJSValue val) {
+ return val.asInt64;
+}
+
+static EncodedJSValue INT32_TO_JSVALUE(int32_t val) {
+ EncodedJSValue res;
+ res.asInt64 = NumberTag | (uint32_t)val;
+ return res;
+}
+
+static EncodedJSValue DOUBLE_TO_JSVALUE(double val) {
+ EncodedJSValue res;
+#ifdef USES_FLOAT
+ res.asInt64 = trunc(val) == val ? val : val - DoubleEncodeOffset;
+#else
+// should never get here
+ res.asInt64 = 0xa;
+#endif
+ return res;
+}
+
+static EncodedJSValue FLOAT_TO_JSVALUE(float val) {
+ return DOUBLE_TO_JSVALUE(val);
+}
+
+static EncodedJSValue BOOLEAN_TO_JSVALUE(bool val) {
+ EncodedJSValue res;
+ res.asInt64 = val ? TagValueTrue : TagValueFalse;
+ return res;
+}
+
+
+static double JSVALUE_TO_DOUBLE(EncodedJSValue val) {
+ return val.asInt64 + DoubleEncodeOffset;
+}
+
+static float JSVALUE_TO_FLOAT(EncodedJSValue val) {
+ return (float)JSVALUE_TO_DOUBLE(val);
+}
+
+static bool JSVALUE_TO_BOOL(EncodedJSValue val) {
+ return val.asInt64 == TagValueTrue;
+}
+
+#define arg(i) ((EncodedJSValue*)args)[i]
+void* JSFunctionCall(void* globalObject, void* callFrame);
+// int64_t JSFunctionCall(void* globalObject, void* callFrame) {
+// EncodedJSValue* args = (EncodedJSValue*)((unsigned char*)callFrame + Bun_FFI_PointerOffsetToArgumentsList);
+// }
+
+
+
+// --- Generated Code ---
+
+
+/* --- The Callback Function */
+/* --- The Callback Function */
+bool my_callback_function(void* arg0);
+
+bool my_callback_function(, void* arg0) {
+#ifdef INJECT_BEFORE
+INJECT_BEFORE;
+#endif
+ EncodedJSValue arguments[1] = {
+void* PTR_TO_JSVALUE(arg0)
+ };
+ EncodedJSValue return_value = {bun_call(cachedJSContext, cachedCallbackFunction, (void*)0, 1, arguments, 0)};
+ return JSVALUE_TO_BOOL(return_value);
+}
+
diff --git a/integration/bunjs-only-snippets/ffi.test.fixture.receiver.c b/integration/bunjs-only-snippets/ffi.test.fixture.receiver.c
new file mode 100644
index 000000000..2107b684e
--- /dev/null
+++ b/integration/bunjs-only-snippets/ffi.test.fixture.receiver.c
@@ -0,0 +1,211 @@
+#define HAS_ARGUMENTS
+// This file is part of Bun!
+// You can find the original source:
+// https://github.com/Jarred-Sumner/bun/blob/main/src/javascript/jsc/api/FFI.h#L2
+//
+// clang-format off
+// This file is only compatible with 64 bit CPUs
+// It must be kept in sync with JSCJSValue.h
+// https://github.com/Jarred-Sumner/WebKit/blob/72c2052b781cbfd4af867ae79ac9de460e392fba/Source/JavaScriptCore/runtime/JSCJSValue.h#L455-L458
+#ifdef IS_CALLBACK
+// #define INJECT_BEFORE printf("bun_call %p cachedJSContext %p cachedCallbackFunction %p\n", &bun_call, cachedJSContext, cachedCallbackFunction);
+#endif
+
+#define IS_BIG_ENDIAN 0
+#define USE_JSVALUE64 1
+#define USE_JSVALUE32_64 0
+
+// #include <stdint.h>
+#ifdef INJECT_BEFORE
+// #include <stdio.h>
+#endif
+// #include <tcclib.h>
+
+// // /* 7.18.1.1 Exact-width integer types */
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+typedef short int16_t;
+typedef unsigned short uint16_t;
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+typedef uint64_t size_t;
+typedef long intptr_t;
+typedef uint64_t uintptr_t;
+typedef _Bool bool;
+
+#define true 1
+#define false 0
+
+#ifdef USES_FLOAT
+// https://git.musl-libc.org/cgit/musl/tree/src/math/trunc.c
+double trunc(double x);
+double trunc(double x)
+{
+ union {double f; uint64_t i;} u = {x};
+ int e = (int)(u.i >> 52 & 0x7ff) - 0x3ff + 12;
+ uint64_t m;
+
+ if (e >= 52 + 12)
+ return x;
+ if (e < 12)
+ e = 1;
+ m = -1ULL >> e;
+ if ((u.i & m) == 0)
+ return x;
+ x + 0x1p120f;
+ u.i &= ~m;
+ return u.f;
+}
+#endif
+
+
+// This value is 2^49, used to encode doubles such that the encoded value will
+// begin with a 15-bit pattern within the range 0x0002..0xFFFC.
+#define DoubleEncodeOffsetBit 49
+#define DoubleEncodeOffset (1ll << DoubleEncodeOffsetBit)
+#define OtherTag 0x2
+#define BoolTag 0x4
+#define UndefinedTag 0x8
+#define TagValueFalse (OtherTag | BoolTag | false)
+#define TagValueTrue (OtherTag | BoolTag | true)
+#define TagValueUndefined (OtherTag | UndefinedTag)
+#define TagValueNull (OtherTag)
+
+// If all bits in the mask are set, this indicates an integer number,
+// if any but not all are set this value is a double precision number.
+#define NumberTag 0xfffe000000000000ll
+
+typedef void* JSCell;
+
+typedef union EncodedJSValue {
+ int64_t asInt64;
+#if USE_JSVALUE32_64
+ double asDouble;
+#elif USE_JSVALUE64
+ JSCell *ptr;
+#endif
+
+#if IS_BIG_ENDIAN
+ struct {
+ int32_t tag;
+ int32_t payload;
+ } asBits;
+#else
+ struct {
+ int32_t payload;
+ int32_t tag;
+ } asBits;
+#endif
+
+ void* asPtr;
+} EncodedJSValue;
+
+EncodedJSValue ValueUndefined = { TagValueUndefined };
+EncodedJSValue ValueTrue = { TagValueTrue };
+
+typedef void* JSContext;
+
+#define LOAD_ARGUMENTS_FROM_CALL_FRAME EncodedJSValue* args = (EncodedJSValue*)((size_t*)callFrame + Bun_FFI_PointerOffsetToArgumentsList);
+
+
+#ifdef IS_CALLBACK
+extern int64_t bun_call(JSContext, void* func, void* thisValue, size_t len, const EncodedJSValue args[], void* exception);
+JSContext cachedJSContext;
+void* cachedCallbackFunction;
+#endif
+
+static EncodedJSValue INT32_TO_JSVALUE(int32_t val) __attribute__((__always_inline__));
+static EncodedJSValue DOUBLE_TO_JSVALUE(double val) __attribute__((__always_inline__));
+static EncodedJSValue FLOAT_TO_JSVALUE(float val) __attribute__((__always_inline__));
+static EncodedJSValue BOOLEAN_TO_JSVALUE(bool val) __attribute__((__always_inline__));
+static EncodedJSValue PTR_TO_JSVALUE(void* ptr) __attribute__((__always_inline__));
+
+static void* JSVALUE_TO_PTR(EncodedJSValue val) __attribute__((__always_inline__));
+static int32_t JSVALUE_TO_INT32(EncodedJSValue val) __attribute__((__always_inline__));
+static float JSVALUE_TO_FLOAT(EncodedJSValue val) __attribute__((__always_inline__));
+static double JSVALUE_TO_DOUBLE(EncodedJSValue val) __attribute__((__always_inline__));
+static bool JSVALUE_TO_BOOL(EncodedJSValue val) __attribute__((__always_inline__));
+
+static void* JSVALUE_TO_PTR(EncodedJSValue val) {
+ // must be a double
+ return (void*)(val.asInt64 - DoubleEncodeOffset);
+}
+
+static EncodedJSValue PTR_TO_JSVALUE(void* ptr) {
+ EncodedJSValue val;
+ val.asInt64 = (int64_t)ptr + DoubleEncodeOffset;
+ return val;
+}
+
+static int32_t JSVALUE_TO_INT32(EncodedJSValue val) {
+ return val.asInt64;
+}
+
+static EncodedJSValue INT32_TO_JSVALUE(int32_t val) {
+ EncodedJSValue res;
+ res.asInt64 = NumberTag | (uint32_t)val;
+ return res;
+}
+
+static EncodedJSValue DOUBLE_TO_JSVALUE(double val) {
+ EncodedJSValue res;
+#ifdef USES_FLOAT
+ res.asInt64 = trunc(val) == val ? val : val - DoubleEncodeOffset;
+#else
+// should never get here
+ res.asInt64 = 0xa;
+#endif
+ return res;
+}
+
+static EncodedJSValue FLOAT_TO_JSVALUE(float val) {
+ return DOUBLE_TO_JSVALUE(val);
+}
+
+static EncodedJSValue BOOLEAN_TO_JSVALUE(bool val) {
+ EncodedJSValue res;
+ res.asInt64 = val ? TagValueTrue : TagValueFalse;
+ return res;
+}
+
+
+static double JSVALUE_TO_DOUBLE(EncodedJSValue val) {
+ return val.asInt64 + DoubleEncodeOffset;
+}
+
+static float JSVALUE_TO_FLOAT(EncodedJSValue val) {
+ return (float)JSVALUE_TO_DOUBLE(val);
+}
+
+static bool JSVALUE_TO_BOOL(EncodedJSValue val) {
+ return val.asInt64 == TagValueTrue;
+}
+
+#define arg(i) ((EncodedJSValue*)args)[i]
+void* JSFunctionCall(void* globalObject, void* callFrame);
+// int64_t JSFunctionCall(void* globalObject, void* callFrame) {
+// EncodedJSValue* args = (EncodedJSValue*)((unsigned char*)callFrame + Bun_FFI_PointerOffsetToArgumentsList);
+// }
+
+
+
+// --- Generated Code ---
+/* --- The Function To Call */
+void callback(void* arg0);
+
+/* ---- Your Wrapper Function ---- */
+void* JSFunctionCall(void* globalObject, void* callFrame) {
+#ifdef HAS_ARGUMENTS
+ LOAD_ARGUMENTS_FROM_CALL_FRAME;
+#endif
+#ifdef INJECT_BEFORE
+//Bun_FFI_PointerOffsetToArgumentsList: 6
+//Bun_FFI_PointerOffsetToArgumentsCount: 0
+#endif
+ callback( JSVALUE_TO_PTR(arg(0)));
+
+ return ValueUndefined.asPtr;
+}
+
diff --git a/integration/bunjs-only-snippets/ffi.test.js b/integration/bunjs-only-snippets/ffi.test.js
index fb297dae2..14a38d6b2 100644
--- a/integration/bunjs-only-snippets/ffi.test.js
+++ b/integration/bunjs-only-snippets/ffi.test.js
@@ -14,17 +14,17 @@ import {
it("ffi print", async () => {
await Bun.write(
- "ffi.test.fixture.callback.c",
+ import.meta.dir + "/ffi.test.fixture.callback.c",
viewSource(
{
return_type: "bool",
- args: [],
+ args: ["ptr"],
},
true
)
);
await Bun.write(
- "ffi.test.fixture.receiver.c",
+ import.meta.dir + "/ffi.test.fixture.receiver.c",
viewSource(
{
callback: {
@@ -349,6 +349,7 @@ it("ffi run", () => {
// expect(returns_42_uint64_t()).toBe(42);
expect(returns_neg_42_int16_t()).toBe(-42);
expect(returns_neg_42_int32_t()).toBe(-42);
+ expect(identity_int32_t(10)).toBe(10);
// expect(returns_neg_42_int64_t()).toBe(-42);
expect(identity_char(10)).toBe(10);
// expect(identity_float(10.1)).toBe(10.1);
@@ -357,7 +358,7 @@ it("ffi run", () => {
// expect(identity_double(10.1)).toBe(10.1);
expect(identity_int8_t(10)).toBe(10);
expect(identity_int16_t(10)).toBe(10);
- expect(identity_int32_t(10)).toBe(10);
+
// expect(identity_int64_t(10)).toBe(10);
expect(identity_uint8_t(10)).toBe(10);
expect(identity_uint16_t(10)).toBe(10);
@@ -383,7 +384,7 @@ it("ffi run", () => {
42
);
expect(ptr(buffer)).toBe(cptr);
- expect(new CString(cptr, 0, 1)).toBe("*");
+ expect(new CString(cptr, 0, 1).toString()).toBe("*");
expect(identity_ptr(cptr)).toBe(cptr);
const second_ptr = ptr(new Buffer(8));
expect(identity_ptr(second_ptr)).toBe(second_ptr);
diff --git a/package.json b/package.json
index af8acaa67..1e7a82c3f 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,6 @@
{
"dependencies": {
+ "mitata": "^0.0.10",
"peechy": "0.4.32",
"react": "^17.0.2"
},
diff --git a/src/javascript/jsc/api/FFI.h b/src/javascript/jsc/api/FFI.h
index 48e4db48d..096abcfd9 100644
--- a/src/javascript/jsc/api/FFI.h
+++ b/src/javascript/jsc/api/FFI.h
@@ -106,6 +106,8 @@ EncodedJSValue ValueTrue = { TagValueTrue };
typedef void* JSContext;
+#define LOAD_ARGUMENTS_FROM_CALL_FRAME EncodedJSValue* args = (EncodedJSValue*)((size_t*)callFrame + Bun_FFI_PointerOffsetToArgumentsList);
+
#ifdef IS_CALLBACK
extern int64_t bun_call(JSContext, void* func, void* thisValue, size_t len, const EncodedJSValue args[], void* exception);
@@ -180,6 +182,12 @@ static bool JSVALUE_TO_BOOL(EncodedJSValue val) {
return val.asInt64 == TagValueTrue;
}
+#define arg(i) ((EncodedJSValue*)args)[i]
+void* JSFunctionCall(void* globalObject, void* callFrame);
+// int64_t JSFunctionCall(void* globalObject, void* callFrame) {
+// EncodedJSValue* args = (EncodedJSValue*)((unsigned char*)callFrame + Bun_FFI_PointerOffsetToArgumentsList);
+// }
+
// --- Generated Code ---
diff --git a/src/javascript/jsc/api/ffi.zig b/src/javascript/jsc/api/ffi.zig
index ceffd6278..7ae3b60dc 100644
--- a/src/javascript/jsc/api/ffi.zig
+++ b/src/javascript/jsc/api/ffi.zig
@@ -371,7 +371,12 @@ pub const FFI = struct {
return ZigString.init("Failed to compile (nothing happend!)").toErrorInstance(global);
},
.compiled => |compiled| {
- var cb = JSC.C.JSObjectMakeFunctionWithCallback(global.ref(), null, @ptrCast(JSC.C.JSObjectCallAsFunctionCallback, compiled.ptr));
+ var cb = Bun__CreateFFIFunction(
+ global,
+ &ZigString.init(std.mem.span(function.base_name)),
+ @intCast(u32, function.arg_types.items.len),
+ compiled.ptr,
+ );
obj.put(global, &ZigString.init(std.mem.span(function.base_name)), JSC.JSValue.cast(cb));
},
@@ -408,7 +413,7 @@ pub const FFI = struct {
if (val.isAnyInt()) {
const int = val.toInt32();
switch (int) {
- 0...13 => {
+ 0...14 => {
abi_types.appendAssumeCapacity(@intToEnum(ABIType, int));
continue;
},
@@ -439,7 +444,7 @@ pub const FFI = struct {
if (ret_value.isAnyInt()) {
const int = ret_value.toInt32();
switch (int) {
- 0...13 => {
+ 0...14 => {
return_type = @intToEnum(ABIType, int);
break :brk;
},
@@ -612,6 +617,19 @@ pub const FFI = struct {
}
_ = 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,
+ );
+ // 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,
@@ -629,6 +647,7 @@ pub const FFI = struct {
}
CompilerRT.inject(state);
_ = TCC.tcc_add_symbol(state, this.base_name, this.symbol_from_dynamic_library.?);
+
if (this.step == .failed) {
return;
}
@@ -658,9 +677,7 @@ pub const FFI = struct {
pthread_jit_write_protect_np(true);
}
- var formatted_symbol_name = try std.fmt.allocPrintZ(allocator, "bun_gen_{s}", .{std.mem.span(this.base_name)});
- defer allocator.free(formatted_symbol_name);
- var symbol = TCC.tcc_get_symbol(state, formatted_symbol_name) orelse {
+ var symbol = TCC.tcc_get_symbol(state, "JSFunctionCall") orelse {
this.step = .{ .failed = .{ .msg = "missing generated symbol in source code" } };
return;
@@ -787,6 +804,10 @@ pub const FFI = struct {
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");
@@ -826,27 +847,20 @@ pub const FFI = struct {
try writer.writeAll(");\n\n");
// -- Generate JavaScriptCore's C wrapper function
- try writer.writeAll("/* ---- Your Wrapper Function ---- */\nvoid* bun_gen_");
- try writer.writeAll(std.mem.span(this.base_name));
- try writer.writeAll("(JSContext ctx, void* function, void* thisObject, size_t argumentCount, const EncodedJSValue arguments[], void* exception);\n\n");
+ try writer.writeAll(
+ \\/* ---- Your Wrapper Function ---- */
+ \\void* JSFunctionCall(void* globalObject, void* callFrame) {
+ \\#ifdef HAS_ARGUMENTS
+ \\ LOAD_ARGUMENTS_FROM_CALL_FRAME;
+ \\#endif
+ \\
+ );
+
+ // try writer.writeAll(
+ // "(JSContext ctx, void* function, void* thisObject, size_t argumentCount, const EncodedJSValue arguments[], void* exception);\n\n",
+ // );
- try writer.writeAll("void* bun_gen_");
- try writer.writeAll(std.mem.span(this.base_name));
- try writer.writeAll("(JSContext ctx, void* function, void* thisObject, size_t argumentCount, const EncodedJSValue arguments[], void* exception) {\n\n");
- if (comptime Environment.isDebug) {
- try writer.writeAll("#ifdef INJECT_BEFORE\n");
- try writer.writeAll("INJECT_BEFORE;\n");
- try writer.writeAll("#endif\n");
- }
var arg_buf: [512]u8 = undefined;
- arg_buf[0.."arguments[".len].* = "arguments[".*;
- for (this.arg_types.items) |arg, i| {
- try writer.writeAll(" ");
- try arg.typename(writer);
- var printed = std.fmt.bufPrintIntToSlice(arg_buf["arguments[".len..], i, 10, .lower, .{});
- arg_buf["arguments[".len + printed.len] = ']';
- try writer.print(" arg{d} = {};\n", .{ i, arg.toC(arg_buf[0 .. printed.len + "arguments[]".len]) });
- }
try writer.writeAll(" ");
if (!(this.return_type == .void)) {
@@ -855,14 +869,20 @@ pub const FFI = struct {
}
try writer.print("{s}(", .{std.mem.span(this.base_name)});
first = true;
- for (this.arg_types.items) |_, i| {
+ arg_buf[0..4].* = "arg(".*;
+ for (this.arg_types.items) |arg, i| {
if (!first) {
try writer.writeAll(", ");
}
first = false;
- try writer.print("arg{d}", .{i});
+
+ try writer.writeAll(" ");
+ _ = std.fmt.bufPrintIntToSlice(arg_buf["arg(".len..], i, 10, .lower, .{});
+ arg_buf["arg(N".len] = ')';
+ try writer.print("{}", .{arg.toC(arg_buf[0..6])});
}
try writer.writeAll(");\n");
+
if (!first) try writer.writeAll("\n");
try writer.writeAll(" ");
@@ -1014,6 +1034,8 @@ pub const FFI = struct {
@"void" = 13,
+ cstring = 14,
+
const map = .{
.{ "bool", ABIType.bool },
.{ "c_int", ABIType.int32_t },
@@ -1047,6 +1069,7 @@ pub const FFI = struct {
.{ "ptr", ABIType.ptr },
.{ "pointer", ABIType.ptr },
.{ "void", ABIType.@"void" },
+ .{ "cstring", ABIType.@"cstring" },
};
pub const label = ComptimeStringMap(ABIType, map);
const EnumMapFormatter = struct {
@@ -1110,7 +1133,7 @@ pub const FFI = struct {
},
.int64_t => {},
.uint64_t => {},
- .ptr => {
+ .cstring, .ptr => {
try writer.print("JSVALUE_TO_PTR({s})", .{self.symbol});
},
.double => {
@@ -1138,7 +1161,7 @@ pub const FFI = struct {
},
.int64_t => {},
.uint64_t => {},
- .ptr => {
+ .cstring, .ptr => {
try writer.print("PTR_TO_JSVALUE({s})", .{self.symbol});
},
.double => {
@@ -1171,7 +1194,7 @@ pub const FFI = struct {
pub fn typenameLabel(this: ABIType) []const u8 {
return switch (this) {
- .ptr => "void*",
+ .cstring, .ptr => "void*",
.bool => "bool",
.int8_t => "int8_t",
.uint8_t => "uint8_t",
@@ -1189,3 +1212,10 @@ pub const FFI = struct {
}
};
};
+
+extern fn Bun__CreateFFIFunction(
+ globalObject: *JSGlobalObject,
+ symbolName: *const ZigString,
+ argCount: u32,
+ functionPointer: *anyopaque,
+) *anyopaque;
diff --git a/src/javascript/jsc/bindings/Buffer.h b/src/javascript/jsc/bindings/Buffer.h
index bc3367ad6..3dc828c87 100644
--- a/src/javascript/jsc/bindings/Buffer.h
+++ b/src/javascript/jsc/bindings/Buffer.h
@@ -10,6 +10,7 @@
#include "BufferEncodingType.h"
#include "JavaScriptCore/GenericTypedArrayView.h"
#include "JavaScriptCore/JSBase.h"
+#include "headers-handwritten.h"
extern "C" JSC::EncodedJSValue JSBuffer__bufferFromPointerAndLengthAndDeinit(JSC::JSGlobalObject* lexicalGlobalObject, char* ptr, unsigned int length, void* ctx, JSTypedArrayBytesDeallocator bytesDeallocator);
extern "C" JSC::EncodedJSValue Bun__encoding__toStringUTF16(const uint8_t* input, size_t len, JSC::JSGlobalObject* globalObject);
diff --git a/src/javascript/jsc/bindings/JSBuffer.cpp b/src/javascript/jsc/bindings/JSBuffer.cpp
index 8f56703ce..347dec29a 100644
--- a/src/javascript/jsc/bindings/JSBuffer.cpp
+++ b/src/javascript/jsc/bindings/JSBuffer.cpp
@@ -797,6 +797,7 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_equalsBody(JSC::JSGl
static inline JSC::EncodedJSValue jsBufferPrototypeFunction_fillBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSBuffer>::ClassParameter castedThis)
{
auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
if (callFrame->argumentCount() < 1) {
return JSValue::encode(castedThis);
@@ -805,7 +806,7 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_fillBody(JSC::JSGlob
auto value = callFrame->uncheckedArgument(0);
if (!value.isString()) {
- auto value_ = value.toInt32() & 0xFF;
+ auto value_ = value.toInt32(lexicalGlobalObject) & 0xFF;
auto value_uint8 = static_cast<uint8_t>(value_);
auto length = castedThis->byteLength();
@@ -815,21 +816,21 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_fillBody(JSC::JSGlob
if (auto start_ = callFrame->uncheckedArgument(1).tryGetAsUint32Index()) {
start = start_.value();
} else {
- return throwVMError(lexicalGlobalObject, JSC::throwScope, createRangeError(lexicalGlobalObject, "start out of range"_s));
+ return throwVMError(lexicalGlobalObject, throwScope, createRangeError(lexicalGlobalObject, "start out of range"_s));
}
if (callFrame->argumentCount() > 2) {
if (auto end_ = callFrame->uncheckedArgument(2).tryGetAsUint32Index()) {
end = end_.value();
} else {
- return throwVMError(lexicalGlobalObject, JSC::throwScope, createRangeError(lexicalGlobalObject, "end out of range"_s));
+ return throwVMError(lexicalGlobalObject, throwScope, createRangeError(lexicalGlobalObject, "end out of range"_s));
}
}
}
if (start > end) {
- return throwVMError(lexicalGlobalObject, JSC::throwScope, createRangeError(lexicalGlobalObject, "start out of range"_s));
+ return throwVMError(lexicalGlobalObject, throwScope, createRangeError(lexicalGlobalObject, "start out of range"_s));
}
if (end > length) {
- return throwVMError(lexicalGlobalObject, JSC::throwScope, createRangeError(lexicalGlobalObject, "end out of range"_s));
+ return throwVMError(lexicalGlobalObject, throwScope, createRangeError(lexicalGlobalObject, "end out of range"_s));
}
auto startPtr = castedThis->typedVector() + start;
auto endPtr = castedThis->typedVector() + end;
@@ -848,14 +849,14 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_fillBody(JSC::JSGlob
if (auto start_ = callFrame->uncheckedArgument(1).tryGetAsUint32Index()) {
start = start_.value();
} else {
- throwVMError(lexicalGlobalObject, JSC::throwScope, createRangeError(lexicalGlobalObject, "start out of range"_s));
+ throwVMError(lexicalGlobalObject, throwScope, createRangeError(lexicalGlobalObject, "start out of range"_s));
return JSC::JSValue::encode(jsUndefined());
}
if (callFrame->argumentCount() > 2) {
if (auto end_ = callFrame->uncheckedArgument(2).tryGetAsUint32Index()) {
end = end_.value();
} else {
- throwVMError(lexicalGlobalObject, JSC::throwScope, createRangeError(lexicalGlobalObject, "end out of range"_s));
+ throwVMError(lexicalGlobalObject, throwScope, createRangeError(lexicalGlobalObject, "end out of range"_s));
return JSC::JSValue::encode(jsUndefined());
}
}
@@ -863,9 +864,9 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_fillBody(JSC::JSGlob
if (callFrame->argumentCount() > 3) {
auto encoding_ = callFrame->uncheckedArgument(3).toString(lexicalGlobalObject);
- std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, arg1.value());
+ std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, encoding_);
if (!encoded) {
- throwTypeError(lexicalGlobalObject, scope, "Invalid encoding");
+ throwTypeError(lexicalGlobalObject, throwScope, "Invalid encoding");
return JSC::JSValue::encode(jsUndefined());
}
@@ -873,24 +874,24 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_fillBody(JSC::JSGlob
}
}
if (start > end) {
- throwVMError(lexicalGlobalObject, JSC::throwScope, createRangeError(lexicalGlobalObject, "start out of range"_s));
+ throwVMError(lexicalGlobalObject, throwScope, createRangeError(lexicalGlobalObject, "start out of range"_s));
return JSC::JSValue::encode(jsUndefined());
}
if (end > length) {
- throwVMError(lexicalGlobalObject, JSC::throwScope, createRangeError(lexicalGlobalObject, "end out of range"_s));
+ throwVMError(lexicalGlobalObject, throwScope, createRangeError(lexicalGlobalObject, "end out of range"_s));
return JSC::JSValue::encode(jsUndefined());
}
auto startPtr = castedThis->typedVector() + start;
- ZigString str = Zig::toString(value.toString(lexicalGlobalObject));
+ // ZigString str = Zig::toString(value.toString(lexicalGlobalObject));
- Bun__ArrayBuffer buf;
- JSC__JSValue__asArrayBuffer_(JSC::JSValue::encode(castedThis), lexicalGlobalObject,
- &buf);
- Bun__Buffer_fill(lexicalGlobalObject, &buf, &str, start, end, encoding);
+ // Bun__ArrayBuffer buf;
+ // JSC__JSValue__asArrayBuffer_(JSC::JSValue::encode(castedThis), lexicalGlobalObject,
+ // &buf);
+ // Bun__Buffer_fill(lexicalGlobalObject, &buf, &str, start, end, encoding);
- return JSValue::encode(castedThis);
+ RELEASE_AND_RETURN(throwScope, JSValue::encode(castedThis));
}
}
static inline JSC::EncodedJSValue jsBufferPrototypeFunction_includesBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSBuffer>::ClassParameter castedThis)
diff --git a/src/javascript/jsc/bindings/JSBufferConstructorBuiltins.h b/src/javascript/jsc/bindings/JSBufferConstructorBuiltins.h
index 328e597eb..f071164d5 100644
--- a/src/javascript/jsc/bindings/JSBufferConstructorBuiltins.h
+++ b/src/javascript/jsc/bindings/JSBufferConstructorBuiltins.h
@@ -1,3 +1,4 @@
+//clang-format off
/*
* Copyright (c) 2016 Apple Inc. All rights reserved.
* Copyright (c) 2022 Codeblog Corp. All rights reserved.
diff --git a/src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.cpp b/src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.cpp
index 2c3969f98..a7548b22a 100644
--- a/src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.cpp
+++ b/src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.cpp
@@ -673,6 +673,19 @@ const char* const s_jsBufferPrototypeToJSONCode =
"})\n" \
;
+const JSC::ConstructAbility s_jsBufferPrototypeSubarrayCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_jsBufferPrototypeSubarrayCodeConstructorKind = JSC::ConstructorKind::None;
+const int s_jsBufferPrototypeSubarrayCodeLength = 196;
+static const JSC::Intrinsic s_jsBufferPrototypeSubarrayCodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_jsBufferPrototypeSubarrayCode =
+ "(function (start, end) {\n" \
+ " \"use strict\";\n" \
+ "\n" \
+ " Buffer[Symbol.species] ??= Buffer;\n" \
+ " return new Buffer(this.buffer, this.byteOffset + (start || 0), (end || this.byteLength) - (start || 0));\n" \
+ "})\n" \
+;
+
const JSC::ConstructAbility s_jsBufferPrototypeInitializeBunBufferCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const JSC::ConstructorKind s_jsBufferPrototypeInitializeBunBufferCodeConstructorKind = JSC::ConstructorKind::None;
const int s_jsBufferPrototypeInitializeBunBufferCodeLength = 45;
diff --git a/src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.h b/src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.h
index 3bd387ff3..beff50d66 100644
--- a/src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.h
+++ b/src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.h
@@ -1,3 +1,4 @@
+//clang-format off
/*
* Copyright (c) 2016 Apple Inc. All rights reserved.
* Copyright (c) 2022 Codeblog Corp. All rights reserved.
@@ -262,6 +263,10 @@ extern const char* const s_jsBufferPrototypeToJSONCode;
extern const int s_jsBufferPrototypeToJSONCodeLength;
extern const JSC::ConstructAbility s_jsBufferPrototypeToJSONCodeConstructAbility;
extern const JSC::ConstructorKind s_jsBufferPrototypeToJSONCodeConstructorKind;
+extern const char* const s_jsBufferPrototypeSubarrayCode;
+extern const int s_jsBufferPrototypeSubarrayCodeLength;
+extern const JSC::ConstructAbility s_jsBufferPrototypeSubarrayCodeConstructAbility;
+extern const JSC::ConstructorKind s_jsBufferPrototypeSubarrayCodeConstructorKind;
extern const char* const s_jsBufferPrototypeInitializeBunBufferCode;
extern const int s_jsBufferPrototypeInitializeBunBufferCodeLength;
extern const JSC::ConstructAbility s_jsBufferPrototypeInitializeBunBufferCodeConstructAbility;
@@ -323,6 +328,7 @@ extern const JSC::ConstructorKind s_jsBufferPrototypeInitializeBunBufferCodeCons
macro(base64urlSlice, jsBufferPrototypeBase64urlSlice, 2) \
macro(hexSlice, jsBufferPrototypeHexSlice, 2) \
macro(toJSON, jsBufferPrototypeToJSON, 0) \
+ macro(subarray, jsBufferPrototypeSubarray, 2) \
macro(initializeBunBuffer, jsBufferPrototypeInitializeBunBuffer, 1) \
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_SETBIGUINT64 1
@@ -380,6 +386,7 @@ extern const JSC::ConstructorKind s_jsBufferPrototypeInitializeBunBufferCodeCons
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_BASE64URLSLICE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_HEXSLICE 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_TOJSON 1
+#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_SUBARRAY 1
#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_INITIALIZEBUNBUFFER 1
#define WEBCORE_FOREACH_JSBUFFERPROTOTYPE_BUILTIN_CODE(macro) \
@@ -438,6 +445,7 @@ extern const JSC::ConstructorKind s_jsBufferPrototypeInitializeBunBufferCodeCons
macro(jsBufferPrototypeBase64urlSliceCode, base64urlSlice, static_cast<const char*>(nullptr), s_jsBufferPrototypeBase64urlSliceCodeLength) \
macro(jsBufferPrototypeHexSliceCode, hexSlice, static_cast<const char*>(nullptr), s_jsBufferPrototypeHexSliceCodeLength) \
macro(jsBufferPrototypeToJSONCode, toJSON, static_cast<const char*>(nullptr), s_jsBufferPrototypeToJSONCodeLength) \
+ macro(jsBufferPrototypeSubarrayCode, subarray, static_cast<const char*>(nullptr), s_jsBufferPrototypeSubarrayCodeLength) \
macro(jsBufferPrototypeInitializeBunBufferCode, initializeBunBuffer, static_cast<const char*>(nullptr), s_jsBufferPrototypeInitializeBunBufferCodeLength) \
#define WEBCORE_FOREACH_JSBUFFERPROTOTYPE_BUILTIN_FUNCTION_NAME(macro) \
@@ -472,6 +480,7 @@ extern const JSC::ConstructorKind s_jsBufferPrototypeInitializeBunBufferCodeCons
macro(readUInt8) \
macro(setBigUint64) \
macro(slice) \
+ macro(subarray) \
macro(toJSON) \
macro(ucs2Slice) \
macro(ucs2Write) \
diff --git a/src/javascript/jsc/bindings/header-gen.zig b/src/javascript/jsc/bindings/header-gen.zig
index 30467f698..3ec73ea94 100644
--- a/src/javascript/jsc/bindings/header-gen.zig
+++ b/src/javascript/jsc/bindings/header-gen.zig
@@ -517,7 +517,7 @@ pub fn HeaderGen(comptime first_import: type, comptime second_import: type, comp
\\
\\#ifndef INCLUDED_{s}
\\#define INCLUDED_{s}
- \\#include {s}
+ \\#include "{s}"
\\#endif
\\
\\extern "C" const size_t {s} = sizeof({s});
diff --git a/src/javascript/jsc/bindings/headers-cpp.h b/src/javascript/jsc/bindings/headers-cpp.h
index 67ae00e83..fdac529b7 100644
--- a/src/javascript/jsc/bindings/headers-cpp.h
+++ b/src/javascript/jsc/bindings/headers-cpp.h
@@ -1,4 +1,4 @@
-//-- AUTOGENERATED FILE -- 1651379222
+//-- AUTOGENERATED FILE -- 1651480881
// clang-format off
#pragma once
@@ -10,7 +10,7 @@
#ifndef INCLUDED_JavaScriptCore_JSObject_h
#define INCLUDED_JavaScriptCore_JSObject_h
-#include JavaScriptCore/JSObject.h
+#include "JavaScriptCore/JSObject.h"
#endif
extern "C" const size_t JSC__JSObject_object_size_ = sizeof(JSC::JSObject);
@@ -18,7 +18,7 @@ extern "C" const size_t JSC__JSObject_object_align_ = alignof(JSC::JSObject);
#ifndef INCLUDED_FetchHeaders_h
#define INCLUDED_FetchHeaders_h
-#include FetchHeaders.h
+#include "FetchHeaders.h"
#endif
extern "C" const size_t WebCore__FetchHeaders_object_size_ = sizeof(WebCore::FetchHeaders);
@@ -26,7 +26,7 @@ extern "C" const size_t WebCore__FetchHeaders_object_align_ = alignof(WebCore::F
#ifndef INCLUDED_JavaScriptCore_JSCell_h
#define INCLUDED_JavaScriptCore_JSCell_h
-#include JavaScriptCore/JSCell.h
+#include "JavaScriptCore/JSCell.h"
#endif
extern "C" const size_t JSC__JSCell_object_size_ = sizeof(JSC::JSCell);
@@ -34,7 +34,7 @@ extern "C" const size_t JSC__JSCell_object_align_ = alignof(JSC::JSCell);
#ifndef INCLUDED_JavaScriptCore_JSString_h
#define INCLUDED_JavaScriptCore_JSString_h
-#include JavaScriptCore/JSString.h
+#include "JavaScriptCore/JSString.h"
#endif
extern "C" const size_t JSC__JSString_object_size_ = sizeof(JSC::JSString);
@@ -42,7 +42,7 @@ extern "C" const size_t JSC__JSString_object_align_ = alignof(JSC::JSString);
#ifndef INCLUDED_JavaScriptCore_ScriptArguments_h
#define INCLUDED_JavaScriptCore_ScriptArguments_h
-#include JavaScriptCore/ScriptArguments.h
+#include "JavaScriptCore/ScriptArguments.h"
#endif
extern "C" const size_t Inspector__ScriptArguments_object_size_ = sizeof(Inspector::ScriptArguments);
@@ -50,7 +50,7 @@ extern "C" const size_t Inspector__ScriptArguments_object_align_ = alignof(Inspe
#ifndef INCLUDED_JavaScriptCore_JSModuleLoader_h
#define INCLUDED_JavaScriptCore_JSModuleLoader_h
-#include JavaScriptCore/JSModuleLoader.h
+#include "JavaScriptCore/JSModuleLoader.h"
#endif
extern "C" const size_t JSC__JSModuleLoader_object_size_ = sizeof(JSC::JSModuleLoader);
@@ -58,7 +58,7 @@ extern "C" const size_t JSC__JSModuleLoader_object_align_ = alignof(JSC::JSModul
#ifndef INCLUDED_JavaScriptCore_JSModuleRecord_h
#define INCLUDED_JavaScriptCore_JSModuleRecord_h
-#include JavaScriptCore/JSModuleRecord.h
+#include "JavaScriptCore/JSModuleRecord.h"
#endif
extern "C" const size_t JSC__JSModuleRecord_object_size_ = sizeof(JSC::JSModuleRecord);
@@ -66,7 +66,7 @@ extern "C" const size_t JSC__JSModuleRecord_object_align_ = alignof(JSC::JSModul
#ifndef INCLUDED_JavaScriptCore_JSPromise_h
#define INCLUDED_JavaScriptCore_JSPromise_h
-#include JavaScriptCore/JSPromise.h
+#include "JavaScriptCore/JSPromise.h"
#endif
extern "C" const size_t JSC__JSPromise_object_size_ = sizeof(JSC::JSPromise);
@@ -74,7 +74,7 @@ extern "C" const size_t JSC__JSPromise_object_align_ = alignof(JSC::JSPromise);
#ifndef INCLUDED_JavaScriptCore_JSInternalPromise_h
#define INCLUDED_JavaScriptCore_JSInternalPromise_h
-#include JavaScriptCore/JSInternalPromise.h
+#include "JavaScriptCore/JSInternalPromise.h"
#endif
extern "C" const size_t JSC__JSInternalPromise_object_size_ = sizeof(JSC::JSInternalPromise);
@@ -82,7 +82,7 @@ extern "C" const size_t JSC__JSInternalPromise_object_align_ = alignof(JSC::JSIn
#ifndef INCLUDED_JavaScriptCore_SourceOrigin_h
#define INCLUDED_JavaScriptCore_SourceOrigin_h
-#include JavaScriptCore/SourceOrigin.h
+#include "JavaScriptCore/SourceOrigin.h"
#endif
extern "C" const size_t JSC__SourceOrigin_object_size_ = sizeof(JSC::SourceOrigin);
@@ -90,7 +90,7 @@ extern "C" const size_t JSC__SourceOrigin_object_align_ = alignof(JSC::SourceOri
#ifndef INCLUDED_JavaScriptCore_SourceProvider_h
#define INCLUDED_JavaScriptCore_SourceProvider_h
-#include JavaScriptCore/SourceProvider.h
+#include "JavaScriptCore/SourceProvider.h"
#endif
extern "C" const size_t JSC__SourceCode_object_size_ = sizeof(JSC::SourceCode);
@@ -98,7 +98,7 @@ extern "C" const size_t JSC__SourceCode_object_align_ = alignof(JSC::SourceCode)
#ifndef INCLUDED_JavaScriptCore_JSFunction_h
#define INCLUDED_JavaScriptCore_JSFunction_h
-#include JavaScriptCore/JSFunction.h
+#include "JavaScriptCore/JSFunction.h"
#endif
extern "C" const size_t JSC__JSFunction_object_size_ = sizeof(JSC::JSFunction);
@@ -106,7 +106,7 @@ extern "C" const size_t JSC__JSFunction_object_align_ = alignof(JSC::JSFunction)
#ifndef INCLUDED_JavaScriptCore_JSGlobalObject_h
#define INCLUDED_JavaScriptCore_JSGlobalObject_h
-#include JavaScriptCore/JSGlobalObject.h
+#include "JavaScriptCore/JSGlobalObject.h"
#endif
extern "C" const size_t JSC__JSGlobalObject_object_size_ = sizeof(JSC::JSGlobalObject);
@@ -114,7 +114,7 @@ extern "C" const size_t JSC__JSGlobalObject_object_align_ = alignof(JSC::JSGloba
#ifndef INCLUDED_wtf_URL_h
#define INCLUDED_wtf_URL_h
-#include wtf/URL.h
+#include "wtf/URL.h"
#endif
extern "C" const size_t WTF__URL_object_size_ = sizeof(WTF::URL);
@@ -122,7 +122,7 @@ extern "C" const size_t WTF__URL_object_align_ = alignof(WTF::URL);
#ifndef INCLUDED_wtf_text_WTFString_h
#define INCLUDED_wtf_text_WTFString_h
-#include wtf/text/WTFString.h
+#include "wtf/text/WTFString.h"
#endif
extern "C" const size_t WTF__String_object_size_ = sizeof(WTF::String);
@@ -130,7 +130,7 @@ extern "C" const size_t WTF__String_object_align_ = alignof(WTF::String);
#ifndef INCLUDED_JavaScriptCore_JSValue_h
#define INCLUDED_JavaScriptCore_JSValue_h
-#include JavaScriptCore/JSValue.h
+#include "JavaScriptCore/JSValue.h"
#endif
extern "C" const size_t JSC__JSValue_object_size_ = sizeof(JSC::JSValue);
@@ -138,7 +138,7 @@ extern "C" const size_t JSC__JSValue_object_align_ = alignof(JSC::JSValue);
#ifndef INCLUDED_JavaScriptCore_PropertyName_h
#define INCLUDED_JavaScriptCore_PropertyName_h
-#include JavaScriptCore/PropertyName.h
+#include "JavaScriptCore/PropertyName.h"
#endif
extern "C" const size_t JSC__PropertyName_object_size_ = sizeof(JSC::PropertyName);
@@ -146,7 +146,7 @@ extern "C" const size_t JSC__PropertyName_object_align_ = alignof(JSC::PropertyN
#ifndef INCLUDED_JavaScriptCore_Exception_h
#define INCLUDED_JavaScriptCore_Exception_h
-#include JavaScriptCore/Exception.h
+#include "JavaScriptCore/Exception.h"
#endif
extern "C" const size_t JSC__Exception_object_size_ = sizeof(JSC::Exception);
@@ -154,7 +154,7 @@ extern "C" const size_t JSC__Exception_object_align_ = alignof(JSC::Exception);
#ifndef INCLUDED_JavaScriptCore_VM_h
#define INCLUDED_JavaScriptCore_VM_h
-#include JavaScriptCore/VM.h
+#include "JavaScriptCore/VM.h"
#endif
extern "C" const size_t JSC__VM_object_size_ = sizeof(JSC::VM);
@@ -162,7 +162,7 @@ extern "C" const size_t JSC__VM_object_align_ = alignof(JSC::VM);
#ifndef INCLUDED_JavaScriptCore_ThrowScope_h
#define INCLUDED_JavaScriptCore_ThrowScope_h
-#include JavaScriptCore/ThrowScope.h
+#include "JavaScriptCore/ThrowScope.h"
#endif
extern "C" const size_t JSC__ThrowScope_object_size_ = sizeof(JSC::ThrowScope);
@@ -170,7 +170,7 @@ extern "C" const size_t JSC__ThrowScope_object_align_ = alignof(JSC::ThrowScope)
#ifndef INCLUDED_JavaScriptCore_CatchScope_h
#define INCLUDED_JavaScriptCore_CatchScope_h
-#include JavaScriptCore/CatchScope.h
+#include "JavaScriptCore/CatchScope.h"
#endif
extern "C" const size_t JSC__CatchScope_object_size_ = sizeof(JSC::CatchScope);
@@ -178,7 +178,7 @@ extern "C" const size_t JSC__CatchScope_object_align_ = alignof(JSC::CatchScope)
#ifndef INCLUDED_JavaScriptCore_CallFrame_h
#define INCLUDED_JavaScriptCore_CallFrame_h
-#include JavaScriptCore/CallFrame.h
+#include "JavaScriptCore/CallFrame.h"
#endif
extern "C" const size_t JSC__CallFrame_object_size_ = sizeof(JSC::CallFrame);
@@ -186,7 +186,7 @@ extern "C" const size_t JSC__CallFrame_object_align_ = alignof(JSC::CallFrame);
#ifndef INCLUDED_JavaScriptCore_Identifier_h
#define INCLUDED_JavaScriptCore_Identifier_h
-#include JavaScriptCore/Identifier.h
+#include "JavaScriptCore/Identifier.h"
#endif
extern "C" const size_t JSC__Identifier_object_size_ = sizeof(JSC::Identifier);
@@ -194,7 +194,7 @@ extern "C" const size_t JSC__Identifier_object_align_ = alignof(JSC::Identifier)
#ifndef INCLUDED_wtf_text_StringImpl_h
#define INCLUDED_wtf_text_StringImpl_h
-#include wtf/text/StringImpl.h
+#include "wtf/text/StringImpl.h"
#endif
extern "C" const size_t WTF__StringImpl_object_size_ = sizeof(WTF::StringImpl);
@@ -202,7 +202,7 @@ extern "C" const size_t WTF__StringImpl_object_align_ = alignof(WTF::StringImpl)
#ifndef INCLUDED_wtf_text_ExternalStringImpl_h
#define INCLUDED_wtf_text_ExternalStringImpl_h
-#include wtf/text/ExternalStringImpl.h
+#include "wtf/text/ExternalStringImpl.h"
#endif
extern "C" const size_t WTF__ExternalStringImpl_object_size_ = sizeof(WTF::ExternalStringImpl);
@@ -210,7 +210,7 @@ extern "C" const size_t WTF__ExternalStringImpl_object_align_ = alignof(WTF::Ext
#ifndef INCLUDED_wtf_text_StringView_h
#define INCLUDED_wtf_text_StringView_h
-#include wtf/text/StringView.h
+#include "wtf/text/StringView.h"
#endif
extern "C" const size_t WTF__StringView_object_size_ = sizeof(WTF::StringView);
@@ -226,7 +226,7 @@ extern "C" const size_t Zig__GlobalObject_object_align_ = alignof(Zig::GlobalObj
#ifndef INCLUDED_BunStream_h
#define INCLUDED_BunStream_h
-#include BunStream.h
+#include "BunStream.h"
#endif
extern "C" const size_t Bun__Readable_object_size_ = sizeof(Bun__Readable);
@@ -234,7 +234,7 @@ extern "C" const size_t Bun__Readable_object_align_ = alignof(Bun__Readable);
#ifndef INCLUDED_BunStream_h
#define INCLUDED_BunStream_h
-#include BunStream.h
+#include "BunStream.h"
#endif
extern "C" const size_t Bun__Writable_object_size_ = sizeof(Bun__Writable);
@@ -242,7 +242,9 @@ extern "C" const size_t Bun__Writable_object_align_ = alignof(Bun__Writable);
#ifndef INCLUDED_Path_h
#define INCLUDED_Path_h
-#include Path.h
+// #include "Path.h"
+#define Bun__Path void*
+#define Bun__Timer void*
#endif
extern "C" const size_t Bun__Path_object_size_ = sizeof(Bun__Path);
@@ -258,7 +260,7 @@ extern "C" const size_t Zig__ConsoleClient_object_align_ = alignof(Zig::ConsoleC
#ifndef INCLUDED_
#define INCLUDED_
-#include
+// #include ""
#endif
extern "C" const size_t Bun__Timer_object_size_ = sizeof(Bun__Timer);
diff --git a/src/javascript/jsc/bindings/headers.h b/src/javascript/jsc/bindings/headers.h
index 2e8b427b1..057e38eb8 100644
--- a/src/javascript/jsc/bindings/headers.h
+++ b/src/javascript/jsc/bindings/headers.h
@@ -1,5 +1,5 @@
// clang-format: off
-//-- AUTOGENERATED FILE -- 1651379222
+//-- AUTOGENERATED FILE -- 1651480881
#pragma once
#include <stddef.h>
diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig
index 5996f5808..efb0481f7 100644
--- a/src/javascript/jsc/javascript.zig
+++ b/src/javascript/jsc/javascript.zig
@@ -1081,7 +1081,7 @@ pub const VirtualMachine = struct {
} else if (strings.eqlComptime(_specifier, "bun:ffi")) {
return ResolvedSource{
.allocator = null,
- .source_code = ZigString.init(@embedFile("ffi.exports.js") ++ "export const FFIType = " ++ JSC.FFI.ABIType.map_to_js_object ++ ";\n"),
+ .source_code = ZigString.init("export const FFIType = " ++ JSC.FFI.ABIType.map_to_js_object ++ ";\n\n" ++ @embedFile("ffi.exports.js") ++ "\n"),
.specifier = ZigString.init("bun:ffi"),
.source_url = ZigString.init("bun:ffi"),
.hash = 0,
diff --git a/types/bun/ffi.d.ts b/types/bun/ffi.d.ts
index 718c97432..afd75103b 100644
--- a/types/bun/ffi.d.ts
+++ b/types/bun/ffi.d.ts
@@ -312,6 +312,14 @@ declare module "bun:ffi" {
*
*/
void = 13,
+
+ /**
+ * When used as a `return_type`, this will automatically become a {@link CString}.
+ *
+ * When used in `args` it is equivalent to {@link FFIType.pointer}
+ *
+ */
+ cstring = 14,
}
export type FFITypeOrString =
| FFIType
@@ -340,7 +348,8 @@ declare module "bun:ffi" {
| "bool"
| "ptr"
| "pointer"
- | "void";
+ | "void"
+ | "cstring";
interface FFIFunction {
/**
@@ -546,6 +555,24 @@ declare module "bun:ffi" {
* undefined behavior. Use with care!
*/
constructor(ptr: number, byteOffset?: number, byteLength?: number): string;
+
+ /**
+ * The ptr to the C string
+ *
+ * This `CString` instance is a clone of the string, so it
+ * is safe to continue using this instance after the `ptr` has been
+ * freed.
+ */
+ ptr: number;
+ byteOffset?: number;
+ byteLength?: number;
+
+ /**
+ * Get the {@link ptr} as an `ArrayBuffer`
+ *
+ * `null` or empty ptrs returns an `ArrayBuffer` with `byteLength` 0
+ */
+ get arrayBuffer(): ArrayBuffer;
}
/**