From 92b9401e4f7090a544d98dae52dda65c86a963b2 Mon Sep 17 00:00:00 2001 From: hanli Date: Fri, 1 Apr 2022 14:04:40 -0700 Subject: [PATCH 01/16] RFC: Deprecate array prototype extensions --- ...00-deprecate-array-prototype-extensions.md | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 text/0000-deprecate-array-prototype-extensions.md diff --git a/text/0000-deprecate-array-prototype-extensions.md b/text/0000-deprecate-array-prototype-extensions.md new file mode 100644 index 0000000000..ca8045932c --- /dev/null +++ b/text/0000-deprecate-array-prototype-extensions.md @@ -0,0 +1,130 @@ +--- +Stage: Initial +Start Date: 2022-4-01 +Release Date: Unreleased +Release Versions: + ember-source: vX.Y.Z + ember-data: vX.Y.Z +Relevant Team(s): Ember.js +RFC PR: +--- + +# Deprecate array prototype extensions + +## Summary + +This RFC proposes to deprecate array prototype extensions. + +## Motivation + +Ember historically extended the prototypes of native Javascript arrays to implement `Ember.Enumerable`, `Ember.MutableEnumerable`, `Ember.MutableArray`, `Ember.Array`. This added convenient methods and properties, and also made Ember arrays automatically participate in the Ember Classic reactivity system. + +Those convenient methods increase the likelihood of becoming potential roadblocks for future built-in language extensions, and make it confusing for users to onboard: is it specifically part of Ember, or Javascript? With Ember Octane, the new reactivity system, those classic observable-based methods are no longer needed. + +We had deprecated [Functions](https://github.com/emberjs/rfcs/blob/master/text/0272-deprecation-native-function-prototype-extensions.md) and [Strings](https://github.com/emberjs/rfcs/blob/master/text/0236-deprecation-ember-string.md) prototype extensions. Array is the last step. And internally we had already been preferring generic array methods over prototype extensions ([epic](https://github.com/emberjs/ember.js/issues/15501)). + +Continuing in that direction, we should consider recommending the usage of generic array functions as opposed to convenient prototype extension functions, and the usage of new tracked properties over classic reactivity methods. + +## Transition Path + +For convenient methods like `without`, `sortBy`, `uniqBy` etc., the replacement functionality already exists either through generic array functions or lodash helper functions. + +For helper functions participating in the Ember classic reactivity system like `pushObject`, `clear`, the replacement functionality also already exists in the form of immutable update style with tracked propreties like `@tracked someArray = []`, or through utilizing `TrackedArray` from `tracked-built-ins`. + +We don't need to build anything new specifically, however, the bulk of the transition will be +focused on deprecating the array prototype extensions. + +## How We Teach This + +An entry to the [Deprecation Guides](https://deprecations.emberjs.com/v4.x) will be added outlining the different recommended transition strategies. + +We will create a new lint rule `no-array-prototype-extensions` and set examples. Examples should have recommendations for equivalences. + +We will also create codemods to help with this migration. + +### Convenient methods +Examples of deprecated and current code: +```js +import { set, action } from '@ember/object'; +import { uniqBy, sortBy } from 'lodash'; + +export default class SampleComponent extends Component{ + abc = ['x', 'y', 'z', 'x']; + + // deprecated + def = this.abc.without('x'); + ghi = this.abc.uniq(); + jkl = this.abc.toArray(); + mno = this.abc.uniqBy('y'); + pqr = this.abc.sortBy('z'); + // ... + + // current + def = this.abc.filter(el => el !== 'x'); + ghi = [...new Set(this.abc)]; + jkl = [...this.abc]; + mno = uniqBy(this.abc, 'y'); + pqr = sortBy(this.abc, 'z'); +}; +``` + +### Observable based methods +Examples of deprecated code: +```js +import { set, action } from '@ember/object'; + +export default class SampleComponent extends Component{ + abc = []; + + @action + someAction(newItem) { + this.abc.pushObject('1'); + } +}; +``` + +Examples of current code. +#### Option 1: tracked properties +```js +import { set, action } from '@ember/object'; +import { tracked } from '@glimmer/tracking'; + +export default class SampleComponent extends Component{ + @tracked abc = []; + + @action + someAction(newItem) { + this.abc = [...abc, newItem]; + } +}; +``` + +#### Option 2: `TrackedArray` +```js +import { set, action } from '@ember/object'; +import { TrackedArray } from 'tracked-built-ins'; + +export default class SampleComponent extends Component{ + abc = new TrackedArray(); + + @action + someAction(newItem) { + abc.push(newItem); + } +}; +``` + +After the deprecated code is removed from Ember, we need to remove the [options to disable the array prototype extension](https://guides.emberjs.com/v4.2.0/configuring-ember/disabling-prototype-extensions/) from Official Guides and we also need to update the [Tracked Properties](https://guides.emberjs.com/v4.2.0/upgrading/current-edition/tracked-properties/#toc_arrays) `Arrays` section with updated suggestions. + +## Drawbacks +- For users relying on Ember array prototype extensions, they will have to refactor their code and use equivalences appropriately. +- A lot of existing Ember forums/blogs had been assuming the enabling of array prototype extensions which could cause confusions for users referencing them. + + +## Alternatives +- Continuing allowing array prototype extensions but turning the EXTEND_PROTOTYPES off by default. +- Do nothing. + +### Unresolved questions +- Some methods like `removeObject`, `removeObjects` that have non-trival logics might require custom helper function in application to ease the migration. +- Shall we deprecate `Ember.A()` as well or still allowing users to use it? From c7e689e6d969ab6fd2dbed7480e81ae89df24f79 Mon Sep 17 00:00:00 2001 From: hanli Date: Tue, 5 Apr 2022 01:17:55 -0700 Subject: [PATCH 02/16] Add more drawbacks and unsolved questions --- ...00-deprecate-array-prototype-extensions.md | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/text/0000-deprecate-array-prototype-extensions.md b/text/0000-deprecate-array-prototype-extensions.md index ca8045932c..0bc69c34e8 100644 --- a/text/0000-deprecate-array-prototype-extensions.md +++ b/text/0000-deprecate-array-prototype-extensions.md @@ -19,17 +19,19 @@ This RFC proposes to deprecate array prototype extensions. Ember historically extended the prototypes of native Javascript arrays to implement `Ember.Enumerable`, `Ember.MutableEnumerable`, `Ember.MutableArray`, `Ember.Array`. This added convenient methods and properties, and also made Ember arrays automatically participate in the Ember Classic reactivity system. -Those convenient methods increase the likelihood of becoming potential roadblocks for future built-in language extensions, and make it confusing for users to onboard: is it specifically part of Ember, or Javascript? With Ember Octane, the new reactivity system, those classic observable-based methods are no longer needed. +Those convenient methods increase the likelihood of becoming potential roadblocks for future built-in language extensions, and make it confusing for users to onboard: is it specifically part of Ember, or Javascript? Also with Ember Octane, the new reactivity system, those classic observable-based methods are no longer needed. We had deprecated [Functions](https://github.com/emberjs/rfcs/blob/master/text/0272-deprecation-native-function-prototype-extensions.md) and [Strings](https://github.com/emberjs/rfcs/blob/master/text/0236-deprecation-ember-string.md) prototype extensions. Array is the last step. And internally we had already been preferring generic array methods over prototype extensions ([epic](https://github.com/emberjs/ember.js/issues/15501)). -Continuing in that direction, we should consider recommending the usage of generic array functions as opposed to convenient prototype extension functions, and the usage of new tracked properties over classic reactivity methods. +Continuing in that direction, we should consider recommending the usage of native array functions as opposed to convenient prototype extension functions, and the usage of new tracked properties or `TrackedArray` over classic reactivity methods. ## Transition Path For convenient methods like `without`, `sortBy`, `uniqBy` etc., the replacement functionality already exists either through generic array functions or lodash helper functions. -For helper functions participating in the Ember classic reactivity system like `pushObject`, `clear`, the replacement functionality also already exists in the form of immutable update style with tracked propreties like `@tracked someArray = []`, or through utilizing `TrackedArray` from `tracked-built-ins`. +For helper functions participating in the Ember classic reactivity system like `pushObject`, `removeObject`, the replacement functionality also already exists in the form of immutable update style with tracked propreties like `@tracked someArray = []`, or through utilizing `TrackedArray` from `tracked-built-ins`. + +During transition, we should still allow users to use `A` from `@ember/array`. We don't need to build anything new specifically, however, the bulk of the transition will be focused on deprecating the array prototype extensions. @@ -38,14 +40,13 @@ focused on deprecating the array prototype extensions. An entry to the [Deprecation Guides](https://deprecations.emberjs.com/v4.x) will be added outlining the different recommended transition strategies. -We will create a new lint rule `no-array-prototype-extensions` and set examples. Examples should have recommendations for equivalences. +We will create new eslint rule and template lint rule `no-array-prototype-extensions` and set examples. Examples should have recommendations for equivalences. We will also create codemods to help with this migration. ### Convenient methods Examples of deprecated and current code: ```js -import { set, action } from '@ember/object'; import { uniqBy, sortBy } from 'lodash'; export default class SampleComponent extends Component{ @@ -71,7 +72,7 @@ export default class SampleComponent extends Component{ ### Observable based methods Examples of deprecated code: ```js -import { set, action } from '@ember/object'; +import { action } from '@ember/object'; export default class SampleComponent extends Component{ abc = []; @@ -86,7 +87,7 @@ export default class SampleComponent extends Component{ Examples of current code. #### Option 1: tracked properties ```js -import { set, action } from '@ember/object'; +import { action } from '@ember/object'; import { tracked } from '@glimmer/tracking'; export default class SampleComponent extends Component{ @@ -101,11 +102,12 @@ export default class SampleComponent extends Component{ #### Option 2: `TrackedArray` ```js -import { set, action } from '@ember/object'; +import { action } from '@ember/object'; +import { tracked } from '@glimmer/tracking'; import { TrackedArray } from 'tracked-built-ins'; export default class SampleComponent extends Component{ - abc = new TrackedArray(); + @tracked abc = new TrackedArray(); @action someAction(newItem) { @@ -119,7 +121,7 @@ After the deprecated code is removed from Ember, we need to remove the [options ## Drawbacks - For users relying on Ember array prototype extensions, they will have to refactor their code and use equivalences appropriately. - A lot of existing Ember forums/blogs had been assuming the enabling of array prototype extensions which could cause confusions for users referencing them. - +- Increase package sizes, for example, before `this.abc.filterBy('x');`, now `this.abc.filter(el => el !== 'x');`. ## Alternatives - Continuing allowing array prototype extensions but turning the EXTEND_PROTOTYPES off by default. @@ -127,4 +129,5 @@ After the deprecated code is removed from Ember, we need to remove the [options ### Unresolved questions - Some methods like `removeObject`, `removeObjects` that have non-trival logics might require custom helper function in application to ease the migration. +- `replace` method is one of ember array extensions but also be string native proptypes, which adds uncertainty for lint rules and can cause issues during the deprecation. - Shall we deprecate `Ember.A()` as well or still allowing users to use it? From 7de7d1d56dbda3fcfa67dcb8850903d1bf32ec72 Mon Sep 17 00:00:00 2001 From: hanli Date: Tue, 12 Apr 2022 13:59:45 -0700 Subject: [PATCH 03/16] Add eslint and template lint links --- ...00-deprecate-array-prototype-extensions.md | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/text/0000-deprecate-array-prototype-extensions.md b/text/0000-deprecate-array-prototype-extensions.md index 0bc69c34e8..12f8ed0d2a 100644 --- a/text/0000-deprecate-array-prototype-extensions.md +++ b/text/0000-deprecate-array-prototype-extensions.md @@ -31,7 +31,7 @@ For convenient methods like `without`, `sortBy`, `uniqBy` etc., the replacement For helper functions participating in the Ember classic reactivity system like `pushObject`, `removeObject`, the replacement functionality also already exists in the form of immutable update style with tracked propreties like `@tracked someArray = []`, or through utilizing `TrackedArray` from `tracked-built-ins`. -During transition, we should still allow users to use `A` from `@ember/array`. +During transition, we still allow users to use `A` from `@ember/array`. We don't need to build anything new specifically, however, the bulk of the transition will be focused on deprecating the array prototype extensions. @@ -40,13 +40,14 @@ focused on deprecating the array prototype extensions. An entry to the [Deprecation Guides](https://deprecations.emberjs.com/v4.x) will be added outlining the different recommended transition strategies. -We will create new eslint rule and template lint rule `no-array-prototype-extensions` and set examples. Examples should have recommendations for equivalences. +Rule `ember/no-array-prototype-extensions` is available for both [eslint](https://github.com/ember-cli/eslint-plugin-ember/blob/master/docs/rules/no-array-prototype-extensions.md) and [template lint](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/no-array-prototype-extensions.md). Rule examples have recommendations for equivalences. -We will also create codemods to help with this migration. +We can leverage the fixers of lint rule to auto fix some of the issues. We will also create codemods to help with this migration. ### Convenient methods Examples of deprecated and current code: ```js +import Component from '@glimmer/component'; import { uniqBy, sortBy } from 'lodash'; export default class SampleComponent extends Component{ @@ -72,6 +73,7 @@ export default class SampleComponent extends Component{ ### Observable based methods Examples of deprecated code: ```js +import Component from '@glimmer/component'; import { action } from '@ember/object'; export default class SampleComponent extends Component{ @@ -87,6 +89,7 @@ export default class SampleComponent extends Component{ Examples of current code. #### Option 1: tracked properties ```js +import Component from '@glimmer/component'; import { action } from '@ember/object'; import { tracked } from '@glimmer/tracking'; @@ -102,6 +105,7 @@ export default class SampleComponent extends Component{ #### Option 2: `TrackedArray` ```js +import Component from '@glimmer/component'; import { action } from '@ember/object'; import { tracked } from '@glimmer/tracking'; import { TrackedArray } from 'tracked-built-ins'; @@ -116,6 +120,18 @@ export default class SampleComponent extends Component{ }; ``` +### Properties in templates +Examples of deprecated code: + +```hbs + +``` + +Examples of current code. +```hbs + +``` + After the deprecated code is removed from Ember, we need to remove the [options to disable the array prototype extension](https://guides.emberjs.com/v4.2.0/configuring-ember/disabling-prototype-extensions/) from Official Guides and we also need to update the [Tracked Properties](https://guides.emberjs.com/v4.2.0/upgrading/current-edition/tracked-properties/#toc_arrays) `Arrays` section with updated suggestions. ## Drawbacks From b28f04e65900b6cef1f4e74e665b28780b650b97 Mon Sep 17 00:00:00 2001 From: Hang Li Date: Thu, 14 Apr 2022 13:33:30 -0700 Subject: [PATCH 04/16] Update text/0000-deprecate-array-prototype-extensions.md Co-authored-by: Chris Krycho --- text/0000-deprecate-array-prototype-extensions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-deprecate-array-prototype-extensions.md b/text/0000-deprecate-array-prototype-extensions.md index 12f8ed0d2a..3c383ba5a1 100644 --- a/text/0000-deprecate-array-prototype-extensions.md +++ b/text/0000-deprecate-array-prototype-extensions.md @@ -27,7 +27,7 @@ Continuing in that direction, we should consider recommending the usage of nativ ## Transition Path -For convenient methods like `without`, `sortBy`, `uniqBy` etc., the replacement functionality already exists either through generic array functions or lodash helper functions. +For convenient methods like `without`, `sortBy`, `uniqBy` etc., the replacement functionality already exists either through generic array functions or utility libraries like [lodash](https://lodash.com), [Ramda](https://ramdajs.com), etc. For helper functions participating in the Ember classic reactivity system like `pushObject`, `removeObject`, the replacement functionality also already exists in the form of immutable update style with tracked propreties like `@tracked someArray = []`, or through utilizing `TrackedArray` from `tracked-built-ins`. From afc0feddcab06d93c5b60c112511ac1c0e44fee0 Mon Sep 17 00:00:00 2001 From: Hang Li Date: Thu, 28 Apr 2022 18:00:22 -0700 Subject: [PATCH 05/16] Update text/0000-deprecate-array-prototype-extensions.md Co-authored-by: Chris Krycho --- text/0000-deprecate-array-prototype-extensions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-deprecate-array-prototype-extensions.md b/text/0000-deprecate-array-prototype-extensions.md index 3c383ba5a1..e14f56900e 100644 --- a/text/0000-deprecate-array-prototype-extensions.md +++ b/text/0000-deprecate-array-prototype-extensions.md @@ -132,7 +132,7 @@ Examples of current code. ``` -After the deprecated code is removed from Ember, we need to remove the [options to disable the array prototype extension](https://guides.emberjs.com/v4.2.0/configuring-ember/disabling-prototype-extensions/) from Official Guides and we also need to update the [Tracked Properties](https://guides.emberjs.com/v4.2.0/upgrading/current-edition/tracked-properties/#toc_arrays) `Arrays` section with updated suggestions. +After the deprecated code is removed from Ember (at 5.0), we need to remove the [options to disable the array prototype extension](https://guides.emberjs.com/v4.2.0/configuring-ember/disabling-prototype-extensions/) from Official Guides and we also need to update the [Tracked Properties](https://guides.emberjs.com/v4.2.0/upgrading/current-edition/tracked-properties/#toc_arrays) `Arrays` section with updated suggestions. ## Drawbacks - For users relying on Ember array prototype extensions, they will have to refactor their code and use equivalences appropriately. From 26b5b73613f8b34bea464d22d11352b4cb2a1471 Mon Sep 17 00:00:00 2001 From: Hang Li Date: Thu, 28 Apr 2022 18:00:29 -0700 Subject: [PATCH 06/16] Update text/0000-deprecate-array-prototype-extensions.md Co-authored-by: Chris Krycho --- text/0000-deprecate-array-prototype-extensions.md | 1 + 1 file changed, 1 insertion(+) diff --git a/text/0000-deprecate-array-prototype-extensions.md b/text/0000-deprecate-array-prototype-extensions.md index e14f56900e..6a24443f33 100644 --- a/text/0000-deprecate-array-prototype-extensions.md +++ b/text/0000-deprecate-array-prototype-extensions.md @@ -138,6 +138,7 @@ After the deprecated code is removed from Ember (at 5.0), we need to remove the - For users relying on Ember array prototype extensions, they will have to refactor their code and use equivalences appropriately. - A lot of existing Ember forums/blogs had been assuming the enabling of array prototype extensions which could cause confusions for users referencing them. - Increase package sizes, for example, before `this.abc.filterBy('x');`, now `this.abc.filter(el => el !== 'x');`. +- Although `tracked-built-ins` is on the path to stabilization as an official API via [RFC #812](https://github.com/emberjs/rfcs/pull/812), it is not yet officially recommended and its API may change somewhat between now and stabilization. ## Alternatives - Continuing allowing array prototype extensions but turning the EXTEND_PROTOTYPES off by default. From f9010fa21d9f1c72e61b07ccf8f830461bba447e Mon Sep 17 00:00:00 2001 From: Hang Li Date: Thu, 28 Apr 2022 18:00:42 -0700 Subject: [PATCH 07/16] Update text/0000-deprecate-array-prototype-extensions.md Co-authored-by: Chris Krycho --- text/0000-deprecate-array-prototype-extensions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-deprecate-array-prototype-extensions.md b/text/0000-deprecate-array-prototype-extensions.md index 6a24443f33..8d36679292 100644 --- a/text/0000-deprecate-array-prototype-extensions.md +++ b/text/0000-deprecate-array-prototype-extensions.md @@ -29,7 +29,7 @@ Continuing in that direction, we should consider recommending the usage of nativ For convenient methods like `without`, `sortBy`, `uniqBy` etc., the replacement functionality already exists either through generic array functions or utility libraries like [lodash](https://lodash.com), [Ramda](https://ramdajs.com), etc. -For helper functions participating in the Ember classic reactivity system like `pushObject`, `removeObject`, the replacement functionality also already exists in the form of immutable update style with tracked propreties like `@tracked someArray = []`, or through utilizing `TrackedArray` from `tracked-built-ins`. +For helper functions participating in the Ember classic reactivity system like `pushObject`, `removeObject`, the replacement functionality also already exists in the form of immutable update style with tracked properties like `@tracked someArray = []`, or through utilizing `TrackedArray` from `tracked-built-ins`. During transition, we still allow users to use `A` from `@ember/array`. From 6823f5a619e98d75965ccce1633327c438c9697a Mon Sep 17 00:00:00 2001 From: hanli Date: Wed, 4 May 2022 23:14:11 -0700 Subject: [PATCH 08/16] Update deprecation guide and unresolved questions --- ...00-deprecate-array-prototype-extensions.md | 37 ++++++++++++------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/text/0000-deprecate-array-prototype-extensions.md b/text/0000-deprecate-array-prototype-extensions.md index 8d36679292..8bda4c337b 100644 --- a/text/0000-deprecate-array-prototype-extensions.md +++ b/text/0000-deprecate-array-prototype-extensions.md @@ -1,6 +1,6 @@ --- Stage: Initial -Start Date: 2022-4-01 +Start Date: 2022-5-01 Release Date: Unreleased Release Versions: ember-source: vX.Y.Z @@ -23,27 +23,26 @@ Those convenient methods increase the likelihood of becoming potential roadblock We had deprecated [Functions](https://github.com/emberjs/rfcs/blob/master/text/0272-deprecation-native-function-prototype-extensions.md) and [Strings](https://github.com/emberjs/rfcs/blob/master/text/0236-deprecation-ember-string.md) prototype extensions. Array is the last step. And internally we had already been preferring generic array methods over prototype extensions ([epic](https://github.com/emberjs/ember.js/issues/15501)). -Continuing in that direction, we should consider recommending the usage of native array functions as opposed to convenient prototype extension functions, and the usage of new tracked properties or `TrackedArray` over classic reactivity methods. +Continuing in that direction, we should consider recommending the usage of native array functions as opposed to convenient prototype extension methods, and the usage of `@tracked` properties or `TrackedArray` over classic reactivity methods. ## Transition Path -For convenient methods like `without`, `sortBy`, `uniqBy` etc., the replacement functionality already exists either through generic array functions or utility libraries like [lodash](https://lodash.com), [Ramda](https://ramdajs.com), etc. +For convenient methods like `without`, `sortBy`, `uniqBy` etc., the replacement functionalities already exist either through native array methods or utility libraries like [lodash](https://lodash.com), [Ramda](https://ramdajs.com), etc. -For helper functions participating in the Ember classic reactivity system like `pushObject`, `removeObject`, the replacement functionality also already exists in the form of immutable update style with tracked properties like `@tracked someArray = []`, or through utilizing `TrackedArray` from `tracked-built-ins`. - -During transition, we still allow users to use `A` from `@ember/array`. +For mutation methods (like `pushObject`, `removeObject`) or observable properties (like `firstObject`, `lastObject`) participating in the Ember classic reactivity system, the replacement functionalities also already exist in the form of immutable update style with tracked properties like `@tracked someArray = []`, or through utilizing `TrackedArray` from `tracked-built-ins`. We don't need to build anything new specifically, however, the bulk of the transition will be -focused on deprecating the array prototype extensions. +focused on deprecating the existing usages of array prototype extensions. ## How We Teach This -An entry to the [Deprecation Guides](https://deprecations.emberjs.com/v4.x) will be added outlining the different recommended transition strategies. +An entry to the [Deprecation Guides](https://deprecations.emberjs.com/v4.x) will be added outlining the different recommended transition strategies. (WIP [Deprecation Guide](https://github.com/smilland/rfcs/pull/1)) -Rule `ember/no-array-prototype-extensions` is available for both [eslint](https://github.com/ember-cli/eslint-plugin-ember/blob/master/docs/rules/no-array-prototype-extensions.md) and [template lint](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/no-array-prototype-extensions.md). Rule examples have recommendations for equivalences. +Rule `ember/no-array-prototype-extensions` is available for both [eslint](https://github.com/ember-cli/eslint-plugin-ember/blob/master/docs/rules/no-array-prototype-extensions.md) and [template lint](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/no-array-prototype-extensions.md) usages. Rule examples have recommendations for equivalences. We can leverage the fixers of lint rule to auto fix some of the issues. We will also create codemods to help with this migration. +Examples (taken from [Deprecation Guide](https://github.com/smilland/rfcs/pull/1)): ### Convenient methods Examples of deprecated and current code: ```js @@ -70,7 +69,7 @@ export default class SampleComponent extends Component{ }; ``` -### Observable based methods +### Observable based methods and properties in js Examples of deprecated code: ```js import Component from '@glimmer/component'; @@ -79,8 +78,14 @@ import { action } from '@ember/object'; export default class SampleComponent extends Component{ abc = []; + // observable property + get lastObj() { + return this.abc.lastObject; + } + @action someAction(newItem) { + // observable method this.abc.pushObject('1'); } }; @@ -96,6 +101,10 @@ import { tracked } from '@glimmer/tracking'; export default class SampleComponent extends Component{ @tracked abc = []; + get lastObj() { + return this.abc.at(-1); + } + @action someAction(newItem) { this.abc = [...abc, newItem]; @@ -113,6 +122,10 @@ import { TrackedArray } from 'tracked-built-ins'; export default class SampleComponent extends Component{ @tracked abc = new TrackedArray(); + get lastObj() { + return this.abc.at(-1); + } + @action someAction(newItem) { abc.push(newItem); @@ -120,7 +133,7 @@ export default class SampleComponent extends Component{ }; ``` -### Properties in templates +### Observable properties in templates Examples of deprecated code: ```hbs @@ -146,5 +159,3 @@ After the deprecated code is removed from Ember (at 5.0), we need to remove the ### Unresolved questions - Some methods like `removeObject`, `removeObjects` that have non-trival logics might require custom helper function in application to ease the migration. -- `replace` method is one of ember array extensions but also be string native proptypes, which adds uncertainty for lint rules and can cause issues during the deprecation. -- Shall we deprecate `Ember.A()` as well or still allowing users to use it? From 9d471fad1c468156db8d0336d0f060d54eba2f7c Mon Sep 17 00:00:00 2001 From: hanli Date: Tue, 21 Jun 2022 21:52:50 -0700 Subject: [PATCH 09/16] Update some examples Please enter the commit message for your changes. Lines starting --- ...00-deprecate-array-prototype-extensions.md | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/text/0000-deprecate-array-prototype-extensions.md b/text/0000-deprecate-array-prototype-extensions.md index 8bda4c337b..f9a530eef8 100644 --- a/text/0000-deprecate-array-prototype-extensions.md +++ b/text/0000-deprecate-array-prototype-extensions.md @@ -1,6 +1,6 @@ --- Stage: Initial -Start Date: 2022-5-01 +Start Date: 2022-6-21 Release Date: Unreleased Release Versions: ember-source: vX.Y.Z @@ -27,7 +27,7 @@ Continuing in that direction, we should consider recommending the usage of nativ ## Transition Path -For convenient methods like `without`, `sortBy`, `uniqBy` etc., the replacement functionalities already exist either through native array methods or utility libraries like [lodash](https://lodash.com), [Ramda](https://ramdajs.com), etc. +For convenient methods like `filterBy`, `compact`, `sortBy` etc., the replacement functionalities already exist either through native array methods or utility libraries like [lodash](https://lodash.com), [Ramda](https://ramdajs.com), etc. For mutation methods (like `pushObject`, `removeObject`) or observable properties (like `firstObject`, `lastObject`) participating in the Ember classic reactivity system, the replacement functionalities also already exist in the form of immutable update style with tracked properties like `@tracked someArray = []`, or through utilizing `TrackedArray` from `tracked-built-ins`. @@ -49,11 +49,11 @@ Examples of deprecated and current code: import Component from '@glimmer/component'; import { uniqBy, sortBy } from 'lodash'; -export default class SampleComponent extends Component{ - abc = ['x', 'y', 'z', 'x']; +export default class SampleComponent extends Component { + abc = ['x', 'y', 'z', undefined, 'x']; // deprecated - def = this.abc.without('x'); + def = this.abc.compact(); ghi = this.abc.uniq(); jkl = this.abc.toArray(); mno = this.abc.uniqBy('y'); @@ -61,15 +61,20 @@ export default class SampleComponent extends Component{ // ... // current - def = this.abc.filter(el => el !== 'x'); + // compact + def = this.abc.filter(el => el !== null && el !== undefined); + // uniq ghi = [...new Set(this.abc)]; + // toArray jkl = [...this.abc]; + // uniqBy mno = uniqBy(this.abc, 'y'); + // sortBy pqr = sortBy(this.abc, 'z'); }; ``` -### Observable based methods and properties in js +### Observable properties and methods in js Examples of deprecated code: ```js import Component from '@glimmer/component'; @@ -86,13 +91,13 @@ export default class SampleComponent extends Component{ @action someAction(newItem) { // observable method - this.abc.pushObject('1'); + this.abc.pushObject(newItem); } }; ``` Examples of current code. -#### Option 1: tracked properties +#### Option 1: use `tracked` property ```js import Component from '@glimmer/component'; import { action } from '@ember/object'; @@ -112,15 +117,14 @@ export default class SampleComponent extends Component{ }; ``` -#### Option 2: `TrackedArray` +#### Option 2: use `TrackedArray` ```js import Component from '@glimmer/component'; import { action } from '@ember/object'; -import { tracked } from '@glimmer/tracking'; import { TrackedArray } from 'tracked-built-ins'; export default class SampleComponent extends Component{ - @tracked abc = new TrackedArray(); + abc = new TrackedArray(); get lastObj() { return this.abc.at(-1); @@ -140,7 +144,7 @@ Examples of deprecated code: ``` -Examples of current code. +Examples of current code: ```hbs ``` @@ -156,6 +160,3 @@ After the deprecated code is removed from Ember (at 5.0), we need to remove the ## Alternatives - Continuing allowing array prototype extensions but turning the EXTEND_PROTOTYPES off by default. - Do nothing. - -### Unresolved questions -- Some methods like `removeObject`, `removeObjects` that have non-trival logics might require custom helper function in application to ease the migration. From 3117290b0e903e5aae7dbb19dbfbb1ff9381aa25 Mon Sep 17 00:00:00 2001 From: Hang Li Date: Mon, 15 Aug 2022 17:25:51 -0700 Subject: [PATCH 10/16] Update text/0000-deprecate-array-prototype-extensions.md Co-authored-by: Chris Krycho --- text/0000-deprecate-array-prototype-extensions.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/text/0000-deprecate-array-prototype-extensions.md b/text/0000-deprecate-array-prototype-extensions.md index f9a530eef8..1401dd093b 100644 --- a/text/0000-deprecate-array-prototype-extensions.md +++ b/text/0000-deprecate-array-prototype-extensions.md @@ -158,5 +158,12 @@ After the deprecated code is removed from Ember (at 5.0), we need to remove the - Although `tracked-built-ins` is on the path to stabilization as an official API via [RFC #812](https://github.com/emberjs/rfcs/pull/812), it is not yet officially recommended and its API may change somewhat between now and stabilization. ## Alternatives -- Continuing allowing array prototype extensions but turning the EXTEND_PROTOTYPES off by default. +- Do the deprecation as suggested here for use within Ember itself, but extract it as a standalone library for users who want to use it. This will only work as long as the underlying Ember Classic reactivity system is supported. + + As a variation on this, we could do this but explicitly only support it up through the first LTS release in the 5.x series. + +- Continuing allowing array prototype extensions but turning the `EXTEND_PROTOTYPES` off by default. + +- Do one of these, but target Ember v6 instead. + - Do nothing. From bb91b2869ff43d40c2fc3a2fad4911c0d75f4f8e Mon Sep 17 00:00:00 2001 From: hanli Date: Tue, 30 Aug 2022 10:43:43 -0700 Subject: [PATCH 11/16] Add unresolved questions --- text/0000-deprecate-array-prototype-extensions.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/text/0000-deprecate-array-prototype-extensions.md b/text/0000-deprecate-array-prototype-extensions.md index 1401dd093b..5bdc948666 100644 --- a/text/0000-deprecate-array-prototype-extensions.md +++ b/text/0000-deprecate-array-prototype-extensions.md @@ -1,6 +1,6 @@ --- Stage: Initial -Start Date: 2022-6-21 +Start Date: 2022-8-21 Release Date: Unreleased Release Versions: ember-source: vX.Y.Z @@ -40,7 +40,9 @@ An entry to the [Deprecation Guides](https://deprecations.emberjs.com/v4.x) will Rule `ember/no-array-prototype-extensions` is available for both [eslint](https://github.com/ember-cli/eslint-plugin-ember/blob/master/docs/rules/no-array-prototype-extensions.md) and [template lint](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/no-array-prototype-extensions.md) usages. Rule examples have recommendations for equivalences. -We can leverage the fixers of lint rule to auto fix some of the issues. We will also create codemods to help with this migration. +We can leverage the fixers of lint rule to auto fix some of the issues, e.g. the built-in [fixer](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/no-array-prototype-extensions.md) of `firstObject` usages in template. + +We also should create codemods or autofixers in lint rules for some of the convinient functions like `reject`, `compact`, `any` etc. Examples (taken from [Deprecation Guide](https://github.com/smilland/rfcs/pull/1)): ### Convenient methods @@ -167,3 +169,10 @@ After the deprecated code is removed from Ember (at 5.0), we need to remove the - Do one of these, but target Ember v6 instead. - Do nothing. + +## Unresolved questions +- Current lint rule [ember/no-array-prototype-extensions](https://github.com/ember-cli/eslint-plugin-ember/blob/master/docs/rules/no-array-prototype-extensions.md) gives a lot of false positives giving the limitation of static analysis. +- Difficulties for providing stable codemods or autofixers: + 1. giving false positives on lint rules, same will apply to codemods or autofixers; + 2. when migrating certain methods, we need to access object. Shall we use Ember `get` or native way? Unless we fully remove ObjectProxy dependency, codemods or autofixers would still require manual work in certain cases. + 3. observable functions or properties requires manual refactoring; From fa8b6d298a27d9c41d08e2f790c824972f33cc9c Mon Sep 17 00:00:00 2001 From: hanli Date: Tue, 30 Aug 2022 10:45:13 -0700 Subject: [PATCH 12/16] Add reference for unresolved questions --- text/0000-deprecate-array-prototype-extensions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-deprecate-array-prototype-extensions.md b/text/0000-deprecate-array-prototype-extensions.md index 5bdc948666..7ef55ad358 100644 --- a/text/0000-deprecate-array-prototype-extensions.md +++ b/text/0000-deprecate-array-prototype-extensions.md @@ -42,7 +42,7 @@ Rule `ember/no-array-prototype-extensions` is available for both [eslint](https: We can leverage the fixers of lint rule to auto fix some of the issues, e.g. the built-in [fixer](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/no-array-prototype-extensions.md) of `firstObject` usages in template. -We also should create codemods or autofixers in lint rules for some of the convinient functions like `reject`, `compact`, `any` etc. +We also should create codemods or autofixers in lint rules for some of the convinient functions like `reject`, `compact`, `any` etc. More discussions on **Unresolved Questions** section. Examples (taken from [Deprecation Guide](https://github.com/smilland/rfcs/pull/1)): ### Convenient methods From caf515f0bbb50578ebd1c7afff35935ae78da67b Mon Sep 17 00:00:00 2001 From: hanli Date: Wed, 31 Aug 2022 22:53:10 -0700 Subject: [PATCH 13/16] Update deprecation guide PR link --- text/0000-deprecate-array-prototype-extensions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-deprecate-array-prototype-extensions.md b/text/0000-deprecate-array-prototype-extensions.md index 7ef55ad358..2e892bc3c4 100644 --- a/text/0000-deprecate-array-prototype-extensions.md +++ b/text/0000-deprecate-array-prototype-extensions.md @@ -36,7 +36,7 @@ focused on deprecating the existing usages of array prototype extensions. ## How We Teach This -An entry to the [Deprecation Guides](https://deprecations.emberjs.com/v4.x) will be added outlining the different recommended transition strategies. (WIP [Deprecation Guide](https://github.com/smilland/rfcs/pull/1)) +An entry to the [Deprecation Guides](https://deprecations.emberjs.com/v4.x) will be added outlining the different recommended transition strategies. ([Proposed deprecation guide](https://github.com/ember-learn/deprecation-app/pull/1192)) Rule `ember/no-array-prototype-extensions` is available for both [eslint](https://github.com/ember-cli/eslint-plugin-ember/blob/master/docs/rules/no-array-prototype-extensions.md) and [template lint](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/no-array-prototype-extensions.md) usages. Rule examples have recommendations for equivalences. From 11ca5d21b8304cdc5e34b0b66939594f793859a0 Mon Sep 17 00:00:00 2001 From: hanli Date: Mon, 5 Sep 2022 21:01:32 -0700 Subject: [PATCH 14/16] Addressing notes/comments --- text/0000-deprecate-array-prototype-extensions.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/text/0000-deprecate-array-prototype-extensions.md b/text/0000-deprecate-array-prototype-extensions.md index 2e892bc3c4..eb13ec22a3 100644 --- a/text/0000-deprecate-array-prototype-extensions.md +++ b/text/0000-deprecate-array-prototype-extensions.md @@ -36,6 +36,10 @@ focused on deprecating the existing usages of array prototype extensions. ## How We Teach This +We should turn off `EmberENV.EXTEND_PROTOTYPES` by default for new applications. + +For existing apps, a deprecation message will be displayed when `EmberENV.EXTEND_PROTOTYPES` flag is not set to `false`. Clear instructions will be provided about turning off the flag and fixing any existing breaks. + An entry to the [Deprecation Guides](https://deprecations.emberjs.com/v4.x) will be added outlining the different recommended transition strategies. ([Proposed deprecation guide](https://github.com/ember-learn/deprecation-app/pull/1192)) Rule `ember/no-array-prototype-extensions` is available for both [eslint](https://github.com/ember-cli/eslint-plugin-ember/blob/master/docs/rules/no-array-prototype-extensions.md) and [template lint](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/no-array-prototype-extensions.md) usages. Rule examples have recommendations for equivalences. From b49ddc39508bab6c6d04112dec54a5e01c378ceb Mon Sep 17 00:00:00 2001 From: Hang Li Date: Mon, 5 Sep 2022 21:02:10 -0700 Subject: [PATCH 15/16] Update text/0000-deprecate-array-prototype-extensions.md Co-authored-by: Bryan Mishkin <698306+bmish@users.noreply.github.com> --- text/0000-deprecate-array-prototype-extensions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-deprecate-array-prototype-extensions.md b/text/0000-deprecate-array-prototype-extensions.md index eb13ec22a3..ffdf72be3b 100644 --- a/text/0000-deprecate-array-prototype-extensions.md +++ b/text/0000-deprecate-array-prototype-extensions.md @@ -175,7 +175,7 @@ After the deprecated code is removed from Ember (at 5.0), we need to remove the - Do nothing. ## Unresolved questions -- Current lint rule [ember/no-array-prototype-extensions](https://github.com/ember-cli/eslint-plugin-ember/blob/master/docs/rules/no-array-prototype-extensions.md) gives a lot of false positives giving the limitation of static analysis. +- The current lint rule [ember/no-array-prototype-extensions](https://github.com/ember-cli/eslint-plugin-ember/blob/master/docs/rules/no-array-prototype-extensions.md) has some false positives because static analysis can't always know when a given object is a native array vs. an `EmberArray` (which has the same array convenience methods) vs. another class with overlapping method names (although the rule does employ some heuristics to avoid false positives when possible). - Difficulties for providing stable codemods or autofixers: 1. giving false positives on lint rules, same will apply to codemods or autofixers; 2. when migrating certain methods, we need to access object. Shall we use Ember `get` or native way? Unless we fully remove ObjectProxy dependency, codemods or autofixers would still require manual work in certain cases. From 734fa12241674cca56ea7a3b30b6eb027ebde752 Mon Sep 17 00:00:00 2001 From: Hang Li Date: Fri, 30 Sep 2022 14:17:49 -0700 Subject: [PATCH 16/16] Formats RFC --- ...848-deprecate-array-prototype-extensions.md} | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) rename text/{0000-deprecate-array-prototype-extensions.md => 0848-deprecate-array-prototype-extensions.md} (97%) diff --git a/text/0000-deprecate-array-prototype-extensions.md b/text/0848-deprecate-array-prototype-extensions.md similarity index 97% rename from text/0000-deprecate-array-prototype-extensions.md rename to text/0848-deprecate-array-prototype-extensions.md index ffdf72be3b..741c76c34e 100644 --- a/text/0000-deprecate-array-prototype-extensions.md +++ b/text/0848-deprecate-array-prototype-extensions.md @@ -1,12 +1,13 @@ --- -Stage: Initial -Start Date: 2022-8-21 -Release Date: Unreleased -Release Versions: - ember-source: vX.Y.Z - ember-data: vX.Y.Z -Relevant Team(s): Ember.js -RFC PR: +stage: accepted +start-date: 2022-08-21T00:00:00.000Z +release-date: +release-versions: +teams: + - framework +prs: + accepted: https://github.com/emberjs/rfcs/pull/848 +project-link: --- # Deprecate array prototype extensions