Spawn proposal strawman

Mark S. Miller erights at google.com
Wed May 6 12:59:37 PDT 2009


On Wed, May 6, 2009 at 10:53 AM, Mark S. Miller <erights at google.com> wrote:
> [...] For the Valija-like level, I
> think the most important enabler would be some kind of hermetic eval
> or spawn primitive for making a new global context (global object and
> set of primordials) whose connection to the world outside itself is
> under control of its spawner. With such a primitive, we would no
> longer need to emulate inheritance and mutable globals per sandbox.

May as well get us started with a strawman, intended only to provide
the global object separations, not any scheduling separations. Whether
these two issues should in fact be coupled or decoupled is an
interesting question.

    eval.hermetic(program :(string | AST), thisValue, optBindings) :any
    eval.spawn(optBindings, optGlobalSubsetDirective :Opt(string)) :Sandbox

    interface Sandbox {
      public getGlobal() :GlobalObject;
      public deactivate(problem :string) :void;
    }

eval.hermetic() does an indirect eval of the program in the current
global context, but, as in
<http://wiki.ecmascript.org/doku.php?id=strawman:lexical_scope>,
without the global object at the bottom of the scope chain.
* Unlike <http://wiki.ecmascript.org/doku.php?id=strawman:lexical_scope>,
the 'this' value in scope at the top of the evaluated program is the
provided thisValue; so a caller without access to their own global
object cannot grant access they don't have. If the 'thisValue' is
absent, then the global 'this' of the evaled program is undefined.
* If optBindings is absent or falsy, then the bottom of the scope
chain is populated with the ES spec defined global bindings, i.e.,
{Object: Object, Array: Array, etc...}. If optBindings is provided and
truthy, then its *own* properties (or perhaps its enumerable
properties, or its enumerable own properties?) are uses to populate
the bottom of the scope chain.  In either case, the object at the
bottom of a hermetic scope chain is a declarative environment record,
not an object environment record.

eval.spawn() makes a new global context -- a global object and a set
of primordials. This new global context is subsidiary to the present
one for (at least) deactivation and language subsetting purposes, so
spawning forms a tree.
* If optBindings are provided, its own properties are copied over to
populate the newly created global object.
* If optGlobalSubsetDirective is provided, then all code evaluated in
this global context is constrained as if by an outer lexical use
subset directive. Subset constraints compose across subsidiary spawns
-- as if the optGlobalSubsetDirective of outer sandboxes were yet more
outer lexical use subset directives.
* It returns a Sandbox object for interacting with that new global
context: obtaining its global object or deactivating all objects
created within this global context or any subsidiary global contexts.
If there are any live stack frames executing within a context that
would be deactivated at the time sandbox.deactivate() is called, then
deactivate throws and has no other effect.

One then runs code hermetically within a sandbox by

    sandbox.getGlobal().eval.hermetic(...)

Given good catchalls and weak-key-tables, good membranes should be
possible. Indeed, this should be a litmus test of catchall proposals.
Given good membranes, one can easily gain other desired security
properties by interposing membranes around some of the above objects.

-- 
    Cheers,
    --MarkM


More information about the es-discuss mailing list