rolldown_plugin_utils/
data_to_esm.rs1use std::fmt::Write as _;
2
3use rolldown_utils::concat_string;
4use serde_json::Value;
5
6use super::constants::THRESHOLD_SIZE;
7
8#[inline]
9fn serialize_value(value: &Value) -> Result<String, serde_json::Error> {
10 let value_as_string = serde_json::to_string(value)?;
11 if value_as_string.len() > THRESHOLD_SIZE && value.is_object() {
12 let value = serde_json::to_string(&value_as_string)?;
13 Ok(concat_string!("/*#__PURE__*/ JSON.parse(", value, ")"))
14 } else {
15 Ok(value_as_string)
16 }
17}
18
19pub fn data_to_esm(data: &Value, named_exports: bool) -> String {
20 if !named_exports || !data.is_object() {
21 return concat_string!("export default ", data.to_string(), ";\n");
22 }
23
24 let data = data.as_object().unwrap();
25 if data.is_empty() {
26 return "export default {};\n".to_string();
27 }
28
29 let mut named_export_code = String::new();
30 let mut default_object_code = String::new();
31 for (key, value) in data {
32 let value = serialize_value(value).expect("Invalid JSON value");
33 if rolldown_utils::ecmascript::is_validate_assignee_identifier_name(key) {
34 writeln!(named_export_code, "export const {key} = {value};").unwrap();
35 writeln!(default_object_code, " {key},").unwrap();
36 } else {
37 let key = serde_json::to_string(key).unwrap();
38 writeln!(default_object_code, " {key}: {value},").unwrap();
39 }
40 }
41
42 default_object_code.truncate(default_object_code.len() - 2);
44
45 concat_string!(named_export_code, "export default {\n", default_object_code, "\n};")
46}
47
48#[cfg(test)]
49mod test {
50 use super::data_to_esm;
51
52 #[test]
53 fn to_esm_named_exports_object() {
54 let data = serde_json::json!({"name": "name"});
55 assert_eq!(
56 "export const name = \"name\";\nexport default {\n name\n};",
57 data_to_esm(&data, true)
58 );
59 }
60
61 #[test]
62 fn to_esm_named_exports_literal() {
63 let data = serde_json::json!(1);
64 assert_eq!("export default 1;\n", data_to_esm(&data, true));
65 }
66
67 #[test]
68 fn to_esm_named_exports_forbidden_ident() {
69 let data = serde_json::json!({"true": true, "\\\"\n": 1234, "eval": 0, "arguments": 0});
70 assert_eq!(
71 "export default {\n \"true\": true,\n \"\\\\\\\"\\n\": 1234,\n \"eval\": 0,\n \"arguments\": 0\n};",
72 data_to_esm(&data, true)
73 );
74 }
75
76 #[test]
77 fn to_esm_named_exports_multiple_fields() {
78 let data = serde_json::json!({"foo": "foo", "bar": "bar"});
79 assert_eq!(
80 "export const foo = \"foo\";\nexport const bar = \"bar\";\nexport default {\n foo,\n bar\n};",
81 data_to_esm(&data, true)
82 );
83 }
84}