Determining what prototype should be used for an object

Background: whenever an object of some sort is created, we have to 
select which standard prototype should be used for it.  The exact 
prototype depends on the kind of object and on which global environment 
we want to get the standard prototype from.  From now on in this mail 
when I refer to the global of an object, or an object being from some 
global, I mean this global that the object's initial prototype came from.

The question is: what global environment to use?

In ES, the answer typically seems to be "the global of the current 
Realm".  But in ES it's also not common for built-in functions to create 
objects and keep returning them, for what it's worth.

What should happen in IDL?  Anne put together some tests at 
https://github.com/w3c/web-platform-tests/pull/1381 that show that for 
the most part in browsers today IDL-defined methods that create objects 
will create the object using the global environment that the "this" 
value for the method is associated with.  This is the global environment 
it initially got its prototype from, except in some cases for nodes when 
adoptNode is involved.

There are some bizarre exceptions to this. For example, in Chrome doing 
global1.CanvasRenderingContext2D.prototype.createImageData.call(canvasRenderingContextFromGlobal2) 
will return an ImageData object which is instanceof global1.Object, but 
whose .data is instanceof global2.Object.  Similarly, Firefox has the 
same issue with getImageData (but not createImageData; I consider that a 
definite bug since getImageData/createImageData should at least match 
each other).  But mostly browsers are remarkably consistent here.

The choice of initial prototype mostly affects two things: instanceof 
checks and whether properties added to a given standard prototype show 
up on a given object.

Anyway, given all that, where do we want to go?  Do we want to just 
accept that ES and IDL will differ on this matter?  Do we want to align 
the two specs with each other, at least for methods that always return a 
new object?  For those, creating the new object in the current Realm's 
global is probably workable.  Note that I do think that having 
createImageData return an ImageData that's not from the same global as 
its .data to be buggy, but that can be addressed in two ways, obviously.

Note, also, that all of this mostly matters when people .call()/.apply() 
methods from one global on objects from another global, since otherwise 
the current Realm and the global of the this value match anyway.

Thoughts?

-Boris

Received on Friday, 14 November 2014 02:47:04 UTC