在编写babel插件时如何知道变量是否是全局变量

时间:2018-11-27 05:18:00

标签: babel

我想编写一个babel插件,该插件可以从部分代码中阻止诸如documentxhr之类的全局变量。 但是我不知道如何判断它是否属于window

示例:

function queryClass(name){
  return document.querySelector(`.${name}`);
  // or return window.document.querySelector(`.${name}`)
}

我希望它会变成这样

function queryClass(name){
  return noDocument.querySelector(`.${name}`);
  // or return window.noDocument.querySelector(`.${name}`)
}

但我不希望此代码转换为

const document = {querySelector(str){return str + '1'}}
function queryClass(name){
  return document.querySelector(`.${name}`);
  // or return obj.document.querySelector(`.${name}`)
} 

所以我认为我应该学习判断它是否是全局变量。 还是有其他方法可以帮助我实现这一目标? 这是我简单的babel代码:

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

const code = `
  function queryClass(name){
    return window.document.querySelector(\`.\${name}\`);
  }
`;

const visitor = {
  Identifier(path) {
    if(path.isIdentifier({name: 'document'})){
      // How to judge if it's a global variable
      path.node.name = 'noDocument';
    }
  }
}

const result = babel.transform(code, {
  plugins: [{visitor}]
});

2 个答案:

答案 0 :(得分:1)

我只是找到一种方法。

我不知道这是个好主意。

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

const code = `
  function queryClass(name){
    return window.document.querySelector(\`.\${name}\`);
  }
`;

const updateParamNameVisitor = {
  Identifier(path) {
    if (path.node.name === this.from) {
      path.replaceWith(this.to);
    }
  }
};

const visitor = {
  Program(path){
    if(path.scope.globals.document){
      const node = path.scope.generateUidIdentifier('no_document');
      path.traverse(updateParamNameVisitor, { from: 'document', to: node })
    }
  }
}

const result = babel.transform(code, {
  plugins: [{visitor}]
});

答案 1 :(得分:0)

我也是 babel 插件的新手
我认为是这样:

// inside Identifier(path)
const binding = path.scope.getBinding('document')
if (!binding) {
    // global
} else {
    // declaration point
    console.log(binding.identifier.loc)
}