javascript - 巴别塔 : Determine the variable value in the current scope

标签 javascript babeljs abstract-syntax-tree

假设我有以下代码,我想使用自定义 Babel 插件进行转换:

let c;
c = document;
console.log(c.readyState);

目标是替换所有出现的 document.readyState具有自定义功能,例如window.getDocumentReadyState() . 所以输出应该是这样的:

let c;
c = document;
console.log(window.getDocumentReadyState());

这里的难点在于判断对象c是哪个值居然有当MemberExpression访问者被调用,因为我只想替换 document 的 MemberExpressions .这就是为什么我需要查明 c 的当前值是否为是document .

这是一个只替换每个 <obj>.readyState 的实现成员表达式:

      /**
       * Replace document.readyState with
       * window.getDocumentReadyState();
       */
      MemberExpression(path) {
        const { node, parent } = path;
        const objName = node.object.name;
        const propName = node.property.name;

        if (t.isAssignmentExpression(parent)) {
          return;
        }

        if (t.isCallExpression(parent)) {
          const isCallee = parent.callee === node;
          if (isCallee) return;
        }

        if (propName === 'readyState') {
          const customReadyStateFn = t.callExpression(
            t.memberExpression(
              t.identifier('window'),
              t.identifier('getDocumentReadyState'),
            ),
            [t.identifier(objName)],
          );
          path.replaceWith(customReadyStateFn);
        }
      },

使用此实现,我执行运行时检查以确定对象的类型是否为 document (HTMLDocument)里面window.getDocumentReadyState ,因为我无法使用 Babel 做同样的事情。 但是必须有一种方法可以可靠地判断这个变量是否具有值 document使用静态分析,对吧?

本质上,我需要在当前范围内找到这个变量的最后一个 AssignmentExpression。

我已经尝试使用 path.scope.getBinding(<variableName>) 在范围内查找变量, 但问题是最后一个 AssignmentExpression 没有出现在 binding.references 中.如果该值是在声明期间分配的(let c = document),那就没问题,因为可以使用 binding 访问该引用。 .

我还尝试遍历范围,但未调用 AssignmentExpression 访问者。

我对 Babel 和 AST 还很陌生,已经到了不知道下一步该做什么的地步,我真的很想摆脱运行时检查。

你会如何解决这样的问题?

最佳答案

也许有点晚了,但我认为可以做到。

需要遍历所有左边的Identifier,检查右边的值是否为document。这样做时,您保留一个数组,其中包含值等于文档的所有变量名称,如果它们的值发生变化并且不再是文档,则将它们从数组中删除。

然后在遍历 MemberExpression 时检查对象名称是否在数组中。

关于javascript - 巴别塔 : Determine the variable value in the current scope,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60834925/

相关文章:

node.js - 如何防止 babel 转译生成器函数

c++ - 如何将 Clang AST 中的 TemplateTypeParm 节点与 AST_Matchers 匹配?

python - 如何编写 Python 调试器/编辑器

javascript - 鼠标悬停时的 jquery slider + 在选择时保持事件状态

javascript - 如何使用 angularjs 过滤器在标题上添加排序?

javascript - Ember 中的 JSON.parse 空响应

javascript - 返回所有交叉点数组 javascript

javascript - 如何正确地将 React 组件存储在单独的文件中并导入 React?

javascript - Webpack 不创建输出文件(不使用 webpack-dev-server)