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

Is there a reason ArraySpeciesCreate (section 9.4.2.3) doesn't just delegate to SpeciesConstructor? #1178

Closed
dead-claudia opened this issue Apr 20, 2018 · 4 comments
Labels

Comments

@dead-claudia
Copy link

dead-claudia commented Apr 20, 2018

There's very little variation in practice between the algorithm for ArraySpeciesCreate(originalArray, length) and the following steps:

  1. Let thisRealm be the current Realm Record.
  2. If length is -0, let length be +0.
  3. Let defaultArray be thisRealm.[[Intrinsics]].[[%Array%]].
  4. Let C be ? SpeciesConstructor(originalArray, defaultArray).
  5. Return ? Construct(C, length).

Is there a reason why the variation exists?

Specifically, this in practice means ArraySpeciesCreate does two things that SpeciesConstructor callees generally don't:

  1. It ignores Symbol.species on functions, but not objects (bug?)
  2. It defaults to the current realm's %Array% instead of the this value's %Array% (documented)

I accounted for 2 in the steps above, but 1 seems like a bug. Would changing it to be aligned with SpeciesConstructor change the behavior to become not web-compatible?

@ljharb
Copy link
Member

ljharb commented Apr 20, 2018

cc @allenwb

@allenwb
Copy link
Member

allenwb commented Apr 20, 2018

ArraySpeciesCreate was crafted to specifically support the five functions that call it. Those are all legacy methods that have both backwards compatibility and web reality requirements and which needed to be extended (in ES6) to support Array subclassing. The choice of realm is the web reality issue and the fall back to ArrayCreate if originalArray does not have a constructor property is one of the backwards compatibility requirements.

It ignores Symbol.species on functions, but not objects (bug?)

No it doesn't. Note that the test is Type(C) is Object. Type() is not typeof and the Type of a function is object, so that predicate will be true when C is a function.

Why; doesn't ArraySpeciesCreate use SpeciesConstructor? One reason is that it was probably written before SpeciesConstructor. But, it is also probably better for operations like this that are trying to exactly duplicate legacy behavior to have all the essential pseudo code in one place.

You could probably refactor it but you will need to be very careful to exactly duplicate the sequencing of the observable behaviors and the backwards compat (with ES3/5) constraints. I don't think it would be worth the effort or necessarily result in a clearer specification.

If it's not broken, don't fix it!

@dead-claudia
Copy link
Author

Thanks for the explanation! I ran into it while writing a proposal's polyfill, and just wanted some clarification for what's going on with that particular section so I didn't erroneously refactor my code to not work like it's supposed to.

@domenic
Copy link
Member

domenic commented Apr 20, 2018

I would suggest that the editors add a non-normative note explaining the things above, so they aren't forever locked up inside @allenwb's brain.

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

No branches or pull requests

4 participants