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 <oli...@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 > >