Architecture
Root Host (A) [localhost:4000]
├─ Exposes: TestService scripting object
├─ Loads guest "intermediateHost"
│ metadata: { vendor: "Acme Credit Corp", tier: "premium" }
│
└─ Intermediate (B) [localhost:4000, same-origin iframe]
├─ Connects as V2 guest to A
├─ Loads ice.guest from localhost:4001/index.js
├─ Gets TestService proxy, clones it
├─ Creates own SSFHost, loads guest "grandchildGuest"
│ metadata: { role: "validator", region: "US-East" }
│
└─ Grandchild (C) [localhost:4001, cross-origin iframe]
└─ Connects as V2 guest to B
└─ Gets TestService proxy → calls methodsTest Steps
- Wait for initialization — check the Invocation Log shows:
"Root Host (A) ready", Intermediate shows"Intermediate (B) ready", Grandchild shows"Got TestService proxy". - Click any button inside the Grandchild (C) panel (e.g. "Call getCallerInfo()").
- Verify on the left — the "callContext.guest" and "callContext.callChain" panels update with the expected values shown below.
- Verify on grandchild — the return value appears in the grandchild's result area (proves round-trip works).
Expected Values (when grandchild C calls any method)
callContext.guest (direct caller = B)
{
"id": "intermediateHost",
"title": "Intermediate Guest+Host (B)",
"url": "...callchain-intermediate.html"
}callContext.callChain (originator chain)
[
{
"id": "grandchildGuest",
"metadata": { "role": "validator", "region": "US-East" }
},
{
"id": "intermediateHost",
"metadata": { "vendor": "Acme Credit Corp", "tier": "premium" }
}
]Actual Results (from Root Host A)
callContext.guest (direct caller)
Waiting — click a button in Grandchild (C)...
callContext.callChain (original callers)
Waiting — click a button in Grandchild (C)...
Method return value (returned to grandchild)
Waiting — click a button in Grandchild (C)...