Re: [WebIDL] interface objects with [Constructor] and [[Call]]

On 10/7/10, Maciej Stachowiak <mjs@apple.com> wrote:
>
> On Oct 7, 2010, at 10:49 PM, Cameron McCormack wrote:
>
>> Garrett Smith:
>>> My statement in the previous paragraph is regarding the algorithm for
>>> [[Construct]], as specified in ECMA-262. Were you discussing a
>>> different [[Construct]]?
>>
>> Ah, I (mis-)interpreted it as a comment on all objects’ [[Construct]],
>> be they native or host objects.
>>
>>> In ECMA-262, step 6 of [[Construct]] is:
>>> | 6. Invoke the [[Call]] property of F, providing Result(1)
>>> | as the this value and providing the argument list passed
>>> | into [[Construct]] as the argument values.
>>>
>>> Understand that an object that implements [[Construct]] implements
>>> [[Call]]. What is not known is what either of those commands will do.
>>> That is what specification is for.
>>
>> Indeed.
>>
>>> How can an object implement [[Construct]] but not [[Call]]?
>>
>> It can if it is a host object and it has a [[Construct]] which is
>> different from the one defined for native Function objects in ECMA-262.
>> Then there is no need for it to have [[Call]].
>
> And in fact, some built-in objects have behavior "when called as a
> constructor" which cannot be explained as the 13.2.2 [[Construct]] algorithm
> invoking their [[Call]] behavior. One example is the String constructor. The
> spec doesn't seem to explicitly define its [[Call]] and [[Construct]]
> internal properties, but this is the only sane interpretation.
>
This behavior is explainable by the fact that [[Construct]] always
results in an object, even if the function that it called returns a
primitive value. There is no constructor in the specification whose
behavior cannot be explained by [[Call]] and [[Construct]].

We discussed this a bit in comp.lang.javascript thread "Using "new
function() {...}" as a Singleton" (for the truly interested).

This can be illustrated by an example. For those interested and
willing to bear with typos (it's late; I'm tired), the following
function returns a string value and yet when called as a constructor,
an object is returned.

function MyString(s) {
  if(this instanceof MyString) {
    this.toString = this.valueOf = function() {
      return String(s);
    };
  }
  return String(s);
}
new MyString("foo"); // Object.
MyString("bar"); // string value.

This is explained by [[Construct]] in ECMA-262 Ed 3:

1. Create a new native ECMAScript object.
2. Set the [[Class]] property of Result(1) to "Object".
3. Get the value of the prototype property of F.
4. If Result(3) is an object, set the [[Prototype]] property of
Result(1) to Result(3).
5. If Result(3) is not an object, set the [[Prototype]] property of
Result(1) to the original Object prototype object as described in
15.2.3.1.
6. Invoke the [[Call]] property of F, providing Result(1) as the this
value and providing the argument list passed into [[Construct]] as the
argument values.
7. If Type(Result(6)) is Object then return Result(6).
8. Return Result(1).

Garrett

Received on Friday, 8 October 2010 06:50:06 UTC