From 7fa78ca3596e79745c13c46e6edca46d92a4bd9a Mon Sep 17 00:00:00 2001 From: Connor Hindley Date: Fri, 10 Oct 2025 14:31:05 -0500 Subject: [PATCH 1/3] feat: add props support to Context Adds support for accessing props passed to workers via service bindings, enabling configuration to be passed based on invocation context. --- worker-sys/src/types/context.rs | 3 +++ worker/src/context.rs | 34 +++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/worker-sys/src/types/context.rs b/worker-sys/src/types/context.rs index 63f7eebb3..e6f05dc59 100644 --- a/worker-sys/src/types/context.rs +++ b/worker-sys/src/types/context.rs @@ -11,4 +11,7 @@ extern "C" { #[wasm_bindgen(method, catch, js_name=passThroughOnException)] pub fn pass_through_on_exception(this: &Context) -> Result<(), JsValue>; + + #[wasm_bindgen(method, getter)] + pub fn props(this: &Context) -> JsValue; } diff --git a/worker/src/context.rs b/worker/src/context.rs index 1b59920c2..e913a0840 100644 --- a/worker/src/context.rs +++ b/worker/src/context.rs @@ -1,7 +1,9 @@ use std::future::Future; use crate::worker_sys::Context as JsContext; +use crate::Result; +use serde::de::DeserializeOwned; use wasm_bindgen::JsValue; use wasm_bindgen_futures::future_to_promise; @@ -47,6 +49,38 @@ impl Context { pub fn pass_through_on_exception(&self) { self.inner.pass_through_on_exception().unwrap() } + + /// Get the props passed to this worker execution context. + /// + /// Props provide a way to pass additional configuration to a worker based on the context + /// in which it was invoked. For example, when your Worker is called by another Worker via + /// a Service Binding, props can provide information about the calling worker. + /// + /// Props are configured in your wrangler.toml when setting up Service Bindings: + /// ```toml + /// [[services]] + /// binding = "MY_SERVICE" + /// service = "my-worker" + /// props = { clientId = "frontend", permissions = ["read", "write"] } + /// ``` + /// + /// Then deserialize them to your custom type: + /// ```no_run + /// use serde::Deserialize; + /// + /// #[derive(Deserialize)] + /// struct MyProps { + /// clientId: String, + /// permissions: Vec, + /// } + /// + /// let props = ctx.props::()?; + /// ``` + /// + /// See: + pub fn props(&self) -> Result { + Ok(serde_wasm_bindgen::from_value(self.inner.props())?) + } } impl AsRef for Context { From 0bf2bb129b8f12f7600ea22294001fbad5b477e1 Mon Sep 17 00:00:00 2001 From: Connor Hindley Date: Fri, 10 Oct 2025 23:12:35 -0500 Subject: [PATCH 2/3] wire up wasm_bindgen_test and wasm-bindgen-test-runner --- .github/workflows/pullrequest.yml | 7 +++- Cargo.lock | 1 + worker/Cargo.toml | 3 ++ worker/src/context.rs | 61 +++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 19888f914..347e81dd3 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -186,7 +186,12 @@ jobs: run: npm ci - name: Build Wasm Bindgen - run: cd wasm-bindgen && cargo build -p wasm-bindgen-cli --bin wasm-bindgen + run: cd wasm-bindgen && cargo build -p wasm-bindgen-cli --bin wasm-bindgen --bin wasm-bindgen-test-runner + + - name: Run wasm-bindgen tests + env: + CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER: ${{ github.workspace }}/wasm-bindgen/target/debug/wasm-bindgen-test-runner + run: cargo test -p worker --target wasm32-unknown-unknown - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 diff --git a/Cargo.lock b/Cargo.lock index ad11ae24b..b8120930f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4039,6 +4039,7 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-bindgen-test", "wasm-streams", "web-sys", "worker-macros", diff --git a/worker/Cargo.toml b/worker/Cargo.toml index 58bf6d1e2..2f8f807d6 100644 --- a/worker/Cargo.toml +++ b/worker/Cargo.toml @@ -50,3 +50,6 @@ d1 = ["worker-sys/d1"] http = ["worker-macros/http"] axum = ["dep:axum"] timezone = ["dep:chrono-tz"] + +[dev-dependencies] +wasm-bindgen-test.workspace = true diff --git a/worker/src/context.rs b/worker/src/context.rs index e913a0840..f84cfe3c4 100644 --- a/worker/src/context.rs +++ b/worker/src/context.rs @@ -88,3 +88,64 @@ impl AsRef for Context { &self.inner } } + +#[cfg(test)] +mod tests { + use super::*; + use serde::Deserialize; + use wasm_bindgen::JsCast; + use wasm_bindgen_test::*; + + #[derive(Debug, Deserialize, PartialEq)] + struct TestProps { + #[serde(rename = "clientId")] + client_id: String, + permissions: Vec, + } + + #[wasm_bindgen_test] + fn test_props_deserialization() { + // Create a mock ExecutionContext with props + let obj = js_sys::Object::new(); + + // Add props to the object + let props = js_sys::Object::new(); + js_sys::Reflect::set(&props, &"clientId".into(), &"frontend-worker".into()).unwrap(); + + let permissions = js_sys::Array::new(); + permissions.push(&"read".into()); + permissions.push(&"write".into()); + js_sys::Reflect::set(&props, &"permissions".into(), &permissions.into()).unwrap(); + + js_sys::Reflect::set(&obj, &"props".into(), &props.into()).unwrap(); + + // Create a Context from the mock object + let js_context: JsContext = obj.unchecked_into(); + let context = Context::new(js_context); + + // Test that props can be deserialized + let result: Result = context.props(); + assert!(result.is_ok()); + + let props = result.unwrap(); + assert_eq!(props.client_id, "frontend-worker"); + assert_eq!(props.permissions, vec!["read", "write"]); + } + + #[wasm_bindgen_test] + fn test_props_empty_object() { + // Create a mock ExecutionContext with empty props + let obj = js_sys::Object::new(); + let props = js_sys::Object::new(); + js_sys::Reflect::set(&obj, &"props".into(), &props.into()).unwrap(); + + let js_context: JsContext = obj.unchecked_into(); + let context = Context::new(js_context); + + #[derive(Debug, Deserialize, PartialEq)] + struct EmptyProps {} + + let result: Result = context.props(); + assert!(result.is_ok()); + } +} From d37fe49bf9bd9421734b1e591089c3ddb9c454cc Mon Sep 17 00:00:00 2001 From: Connor Hindley Date: Tue, 14 Oct 2025 18:17:16 -0500 Subject: [PATCH 3/3] rustup target add wasm32-unknown-unknown --- .github/workflows/pullrequest.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 347e81dd3..afd40bbfb 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -188,6 +188,9 @@ jobs: - name: Build Wasm Bindgen run: cd wasm-bindgen && cargo build -p wasm-bindgen-cli --bin wasm-bindgen --bin wasm-bindgen-test-runner + - name: Install wasm32 target + run: rustup target add wasm32-unknown-unknown + - name: Run wasm-bindgen tests env: CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER: ${{ github.workspace }}/wasm-bindgen/target/debug/wasm-bindgen-test-runner