Re: Safe, Closure-free, Serializable functions‏

David Herman dherman at mozilla.com
Thu Sep 26 15:13:57 PDT 2013


On Sep 26, 2013, at 1:10 PM, François REMY <francois.remy.dev at outlook.com> wrote:

>>> TLDR ==> The web needs a way to express executable code that does not rely on its parent context, is guaranteed to be side-effect-free, and can be executed safely anywhere (even in a different thread/worker/window/device, or as callback for browser code being executed while the DOM is not ready to be accessed)
>> Why "need"? You don't really expose a use case. You only start with
>> "It's been some time I've been working on this idea of a..."
>> 
>> Also, one thing is not really clear to me. Are you trying to protect the
>> function from its caller/loader or the caller from the function? both?
> 
> The use case is at the bottom: I want to be able to use JavaScript functions inside the browser as part of algorithm customization. For example, use some JavaScript function as part of the layout computation of an object, or as the animation timing function.

This is an area I've put some thought into. However, you've described a mechanism but not really made the case that environment-free closures is the only or best solution. In fact I think they are a bad idea, but I agree with the desideratum that a way to share functions across JS heaps would be highly desirable.

## Why shareable functions are desirable

Lots of reasons, such as:

- more convenient workers or worker-like API's (a la Erlang spawn)
- ability to provide JS customization for native API's that want to run JS code in parallel or in the background
- more JS customization (a la the extensible web [1]) for core browser technologies that doesn't compete with potential parallelization of those technologies
- ability to write parallel abstractions (along the lines of map) that can concisely but safely -- and ideally efficiently -- share data

## Why environment-free closures is a bad idea

First, I don't want introduce the ability to test whether a function is environment-free. This interfere with fundamental information hiding guarantees of closures. (And any API that depends on a closure being environment-free to protect its invariants requires the ability to perform that test.)

Second, I think it's very confusing to have code that is lexically nested but interpreted in a completely different scope:

    var x = 42;
    spawn(function!() { // imaginary function! syntax
        ... x ... // x is a global variable in some worker
    });

Third, I don't think it's sufficiently expressive. I'd be much more interested in seeing something along these lines:

- the ability to define custom serialization logic (as opposed to, or perhaps in extension to, the ad hoc structured clone algorithm)
- the ability to define serializable functions whose serialization logic lifts through their upvars

This is more expressive than environment-free closures because it allows shared functions to also share their closure data. But it also narrows the observation you can make on a closure from "does it have anything in its environment?" to "is its environment shareable?" This is the real question you want to be asking anyway, and it doesn't violate the abstraction closures provide.

Don't get me wrong, it's also a much harder problem. But I've been starting to get my head around it little by little. It'd require some published protocol for customizable serialization (a standardized @@serialize symbol, or maybe some kind of traits feature) and some static requirements on the shape of the code of a serializable closure. I imagine the serialized upvars would have to be const, and we'd probably need to require them to all be initialized at the time of serialization. (Or something. More research to do here.) To make serialization efficient, you'd want the ability to write directly into the other heap in a fast and space-efficient way, but the typed objects API is very promising here: user code can pick whatever representation format it wants and the code on the other side will be able to interact with the resulting data as an object.

There's also a question of whether you'd want a single "serialize" operation or two separate "clone" vs "move" operations (analogous to the transfer semantics for ArrayBuffers). Tony Arcieri blogged about some similar ideas last year. [2]

At any rate, this is an area I'm very interested in, and so are some others in my group at Mozilla Research.

Dave

[1] http://extensiblewebmanifesto.org/
[2] http://tonyarcieri.com/2012-the-year-rubyists-learned-to-stop-worrying-and-love-the-threads



More information about the es-discuss mailing list