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

[FEATURE ember-runtime-enumerable-includes] Implements Array.includes and deprecates Array.contains #13553

Merged
merged 1 commit into from
Jun 4, 2016

Conversation

bmeurant
Copy link
Contributor

@bmeurant bmeurant commented May 24, 2016

Implementation of emberjs/rfcs#136

TODO :

@alexspeller
Copy link
Contributor

Oh awesome, thanks for getting this implementation done!

@bmeurant
Copy link
Contributor Author

Here is a first proposal for emberjs/rfcs#136. Work is in progress and feedbacks expected.

I made the asumption that we have to keep Enumerable & Array APIs consistent and then have to provide a consistent includes method in Enumerable (with no index). Let me know if this is not expected.

Aliasing contains with the new includes method can break some existing apps because, according to the spec (https://tc39.github.io/ecma262/2016/#sec-array.prototype.includes), includes relies on the SameValueZero algorithm and actual contains relies on strict equality leading to differences in NaN detections (I will document it). Can we still make this ?

@mixonic
Copy link
Member

mixonic commented May 24, 2016

@bmeurant Thanks :-)

contains should not be aliased to includes. Contains should keep its current implementation, and we can deprecate it though we will likely do that in a separate PR. In this PR it should simply retain its current behavior.

@bmeurant
Copy link
Contributor Author

@mixonic thx for your feedback.

I updated this PR to keep current implementation for Enumerable.contains & Array.contains.

we can deprecate it though we will likely do that in a separate PR

Does it means that I should also remove @deprecated and deprecation warning for now ?

@rwjblue
Copy link
Member

rwjblue commented May 24, 2016

I believe that the deprecation should be included here when the feature flag is enabled.

@mixonic
Copy link
Member

mixonic commented May 24, 2016

@rwjblue I am easily convinced, was just erring on the conservative side. @bmeurant please include the deprecation behind the feature flag! :-)

@bmeurant
Copy link
Contributor Author

bmeurant commented May 25, 2016

@mixonic I added feature flag and move deprecation behind it. Let me know if I forgotten something.

I also removed @deprecated from API because contains is not actually deprecated if feature is not enabled, right ?

But I was wondering: doing that, users will loose the information that contains will be deprecated soon and that they should use includes instead. Is it exists a way to provide this kind of information in APIs ?

@bmeurant bmeurant changed the title [WIP][FEATURE contains-to-includes] Implements Array.includes and deprecates Array.contains [FEATURE contains-to-includes] Implements Array.includes and deprecates Array.contains May 25, 2016
@mixonic
Copy link
Member

mixonic commented May 27, 2016

@bmeurant Yeah the documentation may require some followup tweaks. Feature flagging things like the @deprecated flag is tricky :-/. I think you should feel free to create a followup issue of things to do once the feature is "go'd" for beta.


* `ember-runtime-enumerable-contains`

Deprecates `Enumerable.contains` and `Array.contains` in favor of `Enumerable.includes` and `Array.includes`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again here I lean toward Enumerable#contains, per emberjs/website#2600 (comment). It is a Rubyish approach, curious if there are other thoughts.

Copy link
Contributor

@alexspeller alexspeller May 27, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Enumerable#contains is the convention in Ember even though it was originally a rubyism - at least it has the advantage that it's not valid syntax for something that is completely different

(See for example the changelog where it's used extensively)

@mixonic
Copy link
Member

mixonic commented May 27, 2016

@bmeurant heh, there are no tests for Array#contains?! Can you add one asserting basic behavior and the deprecation please?

This is looking pretty good after some tweaks!

@return {Boolean} `true` if object is found in the array.
@public
*/
includes(obj, startAt) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function (and the enumerable one) must be added only when the feature flag is enabled. For example:

let ArrayMixin = Mixin.create(Enumerable, {
 /* snip */
});
if (isEnabled('ember-runtime-enumerable-includes')) {
  ArrayMixin.reopen({
    includes(obj, startAt) {
      /* ... */
    }
  });
}
export default ArrayMixin;

@bmeurant
Copy link
Contributor Author

Thx for feedbacks, I'll work on it ASAP

@bmeurant
Copy link
Contributor Author

bmeurant commented May 27, 2016

It seemed to me that Array#contains tests are also imported and run from Enumerable#contains tests. Did I miss something ?

@mixonic
Copy link
Member

mixonic commented May 27, 2016

Ah I see @bmeurant :-) right there is no contains on arrays, only on enumerable 👍

@bmeurant
Copy link
Contributor Author

I wanted to add a test to verify assertion calling Enumerable#includes with a second argument but, because tests defined on Enumerable are also run on Array suites, I did not find a good way to do it. Any advice ?

@@ -811,7 +820,9 @@ var Enumerable = Mixin.create({
@public
*/
without(value) {
Copy link
Contributor Author

@bmeurant bmeurant May 27, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we have a problem line 832 during k !== value. If the feature is enabled, without becomes inconsistent because NaN !== NaN is true

return found;
},

without(value) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefered replacing without behind feature flag to not add multiple isEnabled calls in original method

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@mixonic
Copy link
Member

mixonic commented May 30, 2016

@bmeurant it seems ok to add a test for contains without an offset in packages/ember-runtime/tests/mixins/enumerable_test.js, since it only impacts enumerables.

@mixonic
Copy link
Member

mixonic commented May 30, 2016

Thanks for your continued work on this 😄 it looks really close, and quite nice!

@mixonic
Copy link
Member

mixonic commented May 30, 2016

Looking nice. A rebase/squash to some number is semantically meaningful commits (one or more) would be great, each prefixed with [FEATURE ember-runtime-enumerable-includes] would be great.

@mixonic mixonic changed the title [FEATURE contains-to-includes] Implements Array.includes and deprecates Array.contains [FEATURE ember-runtime-enumerable-includes] Implements Array.includes and deprecates Array.contains May 30, 2016
@bmeurant
Copy link
Contributor Author

Done 👌

@homu
Copy link
Contributor

homu commented Jun 1, 2016

☔ The latest upstream changes (presumably #13328) made this pull request unmergeable. Please resolve the merge conflicts.

@mixonic
Copy link
Member

mixonic commented Jun 3, 2016

Looks pretty great to me @bmeurant! Thank you! I'll get someone else on core to review and we can :shipit: with their 👍

var len = get(this, 'length');
var idx, currentObj;

if (Ember.isNone(startAt)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not use the global here (Ember.isNone), if we need isNone it should be imported. Can we just do the null / undefined check ourselves?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rwjblue using the global here was surely a mistake, sorry. isNone is already imported and used in slice. I'll update. But why do you prefer to not use imported isNone and doing null / undefined check ourselves in this case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anyway, explicit null check is unnecessary as we only iterating on idx = startAt. I removed it.

@rwjblue
Copy link
Member

rwjblue commented Jun 3, 2016

This looks good, only one small tweak and this is good to go...

@mixonic mixonic merged commit b0332ef into emberjs:master Jun 4, 2016
@mixonic
Copy link
Member

mixonic commented Jun 4, 2016

This is great! Thank you @bmeurant!

@rwjblue
Copy link
Member

rwjblue commented Aug 25, 2016

FYI - I created https://github.com/rwjblue/ember-runtime-enumerable-includes-polyfill to make this a bit easier for addons to avoid deprecations, use the newer syntax, and continue to support older versions of Ember.

homu added a commit to emberjs/guides that referenced this pull request Oct 18, 2016
Update documentation to move from contains to includes

Related to emberjs/ember.js#13553.

To be merged when feature has been released.
ecksun pushed a commit to Manetos/ember-searchable-select that referenced this pull request Sep 4, 2018
This is required as .contains seems to be deprecated in ember-3.

See emberjs/ember.js#13553 for more information
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants