Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Replace a TaggedTemplateExpression with a CallExpression in a SWC Rust Plugin

I’m working on a SWC Rust WASM plugin to transform JavaScript.

Overall SWC and its API are well designed. However currently I struggle to convert a TaggedTemplateExpression to a CallExpression like in this example:

console.log`Hello, ${name}!`;

to:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

console.log("Hello, ", name, "!");

In Babel, this transformation would be relatively straightforward. Here’s an example of how it might look:

const babel = require("@babel/core");

function transform({ types: t }) {
  return {
    visitor: {
      TaggedTemplateExpression(path) {
        const { tag, quasi } = path.node;

        if (
          t.isMemberExpression(tag) &&
          t.isIdentifier(tag.object, { name: "console" }) &&
          t.isIdentifier(tag.property, { name: "log" })
        ) {
          let args = [];

          quasi.quasis.forEach((element, index) => {
            args.push(t.stringLiteral(element.value.raw));
            if (index < quasi.expressions.length) {
              args.push(quasi.expressions[index]);
            }
          });

          path.replaceWith(
            t.callExpression(
              t.memberExpression(
                t.identifier("console"),
                t.identifier("log")
              ),
              args
            )
          );
        }
      },
    },
  };
}

I found the Changing AST Type section of the SWC CheatSheet but still I don’t know how to convert it properly:

use swc_core::ecma::{
    ast::*,
    visit::{VisitMut, VisitMutWith},
};

struct TemplateToCallTransform;

impl VisitMut for TemplateToCallTransform {
    fn visit_mut_tagged_tpl(&mut self, n: &mut TaggedTpl) {=
        // How do I replace the current node with the new CallExpr?
    }
}

>Solution :

SWC author here (again).

You need to handle it from fn visit_mut_expr(&mut self, e: &mut Expr).

TaggedTpl and CallExpr both belongs to expression in ECMAScript, so you can handle it from there.


use swc_core::ecma::{
    ast::*,
    visit::{VisitMut, VisitMutWith},
};

struct TemplateToCallTransform;

impl VisitMut for TemplateToCallTransform {
    fn visit_mut_expr(&mut self, e: &mut Expr) {
        // You may skip this, depending on the requirements.
        e.visit_mut_children_with(self);

        match e {
            Expr::TaggedTpl(n) => {
                *e = Expr::Call(CallExpr {
                    // ...fields
                });
            }

            _ => {}
        }
    }
}

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading