1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use swc_common::util::take::Take;
use swc_ecma_ast::*;
use swc_ecma_transforms_base::perf::Parallel;
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
use swc_trace_macro::swc_trace;

/// Compile ES2015 shorthand properties to ES5
///
///# Example
///
///## In
///
/// ```js
/// var o = { a, b, c };
/// ```
///
///## Out
///
/// ```js
/// var o = { a: a, b: b, c: c };
/// ```
///
///## In
///
/// ```js
/// var cat = {
///   getName() {
///     return name;
///   }
/// };
/// ```
///
///## Out
///```js
/// var cat = {
///   getName: function () {
///     return name;
///   }
/// };
/// ```
pub fn shorthand() -> impl 'static + Fold + VisitMut {
    as_folder(Shorthand)
}

#[derive(Clone, Copy)]
struct Shorthand;

impl Parallel for Shorthand {
    fn create(&self) -> Self {
        *self
    }

    fn merge(&mut self, _: Self) {}
}

#[swc_trace]
impl VisitMut for Shorthand {
    noop_visit_mut_type!(fail);

    fn visit_mut_prop(&mut self, prop: &mut Prop) {
        prop.visit_mut_children_with(self);

        match prop {
            Prop::Shorthand(ident) => {
                let value = ident.clone().into();

                *prop = Prop::KeyValue(KeyValueProp {
                    key: if ident.sym == "__proto__" {
                        PropName::Computed(ComputedPropName {
                            span: ident.span,
                            expr: ident.sym.clone().into(),
                        })
                    } else {
                        ident.take().into()
                    },
                    value,
                });
            }
            Prop::Method(MethodProp { key, function }) => {
                let key = match key.take() {
                    PropName::Ident(IdentName { span, sym, .. }) if sym == "__proto__" => {
                        ComputedPropName {
                            span,
                            expr: sym.into(),
                        }
                        .into()
                    }
                    PropName::Str(s @ Str { span, .. }) if s.value == "__proto__" => {
                        ComputedPropName {
                            span,
                            expr: s.into(),
                        }
                        .into()
                    }
                    key => key,
                };
                *prop = Prop::KeyValue(KeyValueProp {
                    key,
                    value: FnExpr {
                        ident: None,
                        function: function.take(),
                    }
                    .into(),
                })
            }
            _ => {}
        }
    }
}