Skip to main content

oxc_ecmascript/
to_boolean.rs

1use oxc_ast::ast::Expression;
2
3use crate::GlobalContext;
4
5/// `ToBoolean`
6///
7/// <https://tc39.es/ecma262/multipage/abstract-operations.html#sec-toboolean>
8pub trait ToBoolean<'a> {
9    fn to_boolean(&self, ctx: &impl GlobalContext<'a>) -> Option<bool>;
10}
11
12impl<'a> ToBoolean<'a> for Expression<'a> {
13    fn to_boolean(&self, ctx: &impl GlobalContext<'a>) -> Option<bool> {
14        // 1. If argument is a Boolean, return argument.
15        // 2. If argument is one of undefined, null, +0𝔽, -0𝔽, NaN, 0ℤ, or the empty String, return false.
16        // 3. NOTE: This step is replaced in section B.3.6.1.
17        // 4. Return true.
18        match self {
19            Expression::Identifier(ident) => match ident.name.as_str() {
20                "NaN" | "undefined" if ctx.is_global_reference(ident) => Some(false),
21                "Infinity" if ctx.is_global_reference(ident) => Some(true),
22                _ => None,
23            },
24            Expression::RegExpLiteral(_)
25            | Expression::ArrayExpression(_)
26            | Expression::ArrowFunctionExpression(_)
27            | Expression::ClassExpression(_)
28            | Expression::FunctionExpression(_)
29            | Expression::NewExpression(_)
30            | Expression::ObjectExpression(_) => Some(true),
31            Expression::NullLiteral(_) => Some(false),
32            Expression::BooleanLiteral(boolean_literal) => Some(boolean_literal.value),
33            Expression::NumericLiteral(lit) => {
34                Some(if lit.value.is_nan() { false } else { lit.value != 0.0 })
35            }
36            Expression::BigIntLiteral(big_int_literal) => Some(!big_int_literal.is_zero()),
37            Expression::StringLiteral(string_literal) => Some(!string_literal.value.is_empty()),
38            Expression::TemplateLiteral(template_literal) => {
39                // only for ``
40                template_literal
41                    .quasis
42                    .first()
43                    .filter(|quasi| quasi.tail)
44                    .and_then(|quasi| quasi.value.cooked.as_ref())
45                    .map(|cooked| !cooked.is_empty())
46            }
47            Expression::SequenceExpression(e) => {
48                e.expressions.last().and_then(|expr| expr.to_boolean(ctx))
49            }
50            _ => None,
51        }
52    }
53}