Making "super" work outside a literal?

classic Classic list List threaded Threaded
100 messages Options
12345
Reply | Threaded
Open this post in threaded view
|

Making "super" work outside a literal?

Axel Rauschmayer
It would be nice if "super" could work in any method and not just those methods that are defined inside an object literal. Then, a method would have to know what object it resides in, e.g. via an implicit parameter.

--
Dr. Axel Rauschmayer

[hidden email]
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

Peter Michaux
On Sun, Jun 19, 2011 at 10:20 AM, Axel Rauschmayer <[hidden email]> wrote:
> It would be nice if "super" could work in any method and not just those methods that are defined inside an object literal. Then, a method would have to know what object it resides in, e.g. via an implicit parameter.

So you want "super" to be dynamic but tied to the value of "this"
inside that function? Something like...

function fn() {
    return this.alpha + super.beta();
}

function Foo() {}
Foo.prototype.alpha = function() {return 1;};
Foo.prototype.beta = function() {return 2;};

function Bar() {}
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.beta = function() {return 5;};

var b = new Bar();
fn.call(b); // 1 + 2 = 3

Peter
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

Axel Rauschmayer
Exactly!

One way to do this is to give methods an implicit parameter "here" (the object in which a method was found during dispatch), in addition to "this".

Then
        super.foo(x, y)
would desugar to
        Object.getPrototypeOf(here).foo.call(this, x, y)

With call() and apply(), you would have here === this.

Axel

On Jun 19, 2011, at 19:44 , Peter Michaux wrote:

> On Sun, Jun 19, 2011 at 10:20 AM, Axel Rauschmayer <[hidden email]> wrote:
>> It would be nice if "super" could work in any method and not just those methods that are defined inside an object literal. Then, a method would have to know what object it resides in, e.g. via an implicit parameter.
>
> So you want "super" to be dynamic but tied to the value of "this"
> inside that function? Something like...
>
> function fn() {
>    return this.alpha + super.beta();
> }
>
> function Foo() {}
> Foo.prototype.alpha = function() {return 1;};
> Foo.prototype.beta = function() {return 2;};
>
> function Bar() {}
> Bar.prototype = Object.create(Foo.prototype);
> Bar.prototype.beta = function() {return 5;};
>
> var b = new Bar();
> fn.call(b); // 1 + 2 = 3
>
> Peter
>

--
Dr. Axel Rauschmayer

[hidden email]
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

Peter Michaux
On Sun, Jun 19, 2011 at 10:56 AM, Axel Rauschmayer <[hidden email]> wrote:
> Exactly!
>
> One way to do this is to give methods an implicit parameter "here" (the object in which a method was found during dispatch), in addition to "this".

In some variant, "here" might make it possible to do what I was
describing as "sideways" calls?

http://www.mail-archive.com/es-discuss@.../msg08069.html

> Then
>        super.foo(x, y)
> would desugar to
>        Object.getPrototypeOf(here).foo.call(this, x, y)
>
> With call() and apply(), you would have here === this.

When the prototype chain is three or more objects long, I'm wondering
what would happen.

With "here" I'd expect and think people would expect the following
behavior (but I don't think it is what your proposal of "here" would
do.)

function Alpha() {}
Alpha.prototype.one = function() {return 'Alpha.one';};
Alpha.prototype.two = function() {return 'Alpha.two';};
Alpha.prototype.three = function() {return super.one() + ' ' +
here.one() + ' ' + this.one();};

function Beta() {}
Beta.prototype = Object.create(Alpha.prototype);
Beta.prototype.one = function() {return 'Beta.one';};
Beta.prototype.two = function() {return super.one() + ' ' + here.one()
+ ' ' + this.one();};

function Gamma() {}
Gamma.prototype = Object.create(Beta.prototype);
Gamma.prototype.three = function() {return super.one() + ' ' +
here.one() + ' ' + this.one();};

var a = new Alpha();
var b = new Beta();
var g = new Gamma();

a.three(); // "Alpha.one Alpha.one Alpha.one"
b.two(); // "Alpha.one Beta.one Beta.one"
g.two(); // "Alpha.one Beta.one Gamma.one"
g.three(); // "Beta.one Gamma.one Gamma.one"

Peter


> On Jun 19, 2011, at 19:44 , Peter Michaux wrote:
>
>> On Sun, Jun 19, 2011 at 10:20 AM, Axel Rauschmayer <[hidden email]> wrote:
>>> It would be nice if "super" could work in any method and not just those methods that are defined inside an object literal. Then, a method would have to know what object it resides in, e.g. via an implicit parameter.
>>
>> So you want "super" to be dynamic but tied to the value of "this"
>> inside that function? Something like...
>>
>> function fn() {
>>    return this.alpha + super.beta();
>> }
>>
>> function Foo() {}
>> Foo.prototype.alpha = function() {return 1;};
>> Foo.prototype.beta = function() {return 2;};
>>
>> function Bar() {}
>> Bar.prototype = Object.create(Foo.prototype);
>> Bar.prototype.beta = function() {return 5;};
>>
>> var b = new Bar();
>> fn.call(b); // 1 + 2 = 3
>>
>> Peter
>>
>
> --
> Dr. Axel Rauschmayer
>
> [hidden email]
> twitter.com/rauschma
>
> home: rauschma.de
> blog: 2ality.com
>
>
>
>
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

Axel Rauschmayer
Note that "this" always points to where the search for a method starts (the “receiver” of the method call), there (current) beginning of the prototype chain. "here" points to where a method has been found. This is a static aspect, except that turning it into a property of a function would make it impossible to put the same function into multiple objects.

>> Then
>>        super.foo(x, y)
>> would desugar to
>>        Object.getPrototypeOf(here).foo.call(this, x, y)
>>
>> With call() and apply(), you would have here === this.
>
> When the prototype chain is three or more objects long, I'm wondering
> what would happen.
>
> With "here" I'd expect and think people would expect the following
> behavior (but I don't think it is what your proposal of "here" would
> do.)
>
> function Alpha() {}
> Alpha.prototype.one = function() {return 'Alpha.one';};
> Alpha.prototype.two = function() {return 'Alpha.two';};
> Alpha.prototype.three = function() {return super.one() + ' ' +
> here.one() + ' ' + this.one();};
>
> function Beta() {}
> Beta.prototype = Object.create(Alpha.prototype);
> Beta.prototype.one = function() {return 'Beta.one';};
> Beta.prototype.two = function() {return super.one() + ' ' + here.one()
> + ' ' + this.one();};
>
> function Gamma() {}
> Gamma.prototype = Object.create(Beta.prototype);
> Gamma.prototype.three = function() {return super.one() + ' ' +
> here.one() + ' ' + this.one();};
>
> var a = new Alpha();
> var b = new Beta();
> var g = new Gamma();

Wow, quite a puzzle. I hope I get it right:

> a.three(); // "Alpha.one Alpha.one Alpha.one"

super.one() would cause an exception, because method "three" is found in Alpha.prototype (=> becomes "here") whose prototype is Object.prototype, which does not have a method one().

> b.two(); // "Alpha.one Beta.one Beta.one"

Would work. The search for super.one() would start in Alpha.prototype, the search for here.one() would start in Beta.prototype, the search four this.one() would also start in Beta.prototype.

> g.two(); // "Alpha.one Beta.one Gamma.one"

Is OK, only "this" is different, "here" is still Beta.prototype.

> g.three(); // "Beta.one Gamma.one Gamma.one"


I dont’t see "Gamma.one" anywhere.

I would say: "Beta.one Beta.one Beta.one"

Maybe you can condense this into a simpler example that gets to the core of where you think things might be tricky.

--
Dr. Axel Rauschmayer

[hidden email]
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

Brendan Eich-3
In reply to this post by Axel Rauschmayer
On Jun 19, 2011, at 10:20 AM, Axel Rauschmayer wrote:

It would be nice if "super" could work in any method and not just those methods that are defined inside an object literal. Then, a method would have to know what object it resides in, e.g. via an implicit parameter.

We wish to avoid another parameter computed potentially differently for each call. It will cost, and it will lead to surprises.

Also, anything reachable from |this| can be computed using ES5's Object.* APIs.


 When a function contains a reference to super, that function internally captures an internal reference to the [[Prototype]] of the object created by the enclosing object initialiser. If such a function is subsequently extracted from the original object and installed as a property value in some other object, the internal reference to the original [[Prototype]] is not modified. Essentially, when a function references super it is statically referencing a specific object that is identified when the function is defined and not the [[Prototype]] of the object from which the function was most recently retrieved.

This behavior is consistent with that of most other languages that provide reflection function to extract methods containing super and then independently invoke them.


/be 



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

Axel Rauschmayer
Makes sense.

I don’t know how problematic this would be, but if "super" is an internal property of a function, then it could be updated whenever such a function is set as the value of a property.

I’m increasingly decomposing object literals into assignments to properties, especially if a literal is long (easier rearrangement of methods, because there is no need to avoid the trailing comma; context is clearer).

Axel

On Jun 19, 2011, at 21:14 , Brendan Eich wrote:

On Jun 19, 2011, at 10:20 AM, Axel Rauschmayer wrote:

It would be nice if "super" could work in any method and not just those methods that are defined inside an object literal. Then, a method would have to know what object it resides in, e.g. via an implicit parameter.

We wish to avoid another parameter computed potentially differently for each call. It will cost, and it will lead to surprises.

Also, anything reachable from |this| can be computed using ES5's Object.* APIs.



 When a function contains a reference to super, that function internally captures an internal reference to the [[Prototype]] of the object created by the enclosing object initialiser. If such a function is subsequently extracted from the original object and installed as a property value in some other object, the internal reference to the original [[Prototype]] is not modified. Essentially, when a function references super it is statically referencing a specific object that is identified when the function is defined and not the [[Prototype]] of the object from which the function was most recently retrieved.

This behavior is consistent with that of most other languages that provide reflection function to extract methods containing super and then independently invoke them.


/be 






_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

Brendan Eich-3
On Jun 19, 2011, at 12:54 PM, Axel Rauschmayer wrote:

Makes sense.

I don’t know how problematic this would be, but if "super" is an internal property of a function, then it could be updated whenever such a function is set as the value of a property.

No, that doesn't work. Both for cases where the function author really did mean the proto-object of the literal-induced object surrounding the function, and in efficiency terms (we do not mutate the RHS of assignment depending on the LHS's Reference Base, e.g.).

If you really want to change what super means in a function expressed in an object initialiser, I'd like to see the exact use-case.


I’m increasingly decomposing object literals into assignments to properties, especially if a literal is long (easier rearrangement of methods, because there is no need to avoid the trailing comma; context is clearer).

Assignments to properties is often more expensive, though (I know the Closure library prefers this style but it is the exception).

Trailing comma in object initialiser is fine in ES5-conforming engines.

/be


Axel

On Jun 19, 2011, at 21:14 , Brendan Eich wrote:

On Jun 19, 2011, at 10:20 AM, Axel Rauschmayer wrote:

It would be nice if "super" could work in any method and not just those methods that are defined inside an object literal. Then, a method would have to know what object it resides in, e.g. via an implicit parameter.

We wish to avoid another parameter computed potentially differently for each call. It will cost, and it will lead to surprises.

Also, anything reachable from |this| can be computed using ES5's Object.* APIs.



 When a function contains a reference to super, that function internally captures an internal reference to the [[Prototype]] of the object created by the enclosing object initialiser. If such a function is subsequently extracted from the original object and installed as a property value in some other object, the internal reference to the original [[Prototype]] is not modified. Essentially, when a function references super it is statically referencing a specific object that is identified when the function is defined and not the [[Prototype]] of the object from which the function was most recently retrieved.

This behavior is consistent with that of most other languages that provide reflection function to extract methods containing super and then independently invoke them.


/be 







_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

Axel Rauschmayer
>> I don’t know how problematic this would be, but if "super" is an internal property of a function, then it could be updated whenever such a function is set as the value of a property.
>
> No, that doesn't work. Both for cases where the function author really did mean the proto-object of the literal-induced object surrounding the function, and in efficiency terms (we do not mutate the RHS of assignment depending on the LHS's Reference Base, e.g.).
>
> If you really want to change what super means in a function expressed in an object initialiser, I'd like to see the exact use-case.

The only use case would be assigning a function that uses "super" to a property.

--
Dr. Axel Rauschmayer

[hidden email]
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

Brendan Eich-3
On Jun 19, 2011, at 7:32 PM, Axel Rauschmayer wrote:

>>> I don’t know how problematic this would be, but if "super" is an internal property of a function, then it could be updated whenever such a function is set as the value of a property.
>>
>> No, that doesn't work. Both for cases where the function author really did mean the proto-object of the literal-induced object surrounding the function, and in efficiency terms (we do not mutate the RHS of assignment depending on the LHS's Reference Base, e.g.).
>>
>> If you really want to change what super means in a function expressed in an object initialiser, I'd like to see the exact use-case.
>
> The only use case would be assigning a function that uses "super" to a property.

Such an assignment might need the meaning of super to remain the same, though. What's the use-case for remapping it? Stealing methods from one class to another whose static super is not the same object as the proto of the object into which the stolen function reference is stored?

/be
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

Axel Rauschmayer
>>> If you really want to change what super means in a function expressed in an object initialiser, I'd like to see the exact use-case.
>>
>> The only use case would be assigning a function that uses "super" to a property.
>
> Such an assignment might need the meaning of super to remain the same, though. What's the use-case for remapping it? Stealing methods from one class to another whose static super is not the same object as the proto of the object into which the stolen function reference is stored?


It wouldn’t be about stealing, but about setting up an object differently:

var obj = {
    foo: function (x) {
        super.foo(x);
    }
};

=== VERSUS ===

var obj = {};
obj.foo = function (x) {
    super.foo(x);
};

The <| helps to make that less urgent (I often use Object.create() and then add properties via assignment, to avoid the verbosity of property descriptors).

--
Dr. Axel Rauschmayer

[hidden email]
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

Brendan Eich-3
On Jun 19, 2011, at 9:13 PM, Axel Rauschmayer wrote:

It wouldn’t be about stealing, but about setting up an object differently:

var obj = {
   foo: function (x) {
       super.foo(x);
   }
};

=== VERSUS ===

var obj = {};
obj.foo = function (x) {
   super.foo(x);
};

The <| helps to make that less urgent (I often use Object.create() and then add properties via assignment, to avoid the verbosity of property descriptors).

The assignment form would not work the same way.

Indeed I hope super usage would be an early error in a function that is not directly contained in an ObjectLiteral.

/be


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

Allen Wirfs-Brock
In reply to this post by Axel Rauschmayer
I actually have a solution in mind for this.

Under the current proposal, a method containing super is "statically bound" to a specific object that provides the [[Prototype]] base for the "super" property lookup.  This is normally done by defining the method in the context of an object literal or class declaration.  If you want to define a method containing outside such a context you still need to provide the necessary binding.

What I have in mind is adding a reflection function for doing that:

let f= function () {return super.f()};
f();  //TypeError -- super unbound

let sup = {foo() {return "super hello"};
let sub = sup <| {};

Object.defineMethod(sub,"foo",f};   //adds f as property named "foo" of sub.  binds super for f

f(); // super hello



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

Allen Wirfs-Brock
with corrections below:

On Jun 20, 2011, at 9:09 AM, Allen Wirfs-Brock wrote:

> I actually have a solution in mind for this.
>
> Under the current proposal, a method containing super is "statically bound" to a specific object that provides the [[Prototype]] base for the "super" property lookup.  This is normally done by defining the method in the context of an object literal or class declaration.  If you want to define a method containing super outside such a context you still need to provide the necessary binding.
>
> What I have in mind is adding a reflection function for doing that:
>
> let f= function () {return "sub-"+super.f()};
> f();  //TypeError -- super unbound
>
> let sup = {foo() {return "super hello"}};
> let sub = sup <| {};
>
> Object.defineMethod(sub,"foo",f);   //adds f as property named "foo" of sub.  binds super for f
>
> sub.f(); // sub-super hello
>
>
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

medikoo
In reply to this post by Brendan Eich-3

Brendan Eich-3 wrote
Quoting from http://wiki.ecmascript.org/doku.php?id=harmony:object_initialiser_super :

>  When a function contains a reference to super, that function internally captures an internal reference to the [[Prototype]] of the object created by the enclosing object initialiser. If such a function is subsequently extracted from the original object and installed as a property value in some other object, the internal reference to the original [[Prototype]] is not modified. Essentially, when a function references super it is statically referencing a specific object that is identified when the function is defined and not the [[Prototype]] of the object from which the function was most recently retrieved.
>
> This behavior is consistent with that of most other languages that provide reflection function to extract methods containing super and then independently invoke them.
>
It's most sane proposal I think. However few things are not obvious to me, will following evaluate as I assume:

var A = {
        one: function () {
                return 'A.foo';
        }
};
var B = Object.create(A);

var C = Object.create(B);
C.one = function () {
        return super.one();
};

var c1 = Object.create(C);
obj.one(); // 'A.foo'


B.two = function () {
        this.three();
};
B.three =  function () {
        return 'B.three';
};
C.two = function () {
        super.two();
};
C.three = function () {
        return 'C.three';
};

var c2 = Object.create(C);
c2.two();  // C.three

Thanks!
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

seaneagan1
I have also been working on a proposal to extend "super" to be
available anywhere by using a "super binding" concept similar to the
exising "this binding" concept, as well as taking ideas from [object
initialiser super].  It is a work in progress, any comments would be
much appreciated!

Please see: https://gist.github.com/1036200

[object initialiser super]
http://wiki.ecmascript.org/doku.php?id=harmony:object_initialiser_super

On Mon, Jun 20, 2011 at 6:49 AM, Mariusz Nowak
<[hidden email]> wrote:

>
>
>
> Brendan Eich-3 wrote:
>>
>> Quoting from
>> http://wiki.ecmascript.org/doku.php?id=harmony:object_initialiser_super :
>>
>>>  When a function contains a reference to super, that function internally
>>> captures an internal reference to the [[Prototype]] of the object created
>>> by the enclosing object initialiser. If such a function is subsequently
>>> extracted from the original object and installed as a property value in
>>> some other object, the internal reference to the original [[Prototype]]
>>> is not modified. Essentially, when a function references super it is
>>> statically referencing a specific object that is identified when the
>>> function is defined and not the [[Prototype]] of the object from which
>>> the function was most recently retrieved.
>>>
>>> This behavior is consistent with that of most other languages that
>>> provide reflection function to extract methods containing super and then
>>> independently invoke them.
>>>
>>
>>
>
> It's most sane proposal I think. However few things are not obvious to me,
> will following evaluate as I assume:
>
> var A = {
>        one: function () {
>                return 'A.foo';
>        }
> };
> var B = Object.create(A);
>
> var C = Object.create(B);
> C.one = function () {
>        return super.one();
> };
>
> var c1 = Object.create(C);
> obj.one(); // 'A.foo'
>
>
> B.two = function () {
>        this.three();
> };
> B.three =  function () {
>        return 'B.three';
> };
> C.two = function () {
>        super.two();
> };
> C.three = function () {
>        return 'C.three';
> };
>
> var c2 = Object.create(C);
> c2.two();  // C.three
>
> Thanks!
>
> -----
> Mariusz Nowak
>
> https://github.com/medikoo
> --
> View this message in context: http://old.nabble.com/Making-%22super%22-work-outside-a-literal--tp31880450p31884964.html
> Sent from the Mozilla - ECMAScript 4 discussion mailing list archive at Nabble.com.
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
>



--
Sean Eagan
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

seaneagan1
In reply to this post by Brendan Eich-3
On Sun, Jun 19, 2011 at 2:14 PM, Brendan Eich <[hidden email]> wrote:
> On Jun 19, 2011, at 10:20 AM, Axel Rauschmayer wrote:
>
> It would be nice if "super" could work in any method and not just those
> methods that are defined inside an object literal. Then, a method would have
> to know what object it resides in, e.g. via an implicit parameter.
>
> We wish to avoid another parameter computed potentially differently for each
> call. It will cost

What costs do you foresee?  I am not sure that there is much to
compute.  Assume a method call O.m().  Assume "m" is found on an
object P within O's protoype chain.  This will result in P.m being
called, for which the "super binding" can simply be computed as
P.[[Prototype]].  Next assume a direct function call, e.g.
f.call(this) or f() (this === undefined), the "super binding" here
could just be calculated as this.[[Prototype]] or undefined if |this|
is not an object.

> , and it will lead to surprises.

What surprises do you foresee?  I think a static |super| in light of
ES's dynamic |this| would actually be much more surprising.  This
would lead to looking for properties in a static |super| object that
may be completely unrelated to the dynamic |this| value of a given
function activation, which would certainly be surprising.

> Also, anything reachable from |this| can be computed using ES5's Object.*
> APIs.

Wouldn't the ES5 Object.* APIs be unreliable and inconvenient for such
a calculation?  It is impossible to determine which property name a
method m was accessed with from within m, and even if you assume a
static property name p, climbing the prototype chain of |this| to
determine on which object m was found via
|Object.getOwnPropertyDescriptor(prototypeChainObject, p)| may not be
accurate if there are any proxies in the prototype chain, or if
anything has changed in the prototype chain since it was initially
climbed by the engine.

> Quoting from
> http://wiki.ecmascript.org/doku.php?id=harmony:object_initialiser_super :
>
>  When a function contains a reference to super, that function internally
> captures an internal reference to the [[Prototype]] of the object created by
> the enclosing object initialiser. If such a function is subsequently
> extracted from the original object and installed as a property value in some
> other object, the internal reference to the original [[Prototype]] is not
> modified. Essentially, when a function references super it is statically
> referencing a specific object that is identified when the function is
> defined and not the [[Prototype]] of the object from which the function was
> most recently retrieved.
>
> This behavior is consistent with that of most other languages that provide
> reflection function to extract methods containing super and then
> independently invoke them.

Consistency with other languages is valuable, but consistency with
this language (ES) is vital.  A static |super| would be inconsistent
with ES's dynamic |this|.  The semantics of |super| will be related to
the value of |this| no matter how |super| ends up being specified, and
thus the "super binding" should be calculated in terms of the "this
binding" if intra-language consistency is to be kept.

>
> /be
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
>
>



Cheers,
Sean Eagan
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

Axel Rauschmayer
>> We wish to avoid another parameter computed potentially differently for each
>> call. It will cost
>
> What costs do you foresee?  I am not sure that there is much to
> compute.  Assume a method call O.m().  Assume "m" is found on an
> object P within O's protoype chain.  This will result in P.m being
> called, for which the "super binding" can simply be computed as
> P.[[Prototype]].  Next assume a direct function call, e.g.
> f.call(this) or f() (this === undefined), the "super binding" here
> could just be calculated as this.[[Prototype]] or undefined if |this|
> is not an object.


This may already be what you are suggesting, so to clarify:

I would introduce a binding called "here" that points to the object P where m has been found.

- Method that uses super: compute super as here.[[Prototype]]
- Non-method function that uses super: "here" is undefined, using super causes an error.

If super is not used there is little computational cost! (Other than a binding per function call which may still be prohibitive.)

--
Dr. Axel Rauschmayer

[hidden email]
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

seaneagan1
On Tue, Jun 21, 2011 at 9:40 AM, Axel Rauschmayer <[hidden email]> wrote:

>>> We wish to avoid another parameter computed potentially differently for each
>>> call. It will cost
>>
>> What costs do you foresee?  I am not sure that there is much to
>> compute.  Assume a method call O.m().  Assume "m" is found on an
>> object P within O's protoype chain.  This will result in P.m being
>> called, for which the "super binding" can simply be computed as
>> P.[[Prototype]].  Next assume a direct function call, e.g.
>> f.call(this) or f() (this === undefined), the "super binding" here
>> could just be calculated as this.[[Prototype]] or undefined if |this|
>> is not an object.
>
>
> This may already be what you are suggesting, so to clarify:
>
> I would introduce a binding called "here" that points to the object P where m has been found.
>
> - Method that uses super: compute super as here.[[Prototype]]
> - Non-method function that uses super: "here" is undefined, using super causes an error.
>
> If super is not used there is little computational cost! (Other than a binding per function call which may still be prohibitive.)

Regardless of any "here" binding, "super" would only need to be bound
within functions that actually use it (the same should be true for
|this|).  However, as I mentioned, it seems the cost of a dynamic
|super| binding should be relatively low, comparable to the cost of a
dynamic |this| binding.

>
> --
> Dr. Axel Rauschmayer
>
> [hidden email]
> twitter.com/rauschma
>
> home: rauschma.de
> blog: 2ality.com
>
>
>
>



--
Sean Eagan
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Making "super" work outside a literal?

Allen Wirfs-Brock
In reply to this post by seaneagan1

On Jun 21, 2011, at 3:28 PM, Sean Eagan wrote:

> On Sun, Jun 19, 2011 at 2:14 PM, Brendan Eich <[hidden email]> wrote:
>> On Jun 19, 2011, at 10:20 AM, Axel Rauschmayer wrote:
>>
>> It would be nice if "super" could work in any method and not just those
>> methods that are defined inside an object literal. Then, a method would have
>> to know what object it resides in, e.g. via an implicit parameter.
>>
>> We wish to avoid another parameter computed potentially differently for each
>> call. It will cost
>
> What costs do you foresee?  I am not sure that there is much to
> compute.  Assume a method call O.m().  Assume "m" is found on an
> object P within O's protoype chain.  This will result in P.m being
> called, for which the "super binding" can simply be computed as
> P.[[Prototype]].  Next assume a direct function call, e.g.
> f.call(this) or f() (this === undefined), the "super binding" here
> could just be calculated as this.[[Prototype]] or undefined if |this|
> is not an object.

The call site (O.m()) does not statically know whether or not the the actual function that will be called uses 'super'. Also,  only the call site knows (dynamically) whether 'this' 'and 'super'  are different.  So, every method call site  must always be prepared for the possibility that it is will be invoking a function that uses 'super' and that the resolved 'this' and 'super' values may be different. There are two alternatively ways that a ES engine might deal with that possibility.  One way is for every call site to always pass a separate 'super' value  as an additional implicit argument and for every function to  accept to have a corresponding implicitly formal parameter. If the property lookup found an own property the values passed for 'this'' and 'super' would be the same but still must be passed as distinct values.  The other way, is for each function to have an internal property that says whether or not the function uses 'super'.  A call site, after looking up a meth
 od property could test this bit of the resolved function and only pass the implicit  'super' value to functions that actually use it. However, conditionally passing 'super' based upon whether or not the callee needs it probably has a higher execution cost than simply always passing a distinct 'super' value. So, implementations are likely to use the always pass super approach.

So, at the very least "dynamic super" adds an extra implicit argument to every call site. This is likely to have a real performance impact because the dynamic average number of  function arguments is likely < 2 (assuming JS is similar to other languages and counting the implicit 'this' argument).  Adding an additional implicit parameter to every call would hence be near a 50% increase in argument passing overhead, on average.



>
>> , and it will lead to surprises.
>
> What surprises do you foresee?  I think a static |super| in light of
> ES's dynamic |this| would actually be much more surprising.  This
> would lead to looking for properties in a static |super| object that
> may be completely unrelated to the dynamic |this| value of a given
> function activation, which would certainly be surprising.

The meaning of 'super'  must be learned.  It isn't a very intuitive concept.  The 'static super' approach is essentially the same as is used in the most widely used static and dynamic object-oriented languages.

If we add a Object.defineMethod function that updates the super binding I think we will eliminate most of the other possible sources of confusion.

>
>> Also, anything reachable from |this| can be computed using ES5's Object.*
>> APIs.
>
> Wouldn't the ES5 Object.* APIs be unreliable and inconvenient for such
> a calculation?  It is impossible to determine which property name a
> method m was accessed with from within m, and even if you assume a
> static property name p, climbing the prototype chain of |this| to
> determine on which object m was found via
> |Object.getOwnPropertyDescriptor(prototypeChainObject, p)| may not be
> accurate if there are any proxies in the prototype chain, or if
> anything has changed in the prototype chain since it was initially
> climbed by the engine.

All true, but what is the use case for actually doing this.  'super' is intended to address the most common static use cases.

I suspect that the pervasive overhead of dynamic super is what has kept it out of the language up to now. I really don't think that implementations are going to look favorably upon it now.




>
>> Quoting from
>> http://wiki.ecmascript.org/doku.php?id=harmony:object_initialiser_super :
>>
>>  When a function contains a reference to super, that function internally
>> captures an internal reference to the [[Prototype]] of the object created by
>> the enclosing object initialiser. If such a function is subsequently
>> extracted from the original object and installed as a property value in some
>> other object, the internal reference to the original [[Prototype]] is not
>> modified. Essentially, when a function references super it is statically
>> referencing a specific object that is identified when the function is
>> defined and not the [[Prototype]] of the object from which the function was
>> most recently retrieved.
>>
>> This behavior is consistent with that of most other languages that provide
>> reflection function to extract methods containing super and then
>> independently invoke them.
>
> Consistency with other languages is valuable, but consistency with
> this language (ES) is vital.  A static |super| would be inconsistent
> with ES's dynamic |this|.  The semantics of |super| will be related to
> the value of |this| no matter how |super| ends up being specified, and
> thus the "super binding" should be calculated in terms of the "this
> binding" if intra-language consistency is to be kept.

ES 'this' is no more dynamic than 'this' in any other OO language. What is somewhat unique to ES is how easy it is to detach a method from one inheritance hierarchy and inject it into another inheritance hierarchy. That is what impacts the 'super'.

I agree that there is at least a small bug farm hazard here. However, think that we do things to lower the hazard and I think that go practice will generally minimize the hazard.  In addition, I think that the other extensions that have reached proposal status will lead to a more declarative style of ES program definition that will generally reduce the need and practice of imperative class-like abstraction construction of the sort that might run into this hazard.

Allen
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
12345