From 8e13010fe0547827f2e99c5c55a77aa63f5fe22d Mon Sep 17 00:00:00 2001 From: Vitalii Parovishnyk <870237+ikorich@users.noreply.github.com> Date: Thu, 11 Jun 2026 23:54:23 +0300 Subject: [PATCH] #24 fix(example): bind this when calling Response.json() The #8 rewrite extracted `responseObject.json.function` and invoked it unbound, so `this` was undefined and every fetch tick failed in real browsers with "Illegal invocation". Call it bound via `jsonFn(this:)`. Verified end-to-end in Chrome and in iOS Simulator Safari via the PackageToJS `--use-cdn` browser bundle; README gains a "Running the example" guide (bundle, index.html loader, static serve, simulator Safari) so the run path is documented. Fixes #24 --- CHANGELOG.md | 14 +++++++++ README.md | 41 ++++++++++++++++++++++++- Sources/OpenCombineJSExample/main.swift | 4 ++- 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57157d2..f2e220e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +# 0.6.1 (2026-06-11) + +**Fixed:** + +- Example: `Response.json()` was invoked without its `this` binding, failing every fetch + tick in a real browser with "Illegal invocation"; it is now called bound via + `jsonFn(this:)` ([#24](https://github.com/IGRSoft/OpenCombineJS/issues/24)) + +**Documentation:** + +- README gains a "Running the example" guide: PackageToJS `--use-cdn` bundling, the + `index.html` loader, static serving, and opening the example in a host browser or the + iOS Simulator's Safari ([#24](https://github.com/IGRSoft/OpenCombineJS/issues/24)) + # 0.6.0 (2026-06-11) **Build/packaging change — no public API is removed or deprecated:** diff --git a/README.md b/README.md index 7d17b1a..d59bc7c 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,8 @@ let timer = JSTimer(millisecondsDelay: 1000, isRepeating: true) { guard let obj = responseValue.object, let jsonFn = obj.json.function, - let jsonObj = jsonFn().object, + // `Response.json` must be called with the response as `this`. + let jsonObj = jsonFn(this: obj).object, let jsonPromise = JSPromise(jsonObj) else { return JSPromise(resolver: { resolve in @@ -95,6 +96,44 @@ let timer = JSTimer(millisecondsDelay: 1000, isRepeating: true) { } ``` +## Running the example + +The example is a WebAssembly program: it needs a browser. It cannot run as a native +process on macOS or an iOS simulator — JavaScriptKit's native builds exist only for +editor/type-checking support (the JS bridge is compiled `#if __wasm32__`), so a native +launch aborts immediately. + +1. Bundle for the browser (requires the official wasm Swift SDK matching your toolchain, + e.g. `swift-6.3.2-RELEASE_wasm`): + + ```console + swift package --disable-sandbox --swift-sdk swift-6.3.2-RELEASE_wasm \ + js --use-cdn --product OpenCombineJSExample + ``` + +2. Put an `index.html` next to the produced bundle + (`.build/plugins/PackageToJS/outputs/Package/`): + + ```html + + ``` + +3. Serve the bundle directory and open it — any browser works, including Safari inside + a booted iOS simulator: + + ```console + python3 -m http.server 8741 --directory .build/plugins/PackageToJS/outputs/Package + open http://127.0.0.1:8741/index.html # host browser + xcrun simctl openurl booted http://127.0.0.1:8741/index.html # iOS Simulator Safari + ``` + +`--use-cdn` resolves the WASI shim dependency from a CDN; without it, browsers cannot +resolve the bundle's bare `@bjorn3/browser_wasi_shim` import unless you `npm install` +in the output directory and serve through a bundler. + ### Code of Conduct This project adheres to the [Contributor Covenant Code of diff --git a/Sources/OpenCombineJSExample/main.swift b/Sources/OpenCombineJSExample/main.swift index 7c0a75f..8b5fcf6 100644 --- a/Sources/OpenCombineJSExample/main.swift +++ b/Sources/OpenCombineJSExample/main.swift @@ -84,7 +84,9 @@ let timer = JSTimer(millisecondsDelay: 1000, isRepeating: true) { guard let responseObject = responseValue.object, let jsonFn = responseObject.json.function, - let jsonPromiseObject = jsonFn().object, + // `Response.json` must be called WITH the response as `this` — an unbound + // call throws "Illegal invocation" in browsers (#24). + let jsonPromiseObject = jsonFn(this: responseObject).object, let jsonPromise = JSPromise(jsonPromiseObject) else { // Return a publisher that immediately fails if the response is malformed.