There's nothing that would prevent you from passing a stringified function as postmessage event data. Implementation is trivial, for any function declaration like
function doSomething(){
alert("hello world!");
}
You could encodeURI
its string interpretation:
console.log(encodeURI(doSomething.toString()));
//function%20doSomething()%20%7B%0A%20%20%20%20alert(%22hello%20world!%22);%0A%7D
It can then be executed as part of a closure - something not overly imaginative like
eval('('+decodeURI(strCallback)+')();');
There's a fiddle'd proof of concept without the cross-frame architecture - I'll see if I can put together a postMessage version, but it would be non-trivial to host w/jsfiddle
Update
As promised, a full mockup that works (links below). With correct event.origin
checks this would be sufficiently inpenetrable, but I know for the fact that our security team would never let eval
into production like this :)
Given the option I'd suggest the functionality be normalized across the two pages so that only a parametric message would need to be passed (i.e. pass arguments not functions); however there are definitely a few scenarios where this is a preferred approach.
Parent code:
document.domain = "fiddle.jshell.net";//sync the domains
window.addEventListener("message", receiveMessage, false);//set up the listener
function receiveMessage(e) {
try {
//attempt to deserialize function and execute as closure
eval('(' + decodeURI(e.data) + ')();');
} catch(e) {}
}
Iframe code:
document.domain = "fiddle.jshell.net";//sync the domains
window.addEventListener("message", receiveMessage, false);//set up the listener
function receiveMessage(e) {
//"reply" with a serialized function
e.source.postMessage(serializeFunction(doSomething), "http://fiddle.jshell.net");
}
function serializeFunction(f) {
return encodeURI(f.toString());
}
function doSomething() {
alert("hello world!");
}
Prototype mockup: parent code and iframe code.