From 16d6724b52732df72fcbc2e3d84098e1578e33a2 Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Sat, 3 Nov 2018 00:37:51 +0100 Subject: [PATCH 01/21] [RFC #338] Implement new template helpers - [x] Implement `{{eq}}` helper - [ ] Implement `{{not}}` helper - [ ] Implement `{{and}}` helper - [ ] Implement `{{or}}` helper - [ ] Implement `{{gt}}` helper - [ ] Implement `{{gt3}}` helper - [ ] Implement `{{lt}}` helper - [ ] Implement `{{lte}}` helper --- .../-internals/glimmer/lib/helpers/eq.ts | 30 ++++++++++ .../@ember/-internals/glimmer/lib/resolver.ts | 2 + .../tests/integration/helpers/eq-test.js | 56 +++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 packages/@ember/-internals/glimmer/lib/helpers/eq.ts create mode 100644 packages/@ember/-internals/glimmer/tests/integration/helpers/eq-test.js diff --git a/packages/@ember/-internals/glimmer/lib/helpers/eq.ts b/packages/@ember/-internals/glimmer/lib/helpers/eq.ts new file mode 100644 index 00000000000..3acb464150b --- /dev/null +++ b/packages/@ember/-internals/glimmer/lib/helpers/eq.ts @@ -0,0 +1,30 @@ +import { Arguments, CapturedArguments, VM } from '@glimmer/runtime'; +import { InternalHelperReference } from '../utils/references'; + +/** +@module ember +*/ + +/** + Compares the two given values with === + + Example: + + ```handlebars + {{eq type "button"}} + + {{! be true if `type` is "button"}} + ``` + + @public + @method eq + @for Ember.Templates.helpers + @since 2.7.0 +*/ +function eq({ positional: { references } }: CapturedArguments) { + return references[0].value() === references[1].value(); +} + +export default function(_vm: VM, args: Arguments) { + return new InternalHelperReference(eq, args.capture()); +} diff --git a/packages/@ember/-internals/glimmer/lib/resolver.ts b/packages/@ember/-internals/glimmer/lib/resolver.ts index 0be90ea2d6a..9f7d21b57b3 100644 --- a/packages/@ember/-internals/glimmer/lib/resolver.ts +++ b/packages/@ember/-internals/glimmer/lib/resolver.ts @@ -31,6 +31,7 @@ import { default as normalizeClassHelper } from './helpers/-normalize-class'; import { default as action } from './helpers/action'; import { default as array } from './helpers/array'; import { default as concat } from './helpers/concat'; +import { default as eq } from './helpers/eq'; import { default as eachIn } from './helpers/each-in'; import { default as get } from './helpers/get'; import { default as hash } from './helpers/hash'; @@ -65,6 +66,7 @@ const BUILTINS_HELPERS = { if: inlineIf, action, concat, + eq, get, hash, array, diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/eq-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/eq-test.js new file mode 100644 index 00000000000..dd1dc6c1e6e --- /dev/null +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/eq-test.js @@ -0,0 +1,56 @@ +import { RenderingTest, moduleFor } from '../../utils/test-case'; +import { set } from '@ember/-internals/metal'; + +moduleFor( + 'Helpers test: {{eq}}', + class extends RenderingTest { + ['@test it compares static arguments that are equal']() { + this.render(`{{eq "foo" "foo"}}`); + this.assertText('true'); + } + + ['@test it compares static arguments that are different']() { + this.render(`{{eq "foo" "bar"}}`); + this.assertText('false'); + } + + ['@test it updates for bound arguments']() { + this.render(`{{eq first second}}`, { first: 'one', second: 'two' }); + + this.assertText('false'); + + this.runTask(() => this.rerender()); + + this.assertText('false'); + + this.runTask(() => set(this.context, 'first', 'two')); + + this.assertText('true'); + + this.runTask(() => set(this.context, 'second', '2')); + + this.assertText('false'); + } + + ['@test it can be used as a sub-expression']() { + this.render(`{{if (eq first second) "equal" "different"}}`, { first: 'one', second: 'two' }); + + this.assertText('different'); + + this.runTask(() => this.rerender()); + + this.assertText('different'); + + this.runTask(() => set(this.context, 'first', 'two')); + + this.assertText('equal'); + + this.runTask(() => { + set(this.context, 'first', '1'); + set(this.context, 'second', '2'); + }); + + this.assertText('different'); + } + } +); From 95925ab07a7047741c1d7a56fd255f9de19e6285 Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Sat, 3 Nov 2018 10:58:32 +0100 Subject: [PATCH 02/21] Implement {{not}} helper --- .../-internals/glimmer/lib/helpers/not.ts | 30 ++++++++++ .../@ember/-internals/glimmer/lib/resolver.ts | 2 + .../tests/integration/helpers/not-test.js | 57 +++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 packages/@ember/-internals/glimmer/lib/helpers/not.ts create mode 100644 packages/@ember/-internals/glimmer/tests/integration/helpers/not-test.js diff --git a/packages/@ember/-internals/glimmer/lib/helpers/not.ts b/packages/@ember/-internals/glimmer/lib/helpers/not.ts new file mode 100644 index 00000000000..41a3823f446 --- /dev/null +++ b/packages/@ember/-internals/glimmer/lib/helpers/not.ts @@ -0,0 +1,30 @@ +import { Arguments, CapturedArguments, VM } from '@glimmer/runtime'; +import { InternalHelperReference } from '../utils/references'; + +/** +@module ember +*/ + +/** + Compares the two given values with === + + Example: + + ```handlebars + {{not disabled}} + + {{! be true if `disabled` is false}} + ``` + + @public + @method not + @for Ember.Templates.helpers + @since 2.7.0 +*/ +function not({ positional: { references } }: CapturedArguments) { + return !references[0].value(); +} + +export default function(_vm: VM, args: Arguments) { + return new InternalHelperReference(not, args.capture()); +} diff --git a/packages/@ember/-internals/glimmer/lib/resolver.ts b/packages/@ember/-internals/glimmer/lib/resolver.ts index 9f7d21b57b3..02c2a9d15fd 100644 --- a/packages/@ember/-internals/glimmer/lib/resolver.ts +++ b/packages/@ember/-internals/glimmer/lib/resolver.ts @@ -32,6 +32,7 @@ import { default as action } from './helpers/action'; import { default as array } from './helpers/array'; import { default as concat } from './helpers/concat'; import { default as eq } from './helpers/eq'; +import { default as not } from './helpers/not'; import { default as eachIn } from './helpers/each-in'; import { default as get } from './helpers/get'; import { default as hash } from './helpers/hash'; @@ -72,6 +73,7 @@ const BUILTINS_HELPERS = { array, log, mut, + not, 'query-params': queryParams, readonly, unbound, diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/not-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/not-test.js new file mode 100644 index 00000000000..c636e393e5d --- /dev/null +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/not-test.js @@ -0,0 +1,57 @@ +import { RenderingTest, moduleFor } from '../../utils/test-case'; +import { set } from '@ember/-internals/metal'; + +moduleFor( + 'Helpers test: {{not}}', + class extends RenderingTest { + ['@test returns true for falsy static arguments']() { + this.render(`{{not false}}`); + this.assertText('true'); + } + + ['@test returns false for truthy static arguments']() { + this.render(`{{not 42}}`); + this.assertText('false'); + } + + ['@test it updates for bound arguments']() { + this.render(`{{not argument}}`, { argument: 0 }); + + this.assertText('true'); + + this.runTask(() => this.rerender()); + + this.assertText('true'); + + this.runTask(() => set(this.context, 'argument', 1)); + + this.assertText('false'); + + this.runTask(() => set(this.context, 'argument', false)); + + this.assertText('true'); + + this.runTask(() => set(this.context, 'argument', 'false')); + + this.assertText('false'); + + this.runTask(() => set(this.context, 'argument', true)); + + this.assertText('false'); + } + + ['@test it can be used as a sub-expression']() { + this.render(`{{if (not disabled) "enabled" "disabled"}}`, { disabled: false }); + + this.assertText('enabled'); + + this.runTask(() => this.rerender()); + + this.assertText('enabled'); + + this.runTask(() => set(this.context, 'disabled', true)); + + this.assertText('disabled'); + } + } +); From 4fecacb743d8a42fbfa60bca1ee38995f29ec46b Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Sun, 4 Nov 2018 00:36:07 +0100 Subject: [PATCH 03/21] Implement `gt` helper It has lazy evaluation of the second argument, so it doesn't even get read if the first argument is already undefined. For now without an option to coerce strings to numbers. --- .../-internals/glimmer/lib/helpers/gt.ts | 38 +++++ .../@ember/-internals/glimmer/lib/resolver.ts | 2 + .../tests/integration/helpers/gt-test.js | 137 ++++++++++++++++++ 3 files changed, 177 insertions(+) create mode 100644 packages/@ember/-internals/glimmer/lib/helpers/gt.ts create mode 100644 packages/@ember/-internals/glimmer/tests/integration/helpers/gt-test.js diff --git a/packages/@ember/-internals/glimmer/lib/helpers/gt.ts b/packages/@ember/-internals/glimmer/lib/helpers/gt.ts new file mode 100644 index 00000000000..b0c3035c465 --- /dev/null +++ b/packages/@ember/-internals/glimmer/lib/helpers/gt.ts @@ -0,0 +1,38 @@ +import { Arguments, CapturedArguments, VM } from '@glimmer/runtime'; +import { InternalHelperReference } from '../utils/references'; + +/** +@module ember +*/ + +/** + Compares the two given values with > + + Example: + + ```handlebars + {{gt age 17}} + + {{! be true if `age` is > 17}} + ``` + + @public + @method gt + @for Ember.Templates.helpers + @since 2.7.0 +*/ +function gt({ positional: { references } }: CapturedArguments) { + let left = references[0].value(); + if (left === undefined || left === null) { + return false; + } + let right = references[1].value(); + if (right === undefined || right === null) { + return false; + } + return left > right; +} + +export default function(_vm: VM, args: Arguments) { + return new InternalHelperReference(gt, args.capture()); +} diff --git a/packages/@ember/-internals/glimmer/lib/resolver.ts b/packages/@ember/-internals/glimmer/lib/resolver.ts index 02c2a9d15fd..652e58fe923 100644 --- a/packages/@ember/-internals/glimmer/lib/resolver.ts +++ b/packages/@ember/-internals/glimmer/lib/resolver.ts @@ -33,6 +33,7 @@ import { default as array } from './helpers/array'; import { default as concat } from './helpers/concat'; import { default as eq } from './helpers/eq'; import { default as not } from './helpers/not'; +import { default as gt } from './helpers/gt'; import { default as eachIn } from './helpers/each-in'; import { default as get } from './helpers/get'; import { default as hash } from './helpers/hash'; @@ -69,6 +70,7 @@ const BUILTINS_HELPERS = { concat, eq, get, + gt, hash, array, log, diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/gt-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/gt-test.js new file mode 100644 index 00000000000..2ea137ecdef --- /dev/null +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/gt-test.js @@ -0,0 +1,137 @@ +import { RenderingTest, moduleFor } from '../../utils/test-case'; +import { set } from '@ember/-internals/metal'; +import { Component } from '../../utils/helpers'; +import { computed } from '@ember/-internals/metal'; + +moduleFor( + 'Helpers test: {{gt}}', + class extends RenderingTest { + ['@test returns true when the first static argument is bigger than the second one']() { + this.render(`{{gt 2 1}}`); + this.assertText('true'); + } + + ['@test returns false when the first static argument is not bigger than the second one']() { + this.render(`{{gt 0 1}}`); + this.assertText('false'); + } + + ['@test returns false when both arguments are the same']() { + this.render(`{{gt 1 1}}`); + this.assertText('false'); + } + + ['@test it updates for bound arguments']() { + this.render(`{{gt left right}}`, { left: 1, right: 2 }); + + this.assertText('false'); + + this.runTask(() => this.rerender()); + + this.assertText('false'); + + this.runTask(() => set(this.context, 'left', 3)); + + this.assertText('true'); + + this.runTask(() => set(this.context, 'right', 4)); + + this.assertText('false'); + + this.runTask(() => set(this.context, 'left', 5)); + + this.assertText('true'); + + this.runTask(() => set(this.context, 'right', 5)); + + this.assertText('false'); + } + + ['@test it can be used as a sub-expression']() { + this.render(`{{if (gt left right) "yes" "no"}}`, { left: 1, right: 2 }); + + this.assertText('no'); + + this.runTask(() => this.rerender()); + + this.assertText('no'); + + this.runTask(() => set(this.context, 'left', 3)); + + this.assertText('yes'); + + this.runTask(() => set(this.context, 'right', 4)); + + this.assertText('no'); + + this.runTask(() => { + set(this.context, 'left', 5); + set(this.context, 'right', 0); + }); + + this.assertText('yes'); + } + + ['@test of the first argument is undefined, it never pulls the second argument']() { + let didInvokeLeft = false; + let didInvokeRight = false; + let FooBarComponent = Component.extend({ + left: computed(function() { + didInvokeLeft = true; + return undefined; + }), + right: computed(function() { + didInvokeRight = true; + return 5; + }), + }); + + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + template: `{{gt left right}}`, + }); + + this.render(`{{foo-bar}}`, {}); + + this.assertText('false'); + + this.runTask(() => this.rerender()); + + this.assertText('false'); + + this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); + this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); + } + + ['@test of the first argument is null, it never pulls the second argument']() { + let didInvokeLeft = false; + let didInvokeRight = false; + let FooBarComponent = Component.extend({ + left: computed(function() { + didInvokeLeft = true; + return null; + }), + right: computed(function() { + didInvokeRight = true; + return 5; + }), + }); + + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + template: `{{gt left right}}`, + }); + + this.render(`{{foo-bar}}`, {}); + + this.assertText('false'); + + this.runTask(() => this.rerender()); + + this.assertText('false'); + + this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); + this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); + } + } +); From 98e99e106ce8dac1dc157fa9feaefcb15309e4ca Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Sun, 4 Nov 2018 11:53:10 +0100 Subject: [PATCH 04/21] Implement {{tl}} helper --- .../-internals/glimmer/lib/helpers/lt.ts | 38 +++++ .../@ember/-internals/glimmer/lib/resolver.ts | 2 + .../tests/integration/helpers/lt-test.js | 137 ++++++++++++++++++ 3 files changed, 177 insertions(+) create mode 100644 packages/@ember/-internals/glimmer/lib/helpers/lt.ts create mode 100644 packages/@ember/-internals/glimmer/tests/integration/helpers/lt-test.js diff --git a/packages/@ember/-internals/glimmer/lib/helpers/lt.ts b/packages/@ember/-internals/glimmer/lib/helpers/lt.ts new file mode 100644 index 00000000000..c51cd02c089 --- /dev/null +++ b/packages/@ember/-internals/glimmer/lib/helpers/lt.ts @@ -0,0 +1,38 @@ +import { Arguments, CapturedArguments, VM } from '@glimmer/runtime'; +import { InternalHelperReference } from '../utils/references'; + +/** +@module ember +*/ + +/** + Compares the two given values with < + + Example: + + ```handlebars + {{lt age 17}} + + {{! be true if `age` is < 17}} + ``` + + @public + @method lt + @for Ember.Templates.helpers + @since 2.7.0 +*/ +function lt({ positional: { references } }: CapturedArguments) { + let left = references[0].value(); + if (left === undefined || left === null) { + return false; + } + let right = references[1].value(); + if (right === undefined || right === null) { + return false; + } + return left < right; +} + +export default function(_vm: VM, args: Arguments) { + return new InternalHelperReference(lt, args.capture()); +} diff --git a/packages/@ember/-internals/glimmer/lib/resolver.ts b/packages/@ember/-internals/glimmer/lib/resolver.ts index 652e58fe923..7b6dc477778 100644 --- a/packages/@ember/-internals/glimmer/lib/resolver.ts +++ b/packages/@ember/-internals/glimmer/lib/resolver.ts @@ -39,6 +39,7 @@ import { default as get } from './helpers/get'; import { default as hash } from './helpers/hash'; import { inlineIf, inlineUnless } from './helpers/if-unless'; import { default as log } from './helpers/log'; +import { default as lt } from './helpers/lt'; import { default as mut } from './helpers/mut'; import { default as queryParams } from './helpers/query-param'; import { default as readonly } from './helpers/readonly'; @@ -74,6 +75,7 @@ const BUILTINS_HELPERS = { hash, array, log, + lt, mut, not, 'query-params': queryParams, diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/lt-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/lt-test.js new file mode 100644 index 00000000000..b47291b1fe6 --- /dev/null +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/lt-test.js @@ -0,0 +1,137 @@ +import { RenderingTest, moduleFor } from '../../utils/test-case'; +import { set } from '@ember/-internals/metal'; +import { Component } from '../../utils/helpers'; +import { computed } from '@ember/-internals/metal'; + +moduleFor( + 'Helpers test: {{lt}}', + class extends RenderingTest { + ['@test returns false when the first static argument is bigger than the second one']() { + this.render(`{{lt 2 1}}`); + this.assertText('false'); + } + + ['@test returns true when the first static argument is not bigger than the second one']() { + this.render(`{{lt 0 1}}`); + this.assertText('true'); + } + + ['@test returns false when both arguments are the same']() { + this.render(`{{lt 1 1}}`); + this.assertText('false'); + } + + ['@test it updates for bound arguments']() { + this.render(`{{lt left right}}`, { left: 1, right: 2 }); + + this.assertText('true'); + + this.runTask(() => this.rerender()); + + this.assertText('true'); + + this.runTask(() => set(this.context, 'left', 3)); + + this.assertText('false'); + + this.runTask(() => set(this.context, 'right', 4)); + + this.assertText('true'); + + this.runTask(() => set(this.context, 'left', 5)); + + this.assertText('false'); + + this.runTask(() => set(this.context, 'right', 5)); + + this.assertText('false'); + } + + ['@test it can be used as a sub-expression']() { + this.render(`{{if (lt left right) "yes" "no"}}`, { left: 1, right: 2 }); + + this.assertText('yes'); + + this.runTask(() => this.rerender()); + + this.assertText('yes'); + + this.runTask(() => set(this.context, 'left', 3)); + + this.assertText('no'); + + this.runTask(() => set(this.context, 'right', 4)); + + this.assertText('yes'); + + this.runTask(() => { + set(this.context, 'left', 5); + set(this.context, 'right', 0); + }); + + this.assertText('no'); + } + + ['@test of the first argument is undefined, it never pulls the second argument']() { + let didInvokeLeft = false; + let didInvokeRight = false; + let FooBarComponent = Component.extend({ + left: computed(function() { + didInvokeLeft = true; + return undefined; + }), + right: computed(function() { + didInvokeRight = true; + return 5; + }), + }); + + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + template: `{{lt left right}}`, + }); + + this.render(`{{foo-bar}}`, {}); + + this.assertText('false'); + + this.runTask(() => this.rerender()); + + this.assertText('false'); + + this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); + this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); + } + + ['@test of the first argument is null, it never pulls the second argument']() { + let didInvokeLeft = false; + let didInvokeRight = false; + let FooBarComponent = Component.extend({ + left: computed(function() { + didInvokeLeft = true; + return null; + }), + right: computed(function() { + didInvokeRight = true; + return 5; + }), + }); + + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + template: `{{lt left right}}`, + }); + + this.render(`{{foo-bar}}`, {}); + + this.assertText('false'); + + this.runTask(() => this.rerender()); + + this.assertText('false'); + + this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); + this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); + } + } +); From 207ea8cbb57216a3a98087afcd1e93dd694abfc1 Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Sun, 4 Nov 2018 12:00:08 +0100 Subject: [PATCH 05/21] Implement {{gte}} and {{lte}} helpers --- .../-internals/glimmer/lib/helpers/gte.ts | 38 +++++ .../-internals/glimmer/lib/helpers/lte.ts | 38 +++++ .../@ember/-internals/glimmer/lib/resolver.ts | 4 + .../tests/integration/helpers/gte-test.js | 137 ++++++++++++++++++ .../tests/integration/helpers/lte-test.js | 137 ++++++++++++++++++ 5 files changed, 354 insertions(+) create mode 100644 packages/@ember/-internals/glimmer/lib/helpers/gte.ts create mode 100644 packages/@ember/-internals/glimmer/lib/helpers/lte.ts create mode 100644 packages/@ember/-internals/glimmer/tests/integration/helpers/gte-test.js create mode 100644 packages/@ember/-internals/glimmer/tests/integration/helpers/lte-test.js diff --git a/packages/@ember/-internals/glimmer/lib/helpers/gte.ts b/packages/@ember/-internals/glimmer/lib/helpers/gte.ts new file mode 100644 index 00000000000..840766e25a4 --- /dev/null +++ b/packages/@ember/-internals/glimmer/lib/helpers/gte.ts @@ -0,0 +1,38 @@ +import { Arguments, CapturedArguments, VM } from '@glimmer/runtime'; +import { InternalHelperReference } from '../utils/references'; + +/** +@module ember +*/ + +/** + Compares the two given values with >= + + Example: + + ```handlebars + {{gt age 17}} + + {{! be true if `age` is > 17}} + ``` + + @public + @method gte + @for Ember.Templates.helpers + @since 2.7.0 +*/ +function gte({ positional: { references } }: CapturedArguments) { + let left = references[0].value(); + if (left === undefined || left === null) { + return false; + } + let right = references[1].value(); + if (right === undefined || right === null) { + return false; + } + return left >= right; +} + +export default function(_vm: VM, args: Arguments) { + return new InternalHelperReference(gte, args.capture()); +} diff --git a/packages/@ember/-internals/glimmer/lib/helpers/lte.ts b/packages/@ember/-internals/glimmer/lib/helpers/lte.ts new file mode 100644 index 00000000000..d12e1cb218b --- /dev/null +++ b/packages/@ember/-internals/glimmer/lib/helpers/lte.ts @@ -0,0 +1,38 @@ +import { Arguments, CapturedArguments, VM } from '@glimmer/runtime'; +import { InternalHelperReference } from '../utils/references'; + +/** +@module ember +*/ + +/** + Compares the two given values with <= + + Example: + + ```handlebars + {{lte age 17}} + + {{! be true if `age` is <= 17}} + ``` + + @public + @method lte + @for Ember.Templates.helpers + @since 2.7.0 +*/ +function lte({ positional: { references } }: CapturedArguments) { + let left = references[0].value(); + if (left === undefined || left === null) { + return false; + } + let right = references[1].value(); + if (right === undefined || right === null) { + return false; + } + return left <= right; +} + +export default function(_vm: VM, args: Arguments) { + return new InternalHelperReference(lte, args.capture()); +} diff --git a/packages/@ember/-internals/glimmer/lib/resolver.ts b/packages/@ember/-internals/glimmer/lib/resolver.ts index 7b6dc477778..a449bebd8a8 100644 --- a/packages/@ember/-internals/glimmer/lib/resolver.ts +++ b/packages/@ember/-internals/glimmer/lib/resolver.ts @@ -34,12 +34,14 @@ import { default as concat } from './helpers/concat'; import { default as eq } from './helpers/eq'; import { default as not } from './helpers/not'; import { default as gt } from './helpers/gt'; +import { default as gte } from './helpers/gte'; import { default as eachIn } from './helpers/each-in'; import { default as get } from './helpers/get'; import { default as hash } from './helpers/hash'; import { inlineIf, inlineUnless } from './helpers/if-unless'; import { default as log } from './helpers/log'; import { default as lt } from './helpers/lt'; +import { default as lte } from './helpers/lte'; import { default as mut } from './helpers/mut'; import { default as queryParams } from './helpers/query-param'; import { default as readonly } from './helpers/readonly'; @@ -72,10 +74,12 @@ const BUILTINS_HELPERS = { eq, get, gt, + gte, hash, array, log, lt, + lte, mut, not, 'query-params': queryParams, diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/gte-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/gte-test.js new file mode 100644 index 00000000000..451050d77d1 --- /dev/null +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/gte-test.js @@ -0,0 +1,137 @@ +import { RenderingTest, moduleFor } from '../../utils/test-case'; +import { set } from '@ember/-internals/metal'; +import { Component } from '../../utils/helpers'; +import { computed } from '@ember/-internals/metal'; + +moduleFor( + 'Helpers test: {{gte}}', + class extends RenderingTest { + ['@test returns true when the first static argument is bigger than the second one']() { + this.render(`{{gte 2 1}}`); + this.assertText('true'); + } + + ['@test returns false when the first static argument is not bigger than the second one']() { + this.render(`{{gte 0 1}}`); + this.assertText('false'); + } + + ['@test returns true when both arguments are the same']() { + this.render(`{{gte 1 1}}`); + this.assertText('true'); + } + + ['@test it updates for bound arguments']() { + this.render(`{{gte left right}}`, { left: 1, right: 2 }); + + this.assertText('false'); + + this.runTask(() => this.rerender()); + + this.assertText('false'); + + this.runTask(() => set(this.context, 'left', 3)); + + this.assertText('true'); + + this.runTask(() => set(this.context, 'right', 4)); + + this.assertText('false'); + + this.runTask(() => set(this.context, 'left', 5)); + + this.assertText('true'); + + this.runTask(() => set(this.context, 'right', 5)); + + this.assertText('true'); + } + + ['@test it can be used as a sub-expression']() { + this.render(`{{if (gt left right) "yes" "no"}}`, { left: 1, right: 2 }); + + this.assertText('no'); + + this.runTask(() => this.rerender()); + + this.assertText('no'); + + this.runTask(() => set(this.context, 'left', 3)); + + this.assertText('yes'); + + this.runTask(() => set(this.context, 'right', 4)); + + this.assertText('no'); + + this.runTask(() => { + set(this.context, 'left', 5); + set(this.context, 'right', 0); + }); + + this.assertText('yes'); + } + + ['@test of the first argument is undefined, it never pulls the second argument']() { + let didInvokeLeft = false; + let didInvokeRight = false; + let FooBarComponent = Component.extend({ + left: computed(function() { + didInvokeLeft = true; + return undefined; + }), + right: computed(function() { + didInvokeRight = true; + return 5; + }), + }); + + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + template: `{{gte left right}}`, + }); + + this.render(`{{foo-bar}}`, {}); + + this.assertText('false'); + + this.runTask(() => this.rerender()); + + this.assertText('false'); + + this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); + this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); + } + + ['@test of the first argument is null, it never pulls the second argument']() { + let didInvokeLeft = false; + let didInvokeRight = false; + let FooBarComponent = Component.extend({ + left: computed(function() { + didInvokeLeft = true; + return null; + }), + right: computed(function() { + didInvokeRight = true; + return 5; + }), + }); + + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + template: `{{gte left right}}`, + }); + + this.render(`{{foo-bar}}`, {}); + + this.assertText('false'); + + this.runTask(() => this.rerender()); + + this.assertText('false'); + + this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); + this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); + } + } +); diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/lte-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/lte-test.js new file mode 100644 index 00000000000..3662462abcd --- /dev/null +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/lte-test.js @@ -0,0 +1,137 @@ +import { RenderingTest, moduleFor } from '../../utils/test-case'; +import { set } from '@ember/-internals/metal'; +import { Component } from '../../utils/helpers'; +import { computed } from '@ember/-internals/metal'; + +moduleFor( + 'Helpers test: {{lte}}', + class extends RenderingTest { + ['@test returns false when the first static argument is bigger than the second one']() { + this.render(`{{lte 2 1}}`); + this.assertText('false'); + } + + ['@test returns true when the first static argument is not bigger than the second one']() { + this.render(`{{lte 0 1}}`); + this.assertText('true'); + } + + ['@test returns true when both arguments are the same']() { + this.render(`{{lte 1 1}}`); + this.assertText('true'); + } + + ['@test it updates for bound arguments']() { + this.render(`{{lte left right}}`, { left: 1, right: 2 }); + + this.assertText('true'); + + this.runTask(() => this.rerender()); + + this.assertText('true'); + + this.runTask(() => set(this.context, 'left', 3)); + + this.assertText('false'); + + this.runTask(() => set(this.context, 'right', 4)); + + this.assertText('true'); + + this.runTask(() => set(this.context, 'left', 5)); + + this.assertText('false'); + + this.runTask(() => set(this.context, 'right', 5)); + + this.assertText('true'); + } + + ['@test it can be used as a sub-expression']() { + this.render(`{{if (lt left right) "yes" "no"}}`, { left: 1, right: 2 }); + + this.assertText('yes'); + + this.runTask(() => this.rerender()); + + this.assertText('yes'); + + this.runTask(() => set(this.context, 'left', 3)); + + this.assertText('no'); + + this.runTask(() => set(this.context, 'right', 4)); + + this.assertText('yes'); + + this.runTask(() => { + set(this.context, 'left', 5); + set(this.context, 'right', 0); + }); + + this.assertText('no'); + } + + ['@test of the first argument is undefined, it never pulls the second argument']() { + let didInvokeLeft = false; + let didInvokeRight = false; + let FooBarComponent = Component.extend({ + left: computed(function() { + didInvokeLeft = true; + return undefined; + }), + right: computed(function() { + didInvokeRight = true; + return 5; + }), + }); + + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + template: `{{lte left right}}`, + }); + + this.render(`{{foo-bar}}`, {}); + + this.assertText('false'); + + this.runTask(() => this.rerender()); + + this.assertText('false'); + + this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); + this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); + } + + ['@test of the first argument is null, it never pulls the second argument']() { + let didInvokeLeft = false; + let didInvokeRight = false; + let FooBarComponent = Component.extend({ + left: computed(function() { + didInvokeLeft = true; + return null; + }), + right: computed(function() { + didInvokeRight = true; + return 5; + }), + }); + + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + template: `{{lte left right}}`, + }); + + this.render(`{{foo-bar}}`, {}); + + this.assertText('false'); + + this.runTask(() => this.rerender()); + + this.assertText('false'); + + this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); + this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); + } + } +); From 22a8d33af0529093484a5ee7f9a5e0772a1452a3 Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Sun, 4 Nov 2018 12:58:12 +0100 Subject: [PATCH 06/21] Implement {{and}} helper --- .../-internals/glimmer/lib/helpers/and.ts | 30 +++++ .../@ember/-internals/glimmer/lib/resolver.ts | 2 + .../tests/integration/helpers/and-test.js | 103 ++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 packages/@ember/-internals/glimmer/lib/helpers/and.ts create mode 100644 packages/@ember/-internals/glimmer/tests/integration/helpers/and-test.js diff --git a/packages/@ember/-internals/glimmer/lib/helpers/and.ts b/packages/@ember/-internals/glimmer/lib/helpers/and.ts new file mode 100644 index 00000000000..55f9eeb4856 --- /dev/null +++ b/packages/@ember/-internals/glimmer/lib/helpers/and.ts @@ -0,0 +1,30 @@ +import { Arguments, CapturedArguments, VM } from '@glimmer/runtime'; +import { InternalHelperReference } from '../utils/references'; + +/** +@module ember +*/ + +/** + Evaluates the given arguments with && in short-circuit + + Example: + + ```handlebars + {{and isAdmin isIdle validData}} + + {{! be validData if `isAdmin` and `isIdle` are both truthy}} + ``` + + @public + @method and + @for Ember.Templates.helpers + @since 2.7.0 +*/ +function and({ positional: { references } }: CapturedArguments) { + return references.reduce((acc: any, ref) => acc && ref.value(), true); +} + +export default function(_vm: VM, args: Arguments) { + return new InternalHelperReference(and, args.capture()); +} diff --git a/packages/@ember/-internals/glimmer/lib/resolver.ts b/packages/@ember/-internals/glimmer/lib/resolver.ts index a449bebd8a8..a29f8d43c65 100644 --- a/packages/@ember/-internals/glimmer/lib/resolver.ts +++ b/packages/@ember/-internals/glimmer/lib/resolver.ts @@ -29,6 +29,7 @@ import { default as htmlSafeHelper } from './helpers/-html-safe'; import { default as inputTypeHelper } from './helpers/-input-type'; import { default as normalizeClassHelper } from './helpers/-normalize-class'; import { default as action } from './helpers/action'; +import { default as and } from './helpers/and'; import { default as array } from './helpers/array'; import { default as concat } from './helpers/concat'; import { default as eq } from './helpers/eq'; @@ -70,6 +71,7 @@ function makeOptions(moduleName: string, namespace?: string): LookupOptions { const BUILTINS_HELPERS = { if: inlineIf, action, + and, concat, eq, get, diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/and-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/and-test.js new file mode 100644 index 00000000000..8788fccd257 --- /dev/null +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/and-test.js @@ -0,0 +1,103 @@ +import { RenderingTest, moduleFor } from '../../utils/test-case'; +import { set } from '@ember/-internals/metal'; +import { Component } from '../../utils/helpers'; +import { computed } from '@ember/-internals/metal'; + +moduleFor( + 'Helpers test: {{and}}', + class extends RenderingTest { + ['@test if all arguments are truthy, it returns the last argument']() { + this.render(`{{and 2 1 true "foo"}}`); + this.assertText('foo'); + } + + ['@test if any argument is falsy, it return the first falsy argument']() { + this.render(`{{and "foo" 0 1}}`); + this.assertText('0'); + } + + ['@test it updates for bound arguments']() { + this.render(`{{and first second third}}`, { first: 1, second: true, third: 'foo' }); + + this.assertText('foo'); + + this.runTask(() => this.rerender()); + + this.assertText('foo'); + + this.runTask(() => set(this.context, 'third', 3)); + + this.assertText('3'); + + this.runTask(() => set(this.context, 'second', false)); + + this.assertText('false'); + + this.runTask(() => set(this.context, 'first', 0)); + + this.assertText('0'); + } + + ['@test it can be used as a sub-expression']() { + this.render(`{{if (and first second) "yes" "no"}}`, { first: 1, second: 2 }); + + this.assertText('yes'); + + this.runTask(() => this.rerender()); + + this.assertText('yes'); + + this.runTask(() => set(this.context, 'second', false)); + + this.assertText('no'); + + this.runTask(() => set(this.context, 'first', 0)); + + this.assertText('no'); + + this.runTask(() => { + set(this.context, 'first', 'foo'); + set(this.context, 'second', 'bar'); + }); + + this.assertText('yes'); + } + + ['@test once if finds the first falsy argument, the following arguments are not evaluated']() { + let didInvokeFirst = false; + let didInvokeSecond = false; + let didInvokeThird = false; + let FooBarComponent = Component.extend({ + first: computed(function() { + didInvokeFirst = true; + return true; + }), + second: computed(function() { + didInvokeSecond = true; + return false; + }), + third: computed(function() { + didInvokeThird = true; + return 'foo§'; + }), + }); + + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + template: `{{and first second third}}`, + }); + + this.render(`{{foo-bar}}`, {}); + + this.assertText('false'); + + this.runTask(() => this.rerender()); + + this.assertText('false'); + + this.assert.ok(didInvokeFirst, 'the `first` property was accessed'); + this.assert.ok(didInvokeSecond, 'the `second` property was accessed'); + this.assert.notOk(didInvokeThird, "the `third` property wasn't accessed"); + } + } +); From 71429796d9f79fd717ab736e4b7d055cd18429f5 Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Sun, 4 Nov 2018 14:47:59 +0100 Subject: [PATCH 07/21] Implement {{or}} helper --- .../-internals/glimmer/lib/helpers/or.ts | 30 ++++++ .../@ember/-internals/glimmer/lib/resolver.ts | 2 + .../tests/integration/helpers/or-test.js | 96 +++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 packages/@ember/-internals/glimmer/lib/helpers/or.ts create mode 100644 packages/@ember/-internals/glimmer/tests/integration/helpers/or-test.js diff --git a/packages/@ember/-internals/glimmer/lib/helpers/or.ts b/packages/@ember/-internals/glimmer/lib/helpers/or.ts new file mode 100644 index 00000000000..e91bb2a627e --- /dev/null +++ b/packages/@ember/-internals/glimmer/lib/helpers/or.ts @@ -0,0 +1,30 @@ +import { Arguments, CapturedArguments, VM } from '@glimmer/runtime'; +import { InternalHelperReference } from '../utils/references'; + +/** +@module ember +*/ + +/** + Evaluates the given arguments with || in short-circuit + + Example: + + ```handlebars + {{or isAdmin isAuthor}} + + {{! be validData either `isAdmin` or `isAuthor` are truthy}} + ``` + + @public + @method or + @for Ember.Templates.helpers + @since 2.7.0 +*/ +function or({ positional: { references } }: CapturedArguments) { + return references.reduce((acc: any, ref) => acc || ref.value(), false); +} + +export default function(_vm: VM, args: Arguments) { + return new InternalHelperReference(or, args.capture()); +} diff --git a/packages/@ember/-internals/glimmer/lib/resolver.ts b/packages/@ember/-internals/glimmer/lib/resolver.ts index a29f8d43c65..d35d8692c14 100644 --- a/packages/@ember/-internals/glimmer/lib/resolver.ts +++ b/packages/@ember/-internals/glimmer/lib/resolver.ts @@ -44,6 +44,7 @@ import { default as log } from './helpers/log'; import { default as lt } from './helpers/lt'; import { default as lte } from './helpers/lte'; import { default as mut } from './helpers/mut'; +import { default as or } from './helpers/or'; import { default as queryParams } from './helpers/query-param'; import { default as readonly } from './helpers/readonly'; import { default as unbound } from './helpers/unbound'; @@ -84,6 +85,7 @@ const BUILTINS_HELPERS = { lte, mut, not, + or, 'query-params': queryParams, readonly, unbound, diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/or-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/or-test.js new file mode 100644 index 00000000000..416e1ada6c6 --- /dev/null +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/or-test.js @@ -0,0 +1,96 @@ +import { RenderingTest, moduleFor } from '../../utils/test-case'; +import { set } from '@ember/-internals/metal'; +import { Component } from '../../utils/helpers'; +import { computed } from '@ember/-internals/metal'; + +moduleFor( + 'Helpers test: {{or}}', + class extends RenderingTest { + ['@test returns the first truthy argument']() { + this.render(`{{or false 0 "foo"}}`); + this.assertText('foo'); + } + + ['@test if all arguments are falsy, it return the last argument']() { + this.render(`{{or false "" 0}}`); + this.assertText('0'); + } + + ['@test it updates for bound arguments']() { + this.render(`{{or first second third}}`, { first: 1, second: true, third: 'foo' }); + + this.assertText('1'); + + this.runTask(() => this.rerender()); + + this.assertText('1'); + + this.runTask(() => set(this.context, 'first', false)); + + this.assertText('true'); + + this.runTask(() => set(this.context, 'second', 0)); + + this.assertText('foo'); + + this.runTask(() => set(this.context, 'third', '')); + + this.assertText(''); + } + + ['@test it can be used as a sub-expression']() { + this.render(`{{if (or first second) "yes" "no"}}`, { first: 1, second: 2 }); + + this.assertText('yes'); + + this.runTask(() => this.rerender()); + + this.assertText('yes'); + + this.runTask(() => set(this.context, 'first', false)); + + this.assertText('yes'); + + this.runTask(() => set(this.context, 'second', 0)); + + this.assertText('no'); + } + + ['@test once if finds the first truthy argument, the following arguments are not evaluated']() { + let didInvokeFirst = false; + let didInvokeSecond = false; + let didInvokeThird = false; + let FooBarComponent = Component.extend({ + first: computed(function() { + didInvokeFirst = true; + return true; + }), + second: computed(function() { + didInvokeSecond = true; + return false; + }), + third: computed(function() { + didInvokeThird = true; + return 'foo§'; + }), + }); + + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + template: `{{or first second third}}`, + }); + + this.render(`{{foo-bar}}`, {}); + + this.assertText('true'); + + this.runTask(() => this.rerender()); + + this.assertText('true'); + + this.assert.ok(didInvokeFirst, 'the `first` property was accessed'); + this.assert.notOk(didInvokeSecond, 'the `second` property was accessed'); + this.assert.notOk(didInvokeThird, "the `third` property wasn't accessed"); + } + } +); From 58f1426eef8cd6e9afab5c3983bd168c329c118f Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Sun, 4 Nov 2018 17:51:24 +0100 Subject: [PATCH 08/21] Perf improvement: replace `[].reduce` with `for` loop --- packages/@ember/-internals/glimmer/lib/helpers/and.ts | 9 ++++++++- packages/@ember/-internals/glimmer/lib/helpers/or.ts | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/@ember/-internals/glimmer/lib/helpers/and.ts b/packages/@ember/-internals/glimmer/lib/helpers/and.ts index 55f9eeb4856..31d96855182 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/and.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/and.ts @@ -22,7 +22,14 @@ import { InternalHelperReference } from '../utils/references'; @since 2.7.0 */ function and({ positional: { references } }: CapturedArguments) { - return references.reduce((acc: any, ref) => acc && ref.value(), true); + let last: any = true; + for (let i = 0; i < references.length; i++) { + last = references[i].value(); + if (!last) { + return last; + } + } + return last; } export default function(_vm: VM, args: Arguments) { diff --git a/packages/@ember/-internals/glimmer/lib/helpers/or.ts b/packages/@ember/-internals/glimmer/lib/helpers/or.ts index e91bb2a627e..0f7058466de 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/or.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/or.ts @@ -22,7 +22,14 @@ import { InternalHelperReference } from '../utils/references'; @since 2.7.0 */ function or({ positional: { references } }: CapturedArguments) { - return references.reduce((acc: any, ref) => acc || ref.value(), false); + let last: any = false; + for (let i = 0; i < references.length; i++) { + last = references[i].value(); + if (last) { + return last; + } + } + return last; } export default function(_vm: VM, args: Arguments) { From 552f776162dac4a8d6049d65b738ba1a45e1fcb7 Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Sun, 4 Nov 2018 18:06:20 +0100 Subject: [PATCH 09/21] Ensure gt, get, lt, and lte compare treat null on the second argument as 0 --- packages/@ember/-internals/glimmer/lib/helpers/gt.ts | 5 ++++- .../@ember/-internals/glimmer/lib/helpers/gte.ts | 5 ++++- packages/@ember/-internals/glimmer/lib/helpers/lt.ts | 5 ++++- .../@ember/-internals/glimmer/lib/helpers/lte.ts | 5 ++++- .../glimmer/tests/integration/helpers/gt-test.js | 8 ++++++++ .../glimmer/tests/integration/helpers/gte-test.js | 12 ++++++++++++ .../glimmer/tests/integration/helpers/lt-test.js | 8 ++++++++ .../glimmer/tests/integration/helpers/lte-test.js | 8 ++++++++ 8 files changed, 52 insertions(+), 4 deletions(-) diff --git a/packages/@ember/-internals/glimmer/lib/helpers/gt.ts b/packages/@ember/-internals/glimmer/lib/helpers/gt.ts index b0c3035c465..1dffc5d5540 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/gt.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/gt.ts @@ -27,9 +27,12 @@ function gt({ positional: { references } }: CapturedArguments) { return false; } let right = references[1].value(); - if (right === undefined || right === null) { + if (right === undefined) { return false; } + if (right === null) { + return left > 0; + } return left > right; } diff --git a/packages/@ember/-internals/glimmer/lib/helpers/gte.ts b/packages/@ember/-internals/glimmer/lib/helpers/gte.ts index 840766e25a4..a1dc1451dce 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/gte.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/gte.ts @@ -27,9 +27,12 @@ function gte({ positional: { references } }: CapturedArguments) { return false; } let right = references[1].value(); - if (right === undefined || right === null) { + if (right === undefined) { return false; } + if (right === null) { + return left >= 0; + } return left >= right; } diff --git a/packages/@ember/-internals/glimmer/lib/helpers/lt.ts b/packages/@ember/-internals/glimmer/lib/helpers/lt.ts index c51cd02c089..90d5339d78d 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/lt.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/lt.ts @@ -27,9 +27,12 @@ function lt({ positional: { references } }: CapturedArguments) { return false; } let right = references[1].value(); - if (right === undefined || right === null) { + if (right === undefined) { return false; } + if (right === null) { + return left < 0; + } return left < right; } diff --git a/packages/@ember/-internals/glimmer/lib/helpers/lte.ts b/packages/@ember/-internals/glimmer/lib/helpers/lte.ts index d12e1cb218b..85f215f2b5d 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/lte.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/lte.ts @@ -27,9 +27,12 @@ function lte({ positional: { references } }: CapturedArguments) { return false; } let right = references[1].value(); - if (right === undefined || right === null) { + if (right === undefined) { return false; } + if (right === null) { + return left <= 0; + } return left <= right; } diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/gt-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/gt-test.js index 2ea137ecdef..487da04b42d 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/gt-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/gt-test.js @@ -45,6 +45,14 @@ moduleFor( this.runTask(() => set(this.context, 'right', 5)); this.assertText('false'); + + this.runTask(() => set(this.context, 'right', null)); + + this.assertText('true'); + + this.runTask(() => set(this.context, 'left', -1)); + + this.assertText('false'); } ['@test it can be used as a sub-expression']() { diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/gte-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/gte-test.js index 451050d77d1..6bf154db5d7 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/gte-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/gte-test.js @@ -45,6 +45,18 @@ moduleFor( this.runTask(() => set(this.context, 'right', 5)); this.assertText('true'); + + this.runTask(() => set(this.context, 'right', null)); + + this.assertText('true'); + + this.runTask(() => set(this.context, 'left', -1)); + + this.assertText('false'); + + this.runTask(() => set(this.context, 'left', 0)); + + this.assertText('true'); } ['@test it can be used as a sub-expression']() { diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/lt-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/lt-test.js index b47291b1fe6..e4bf66f50bc 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/lt-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/lt-test.js @@ -45,6 +45,14 @@ moduleFor( this.runTask(() => set(this.context, 'right', 5)); this.assertText('false'); + + this.runTask(() => set(this.context, 'right', null)); + + this.assertText('false'); + + this.runTask(() => set(this.context, 'left', -1)); + + this.assertText('true'); } ['@test it can be used as a sub-expression']() { diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/lte-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/lte-test.js index 3662462abcd..5d7d75574ee 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/lte-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/lte-test.js @@ -45,6 +45,14 @@ moduleFor( this.runTask(() => set(this.context, 'right', 5)); this.assertText('true'); + + this.runTask(() => set(this.context, 'right', null)); + + this.assertText('false'); + + this.runTask(() => set(this.context, 'left', 0)); + + this.assertText('true'); } ['@test it can be used as a sub-expression']() { From d024e9149c329b895642fc2e79466f7ce928575e Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Tue, 6 Nov 2018 00:36:25 +0100 Subject: [PATCH 10/21] Implement {{not-eq}} helper --- .../-internals/glimmer/lib/helpers/not-eq.ts | 30 ++++++++++ .../@ember/-internals/glimmer/lib/resolver.ts | 2 + .../tests/integration/helpers/not-eq-test.js | 59 +++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 packages/@ember/-internals/glimmer/lib/helpers/not-eq.ts create mode 100644 packages/@ember/-internals/glimmer/tests/integration/helpers/not-eq-test.js diff --git a/packages/@ember/-internals/glimmer/lib/helpers/not-eq.ts b/packages/@ember/-internals/glimmer/lib/helpers/not-eq.ts new file mode 100644 index 00000000000..efc8f4ab768 --- /dev/null +++ b/packages/@ember/-internals/glimmer/lib/helpers/not-eq.ts @@ -0,0 +1,30 @@ +import { Arguments, CapturedArguments, VM } from '@glimmer/runtime'; +import { InternalHelperReference } from '../utils/references'; + +/** +@module ember +*/ + +/** + Compares the two given values with !== + + Example: + + ```handlebars + {{not-eq type "button"}} + + {{! be true if `type` !== "button"}} + ``` + + @public + @method not-eq + @for Ember.Templates.helpers + @since 2.7.0 +*/ +function notEq({ positional: { references } }: CapturedArguments) { + return references[0].value() !== references[1].value(); +} + +export default function(_vm: VM, args: Arguments) { + return new InternalHelperReference(notEq, args.capture()); +} diff --git a/packages/@ember/-internals/glimmer/lib/resolver.ts b/packages/@ember/-internals/glimmer/lib/resolver.ts index d35d8692c14..9543caa4c3c 100644 --- a/packages/@ember/-internals/glimmer/lib/resolver.ts +++ b/packages/@ember/-internals/glimmer/lib/resolver.ts @@ -34,6 +34,7 @@ import { default as array } from './helpers/array'; import { default as concat } from './helpers/concat'; import { default as eq } from './helpers/eq'; import { default as not } from './helpers/not'; +import { default as notEq } from './helpers/not-eq'; import { default as gt } from './helpers/gt'; import { default as gte } from './helpers/gte'; import { default as eachIn } from './helpers/each-in'; @@ -85,6 +86,7 @@ const BUILTINS_HELPERS = { lte, mut, not, + 'not-eq': notEq, or, 'query-params': queryParams, readonly, diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/not-eq-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/not-eq-test.js new file mode 100644 index 00000000000..e33f6ff4388 --- /dev/null +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/not-eq-test.js @@ -0,0 +1,59 @@ +import { RenderingTest, moduleFor } from '../../utils/test-case'; +import { set } from '@ember/-internals/metal'; + +moduleFor( + 'Helpers test: {{not-eq}}', + class extends RenderingTest { + ['@test it compares static arguments that are equal']() { + this.render(`{{not-eq "foo" "foo"}}`); + this.assertText('false'); + } + + ['@test it compares static arguments that are different']() { + this.render(`{{not-eq "foo" "bar"}}`); + this.assertText('true'); + } + + ['@test it updates for bound arguments']() { + this.render(`{{not-eq first second}}`, { first: 'one', second: 'two' }); + + this.assertText('true'); + + this.runTask(() => this.rerender()); + + this.assertText('true'); + + this.runTask(() => set(this.context, 'first', 'two')); + + this.assertText('false'); + + this.runTask(() => set(this.context, 'second', '2')); + + this.assertText('true'); + } + + ['@test it can be used as a sub-expression']() { + this.render(`{{if (not-eq first second) "different" "equal"}}`, { + first: 'one', + second: 'two', + }); + + this.assertText('different'); + + this.runTask(() => this.rerender()); + + this.assertText('different'); + + this.runTask(() => set(this.context, 'first', 'two')); + + this.assertText('equal'); + + this.runTask(() => { + set(this.context, 'first', '1'); + set(this.context, 'second', '2'); + }); + + this.assertText('different'); + } + } +); From 1d791adbadd507efd3260ef6c45fb7579096f237 Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Tue, 6 Nov 2018 00:59:57 +0100 Subject: [PATCH 11/21] Fix linting problems --- packages/@ember/-internals/glimmer/lib/resolver.ts | 8 ++++---- tests/docs/expected.js | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/@ember/-internals/glimmer/lib/resolver.ts b/packages/@ember/-internals/glimmer/lib/resolver.ts index 9543caa4c3c..29a28c62323 100644 --- a/packages/@ember/-internals/glimmer/lib/resolver.ts +++ b/packages/@ember/-internals/glimmer/lib/resolver.ts @@ -32,19 +32,19 @@ import { default as action } from './helpers/action'; import { default as and } from './helpers/and'; import { default as array } from './helpers/array'; import { default as concat } from './helpers/concat'; +import { default as eachIn } from './helpers/each-in'; import { default as eq } from './helpers/eq'; -import { default as not } from './helpers/not'; -import { default as notEq } from './helpers/not-eq'; +import { default as get } from './helpers/get'; import { default as gt } from './helpers/gt'; import { default as gte } from './helpers/gte'; -import { default as eachIn } from './helpers/each-in'; -import { default as get } from './helpers/get'; import { default as hash } from './helpers/hash'; import { inlineIf, inlineUnless } from './helpers/if-unless'; import { default as log } from './helpers/log'; import { default as lt } from './helpers/lt'; import { default as lte } from './helpers/lte'; import { default as mut } from './helpers/mut'; +import { default as not } from './helpers/not'; +import { default as notEq } from './helpers/not-eq'; import { default as or } from './helpers/or'; import { default as queryParams } from './helpers/query-param'; import { default as readonly } from './helpers/readonly'; diff --git a/tests/docs/expected.js b/tests/docs/expected.js index f00cda89ee2..e1f560fed19 100644 --- a/tests/docs/expected.js +++ b/tests/docs/expected.js @@ -193,6 +193,7 @@ module.exports = { 'engine', 'ensureInitializers', 'enter', + 'eq', 'equal', 'error', 'eventDispatcher', @@ -363,6 +364,7 @@ module.exports = { 'none', 'normalize', 'normalizeFullName', + 'not-eq', 'not', 'notEmpty', 'notifyPropertyChange', From 77fc37a0c4039b6935b896669cd19bb797d2a7d2 Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Tue, 6 Nov 2018 12:49:44 +0100 Subject: [PATCH 12/21] Add feature flag for new template helpers --- FEATURES.md | 5 + .../@ember/-internals/glimmer/lib/resolver.ts | 22 +- .../tests/integration/helpers/and-test.js | 153 ++++++------- .../tests/integration/helpers/eq-test.js | 73 ++++--- .../tests/integration/helpers/gt-test.js | 197 ++++++++--------- .../tests/integration/helpers/gte-test.js | 201 +++++++++--------- .../tests/integration/helpers/lt-test.js | 197 ++++++++--------- .../tests/integration/helpers/lte-test.js | 197 ++++++++--------- .../tests/integration/helpers/not-eq-test.js | 79 +++---- .../tests/integration/helpers/not-test.js | 71 ++++--- .../tests/integration/helpers/or-test.js | 143 +++++++------ packages/@ember/canary-features/index.ts | 2 + 12 files changed, 689 insertions(+), 651 deletions(-) diff --git a/FEATURES.md b/FEATURES.md index 7d21b742fb0..de6bdd4d14e 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -55,3 +55,8 @@ for a detailed explanation. * `ember-template-block-let-helper` Introduce the block form of the `let` helper per [RFC](https://github.com/emberjs/rfcs/blob/78211b11387e7f477264e322687f1ec5ab131361/text/0286-block-let-template-helper.md). + +* `ember-basic-template-helpers` + + Introduces several template helpers to perform basic comparisons and boolean operation in templates: + `{{eq}}`, `{{not-eq}}`, `{{gt}}`, `{{gte}}`, `{{lt}}`, `{{lte}}`, `{{not}}`, `{{and}}` and `{{or}}`. \ No newline at end of file diff --git a/packages/@ember/-internals/glimmer/lib/resolver.ts b/packages/@ember/-internals/glimmer/lib/resolver.ts index 29a28c62323..17b6aa3f26d 100644 --- a/packages/@ember/-internals/glimmer/lib/resolver.ts +++ b/packages/@ember/-internals/glimmer/lib/resolver.ts @@ -6,6 +6,7 @@ import { EMBER_MODULE_UNIFICATION, GLIMMER_CUSTOM_COMPONENT_MANAGER, GLIMMER_MODIFIER_MANAGER, + EMBER_BASIC_TEMPLATE_HELPERS, } from '@ember/canary-features'; import { assert } from '@ember/debug'; import { _instrumentStart } from '@ember/instrumentation'; @@ -73,21 +74,12 @@ function makeOptions(moduleName: string, namespace?: string): LookupOptions { const BUILTINS_HELPERS = { if: inlineIf, action, - and, concat, - eq, get, - gt, - gte, hash, array, log, - lt, - lte, mut, - not, - 'not-eq': notEq, - or, 'query-params': queryParams, readonly, unbound, @@ -102,6 +94,18 @@ const BUILTINS_HELPERS = { '-outlet': outletHelper, }; +if (EMBER_BASIC_TEMPLATE_HELPERS) { + BUILTINS_HELPERS['and'] = and; + BUILTINS_HELPERS['eq'] = eq; + BUILTINS_HELPERS['gt'] = gt; + BUILTINS_HELPERS['gte'] = gte; + BUILTINS_HELPERS['lt'] = lt; + BUILTINS_HELPERS['lte'] = lte; + BUILTINS_HELPERS['not'] = not; + BUILTINS_HELPERS['not-eq'] = notEq; + BUILTINS_HELPERS['or'] = or; +} + if (DEBUG) { BUILTINS_HELPERS['-assert-implicit-component-helper-argument'] = componentAssertionHelper; } diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/and-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/and-test.js index 8788fccd257..a314fe3790f 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/and-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/and-test.js @@ -2,102 +2,105 @@ import { RenderingTest, moduleFor } from '../../utils/test-case'; import { set } from '@ember/-internals/metal'; import { Component } from '../../utils/helpers'; import { computed } from '@ember/-internals/metal'; +import { EMBER_BASIC_TEMPLATE_HELPERS } from '@ember/canary-features'; -moduleFor( - 'Helpers test: {{and}}', - class extends RenderingTest { - ['@test if all arguments are truthy, it returns the last argument']() { - this.render(`{{and 2 1 true "foo"}}`); - this.assertText('foo'); - } +if (EMBER_BASIC_TEMPLATE_HELPERS) { + moduleFor( + 'Helpers test: {{and}}', + class extends RenderingTest { + ['@test if all arguments are truthy, it returns the last argument']() { + this.render(`{{and 2 1 true "foo"}}`); + this.assertText('foo'); + } - ['@test if any argument is falsy, it return the first falsy argument']() { - this.render(`{{and "foo" 0 1}}`); - this.assertText('0'); - } + ['@test if any argument is falsy, it return the first falsy argument']() { + this.render(`{{and "foo" 0 1}}`); + this.assertText('0'); + } - ['@test it updates for bound arguments']() { - this.render(`{{and first second third}}`, { first: 1, second: true, third: 'foo' }); + ['@test it updates for bound arguments']() { + this.render(`{{and first second third}}`, { first: 1, second: true, third: 'foo' }); - this.assertText('foo'); + this.assertText('foo'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('foo'); + this.assertText('foo'); - this.runTask(() => set(this.context, 'third', 3)); + this.runTask(() => set(this.context, 'third', 3)); - this.assertText('3'); + this.assertText('3'); - this.runTask(() => set(this.context, 'second', false)); + this.runTask(() => set(this.context, 'second', false)); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => set(this.context, 'first', 0)); + this.runTask(() => set(this.context, 'first', 0)); - this.assertText('0'); - } + this.assertText('0'); + } - ['@test it can be used as a sub-expression']() { - this.render(`{{if (and first second) "yes" "no"}}`, { first: 1, second: 2 }); + ['@test it can be used as a sub-expression']() { + this.render(`{{if (and first second) "yes" "no"}}`, { first: 1, second: 2 }); - this.assertText('yes'); + this.assertText('yes'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('yes'); + this.assertText('yes'); - this.runTask(() => set(this.context, 'second', false)); + this.runTask(() => set(this.context, 'second', false)); - this.assertText('no'); + this.assertText('no'); - this.runTask(() => set(this.context, 'first', 0)); + this.runTask(() => set(this.context, 'first', 0)); - this.assertText('no'); + this.assertText('no'); - this.runTask(() => { - set(this.context, 'first', 'foo'); - set(this.context, 'second', 'bar'); - }); + this.runTask(() => { + set(this.context, 'first', 'foo'); + set(this.context, 'second', 'bar'); + }); - this.assertText('yes'); - } + this.assertText('yes'); + } + + ['@test once if finds the first falsy argument, the following arguments are not evaluated']() { + let didInvokeFirst = false; + let didInvokeSecond = false; + let didInvokeThird = false; + let FooBarComponent = Component.extend({ + first: computed(function() { + didInvokeFirst = true; + return true; + }), + second: computed(function() { + didInvokeSecond = true; + return false; + }), + third: computed(function() { + didInvokeThird = true; + return 'foo§'; + }), + }); + + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + template: `{{and first second third}}`, + }); + + this.render(`{{foo-bar}}`, {}); + + this.assertText('false'); + + this.runTask(() => this.rerender()); + + this.assertText('false'); - ['@test once if finds the first falsy argument, the following arguments are not evaluated']() { - let didInvokeFirst = false; - let didInvokeSecond = false; - let didInvokeThird = false; - let FooBarComponent = Component.extend({ - first: computed(function() { - didInvokeFirst = true; - return true; - }), - second: computed(function() { - didInvokeSecond = true; - return false; - }), - third: computed(function() { - didInvokeThird = true; - return 'foo§'; - }), - }); - - this.registerComponent('foo-bar', { - ComponentClass: FooBarComponent, - template: `{{and first second third}}`, - }); - - this.render(`{{foo-bar}}`, {}); - - this.assertText('false'); - - this.runTask(() => this.rerender()); - - this.assertText('false'); - - this.assert.ok(didInvokeFirst, 'the `first` property was accessed'); - this.assert.ok(didInvokeSecond, 'the `second` property was accessed'); - this.assert.notOk(didInvokeThird, "the `third` property wasn't accessed"); + this.assert.ok(didInvokeFirst, 'the `first` property was accessed'); + this.assert.ok(didInvokeSecond, 'the `second` property was accessed'); + this.assert.notOk(didInvokeThird, "the `third` property wasn't accessed"); + } } - } -); + ); +} diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/eq-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/eq-test.js index dd1dc6c1e6e..92907cdccb6 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/eq-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/eq-test.js @@ -1,56 +1,59 @@ import { RenderingTest, moduleFor } from '../../utils/test-case'; import { set } from '@ember/-internals/metal'; +import { EMBER_BASIC_TEMPLATE_HELPERS } from '@ember/canary-features'; -moduleFor( - 'Helpers test: {{eq}}', - class extends RenderingTest { - ['@test it compares static arguments that are equal']() { - this.render(`{{eq "foo" "foo"}}`); - this.assertText('true'); - } +if (EMBER_BASIC_TEMPLATE_HELPERS) { + moduleFor( + 'Helpers test: {{eq}}', + class extends RenderingTest { + ['@test it compares static arguments that are equal']() { + this.render(`{{eq "foo" "foo"}}`); + this.assertText('true'); + } - ['@test it compares static arguments that are different']() { - this.render(`{{eq "foo" "bar"}}`); - this.assertText('false'); - } + ['@test it compares static arguments that are different']() { + this.render(`{{eq "foo" "bar"}}`); + this.assertText('false'); + } - ['@test it updates for bound arguments']() { - this.render(`{{eq first second}}`, { first: 'one', second: 'two' }); + ['@test it updates for bound arguments']() { + this.render(`{{eq first second}}`, { first: 'one', second: 'two' }); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => set(this.context, 'first', 'two')); + this.runTask(() => set(this.context, 'first', 'two')); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => set(this.context, 'second', '2')); + this.runTask(() => set(this.context, 'second', '2')); - this.assertText('false'); - } + this.assertText('false'); + } - ['@test it can be used as a sub-expression']() { - this.render(`{{if (eq first second) "equal" "different"}}`, { first: 'one', second: 'two' }); + ['@test it can be used as a sub-expression']() { + this.render(`{{if (eq first second) "equal" "different"}}`, { first: 'one', second: 'two' }); - this.assertText('different'); + this.assertText('different'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('different'); + this.assertText('different'); - this.runTask(() => set(this.context, 'first', 'two')); + this.runTask(() => set(this.context, 'first', 'two')); - this.assertText('equal'); + this.assertText('equal'); - this.runTask(() => { - set(this.context, 'first', '1'); - set(this.context, 'second', '2'); - }); + this.runTask(() => { + set(this.context, 'first', '1'); + set(this.context, 'second', '2'); + }); - this.assertText('different'); + this.assertText('different'); + } } - } -); + ); +} diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/gt-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/gt-test.js index 487da04b42d..3a458b06573 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/gt-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/gt-test.js @@ -2,144 +2,147 @@ import { RenderingTest, moduleFor } from '../../utils/test-case'; import { set } from '@ember/-internals/metal'; import { Component } from '../../utils/helpers'; import { computed } from '@ember/-internals/metal'; +import { EMBER_BASIC_TEMPLATE_HELPERS } from '@ember/canary-features'; -moduleFor( - 'Helpers test: {{gt}}', - class extends RenderingTest { - ['@test returns true when the first static argument is bigger than the second one']() { - this.render(`{{gt 2 1}}`); - this.assertText('true'); - } +if (EMBER_BASIC_TEMPLATE_HELPERS) { + moduleFor( + 'Helpers test: {{gt}}', + class extends RenderingTest { + ['@test returns true when the first static argument is bigger than the second one']() { + this.render(`{{gt 2 1}}`); + this.assertText('true'); + } - ['@test returns false when the first static argument is not bigger than the second one']() { - this.render(`{{gt 0 1}}`); - this.assertText('false'); - } + ['@test returns false when the first static argument is not bigger than the second one']() { + this.render(`{{gt 0 1}}`); + this.assertText('false'); + } - ['@test returns false when both arguments are the same']() { - this.render(`{{gt 1 1}}`); - this.assertText('false'); - } + ['@test returns false when both arguments are the same']() { + this.render(`{{gt 1 1}}`); + this.assertText('false'); + } - ['@test it updates for bound arguments']() { - this.render(`{{gt left right}}`, { left: 1, right: 2 }); + ['@test it updates for bound arguments']() { + this.render(`{{gt left right}}`, { left: 1, right: 2 }); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => set(this.context, 'left', 3)); + this.runTask(() => set(this.context, 'left', 3)); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => set(this.context, 'right', 4)); + this.runTask(() => set(this.context, 'right', 4)); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => set(this.context, 'left', 5)); + this.runTask(() => set(this.context, 'left', 5)); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => set(this.context, 'right', 5)); + this.runTask(() => set(this.context, 'right', 5)); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => set(this.context, 'right', null)); + this.runTask(() => set(this.context, 'right', null)); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => set(this.context, 'left', -1)); + this.runTask(() => set(this.context, 'left', -1)); - this.assertText('false'); - } + this.assertText('false'); + } - ['@test it can be used as a sub-expression']() { - this.render(`{{if (gt left right) "yes" "no"}}`, { left: 1, right: 2 }); + ['@test it can be used as a sub-expression']() { + this.render(`{{if (gt left right) "yes" "no"}}`, { left: 1, right: 2 }); - this.assertText('no'); + this.assertText('no'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('no'); + this.assertText('no'); - this.runTask(() => set(this.context, 'left', 3)); + this.runTask(() => set(this.context, 'left', 3)); - this.assertText('yes'); + this.assertText('yes'); - this.runTask(() => set(this.context, 'right', 4)); + this.runTask(() => set(this.context, 'right', 4)); - this.assertText('no'); + this.assertText('no'); - this.runTask(() => { - set(this.context, 'left', 5); - set(this.context, 'right', 0); - }); + this.runTask(() => { + set(this.context, 'left', 5); + set(this.context, 'right', 0); + }); - this.assertText('yes'); - } + this.assertText('yes'); + } - ['@test of the first argument is undefined, it never pulls the second argument']() { - let didInvokeLeft = false; - let didInvokeRight = false; - let FooBarComponent = Component.extend({ - left: computed(function() { - didInvokeLeft = true; - return undefined; - }), - right: computed(function() { - didInvokeRight = true; - return 5; - }), - }); + ['@test of the first argument is undefined, it never pulls the second argument']() { + let didInvokeLeft = false; + let didInvokeRight = false; + let FooBarComponent = Component.extend({ + left: computed(function() { + didInvokeLeft = true; + return undefined; + }), + right: computed(function() { + didInvokeRight = true; + return 5; + }), + }); - this.registerComponent('foo-bar', { - ComponentClass: FooBarComponent, - template: `{{gt left right}}`, - }); + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + template: `{{gt left right}}`, + }); - this.render(`{{foo-bar}}`, {}); + this.render(`{{foo-bar}}`, {}); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('false'); + this.assertText('false'); - this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); - this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); - } + this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); + this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); + } - ['@test of the first argument is null, it never pulls the second argument']() { - let didInvokeLeft = false; - let didInvokeRight = false; - let FooBarComponent = Component.extend({ - left: computed(function() { - didInvokeLeft = true; - return null; - }), - right: computed(function() { - didInvokeRight = true; - return 5; - }), - }); + ['@test of the first argument is null, it never pulls the second argument']() { + let didInvokeLeft = false; + let didInvokeRight = false; + let FooBarComponent = Component.extend({ + left: computed(function() { + didInvokeLeft = true; + return null; + }), + right: computed(function() { + didInvokeRight = true; + return 5; + }), + }); - this.registerComponent('foo-bar', { - ComponentClass: FooBarComponent, - template: `{{gt left right}}`, - }); + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + template: `{{gt left right}}`, + }); - this.render(`{{foo-bar}}`, {}); + this.render(`{{foo-bar}}`, {}); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('false'); + this.assertText('false'); - this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); - this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); + this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); + this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); + } } - } -); + ); +} diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/gte-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/gte-test.js index 6bf154db5d7..b68faf1a02a 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/gte-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/gte-test.js @@ -2,148 +2,151 @@ import { RenderingTest, moduleFor } from '../../utils/test-case'; import { set } from '@ember/-internals/metal'; import { Component } from '../../utils/helpers'; import { computed } from '@ember/-internals/metal'; +import { EMBER_BASIC_TEMPLATE_HELPERS } from '@ember/canary-features'; -moduleFor( - 'Helpers test: {{gte}}', - class extends RenderingTest { - ['@test returns true when the first static argument is bigger than the second one']() { - this.render(`{{gte 2 1}}`); - this.assertText('true'); - } +if (EMBER_BASIC_TEMPLATE_HELPERS) { + moduleFor( + 'Helpers test: {{gte}}', + class extends RenderingTest { + ['@test returns true when the first static argument is bigger than the second one']() { + this.render(`{{gte 2 1}}`); + this.assertText('true'); + } - ['@test returns false when the first static argument is not bigger than the second one']() { - this.render(`{{gte 0 1}}`); - this.assertText('false'); - } + ['@test returns false when the first static argument is not bigger than the second one']() { + this.render(`{{gte 0 1}}`); + this.assertText('false'); + } - ['@test returns true when both arguments are the same']() { - this.render(`{{gte 1 1}}`); - this.assertText('true'); - } + ['@test returns true when both arguments are the same']() { + this.render(`{{gte 1 1}}`); + this.assertText('true'); + } - ['@test it updates for bound arguments']() { - this.render(`{{gte left right}}`, { left: 1, right: 2 }); + ['@test it updates for bound arguments']() { + this.render(`{{gte left right}}`, { left: 1, right: 2 }); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => set(this.context, 'left', 3)); + this.runTask(() => set(this.context, 'left', 3)); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => set(this.context, 'right', 4)); + this.runTask(() => set(this.context, 'right', 4)); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => set(this.context, 'left', 5)); + this.runTask(() => set(this.context, 'left', 5)); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => set(this.context, 'right', 5)); + this.runTask(() => set(this.context, 'right', 5)); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => set(this.context, 'right', null)); + this.runTask(() => set(this.context, 'right', null)); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => set(this.context, 'left', -1)); + this.runTask(() => set(this.context, 'left', -1)); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => set(this.context, 'left', 0)); + this.runTask(() => set(this.context, 'left', 0)); - this.assertText('true'); - } + this.assertText('true'); + } - ['@test it can be used as a sub-expression']() { - this.render(`{{if (gt left right) "yes" "no"}}`, { left: 1, right: 2 }); + ['@test it can be used as a sub-expression']() { + this.render(`{{if (gt left right) "yes" "no"}}`, { left: 1, right: 2 }); - this.assertText('no'); + this.assertText('no'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('no'); + this.assertText('no'); - this.runTask(() => set(this.context, 'left', 3)); + this.runTask(() => set(this.context, 'left', 3)); - this.assertText('yes'); + this.assertText('yes'); - this.runTask(() => set(this.context, 'right', 4)); + this.runTask(() => set(this.context, 'right', 4)); - this.assertText('no'); + this.assertText('no'); - this.runTask(() => { - set(this.context, 'left', 5); - set(this.context, 'right', 0); - }); + this.runTask(() => { + set(this.context, 'left', 5); + set(this.context, 'right', 0); + }); - this.assertText('yes'); - } + this.assertText('yes'); + } - ['@test of the first argument is undefined, it never pulls the second argument']() { - let didInvokeLeft = false; - let didInvokeRight = false; - let FooBarComponent = Component.extend({ - left: computed(function() { - didInvokeLeft = true; - return undefined; - }), - right: computed(function() { - didInvokeRight = true; - return 5; - }), - }); + ['@test of the first argument is undefined, it never pulls the second argument']() { + let didInvokeLeft = false; + let didInvokeRight = false; + let FooBarComponent = Component.extend({ + left: computed(function() { + didInvokeLeft = true; + return undefined; + }), + right: computed(function() { + didInvokeRight = true; + return 5; + }), + }); - this.registerComponent('foo-bar', { - ComponentClass: FooBarComponent, - template: `{{gte left right}}`, - }); + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + template: `{{gte left right}}`, + }); - this.render(`{{foo-bar}}`, {}); + this.render(`{{foo-bar}}`, {}); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('false'); + this.assertText('false'); - this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); - this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); - } + this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); + this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); + } - ['@test of the first argument is null, it never pulls the second argument']() { - let didInvokeLeft = false; - let didInvokeRight = false; - let FooBarComponent = Component.extend({ - left: computed(function() { - didInvokeLeft = true; - return null; - }), - right: computed(function() { - didInvokeRight = true; - return 5; - }), - }); + ['@test of the first argument is null, it never pulls the second argument']() { + let didInvokeLeft = false; + let didInvokeRight = false; + let FooBarComponent = Component.extend({ + left: computed(function() { + didInvokeLeft = true; + return null; + }), + right: computed(function() { + didInvokeRight = true; + return 5; + }), + }); - this.registerComponent('foo-bar', { - ComponentClass: FooBarComponent, - template: `{{gte left right}}`, - }); + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + template: `{{gte left right}}`, + }); - this.render(`{{foo-bar}}`, {}); + this.render(`{{foo-bar}}`, {}); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('false'); + this.assertText('false'); - this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); - this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); + this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); + this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); + } } - } -); + ); +} diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/lt-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/lt-test.js index e4bf66f50bc..263767107bf 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/lt-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/lt-test.js @@ -2,144 +2,147 @@ import { RenderingTest, moduleFor } from '../../utils/test-case'; import { set } from '@ember/-internals/metal'; import { Component } from '../../utils/helpers'; import { computed } from '@ember/-internals/metal'; +import { EMBER_BASIC_TEMPLATE_HELPERS } from '@ember/canary-features'; -moduleFor( - 'Helpers test: {{lt}}', - class extends RenderingTest { - ['@test returns false when the first static argument is bigger than the second one']() { - this.render(`{{lt 2 1}}`); - this.assertText('false'); - } +if (EMBER_BASIC_TEMPLATE_HELPERS) { + moduleFor( + 'Helpers test: {{lt}}', + class extends RenderingTest { + ['@test returns false when the first static argument is bigger than the second one']() { + this.render(`{{lt 2 1}}`); + this.assertText('false'); + } - ['@test returns true when the first static argument is not bigger than the second one']() { - this.render(`{{lt 0 1}}`); - this.assertText('true'); - } + ['@test returns true when the first static argument is not bigger than the second one']() { + this.render(`{{lt 0 1}}`); + this.assertText('true'); + } - ['@test returns false when both arguments are the same']() { - this.render(`{{lt 1 1}}`); - this.assertText('false'); - } + ['@test returns false when both arguments are the same']() { + this.render(`{{lt 1 1}}`); + this.assertText('false'); + } - ['@test it updates for bound arguments']() { - this.render(`{{lt left right}}`, { left: 1, right: 2 }); + ['@test it updates for bound arguments']() { + this.render(`{{lt left right}}`, { left: 1, right: 2 }); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => set(this.context, 'left', 3)); + this.runTask(() => set(this.context, 'left', 3)); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => set(this.context, 'right', 4)); + this.runTask(() => set(this.context, 'right', 4)); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => set(this.context, 'left', 5)); + this.runTask(() => set(this.context, 'left', 5)); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => set(this.context, 'right', 5)); + this.runTask(() => set(this.context, 'right', 5)); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => set(this.context, 'right', null)); + this.runTask(() => set(this.context, 'right', null)); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => set(this.context, 'left', -1)); + this.runTask(() => set(this.context, 'left', -1)); - this.assertText('true'); - } + this.assertText('true'); + } - ['@test it can be used as a sub-expression']() { - this.render(`{{if (lt left right) "yes" "no"}}`, { left: 1, right: 2 }); + ['@test it can be used as a sub-expression']() { + this.render(`{{if (lt left right) "yes" "no"}}`, { left: 1, right: 2 }); - this.assertText('yes'); + this.assertText('yes'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('yes'); + this.assertText('yes'); - this.runTask(() => set(this.context, 'left', 3)); + this.runTask(() => set(this.context, 'left', 3)); - this.assertText('no'); + this.assertText('no'); - this.runTask(() => set(this.context, 'right', 4)); + this.runTask(() => set(this.context, 'right', 4)); - this.assertText('yes'); + this.assertText('yes'); - this.runTask(() => { - set(this.context, 'left', 5); - set(this.context, 'right', 0); - }); + this.runTask(() => { + set(this.context, 'left', 5); + set(this.context, 'right', 0); + }); - this.assertText('no'); - } + this.assertText('no'); + } - ['@test of the first argument is undefined, it never pulls the second argument']() { - let didInvokeLeft = false; - let didInvokeRight = false; - let FooBarComponent = Component.extend({ - left: computed(function() { - didInvokeLeft = true; - return undefined; - }), - right: computed(function() { - didInvokeRight = true; - return 5; - }), - }); + ['@test of the first argument is undefined, it never pulls the second argument']() { + let didInvokeLeft = false; + let didInvokeRight = false; + let FooBarComponent = Component.extend({ + left: computed(function() { + didInvokeLeft = true; + return undefined; + }), + right: computed(function() { + didInvokeRight = true; + return 5; + }), + }); - this.registerComponent('foo-bar', { - ComponentClass: FooBarComponent, - template: `{{lt left right}}`, - }); + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + template: `{{lt left right}}`, + }); - this.render(`{{foo-bar}}`, {}); + this.render(`{{foo-bar}}`, {}); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('false'); + this.assertText('false'); - this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); - this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); - } + this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); + this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); + } - ['@test of the first argument is null, it never pulls the second argument']() { - let didInvokeLeft = false; - let didInvokeRight = false; - let FooBarComponent = Component.extend({ - left: computed(function() { - didInvokeLeft = true; - return null; - }), - right: computed(function() { - didInvokeRight = true; - return 5; - }), - }); + ['@test of the first argument is null, it never pulls the second argument']() { + let didInvokeLeft = false; + let didInvokeRight = false; + let FooBarComponent = Component.extend({ + left: computed(function() { + didInvokeLeft = true; + return null; + }), + right: computed(function() { + didInvokeRight = true; + return 5; + }), + }); - this.registerComponent('foo-bar', { - ComponentClass: FooBarComponent, - template: `{{lt left right}}`, - }); + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + template: `{{lt left right}}`, + }); - this.render(`{{foo-bar}}`, {}); + this.render(`{{foo-bar}}`, {}); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('false'); + this.assertText('false'); - this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); - this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); + this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); + this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); + } } - } -); + ); +} diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/lte-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/lte-test.js index 5d7d75574ee..416458734bd 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/lte-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/lte-test.js @@ -2,144 +2,147 @@ import { RenderingTest, moduleFor } from '../../utils/test-case'; import { set } from '@ember/-internals/metal'; import { Component } from '../../utils/helpers'; import { computed } from '@ember/-internals/metal'; +import { EMBER_BASIC_TEMPLATE_HELPERS } from '@ember/canary-features'; -moduleFor( - 'Helpers test: {{lte}}', - class extends RenderingTest { - ['@test returns false when the first static argument is bigger than the second one']() { - this.render(`{{lte 2 1}}`); - this.assertText('false'); - } +if (EMBER_BASIC_TEMPLATE_HELPERS) { + moduleFor( + 'Helpers test: {{lte}}', + class extends RenderingTest { + ['@test returns false when the first static argument is bigger than the second one']() { + this.render(`{{lte 2 1}}`); + this.assertText('false'); + } - ['@test returns true when the first static argument is not bigger than the second one']() { - this.render(`{{lte 0 1}}`); - this.assertText('true'); - } + ['@test returns true when the first static argument is not bigger than the second one']() { + this.render(`{{lte 0 1}}`); + this.assertText('true'); + } - ['@test returns true when both arguments are the same']() { - this.render(`{{lte 1 1}}`); - this.assertText('true'); - } + ['@test returns true when both arguments are the same']() { + this.render(`{{lte 1 1}}`); + this.assertText('true'); + } - ['@test it updates for bound arguments']() { - this.render(`{{lte left right}}`, { left: 1, right: 2 }); + ['@test it updates for bound arguments']() { + this.render(`{{lte left right}}`, { left: 1, right: 2 }); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => set(this.context, 'left', 3)); + this.runTask(() => set(this.context, 'left', 3)); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => set(this.context, 'right', 4)); + this.runTask(() => set(this.context, 'right', 4)); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => set(this.context, 'left', 5)); + this.runTask(() => set(this.context, 'left', 5)); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => set(this.context, 'right', 5)); + this.runTask(() => set(this.context, 'right', 5)); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => set(this.context, 'right', null)); + this.runTask(() => set(this.context, 'right', null)); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => set(this.context, 'left', 0)); + this.runTask(() => set(this.context, 'left', 0)); - this.assertText('true'); - } + this.assertText('true'); + } - ['@test it can be used as a sub-expression']() { - this.render(`{{if (lt left right) "yes" "no"}}`, { left: 1, right: 2 }); + ['@test it can be used as a sub-expression']() { + this.render(`{{if (lt left right) "yes" "no"}}`, { left: 1, right: 2 }); - this.assertText('yes'); + this.assertText('yes'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('yes'); + this.assertText('yes'); - this.runTask(() => set(this.context, 'left', 3)); + this.runTask(() => set(this.context, 'left', 3)); - this.assertText('no'); + this.assertText('no'); - this.runTask(() => set(this.context, 'right', 4)); + this.runTask(() => set(this.context, 'right', 4)); - this.assertText('yes'); + this.assertText('yes'); - this.runTask(() => { - set(this.context, 'left', 5); - set(this.context, 'right', 0); - }); + this.runTask(() => { + set(this.context, 'left', 5); + set(this.context, 'right', 0); + }); - this.assertText('no'); - } + this.assertText('no'); + } - ['@test of the first argument is undefined, it never pulls the second argument']() { - let didInvokeLeft = false; - let didInvokeRight = false; - let FooBarComponent = Component.extend({ - left: computed(function() { - didInvokeLeft = true; - return undefined; - }), - right: computed(function() { - didInvokeRight = true; - return 5; - }), - }); + ['@test of the first argument is undefined, it never pulls the second argument']() { + let didInvokeLeft = false; + let didInvokeRight = false; + let FooBarComponent = Component.extend({ + left: computed(function() { + didInvokeLeft = true; + return undefined; + }), + right: computed(function() { + didInvokeRight = true; + return 5; + }), + }); - this.registerComponent('foo-bar', { - ComponentClass: FooBarComponent, - template: `{{lte left right}}`, - }); + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + template: `{{lte left right}}`, + }); - this.render(`{{foo-bar}}`, {}); + this.render(`{{foo-bar}}`, {}); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('false'); + this.assertText('false'); - this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); - this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); - } + this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); + this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); + } - ['@test of the first argument is null, it never pulls the second argument']() { - let didInvokeLeft = false; - let didInvokeRight = false; - let FooBarComponent = Component.extend({ - left: computed(function() { - didInvokeLeft = true; - return null; - }), - right: computed(function() { - didInvokeRight = true; - return 5; - }), - }); + ['@test of the first argument is null, it never pulls the second argument']() { + let didInvokeLeft = false; + let didInvokeRight = false; + let FooBarComponent = Component.extend({ + left: computed(function() { + didInvokeLeft = true; + return null; + }), + right: computed(function() { + didInvokeRight = true; + return 5; + }), + }); - this.registerComponent('foo-bar', { - ComponentClass: FooBarComponent, - template: `{{lte left right}}`, - }); + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + template: `{{lte left right}}`, + }); - this.render(`{{foo-bar}}`, {}); + this.render(`{{foo-bar}}`, {}); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('false'); + this.assertText('false'); - this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); - this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); + this.assert.ok(didInvokeLeft, 'the `left` property was accessed'); + this.assert.notOk(didInvokeRight, "the `right` property wasn't accessed"); + } } - } -); + ); +} diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/not-eq-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/not-eq-test.js index e33f6ff4388..600e7630050 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/not-eq-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/not-eq-test.js @@ -1,59 +1,62 @@ import { RenderingTest, moduleFor } from '../../utils/test-case'; import { set } from '@ember/-internals/metal'; +import { EMBER_BASIC_TEMPLATE_HELPERS } from '@ember/canary-features'; -moduleFor( - 'Helpers test: {{not-eq}}', - class extends RenderingTest { - ['@test it compares static arguments that are equal']() { - this.render(`{{not-eq "foo" "foo"}}`); - this.assertText('false'); - } +if (EMBER_BASIC_TEMPLATE_HELPERS) { + moduleFor( + 'Helpers test: {{not-eq}}', + class extends RenderingTest { + ['@test it compares static arguments that are equal']() { + this.render(`{{not-eq "foo" "foo"}}`); + this.assertText('false'); + } - ['@test it compares static arguments that are different']() { - this.render(`{{not-eq "foo" "bar"}}`); - this.assertText('true'); - } + ['@test it compares static arguments that are different']() { + this.render(`{{not-eq "foo" "bar"}}`); + this.assertText('true'); + } - ['@test it updates for bound arguments']() { - this.render(`{{not-eq first second}}`, { first: 'one', second: 'two' }); + ['@test it updates for bound arguments']() { + this.render(`{{not-eq first second}}`, { first: 'one', second: 'two' }); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => set(this.context, 'first', 'two')); + this.runTask(() => set(this.context, 'first', 'two')); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => set(this.context, 'second', '2')); + this.runTask(() => set(this.context, 'second', '2')); - this.assertText('true'); - } + this.assertText('true'); + } - ['@test it can be used as a sub-expression']() { - this.render(`{{if (not-eq first second) "different" "equal"}}`, { - first: 'one', - second: 'two', - }); + ['@test it can be used as a sub-expression']() { + this.render(`{{if (not-eq first second) "different" "equal"}}`, { + first: 'one', + second: 'two', + }); - this.assertText('different'); + this.assertText('different'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('different'); + this.assertText('different'); - this.runTask(() => set(this.context, 'first', 'two')); + this.runTask(() => set(this.context, 'first', 'two')); - this.assertText('equal'); + this.assertText('equal'); - this.runTask(() => { - set(this.context, 'first', '1'); - set(this.context, 'second', '2'); - }); + this.runTask(() => { + set(this.context, 'first', '1'); + set(this.context, 'second', '2'); + }); - this.assertText('different'); + this.assertText('different'); + } } - } -); + ); +} diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/not-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/not-test.js index c636e393e5d..a081da9c805 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/not-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/not-test.js @@ -1,57 +1,60 @@ import { RenderingTest, moduleFor } from '../../utils/test-case'; import { set } from '@ember/-internals/metal'; +import { EMBER_BASIC_TEMPLATE_HELPERS } from '@ember/canary-features'; -moduleFor( - 'Helpers test: {{not}}', - class extends RenderingTest { - ['@test returns true for falsy static arguments']() { - this.render(`{{not false}}`); - this.assertText('true'); - } +if (EMBER_BASIC_TEMPLATE_HELPERS) { + moduleFor( + 'Helpers test: {{not}}', + class extends RenderingTest { + ['@test returns true for falsy static arguments']() { + this.render(`{{not false}}`); + this.assertText('true'); + } - ['@test returns false for truthy static arguments']() { - this.render(`{{not 42}}`); - this.assertText('false'); - } + ['@test returns false for truthy static arguments']() { + this.render(`{{not 42}}`); + this.assertText('false'); + } - ['@test it updates for bound arguments']() { - this.render(`{{not argument}}`, { argument: 0 }); + ['@test it updates for bound arguments']() { + this.render(`{{not argument}}`, { argument: 0 }); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => set(this.context, 'argument', 1)); + this.runTask(() => set(this.context, 'argument', 1)); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => set(this.context, 'argument', false)); + this.runTask(() => set(this.context, 'argument', false)); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => set(this.context, 'argument', 'false')); + this.runTask(() => set(this.context, 'argument', 'false')); - this.assertText('false'); + this.assertText('false'); - this.runTask(() => set(this.context, 'argument', true)); + this.runTask(() => set(this.context, 'argument', true)); - this.assertText('false'); - } + this.assertText('false'); + } - ['@test it can be used as a sub-expression']() { - this.render(`{{if (not disabled) "enabled" "disabled"}}`, { disabled: false }); + ['@test it can be used as a sub-expression']() { + this.render(`{{if (not disabled) "enabled" "disabled"}}`, { disabled: false }); - this.assertText('enabled'); + this.assertText('enabled'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('enabled'); + this.assertText('enabled'); - this.runTask(() => set(this.context, 'disabled', true)); + this.runTask(() => set(this.context, 'disabled', true)); - this.assertText('disabled'); + this.assertText('disabled'); + } } - } -); + ); +} diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/or-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/or-test.js index 416e1ada6c6..f09faa16d7b 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/or-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/or-test.js @@ -2,95 +2,98 @@ import { RenderingTest, moduleFor } from '../../utils/test-case'; import { set } from '@ember/-internals/metal'; import { Component } from '../../utils/helpers'; import { computed } from '@ember/-internals/metal'; +import { EMBER_BASIC_TEMPLATE_HELPERS } from '@ember/canary-features'; -moduleFor( - 'Helpers test: {{or}}', - class extends RenderingTest { - ['@test returns the first truthy argument']() { - this.render(`{{or false 0 "foo"}}`); - this.assertText('foo'); - } +if (EMBER_BASIC_TEMPLATE_HELPERS) { + moduleFor( + 'Helpers test: {{or}}', + class extends RenderingTest { + ['@test returns the first truthy argument']() { + this.render(`{{or false 0 "foo"}}`); + this.assertText('foo'); + } - ['@test if all arguments are falsy, it return the last argument']() { - this.render(`{{or false "" 0}}`); - this.assertText('0'); - } + ['@test if all arguments are falsy, it return the last argument']() { + this.render(`{{or false "" 0}}`); + this.assertText('0'); + } - ['@test it updates for bound arguments']() { - this.render(`{{or first second third}}`, { first: 1, second: true, third: 'foo' }); + ['@test it updates for bound arguments']() { + this.render(`{{or first second third}}`, { first: 1, second: true, third: 'foo' }); - this.assertText('1'); + this.assertText('1'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('1'); + this.assertText('1'); - this.runTask(() => set(this.context, 'first', false)); + this.runTask(() => set(this.context, 'first', false)); - this.assertText('true'); + this.assertText('true'); - this.runTask(() => set(this.context, 'second', 0)); + this.runTask(() => set(this.context, 'second', 0)); - this.assertText('foo'); + this.assertText('foo'); - this.runTask(() => set(this.context, 'third', '')); + this.runTask(() => set(this.context, 'third', '')); - this.assertText(''); - } + this.assertText(''); + } - ['@test it can be used as a sub-expression']() { - this.render(`{{if (or first second) "yes" "no"}}`, { first: 1, second: 2 }); + ['@test it can be used as a sub-expression']() { + this.render(`{{if (or first second) "yes" "no"}}`, { first: 1, second: 2 }); - this.assertText('yes'); + this.assertText('yes'); - this.runTask(() => this.rerender()); + this.runTask(() => this.rerender()); - this.assertText('yes'); + this.assertText('yes'); - this.runTask(() => set(this.context, 'first', false)); + this.runTask(() => set(this.context, 'first', false)); - this.assertText('yes'); + this.assertText('yes'); - this.runTask(() => set(this.context, 'second', 0)); + this.runTask(() => set(this.context, 'second', 0)); - this.assertText('no'); - } + this.assertText('no'); + } + + ['@test once if finds the first truthy argument, the following arguments are not evaluated']() { + let didInvokeFirst = false; + let didInvokeSecond = false; + let didInvokeThird = false; + let FooBarComponent = Component.extend({ + first: computed(function() { + didInvokeFirst = true; + return true; + }), + second: computed(function() { + didInvokeSecond = true; + return false; + }), + third: computed(function() { + didInvokeThird = true; + return 'foo§'; + }), + }); + + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + template: `{{or first second third}}`, + }); + + this.render(`{{foo-bar}}`, {}); + + this.assertText('true'); + + this.runTask(() => this.rerender()); + + this.assertText('true'); - ['@test once if finds the first truthy argument, the following arguments are not evaluated']() { - let didInvokeFirst = false; - let didInvokeSecond = false; - let didInvokeThird = false; - let FooBarComponent = Component.extend({ - first: computed(function() { - didInvokeFirst = true; - return true; - }), - second: computed(function() { - didInvokeSecond = true; - return false; - }), - third: computed(function() { - didInvokeThird = true; - return 'foo§'; - }), - }); - - this.registerComponent('foo-bar', { - ComponentClass: FooBarComponent, - template: `{{or first second third}}`, - }); - - this.render(`{{foo-bar}}`, {}); - - this.assertText('true'); - - this.runTask(() => this.rerender()); - - this.assertText('true'); - - this.assert.ok(didInvokeFirst, 'the `first` property was accessed'); - this.assert.notOk(didInvokeSecond, 'the `second` property was accessed'); - this.assert.notOk(didInvokeThird, "the `third` property wasn't accessed"); + this.assert.ok(didInvokeFirst, 'the `first` property was accessed'); + this.assert.notOk(didInvokeSecond, 'the `second` property was accessed'); + this.assert.notOk(didInvokeThird, "the `third` property wasn't accessed"); + } } - } -); + ); +} diff --git a/packages/@ember/canary-features/index.ts b/packages/@ember/canary-features/index.ts index 4a247f167eb..3769456d87c 100644 --- a/packages/@ember/canary-features/index.ts +++ b/packages/@ember/canary-features/index.ts @@ -18,6 +18,7 @@ export const DEFAULT_FEATURES = { EMBER_TEMPLATE_BLOCK_LET_HELPER: true, EMBER_METAL_TRACKED_PROPERTIES: null, EMBER_GLIMMER_ANGLE_BRACKET_INVOCATION: true, + EMBER_BASIC_TEMPLATE_HELPERS: true, }; /** @@ -88,3 +89,4 @@ export const EMBER_GLIMMER_ANGLE_BRACKET_INVOCATION = featureValue( FEATURES.EMBER_GLIMMER_ANGLE_BRACKET_INVOCATION ); export const GLIMMER_MODIFIER_MANAGER = featureValue(FEATURES.GLIMMER_MODIFIER_MANAGER); +export const EMBER_BASIC_TEMPLATE_HELPERS = featureValue(FEATURES.EMBER_BASIC_TEMPLATE_HELPERS); From 544da6dedf4d84798bc600deca14568e43ce51fc Mon Sep 17 00:00:00 2001 From: Ricardo Mendes Date: Tue, 6 Nov 2018 12:57:41 +0000 Subject: [PATCH 13/21] fix linting errors --- packages/@ember/-internals/glimmer/lib/resolver.ts | 2 +- .../-internals/glimmer/tests/integration/helpers/eq-test.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/@ember/-internals/glimmer/lib/resolver.ts b/packages/@ember/-internals/glimmer/lib/resolver.ts index 17b6aa3f26d..ac16a92624c 100644 --- a/packages/@ember/-internals/glimmer/lib/resolver.ts +++ b/packages/@ember/-internals/glimmer/lib/resolver.ts @@ -3,10 +3,10 @@ import { ENV } from '@ember/-internals/environment'; import { LookupOptions, Owner, setOwner } from '@ember/-internals/owner'; import { lookupComponent, lookupPartial, OwnedTemplateMeta } from '@ember/-internals/views'; import { + EMBER_BASIC_TEMPLATE_HELPERS, EMBER_MODULE_UNIFICATION, GLIMMER_CUSTOM_COMPONENT_MANAGER, GLIMMER_MODIFIER_MANAGER, - EMBER_BASIC_TEMPLATE_HELPERS, } from '@ember/canary-features'; import { assert } from '@ember/debug'; import { _instrumentStart } from '@ember/instrumentation'; diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/eq-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/eq-test.js index 92907cdccb6..69ee8df1b33 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/eq-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/eq-test.js @@ -35,7 +35,10 @@ if (EMBER_BASIC_TEMPLATE_HELPERS) { } ['@test it can be used as a sub-expression']() { - this.render(`{{if (eq first second) "equal" "different"}}`, { first: 'one', second: 'two' }); + this.render(`{{if (eq first second) "equal" "different"}}`, { + first: 'one', + second: 'two', + }); this.assertText('different'); From b6f5f7ff5f1865d24b18e3754803977177e101e1 Mon Sep 17 00:00:00 2001 From: Ricardo Mendes Date: Tue, 6 Nov 2018 14:13:14 +0100 Subject: [PATCH 14/21] Update packages/@ember/-internals/glimmer/lib/helpers/or.ts Co-Authored-By: cibernox --- packages/@ember/-internals/glimmer/lib/helpers/or.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@ember/-internals/glimmer/lib/helpers/or.ts b/packages/@ember/-internals/glimmer/lib/helpers/or.ts index 0f7058466de..709ddf03b2b 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/or.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/or.ts @@ -19,7 +19,7 @@ import { InternalHelperReference } from '../utils/references'; @public @method or @for Ember.Templates.helpers - @since 2.7.0 + @since 3.7.0 */ function or({ positional: { references } }: CapturedArguments) { let last: any = false; From c72054927e01af527f887ae2db5cdd835cdc8c16 Mon Sep 17 00:00:00 2001 From: Ricardo Mendes Date: Tue, 6 Nov 2018 14:13:17 +0100 Subject: [PATCH 15/21] Update packages/@ember/-internals/glimmer/lib/helpers/not.ts Co-Authored-By: cibernox --- packages/@ember/-internals/glimmer/lib/helpers/not.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@ember/-internals/glimmer/lib/helpers/not.ts b/packages/@ember/-internals/glimmer/lib/helpers/not.ts index 41a3823f446..4553bf97d98 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/not.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/not.ts @@ -19,7 +19,7 @@ import { InternalHelperReference } from '../utils/references'; @public @method not @for Ember.Templates.helpers - @since 2.7.0 + @since 3.7.0 */ function not({ positional: { references } }: CapturedArguments) { return !references[0].value(); From 4ccf90a6b72048291a43ef5fc41cb0fe7af5cfe0 Mon Sep 17 00:00:00 2001 From: Ricardo Mendes Date: Tue, 6 Nov 2018 14:13:21 +0100 Subject: [PATCH 16/21] Update packages/@ember/-internals/glimmer/lib/helpers/not-eq.ts Co-Authored-By: cibernox --- packages/@ember/-internals/glimmer/lib/helpers/not-eq.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@ember/-internals/glimmer/lib/helpers/not-eq.ts b/packages/@ember/-internals/glimmer/lib/helpers/not-eq.ts index efc8f4ab768..2c04608e16b 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/not-eq.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/not-eq.ts @@ -19,7 +19,7 @@ import { InternalHelperReference } from '../utils/references'; @public @method not-eq @for Ember.Templates.helpers - @since 2.7.0 + @since 3.7.0 */ function notEq({ positional: { references } }: CapturedArguments) { return references[0].value() !== references[1].value(); From 8fbdda2273ca09510365b35520b4a76959bd5e0f Mon Sep 17 00:00:00 2001 From: Ricardo Mendes Date: Tue, 6 Nov 2018 14:13:24 +0100 Subject: [PATCH 17/21] Update packages/@ember/-internals/glimmer/lib/helpers/gte.ts Co-Authored-By: cibernox --- packages/@ember/-internals/glimmer/lib/helpers/gte.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@ember/-internals/glimmer/lib/helpers/gte.ts b/packages/@ember/-internals/glimmer/lib/helpers/gte.ts index a1dc1451dce..7a19769cda2 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/gte.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/gte.ts @@ -19,7 +19,7 @@ import { InternalHelperReference } from '../utils/references'; @public @method gte @for Ember.Templates.helpers - @since 2.7.0 + @since 3.7.0 */ function gte({ positional: { references } }: CapturedArguments) { let left = references[0].value(); From 9f8e8a55317a1e7e2f13bc86314af037ed193d15 Mon Sep 17 00:00:00 2001 From: Ricardo Mendes Date: Tue, 6 Nov 2018 14:13:27 +0100 Subject: [PATCH 18/21] Update packages/@ember/-internals/glimmer/lib/helpers/gt.ts Co-Authored-By: cibernox --- packages/@ember/-internals/glimmer/lib/helpers/gt.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@ember/-internals/glimmer/lib/helpers/gt.ts b/packages/@ember/-internals/glimmer/lib/helpers/gt.ts index 1dffc5d5540..993b466cd88 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/gt.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/gt.ts @@ -19,7 +19,7 @@ import { InternalHelperReference } from '../utils/references'; @public @method gt @for Ember.Templates.helpers - @since 2.7.0 + @since 3.7.0 */ function gt({ positional: { references } }: CapturedArguments) { let left = references[0].value(); From f3e4192c49c09aaf72f6786a6cc8a53898d93e97 Mon Sep 17 00:00:00 2001 From: Ricardo Mendes Date: Tue, 6 Nov 2018 14:13:30 +0100 Subject: [PATCH 19/21] Update packages/@ember/-internals/glimmer/lib/helpers/eq.ts Co-Authored-By: cibernox --- packages/@ember/-internals/glimmer/lib/helpers/eq.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@ember/-internals/glimmer/lib/helpers/eq.ts b/packages/@ember/-internals/glimmer/lib/helpers/eq.ts index 3acb464150b..f215fd51d77 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/eq.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/eq.ts @@ -19,7 +19,7 @@ import { InternalHelperReference } from '../utils/references'; @public @method eq @for Ember.Templates.helpers - @since 2.7.0 + @since 3.7.0 */ function eq({ positional: { references } }: CapturedArguments) { return references[0].value() === references[1].value(); From 81e61d7b648754d21171c682a4e08fb492edfa34 Mon Sep 17 00:00:00 2001 From: Ricardo Mendes Date: Tue, 6 Nov 2018 14:13:33 +0100 Subject: [PATCH 20/21] Update packages/@ember/-internals/glimmer/lib/helpers/and.ts Co-Authored-By: cibernox --- packages/@ember/-internals/glimmer/lib/helpers/and.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@ember/-internals/glimmer/lib/helpers/and.ts b/packages/@ember/-internals/glimmer/lib/helpers/and.ts index 31d96855182..657f388014b 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/and.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/and.ts @@ -19,7 +19,7 @@ import { InternalHelperReference } from '../utils/references'; @public @method and @for Ember.Templates.helpers - @since 2.7.0 + @since 3.7.0 */ function and({ positional: { references } }: CapturedArguments) { let last: any = true; From 1b7e613f4455c929010b59dd8d65c0b892ca3b08 Mon Sep 17 00:00:00 2001 From: Miguel Camba Date: Tue, 6 Nov 2018 14:20:37 +0100 Subject: [PATCH 21/21] Add @category ember-basic-template-helpers to docs of all new helpers --- packages/@ember/-internals/glimmer/lib/helpers/and.ts | 1 + packages/@ember/-internals/glimmer/lib/helpers/eq.ts | 1 + packages/@ember/-internals/glimmer/lib/helpers/gt.ts | 1 + packages/@ember/-internals/glimmer/lib/helpers/gte.ts | 1 + packages/@ember/-internals/glimmer/lib/helpers/lt.ts | 3 ++- packages/@ember/-internals/glimmer/lib/helpers/lte.ts | 3 ++- packages/@ember/-internals/glimmer/lib/helpers/not-eq.ts | 1 + packages/@ember/-internals/glimmer/lib/helpers/not.ts | 1 + packages/@ember/-internals/glimmer/lib/helpers/or.ts | 1 + packages/@ember/canary-features/index.ts | 2 +- 10 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/@ember/-internals/glimmer/lib/helpers/and.ts b/packages/@ember/-internals/glimmer/lib/helpers/and.ts index 657f388014b..cc2eda674ca 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/and.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/and.ts @@ -20,6 +20,7 @@ import { InternalHelperReference } from '../utils/references'; @method and @for Ember.Templates.helpers @since 3.7.0 + @category ember-basic-template-helpers */ function and({ positional: { references } }: CapturedArguments) { let last: any = true; diff --git a/packages/@ember/-internals/glimmer/lib/helpers/eq.ts b/packages/@ember/-internals/glimmer/lib/helpers/eq.ts index f215fd51d77..df2b041d784 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/eq.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/eq.ts @@ -20,6 +20,7 @@ import { InternalHelperReference } from '../utils/references'; @method eq @for Ember.Templates.helpers @since 3.7.0 + @category ember-basic-template-helpers */ function eq({ positional: { references } }: CapturedArguments) { return references[0].value() === references[1].value(); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/gt.ts b/packages/@ember/-internals/glimmer/lib/helpers/gt.ts index 993b466cd88..7bb762c19a6 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/gt.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/gt.ts @@ -20,6 +20,7 @@ import { InternalHelperReference } from '../utils/references'; @method gt @for Ember.Templates.helpers @since 3.7.0 + @category ember-basic-template-helpers */ function gt({ positional: { references } }: CapturedArguments) { let left = references[0].value(); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/gte.ts b/packages/@ember/-internals/glimmer/lib/helpers/gte.ts index 7a19769cda2..6f087d328d6 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/gte.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/gte.ts @@ -20,6 +20,7 @@ import { InternalHelperReference } from '../utils/references'; @method gte @for Ember.Templates.helpers @since 3.7.0 + @category ember-basic-template-helpers */ function gte({ positional: { references } }: CapturedArguments) { let left = references[0].value(); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/lt.ts b/packages/@ember/-internals/glimmer/lib/helpers/lt.ts index 90d5339d78d..5571824dedb 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/lt.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/lt.ts @@ -19,7 +19,8 @@ import { InternalHelperReference } from '../utils/references'; @public @method lt @for Ember.Templates.helpers - @since 2.7.0 + @since 3.7.0 + @category ember-basic-template-helpers */ function lt({ positional: { references } }: CapturedArguments) { let left = references[0].value(); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/lte.ts b/packages/@ember/-internals/glimmer/lib/helpers/lte.ts index 85f215f2b5d..13b4bd445b9 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/lte.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/lte.ts @@ -19,7 +19,8 @@ import { InternalHelperReference } from '../utils/references'; @public @method lte @for Ember.Templates.helpers - @since 2.7.0 + @since 3.7.0 + @category ember-basic-template-helpers */ function lte({ positional: { references } }: CapturedArguments) { let left = references[0].value(); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/not-eq.ts b/packages/@ember/-internals/glimmer/lib/helpers/not-eq.ts index 2c04608e16b..de7e1035cd4 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/not-eq.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/not-eq.ts @@ -20,6 +20,7 @@ import { InternalHelperReference } from '../utils/references'; @method not-eq @for Ember.Templates.helpers @since 3.7.0 + @category ember-basic-template-helpers */ function notEq({ positional: { references } }: CapturedArguments) { return references[0].value() !== references[1].value(); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/not.ts b/packages/@ember/-internals/glimmer/lib/helpers/not.ts index 4553bf97d98..123180817a2 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/not.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/not.ts @@ -20,6 +20,7 @@ import { InternalHelperReference } from '../utils/references'; @method not @for Ember.Templates.helpers @since 3.7.0 + @category ember-basic-template-helpers */ function not({ positional: { references } }: CapturedArguments) { return !references[0].value(); diff --git a/packages/@ember/-internals/glimmer/lib/helpers/or.ts b/packages/@ember/-internals/glimmer/lib/helpers/or.ts index 709ddf03b2b..fd86d8a980c 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/or.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/or.ts @@ -20,6 +20,7 @@ import { InternalHelperReference } from '../utils/references'; @method or @for Ember.Templates.helpers @since 3.7.0 + @category ember-basic-template-helpers */ function or({ positional: { references } }: CapturedArguments) { let last: any = false; diff --git a/packages/@ember/canary-features/index.ts b/packages/@ember/canary-features/index.ts index 3769456d87c..476c0f3823b 100644 --- a/packages/@ember/canary-features/index.ts +++ b/packages/@ember/canary-features/index.ts @@ -18,7 +18,7 @@ export const DEFAULT_FEATURES = { EMBER_TEMPLATE_BLOCK_LET_HELPER: true, EMBER_METAL_TRACKED_PROPERTIES: null, EMBER_GLIMMER_ANGLE_BRACKET_INVOCATION: true, - EMBER_BASIC_TEMPLATE_HELPERS: true, + EMBER_BASIC_TEMPLATE_HELPERS: null, }; /**