swc_ecma_compat_es3/
prop_lits.rs

1use swc_ecma_ast::*;
2use swc_ecma_utils::{is_valid_ident, swc_atoms::Atom};
3use swc_ecma_visit::{fold_pass, standard_only_fold, Fold, FoldWith};
4use swc_trace_macro::swc_trace;
5
6/// babel: `transform-property-literals`
7///
8/// # Input
9/// ```js
10/// var foo = {
11///   // changed
12///   "bar": function () {},
13///   "1": function () {},
14///
15///   // not changed
16///   "default": 1,
17///   [a]: 2,
18///   foo: 1
19/// };
20/// ```
21///
22/// # Output
23/// ```js
24/// var foo = {
25///   bar: function () {},
26///   1: function () {},
27///
28///   "default": 1,
29///   [a]: 2,
30///   foo: 1
31/// };
32/// ```
33pub fn property_literals() -> impl Pass {
34    fold_pass(PropertyLiteral)
35}
36
37struct PropertyLiteral;
38
39#[swc_trace]
40impl Fold for PropertyLiteral {
41    standard_only_fold!();
42
43    fn fold_prop_name(&mut self, n: PropName) -> PropName {
44        let n = n.fold_children_with(self);
45
46        match n {
47            PropName::Str(Str {
48                raw, value, span, ..
49            }) if value.as_str().is_some() => {
50                let v = value.as_str().unwrap();
51                if v.is_reserved() || !is_valid_ident(v) {
52                    PropName::Str(Str { span, raw, value })
53                } else {
54                    PropName::Ident(IdentName::new(
55                        // SAFETY: checked above
56                        unsafe { Atom::from_wtf8_unchecked(value.clone()) },
57                        span,
58                    ))
59                }
60            }
61            PropName::Ident(i) => {
62                let IdentName { sym, span, .. } = i;
63                if sym.is_reserved() || sym.contains('-') || sym.contains('.') {
64                    PropName::Str(Str {
65                        span,
66                        raw: None,
67                        value: sym.into(),
68                    })
69                } else {
70                    PropName::Ident(IdentName { span, sym })
71                }
72            }
73            _ => n,
74        }
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use swc_ecma_transforms_testing::test;
81
82    use super::*;
83
84    test!(
85        ::swc_ecma_parser::Syntax::default(),
86        |_| fold_pass(PropertyLiteral),
87        babel_basic,
88        r#"var foo = {
89  // changed
90  "bar": function () {},
91  "1": function () {},
92
93  // not changed
94  "default": 1,
95  [a]: 2,
96  foo: 1
97};"#,
98        ok_if_code_eq
99    );
100
101    test!(
102        ::swc_ecma_parser::Syntax::default(),
103        |_| fold_pass(PropertyLiteral),
104        str_lit,
105        r#"'use strict';
106var x = {
107    'foo.bar': true
108};"#,
109        ok_if_code_eq
110    );
111}