Re: Associating new objects with globals: how to best do it?

On Feb 25, 2014, at 9:45 AM, Boris Zbarsky wrote:

> Bobby and I were just discussing how newly created objects are (or rather should be) associated with globals.

I believe by "globals" you mean what the ES6 spec. calls a Realm.  A Realm is more than just a global object.  It is all of the the state, including built-in objects that don't have global name bindings, that from a complete self-contained ES execution environment. The concept of Realms or even multiple global objects was never addressed in ECMAScript specifications prior to ES6. 

> 
> Here's the situation as I currently understand it:
> 
> 1)  Every newly object is, generally speaking, associated with a global by default via its proto chain.  I realize script can munge those proto chains (e.g. by making Node.prototype.__proto__ in one window be EventTarget.prototype from another window); I'm talking about the default behavior.

Strictly speaking, ordinary non-function objects aren't associated with a specific Realms. The ES spec. does not require any sort of explicit pointer or tag on such objects that associate them with a specific Realm.  However, most built-in objects are created in support of some Realm and there is a explicit association from the Realm to those objects.  For example, each Realm has its own Object.prototype object and a Object constructor function that was created specifically for that Realm. When an Object constructor creates a new object it always sets the [[Prototyope]] of the new object to the Object.prototype object from the same Realm as the constructor.

In the ES specification, only function objects have a direct association (a pointer or tag) from the object to a specific Realm.

The fact that some object, X., has an object  P (say Object.prototype) on this prototype chain and P is (directly or implicitly) associated with Ream R1 does not mean that X is associated with R1.  The prototype chain of X might contain several objects, each associated with a different Realm and none of them effects the Realm association (if any) of X.

> 
> 2)  Every function is associated with some global; in ES6 this is formalized by the [[Realm]] internal slot of functions, from which a global is reachable.
Yes, but as mentioned above, a Realm association implies more than just a specific global object.

> 
> 3)  Currently WebIDL requires all objects to explicitly say what global they're associated with.  This requirement is observed by pretty much no one.

ok...

> 
> 4)  In ES6, there is some informal concept of an "ambient global".  For example, when a built-in function is called that ambient global is the global of the [[Realm]] of that built-in function.  Operations that create new objects associate them with the default prototypes of that ambient global.  If this is correct, it might be good to formalize this somehow...

Well, it's not informal and it really isn't ambient.  All function objects (both built-in or dynamically created; ECMAScript or "native") are associated with a specific Realm at the time of their creation. When a function is called, its Realm association becomes the "current Realm" that is recorded part of the activation environment for the function.   Everything that happens within an ECMAscript program happens in the context of executing some function (or a global script that is treated as if it was a function body) and if a Realm needs to be referenced the Realm association of the currently active function environment is used.

Much of the ECMAScript specification is expressed ising "Abstract Operations" that are performed in the course of evaluating ECMAScript code.  Abstract operations aren't functions, aren't called as functions and don't have function environments.  There may appear to be an ambient Realm that is used by such abstraction operations, but really they are just being performed as part of whatever function code directly or indirectly referenced the abstract operation and if the current Realm needs to be referenced it is just the "current Realm" recorded as part of the active function environment,

> 
> Is my understanding correct so far?

Approximately, subject to the above clarifications. 
> 
> We've talked about some sort of default global-association for WebIDL methods and geteters.  Would it make sense to align this with the ES6 behavior by declaring that if a WebIDL method creates objects it does so in the global of the callee function unless something explicitly specifies otherwise?

ES6 requires that every function, including get/set functions have a Realm association. 

Just to be clear, when you say "callee" above you mean the WebIDL method under discussion.  If so, then what you are describing is consistent with the ES6 requirements.  A function that creates a new object normally initializes the new object (eg, sets its [[Prototype]]) using the Realm of the creating function.

> 
> So in this case:
> 
>  window1.SomeInterface.prototype.someMethod.call(objectFromWindow2)
> 
> the return value object would be created in window1, not window2, by default?  Same thing for getters, of course.
yes, assuming that someMethod was originally created in the same Realm as window1.  The actual access path has nothing to do it.  EG:

window2.foo=window1.SomeInterface.prototype.someMethod;
window2.foo.call(objectFromWindow2)

would still create objects associated with window1.

> 
> Obviously, some DOM specs would need to go through and explicitly specify globals for some objects (e.g. nodes), but the vast majority of specs should be able to get away with just not having to say anything.
> 
> This has the benefit of not needing any extra work for static WebIDL methods and getters, which generally ignore their this value entirely at the moment...
> 
> Thoughts?  Did I understand the ES6 behavior we're trying to align with correctly?

I think so.

Allen

Received on Tuesday, 25 February 2014 18:49:32 UTC