Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Array.from/Array.of/Array#slice without "class" #453

Open
ljharb opened this issue Feb 26, 2015 · 12 comments
Open

Array.from/Array.of/Array#slice without "class" #453

ljharb opened this issue Feb 26, 2015 · 12 comments

Comments

@ljharb
Copy link
Member

ljharb commented Feb 26, 2015

Although class keyword semantics are required to actually subclass Array, these three methods can still be tested without it:

function Foo() {}
Object.setPrototypeOf(Foo, Array);
Foo.prototype = Array.prototype;

assert(Foo.from([1, 2]) instanceof Foo);
assert(Foo.of(1, 2) instanceof Foo);
assert(new Foo().slice() instanceof Foo);

I'm asking because the es6-shim does (or will at next publish) ensure that all of these tests pass. In io.js, which implements class but not Array.from, the es6-shim also makes these tests pass with the "class" syntax.

  • Do you think we can change the test code for these three to not require "class" syntax?
  • Is this sufficient for me to mark es6-shim a "Yes" for these 3 tests, once they all pass?
@zloirock
Copy link
Collaborator

Object.setPrototypeOf(Foo, Array);

Tests shoud be called on IE9.

Is this sufficient for me to mark es6-shim a "Yes" for these 3 tests, once they all pass?

Ok, which result shoud be on babel / core-js? :) This methods are generics in core-js, but subclassing with static methods in babel required __proto__.

I think, possible change Array.from / Array.of tests to Array.from.call(C, {length: 0}) instanceof C.

@ljharb
Copy link
Member Author

ljharb commented Feb 26, 2015

It definitely requires __proto__/Object.setPrototypeOf support for any form of subclassing.

However, I agree - Array.from.call(C) instanceof C would certainly work. I'll update the tests for these three so they don't implicitly depend on subclassing, and make a PR with that, and the updated es6-shim results.

@zloirock
Copy link
Collaborator

for these three

Why only for 3? :) Most Array.prototype methods (concat, filter, map, slice, splice) uses ArraySpeciesCreate and based on @@species. I think, only for static methods or for statics + all prototype methods with @@species check.

@ljharb
Copy link
Member Author

ljharb commented Feb 26, 2015

Those are the only ones that exist in the compat table so far :-)

@zloirock
Copy link
Collaborator

@ljharb ok, how you propose test slice w/o subclassing? Steps 4-7, if you call it not on array - creates simple array, es6-shim implementation isn't correct and will break convert array-like (for example, HTMLCollection) -> array in old code.

@ljharb
Copy link
Member Author

ljharb commented Feb 26, 2015

The way ES.Construct works in es6-shim does use Symbol.species behavior when present, and has a fallback when it's not.

Hmm - with my shimmed slice, I run Array.prototype.slice.call(document.querySelectorAll('div')) instanceof NodeList and get a TypeError, which is actually the correct behavior based on ES6. However, that's almost certainly not what people want to happen :-/

@ljharb
Copy link
Member Author

ljharb commented Feb 26, 2015

@zloirock Please file an issue about this on es6-shim - I'll definitely figure it out there before updating anything in compat-table.

@zloirock
Copy link
Collaborator

It's not correct ES6 behavior, see link to spec :) Ok, will create issue.

@kangax
Copy link
Collaborator

kangax commented Feb 26, 2015

@ljharb it's a tricky question. On one hand, I can see how we would want to mark implementations that don't support class but support array subclassing (and other built-ins — does es6-shim allow other built-ins subclassing, btw?). On the other hand, we have implemenations that support class but don't support built-in subclassing via class ..., and I think it's important to show that.

I just looked at the spec and can't figure out how exactly (for example) Array-subclassed objects inherit "magic"/exotic [[DefineOwnProperty]] behavior.

22.1.1 says:

The Array constructor is designed to be subclassable. It may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the exotic Array behaviour must include a super call to the Array constructor to initialize subclass instances that are exotic Array objects. However, most of the Array.prototype methods are generic methods that are not dependent upon their this value being an exotic Array object.

And I don't see anything relevant in 14.5.14 (RuntimeSemantics of ClassHeritage). It sets [[Prototype]] in 15 but which mechanism takes care of [[DefineOwnProperty]] "propagation"? ArraySpeciesCreate internal function sounds like something that could be taking care of it, but it's only used in few Array.prototype methods.

Does anybody know more?

@kangax
Copy link
Collaborator

kangax commented Feb 26, 2015

I'm also confused by this part:

"Subclass constructors that intend to inherit the exotic Array behaviour must include a super call to the Array constructor to initialize subclass instances that are exotic Array objects."

what's a super call to the Array constructor? Do they mean new Foo in class Foo extends Array { } or do they mean class Foo extends Array { super() /* super call in derived constructor */ }?

That latter doesn't make (common) sense and implementations already work without it.

@ljharb
Copy link
Member Author

ljharb commented Feb 27, 2015

@kangax Technically the requirement for Array methods (from, of, slice, etc) to work on non-arrays is completely unrelated to the ability to subclass arrays - so I think the feature tests shouldn't require subclassing in order to ensure that the methods are generic, per spec.

A super call to the Array constructor basically means A.apply(this, arguments) or super().

@kangax
Copy link
Collaborator

kangax commented Feb 28, 2015

@ljharb methods — yes, but I was talking about [[DefineOwnProperty]] behavior (something that we couldn't inherit in ES5 — http://perfectionkills.com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array/)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants