Skip to content

Support compiling and running C from JavaScript - #13403

Merged
Jarred-Sumner merged 22 commits into
mainfrom
jarred/cc
Sep 14, 2024
Merged

Jarred-Sumner merged 22 commits into
mainfrom
jarred/cc

Conversation

@Jarred-Sumner

Copy link
Copy Markdown
Collaborator

What does this PR do?

This adds a cc function in bun:ffi which directly exposes TinyCC (a C compiler) and lets you run the code.

An example program below converts a file to .mp4 using ffmpeg's API. Converting a 20 MB .mov file to .mp4 this method takes about 13ms per invocation, but ffmpeg -i node-1.mov -c:v copy node-1.mp4 takes 34ms, likely due to start time overhead.

script:

❯ bun-debug mp4.js node-1.mov
[27.54ms] Compile ./mp4.c
[13.31ms] Convert node-1.mov to /Users/jarred/Desktop/node-1.mp4
[10.47ms] Convert node-1.mov to /Users/jarred/Desktop/node-1.mp4
[10.40ms] Convert node-1.mov to /Users/jarred/Desktop/node-1.mp4
[10.62ms] Convert node-1.mov to /Users/jarred/Desktop/node-1.mp4
[10.49ms] Convert node-1.mov to /Users/jarred/Desktop/node-1.mp4
[10.39ms] Convert node-1.mov to /Users/jarred/Desktop/node-1.mp4
[10.72ms] Convert node-1.mov to /Users/jarred/Desktop/node-1.mp4
[10.47ms] Convert node-1.mov to /Users/jarred/Desktop/node-1.mp4
[10.26ms] Convert node-1.mov to /Users/jarred/Desktop/node-1.mp4
[10.17ms] Convert node-1.mov to /Users/jarred/Desktop/node-1.mp4

ffmpeg cli:

❯ hyperfine "ffmpeg -i node-1.mov -c:v copy node-1.mp4 -y"
Benchmark 1: ffmpeg -i node-1.mov -c:v copy node-1.mp4 -y
  Time (mean ± σ):      36.8 ms ±   2.3 ms    [User: 21.6 ms, System: 14.7 ms]
  Range (min … max):    34.2 ms …  44.4 ms    79 runs
import { cc, ptr } from "bun:ffi";
import source from './mp4.c' with {type: 'file'};
import { basename, extname, join } from "path";

console.time(`Compile ./mp4.c`)
const {
  symbols: { convert_file_to_mp4 },
} = cc({
  source,
  library: ["c", "avcodec", "swscale", "avformat"],
  symbols: {
    convert_file_to_mp4: {
      returns: "int",
      args: ["cstring", "cstring"],
    },
  },
});
console.timeEnd(`Compile ./mp4.c`)
const outname = join(process.cwd(), basename(process.argv.at(2), extname(process.argv.at(2))) + ".mp4");
const input = Buffer.from(process.argv.at(2) + "\0");
const output = Buffer.from(outname + "\0");
for (let i = 0; i < 10; i++) {
console.time(`Convert ${process.argv.at(2)} to ${outname}`);
const result = convert_file_to_mp4(ptr(input), ptr(output));
if (result == 0) {
  console.timeEnd(`Convert ${process.argv.at(2)} to ${outname}`);
}
}

C (this was generated by claude)

#include <dlfcn.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>
#include <libswscale/swscale.h>
#include <stdio.h>
#include <stdlib.h>

int to_mp4(void *buf, size_t buflen, void **out, size_t *outlen) {
  AVFormatContext *input_ctx = NULL, *output_ctx = NULL;
  AVIOContext *input_io_ctx = NULL, *output_io_ctx = NULL;
  uint8_t *output_buffer = NULL;
  int ret = 0;
  int64_t *last_dts = NULL;

  // Register all codecs and formats

  // Create input IO context
  input_io_ctx = avio_alloc_context(buf, buflen, 0, NULL, NULL, NULL, NULL);
  if (!input_io_ctx) {
    ret = AVERROR(ENOMEM);
    goto end;
  }

  // Allocate input format context
  input_ctx = avformat_alloc_context();
  if (!input_ctx) {
    ret = AVERROR(ENOMEM);
    goto end;
  }

  input_ctx->pb = input_io_ctx;

  // Open input
  if ((ret = avformat_open_input(&input_ctx, NULL, NULL, NULL)) < 0) {
    goto end;
  }

  // Retrieve stream information
  if ((ret = avformat_find_stream_info(input_ctx, NULL)) < 0) {
    goto end;
  }

  // Allocate output format context
  avformat_alloc_output_context2(&output_ctx, NULL, "mp4", NULL);
  if (!output_ctx) {
    ret = AVERROR(ENOMEM);
    goto end;
  }

  // Create output IO context
  ret = avio_open_dyn_buf(&output_ctx->pb);
  if (ret < 0) {
    goto end;
  }

  // Copy streams
  for (int i = 0; i < input_ctx->nb_streams; i++) {
    AVStream *in_stream = input_ctx->streams[i];
    AVStream *out_stream = avformat_new_stream(output_ctx, NULL);
    if (!out_stream) {
      ret = AVERROR(ENOMEM);
      goto end;
    }

    ret = avcodec_parameters_copy(out_stream->codecpar, in_stream->codecpar);
    if (ret < 0) {
      goto end;
    }
    out_stream->codecpar->codec_tag = 0;
  }

  // Write header
  ret = avformat_write_header(output_ctx, NULL);
  if (ret < 0) {
    goto end;
  }

  // Allocate last_dts array
  last_dts = calloc(input_ctx->nb_streams, sizeof(int64_t));
  if (!last_dts) {
    ret = AVERROR(ENOMEM);
    goto end;
  }

  // Copy packets
  AVPacket pkt;
  while (1) {
    ret = av_read_frame(input_ctx, &pkt);
    if (ret < 0) {
      break;
    }

    AVStream *in_stream = input_ctx->streams[pkt.stream_index];
    AVStream *out_stream = output_ctx->streams[pkt.stream_index];

    // Convert timestamps
    pkt.pts =
        av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base,
                         AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
    pkt.dts =
        av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base,
                         AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
    pkt.duration =
        av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);

    // Ensure monotonically increasing DTS
    if (pkt.dts <= last_dts[pkt.stream_index]) {
      pkt.dts = last_dts[pkt.stream_index] + 1;
      pkt.pts = FFMAX(pkt.pts, pkt.dts);
    }
    last_dts[pkt.stream_index] = pkt.dts;

    pkt.pos = -1;

    ret = av_interleaved_write_frame(output_ctx, &pkt);
    if (ret < 0) {
      char errbuf[AV_ERROR_MAX_STRING_SIZE];
      av_strerror(ret, errbuf, AV_ERROR_MAX_STRING_SIZE);
      fprintf(stderr, "Error writing frame: %s\n", errbuf);
      break;
    }
    av_packet_unref(&pkt);
  }

  // Write trailer
  ret = av_write_trailer(output_ctx);
  if (ret < 0) {
    goto end;
  }

  // Get the output buffer
  *outlen = avio_close_dyn_buf(output_ctx->pb, &output_buffer);
  *out = output_buffer;
  output_ctx->pb = NULL; // Set to NULL to prevent double free

  ret = 0; // Success

end:
  if (input_ctx) {
    avformat_close_input(&input_ctx);
  }
  if (output_ctx) {
    avformat_free_context(output_ctx);
  }
  if (input_io_ctx) {
    av_freep(&input_io_ctx->buffer);
    av_freep(&input_io_ctx);
  }

  return ret;
}

int convert_file_to_mp4(const char *input_filename,
                        const char *output_filename) {
  FILE *input_file = NULL;
  FILE *output_file = NULL;
  uint8_t *input_buffer = NULL;
  uint8_t *output_buffer = NULL;
  size_t input_size = 0;
  size_t output_size = 0;
  int ret = 0;

  // Open the input file
  input_file = fopen(input_filename, "rb");
  if (!input_file) {
    perror("Could not open input file");
    return -1;
  }

  // Get the size of the input file
  fseek(input_file, 0, SEEK_END);
  input_size = ftell(input_file);
  fseek(input_file, 0, SEEK_SET);

  // Allocate memory for the input buffer
  input_buffer = (uint8_t *)malloc(input_size);
  if (!input_buffer) {
    perror("Could not allocate input buffer");
    ret = -1;
    goto cleanup;
  }

  // Read the input file into the buffer
  if (fread(input_buffer, 1, input_size, input_file) != input_size) {
    perror("Could not read input file");
    ret = -1;
    goto cleanup;
  }

  // Call the to_mp4 function to convert the buffer
  ret = to_mp4(input_buffer, input_size, (void **)&output_buffer, &output_size);
  if (ret < 0) {
    fprintf(stderr, "Error converting to MP4\n");
    goto cleanup;
  }

  // Open the output file
  output_file = fopen(output_filename, "wb");
  if (!output_file) {
    perror("Could not open output file");
    ret = -1;
    goto cleanup;
  }

  // Write the output buffer to the file
  if (fwrite(output_buffer, 1, output_size, output_file) != output_size) {
    perror("Could not write output file");
    ret = -1;
    goto cleanup;
  }

cleanup:

  if (output_buffer) {
    av_free(output_buffer);
  }
  if (input_file) {
    fclose(input_file);
  }
  if (output_file) {
    fclose(output_file);
  }

  return ret;
}

// for running it standalone
int main(const int argc, const char **argv) {

  if (argc != 3) {
    printf("Usage: %s <input_file> <output_file>\n", argv[0]);
    return -1;
  }

  const char *input_filename = argv[1];
  const char *output_filename = argv[2];

  int result = convert_file_to_mp4(input_filename, output_filename);
  if (result == 0) {
    printf("Conversion successful!\n");
  } else {
    printf("Conversion failed!\n");
  }
  return result;
}

This program below which includes 144 header files compiles in about 30ms in a debug build on an M1.

How did you verify your code works?

@paperclover

Copy link
Copy Markdown
Contributor

amazing proof of concept.

i still think the header parsing issue is a solvable skill issue and that should be attempted before making this the api we use. then the api would simply be cc({ source, libraries })

would be cool to explore later letting this be statically analyzable with --compile, bundling library requirements alongside pre-compiled code.


a note about your benchmark

  • -c:v copy tells ffmpeg to do nothing except memcpy the data streams
  • mov and mp4 are the same format

would have to look at both files but your demo is possibly just re-encoding the metadata. this is good to show call overhead, but good video encoding take seconds or minutes, not milliseconds; i don't see ffmpeg via ffi over cli a notable use case.

the opinionated command i use for encoding mp4+H.264 doesn't really care about encode time, but more so file size and quality:

ffmpeg -i "$input" -c:v libx264 -preset:v slow -crf:v 24 -c:a aac -pix_fmt yuv420p -movflags +faststart "$output"

(-crf can be moved down, not below 18, for higher quality, moved up to not above 50 for lower quality)

@190n 190n closed this Aug 19, 2024
@190n 190n reopened this Aug 19, 2024
@190n

190n commented Aug 19, 2024

Copy link
Copy Markdown
Contributor

so sorry, i hit the wrong button

@Jarred-Sumner
Jarred-Sumner marked this pull request as ready for review September 14, 2024 08:57
@Jarred-Sumner
Jarred-Sumner merged commit f4391e7 into main Sep 14, 2024
@Jarred-Sumner
Jarred-Sumner deleted the jarred/cc branch September 14, 2024 08:57
@alextwothousand

Copy link
Copy Markdown

I’m curious, is there perhaps a method to specify compiler, and is there any possibility building as a shared library can be added?

@TheApproach

TheApproach commented Sep 14, 2024 •

Copy link
Copy Markdown

does this use native types -- as in can I circumvent javascript's goofy floating point precision issues?

Jarred-Sumner pushed a commit that referenced this pull request Aug 18, 2026
…s, and misc crates (#39585)

Fresh PR for the part of #39561 that still applies on current main, as
requested there. Net -1,851 lines (71 files, +49 / -1,900). The
TextCodec section of #39561 is gone: #39485 deleted the WebKit codecs
outright. Everything else from that PR is carried over unchanged (it was
reviewed there, all threads resolved), plus one new group: orphaned
headers. No file here is touched by a dead-code PR that is still open.

Every removal has no reference left in `src/`, `packages/`, `scripts/`,
`test/` or the regenerated `build/debug/codegen/`, and the tree builds
without it. For Rust, C++ and headers that build is the reference check:
a definition with a caller, or a header with an includer, does not
compile.

### Orphaned headers (-1,169, new in this PR)

Nothing includes any of these (checked by include name and by plain text
across the tree, then by the build):

* `src/jsc/bindings/webcore/`: `EventSender.h`,
`JSDOMBindingInternalsBuiltins.h`, `JSDOMConstructorNotCallable.h`,
`JSDOMConvertVariadic.h`, `JSDOMConvertXPathNSResolver.h`,
`JSDOMConvertScheduledAction.h`, `BroadcastChannelIdentifier.h`,
`PortIdentifier.h`, `WebSocketIdentifier.h`. WebKit-derived headers
whose includers were removed by earlier cleanups.
* The empty stubs earlier sweeps left in place of deleted headers (their
own comment says to remove them once possible): `MessagePortChannel.h`,
`MessagePortChannelProvider.h`, `MessagePortChannelProviderImpl.h`,
`MessagePortChannelRegistry.h`, `MessagePortIdentifier.h`,
`BroadcastChannelRegistry.h`, `JSDOMBuiltinConstructorBase.h`,
`JSDOMConvertSerializedScriptValue.h`. The live registry is
`BunBroadcastChannelRegistry.h`.
* `src/jsc/bindings/objects.h`: 254 lines, every one of them commented
out.
* `src/jsc/bindings/ZigLazyStaticFunctions.h` and
`ZigLazyStaticFunctions-inlines.h`: marked "GENERATED FILE", but no
generator emits them and nothing includes them. The `*__put` helpers
they described live in the checked-in `ZigGeneratedCode.cpp`, and since
#36903 those install plain host functions. The comments in
`ffi/FFIObject.rs`, `ffi/mod.rs` and `host_fn.rs` that pointed at the
deleted header now say that instead.
* `src/runtime/ffi/ffi-stdatomic.h`: added with `cc()` in #13403 but
never part of the embedded header list (`ffi_body.rs` embeds stdbool,
stdarg, stdnoreturn, stdalign, tgmath, stddef), so `bun:ffi` users never
saw it.

### bun_install (-150)

* `PackageInstaller.rs`: `LazyPackageDestinationDir`. The only value
ever passed to `get_dir()` was the `Dir` variant, so `Owned`, the
`NodeModulesPath` arm (sole reader of its `#[allow(dead_code)]` field),
`Closed` and the error branch were unreachable; the else-branch built a
second value only to `close()` it. The EACCES handler reads
`destination_dir.fd()` directly. `pkg_dependencies` was written twice
and never read.
* `dependency.rs`: `DependencyExt::is_less_than` / `cmp` are
byte-identical copies of the inherent `Dependency::is_less_than` / `cmp`
in `install_types/resolver_hooks.rs`, and inherent associated functions
win for every `Dependency::cmp(..)` path in the tree (no UFCS call
exists). `DependencyExt::is_aliased`, `VersionExt::zeroed`, the
two-argument `VersionExt::clone_in` (every `clone_in` call is the
three-argument `Dependency` one) and the `ValueExt` trait it alone used,
plus the crate-root re-export.
* `error.rs`: `Error::DeviceBusy`, `BrokenPipe`, `Invalid`; the `From`
impls only produce `Sys(errno)` and `WriteFailed`, so the two match arms
naming them were dead too. `repository.rs`: the `Term::Stopped` arm
(variant removed below).

### bun_boringssl_sys (-60)

The file documents itself as the subset of symbols Bun's Rust crates
consume. Removed the ones none does: `SHA512_CTX`, `RIPEMD160_CTX`,
`RIPEMD160_DIGEST_LENGTH`, the `SHA384_*` / `SHA512_*` / `SHA512_256_*`
/ `RIPEMD160_*` functions (`bun_sha_hmac` drives these through EVP),
`EVP_md5_sha1`, `SSL_CTX_get_ex_data`, `SSL_CTX_set_cipher_list`,
`ERR_peek_error`, the `SSL_CIPHER` handle with `SSL_get_current_cipher`
/ `SSL_CIPHER_standard_name` / `SSL_CIPHER_get_name` /
`SSL_get_version`, `X509_STORE_free`, `i2d_SSL_SESSION` /
`d2i_SSL_SESSION` (`socket/tls_socket_functions.rs` declares and uses
its own copies of that last group).

### Other C++ (-70)

* `BunJSCModule.h`: the `@begin BunJSCModuleTable` lut source (never
generated; the module registers with `putNativeFn`) and the
`USE(BMALLOC_MEMORY_FOOTPRINT_API)` branch (macro defined nowhere, so
only the `jsNull()` body was ever compiled). Dropping the stray `//
clang-format off` needed one spacing fix.
* `ErrorCode.cpp/.h`: the `CRYPTO_INVALID_KEY_OBJECT_TYPE(JSValue, ...)`
overload; all 9 callers pass a `CryptoKeyType` (an `enum class`, not
convertible to `JSValue`).
* `headers-handwritten.h` + `node_process.rs`: `Bun__versions_uws` /
`Bun__versions_usockets`; `BunProcess.cpp` reads versions from the
generated header.

### Misc Rust (-400)

* `valkey_jsc`: the file-local `UnwrapOrOom` trait, replaced by
`bun_core::UnwrapOrOom`; `Default` for `Command` and `Args`. (The unused
`close_subscription_ctx` from #39561 was removed on main by #39530 in
the meantime.)
* `sql_jsc/mysql`: the `_options` / `options_buf` fields, the `init`
parameters feeding them and the JS-argument conversion; `_options` was
never read and `options_buf` was always an empty box. JS call shape
unchanged. `Default` for `SSLRequest`, `MySQLStatement`, `Raw`.
* `crypto/CryptoHasher.rs`: `StaticHasher::HAS_ENGINE`, `true` in the
only implementation, and the null-engine branches behind it.
`test/js/node/crypto/crypto.test.ts` now checks the one-shot
`Hash.hash()` outputs against `node:crypto`, the streaming digest and a
sentinel-filled caller buffer (review requests from #39561).
* `zlib.classes.ts` + `node_zlib_binding.rs`: the `dictionary`
cached-value slot; the bytes have been copied into the native context
since cd1ad59 and no accessor call remains.
* `node_fs_stat_watcher.rs` and `timer/TimeoutObject.rs`: hand-written
accessor modules that duplicated `generated_classes::js_StatWatcher` and
`bun_jsc::generated::JSTimeout`, now imports.
* `bun_spawn`: `Term::Stopped` (`run()` never builds it), the
`spawn_sys` compat re-export, the `IoCounters` / `WinRusage` /
`WinTimeval` / `FdT` re-exports (and the `spawn_sys/Cargo.toml` comment
that named them), `Default` for `NewQueue`.
* Manual impls with no user: `Default` for `bun_io::Request`,
`PipeReadScratch`, `HTTPResponseMetadata`, `InternalStateFlags`,
`RwLock<T>`, `Link<T>`, `SocketAddress`, shell `ast::Group`, `ast::If`,
`WorkerPipe` (and its empty `Drop`), `PackQueueItem`,
`ParseArgumentsCfg`; `Display` for shell `IO` / `InKind` / `OutKind` and
for `SmolList` (no element type implements `Debug`); `PartialEq<Error>
for ScanError` with the `IntoStaticStr` derive that served it;
`From<Tag> for &str` in `which_npm_client.rs`.
* `test/internal/source-lints/dead-code-escape-limits.json` regenerated:
`PackageInstaller.rs` no longer has escapes. This is the one check whose
result the PR changes (it fails against the base sources with this
inventory and passes here). No other test can fail before and pass after
a removal of uncalled code, and `test/internal/source-lints/CLAUDE.md`
asks for no dead-symbol tests.

### Verification

* `bun bd` builds and links with everything above removed (the header
deletions were built separately first, so an includer would have failed
that build).
* `bun run rust:check-all`: clean on all 12 target triples.
* `bun bd test`: `node/crypto/crypto.test.ts`, `bun/ffi/ffi.test.js`,
`node/zlib/zlib.test.js`, `fs.watchFile`, `node/timers` (981 pass),
`cli/install` bun-add + bun-pack, `bun/shell` brace + parse (all pass).
On the previous base the same Rust diff also passed the encoding, shell
interpreter, parallel runner and source-lint suites, plus hand-run
Bun.SQL against MariaDB and Bun.RedisClient against redis.
* `web/workers/worker.test.ts`: three "terminate() races" cases fail in
this container's debug build while a 12-target cargo check was running
(worker startup did not happen within the 30 ms / 5 s the tests allow);
the same cases pass here on a release build that contains the same Rust
and C++ changes, and nothing in this PR is reachable from worker code
(the MessagePort and BroadcastChannel files removed are empty or
never-included headers).

### Probably dead, left alone

* `headers.h` still declares thirteen `*__fastpath` functions
(`FFI__ptr__fastpath`, `Reader__*__fastpath`) that have had no
definition since #36903 removed the DOMJIT paths; left out only because
touching `headers.h` rebuilds most of the C++.
* From #39561, unchanged: the three react_compiler lint validators whose
result `pipeline.rs` discards, the never-constructed logger types in
`compile_result.rs`, the test-only outbound half of the h2 engine,
`bun_shim_impl::read_without_launch`, the `#[cfg(not(windows))]` stubs
inside the windows-only named-pipe modules,
`DependencyToEnqueue::Pending`, `misctools/cold-jsc-start.cpp` (no build
rule since #21863) and `completions/spec.yaml`.

<!-- robobun:evidence:begin -->

---

**[review]** gate passed · iteration 3 · 71 files touched

<details><summary>fails on main (without fix)</summary>

```console
ASAN without fix: BUILD FAILED (no junit output)
$ BUN_DEBUG_QUIET_LOGS=1 bun scripts/build.ts --profile=debug --quiet test "--reporter=junit" "--reporter-outfile=/tmp/mechgate.xml" test/js/node/crypto/crypto.test.ts
ninja: Entering directory `/workspace/bun/build/debug'
[1/181] gen ErrorCode+*.h
[2/181] gen bake.{client,server,error}.js
-> bake.client.js, bake.server.js, bake.error.js
[3/181] gen JSBuffer.lut.h
Generating /workspace/bun/build/debug/codegen/JSBuffer.lut.h from /workspace/bun/src/jsc/bindings/JSBuffer.cpp
[4/181] gen generated_host_exports.rs
generated_host_exports.rs: 92 exports (host=3, lazy=10, generic=79, rust=0); 241 extern-C blocks audited
[5/181] gen ZigGeneratedClasses.{cpp,h,rs}
Found 2 classes from /workspace/bun/src/jsc/resolve_message.classes.ts
  - ResolveMessage (15 fields)
  - BuildMessage (10 fields)
Found 1 classes from /workspace/bun/src/runtime/api/Archive.classes.ts
  - Archive (4 fields, 1 class fields)
Found 2 classes from /workspace/bun/src/runtime/api/BunObject.classes.ts
  - ResourceUsage (8 fields)
  - Subprocess (20 fields)
Found 1 classes from /workspace/bun/src/runtime/api/cron.classes.ts
  - CronJob (5 fields)
Found 3 classes from /workspace/bun/src/runtime/api/filesys
... (truncated)

release without fix: all passed
bun test v1.4.0-canary.1 (6fcf13c)

test/js/node/crypto/crypto.test.ts:
(pass) CryptoHasher > CryptoHasher.algorithms [0.08ms]
(pass) CryptoHasher > new CryptoHasher blake2b256 [1.14ms]
(pass) CryptoHasher > CryptoHasher.hash blake2b256 [0.04ms]
(pass) CryptoHasher > new CryptoHasher blake2b256 multi-part [0.04ms]
(pass) CryptoHasher > new CryptoHasher blake2b256 to Buffer [0.05ms]
(pass) CryptoHasher > new CryptoHasher blake2b512 [0.01ms]
(pass) CryptoHasher > CryptoHasher.hash blake2b512
(pass) CryptoHasher > new CryptoHasher blake2b512 multi-part
(pass) CryptoHasher > new CryptoHasher blake2b512 to Buffer
(pass) CryptoHasher > new CryptoHasher blake2s256 [0.01ms]
(pass) CryptoHasher > CryptoHasher.hash blake2s256
(pass) CryptoHasher > new CryptoHasher blake2s256 multi-part
(pass) CryptoHasher > new CryptoHasher blake2s256 to Buffer
(pass) CryptoHasher > new CryptoHasher md4
(pass) CryptoHasher > CryptoHasher.hash md4
(pass) CryptoHasher > new CryptoHasher md4 multi-part
(pass) CryptoHasher > new CryptoHasher md4 to Buffer
(pass) CryptoHasher > new CryptoHasher md5
(pass) CryptoHasher > CryptoHasher.hash md5
(pass) CryptoHasher > new CryptoHasher md5 multi-part

... (truncated)
```

</details>

<details><summary>passes on PR (with fix)</summary>

```console
ASAN with fix: all passed
$ BUN_DEBUG_QUIET_LOGS=1 bun scripts/build.ts --profile=debug --quiet test "--reporter=junit" "--reporter-outfile=/tmp/mechgate.xml" test/js/node/crypto/crypto.test.ts
bun test v1.4.0 (8326d1b)

test/js/node/crypto/crypto.test.ts:
(pass) CryptoHasher > CryptoHasher.algorithms [2.82ms]
(pass) CryptoHasher > new CryptoHasher blake2b256 [3.70ms]
(pass) CryptoHasher > CryptoHasher.hash blake2b256 [2.35ms]
(pass) CryptoHasher > new CryptoHasher blake2b256 multi-part [2.37ms]
(pass) CryptoHasher > new CryptoHasher blake2b256 to Buffer [3.36ms]
(pass) CryptoHasher > new CryptoHasher blake2b512 [1.62ms]
(pass) CryptoHasher > CryptoHasher.hash blake2b512 [0.74ms]
(pass) CryptoHasher > new CryptoHasher blake2b512 multi-part [1.00ms]
(pass) CryptoHasher > new CryptoHasher blake2b512 to Buffer [0.97ms]
(pass) CryptoHasher > new CryptoHasher blake2s256 [0.86ms]
(pass) CryptoHasher > CryptoHasher.hash blake2s256 [0.38ms]
(pass) CryptoHasher > new CryptoHasher blake2s256 multi-part [0.56ms]
(pass) CryptoHasher > new CryptoHasher blake2s256 to Buffer [1.40ms]
(pass) CryptoHasher > new CryptoHasher md4 [0.76ms]
(pass) CryptoHasher > CryptoHasher.hash md4 [0.43ms]
(pass) CryptoHash
... (truncated)

release with fix: all passed
$ bun scripts/build.ts --profile=release
[configured] bun-profile → bun (stripped) in 666ms (unchanged)
ninja: Entering directory `/workspace/bun/build/release'
[1/141] gen ErrorCode+*.h
[2/141] gen bake.{client,server,error}.js
-> bake.client.js, bake.server.js, bake.error.js
[3/141] gen JSBuffer.lut.h
Generating /workspace/bun/build/release/codegen/JSBuffer.lut.h from /workspace/bun/src/jsc/bindings/JSBuffer.cpp
[4/141] gen generated_host_exports.rs
generated_host_exports.rs: 92 exports (host=3, lazy=10, generic=79, rust=0); 241 extern-C blocks audited
[5/141] gen ZigGeneratedClasses.{cpp,h,rs}
Found 2 classes from /workspace/bun/src/jsc/resolve_message.classes.ts
  - ResolveMessage (15 fields)
  - BuildMessage (10 fields)
Found 1 classes from /workspace/bun/src/runtime/api/Archive.classes.ts
  - Archive (4 fields, 1 class fields)
Found 2 classes from /workspace/bun/src/runtime/api/BunObject.classes.ts
  - ResourceUsage (8 fields)
  - Subprocess (20 fields)
Found 1 classes from /workspace/bun/src/runtime/api/cron.classes.ts
  - CronJob (5 fields)
Found 3 classes from /workspace/bun/src/runtime/api/filesystem_router.classes.ts
  - FileSystemRouter (5 fields)
  - 
... (truncated)
```

</details>

<details><summary>diff hotspot</summary>

```
src/boringssl_sys/boringssl.rs                     |  69 ------
 src/http/InternalState.rs                          |   7 -
 src/http/lib.rs                                    |  15 +-
 src/install/PackageInstaller.rs                    |  90 +-------
 .../PackageManager/PackageManagerResolution.rs     |   3 +-
 src/install/dependency.rs                          |  99 --------
 src/install/error.rs                               |   9 -
 src/install/hoisted_install.rs                     |   2 -
 src/install/lib.rs                                 |   2 +-
 src/install/lockfile.rs                            |   2 +-
 src/install/repository.rs                          |   1 -
 src/io/lib.rs                                      |  10 -
 src/io/pipe_read_scratch.rs                        |   6 -
 src/jsc/bindings/ErrorCode.cpp                     |  14 --
 src/jsc/bindings/ErrorCode.h                       |   1 -
 src/jsc/bindings/ZigLazyStaticFunctions-inlines.h  |  33 ---
 src/jsc/bindings/ZigLazyStaticFunctions.h          |  21 --
 src/jsc/bindings/headers-handwritten.h             |   5 -
 src/jsc/bindings/objects.h                         | 254 ---------------------
 .../bindings/webcore/BroadcastChannelIdentifier.h  |  35 ---
 .../bindings/webcore/BroadcastChannelRegistry.h    |   5 -
 src/jsc/bindings/webcore/EventSender.h             | 116 ----------
 .../webcore/JSDOMBindingInternalsBuiltins.h        | 159 -------------
 .../bindings/webcore/JSDOMBuiltinConstructorBase.h |   2 -
 .../bindings/webcore/JSDOMConstructorNotCallable.h |  85 -------
 .../bindings/webcore/JSDOMConvertScheduledAction.h |  53 -----
 .../webcore/JSDOMConvertSerializedScriptValue.h    |   2 -
 src/jsc/bindings/webcore/JSDOMConvertVariadic.h    |  74 ------
 .../bindings/webcore/JSDOMConvertXPathNSResolver.h |  55 -----
 src/jsc/bindings/webcore/MessagePortChannel.h      |   5 -
 .../bindings/webcore/MessagePortChannelProvider.h  |   5 -
 .../webcore/MessagePortChannelProvi
... (truncated)
```

</details>

**gate history** · 2 passed · 0 rejected · iteration 3

<details><summary>evidence per changed file</summary>

```
file                                                    reads  edits  tests
src/boringssl_sys/boringssl.rs                              0      0      0
src/http/InternalState.rs                                   0      0      0
src/http/lib.rs                                             0      0      0
src/install/PackageInstaller.rs                             5      0      0
src/install/PackageManager/PackageManagerResolution.rs      0      0      0
src/install/dependency.rs                                   0      0      0
src/install/error.rs                                        0      0      0
src/install/hoisted_install.rs                              0      0      0
src/install/lib.rs                                          0      0      0
src/install/lockfile.rs                                     0      0      0
src/install/repository.rs                                   0      0      0
src/io/lib.rs                                               0      0      0
src/io/pipe_read_scratch.rs                                 0      0      0
src/jsc/bindings/ErrorCode.cpp                              0      0      0
src/jsc/bindings/ErrorCode.h                                0      0      0
src/jsc/bindings/ZigLazyStaticFunctions-inlines.h           0      0      0
(+ 55 more files)
```

</details>

<!-- robobun:evidence:end -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants