Skip to content

fast_api: require &'static for CFunction overload storage#1990

Open
divybot wants to merge 1 commit into
mainfrom
orch/divybot-160
Open

fast_api: require &'static for CFunction overload storage#1990
divybot wants to merge 1 commit into
mainfrom
orch/divybot-160

Conversation

@divybot
Copy link
Copy Markdown

@divybot divybot commented May 20, 2026

Summary

Resolves #1989 by enforcing — at the Rust type level — the
storage-lifetime invariant introduced by upstream V8 change
crrev.com/c/7828135
([fastapi] Store v8::CFunction pointer directly in FunctionTemplateInfo,
slated for V8 15).

Before that V8 patch, FunctionTemplate::NewWithCFunctionOverloads copied
each v8::CFunction into a Managed<CFunctionWithSignature> heap object, so
the embedder's overload storage only needed to outlive the call. After it,
V8 retains the raw v8::CFunction* directly inside FunctionTemplateInfo
and reads it back on every fast-call dispatch, so the pointed-to storage
must outlive every FunctionTemplate that references it — which in
practice means 'static (templates can live until isolate disposal).

Today FunctionBuilder::build_fast accepts any &[CFunction] and forwards
as_ptr() to V8, so a deno_core-style call shape like
builder.build_fast(scope, &[fast_function]) would silently dangle once the
V8 15 ABI lands. This PR makes that misuse a compile error today instead
of a use-after-free tomorrow.

Changes

  • FunctionBuilder::build_fast now takes overloads: &'static [CFunction].
  • fast_api::CFunction::new now takes type_info: &'static CFunctionInfo,
    so the type_info_ pointer it caches cannot dangle either.
  • fast_api::CFunctionInfo::new now takes arg_info: &'static [CTypeInfo],
    same reason — the constructed CFunctionInfo caches arg_info.as_ptr().
  • Doc comments on all three explain the invariant and the canonical
    static-promoted const pattern.

Tests / call sites

The existing call sites in tests/test_api.rs and benches/function.rs
already use the canonical pattern —

const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new(
    fast_fn as _,
    &fast_api::CFunctionInfo::new(/* ... */),
);
// ...
.build_fast(scope, &[FAST_TEST]);

— which Rust static-promotes to &'static [CFunction; 1], so no test
changes are required. cargo check --benches and cargo test --test test_ui both pass locally; the test-suite test_api/test_cppgc
binaries also compile through the relevant call sites (their only
remaining errors here are missing third_party/icu/common/icudtl.dat,
unrelated to this change).

A new trybuild compile_fail test
tests/compile_fail/build_fast_local_overloads.rs
demonstrates that a runtime-built Vec<CFunction> is now rejected with
E0597 — argument requires that 'overloads' is borrowed for 'static.

Context

Closes denoland/divybot#160

Upstream crrev.com/c/7828135 (slated for V8 15) changes
FunctionTemplateInfo to store the raw v8::CFunction pointers passed to
NewWithCFunctionOverloads directly, rather than copying them into a
Managed<CFunctionWithSignature> heap object. The pointed-to storage must
therefore outlive every FunctionTemplate that references it - in
practice this means it has to be 'static, since a FunctionTemplate can
live until isolate disposal.

Enforce the invariant at the Rust type level so embedders cannot pass
stack-local overload storage:

* FunctionBuilder::build_fast now requires &'static [CFunction].
* CFunction::new now requires &'static CFunctionInfo so the type_info
  pointer it caches cannot dangle.
* CFunctionInfo::new now requires &'static [CTypeInfo] for arg_info for
  the same reason - the constructed CFunctionInfo caches arg_info.as_ptr().

The existing call sites in tests/test_api.rs and benches/function.rs
already use the canonical pattern - const FAST: CFunction = ...; build_fast(
scope, &[FAST]) - which Rust static-promotes to &'static [CFunction; 1],
so no test changes are required. A new trybuild compile_fail test
(tests/compile_fail/build_fast_local_overloads.rs) demonstrates that a
runtime-built Vec<CFunction> is now rejected with E0597.

Refs #1989
Closes denoland/orchid#160

Co-Authored-By: Divy Srivastava <me@littledivy.com>
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@divybot divybot changed the title rusty_v8: make fast API CFunction overload storage V8-15 safe fast_api: require &'static for CFunction overload storage May 20, 2026
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.

fast_api: tighten FunctionTemplateBuilder::build_fast overload-list lifetime for V8 15.x

2 participants