From 25eb73bb74a5691b52f187096c8cb6106fd71b59 Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Sat, 13 Oct 2018 12:20:35 +0200 Subject: [PATCH 1/9] Add rfc to move some popular truth-helpers to core --- text/0000-basic-template-helpers.md | 86 +++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 text/0000-basic-template-helpers.md diff --git a/text/0000-basic-template-helpers.md b/text/0000-basic-template-helpers.md new file mode 100644 index 0000000000..a7b50a8d26 --- /dev/null +++ b/text/0000-basic-template-helpers.md @@ -0,0 +1,86 @@ +- Start Date: 2018-10-13 +- RFC PR: (leave this empty) +- Ember Issue: (leave this empty) + +# (RFC title goes here) + +## Summary + +Add new built-in template helpers to perform basic operations in templates, identical to the +helpers in [ember-truth-helpers](https://github.com/jmurphyau/ember-truth-helpers) + +## Motivation + +It is a very common necessity to almost every Ember app to perform certain operations like compare +by equality, negate a value, or perform boolean operations, and often the most convenient place to +do it is in the templates. +Because of that, `ember-truth-helpers` is probably the single most installed addon either directly +or transitively in the entire ecosystem. + +The fact that this addon is so popular is very telling and Ember should consider to move into the +core of the templating engine at least the most popular helpers. + +One of the shocking moments developers that are familiar with React, Vue or Angular have when trying Ember +is that they cannot, at least out of the box, perform the most basic comparisons and boolean operations +they are so used to in JSX or Vue/Angular templates. + +Furthermore, if the [RFC #367](https://github.com/emberjs/rfcs/pull/367) eventually gets merged, these +helpers are the perfect candidates to create adoption friction in the community because of how +pervasive its usage it in so many templates. + +Albeit less important, implementing these helpers in the core _could_ enable clever trickery in the +Glimmer VM, like evaluating them at compile time when the arguments are constant. + +## Detailed design + +The process consists on deciding what helpers from `ember-truth-helpers` we consider the most important +and move them into Ember.js itself or even the Glimmer VM, in a fully backwards compatible way. + +I propose to move to core at least: + +- `eq` +- `not` +- `and` +- `or` +- `gt` and `gte` +- `lt` and `lte` + +Those helpers are very low lever and generally useful in both Ember and Glimmer. + +I propose to not move: + +- `is-array` (uses `Ember.isArray`) +- `is-empty` (uses `Ember.isEmpty`) +- `is-equal` (uses `Ember.isEqual`) +- `xor` (not very common) +- `not-eq` (can be expressed as `(not (eq a b)`) + +When this feature is implemented, we would update `ember-truth-helpers` to not ship the helpers that +were moved into the core if the version of Ember is + +## How we teach this + +As any new API, will have to be documented in the guides with examples. + +## Drawbacks + +We are increasing the public API of the framework, and every line of code is a liability, although +those helpers are extremely straightforward. + +## Alternatives + +An alternative path would be to include `ember-truth-helpers` in the default blueprint for apps an +addons. + +## Unresolved questions + +The main unresolved question is what helpers we deem worthy of being moved into the core, and also +if we want any other helpers not mentioned above. + +Other helpers that come to mind that _could_ also be worth adding: + +- `array` (there is an RFC for it: https://github.com/emberjs/rfcs/pull/318) +- `add`, `subtract`, and other arithmetic operators. +- `{{#await promise as |value|}}` to render a block conditionally if a promise resolves or fails. + +If there is interest in them, I advocate creating standalone RFCS for them. \ No newline at end of file From 3da4af276c7b1767431ae89a830142aca4c79ce8 Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Sat, 13 Oct 2018 22:25:57 +0200 Subject: [PATCH 2/9] Apply some feedback --- text/0000-basic-template-helpers.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text/0000-basic-template-helpers.md b/text/0000-basic-template-helpers.md index a7b50a8d26..0641ad557a 100644 --- a/text/0000-basic-template-helpers.md +++ b/text/0000-basic-template-helpers.md @@ -2,7 +2,7 @@ - RFC PR: (leave this empty) - Ember Issue: (leave this empty) -# (RFC title goes here) +# Promote helpers from ember-truth-helpers into Ember ## Summary @@ -55,8 +55,8 @@ I propose to not move: - `xor` (not very common) - `not-eq` (can be expressed as `(not (eq a b)`) -When this feature is implemented, we would update `ember-truth-helpers` to not ship the helpers that -were moved into the core if the version of Ember is +When this feature is implemented, we would update `ember-truth-helpers` to automatically remove +the promoted helpers from the code when the Ember is above a certain version number. ## How we teach this From 575dfc1b38d07ba8315320165907cb9e4985128a Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Sun, 14 Oct 2018 11:38:44 +0200 Subject: [PATCH 3/9] Reextructure motivation and mention the importance of lazy argument evaluation --- text/0000-basic-template-helpers.md | 67 +++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 17 deletions(-) diff --git a/text/0000-basic-template-helpers.md b/text/0000-basic-template-helpers.md index 0641ad557a..bc709efefe 100644 --- a/text/0000-basic-template-helpers.md +++ b/text/0000-basic-template-helpers.md @@ -7,29 +7,58 @@ ## Summary Add new built-in template helpers to perform basic operations in templates, identical to the -helpers in [ember-truth-helpers](https://github.com/jmurphyau/ember-truth-helpers) +helpers in [ember-truth-helpers](https://github.com/jmurphyau/ember-truth-helpers). + +This is a resurrection of [RFC #152](https://github.com/emberjs/rfcs/pull/152) that was opened over +by @martndemus two years ago, updated to reflect the new start of the things in Ember, with the glimmer +VM powering our templates. ## Motivation It is a very common necessity to almost every Ember app to perform certain operations like compare -by equality, negate a value, or perform boolean operations, and often the most convenient place to -do it is in the templates. -Because of that, `ember-truth-helpers` is probably the single most installed addon either directly -or transitively in the entire ecosystem. +by equality, negate a value or perform boolean operations, and often the most convenient place to +do it is right in the templates. +Because of that, `ember-truth-helpers` is probably the single most installed addon that exists, either +directly by apps or indirectly by other addons that those apps use. + +The fact that this addon is so popular is very telling and Ember.js should consider moving into the +core of the templating engine at least some of those helpers. + +A second reason is that I believe it would help making Ember more approachable by newcomers +that have _some_ experience in other frameworks. One of the most shocking moments that developers +that are familiar with React, Vue or Angular experience when trying Ember is that they cannot, +at least out of the box, perform the most basic logical comparisons and operation they are so used to +in JSX or Vue/Angular templates. + +A third reason is that if we implement those super common helpers in the Glimmer VM, that would open +a important vector of low level optimization. -The fact that this addon is so popular is very telling and Ember should consider to move into the -core of the templating engine at least the most popular helpers. +Consider the following template: -One of the shocking moments developers that are familiar with React, Vue or Angular have when trying Ember -is that they cannot, at least out of the box, perform the most basic comparisons and boolean operations -they are so used to in JSX or Vue/Angular templates. +```hbs +{{#if (and @featureEnabled this.expensiveComputedProperty @model.asyncEDRelationship.length)}} + {{!-- some logic --}} +{{else}} + {{!-- some logic --}} -Furthermore, if the [RFC #367](https://github.com/emberjs/rfcs/pull/367) eventually gets merged, these -helpers are the perfect candidates to create adoption friction in the community because of how -pervasive its usage it in so many templates. +{{/if}} +``` -Albeit less important, implementing these helpers in the core _could_ enable clever trickery in the -Glimmer VM, like evaluating them at compile time when the arguments are constant. +Because of the way Ember helpers work, all their input parameters are eagerly evaluated by the +Glimmer VM and passed to the helpers. This might include computationally expensive computed properties, +or hitting code paths that trigger network requests. + +Implementing helpers like `and` or `or` at a lower lever would allow those helpers to be evaluated in +short circuit, so if `@featureEnabled` is false, neither of the following arguments will ever evaluated. + +Going one step further into the optimizing compiler world, if **every** invocation of the component +with this template receives `@featureEnabled={{false}}`, the compiler could even completely remove +the conditional and the truthy branch of the if from compiled output. + +The last reason is that if the [RFC #367](https://github.com/emberjs/rfcs/pull/367) eventually gets merged, +these helpers are the perfect candidates to create adoption friction in the community because of how +pervasive its usage it in so many templates, forcing them to explicitly importing them on most templates +or adding them to the proposed `prelude.hbs` file. ## Detailed design @@ -77,10 +106,14 @@ addons. The main unresolved question is what helpers we deem worthy of being moved into the core, and also if we want any other helpers not mentioned above. +In particular, I'm sitting on the fence about `not-eq`. +It is not _really necessary_, in the same way `{{unless foo}}` can also be expressed as `{{#if (not foo)}}`, +but it may be convenient. + Other helpers that come to mind that _could_ also be worth adding: -- `array` (there is an RFC for it: https://github.com/emberjs/rfcs/pull/318) +- `array` (there is an [RFC](https://github.com/emberjs/rfcs/pull/318) and its being implemented) - `add`, `subtract`, and other arithmetic operators. - `{{#await promise as |value|}}` to render a block conditionally if a promise resolves or fails. -If there is interest in them, I advocate creating standalone RFCS for them. \ No newline at end of file +If there is interest in them, I advocate creating standalone RFCS for each one of them. \ No newline at end of file From 6b7d5094d37f676ad4a5ba068036b6fce7c1e92c Mon Sep 17 00:00:00 2001 From: Ricardo Mendes Date: Mon, 15 Oct 2018 03:03:11 +0100 Subject: [PATCH 4/9] Update 0000-basic-template-helpers.md --- text/0000-basic-template-helpers.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/text/0000-basic-template-helpers.md b/text/0000-basic-template-helpers.md index bc709efefe..6acba7f492 100644 --- a/text/0000-basic-template-helpers.md +++ b/text/0000-basic-template-helpers.md @@ -89,7 +89,10 @@ the promoted helpers from the code when the Ember is above a certain version num ## How we teach this -As any new API, will have to be documented in the guides with examples. +The introduction of these helpers does not impact the current mental model for Ember applications. + +In addition to API and Guides documentation with illustrative examples of usage of the various helpers, +and explanation of their short circuiting nature might be warranted. ## Drawbacks @@ -98,8 +101,10 @@ those helpers are extremely straightforward. ## Alternatives -An alternative path would be to include `ember-truth-helpers` in the default blueprint for apps an +An alternative path would be to include `ember-truth-helpers` in the default blueprint for apps and addons. +However, this alternative loses strength due to the fact that it is not possible to implement short +circuiting helpers in Ember's userspace. ## Unresolved questions @@ -116,4 +121,4 @@ Other helpers that come to mind that _could_ also be worth adding: - `add`, `subtract`, and other arithmetic operators. - `{{#await promise as |value|}}` to render a block conditionally if a promise resolves or fails. -If there is interest in them, I advocate creating standalone RFCS for each one of them. \ No newline at end of file +If there is interest in them, I advocate creating standalone RFCS for each one of them. From 298e77fcf92aaa1b66adb8a703045c3dc14125c5 Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Mon, 15 Oct 2018 10:29:03 +0200 Subject: [PATCH 5/9] Improve wording --- text/0000-basic-template-helpers.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/text/0000-basic-template-helpers.md b/text/0000-basic-template-helpers.md index 6acba7f492..ea5800bd79 100644 --- a/text/0000-basic-template-helpers.md +++ b/text/0000-basic-template-helpers.md @@ -2,11 +2,11 @@ - RFC PR: (leave this empty) - Ember Issue: (leave this empty) -# Promote helpers from ember-truth-helpers into Ember +# Add new basic template helpers to Ember ## Summary -Add new built-in template helpers to perform basic operations in templates, identical to the +Add new built-in template helpers to perform basic boolean operations and comparisons in templates, identical to some of the helpers in [ember-truth-helpers](https://github.com/jmurphyau/ember-truth-helpers). This is a resurrection of [RFC #152](https://github.com/emberjs/rfcs/pull/152) that was opened over @@ -39,8 +39,7 @@ Consider the following template: {{#if (and @featureEnabled this.expensiveComputedProperty @model.asyncEDRelationship.length)}} {{!-- some logic --}} {{else}} - {{!-- some logic --}} - + {{!-- some other logic --}} {{/if}} ``` @@ -65,7 +64,7 @@ or adding them to the proposed `prelude.hbs` file. The process consists on deciding what helpers from `ember-truth-helpers` we consider the most important and move them into Ember.js itself or even the Glimmer VM, in a fully backwards compatible way. -I propose to move to core at least: +I propose to add to core at least: - `eq` - `not` @@ -76,7 +75,7 @@ I propose to move to core at least: Those helpers are very low lever and generally useful in both Ember and Glimmer. -I propose to not move: +I propose to not add: - `is-array` (uses `Ember.isArray`) - `is-empty` (uses `Ember.isEmpty`) @@ -104,7 +103,8 @@ those helpers are extremely straightforward. An alternative path would be to include `ember-truth-helpers` in the default blueprint for apps and addons. However, this alternative loses strength due to the fact that it is not possible to implement short -circuiting helpers in Ember's userspace. +circuiting helpers in Ember's userspace, and because even if an addon is added by default, user +can still choose to remove it, so addons would not just be able to rely on them. ## Unresolved questions From c1172ff49cc734c77a633dc4a619deeaf28fa05c Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Mon, 5 Nov 2018 15:32:17 +0100 Subject: [PATCH 6/9] Add `{{not-eq}}` to the list of helpers --- text/0000-basic-template-helpers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-basic-template-helpers.md b/text/0000-basic-template-helpers.md index ea5800bd79..2908132b31 100644 --- a/text/0000-basic-template-helpers.md +++ b/text/0000-basic-template-helpers.md @@ -67,6 +67,7 @@ and move them into Ember.js itself or even the Glimmer VM, in a fully backwards I propose to add to core at least: - `eq` +- `not-eq` - `not` - `and` - `or` @@ -81,7 +82,6 @@ I propose to not add: - `is-empty` (uses `Ember.isEmpty`) - `is-equal` (uses `Ember.isEqual`) - `xor` (not very common) -- `not-eq` (can be expressed as `(not (eq a b)`) When this feature is implemented, we would update `ember-truth-helpers` to automatically remove the promoted helpers from the code when the Ember is above a certain version number. From eb6810ab7bcf9577e9366cd5fea998440afac3ad Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Tue, 6 Nov 2018 23:55:25 +0100 Subject: [PATCH 7/9] Update detailed implementation with arity and other details of each helper --- text/0000-basic-template-helpers.md | 55 +++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/text/0000-basic-template-helpers.md b/text/0000-basic-template-helpers.md index 2908132b31..cce52e0675 100644 --- a/text/0000-basic-template-helpers.md +++ b/text/0000-basic-template-helpers.md @@ -86,6 +86,61 @@ I propose to not add: When this feature is implemented, we would update `ember-truth-helpers` to automatically remove the promoted helpers from the code when the Ember is above a certain version number. +The implementation details of each helper: + +#### `{{not}}` + +- Unary operation. Throws an error if not called with **exactly** one argument. +- Equivalent of `!` + +#### `{{eq}}` + +- Binary operation. Throws an error if not called with **exactly** two arguments. +- Equivalent of ` === ` + +#### `{{not-eq}}` + +- Binary operation. Throws an error if not called with **exactly** two arguments. +- Equivalent of ` !== ` + +#### `{{gt}}` + +- Binary operation. Throws an error if not called with **exactly** two arguments. +- Equivalent of ` > ` +- Lazy: If the first argument is `null` or `undefined`, the second argument is never evaluated + +#### `{{gte}}` + +- Binary operation. Throws an error if not called with **exactly** two arguments. +- Equivalent of ` >= ` +- Lazy: If the first argument is `null` or `undefined`, the second argument is never evaluated + +#### `{{lt}}` + +- Binary operation. Throws an error if not called with **exactly** two arguments. +- Equivalent of ` < ` +- Lazy: If the first argument is `null` or `undefined`, the second argument is never evaluated + +#### `{{lte}}` + +- Binary operation. Throws an error if not called with **exactly** two arguments. +- Equivalent of ` <= ` +- Lazy: If the first argument is `null` or `undefined`, the second argument is never evaluated + +#### `{{and}}` + +- Binary or greater operation. Throws an error if called with **less than** two arguments. +- Equivalent of ` && && ... && `. That means it returns the last truthy value or the first falsy value. +- Definition of truthiness: The same the `&&` operator has in javascript. +- Lazy: It starts evaluating arguments in order and short-circuits as soon as one of them is falsy. + +#### `{{or}}` + +- Binary or greater operation. Throws an error if called with **less than** two arguments. +- Equivalent of ` || || ... || `. That means it returns the first truthy value or the last value. +- Definition of truthiness: The same the `||` operator has in javascript. +- Lazy: It starts evaluating arguments in order and short-circuits as soon as one of them is truthy. + ## How we teach this The introduction of these helpers does not impact the current mental model for Ember applications. From ed7368ead08f433bd8a71f023a1235c7e5e2b845 Mon Sep 17 00:00:00 2001 From: Ricardo Mendes Date: Fri, 25 Jan 2019 02:51:51 +0000 Subject: [PATCH 8/9] Remove array helper mention It is shipped! --- text/0000-basic-template-helpers.md | 1 - 1 file changed, 1 deletion(-) diff --git a/text/0000-basic-template-helpers.md b/text/0000-basic-template-helpers.md index cce52e0675..9e7596f441 100644 --- a/text/0000-basic-template-helpers.md +++ b/text/0000-basic-template-helpers.md @@ -172,7 +172,6 @@ but it may be convenient. Other helpers that come to mind that _could_ also be worth adding: -- `array` (there is an [RFC](https://github.com/emberjs/rfcs/pull/318) and its being implemented) - `add`, `subtract`, and other arithmetic operators. - `{{#await promise as |value|}}` to render a block conditionally if a promise resolves or fails. From b73460a7381fe7521709be8875aa60cff7173898 Mon Sep 17 00:00:00 2001 From: Ricardo Mendes Date: Fri, 25 Jan 2019 02:52:19 +0000 Subject: [PATCH 9/9] Update 0000-basic-template-helpers.md --- text/0000-basic-template-helpers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-basic-template-helpers.md b/text/0000-basic-template-helpers.md index 9e7596f441..f2a54fe001 100644 --- a/text/0000-basic-template-helpers.md +++ b/text/0000-basic-template-helpers.md @@ -1,5 +1,5 @@ - Start Date: 2018-10-13 -- RFC PR: (leave this empty) +- RFC PR: https://github.com/emberjs/rfcs/pull/388 - Ember Issue: (leave this empty) # Add new basic template helpers to Ember