@@ -413,6 +413,15 @@ class PipelineExpressionParserWeb {
413413 }
414414 case 'switch_on' :
415415 return _switchOnToExpression (argsMap);
416+ // Boolean combinators / `not` — used as value expressions in add_fields,
417+ // select, etc. (e.g. `Expression.nor(...).as('x')`). Those stages call
418+ // [toExpression] only; [where] uses [toBooleanExpression] directly.
419+ case 'and' :
420+ case 'or' :
421+ case 'xor' :
422+ case 'nor' :
423+ case 'not' :
424+ return _expressionFromBooleanMap (map);
416425 default :
417426 throw FirebaseException (
418427 plugin: 'cloud_firestore' ,
@@ -424,6 +433,24 @@ class PipelineExpressionParserWeb {
424433 }
425434 }
426435
436+ /// Builds a JS value [Expression] from a serialized boolean expression map.
437+ ///
438+ /// The Firebase JS pipeline API represents boolean expressions as values
439+ /// where needed (e.g. aliased add_fields); [toBooleanExpression] already
440+ /// constructs the correct interop objects.
441+ interop.ExpressionJsImpl _expressionFromBooleanMap (
442+ Map <String , dynamic > map,
443+ ) {
444+ final boolExpr = toBooleanExpression (map);
445+ if (boolExpr == null ) {
446+ final n = map[_kName] as String ? ?? '?' ;
447+ throw UnsupportedError (
448+ 'Boolean expression $n requires at least one valid sub-expression' ,
449+ );
450+ }
451+ return boolExpr as interop.ExpressionJsImpl ;
452+ }
453+
427454 interop.ExpressionJsImpl _switchOnToExpression (Map <String , dynamic > argsMap) {
428455 final exprMaps = argsMap['expressions' ] as List <dynamic >? ;
429456 if (exprMaps == null || exprMaps.length < 2 ) {
0 commit comments