Skip to content

Conversation

@anonrig
Copy link
Member

@anonrig anonrig commented Oct 22, 2025

Add Rust JSG bindings and comprehensive test coverage

This PR introduces Rust bindings for JSG, enabling
Rust code to interact with V8 and implement JavaScript APIs.

Key changes:

  • Add jsg crate with V8 bindings (Local/Global handles, types, resources)
  • Add jsg-macros for procedural macros (jsg_struct, jsg_resource, jsg_method)
  • Add jsg-test harness with proper Realm initialization for testing
  • Implement comprehensive test suite for JSG bindings
  • Add support for wrapping/unwrapping Rust resources in V8

The Rust JSG implementation provides type-safe V8 integration and will
enable more Rust-based APIs in workerd.

Example usage:

#[test]
fn objects_can_be_wrapped_and_unwrapped() {
    let harness = crate::Harness::new();
    harness.run_in_context(|isolate| unsafe {
        let mut lock = Lock::from_isolate(isolate);
        let instance = TestStruct {
            str: "test".to_string(),
        };
        let wrapped = instance.wrap(&mut lock);
        let mut obj: v8::Local<'_, v8::Object> = wrapped.into();
        assert!(obj.has(&mut lock, "str"));
        let str_value = obj.get(&mut lock, "str");
        assert!(str_value.unwrap().is_string());
        assert!(!obj.has(&mut lock, "test"));
        let value = "value".to_local(&mut lock);
        assert!(value.is_string());
        obj.set(&mut lock, "test", value);
        assert!(obj.has(&mut lock, "test"));
    });
}

@anonrig anonrig force-pushed the yagiz/rust-jsg-boilerplate branch from 89d6e2b to 01bc9ec Compare October 22, 2025 20:28
@codspeed-hq

This comment has been minimized.

@github-actions
Copy link

github-actions bot commented Oct 23, 2025

The generated output of @cloudflare/workers-types matches the snapshot in types/generated-snapshot 🎉

@anonrig anonrig force-pushed the yagiz/rust-jsg-boilerplate branch from f30d328 to 0fc6fee Compare October 27, 2025 17:47
@anonrig anonrig force-pushed the yagiz/rust-jsg-boilerplate branch 3 times, most recently from f463539 to 440508a Compare October 30, 2025 20:24
@anonrig anonrig force-pushed the yagiz/rust-jsg-boilerplate branch 7 times, most recently from 7be536c to e218b33 Compare November 10, 2025 17:01
@anonrig anonrig force-pushed the yagiz/rust-jsg-boilerplate branch 3 times, most recently from f33addc to 3f458ba Compare November 17, 2025 21:38
@anonrig anonrig changed the title start working on jsg/rust integration add initial jsg rust integration Nov 17, 2025
@anonrig anonrig force-pushed the yagiz/rust-jsg-boilerplate branch from 3f458ba to 1527967 Compare November 17, 2025 21:58
@anonrig anonrig force-pushed the yagiz/rust-jsg-boilerplate branch 3 times, most recently from f636b19 to 42435db Compare November 18, 2025 20:16
@anonrig anonrig mentioned this pull request Nov 19, 2025
3 tasks
@anonrig anonrig force-pushed the yagiz/rust-jsg-boilerplate branch from 20579ac to 31942b8 Compare November 21, 2025 20:54
@jasnell
Copy link
Collaborator

jasnell commented Nov 24, 2025

The C++ bits LGTM. Looked over the Rust bits too and they look fine but would rather have someone who's more of a rust expert to do the sign off.

@anonrig anonrig force-pushed the yagiz/rust-jsg-boilerplate branch 2 times, most recently from bd1711a to f69900d Compare November 24, 2025 16:03
@anonrig anonrig requested review from Copilot and mikea and removed request for erikcorry, fhanau, harrishancock and mikea November 25, 2025 03:14
Copilot finished reviewing on behalf of anonrig November 25, 2025 03:17
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces comprehensive Rust bindings for the JSG (JavaScript Glue) system, enabling Rust code to interact with V8 and implement JavaScript APIs. The implementation provides type-safe V8 integration with support for wrapping/unwrapping Rust resources, procedural macros for reducing boilerplate, and a test harness with proper Realm initialization.

Key Changes:

  • Added core Rust JSG bindings (jsg crate) with V8 handle types (Local/Global), FFI bridges, and resource management
  • Implemented procedural macros (jsg-macros) for #[jsg_struct], #[jsg_resource], and #[jsg_method] to reduce boilerplate
  • Created test infrastructure (jsg-test) with proper V8 context setup for testing Rust JSG bindings
  • Integrated Rust-backed Node.js DNS implementation as a demonstration, conditionally enabled via autogate
  • Added Realm tracking for deterministic cleanup of Rust resources when V8 contexts are disposed

Reviewed changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
src/workerd/util/autogate.h Added RUST_BACKED_NODE_DNS autogate key for feature flagging
src/workerd/util/autogate.c++ Registered the new autogate key with its string representation
src/workerd/jsg/wrappable.h Added RUST_REALM context slot and WORKERD_RUST_WRAPPABLE_TAG for Rust resources
src/workerd/jsg/setup.h Exposed getIsolate() method for Rust FFI access to V8 isolate
src/workerd/jsg/BUILD.bazel Added Rust JSG dependency and visibility for Rust packages
src/workerd/io/worker.c++ Integrated Realm creation/disposal in context lifecycle
src/workerd/api/rtti.c++ Added stub addBuiltinModule overload for future module registration
src/workerd/api/node/node.h Conditionally registers C++ or Rust DNS implementation based on autogate
src/workerd/api/node/BUILD.bazel Added Rust API dependency
src/rust/jsg/v8.rs Core V8 FFI bindings with Local/Global handles and type conversions
src/rust/jsg/modules.rs Module registration interface for Rust modules
src/rust/jsg/lib.rs Core JSG types: Lock, Ref, Resource/Struct traits, Realm, and resource lifecycle
src/rust/jsg/jsg.h C++ wrapper for Rust module registry integration
src/rust/jsg/ffi.h FFI function declarations for V8 operations
src/rust/jsg/ffi.c++ FFI function implementations bridging Rust and V8 C++ APIs
src/rust/jsg/ffi-inl.h Template implementations for FFI type conversions
src/rust/jsg/BUILD.bazel Build configuration for JSG Rust crate and FFI library
src/rust/jsg-test/lib.rs Test harness and comprehensive integration tests for JSG bindings
src/rust/jsg-test/ffi.h Test harness interface declarations
src/rust/jsg-test/ffi.c++ Test harness implementation with V8 context setup
src/rust/jsg-test/BUILD.bazel Build configuration for test infrastructure
src/rust/jsg-macros/lib.rs Procedural macros for struct/resource/method code generation
src/rust/jsg-macros/README.md Documentation for macro usage patterns
src/rust/jsg-macros/BUILD.bazel Build configuration for proc macro crate
src/rust/dns/lib.rs Added note about temporary duplication during migration
src/rust/api/lib.rs Module registration entry point for Rust Node.js APIs
src/rust/api/dns.rs Rust implementation of DNS utility with CAA/NAPTR record parsing
src/rust/api/BUILD.bazel Build configuration for API crate
patches/v8/0014-Add-another-slot-in-the-isolate-for-embedder.patch Increased V8 isolate data slots to accommodate Rust realm
compile_flags.txt Added include paths for new Rust JSG modules

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@anonrig anonrig force-pushed the yagiz/rust-jsg-boilerplate branch 4 times, most recently from c42f082 to efee4b3 Compare November 25, 2025 21:26
@anonrig anonrig force-pushed the yagiz/rust-jsg-boilerplate branch 2 times, most recently from b4423e0 to 6537ca2 Compare November 26, 2025 19:10
@anonrig anonrig closed this Nov 26, 2025
@anonrig anonrig force-pushed the yagiz/rust-jsg-boilerplate branch from 6537ca2 to 6cc580c Compare November 26, 2025 19:25
@anonrig anonrig reopened this Nov 26, 2025
@anonrig anonrig force-pushed the yagiz/rust-jsg-boilerplate branch from eed4176 to 473a0a0 Compare November 26, 2025 20:00
}
}
let result = self_.#fn_name(#(#arg_refs),*);
unsafe { jsg::handle_result(&mut lock, &mut args, result) };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we put these kinds of unsafe / system calls into a special namespace that is clear that it isn't meant to be used directly in user code?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't that the whole point of using unsafe keyword in Rust?

@anonrig anonrig force-pushed the yagiz/rust-jsg-boilerplate branch from 4338c6a to 945b0bf Compare November 30, 2025 02:44
@anonrig anonrig force-pushed the yagiz/rust-jsg-boilerplate branch from 945b0bf to 7b211af Compare November 30, 2025 02:47
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.

4 participants