Skip to content

Instantly share code, notes, and snippets.

@caridy
Last active February 14, 2017 03:59
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save caridy/311ad2c17a0cd875ae17ac11ffb597a9 to your computer and use it in GitHub Desktop.
Save caridy/311ad2c17a0cd875ae17ac11ffb597a9 to your computer and use it in GitHub Desktop.

Updated (Aug 2nd, 2016)

API Refinements:

  • The default global scope when creating a new realm has no extra capabilities, it is confusing, we can remove it.
  • The realm object is the real power object, and users can decide to share it or not via endowments.
  • In a realm, you can create as many global scopes as you want via realmObj.createNewGlobalScope().
  • No more proxy-like API at the realm level, if you want to proxy a global, that should be used when creating a new global scope.

The API proposal:

class Realm {
  constructor() -> void

  // intended to be overridden by subclasses
  @@indirectEval(...any) -> stringable,           // default: no translation
  @@directEval(...any) -> stringable,             // default: no translation
  init( globalScope: GlobalScope  ) -> void,      // default: initialization of a global scope in this realm

  // accessor methods
  get stdlib() -> PropertyDescriptorMap,          // property descriptor map for standard globals
  get intrinsics() -> { string: any, ... },       // original values of standard %foo% intrinsics

  // public methods
  createNewGlobalScope: (target: object?, handler: object?) -> GlobalScope Instance
}

class GlobalScope {
  constructor: () -> throw,                       // you can only create this via `realmObj.createNewGlobalScope()`

  // inherited accessor properties
  get global() -> object,                         // access this scope's global object

  // public methods
  eval(stringable) -> any                         // do an indirect eval in this scope
  Function(stringable) -> any                     // a function constructor
}

Updated (July 26th, 2016)

Notes from the discussion with @dherman:

  • Rename contour to scope: @dherman's argument is that the scope is a more broader term that includes a contour and a global.
  • A realm is a power object that contains a scope, but it is not an instance of scope itself.
  • System.scope and System.global sounds good for him.
  • new Realm() produces a new power object (the realm object), this object also include a scope.
  • global and eval methods belong to the scope object, not need to have them as members of the realm object.
  • In a separete proposal, we might want to consider adding more operations to the scope to control its contour (e.g.: delete a let from it)

The API proposal:

class Realm {
  // intended to be overridden by subclasses
  @@indirectEval(...any) -> stringable,           // default: no translation
  @@directEval(...any) -> stringable,             // default: no translation
  init() -> void,                                 // default: initialization of the global of any new scope in this realm

  // accessor methods
  get stdlib() -> PropertyDescriptorMap,          // property descriptor map for standard globals
  get intrinsics() -> { string: any, ... },       // original values of standard %foo% intrinsics

  // inherited accessor properties
  get scope() -> object,                          // access this realm's scope object
}

class Scope {
  constructor: () -> throw,                       // you can only create this via `createNewScope()`
  createNewScope() -> object,                     // new scope object bound to this' scope realm

  // inherited accessor properties
  get global() -> object,                         // access this scope's global object

  // public methods
  eval(stringable) -> any                         // do an indirect eval in this scope
}

Open questions:

  • Can Realm's constructor still support a proxy-like API?
  • Should Realm's init be invoke when creating new scopes?

Proposal

  • Introducing a new api to create a new global contours via realm.createNewContour() instead of realm.spawn().global.
  • A realm is a contour.
  • Current contour can be accessed via System.contour.
  • New global objects (equivalent to System.global) can be created of a contour.
  • New realms will always create its global object and new intrinsics as described in the new realm api.
  • Direct and indirect evaluation in a contour will go through the associated realm's hooks.
  • Stratification to match the realm API

Basic API

const r = new Realm();          // create a new contour (a brand new realm) with brand new intrinsics and stdlibs
r.global;                       // getter to the "default" global of the contour
r.eval('1 + 1');                // yield 2; indirect evaluation on the contour `r`
let c = r.createContour();      // create a new contour `c` from the realm `r`
c.global;                       // getter to the global of the contour created in the previous line
c.eval('1 + 1');                // yield 2; indirect evaluation on the contour `c`

Any sandbox can access its contour and global object via System:

System.contour;  // getter to the current contour
System.global;   // getter to the global of the current contour (System.global === System.contour.global)

Changes to the Realm API

  • Realm inherit from a new intrinsic called Contour
  • Part of the existing realm API will need to be moved into Contour
  • Contour.prototype.createContour() is a new method

Creating a new Global

const myContour = System.contour;                   // current contour object
const myGlobal = myContour.createContour().global;  // create a new contour that shares the same realm with the current contour
myGlobal.eval('this') === myGlobal;                 // it is just the global object
myGlobal.Array === Array;                           // intrinsics from the realm associated to the current contour

Evaluation in a new contour

function evalInSandbox(src, contour = System.contour) {
    const c = contour.createContour();
    return c.eval(src);
}

evalInSandbox('let foo = 1');  // create a new let binding on a new contour
evalInSandbox('foo');          // throw b/c `foo` is not defined

Identity Discontinuity

const realm = new Realm();
const realmGlobal = realm.global;
System.global === realmGlobal;             // yield false
System.global.Array === realmGlobal.Array; // yield false

const anotherRealm = new Realm();
const anotherGlobal = anotherRealm.global;
anotherGlobal === realmGlobal;             // yield false
anotherGlobal.Array === realmGlobal.Array; // yield false
@erights
Copy link

erights commented Jun 28, 2016

I notice that this gist seems to be tagged "SECRET" (yellow banner next to caridy/reflect-global.md). Curious, I looked at this url from a browser not signed into github and still saw this page. What does "SECRET" mean?

@littledan
Copy link

littledan commented Jul 1, 2016

Do you have an explainer doc with use cases for this API?

Edit: Found https://gist.github.com/dherman/9146568

@caridy
Copy link
Author

caridy commented Jul 27, 2016

@erights, secret gist means that this is not searchable, I will make it public to preserve the history of this.

I have discussed the API with @dherman, and he provided good inside, will update the gist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment