简体   繁体   中英

How to remove the surround IIFE from @babel/template?

I'm trying to convert some Ember codes to React. Here is what I want to transform.

From

export default Ember.Component.extend(({
    didInsertElement() { }
});

To

export default class MyComponent extends React.Component {
    componentDidMount() { }
}

I write a babel plugin, and try to replace the Ember.Component.extend call with an AST node which is produced by template method. Here is the code snippet.

babel-plugin

const { default: template } = require("@babel/template");

const code = `class TestComponent extends React.Component { 
   componentDidMount() { }
 }`;
let classDeclarationNode = template.ast(code);
module.exports = function ({ types: t }) {
    return {
        visitor: {
            CallExpression(path) {
                if (!path.getSource().startsWith("Ember.Component.extend")) {
                    return;
                }
                path.replaceWith(classDeclarationNode);
            }
        }
    };
};

Output

export default (function () {
  class TestComponent extends React.Component {
    componentDidMount() {}
  }
})();

Instead of the expected code I wrote above, I get the ClassDeclaration statement surrounded with IIFE . Is there any way to remove the IIFE ?

I have struggled with the problem one whole day, but have no way to resolve it.


BTW, I also tried parseExpression method, but still can't get what exactly I want.

babel-plugin

const { parseExpression } = require('@babel/parser');

const code = `class TestComponent extends React.Component { 
    componentDidMount() { }
}`;
let expression = parseExpression(code);
module.exports = function ({ types: t }) {
    return {
        visitor: {
            CallExpression(path) {
                if (!path.getSource().startsWith("Ember.Component.extend")) {
                    return;
                }
                path.replaceWith(expression);
            }
        }
    };
};

Output

export default (class TestComponent extends React.Component {
  componentDidMount() {}
});

It's quite close to the correct code, except an extra pair of () . Is there any way to generate the pure class declaration ?

Thanks for the help of loganfsmyth on Slack, the problem was finally resolved. I should replace the node of whole export default but not only the CallExpression . Here is the code.

babel-plugin

const { default: template } = require("@babel/template");

const code = `export default class TestComponent extends React.Component { 
   componentDidMount() { }
 }`;
let rootNode = template.ast(code);
module.exports = function ({ types: t }) {
    return {
        visitor: {
            ExportDefaultDeclaration(path) {
                let isMatchedNode = (path.node.declaration &&
                    t.matchesPattern(path.node.declaration.callee, "Ember.Component.extend"));
                if (!isMatchedNode) {
                    return;
                }
                path.replaceWith(rootNode);
            }
        }
    };
};

Output

export default class TestComponent extends React.Component {
  componentDidMount() {}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM