Skip to main content

turbopack_ecmascript/references/
constant_value.rs

1use anyhow::Result;
2use bincode::{Decode, Encode};
3use swc_core::{
4    common::{DUMMY_SP, FileName, SourceMap, sync::Lrc},
5    ecma::{
6        ast::{
7            ArrayLit, EsVersion, Expr, KeyValueProp, Lit, ObjectLit, Prop, PropName, Regex, Str,
8        },
9        parser::{Syntax, parse_file_as_expr},
10    },
11    quote,
12};
13use turbo_rcstr::RcStr;
14use turbo_tasks::{NonLocalValue, Vc, debug::ValueDebugFormat, trace::TraceRawVcs};
15use turbopack_core::{chunk::ChunkingContext, compile_time_info::CompileTimeDefineValue};
16
17use crate::{
18    code_gen::{CodeGen, CodeGeneration},
19    create_visitor,
20    references::AstPath,
21};
22
23#[derive(
24    Clone, Debug, PartialEq, Eq, Hash, TraceRawVcs, ValueDebugFormat, NonLocalValue, Encode, Decode,
25)]
26pub struct ConstantValueCodeGen {
27    value: CompileTimeDefineValue,
28    path: AstPath,
29}
30
31impl ConstantValueCodeGen {
32    pub fn new(value: CompileTimeDefineValue, path: AstPath) -> Self {
33        ConstantValueCodeGen { value, path }
34    }
35    pub async fn code_generation(
36        &self,
37        _chunking_context: Vc<Box<dyn ChunkingContext>>,
38    ) -> Result<CodeGeneration> {
39        let value = self.value.clone();
40
41        let visitor = create_visitor!(self.path, visit_mut_expr, |expr: &mut Expr| {
42            *expr = value_to_expr(&value);
43        });
44
45        Ok(CodeGeneration::visitors(vec![visitor]))
46    }
47}
48
49impl From<ConstantValueCodeGen> for CodeGen {
50    fn from(val: ConstantValueCodeGen) -> Self {
51        CodeGen::ConstantValueCodeGen(val)
52    }
53}
54
55fn value_to_expr(value: &CompileTimeDefineValue) -> Expr {
56    match value {
57        CompileTimeDefineValue::Undefined => {
58            quote!("(\"TURBOPACK compile-time value\", void 0)" as Expr)
59        }
60        CompileTimeDefineValue::Null => {
61            quote!("(\"TURBOPACK compile-time value\", null)" as Expr)
62        }
63        CompileTimeDefineValue::Bool(true) => {
64            quote!("(\"TURBOPACK compile-time value\", true)" as Expr)
65        }
66        CompileTimeDefineValue::Bool(false) => {
67            quote!("(\"TURBOPACK compile-time value\", false)" as Expr)
68        }
69        CompileTimeDefineValue::Number(n) => {
70            quote!("(\"TURBOPACK compile-time value\", $e)" as Expr, e: Expr = (**n).into())
71        }
72        CompileTimeDefineValue::String(s) => {
73            quote!("(\"TURBOPACK compile-time value\", $e)" as Expr, e: Expr = s.as_str().into())
74        }
75        CompileTimeDefineValue::BigInt(n) => {
76            quote!("(\"TURBOPACK compile-time value\", $e)" as Expr, e: Expr = Expr::Lit(Lit::BigInt(n.as_ref().clone().into())))
77        }
78        CompileTimeDefineValue::Regex(pattern, flags) => {
79            quote!("(\"TURBOPACK compile-time value\", $e)" as Expr, e: Expr = Expr::Lit(Lit::Regex(Regex {
80               span: DUMMY_SP,
81               exp: pattern.as_str().into(),
82               flags: flags.as_str().into(),
83            })))
84        }
85        CompileTimeDefineValue::Array(a) => {
86            quote!("(\"TURBOPACK compile-time value\", $e)" as Expr, e: Expr = Expr::Array(ArrayLit {
87                span: DUMMY_SP,
88                elems: a.iter().map(|i| Some(value_to_expr(i).into())).collect(),
89            }))
90        }
91        CompileTimeDefineValue::Object(m) => {
92            quote!("(\"TURBOPACK compile-time value\", $e)" as Expr, e: Expr = Expr::Object(ObjectLit {
93                span: DUMMY_SP,
94                props: m
95                    .iter()
96                    .map(|(k, v)| {
97                        swc_core::ecma::ast::PropOrSpread::Prop(
98                            Prop::KeyValue(KeyValueProp {
99                                key: PropName::Str(Str::from(k.as_str())),
100                                value: value_to_expr(v).into(),
101                            })
102                            .into(),
103                        )
104                    })
105                    .collect(),
106            }))
107        }
108        CompileTimeDefineValue::Evaluate(s) => parse_single_expr_lit(s),
109    }
110}
111
112pub(crate) fn parse_single_expr_lit(expr_lit: &RcStr) -> Expr {
113    let cm = Lrc::new(SourceMap::default());
114    let fm = cm.new_source_file(FileName::Anon.into(), expr_lit.clone());
115    parse_file_as_expr(
116        &fm,
117        Syntax::Es(Default::default()),
118        EsVersion::latest(),
119        None,
120        &mut vec![],
121    )
122    .map_or(
123        quote!("(\"Failed parsed TURBOPACK compile-time value\", $s)" as Expr, s: Expr = expr_lit.as_str().into()),
124        |expr| quote!("(\"TURBOPACK compile-time value\", $e)" as Expr, e: Expr = *expr),
125    )
126}