From 125a4c747b24fde0cc7f19d23c5f6b7c78244329 Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Mon, 2 May 2022 03:40:14 -0700 Subject: [PATCH] [bun:ffi] cleanup --- Makefile | 8 + bench/ffi/ffi-overhead.js | 419 ++++++++++++++++++ bench/ffi/noop.c | 5 + bench/ffi/noop.dylib | Bin 0 -> 16759 bytes bench/ffi/noop.js | 16 + .../ffi.test.fixture.callback.c | 211 +++++++++ .../ffi.test.fixture.receiver.c | 211 +++++++++ integration/bunjs-only-snippets/ffi.test.js | 11 +- package.json | 1 + src/javascript/jsc/api/FFI.h | 8 + src/javascript/jsc/api/ffi.zig | 90 ++-- src/javascript/jsc/bindings/Buffer.h | 1 + src/javascript/jsc/bindings/JSBuffer.cpp | 35 +- .../bindings/JSBufferConstructorBuiltins.h | 1 + .../bindings/JSBufferPrototypeBuiltins.cpp | 13 + .../jsc/bindings/JSBufferPrototypeBuiltins.h | 9 + src/javascript/jsc/bindings/header-gen.zig | 2 +- src/javascript/jsc/bindings/headers-cpp.h | 64 +-- src/javascript/jsc/bindings/headers.h | 2 +- src/javascript/jsc/javascript.zig | 2 +- types/bun/ffi.d.ts | 29 +- 21 files changed, 1051 insertions(+), 87 deletions(-) create mode 100644 bench/ffi/ffi-overhead.js create mode 100644 bench/ffi/noop.c create mode 100755 bench/ffi/noop.dylib create mode 100644 bench/ffi/noop.js create mode 100644 integration/bunjs-only-snippets/ffi.test.fixture.callback.c create mode 100644 integration/bunjs-only-snippets/ffi.test.fixture.receiver.c diff --git a/Makefile b/Makefile index f2500637001a50..0e19242cc17e3d 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 00000000000000..841c599925233d --- /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 00000000000000..6b93beeafc0c49 --- /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 0000000000000000000000000000000000000000..74a1d3155346bf170a131eab03da1803db8eaf53 GIT binary patch literal 16759 zcmeI3O-NKx6vxlZXlRWe43UL7O`EVr9O*+`1U{k(#jvQMrUIXtBS`h8bS6^_T{J|s z2`XGztt>YRl9CApvxulgg+&$;L2j%?s}?e|m^$aaH}V=HAzJzzhNlq0$Q9$WnytV`nm*3aII&+<;G)%E?2%}v3* zjoG(q92C>ky1e%&VkS82s0xaBtz@ld+2ckudak;?_e^J-Dx;l5gNm?5RKuYimS4lZ z#N}J1M+5uPC(OIBS;IQWvYX`Xzh%#@bS~!t`JHM1>wBBu)q5^Ka177IQ`&Zp`B-LO z{tqFyI=lEply+|8ReitmB}-Jtl3w!duJ%p*=XX#b-rW`8SBnn!cE=)TtM}MBY~fnz zqiN>*wpzZtTdaa5`Bsgn>|Y>R(3%)0bvcal4naXQ;}EyuXr;UZ_A zT$HP)SYehJ&y8!XKBpQfHzR*twdJgB#@-nHaVha)-NNF_siOt{lGL-4fw97cp(X$L zWZR?NwX@>`V-Lg8=ifS#c^_tHPdg8U^MCeF_4g&_pI&dcS~a>-zPzQb`N);yUFW@_ z;Lz%#+n;vPiKf8tvC7oEcjV^#Yp+_WzD)OJJ{C{zTe_Q>x%1ZZ#9Mp6;zD#W;wc_6 GZv6tqyQWzH literal 0 HcmV?d00001 diff --git a/bench/ffi/noop.js b/bench/ffi/noop.js new file mode 100644 index 00000000000000..e28ea0629c2c18 --- /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 00000000000000..a428926ef945b3 --- /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 +#ifdef INJECT_BEFORE +// #include +#endif +// #include + +// // /* 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 00000000000000..2107b684eae5f8 --- /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 +#ifdef INJECT_BEFORE +// #include +#endif +// #include + +// // /* 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 fb297dae2b4a62..14a38d6b2fc651 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 af8acaa6729d46..1e7a82c3fa4769 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 48e4db48d11190..096abcfd96d463 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 ceffd627802899..7ae3b60dcfc86c 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 bc3367ad639864..3dc828c8798b79 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 8f56703ce1171a..347dec29a3db7b 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::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(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 encoded = parseEnumeration(*lexicalGlobalObject, arg1.value()); + std::optional encoded = parseEnumeration(*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::ClassParameter castedThis) diff --git a/src/javascript/jsc/bindings/JSBufferConstructorBuiltins.h b/src/javascript/jsc/bindings/JSBufferConstructorBuiltins.h index 328e597eb6abae..f071164d522009 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 2c3969f9819d72..a7548b22a02f1c 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 3bd387ff3527bb..beff50d66108b9 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(nullptr), s_jsBufferPrototypeBase64urlSliceCodeLength) \ macro(jsBufferPrototypeHexSliceCode, hexSlice, static_cast(nullptr), s_jsBufferPrototypeHexSliceCodeLength) \ macro(jsBufferPrototypeToJSONCode, toJSON, static_cast(nullptr), s_jsBufferPrototypeToJSONCodeLength) \ + macro(jsBufferPrototypeSubarrayCode, subarray, static_cast(nullptr), s_jsBufferPrototypeSubarrayCodeLength) \ macro(jsBufferPrototypeInitializeBunBufferCode, initializeBunBuffer, static_cast(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 30467f69856f5e..3ec73ea949f375 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 67ae00e83c3466..fdac529b7b2fb3 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 2e8b427b1b78d1..057e38eb8d7bf3 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 diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig index 5996f580857f3d..efb0481f735d22 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 718c974327aca0..afd75103ba22d6 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; } /**