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
}
Notes from the discussion with @dherman:
- Rename
contour
toscope
: @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
andSystem.global
sounds good for him.new Realm()
produces a new power object (the realm object), this object also include a scope.global
andeval
methods belong to thescope
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?
- Introducing a new api to create a new global contours via
realm.createNewContour()
instead ofrealm.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
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)
Realm
inherit from a new intrinsic calledContour
- Part of the existing realm API will need to be moved into
Contour
Contour.prototype.createContour()
is a new method
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
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
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
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?