ImplementsNull-prototype cache so a hostile page that pollutes Object.prototype
cannot supply a callable from there if capture ever misses a handler.
Uses the { __proto__: null } literal rather than Object.create(null)
because the latter is a method dispatch through globalThis.Object, which
page JS could replace before this class field runs if transport
construction is deferred (Messaging is lazy on ContentFeature.messaging).
The __proto__: null literal is a syntactic construct, not method
dispatch, so it always yields a true null-prototype object.
Capture the postMessage method on each webkit messageHandler so the
transport can call them later without re-reading window.webkit.messageHandlers.
Makes the transport resilient to later removal or replacement of
window.webkit.messageHandlers (e.g. by privacy hardening that nullifies
the namespace for site JS to reduce fingerprinting surface).
Stores the handler object and its postMessage function as a pair so
wkSend can dispatch via the captured ReflectApply rather than calling
.bind() here. .bind is a method on the page-mutable
Function.prototype — if transport construction is deferred (Messaging
is lazy on ContentFeature.messaging) page JS could replace
Function.prototype.bind first and have the cache store an attacker-
controlled function. Storing the unbound pair sidesteps that.
Example
Calls through to
window.webkit.messageHandlers.x.postMessage.For a
foomessage defined in Swift that accepted the payload{"bar": "baz"}, the following would occur: