Safe, Closure-free, Serializable functions

François REMY at
Fri Sep 27 13:03:32 PDT 2013

> We've found the need for serializable functions in AmbientTalk, which,  
> like JS, encourages a style of programming that makes significant use  
> of lexical nesting. We have found that this programming style makes  
> that requiring serializable functions to be closed is indeed too  
> restrictive.
> Translated to JS, our solution looks like: 
> var z = 42; 
> var f = function(x,y) (z) { 
> // x and y are locals, z refers to (a copy of) the upvar 
> } 
> Here, f is a pass-by-copy function. The second parameter list captures  
> the upvars that should be serialized together with the function.

That seems a syntax sugar for something along those lines:

|    var z = 42;
|    var f = function(x,y):safe(z){
|        ...
|    };


|    var z = 42;
|    var f = function(x,y):safe{
|        const z = 42;
|        ...
|    }

where 42 is actually replaced by the value of 'z' at the time of construction. Did I understand correctly?

I think the idea is good, but in practice this could be emulated by using eval("function(x,y):safe { var z = " + uneval(z) + " ... }")

Any other kind of non-serialization transfer (like transferring an object to another thread) can be done using standards arguments of the safe function (and, if necessary, a library on top of it), it doesn't have to be dealt with at the safe-function level.

Any kind of special serialization can be handled on the platform separately. We could even define an object with an @unserialize serializable function, which would finally enable to serialize properly cyclic graphs of objects:

|    function serializeAsFunction(o){
    |        var source = [o]; var destin = ['o']; var instructions = [];
    |        var jso=Object.mapPropertiesRecursively(o, function(object, property, path){
|            var v = property.value; if(!v) return;
        |            if (typeof v =='object') {
            |                var index = source.indexOf(v);
            |                if(index !== -1) { 
|                    instructions.push("o"+path+"=o"destin[index]);
|                    return null;
|                } else {
|                    source.push(v);
|                    destin.push(path);
|                }
        |            }
|            return v;
    |        });
    |        return function():safe(o,instructions) { 
|            ... execute all instructions in order ...
|            return o;
|        };
|    };

I could obviously already achieve something like that using simple functions, but safe functions are much better because the person executing the code can be sure that, whatever the function does, it is not having a single pointer to the current environment and therefore cannot do more harm that just eating the CPU (and the calling code could setup some kind of "abort in X seconds" system if needed).

This also opens the way to more compressed data messages, since you could for instance define functions for serializing purposes:

|    function():safe {
|        var row = function StockActionUpdate(name,oldPrice,newPrice){
|            return { name: name, oldPrice: oldPrice, newPrice: newPrice, variation: (newPrice-oldPrice)/oldPrice, isUp:(newPrice>oldPrice), isDown:(oldPrice>newPrice), toSpeakAloudString: function():safe{ return' ('+this.newPrice+')'+(this.isDown?' is down':' is up')+' since yesterday ('+this.oldPrice+')'} }
|        };
|        return {
|            'MSFT':row('Microsoft Corporation', 30, 31),
|            'GOOG':row('Google Inc', 490, 491),
|            'AAPL':row('Apple Inc', 480, 481),
|            ...
|        };
|    }

This is more compact than a traditional JSON channel, and safer than a traditional "eval" code channel. I didn't say "totally safe" because the browser can have a security bug, which even a "safe" function could use, but this is very unlikely in pure JS functions, and you cannot protect reliably your application from browser bugs anyway.

The beauty of all this, is that all code coming out of the safe function as a return value cannot possibly be unsafe, because it cannot possibly have got any reference to the outside world (at least not any you didn't give them). 		 	   		  

More information about the es-discuss mailing list