turbopack_ecmascript/references/
constant_value.rs1use 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 *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}