Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions scripts/build/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -863,10 +863,9 @@ export function resolveConfig(partial: PartialConfig, toolchain: Toolchain): Con
// failure is loud ("cannot find -l:libatomic.a") and the fix is obvious.
const staticLibatomic = partial.staticLibatomic ?? true;

// TinyCC: off on Windows ARM64 (not supported), Android (no upstream
// bionic support; FFI cc() falls back to dlopen-only), and FreeBSD
// (oven-sh/tinycc has no FreeBSD target).
const tinycc = partial.tinycc ?? !((windows && arm64) || abi === "android" || freebsd);
// TinyCC: off on Android (no upstream bionic support; FFI cc() falls back
// to dlopen-only) and FreeBSD (oven-sh/tinycc has no FreeBSD target).
const tinycc = partial.tinycc ?? !(abi === "android" || freebsd);
Comment thread
claude[bot] marked this conversation as resolved.

const valgrind = partial.valgrind ?? false;
const fuzzilli = partial.fuzzilli ?? false;
Expand Down
6 changes: 1 addition & 5 deletions scripts/build/deps/tinycc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
* TinyCC — small embeddable C compiler. Powers bun:ffi's JIT-compile path,
* where user-provided C gets compiled and linked at runtime.
*
* Disabled on windows-arm64 (tinycc doesn't have an arm64-coff backend).
*
* Built via DirectBuild — no cmake sub-process. The old overlay
* CMakeLists.txt had two recurring ASAN workarounds for the c2str host
* tool (Linux ASLR/shadow-map, macOS 26.4 dyld deadlock); DirectBuild's
Expand All @@ -12,14 +10,12 @@

import type { Dependency, DirectBuild } from "../source.ts";

const TINYCC_COMMIT = "12882eee073cfe5c7621bcfadf679e1372d4537b";
const TINYCC_COMMIT = "c49c2204b07c526c9ad935fabfcaf3802cae1346";

export const tinycc: Dependency = {
name: "tinycc",
versionMacro: "TINYCC",

// The cfg.tinycc flag already encodes the windows-arm64 exclusion
// (see config.ts: `tinycc ?? !(windows && arm64)`).
enabled: cfg => cfg.tinycc,

source: () => ({
Expand Down
2 changes: 1 addition & 1 deletion scripts/build/source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ export interface Dependency {

/**
* Whether this dep participates in the build at all. Defaults to always-on.
* E.g. libuv is windows-only, tinycc is disabled on windows-arm64.
* E.g. libuv is windows-only.
*/
enabled?: (cfg: Config) => boolean;

Expand Down
12 changes: 5 additions & 7 deletions test/js/bun/ffi/cc.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import { cc, CString, JSCallback, ptr, type FFIFunction, type Library } from "bun:ffi";
import { afterAll, beforeAll, describe, expect, it } from "bun:test";
import { promises as fs } from "fs";
import { bunEnv, bunExe, isArm64, isASAN, isWindows, normalizeBunSnapshot, tempDir, tempDirWithFiles } from "harness";
import { bunEnv, bunExe, isASAN, isWindows, normalizeBunSnapshot, tempDir, tempDirWithFiles } from "harness";
import path from "path";

Check warning on line 5 in test/js/bun/ffi/cc.test.ts

View check run for this annotation

Claude / Claude Code Review

Missed sibling isFFIUnavailable guards in ffi.test.js and cp.test.ts

Two sibling `isWindows && isArm64` FFI-skip sites weren't caught in the sweep: `test/js/bun/ffi/ffi.test.js:680-681` (`const isFFIUnavailable = isWindows && isArm64`, used at :685 and :722) and `test/js/node/fs/cp.test.ts:438` (`test.skipIf(!isWindows || isArm64)` gating a `bun:ffi` dlopen repro). These will stay skipped on windows-aarch64 after this lands — probably worth un-skipping in the same PR, or noting why they're excluded (e.g. if they trip the build #46411 crashes).
Comment thread
claude[bot] marked this conversation as resolved.

// TinyCC (and all of bun:ffi) is disabled on Windows ARM64
const isFFIUnavailable = isWindows && isArm64;

// TODO: we need to install build-essential and Apple SDK in CI.
// It can't find includes. It can on machines with that enabled.
// TinyCC's setjmp/longjmp error handling conflicts with ASan.
it.todoIf(isWindows || isASAN || isFFIUnavailable)("can run a .c file", () => {
it.todoIf(isWindows || isASAN)("can run a .c file", () => {
const result = Bun.spawnSync({
cmd: [bunExe(), path.join(__dirname, "cc-fixture.js")],
cwd: __dirname,
Expand All @@ -22,8 +20,8 @@
});

// TinyCC's setjmp/longjmp error handling conflicts with ASan.
// TinyCC is disabled on Windows ARM64.
describe.skipIf(isASAN || isFFIUnavailable)("given an add(a, b) function", () => {
describe.skipIf(isASAN)("given an add(a, b) function", () => {

Check warning on line 24 in test/js/bun/ffi/cc.test.ts

View check run for this annotation

Claude / Claude Code Review

Stale comment: 'TinyCC is disabled on Windows ARM64'

The comment `// TinyCC is disabled on Windows ARM64.` is now stale — this PR removed the `isFFIUnavailable` term from the `.skipIf()` on the next line (and enabling TinyCC on Windows ARM64 is the whole point of the PR). The comment should be deleted along with the guard.
const source = /* c */ `
Comment thread
claude[bot] marked this conversation as resolved.
int add(int a, int b) {
return a + b;
Expand Down Expand Up @@ -391,7 +389,7 @@
// Pins GC liveness: compiled trampolines survive the library wrapper being
// collected, and a JSCallback's closure stays alive until close().
// TinyCC's setjmp/longjmp error handling conflicts with ASan.
describe.skipIf(isASAN || isFFIUnavailable)("GC liveness of compiled symbols and callbacks", () => {
describe.skipIf(isASAN)("GC liveness of compiled symbols and callbacks", () => {
it("keeps symbol functions and callback closures alive across forced GC", async () => {
using dir = tempDir("bun-ffi-cc-gc-liveness", {
"lib.c": /* c */ `
Expand Down Expand Up @@ -457,7 +455,7 @@
});
});

describe.skipIf(isFFIUnavailable)("double <-> JSValue conversions", () => {
describe("double <-> JSValue conversions", () => {
// JSC NaN-boxes doubles, so a NaN whose payload collides with the tag space
// ("impure NaN", see JSC's PureNaN.h) must never be encoded as-is: it would
// decode as a native-chosen JSValue (true, undefined, an Int32, or a cell
Expand Down
7 changes: 2 additions & 5 deletions test/js/bun/ffi/ffi-error-messages.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import { dlopen, linkSymbols } from "bun:ffi";
import { describe, expect, test } from "bun:test";
import { isArm64, isMusl, isWindows } from "harness";
import { isMusl } from "harness";

// TinyCC (and all of bun:ffi) is disabled on Windows ARM64
const isFFIUnavailable = isWindows && isArm64;

describe.skipIf(isFFIUnavailable)("FFI error messages", () => {
describe("FFI error messages", () => {
test("dlopen shows library name when library cannot be opened", () => {
// Try to open a non-existent library
try {
Expand Down
5 changes: 1 addition & 4 deletions test/js/bun/ffi/ffi-viewSource-non-object.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { describe, expect, test } from "bun:test";
import { isArm64, isWindows } from "harness";

const isFFIUnavailable = isWindows && isArm64;

describe.skipIf(isFFIUnavailable)("FFI viewSource", () => {
describe("FFI viewSource", () => {
test("rejects non-object symbol descriptor values", () => {
// These should throw a TypeError because each symbol descriptor
// must be an object like { args: [...], returns: "void" }.
Expand Down
7 changes: 2 additions & 5 deletions test/js/node/fs/fs-writeSync-stdio-windows.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,11 @@
// Now `fromJS`/`fromJSValidated` return `.fromUV(0|1|2)` directly, and
// `FD.uv()` checks the cached stdio handles before `GetStdHandle`.
import { describe, expect, test } from "bun:test";
import { bunEnv, bunExe, isArm64, isWindows, tempDir } from "harness";
import { bunEnv, bunExe, isWindows, tempDir } from "harness";
import { join } from "node:path";

describe.concurrent.skipIf(!isWindows)("fs.writeSync on Windows stdio/handles", () => {
// bun:ffi (TinyCC) is unavailable on Windows arm64, so this repro can only
// run on x64. The second test below covers the plain openSync→writeSync path
// on all Windows arches.
test.skipIf(isArm64)("fs.writeSync(1, ...) does not panic after SetStdHandle swaps stdout", async () => {
test("fs.writeSync(1, ...) does not panic after SetStdHandle swaps stdout", async () => {
const fixture = `
const fs = require("node:fs");
const { dlopen } = require("bun:ffi");
Expand Down
7 changes: 3 additions & 4 deletions test/napi/napi-value-ffi.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { spawnSync } from "bun";
import { cc, dlopen } from "bun:ffi";
import { beforeAll, describe, expect, it } from "bun:test";
import { bunEnv, bunExe, canBuildNodeAddons, isArm64, isASAN, isWindows } from "harness";
import { bunEnv, bunExe, canBuildNodeAddons, isASAN, isWindows } from "harness";
import { join } from "path";

import source from "./napi-app/ffi_addon_1.c" with { type: "file" };

// TinyCC (and all of bun:ffi) is disabled on Windows ARM64; the napi-app
// fixture needs a toolchain that can compile the reported Node headers.
const isFFIUnavailable = (isWindows && isArm64) || !canBuildNodeAddons();
// The napi-app fixture needs a toolchain that can compile the Node headers.
const isFFIUnavailable = !canBuildNodeAddons();

const symbols = {
set_instance_data: {
Expand Down
Loading