From d3f917854ecdba3274306fb2507a78e374e1b6eb Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 11 Sep 2026 09:14:34 -0700 Subject: [PATCH] feat(rong): re-export TaskScope MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `rong_core` 0.6.1 added `TaskScope` and the three context methods that open, switch and cancel one. The methods came through the `rong` facade for free — they are inherent on `JSContext`, which is an alias for the core type — but the type itself was never added to the re-export list, so under `rong` it has no name. That is enough to use a scope and not enough to embed one. An embedder opening a scope per request opens it where the request starts and cancels it where the request ends; in between the value lives in a field, and a field has to be written with a type. Reaching into `rong_core` to name it would mean depending on the crate the facade exists to cover. The existing tests did not catch this because every one of them takes the type from inference, inside a single function. The new one stores a scope in a struct and cancels it from there, which is the shape an embedder actually has, and it fails to compile without the re-export. --- CHANGELOG.md | 7 +++++++ Cargo.toml | 2 +- src/lib.rs | 2 +- tests/task_scope.rs | 23 +++++++++++++++++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1342cc12..7ae3dac0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,13 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve manual dispatch still run it. macOS jobs prefer Xcode libclang over Homebrew LLVM when present. +### Core + +- `rong` re-exports `TaskScope`. The scope methods reached embedders already, + being inherent on `JSContext`, but the type did not, so a scope could only + be opened and cancelled inside one function — never stored, which is what + one scope per request needs. + ## [0.6.2] - 2026-09-11 Independent crate and npm releases: first publish of `rong_crypto` 0.6.0, diff --git a/Cargo.toml b/Cargo.toml index 410bb81f..67c260df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -123,7 +123,7 @@ base64 = { version = "0.22.1" } [package] name = "rong" -version = "0.6.0" +version = "0.6.1" edition = "2024" description = "RongJS runtime and embedding API" diff --git a/src/lib.rs b/src/lib.rs index 41d89c5c..1864b217 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,7 @@ pub use rong_core::{ JSRuntime as CoreJSRuntime, JSRuntimeService, JSSymbol as CoreJSSymbol, JSTypedArray as CoreJSTypedArray, JSTypedArrayKind, JSValue as CoreJSValue, JSValueType, JsonToJSValue, Promise as CorePromise, PropertyDescriptor as CorePropertyDescriptor, - RongJSError, Source, SourceKind, Uint8Clamped, error, illegal_constructor, + RongJSError, Source, SourceKind, TaskScope, Uint8Clamped, error, illegal_constructor, install_async_iterator_symbol, install_iterator_symbol, }; // Re-export selected runtime API from rong_core::rong so downstream crates use `rong::...` diff --git a/tests/task_scope.rs b/tests/task_scope.rs index c0ffdfab..6ab35885 100644 --- a/tests/task_scope.rs +++ b/tests/task_scope.rs @@ -185,3 +185,26 @@ fn scope_ids_are_not_reused_across_runtimes() { assert_eq!(ctx.current_task_scope(), Some(second)); assert!(ctx.cancel_task_scope(second)); } + +/// An embedder that opens a scope per request cannot open and cancel it in one +/// function: it opens the scope where the request starts and cancels it where +/// the request ends, so the value has to live in a field in between. Writing a +/// field means writing the type, which means `TaskScope` has to be reachable +/// under the name an embedder depends on — `rong`, not `rong_core`. +/// +/// Every other test here gets the type from inference, so none of them would +/// notice it missing from the facade. +#[test] +fn a_scope_can_be_stored_under_its_public_name() { + struct PendingRequest { + scope: TaskScope, + } + + let runtime = RongJS::runtime(); + let ctx = runtime.context(); + let request = PendingRequest { + scope: ctx.begin_task_scope(), + }; + // Opened elsewhere, cancelled here, exactly as a request's lifetime runs. + assert!(ctx.cancel_task_scope(request.scope)); +}