@@ -6,19 +6,56 @@ const UNKNOWN = {};
66 * @param {Node } node
77 * @param {boolean } is_class
88 * @param {Set<any> } set
9+ * @param {boolean } is_nested
910 */
10- function gather_possible_values ( node , is_class , set ) {
11+ function gather_possible_values ( node , is_class , set , is_nested = false ) {
12+ if ( set . has ( UNKNOWN ) ) {
13+ // no point traversing any further
14+ return ;
15+ }
16+
1117 if ( node . type === 'Literal' ) {
1218 set . add ( String ( node . value ) ) ;
1319 } else if ( node . type === 'ConditionalExpression' ) {
14- gather_possible_values ( node . consequent , is_class , set ) ;
15- gather_possible_values ( node . alternate , is_class , set ) ;
20+ gather_possible_values ( node . consequent , is_class , set , is_nested ) ;
21+ gather_possible_values ( node . alternate , is_class , set , is_nested ) ;
22+ } else if ( node . type === 'LogicalExpression' ) {
23+ if ( node . operator === '&&' ) {
24+ // && is a special case, because the only way the left
25+ // hand value can be included is if it's falsy. this is
26+ // a bit of extra work but it's worth it because
27+ // `class={[condition && 'blah']}` is common,
28+ // and we don't want to deopt on `condition`
29+ const left = new Set ( ) ;
30+ gather_possible_values ( node . left , is_class , left , is_nested ) ;
31+
32+ if ( left . has ( UNKNOWN ) ) {
33+ // add all non-nullish falsy values, unless this is a `class` attribute that
34+ // will be processed by cslx, in which case falsy values are removed, unless
35+ // they're not inside an array/object (TODO 6.0 remove that last part)
36+ if ( ! is_class || ! is_nested ) {
37+ set . add ( '' ) ;
38+ set . add ( false ) ;
39+ set . add ( NaN ) ;
40+ set . add ( 0 ) ; // -0 and 0n are also falsy, but stringify to '0'
41+ }
42+ } else {
43+ for ( const value of left ) {
44+ if ( ! value ) {
45+ set . add ( value ) ;
46+ }
47+ }
48+ }
49+
50+ gather_possible_values ( node . right , is_class , set , is_nested ) ;
51+ } else {
52+ gather_possible_values ( node . left , is_class , set , is_nested ) ;
53+ gather_possible_values ( node . right , is_class , set , is_nested ) ;
54+ }
1655 } else if ( is_class && node . type === 'ArrayExpression' ) {
1756 for ( const entry of node . elements ) {
1857 if ( entry ) {
19- gather_possible_values ( entry , is_class , set ) ;
20- } else {
21- set . add ( UNKNOWN ) ;
58+ gather_possible_values ( entry , is_class , set , true ) ;
2259 }
2360 }
2461 } else if ( is_class && node . type === 'ObjectExpression' ) {
@@ -43,7 +80,7 @@ function gather_possible_values(node, is_class, set) {
4380/**
4481 * @param {AST.Text | AST.ExpressionTag } chunk
4582 * @param {boolean } is_class
46- * @returns {Set<string> | null }
83+ * @returns {Set<string | number | boolean > | null }
4784 */
4885export function get_possible_values ( chunk , is_class ) {
4986 const values = new Set ( ) ;
0 commit comments