swc_ecma_compat_es2015/
instanceof.rs

1use swc_common::{util::take::Take, Span, Spanned};
2use swc_ecma_ast::*;
3use swc_ecma_transforms_base::{helper, perf::Parallel};
4use swc_ecma_utils::ExprFactory;
5use swc_ecma_visit::{noop_visit_mut_type, visit_mut_pass, VisitMut, VisitMutWith};
6use swc_trace_macro::swc_trace;
7
8/// `@babel/plugin-transform-instanceof`
9///
10///
11///
12/// # Example
13///
14/// ## In
15///
16/// ```js
17/// foo instanceof Bar;
18/// ```
19///
20/// ## Out
21///
22/// ```js
23/// function _instanceof(left, right) {
24///   if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
25///     return !!right[Symbol.hasInstance](left);
26///   } else {
27///     return left instanceof right;
28///   }
29/// }
30///
31/// _instanceof(foo, Bar);
32/// ```
33pub fn instance_of() -> impl Pass {
34    visit_mut_pass(InstanceOf)
35}
36struct InstanceOf;
37
38impl Parallel for InstanceOf {
39    fn merge(&mut self, _: Self) {}
40
41    fn create(&self) -> Self {
42        InstanceOf
43    }
44}
45
46#[swc_trace]
47impl VisitMut for InstanceOf {
48    noop_visit_mut_type!(fail);
49
50    fn visit_mut_expr(&mut self, expr: &mut Expr) {
51        expr.visit_mut_children_with(self);
52
53        if let Expr::Bin(BinExpr {
54            span,
55            left,
56            op: op!("instanceof"),
57            right,
58        }) = expr
59        {
60            let instanceof_span = Span {
61                lo: left.span_hi(),
62                hi: right.span_lo(),
63            };
64
65            *expr = CallExpr {
66                span: *span,
67                callee: helper!(instanceof_span, instanceof),
68                args: vec![left.take().as_arg(), right.take().as_arg()],
69                ..Default::default()
70            }
71            .into();
72        }
73    }
74}