Files
bun.sh/test/napi/napi-value-ffi.test.ts

90 lines
2.6 KiB
TypeScript

import { spawnSync } from "bun";
import { cc, dlopen } from "bun:ffi";
import { beforeAll, describe, expect, it } from "bun:test";
import { bunEnv, bunExe, isWindows } from "harness";
import { join } from "path";
import source from "./napi-app/ffi_addon_1.c" with { type: "file" };
const symbols = {
set_instance_data: {
args: ["napi_env", "int"],
returns: "void",
},
get_instance_data: {
args: ["napi_env"],
returns: "int",
},
get_type: {
args: ["napi_env", "napi_value"],
returns: "cstring",
},
};
let addon1, addon2, cc1, cc2;
beforeAll(() => {
// build gyp
const install = spawnSync({
cmd: [bunExe(), "install", "--verbose"],
cwd: join(__dirname, "napi-app"),
stderr: "inherit",
env: bunEnv,
stdout: "inherit",
stdin: "inherit",
});
if (!install.success) {
throw new Error("build failed");
}
addon1 = dlopen(join(__dirname, `napi-app/build/Debug/ffi_addon_1.node`), symbols).symbols;
addon2 = dlopen(join(__dirname, `napi-app/build/Debug/ffi_addon_2.node`), symbols).symbols;
try {
cc1 = cc({
source,
symbols,
flags: `-I${join(__dirname, "napi-app/node_modules/node-api-headers/include")}`,
}).symbols;
cc2 = cc({
source,
symbols,
flags: `-I${join(__dirname, "napi-app/node_modules/node-api-headers/include")}`,
}).symbols;
} catch (e) {
// ignore compilation failure on Windows
if (!isWindows) throw e;
}
});
describe("ffi napi integration", () => {
it("has a different napi_env for each ffi library", () => {
addon1.set_instance_data(undefined, 5);
addon2.set_instance_data(undefined, 6);
expect(addon1.get_instance_data()).toBe(5);
expect(addon2.get_instance_data()).toBe(6);
});
// broken
it.todo("passes values correctly", () => {
expect(addon1.get_type(undefined, 123).toString()).toBe("number");
expect(addon1.get_type(undefined, "hello").toString()).toBe("string");
expect(addon1.get_type(undefined, 190n).toString()).toBe("bigint");
});
});
describe("cc napi integration", () => {
// fails on windows as TCC can't link the napi_ functions
it.todoIf(isWindows)("has a different napi_env for each cc invocation", () => {
cc1.set_instance_data(undefined, 5);
cc2.set_instance_data(undefined, 6);
expect(cc1.get_instance_data()).toBe(5);
expect(cc2.get_instance_data()).toBe(6);
});
// broken
it.todo("passes values correctly", () => {
expect(cc1.get_type(undefined, 123).toString()).toBe("number");
expect(cc1.get_type(undefined, "hello").toString()).toBe("string");
expect(cc1.get_type(undefined, 190n).toString()).toBe("bigint");
});
});