- From: Boris Zbarsky <bzbarsky@MIT.EDU>
- Date: Tue, 01 Jul 2014 23:10:24 -0400
- To: public-script-coord@w3.org
On 7/1/14, 6:16 PM, Domenic Denicola wrote: > So if I understand correctly, you are saying that there are two different functions being run when I do (new DOMQuad()).bounds.x and when I do (new DOMRect()).x, but to JavaScript, since DOMQuadBounds has a different implementation than DOMRect. But it looks like they are the same function to JavaScript? > > How is this possible? There are several things going on here. First of all, the prototopy chains for (new DOMQuad()).bounds) and (new DOMRect()) look like this: (new DOMQuad()).bounds) -> DOMRectReadOnly.prototype (new DOMRect()) -> DOMRect.prototype -> DOMRectReadonly.prototype In this case, there is a getter for the property named "x" on _both_ DOMRect.prototype and DOMRectReadonly.prototype. So when you do (new DOMQuad()).bounds).x and (new DOMRect()).x you are not in fact calling the same JS function. But that's an accident, more or less. We could add a new property, call it "area" on DOMRectReadOnly.prototype that is not shadowed by DOMRect. Getting .area on either of those objects would then call this same JS function. What this JS function does in Gecko is extract the underlying C++ object (a DOMRectReadOnly in this case) and call a method on it. It so happens that in Gecko the DOMRectReadOnly C++ object only has pure virtual functions. That is, it delegates all calls on it to subclasses. Internally, (new DOMQuad()).bounds) and (new DOMRect()) instantiate different subclasses of DOMRectReadOnly, that have functions named "X" that have different implementations. So effectively, these two objects have an internal slot (the C++ vtable in this case, but you could do the same sort of thing in JS via symbols, say, or in C++ via a boolean member or some other polymorphism mechanism) that indicates what the getter should do when invoked with that sort of object as a this object. Back to my "area" example, if we were to implement that, we would of course implement it directly on DOMRectReadOnly, not on subclasses, since all it needs is the already existing exposed API to compute its result.. So an "area" getter would not in fact be polymorphic. I can't speak to the desirability of this behavior. Polymorphic behavior via introspection of the this value is not super-common in JS (not least because introspection is complicated) but is not unknown. In fact, a number of ES6 algorithms support just that sort of polymorphism by delegating various tasks this.something, which allows subclasses to override the default superclass implementation in certain well-defined ways. -Boris
Received on Wednesday, 2 July 2014 03:10:54 UTC