aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/bun.js/ffi.test.fixture.callback.c39
-rw-r--r--test/bun.js/ffi.test.fixture.receiver.c33
-rw-r--r--test/bun.js/ffi.test.js164
3 files changed, 109 insertions, 127 deletions
diff --git a/test/bun.js/ffi.test.fixture.callback.c b/test/bun.js/ffi.test.fixture.callback.c
index cb38eebe8..58e6c482e 100644
--- a/test/bun.js/ffi.test.fixture.callback.c
+++ b/test/bun.js/ffi.test.fixture.callback.c
@@ -1,3 +1,4 @@
+#define JS_GLOBAL_OBJECT (void*)0x0UL
#define IS_CALLBACK 1
// This file is part of Bun!
// You can find the original source:
@@ -102,9 +103,16 @@ typedef void* JSContext;
#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;
+ZIG_REPR_TYPE FFI_Callback_call(void* ctx, size_t argCount, ZIG_REPR_TYPE* args);
+// We wrap
+static EncodedJSValue _FFI_Callback_call(void* ctx, size_t argCount, ZIG_REPR_TYPE* args) __attribute__((__always_inline__));
+static EncodedJSValue _FFI_Callback_call(void* ctx, size_t argCount, ZIG_REPR_TYPE* args) {
+ EncodedJSValue return_value;
+ return_value.asZigRepr = FFI_Callback_call(ctx, argCount, args);
+ return return_value;
+}
+static ZIG_REPR_TYPE arguments[100];
+
#endif
static bool JSVALUE_IS_CELL(EncodedJSValue val) __attribute__((__always_inline__));
@@ -116,10 +124,10 @@ static int64_t JSVALUE_TO_INT64(EncodedJSValue value) __attribute__((__always_i
uint64_t JSVALUE_TO_UINT64_SLOW(EncodedJSValue value);
int64_t JSVALUE_TO_INT64_SLOW(EncodedJSValue value);
-EncodedJSValue UINT64_TO_JSVALUE_SLOW(void* globalObject, uint64_t val);
-EncodedJSValue INT64_TO_JSVALUE_SLOW(void* globalObject, int64_t val);
-static EncodedJSValue UINT64_TO_JSVALUE(void* globalObject, uint64_t val) __attribute__((__always_inline__));
-static EncodedJSValue INT64_TO_JSVALUE(void* globalObject, int64_t val) __attribute__((__always_inline__));
+EncodedJSValue UINT64_TO_JSVALUE_SLOW(void* jsGlobalObject, uint64_t val);
+EncodedJSValue INT64_TO_JSVALUE_SLOW(void* jsGlobalObject, int64_t val);
+static EncodedJSValue UINT64_TO_JSVALUE(void* jsGlobalObject, uint64_t val) __attribute__((__always_inline__));
+static EncodedJSValue INT64_TO_JSVALUE(void* jsGlobalObject, int64_t val) __attribute__((__always_inline__));
static EncodedJSValue INT32_TO_JSVALUE(int32_t val) __attribute__((__always_inline__));
@@ -241,7 +249,7 @@ static int64_t JSVALUE_TO_INT64(EncodedJSValue value) {
return JSVALUE_TO_INT64_SLOW(value);
}
-static EncodedJSValue UINT64_TO_JSVALUE(void* globalObject, uint64_t val) {
+static EncodedJSValue UINT64_TO_JSVALUE(void* jsGlobalObject, uint64_t val) {
if (val < MAX_INT32) {
return INT32_TO_JSVALUE((int32_t)val);
}
@@ -250,10 +258,10 @@ static EncodedJSValue UINT64_TO_JSVALUE(void* globalObject, uint64_t val) {
return DOUBLE_TO_JSVALUE((double)val);
}
- return UINT64_TO_JSVALUE_SLOW(globalObject, val);
+ return UINT64_TO_JSVALUE_SLOW(jsGlobalObject, val);
}
-static EncodedJSValue INT64_TO_JSVALUE(void* globalObject, int64_t val) {
+static EncodedJSValue INT64_TO_JSVALUE(void* jsGlobalObject, int64_t val) {
if (val >= -MAX_INT32 && val <= MAX_INT32) {
return INT32_TO_JSVALUE((int32_t)val);
}
@@ -262,11 +270,11 @@ static EncodedJSValue INT64_TO_JSVALUE(void* globalObject, int64_t val) {
return DOUBLE_TO_JSVALUE((double)val);
}
- return INT64_TO_JSVALUE_SLOW(globalObject, val);
+ return INT64_TO_JSVALUE_SLOW(jsGlobalObject, val);
}
#ifndef IS_CALLBACK
-ZIG_REPR_TYPE JSFunctionCall(void* globalObject, void* callFrame);
+ZIG_REPR_TYPE JSFunctionCall(void* jsGlobalObject, void* callFrame);
#endif
@@ -282,10 +290,7 @@ bool my_callback_function(void* arg0) {
#ifdef INJECT_BEFORE
INJECT_BEFORE;
#endif
- EncodedJSValue arguments[1] = {
- PTR_TO_JSVALUE(arg0)
- };
- EncodedJSValue return_value = {bun_call(cachedJSContext, cachedCallbackFunction, (void*)0, 1, &arguments[0], (void*)0)};
- return JSVALUE_TO_BOOL(return_value);
+arguments[0] = PTR_TO_JSVALUE(arg0).asZigRepr;
+ return (bool)JSVALUE_TO_BOOL(_FFI_Callback_call((void*)0x0UL, 1, arguments));
}
diff --git a/test/bun.js/ffi.test.fixture.receiver.c b/test/bun.js/ffi.test.fixture.receiver.c
index f8417805d..c972c2df1 100644
--- a/test/bun.js/ffi.test.fixture.receiver.c
+++ b/test/bun.js/ffi.test.fixture.receiver.c
@@ -103,9 +103,16 @@ typedef void* JSContext;
#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;
+ZIG_REPR_TYPE FFI_Callback_call(void* ctx, size_t argCount, ZIG_REPR_TYPE* args);
+// We wrap
+static EncodedJSValue _FFI_Callback_call(void* ctx, size_t argCount, ZIG_REPR_TYPE* args) __attribute__((__always_inline__));
+static EncodedJSValue _FFI_Callback_call(void* ctx, size_t argCount, ZIG_REPR_TYPE* args) {
+ EncodedJSValue return_value;
+ return_value.asZigRepr = FFI_Callback_call(ctx, argCount, args);
+ return return_value;
+}
+static ZIG_REPR_TYPE arguments[100];
+
#endif
static bool JSVALUE_IS_CELL(EncodedJSValue val) __attribute__((__always_inline__));
@@ -117,10 +124,10 @@ static int64_t JSVALUE_TO_INT64(EncodedJSValue value) __attribute__((__always_i
uint64_t JSVALUE_TO_UINT64_SLOW(EncodedJSValue value);
int64_t JSVALUE_TO_INT64_SLOW(EncodedJSValue value);
-EncodedJSValue UINT64_TO_JSVALUE_SLOW(void* globalObject, uint64_t val);
-EncodedJSValue INT64_TO_JSVALUE_SLOW(void* globalObject, int64_t val);
-static EncodedJSValue UINT64_TO_JSVALUE(void* globalObject, uint64_t val) __attribute__((__always_inline__));
-static EncodedJSValue INT64_TO_JSVALUE(void* globalObject, int64_t val) __attribute__((__always_inline__));
+EncodedJSValue UINT64_TO_JSVALUE_SLOW(void* jsGlobalObject, uint64_t val);
+EncodedJSValue INT64_TO_JSVALUE_SLOW(void* jsGlobalObject, int64_t val);
+static EncodedJSValue UINT64_TO_JSVALUE(void* jsGlobalObject, uint64_t val) __attribute__((__always_inline__));
+static EncodedJSValue INT64_TO_JSVALUE(void* jsGlobalObject, int64_t val) __attribute__((__always_inline__));
static EncodedJSValue INT32_TO_JSVALUE(int32_t val) __attribute__((__always_inline__));
@@ -242,7 +249,7 @@ static int64_t JSVALUE_TO_INT64(EncodedJSValue value) {
return JSVALUE_TO_INT64_SLOW(value);
}
-static EncodedJSValue UINT64_TO_JSVALUE(void* globalObject, uint64_t val) {
+static EncodedJSValue UINT64_TO_JSVALUE(void* jsGlobalObject, uint64_t val) {
if (val < MAX_INT32) {
return INT32_TO_JSVALUE((int32_t)val);
}
@@ -251,10 +258,10 @@ static EncodedJSValue UINT64_TO_JSVALUE(void* globalObject, uint64_t val) {
return DOUBLE_TO_JSVALUE((double)val);
}
- return UINT64_TO_JSVALUE_SLOW(globalObject, val);
+ return UINT64_TO_JSVALUE_SLOW(jsGlobalObject, val);
}
-static EncodedJSValue INT64_TO_JSVALUE(void* globalObject, int64_t val) {
+static EncodedJSValue INT64_TO_JSVALUE(void* jsGlobalObject, int64_t val) {
if (val >= -MAX_INT32 && val <= MAX_INT32) {
return INT32_TO_JSVALUE((int32_t)val);
}
@@ -263,11 +270,11 @@ static EncodedJSValue INT64_TO_JSVALUE(void* globalObject, int64_t val) {
return DOUBLE_TO_JSVALUE((double)val);
}
- return INT64_TO_JSVALUE_SLOW(globalObject, val);
+ return INT64_TO_JSVALUE_SLOW(jsGlobalObject, val);
}
#ifndef IS_CALLBACK
-ZIG_REPR_TYPE JSFunctionCall(void* globalObject, void* callFrame);
+ZIG_REPR_TYPE JSFunctionCall(void* jsGlobalObject, void* callFrame);
#endif
@@ -278,7 +285,7 @@ float not_a_callback(float arg0);
/* ---- Your Wrapper Function ---- */
-ZIG_REPR_TYPE JSFunctionCall(void* globalObject, void* callFrame) {
+ZIG_REPR_TYPE JSFunctionCall(void* JS_GLOBAL_OBJECT, void* callFrame) {
LOAD_ARGUMENTS_FROM_CALL_FRAME;
EncodedJSValue arg0;
arg0.asInt64 = *argsPtr;
diff --git a/test/bun.js/ffi.test.js b/test/bun.js/ffi.test.js
index 536e6d7aa..6433f0161 100644
--- a/test/bun.js/ffi.test.js
+++ b/test/bun.js/ffi.test.js
@@ -4,6 +4,7 @@ import {
CFunction,
CString,
dlopen as _dlopen,
+ JSCallback,
ptr,
read,
toArrayBuffer,
@@ -372,6 +373,7 @@ function ffiRunner(fast) {
},
close,
} = dlopen("/tmp/bun-ffi-test.dylib", types);
+
Bun.gc(true);
expect(returns_true()).toBe(true);
Bun.gc(true);
@@ -407,6 +409,7 @@ function ffiRunner(fast) {
expect(identity_int8_t(10)).toBe(10);
expect(identity_int16_t(10)).toBe(10);
+
if (fast) expect(identity_int64_t(10)).toBe(10);
else expect(identity_int64_t(10)).toBe(10n);
expect(identity_uint8_t(10)).toBe(10);
@@ -486,6 +489,70 @@ function ffiRunner(fast) {
});
expect(myCFunction()).toBe(true);
+ {
+ const typeMap = {
+ int8_t: -8,
+ int16_t: -16,
+ int32_t: -32,
+ int64_t: -64n,
+ uint8_t: 8,
+ uint16_t: 16,
+ uint32_t: 32,
+ uint64_t: 64n,
+ float: 32.5,
+ double: 64.5,
+ ptr: 0xdeadbeef,
+ "void*": null,
+ };
+
+ // Return types, 1 argument
+ for (let [returnName, returnValue] of Object.entries(typeMap)) {
+ var roundtripFunction = new CFunction({
+ ptr: new JSCallback(
+ {
+ returns: returnName,
+ args: [returnName],
+ },
+ (input) => {
+ return input;
+ }
+ ).ptr,
+ returns: returnName,
+ args: [returnName],
+ });
+ expect(roundtripFunction(returnValue)).toBe(returnValue);
+ }
+
+ {
+ var toClose = new JSCallback(
+ {
+ returns: "bool",
+ args: ["bool"],
+ },
+ (input) => {
+ return input;
+ }
+ );
+ expect(toClose.ptr > 0).toBe(true);
+ toClose.close();
+ expect(toClose.ptr === null).toBe(true);
+ }
+
+ // Return types, no args
+ for (let [name, value] of Object.entries(typeMap)) {
+ var roundtripFunction = new CFunction({
+ ptr: new JSCallback(
+ {
+ returns: name,
+ },
+ () => value
+ ).ptr,
+ returns: name,
+ });
+ expect(roundtripFunction()).toBe(value);
+ }
+ }
+
// check deallocator is called
// for (let constructor of [toArrayBuffer, toBuffer]) {
@@ -506,103 +573,6 @@ function ffiRunner(fast) {
// Bun.gc(true);
// }
close();
- /*
- ---
- This style of callback is not implemented yet
- */
- // function identityBool() {
- // return true;
- // }
- // globalThis.identityBool = identityBool;
-
- // const first = native.callback(
- // {
- // returns: "bool",
- // },
- // identityBool
- // );
- // expect(
- // cb_identity_true()
- // ).toBe(true);
-
- // expect(cb_identity_true(first)).toBe(true);
-
- // expect(
- // cb_identity_false(
- // callback(
- // {
- // returns: "bool",
- // },
- // () => false
- // )
- // )
- // ).toBe(false);
-
- // expect(
- // cb_identity_42_char(
- // callback(
- // {
- // returns: "char",
- // },
- // () => 42
- // )
- // )
- // ).toBe(42);
- // expect(
- // cb_identity_42_uint8_t(
- // callback(
- // {
- // returns: "uint8_t",
- // },
- // () => 42
- // )
- // )
- // ).toBe(42);
-
- // cb_identity_neg_42_int8_t(
- // callback(
- // {
- // returns: "int8_t",
- // },
- // () => -42
- // )
- // ).toBe(-42);
-
- // cb_identity_42_uint16_t(
- // callback(
- // {
- // returns: "uint16_t",
- // },
- // () => 42
- // )
- // ).toBe(42);
-
- // cb_identity_42_uint32_t(
- // callback(
- // {
- // returns: "uint32_t",
- // },
- // () => 42
- // )
- // ).toBe(42);
-
- // cb_identity_neg_42_int16_t(
- // callback(
- // {
- // returns: "int16_t",
- // },
- // () => -42
- // )
- // ).toBe(-42);
-
- // cb_identity_neg_42_int32_t(
- // callback(
- // {
- // returns: "int32_t",
- // },
- // () => -42
- // )
- // ).toBe(-42);
}
// TODO: There is a crash when dlopen() two times the same library in quick succession