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