How to execute a function through postMessage
javascript, jquery, postmessage
Solution
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.
Problem
I have this code inside a iframe: ``` window.addEventListener('message', function(e){ if(e.data == 'test') console.log(e); }, false); ``` and this inside the parent document: ``` $('#the_iframe').get(0).contentWindow.postMessage('test', 'http://localhost/'); ``` So the parent document sends a "test" message to the iframe and it works. But how can I define a function in the parent document, and somehow send this function through postMessage to the iframe, which will execute the function locally? The function does some changes to the document like this: ``` var func = function(){ $("#some_div").addClass('sss'); } ``` (`#some_div` exists in the iframe, not the parent document)