archives

« Bugzilla Issues Index

#3550 — new Object(value), for value != null, is no longer equivalent to ToObject(value)


+++ This bug was initially created as a clone of Bug #3544 +++

[removing noise of Bug #3544]

19.1.1.1 Object([ value ])

As specced in Rev 31, `new Object(foo)`, for foo != null, is now just equivalent to `new Object()` instead of ToObject(foo).

One should revert to the definition of Rev 30, that is removing the newly added step 1.


*** Bug 3544 has been marked as a duplicate of this bug. ***


Better fix: modify step 1 the following way:

1. If NewTarget is neither null nor the active function object, then,
a. Return etc.


fixed in rev32 editor's draft


(In reply to Allen Wirfs-Brock from comment #3)
> fixed in rev32 editor's draft

I assume this was changed in the following way. Correct?

---
1. If NewTarget is null, let newTarget be the active function object, else let newTarget be NewTarget.
2. If value is null, undefined or not supplied, return OrdinaryCreateFromConstructor(newTarget, "%ObjectPrototype%" ).
3. Return ToObject(value).
---


(In reply to André Bargull from comment #4)

Consider:

class Foo extends Object { }
new Foo(3)

With your algorithm you obtain a Number object. I think that the spec intent is to produce an instance of Foo.


(In reply to Claude Pache from comment #5)
> (In reply to André Bargull from comment #4)
>
> Consider:
>
> class Foo extends Object { }
> new Foo(3)
>
> With your algorithm you obtain a Number object. I think that the spec intent
> is to produce an instance of Foo.

Ah I see. What about this solution? Step 3 should handle the Object called from sub-class constructor issue.

---
1. Let activeF be the active function object.
2. If NewTarget is null, let newTarget be activeF, else let newTarget be NewTarget.
3. If SameValue(activeF, newTarget) is false, return OrdinaryCreateFromConstructor(newTarget, "%ObjectPrototype%").
4. If value is null, undefined or not supplied, return OrdinaryCreateFromConstructor(newTarget, "%ObjectPrototype%").
5. Return ToObject(value).
---


Here is the algorithm I actually used for Comment 3

1. If NewTarget is neither undefined nor the active function, then,
a. Return OrdinaryCreateFromConstructor(NewTarget, "%ObjectPrototype%").
2. If value is null, undefined or not supplied, return ObjectCreate(%ObjectPrototype%).
3. Return ToObject(value).

(note the [[call]] state of NewTarget has now been changed from null to undefined)

note that by step 2 we know that NewTarget is either undefined or a Object constructor function, so we can use ObjectCreate instead of OrdinaryCreate...


(In reply to Allen Wirfs-Brock from comment #7)
> note that by step 2 we know that NewTarget is either undefined or a Object
> constructor function, so we can use ObjectCreate instead of OrdinaryCreate...

That means I have to re-open bug 3136. Here's another test case for bug 3136:
---
function cloneWithProto(constructor, prototype) {
return Object.defineProperty(constructor.toMethod({}), "prototype", {value: prototype});
}

for (var constructor of [Object, Array, Date, Error, TypeError, RegExp, String, Boolean, Number]) {
var clone = cloneWithProto(constructor, {});
var obj = new clone();
print(Object.getPrototypeOf(obj) === clone.prototype);
}
---

The above program prints "true" for every constructor function except for `Object`. Changing ObjectCreate to ObjectCreateFromConstructor will align `Object`'s behaviour to be in line with the other built-in constructor functions.


(In reply to Claude Pache from comment #5)
> (In reply to André Bargull from comment #4)
>
> Consider:
>
> class Foo extends Object { }
> new Foo(3)
>
> With your algorithm you obtain a Number object. I think that the spec intent
> is to produce an instance of Foo.

I actually think this should create an `[object Number]` exotic object. The prototype chain will still have Foo.prototype on it.

That would be much more consistent with the rest of the semantics.

class C extends Object {}

is very different from

class C {}

The former has class side inheritance and the instance object is created by calling [[Construct]] on Object with NewTarget passed along.

A similar case would be if I have a base class that might create a typed array in some cases and a plain array in other cases.


(In reply to Erik Arvidsson from comment #9)
> (In reply to Claude Pache from comment #5)
> > (In reply to André Bargull from comment #4)
> >
> > Consider:
> >
> > class Foo extends Object { }
> > new Foo(3)
> >
> > With your algorithm you obtain a Number object. I think that the spec intent
> > is to produce an instance of Foo.
>
> I actually think this should create an `[object Number]` exotic object. The
> prototype chain will still have Foo.prototype on it.
>

Maybe, but I doubt that anyone would willfully construct a Number object without `Number.prototype` in its prototype chain using that syntax. DDWIDM.


fixed in rev32 draft