- From: Leo Balter <notifications@github.com>
- Date: Thu, 13 May 2021 15:28:14 -0700
- To: w3ctag/design-reviews <design-reviews@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <w3ctag/design-reviews/issues/542/840871150@github.com>
> 2. The mechanism for how values are passed back and forth seem unclear from our reading. There are mentions of transferrables, but presumable non-transferrable objects are copied in each direction? Only primitive values are fully transferable. Any try to transfer Non-callable objects will cause an abrupt completion (thrown exception). Callable Objects are internally wrapped into a new exoctic callable, called "Wrapped Function Exotic Object". That means, if the importValue or the result of `evaluate` returns a callable object (functions, proxied functions, arrow functions, etc), this callable object is wrapped into this new exotic. The same happens if a wrapped function returns any callable object. This means, if I have incubator Realm A, and child Realm B, and I inside A I run `B.evaluate('x => x * 2')`, this evaluation will create a new Wrapped Function Exotic Object in Realm A. When Realm A calls this new exotic object, it synchronously calls the evaluated arrow function from B, captures the return value, and return it in Realm A. ```js // Realm A const B = new Realm(); // Realm B creates an arrow function and returns it // fn is a Wrapped Exotic object that as an internal [[Wrapped]] containing the arrow function const fn = B.evaluate('x => x * 2'); // This call will internally call fn.[[Wrapped]](3). The result is a primitive, return it. fn(3); // 6 ``` There is no function unwrapping in user code, and this is a hard requirement to avoid leaking identities. This means each time I evaluate something that returns the same callable, I always receive a new Wrapped Function Exotic Object. ```js // Realm A const B = new Realm(); B.evaluate('globalThis.fn = x => x * 2'); B.evaluate('fn === fn'); // true const wrapped = B.evaluate('fn'); const wrappedAgain = B.evaluate('fn'); console.log(wrapped === wrappedAgain); // false wrapped(3); // 6 wrappedAgain(3); // 6, they are both callables from Realm A connected to the same function in Realm B ``` This also means we wrap functions the other way around, with no identification: ```js // Realm A const B = new Realm(); B.evaluate('globalThis.fn = x => x * 2'); const wrapped = B.evaluate('fn'); const compare = B.evaluate('callable => callable === fn'); compare(wrapped); // false const verify = B.evaluate('callable => callable(7)'); verify(wrapped); // 14 ``` In the example above, `compare` sends `wrapped` to Realm B, but `wrapped` is once again _wrapped_ as an internal of a new Wrapped Function Exotic Object inside Realm B. It's not unwrapped identifying `fn`. The `verify` sends `wrapped` to be executed in B and capture it's value. Realm B receives it with the name `callable` and call with the argument 7, returning it back to Realm A's `verify`. -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/w3ctag/design-reviews/issues/542#issuecomment-840871150
Received on Thursday, 13 May 2021 22:28:28 UTC