Making "super" work outside a literal?

Sean Eagan seaneagan1 at gmail.com
Wed Jun 22 06:48:18 PDT 2011


There is no infinite recursion hazard in the semantics that Axel
suggested, and that I used in the gist I posted
(https://gist.github.com/1036200), where |super| is essentially the
"the [[Prototype]] internal property of the object on which the method
or accessor getter or setter was found" except that the |this| used in
method calls and accessor getters and setters accessed from |super|,
e.g. super.method() or super.accessorWithGetterOrSetterThatUseSuper,
is the |this| of the caller, rather than the |super| of the caller.

I don't think we need any "safety check" when assigning a method or
accessor getter or setter that uses super to an object.  The concept
of "super" seems to be a relative one, it is the object one step up in
the prototype chain from the current object.  If a method or accessor
getter or setter needs an *absolute* reference to the prototype of a
given object, it should refer to it by name.

Also, AFAICT there is no performance cost of a dynamic super beyond
the performance cost of static super.  If there would be any
difference between the two, it would be in the work that needs to be
done to determine what the |super| binding of a particular call site
should be.  In either the dynamic or static case, the engine will
climb the prototype chain when looking for a method or accessor
property.  When it finds one that matches, in the dynamic case the
|super| binding will just be the [[Prototype]] internal property of
the current prototype chain object, in the static case it will be the
[[???]] internal property of the method or accessor getter or setter
found.  Thus, in both cases it will just be a matter of accessing an
internal property of an object that is immediately accessible when
climbing the prototype chain.

On Tue, Jun 21, 2011 at 3:55 PM, Brendan Eich <brendan at mozilla.com> wrote:
> On Jun 21, 2011, at 11:53 AM, Brendan Eich wrote:
>
> On Jun 21, 2011, at 11:33 AM, Oliver Hunt wrote:
>
> I'm answering some of the performance questions in this, but i don't know
> what the intended semantics of 'dynamic super' would be so I can't give
> specific details of most of the use cases.  If it's essentially sugar for
> super.foo => Object.getPrototypeOf(this).foo (with appropriate munging for
> calls, etc) then the cost is at point of use only, but if it's anything more
> fun (there are references to additional implicit parameters below which
> would be fairly bad for performance of calls)
>
> That's the point: super must mean something other than
> Object.getPrototypeOf(this). Otherwise with the prototypal pattern you will
> infinitely recurse calling the same prototype-homed foo from foo via
> super.foo().
>
> Example:
> C.prototype = {
>   foo() { addedValue(); return super.foo(); }
>   ...
> };
> x = new C;
> x.foo();   // oops, diverges in endless self-recursion.
>
> Now, with the static 'super' semantics plus Object.defineMethod(O, 'foo',
> C.prototype.foo), you can rebind 'super'.
> One thing I'm not sure about: whether Object.defineMethod should mutate
> C.prototype.foo's internal property, or make a new function object with a
> different 'super' binding.
> In any case, the static and internal-to-method semantics avoid the infinite
> recursion hazard, and they avoid the cost of an extra parameter beyond
> |this|.
> /be
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>

Cheers,
Sean Eagan


More information about the es-discuss mailing list