[whatwg] Passing more than JSON data to workers

On 17 Dec 2009, at 19:26, Drew Wilson wrote:

> That was my point earlier - for this to work, if you post getX and setX over separately, they need to share a closure otherwise they don't work. 
> 
> Realistically, given Javascript's dynamic nature, you need to copy everything reachable via the function's scope chain, and recursively copy everything reachable via any reachable function's scope chain. In effect, copying a function to worker context means bringing over the entire reachable heap. Anything else you try to do is going to break in subtle ways when something in the source context's scope chain isn't in the destination context's scope chain.

Ah, there is my error. I thought closures were implemented by determining what the free variables of a function are, and then only keeping a reference to their value. For example:

(function() {
    var foo = 'banana';
    var bar = 'monkey';
    return function() {
        return [foo, eval('bar')];
    }
})()()

I thought it would return ['banana', undefined], but it returns ['banana', 'monkey']. The whole context object is preserved, not just what is "relevant at first sight" (which is why Boris was talking about analysis complexity).

> I understand that we might like to treat code running in a worker as if it were running in a same context as the parent page, so you could pass all the same things to it that you could pass to any Javascript function, but the situations are not identical - the only way something like this would be feasible would be by adding limitations (i.e. not copying over the scope chain of a function) that IMO fundamentally break Javascript semantics ; once you do that, you might as well just use the existing string + eval() mechanisms.

Yes, indeed, that would be confusing to explain what does and what doesn't work. I do suspect certain patterns will emerge to pass over functions and some self-defined context, but then there is no need to do this in VM code.

> 
> -atw

Thank you all for your effort to explain to me why this is not possible. I had a feeling that when people from Firefox/MIT, Google and Apple (certainly when I saw the subject of Oliver's thesis) were telling me it was impossible, that there was something I was missing. Now I know. Thank you for this mind-altering experience!

Then my only other request remains: could the summary of this discussion be placed in the FAQ, so others won't think you were short-sighted for not including it?

Greetings,

Jan Fabry


> 
> On Thu, Dec 17, 2009 at 2:06 AM, Oliver Hunt <oliver at apple.com> wrote:
> On Dec 17, 2009, at 10:03 PM, Boris Zbarsky wrote:
> 
> > On 12/17/09 12:48 AM, Boris Zbarsky wrote:
> >> It seems very difficult to me to come up with a "function cloning"
> >> solution that won't break in subtle ways when such functions are passed
> >> to it...
> >
> > I should clarify this.  It seems to me eminently possible to clone functions that only reference local (declared with var) variables and their arguments.  And maybe explicit |this| access; not sure.
> >
> > As soon as you're talking anything else, the situation gets very complicated, it seems to me.  That includes implicit property access on the global object.
> >
> > To make that clearer, consider these two functions, defined at global scope:
> >
> >  var x = 1;
> >  function f() {
> >    return x;
> >  }
> >  function g() {
> >    return Math;
> >  }
> >
> > If I understand your proposal correctly, passing f to a worker would pass across a function which always returns 1.  Passing g to a worker would do what?  Pass across a function that always returns the Math object from the web page scope?  If not, then how is Math different from x, exactly?  If yes, then why are we baking anything at all in at pass time?
> >
> > How is the f() example above affected if x is bound to an object, not to a number?
> 
> I think a more interesting case is the relatively common idiom of closures for access protection, eg.
> 
> function MyObject() {
>    var x;
>    this.setX = function(_x) { x = _x };
>    this.getX = function() { return x }
> }
> 
> What should worker.postMessage(new MyObject) do if we were to try and serialise the functions? obviously you don't want them each to have (effectively) separate closures, and you can't just substitute their containing scope with the global object.
> 
> > -Boris
> 
> 
> --Oliver
> 
> 

Received on Thursday, 17 December 2009 11:47:22 UTC