swc_estree_compat/babelify/
expr.rs

1use copyless::BoxHelper;
2use serde::{Deserialize, Serialize};
3use swc_atoms::atom;
4use swc_common::{BytePos, Span, Spanned};
5use swc_ecma_ast::{
6    ArrayLit, ArrowExpr, AssignExpr, AssignTarget, AssignTargetPat, AwaitExpr, BinExpr, BinaryOp,
7    BlockStmtOrExpr, CallExpr, Callee, ClassExpr, CondExpr, Expr, ExprOrSpread, FnExpr, Ident,
8    Import, Lit, MemberExpr, MemberProp, MetaPropExpr, MetaPropKind, NewExpr, ObjectLit, ParenExpr,
9    PropOrSpread, SeqExpr, SimpleAssignTarget, SpreadElement, Super, SuperProp, SuperPropExpr,
10    TaggedTpl, ThisExpr, Tpl, TplElement, UnaryExpr, UpdateExpr, YieldExpr,
11};
12use swc_estree_ast::{
13    flavor::Flavor, ArrayExprEl, ArrayExpression, ArrowFuncExprBody, ArrowFunctionExpression,
14    AssignmentExpression, AwaitExpression, BinaryExprLeft, BinaryExpression, CallExpression,
15    Callee as BabelCallee, ClassExpression, ConditionalExpression, Expression, FunctionExpression,
16    Import as BabelImport, LVal, Literal, LogicalExpression, MemberExprProp, MemberExpression,
17    MetaProperty, NewExpression, ObjectExprProp, ObjectExpression, ObjectKey, ObjectMember,
18    ParenthesizedExpression, PrivateName, SequenceExpression, SpreadElement as BabelSpreadElement,
19    Super as BabelSuper, TaggedTemplateExprTypeParams, TaggedTemplateExpression, TemplateElVal,
20    TemplateElement, TemplateLiteral, TemplateLiteralExpr, ThisExpression, UnaryExpression,
21    UpdateExpression, YieldExpression,
22};
23
24use crate::babelify::{Babelify, Context};
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub enum ExprOutput {
28    Expr(Box<Expression>),
29    Private(PrivateName),
30}
31
32impl Babelify for Expr {
33    type Output = ExprOutput;
34
35    fn babelify(self, ctx: &Context) -> Self::Output {
36        match self {
37            Expr::This(t) => ExprOutput::Expr(Box::alloc().init(Expression::This(t.babelify(ctx)))),
38            Expr::Array(a) => {
39                ExprOutput::Expr(Box::alloc().init(Expression::Array(a.babelify(ctx))))
40            }
41            Expr::Object(o) => {
42                ExprOutput::Expr(Box::alloc().init(Expression::Object(o.babelify(ctx))))
43            }
44            Expr::Fn(f) => ExprOutput::Expr(Box::alloc().init(Expression::Func(f.babelify(ctx)))),
45            Expr::Unary(u) => {
46                ExprOutput::Expr(Box::alloc().init(Expression::Unary(u.babelify(ctx))))
47            }
48            Expr::Update(u) => {
49                ExprOutput::Expr(Box::alloc().init(Expression::Update(u.babelify(ctx))))
50            }
51            Expr::Bin(b) => match b.babelify(ctx) {
52                BinaryOrLogicalExpr::Binary(bin) => {
53                    ExprOutput::Expr(Box::alloc().init(Expression::Binary(bin)))
54                }
55                BinaryOrLogicalExpr::Logical(log) => {
56                    ExprOutput::Expr(Box::alloc().init(Expression::Logical(log)))
57                }
58            },
59            Expr::Assign(a) => {
60                ExprOutput::Expr(Box::alloc().init(Expression::Assignment(a.babelify(ctx))))
61            }
62            Expr::Member(m) => {
63                ExprOutput::Expr(Box::alloc().init(Expression::Member(m.babelify(ctx))))
64            }
65            Expr::SuperProp(m) => {
66                ExprOutput::Expr(Box::alloc().init(Expression::Member(m.babelify(ctx))))
67            }
68            Expr::Cond(c) => {
69                ExprOutput::Expr(Box::alloc().init(Expression::Conditional(c.babelify(ctx))))
70            }
71            Expr::Call(c) => ExprOutput::Expr(Box::alloc().init(Expression::Call(c.babelify(ctx)))),
72            Expr::New(n) => ExprOutput::Expr(Box::alloc().init(Expression::New(n.babelify(ctx)))),
73            Expr::Seq(s) => {
74                ExprOutput::Expr(Box::alloc().init(Expression::Sequence(s.babelify(ctx))))
75            }
76            Expr::Ident(i) => ExprOutput::Expr(Box::alloc().init(Expression::Id(i.babelify(ctx)))),
77            Expr::Lit(lit) => {
78                match lit {
79                    Lit::Str(s) => ExprOutput::Expr(
80                        Box::alloc().init(Expression::Literal(Literal::String(s.babelify(ctx)))),
81                    ),
82                    Lit::Bool(b) => ExprOutput::Expr(
83                        Box::alloc().init(Expression::Literal(Literal::Boolean(b.babelify(ctx)))),
84                    ),
85                    Lit::Null(n) => ExprOutput::Expr(
86                        Box::alloc().init(Expression::Literal(Literal::Null(n.babelify(ctx)))),
87                    ),
88                    Lit::Num(n) => ExprOutput::Expr(
89                        Box::alloc().init(Expression::Literal(Literal::Numeric(n.babelify(ctx)))),
90                    ),
91                    Lit::BigInt(i) => ExprOutput::Expr(
92                        Box::alloc().init(Expression::Literal(Literal::BigInt(i.babelify(ctx)))),
93                    ),
94                    Lit::Regex(r) => ExprOutput::Expr(
95                        Box::alloc().init(Expression::Literal(Literal::RegExp(r.babelify(ctx)))),
96                    ),
97                    Lit::JSXText(_) => panic!(
98                        "illegal conversion: Cannot convert {:?} to ExprOutput",
99                        &lit
100                    ), // TODO(dwoznicki): is this really illegal?
101                }
102            }
103            Expr::Tpl(t) => {
104                ExprOutput::Expr(Box::alloc().init(Expression::TemplateLiteral(t.babelify(ctx))))
105            }
106            Expr::TaggedTpl(t) => {
107                ExprOutput::Expr(Box::alloc().init(Expression::TaggedTemplate(t.babelify(ctx))))
108            }
109            Expr::Arrow(a) => {
110                ExprOutput::Expr(Box::alloc().init(Expression::ArrowFunc(a.babelify(ctx))))
111            }
112            Expr::Class(c) => {
113                ExprOutput::Expr(Box::alloc().init(Expression::Class(c.babelify(ctx))))
114            }
115            Expr::Yield(y) => {
116                ExprOutput::Expr(Box::alloc().init(Expression::Yield(y.babelify(ctx))))
117            }
118            Expr::MetaProp(m) => {
119                ExprOutput::Expr(Box::alloc().init(Expression::MetaProp(m.babelify(ctx))))
120            }
121            Expr::Await(a) => {
122                ExprOutput::Expr(Box::alloc().init(Expression::Await(a.babelify(ctx))))
123            }
124            Expr::Paren(p) => {
125                ExprOutput::Expr(Box::alloc().init(Expression::Parenthesized(p.babelify(ctx))))
126            }
127            Expr::JSXElement(e) => {
128                ExprOutput::Expr(Box::alloc().init(Expression::JSXElement(e.babelify(ctx))))
129            }
130            Expr::JSXFragment(f) => {
131                ExprOutput::Expr(Box::alloc().init(Expression::JSXFragment(f.babelify(ctx))))
132            }
133            Expr::TsTypeAssertion(a) => {
134                ExprOutput::Expr(Box::alloc().init(Expression::TSTypeAssertion(a.babelify(ctx))))
135            }
136            Expr::TsNonNull(n) => {
137                ExprOutput::Expr(Box::alloc().init(Expression::TSNonNull(n.babelify(ctx))))
138            }
139            Expr::TsAs(a) => ExprOutput::Expr(Box::alloc().init(Expression::TSAs(a.babelify(ctx)))),
140            Expr::TsInstantiation(..) => unimplemented!("Babel doesn't support this right now."),
141            Expr::PrivateName(p) => ExprOutput::Private(p.babelify(ctx)),
142
143            // TODO(dwoznicki): how does babel handle these?
144            Expr::JSXMember(_) => panic!(
145                "illegal conversion: Cannot convert {:?} to ExprOutput - babel has no equivalent",
146                &self
147            ),
148            Expr::JSXNamespacedName(_) => panic!(
149                "illegal conversion: Cannot convert {:?} to ExprOutput - babel has no equivalent",
150                &self
151            ),
152            Expr::JSXEmpty(_) => panic!(
153                "illegal conversion: Cannot convert {:?} to ExprOutput - babel has no equivalent",
154                &self
155            ),
156            Expr::TsConstAssertion(_) => panic!(
157                "illegal conversion: Cannot convert {:?} to ExprOutput - babel has no equivalent",
158                &self
159            ),
160            Expr::TsSatisfies(_) => panic!(
161                "illegal conversion: Cannot convert {:?} to ExprOutput - babel has no equivalent",
162                &self
163            ),
164            Expr::OptChain(_) => panic!(
165                "illegal conversion: Cannot convert {:?} to ExprOutput - babel has no equivalent",
166                &self
167            ),
168            Expr::Invalid(_) => panic!(
169                "illegal conversion: Cannot convert {:?} to ExprOutput - babel has no equivalent",
170                &self
171            ),
172        }
173    }
174}
175
176impl From<ExprOutput> for Expression {
177    fn from(o: ExprOutput) -> Self {
178        match o {
179            ExprOutput::Expr(expr) => *expr,
180            ExprOutput::Private(_) => panic!(
181                "illegal conversion: Cannot convert {:?} to Expression - babel has no equivalent",
182                &o
183            ),
184        }
185    }
186}
187
188impl From<ExprOutput> for BinaryExprLeft {
189    fn from(o: ExprOutput) -> Self {
190        match o {
191            ExprOutput::Expr(e) => BinaryExprLeft::Expr(e),
192            ExprOutput::Private(p) => BinaryExprLeft::Private(p),
193        }
194    }
195}
196
197impl From<ExprOutput> for ObjectKey {
198    fn from(o: ExprOutput) -> Self {
199        match o {
200            ExprOutput::Expr(e) => match *e {
201                Expression::Id(i) => ObjectKey::Id(i),
202                Expression::Literal(Literal::String(s)) => ObjectKey::String(s),
203                Expression::Literal(Literal::Numeric(n)) => ObjectKey::Numeric(n),
204                _ => ObjectKey::Expr(e),
205            },
206            ExprOutput::Private(_) => panic!(
207                "illegal conversion: Cannot convert {:?} to ObjectKey - babel has no equivalent",
208                &o
209            ),
210        }
211    }
212}
213
214impl From<ExprOutput> for MemberExprProp {
215    fn from(o: ExprOutput) -> Self {
216        match o {
217            ExprOutput::Private(p) => MemberExprProp::PrivateName(p),
218            ExprOutput::Expr(e) => match *e {
219                Expression::Id(i) => MemberExprProp::Id(i),
220                _ => MemberExprProp::Expr(e),
221            },
222        }
223    }
224}
225
226impl Babelify for ThisExpr {
227    type Output = ThisExpression;
228
229    fn babelify(self, ctx: &Context) -> Self::Output {
230        ThisExpression {
231            base: ctx.base(self.span),
232        }
233    }
234}
235
236impl Babelify for ArrayLit {
237    type Output = ArrayExpression;
238
239    fn babelify(self, ctx: &Context) -> Self::Output {
240        ArrayExpression {
241            base: ctx.base(self.span),
242            elements: self.elems.babelify(ctx),
243        }
244    }
245}
246
247impl Babelify for ObjectLit {
248    type Output = ObjectExpression;
249
250    fn babelify(self, ctx: &Context) -> Self::Output {
251        ObjectExpression {
252            base: ctx.base(self.span),
253            properties: self.props.babelify(ctx),
254        }
255    }
256}
257
258impl Babelify for PropOrSpread {
259    type Output = ObjectExprProp;
260
261    fn babelify(self, ctx: &Context) -> Self::Output {
262        match self {
263            PropOrSpread::Spread(s) => ObjectExprProp::Spread(s.babelify(ctx)),
264            PropOrSpread::Prop(prop) => {
265                let member = prop.babelify(ctx);
266                match member {
267                    ObjectMember::Method(m) => ObjectExprProp::Method(m),
268                    ObjectMember::Prop(p) => ObjectExprProp::Prop(p),
269                }
270            }
271        }
272    }
273}
274
275impl Babelify for SpreadElement {
276    type Output = BabelSpreadElement;
277
278    fn babelify(self, ctx: &Context) -> Self::Output {
279        BabelSpreadElement {
280            base: ctx.base(self.span()),
281            argument: Box::alloc().init(self.expr.babelify(ctx).into()),
282        }
283    }
284}
285
286impl Babelify for UnaryExpr {
287    type Output = UnaryExpression;
288
289    fn babelify(self, ctx: &Context) -> Self::Output {
290        UnaryExpression {
291            base: ctx.base(self.span),
292            operator: self.op.babelify(ctx),
293            argument: Box::alloc().init(self.arg.babelify(ctx).into()),
294            prefix: true,
295        }
296    }
297}
298
299impl Babelify for UpdateExpr {
300    type Output = UpdateExpression;
301
302    fn babelify(self, ctx: &Context) -> Self::Output {
303        UpdateExpression {
304            base: ctx.base(self.span),
305            operator: self.op.babelify(ctx),
306            prefix: self.prefix,
307            argument: Box::alloc().init(self.arg.babelify(ctx).into()),
308        }
309    }
310}
311
312#[derive(Debug, Clone, Serialize, Deserialize)]
313pub enum BinaryOrLogicalExpr {
314    Binary(BinaryExpression),
315    Logical(LogicalExpression),
316}
317
318impl Babelify for BinExpr {
319    type Output = BinaryOrLogicalExpr;
320
321    fn babelify(self, ctx: &Context) -> Self::Output {
322        match self.op {
323            BinaryOp::LogicalOr | BinaryOp::LogicalAnd | BinaryOp::NullishCoalescing => {
324                BinaryOrLogicalExpr::Logical(LogicalExpression {
325                    base: ctx.base(self.span),
326                    operator: self.op.babelify(ctx).into(),
327                    left: Box::alloc().init(self.left.babelify(ctx).into()),
328                    right: Box::alloc().init(self.right.babelify(ctx).into()),
329                })
330            }
331            _ => BinaryOrLogicalExpr::Binary(BinaryExpression {
332                base: ctx.base(self.span),
333                operator: self.op.babelify(ctx).into(),
334                left: Box::alloc().init(self.left.babelify(ctx).into()),
335                right: Box::alloc().init(self.right.babelify(ctx).into()),
336            }),
337        }
338
339        // BinaryExpression {
340        //     base: ctx.base(self.span),
341        //     operator: self.op.babelify(ctx).into(),
342        //     left: Box::alloc().init(self.left.babelify(ctx).into()),
343        //     right: Box::alloc().init(self.right.babelify(ctx).into()),
344        // }
345    }
346}
347
348impl Babelify for FnExpr {
349    type Output = FunctionExpression;
350
351    fn babelify(self, ctx: &Context) -> Self::Output {
352        FunctionExpression {
353            id: self.ident.map(|id| id.babelify(ctx)),
354            ..self.function.babelify(ctx)
355        }
356    }
357}
358
359impl Babelify for ClassExpr {
360    type Output = ClassExpression;
361
362    fn babelify(self, ctx: &Context) -> Self::Output {
363        ClassExpression {
364            id: self.ident.map(|id| id.babelify(ctx)),
365            ..self.class.babelify(ctx)
366        }
367    }
368}
369
370impl Babelify for AssignExpr {
371    type Output = AssignmentExpression;
372
373    fn babelify(self, ctx: &Context) -> Self::Output {
374        AssignmentExpression {
375            base: ctx.base(self.span),
376            operator: self.op.as_str().into(),
377            left: Box::alloc().init(self.left.babelify(ctx)),
378            right: Box::alloc().init(self.right.babelify(ctx).into()),
379        }
380    }
381}
382
383impl Babelify for MemberExpr {
384    type Output = MemberExpression;
385
386    fn babelify(self, ctx: &Context) -> Self::Output {
387        let computed = self.prop.is_computed();
388
389        MemberExpression {
390            base: ctx.base(self.span),
391            object: Box::alloc().init(self.obj.babelify(ctx).into()),
392            property: Box::alloc().init(self.prop.babelify(ctx)),
393            computed,
394            optional: Default::default(),
395        }
396    }
397}
398
399impl Babelify for MemberProp {
400    type Output = MemberExprProp;
401
402    fn babelify(self, ctx: &Context) -> Self::Output {
403        match self {
404            Self::Computed(c) => MemberExprProp::Expr(c.babelify(ctx).into()),
405            Self::Ident(i) => MemberExprProp::Id(i.babelify(ctx)),
406            Self::PrivateName(p) => MemberExprProp::PrivateName(p.babelify(ctx)),
407        }
408    }
409}
410
411impl Babelify for SuperPropExpr {
412    type Output = MemberExpression;
413
414    fn babelify(self, ctx: &Context) -> Self::Output {
415        let computed = self.prop.is_computed();
416
417        MemberExpression {
418            base: ctx.base(self.span),
419            object: Box::alloc().init(Expression::Super(self.obj.babelify(ctx))),
420            property: Box::alloc().init(self.prop.babelify(ctx)),
421            computed,
422            optional: Default::default(),
423        }
424    }
425}
426
427impl Babelify for SuperProp {
428    type Output = MemberExprProp;
429
430    fn babelify(self, ctx: &Context) -> Self::Output {
431        match self {
432            Self::Computed(c) => MemberExprProp::Expr(c.babelify(ctx).into()),
433            Self::Ident(i) => MemberExprProp::Id(i.babelify(ctx)),
434        }
435    }
436}
437
438impl Babelify for CondExpr {
439    type Output = ConditionalExpression;
440
441    fn babelify(self, ctx: &Context) -> Self::Output {
442        ConditionalExpression {
443            base: ctx.base(self.span),
444            test: Box::alloc().init(self.test.babelify(ctx).into()),
445            consequent: Box::alloc().init(self.cons.babelify(ctx).into()),
446            alternate: Box::alloc().init(self.alt.babelify(ctx).into()),
447        }
448    }
449}
450
451impl Babelify for CallExpr {
452    type Output = CallExpression;
453
454    fn babelify(self, ctx: &Context) -> Self::Output {
455        CallExpression {
456            base: ctx.base(self.span),
457            callee: Box::alloc().init(self.callee.babelify(ctx).into()),
458            arguments: self
459                .args
460                .into_iter()
461                .map(|arg| arg.babelify(ctx).into())
462                .collect(),
463            type_parameters: self.type_args.map(|t| t.babelify(ctx)),
464            type_arguments: Default::default(),
465            optional: Default::default(),
466        }
467    }
468}
469
470impl Babelify for NewExpr {
471    type Output = NewExpression;
472
473    fn babelify(self, ctx: &Context) -> Self::Output {
474        NewExpression {
475            base: ctx.base(self.span),
476            callee: BabelCallee::Expr(Box::alloc().init(self.callee.babelify(ctx).into())),
477            arguments: match self.args {
478                Some(args) => args
479                    .into_iter()
480                    .map(|arg| arg.babelify(ctx).into())
481                    .collect(),
482                None => Vec::new(),
483            },
484            type_parameters: self.type_args.map(|t| t.babelify(ctx)),
485            type_arguments: Default::default(),
486            optional: Default::default(),
487        }
488    }
489}
490
491impl Babelify for SeqExpr {
492    type Output = SequenceExpression;
493
494    fn babelify(self, ctx: &Context) -> Self::Output {
495        SequenceExpression {
496            base: ctx.base(self.span),
497            expressions: self
498                .exprs
499                .into_iter()
500                .map(|expr| Box::alloc().init(expr.babelify(ctx).into()))
501                .collect(),
502        }
503    }
504}
505
506impl Babelify for ArrowExpr {
507    type Output = ArrowFunctionExpression;
508
509    fn babelify(self, ctx: &Context) -> Self::Output {
510        ArrowFunctionExpression {
511            base: ctx.base(self.span),
512            params: self
513                .params
514                .into_iter()
515                .map(|p| p.babelify(ctx).into())
516                .collect(),
517            body: Box::alloc().init(self.body.babelify(ctx)),
518            is_async: self.is_async,
519            expression: match Flavor::current() {
520                Flavor::Babel => Default::default(),
521                Flavor::Acorn { .. } => true,
522            },
523            generator: self.is_generator,
524            return_type: self
525                .return_type
526                .map(|t| Box::alloc().init(t.babelify(ctx).into())),
527            type_parameters: self.type_params.map(|t| t.babelify(ctx).into()),
528        }
529    }
530}
531
532impl Babelify for YieldExpr {
533    type Output = YieldExpression;
534
535    fn babelify(self, ctx: &Context) -> Self::Output {
536        YieldExpression {
537            base: ctx.base(self.span),
538            argument: self.arg.map(|a| Box::alloc().init(a.babelify(ctx).into())),
539            delegate: self.delegate,
540        }
541    }
542}
543
544impl Babelify for MetaPropExpr {
545    type Output = MetaProperty;
546
547    fn babelify(self, ctx: &Context) -> Self::Output {
548        let (meta, property) = match self.kind {
549            MetaPropKind::ImportMeta => (
550                Ident {
551                    span: Span {
552                        hi: self.span.hi - BytePos(5),
553                        ..self.span
554                    },
555                    sym: atom!("import"),
556                    ..Default::default()
557                }
558                .babelify(ctx),
559                Ident {
560                    span: Span {
561                        lo: self.span.lo + BytePos(7),
562                        ..self.span
563                    },
564                    sym: atom!("meta"),
565                    ..Default::default()
566                }
567                .babelify(ctx),
568            ),
569            MetaPropKind::NewTarget => (
570                Ident {
571                    span: Span {
572                        hi: self.span.hi - BytePos(7),
573                        ..self.span
574                    },
575                    sym: atom!("new"),
576                    ..Default::default()
577                }
578                .babelify(ctx),
579                Ident {
580                    span: Span {
581                        hi: self.span.hi + BytePos(4),
582                        ..self.span
583                    },
584                    sym: atom!("target"),
585                    ..Default::default()
586                }
587                .babelify(ctx),
588            ),
589        };
590        MetaProperty {
591            base: ctx.base(self.span()),
592            meta,
593            property,
594        }
595    }
596}
597
598impl Babelify for AwaitExpr {
599    type Output = AwaitExpression;
600
601    fn babelify(self, ctx: &Context) -> Self::Output {
602        AwaitExpression {
603            base: ctx.base(self.span),
604            argument: Box::alloc().init(self.arg.babelify(ctx).into()),
605        }
606    }
607}
608
609impl Babelify for Tpl {
610    type Output = TemplateLiteral;
611
612    fn babelify(self, ctx: &Context) -> Self::Output {
613        TemplateLiteral {
614            base: ctx.base(self.span),
615            expressions: self
616                .exprs
617                .into_iter()
618                .map(|e| TemplateLiteralExpr::Expr(Box::alloc().init(e.babelify(ctx).into())))
619                .collect(),
620            quasis: self.quasis.babelify(ctx),
621        }
622    }
623}
624
625impl Babelify for TaggedTpl {
626    type Output = TaggedTemplateExpression;
627
628    fn babelify(self, ctx: &Context) -> Self::Output {
629        TaggedTemplateExpression {
630            base: ctx.base(self.span),
631            tag: Box::alloc().init(self.tag.babelify(ctx).into()),
632            quasi: self.tpl.babelify(ctx),
633            type_parameters: self
634                .type_params
635                .map(|t| TaggedTemplateExprTypeParams::TS(t.babelify(ctx))),
636        }
637    }
638}
639
640impl Babelify for TplElement {
641    type Output = TemplateElement;
642
643    fn babelify(self, ctx: &Context) -> Self::Output {
644        TemplateElement {
645            base: ctx.base(self.span),
646            tail: self.tail,
647            value: TemplateElVal {
648                raw: self.raw,
649                cooked: self.cooked,
650            },
651        }
652    }
653}
654
655impl Babelify for ParenExpr {
656    type Output = ParenthesizedExpression;
657
658    fn babelify(self, ctx: &Context) -> Self::Output {
659        ParenthesizedExpression {
660            base: ctx.base(self.span),
661            expression: Box::alloc().init(self.expr.babelify(ctx).into()),
662        }
663    }
664}
665
666impl Babelify for Callee {
667    type Output = Expression;
668
669    fn babelify(self, ctx: &Context) -> Self::Output {
670        match self {
671            Callee::Expr(e) => e.babelify(ctx).into(),
672            Callee::Super(s) => Expression::Super(s.babelify(ctx)),
673            Callee::Import(i) => Expression::Import(i.babelify(ctx)),
674        }
675    }
676}
677
678impl Babelify for Super {
679    type Output = BabelSuper;
680
681    fn babelify(self, ctx: &Context) -> Self::Output {
682        BabelSuper {
683            base: ctx.base(self.span),
684        }
685    }
686}
687
688impl Babelify for Import {
689    type Output = BabelImport;
690
691    fn babelify(self, ctx: &Context) -> Self::Output {
692        BabelImport {
693            base: ctx.base(self.span),
694        }
695    }
696}
697
698impl Babelify for ExprOrSpread {
699    type Output = ArrayExprEl;
700
701    fn babelify(self, ctx: &Context) -> Self::Output {
702        match self.spread {
703            Some(_) => ArrayExprEl::Spread(BabelSpreadElement {
704                base: ctx.base(self.span()),
705                argument: Box::alloc().init(self.expr.babelify(ctx).into()),
706            }),
707            None => ArrayExprEl::Expr(Box::alloc().init(self.expr.babelify(ctx).into())),
708        }
709    }
710}
711
712impl Babelify for BlockStmtOrExpr {
713    type Output = ArrowFuncExprBody;
714
715    fn babelify(self, ctx: &Context) -> Self::Output {
716        match self {
717            BlockStmtOrExpr::BlockStmt(b) => ArrowFuncExprBody::Block(b.babelify(ctx)),
718            BlockStmtOrExpr::Expr(e) => {
719                ArrowFuncExprBody::Expr(Box::alloc().init(e.babelify(ctx).into()))
720            }
721        }
722    }
723}
724
725impl Babelify for AssignTarget {
726    type Output = LVal;
727
728    fn babelify(self, ctx: &Context) -> Self::Output {
729        match self {
730            AssignTarget::Simple(s) => s.babelify(ctx),
731            AssignTarget::Pat(p) => p.babelify(ctx),
732        }
733    }
734}
735
736impl Babelify for SimpleAssignTarget {
737    type Output = LVal;
738
739    fn babelify(self, ctx: &Context) -> Self::Output {
740        match self {
741            SimpleAssignTarget::Ident(i) => LVal::Id(i.babelify(ctx)),
742            SimpleAssignTarget::Member(m) => LVal::MemberExpr(m.babelify(ctx)),
743            SimpleAssignTarget::SuperProp(s) => LVal::MemberExpr(s.babelify(ctx)),
744            _ => unreachable!(),
745        }
746    }
747}
748
749impl Babelify for AssignTargetPat {
750    type Output = LVal;
751
752    fn babelify(self, ctx: &Context) -> Self::Output {
753        match self {
754            AssignTargetPat::Array(a) => LVal::ArrayPat(a.babelify(ctx)),
755            AssignTargetPat::Object(o) => LVal::ObjectPat(o.babelify(ctx)),
756            AssignTargetPat::Invalid(_) => todo!(),
757        }
758    }
759}
760
761// NOTE: OptChainExpr does not appear to have an official Babel AST node yet.
762
763// #[ast_node("OptionalChainingExpression")]
764// #[derive(Eq, Hash, EqIgnoreSpan)]
765// #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
766// pub struct OptChainExpr {
767//     pub span: Span,
768//     pub question_dot_token: Span,
769//     pub expr: Box<Expr>,
770// }
771//