mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
## What does this PR do? Updates the oven-sh/tinycc fork to the latest upstream TinyCC, incorporating 30+ upstream commits while preserving all Bun-specific patches. ### Upstream changes incorporated - Build system improvements (c2str.exe handling, cross-compilation) - macOS 15 compatibility fixes - libtcc debugging support - pic/pie support for i386 - arm64 alignment and symbol offset fixes - RISC-V 64 improvements (pointer difference, assembly, Zicsr extension) - Relocation updates - Preprocessor improvements (integer literal overflow handling) - x86-64 cvts*2si fix - Various bug fixes ### Bun-specific patches preserved - Fix crash on macOS x64 (libxcselect.dylib memory handling) - Implement `-framework FrameworkName` on macOS (for framework header parsing) - Add missing #ifdef guards for TCC_IS_NATIVE - Make `__attribute__(deprecated)` a no-op - Fix `__has_include` with framework paths - Support attributes after identifiers in enums - Fix dlsym behavior on macOS (RTLD_SELF first, then RTLD_DEFAULT) - Various tccmacho.c improvements ### Related PRs - TinyCC fork CI is passing: https://github.com/oven-sh/tinycc/actions/runs/21105489093 ## How did you verify your code works? - [x] TinyCC fork CI passes on all platforms (Linux x86_64/arm64/armv7/riscv64, macOS x86_64/arm64, Windows i386/x86_64) - [ ] Bun CI passes 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Bot <claude-bot@bun.sh> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
95 lines
2.9 KiB
TypeScript
95 lines
2.9 KiB
TypeScript
import { spawnSync } from "bun";
|
|
import { cc, dlopen } from "bun:ffi";
|
|
import { beforeAll, describe, expect, it } from "bun:test";
|
|
import { bunEnv, bunExe, isASAN, 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;
|
|
// TinyCC's setjmp/longjmp error handling conflicts with ASan.
|
|
// Skip cc() calls on ASan, and catch errors on Windows.
|
|
if (!isASAN) {
|
|
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
|
|
// TinyCC's setjmp/longjmp error handling conflicts with ASan.
|
|
it.todoIf(isWindows || isASAN)("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");
|
|
});
|
|
});
|