feat(data-rpc): schema-driven bidirectional service projection across iframe/MessagePort - #197
Merged
Conversation
… iframe/MessagePort New @adobe/data-rpc package projects AsyncDataServices across a boundary in both directions over one channel; only Data crosses the wire, far side synthesizes equivalent-shaped members (incl. nested sub-services). Extracts shared memberKind from create-lazy. Adds data-rpc-iframe Lit sample. Bumps to 0.10.10. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… a reverse channel An Observe passed as/inside a call argument streams caller→callee: the caller sends a ref and streams values back on demand (arg-subscribe/arg-next/ arg-unsubscribe); the callee reconstructs a local Observe. Only Data crosses. Providers released on op-teardown and endpoint close. Relaxes the expose gate to schema-describes-service (like createLazy), since IsValid rejects Observe args. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…enerator Extends the argument reverse channel beyond Observe: a Promise or AsyncGenerator passed as/inside a call argument is serviced from the caller. Unified arg-marshal walker dispatches per constructor kind; promise=arg-resolve/arg-reject, generator=arg-pull/arg-yield/arg-done/arg-throw/arg-return/arg-raise (pull-based). Only Data crosses; providers released on op-teardown and endpoint close. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…pe-path guard, safer transports - B1: suppress unhandled rejection when a member ignores a rejecting promise arg - S1: cancel a promise/generator arg on release so the callee can't hang after the call completes - S2: own-property guards in host path resolution (reject constructor/__proto__ paths) - S4: void members reject constructor-typed arguments (no completion signal to release them) - N1: createWindowTransport requires an explicit targetOrigin when origins are ambiguous (never "*") - N2: arg refs travel as a tagged envelope so a literal value can't be mistaken for a ref - N3: remove dead `deadline` field Adds red-then-green pin tests for each (48 tests total). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
New
@adobe/data-rpcpackage: schema-driven, bidirectional projection of@adobe/dataasync data services across a boundary (iframe / MessagePort /Worker). One
createRpcEndpoint(transport)per side; each canexposeits ownservices and
consumethe peer's over a single channel.Core invariant: only
Dataever crosses the wire. We never serialize anObserve/Promise/AsyncGenerator/function — the consuming side synthesizes anequivalent-shaped service locally whose members translate to/from
Data-onlymessages. Gating
exposeonAsyncDataService.IsValidWithCompleteSchemaguarantees there is nothing but
Datato marshal.Highlights:
Observe,fn:observe,fn:promise,fn:generator(strictly pull-based),
fn:void.path from the service root.
Observe,Promise, orAsyncGeneratorpassed as/inside a call argument is serviced from the caller —the caller sends a ref and the value is streamed/settled/pulled back over a
reverse channel; only
Datacrosses.createMessagePortTransport(primary),createWindowTransport(port handoff + origin allowlist),
createRpcLoopbackTransport(tests).{name,message,stack}; separate per-originator id tables;graceful close teardown (pending calls reject, subscriptions/generators end).
canInvokeseam + incoming arg validation againstsignature.parameters.Also:
memberKindclassifier out ofcreate-lazy.tsintoasync-data-service/member-kind.ts(re-exported viaAsyncDataService);createLazybehavior unchanged.data-rpc-iframe— a Lit sample (main frame + real iframe over aMessagePort) demonstrating all four kinds in both directions plus a nested
sub-service.
Test evidence
@adobe/data-rpc(every member kind both directions; hardpaths: close-mid-call, unsubscribe-in-flight, generator early return/dispose,
bidirectional id independence, consume-before-expose, arg-validation rejection,
teardown-on-close; nested services and Observe/Promise/AsyncGenerator arguments
over loopback and a real
MessageChannel).@adobe/dataservice suite (122 tests) still green after thememberKindextract.nested
sub.calc.*sub-service confirmed working across the iframe, console clean.pnpm run lint+pnpm run typecheckpass (caches cleared).Related PRs
Builds on #196 (pure-JSON Schema + observable
Service.schemaslot).Jira ticket
N/A — no ticket (public repo, library feature).