Babel: определить значение переменной в текущей области - PullRequest
0 голосов
/ 24 марта 2020

Допустим, у меня есть следующий код, который я хочу преобразовать с помощью пользовательского плагина Babel:

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

Цель состоит в том, чтобы заменить все вхождения document.readyState пользовательской функцией, например, window.getDocumentReadyState() , Поэтому выходные данные должны выглядеть примерно так:

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

Сложность состоит в том, чтобы определить, какое значение на самом деле имеет объект c, когда вызывается посетитель MemberExpression, так как я просто хочу заменить MemberExpressions для document. Вот почему мне нужно выяснить, является ли текущее значение c document.

Вот реализация, которая просто заменяет каждое <obj>.readyState MemberExpression:

      /**
       * 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 с использованием анализа stati c, верно?

По сути, мне нужно найти последнее выражение AssignmentExpression этой переменной в текущей области видимости.

Я уже пытался искать переменную в области видимости, используя path.scope.getBinding(<variableName>), но проблема в том, что последнее выражение AssignmentExpression не отображается в binding.references. Если бы значение было назначено во время объявления (let c = document), это не было бы проблемой, потому что к этой ссылке можно получить доступ, используя binding.

. Я также пытался пройти через область действия, но посетитель AssignmentExpression не был не вызывается.

Я довольно плохо знаком с Babel и ASTs и достиг точки, когда я не знаю, что делать дальше, и я действительно хотел бы избавиться от этой проверки во время выполнения.

Как бы вы решили такую ​​проблему?

...