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