File tree Expand file tree Collapse file tree
@glimmer-workspace/integration-tests/test/keywords
@glimmer/runtime/lib/helpers Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -6,6 +6,40 @@ import { template } from '@ember/template-compiler';
66class KeywordAnd extends RenderTest {
77 static suiteName = 'keyword helper: and' ;
88
9+ @test
10+ 'references are lazy' ( assert : Assert ) {
11+ const obj = {
12+ get a ( ) {
13+ assert . step ( 'a' ) ;
14+ return 1 ;
15+ } ,
16+ get b ( ) {
17+ assert . step ( 'b' ) ;
18+ return 89 ;
19+ } ,
20+ get c ( ) {
21+ assert . step ( 'c' ) ;
22+ return false ;
23+ } ,
24+ get d ( ) {
25+ assert . step ( 'd' ) ;
26+ return 'unexpected!!!' ;
27+ } ,
28+ } ;
29+
30+ const compiled = template ( '{{and obj.a obj.b obj.c obj.d}}' , {
31+ strictMode : true ,
32+ scope : ( ) => ( { obj } ) ,
33+ } ) ;
34+
35+ this . renderComponent ( compiled ) ;
36+ this . assertHTML ( 'false' ) ;
37+ assert . verifySteps (
38+ [ 'a' , 'b' , 'c' ] ,
39+ 'd not evaluated because obj.c was the last to be evaluated and short-circuited'
40+ ) ;
41+ }
42+
943 @test
1044 'explicit scope' ( ) {
1145 let a = 'yes' ;
Original file line number Diff line number Diff line change @@ -6,6 +6,40 @@ import { template } from '@ember/template-compiler';
66class KeywordOr extends RenderTest {
77 static suiteName = 'keyword helper: or' ;
88
9+ @test
10+ 'references are lazy' ( assert : Assert ) {
11+ const obj = {
12+ get a ( ) {
13+ assert . step ( 'a' ) ;
14+ return false ;
15+ } ,
16+ get b ( ) {
17+ assert . step ( 'b' ) ;
18+ return null ;
19+ } ,
20+ get c ( ) {
21+ assert . step ( 'c' ) ;
22+ return 2 ;
23+ } ,
24+ get d ( ) {
25+ assert . step ( 'd' ) ;
26+ return 'unexpected!!!' ;
27+ } ,
28+ } ;
29+
30+ const compiled = template ( '{{or obj.a obj.b obj.c obj.d}}' , {
31+ strictMode : true ,
32+ scope : ( ) => ( { obj } ) ,
33+ } ) ;
34+
35+ this . renderComponent ( compiled ) ;
36+ this . assertHTML ( '2' ) ;
37+ assert . verifySteps (
38+ [ 'a' , 'b' , 'c' ] ,
39+ 'd not evaluated because obj.c was the last to be evaluated and short-circuited'
40+ ) ;
41+ }
42+
943 @test
1044 'explicit scope' ( ) {
1145 let a = false ;
Original file line number Diff line number Diff line change 11import { DEBUG } from '@glimmer/env' ;
2+ import type { CapturedArguments } from '@glimmer/interfaces' ;
23import { toBool } from '@glimmer/global-context' ;
4+ import { createComputeRef , valueForRef } from '@glimmer/reference' ;
35
4- export const and = ( ...args : unknown [ ] ) => {
5- if ( DEBUG && args . length < 2 ) {
6- throw new Error ( `\`and\` expects at least two arguments, but received ${ args . length } .` ) ;
7- }
6+ import { internalHelper } from './internal-helper' ;
87
9- for ( let i = 0 ; i < args . length ; i ++ ) {
10- if ( ! toBool ( args [ i ] ) ) return args [ i ] ;
8+ export const and = internalHelper ( ( { positional } : CapturedArguments ) => {
9+ if ( DEBUG && positional . length < 2 ) {
10+ throw new Error ( `\`and\` expects at least two arguments, but received ${ positional . length } .` ) ;
1111 }
12- return args [ args . length - 1 ] ;
13- } ;
12+
13+ return createComputeRef (
14+ ( ) => {
15+ let last : unknown ;
16+ for ( let i = 0 ; i < positional . length ; i ++ ) {
17+ let arg = positional [ i ] ;
18+ last = arg ? valueForRef ( arg ) : arg ;
19+ if ( ! toBool ( last ) ) return last ;
20+ }
21+ return last ;
22+ } ,
23+ null ,
24+ 'and'
25+ ) ;
26+ } ) ;
Original file line number Diff line number Diff line change 11import { DEBUG } from '@glimmer/env' ;
2+ import type { CapturedArguments } from '@glimmer/interfaces' ;
23import { toBool } from '@glimmer/global-context' ;
4+ import { createComputeRef , valueForRef } from '@glimmer/reference' ;
35
4- export const or = ( ...args : unknown [ ] ) => {
5- if ( DEBUG && args . length < 2 ) {
6- throw new Error ( `\`or\` expects at least two arguments, but received ${ args . length } .` ) ;
7- }
6+ import { internalHelper } from './internal-helper' ;
87
9- for ( let i = 0 ; i < args . length ; i ++ ) {
10- if ( toBool ( args [ i ] ) ) return args [ i ] ;
8+ export const or = internalHelper ( ( { positional } : CapturedArguments ) => {
9+ if ( DEBUG && positional . length < 2 ) {
10+ throw new Error ( `\`or\` expects at least two arguments, but received ${ positional . length } .` ) ;
1111 }
12- return args [ args . length - 1 ] ;
13- } ;
12+
13+ return createComputeRef (
14+ ( ) => {
15+ let last : unknown ;
16+ for ( let i = 0 ; i < positional . length ; i ++ ) {
17+ let arg = positional [ i ] ;
18+ last = arg ? valueForRef ( arg ) : arg ;
19+ if ( toBool ( last ) ) return last ;
20+ }
21+ return last ;
22+ } ,
23+ null ,
24+ 'or'
25+ ) ;
26+ } ) ;
You can’t perform that action at this time.
0 commit comments