.
This commit is contained in:
		
							
								
								
									
										367
									
								
								qwen/nodejs/node_modules/babel-plugin-jest-hoist/build/index.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										367
									
								
								qwen/nodejs/node_modules/babel-plugin-jest-hoist/build/index.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,367 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
Object.defineProperty(exports, '__esModule', {
 | 
			
		||||
  value: true
 | 
			
		||||
});
 | 
			
		||||
exports.default = jestHoist;
 | 
			
		||||
function _template() {
 | 
			
		||||
  const data = require('@babel/template');
 | 
			
		||||
  _template = function () {
 | 
			
		||||
    return data;
 | 
			
		||||
  };
 | 
			
		||||
  return data;
 | 
			
		||||
}
 | 
			
		||||
function _types() {
 | 
			
		||||
  const data = require('@babel/types');
 | 
			
		||||
  _types = function () {
 | 
			
		||||
    return data;
 | 
			
		||||
  };
 | 
			
		||||
  return data;
 | 
			
		||||
}
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 | 
			
		||||
 *
 | 
			
		||||
 * This source code is licensed under the MIT license found in the
 | 
			
		||||
 * LICENSE file in the root directory of this source tree.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
const JEST_GLOBAL_NAME = 'jest';
 | 
			
		||||
const JEST_GLOBALS_MODULE_NAME = '@jest/globals';
 | 
			
		||||
const JEST_GLOBALS_MODULE_JEST_EXPORT_NAME = 'jest';
 | 
			
		||||
const hoistedVariables = new WeakSet();
 | 
			
		||||
const hoistedJestGetters = new WeakSet();
 | 
			
		||||
const hoistedJestExpressions = new WeakSet();
 | 
			
		||||
 | 
			
		||||
// We allow `jest`, `expect`, `require`, all default Node.js globals and all
 | 
			
		||||
// ES2015 built-ins to be used inside of a `jest.mock` factory.
 | 
			
		||||
// We also allow variables prefixed with `mock` as an escape-hatch.
 | 
			
		||||
const ALLOWED_IDENTIFIERS = new Set(
 | 
			
		||||
  [
 | 
			
		||||
    'Array',
 | 
			
		||||
    'ArrayBuffer',
 | 
			
		||||
    'Boolean',
 | 
			
		||||
    'BigInt',
 | 
			
		||||
    'DataView',
 | 
			
		||||
    'Date',
 | 
			
		||||
    'Error',
 | 
			
		||||
    'EvalError',
 | 
			
		||||
    'Float32Array',
 | 
			
		||||
    'Float64Array',
 | 
			
		||||
    'Function',
 | 
			
		||||
    'Generator',
 | 
			
		||||
    'GeneratorFunction',
 | 
			
		||||
    'Infinity',
 | 
			
		||||
    'Int16Array',
 | 
			
		||||
    'Int32Array',
 | 
			
		||||
    'Int8Array',
 | 
			
		||||
    'InternalError',
 | 
			
		||||
    'Intl',
 | 
			
		||||
    'JSON',
 | 
			
		||||
    'Map',
 | 
			
		||||
    'Math',
 | 
			
		||||
    'NaN',
 | 
			
		||||
    'Number',
 | 
			
		||||
    'Object',
 | 
			
		||||
    'Promise',
 | 
			
		||||
    'Proxy',
 | 
			
		||||
    'RangeError',
 | 
			
		||||
    'ReferenceError',
 | 
			
		||||
    'Reflect',
 | 
			
		||||
    'RegExp',
 | 
			
		||||
    'Set',
 | 
			
		||||
    'String',
 | 
			
		||||
    'Symbol',
 | 
			
		||||
    'SyntaxError',
 | 
			
		||||
    'TypeError',
 | 
			
		||||
    'URIError',
 | 
			
		||||
    'Uint16Array',
 | 
			
		||||
    'Uint32Array',
 | 
			
		||||
    'Uint8Array',
 | 
			
		||||
    'Uint8ClampedArray',
 | 
			
		||||
    'WeakMap',
 | 
			
		||||
    'WeakSet',
 | 
			
		||||
    'arguments',
 | 
			
		||||
    'console',
 | 
			
		||||
    'expect',
 | 
			
		||||
    'isNaN',
 | 
			
		||||
    'jest',
 | 
			
		||||
    'parseFloat',
 | 
			
		||||
    'parseInt',
 | 
			
		||||
    'exports',
 | 
			
		||||
    'require',
 | 
			
		||||
    'module',
 | 
			
		||||
    '__filename',
 | 
			
		||||
    '__dirname',
 | 
			
		||||
    'undefined',
 | 
			
		||||
    ...Object.getOwnPropertyNames(globalThis)
 | 
			
		||||
  ].sort()
 | 
			
		||||
);
 | 
			
		||||
const IDVisitor = {
 | 
			
		||||
  ReferencedIdentifier(path, {ids}) {
 | 
			
		||||
    ids.add(path);
 | 
			
		||||
  },
 | 
			
		||||
  blacklist: [
 | 
			
		||||
    'TypeAnnotation',
 | 
			
		||||
    'TSTypeAnnotation',
 | 
			
		||||
    'TSTypeQuery',
 | 
			
		||||
    'TSTypeReference'
 | 
			
		||||
  ]
 | 
			
		||||
};
 | 
			
		||||
const FUNCTIONS = Object.create(null);
 | 
			
		||||
FUNCTIONS.mock = args => {
 | 
			
		||||
  if (args.length === 1) {
 | 
			
		||||
    return args[0].isStringLiteral() || args[0].isLiteral();
 | 
			
		||||
  } else if (args.length === 2 || args.length === 3) {
 | 
			
		||||
    const moduleFactory = args[1];
 | 
			
		||||
    if (!moduleFactory.isFunction()) {
 | 
			
		||||
      throw moduleFactory.buildCodeFrameError(
 | 
			
		||||
        'The second argument of `jest.mock` must be an inline function.\n',
 | 
			
		||||
        TypeError
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    const ids = new Set();
 | 
			
		||||
    const parentScope = moduleFactory.parentPath.scope;
 | 
			
		||||
    // @ts-expect-error: ReferencedIdentifier and blacklist are not known on visitors
 | 
			
		||||
    moduleFactory.traverse(IDVisitor, {
 | 
			
		||||
      ids
 | 
			
		||||
    });
 | 
			
		||||
    for (const id of ids) {
 | 
			
		||||
      const {name} = id.node;
 | 
			
		||||
      let found = false;
 | 
			
		||||
      let scope = id.scope;
 | 
			
		||||
      while (scope !== parentScope) {
 | 
			
		||||
        if (scope.bindings[name] != null) {
 | 
			
		||||
          found = true;
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
        scope = scope.parent;
 | 
			
		||||
      }
 | 
			
		||||
      if (!found) {
 | 
			
		||||
        let isAllowedIdentifier =
 | 
			
		||||
          (scope.hasGlobal(name) && ALLOWED_IDENTIFIERS.has(name)) ||
 | 
			
		||||
          /^mock/i.test(name) ||
 | 
			
		||||
          // Allow istanbul's coverage variable to pass.
 | 
			
		||||
          /^(?:__)?cov/.test(name);
 | 
			
		||||
        if (!isAllowedIdentifier) {
 | 
			
		||||
          const binding = scope.bindings[name];
 | 
			
		||||
          if (binding?.path.isVariableDeclarator()) {
 | 
			
		||||
            const {node} = binding.path;
 | 
			
		||||
            const initNode = node.init;
 | 
			
		||||
            if (initNode && binding.constant && scope.isPure(initNode, true)) {
 | 
			
		||||
              hoistedVariables.add(node);
 | 
			
		||||
              isAllowedIdentifier = true;
 | 
			
		||||
            }
 | 
			
		||||
          } else if (binding?.path.isImportSpecifier()) {
 | 
			
		||||
            const importDecl = binding.path.parentPath;
 | 
			
		||||
            const imported = binding.path.node.imported;
 | 
			
		||||
            if (
 | 
			
		||||
              importDecl.node.source.value === JEST_GLOBALS_MODULE_NAME &&
 | 
			
		||||
              ((0, _types().isIdentifier)(imported)
 | 
			
		||||
                ? imported.name
 | 
			
		||||
                : imported.value) === JEST_GLOBALS_MODULE_JEST_EXPORT_NAME
 | 
			
		||||
            ) {
 | 
			
		||||
              isAllowedIdentifier = true;
 | 
			
		||||
              // Imports are already hoisted, so we don't need to add it
 | 
			
		||||
              // to hoistedVariables.
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!isAllowedIdentifier) {
 | 
			
		||||
          throw id.buildCodeFrameError(
 | 
			
		||||
            'The module factory of `jest.mock()` is not allowed to ' +
 | 
			
		||||
              'reference any out-of-scope variables.\n' +
 | 
			
		||||
              `Invalid variable access: ${name}\n` +
 | 
			
		||||
              `Allowed objects: ${Array.from(ALLOWED_IDENTIFIERS).join(
 | 
			
		||||
                ', '
 | 
			
		||||
              )}.\n` +
 | 
			
		||||
              'Note: This is a precaution to guard against uninitialized mock ' +
 | 
			
		||||
              'variables. If it is ensured that the mock is required lazily, ' +
 | 
			
		||||
              'variable names prefixed with `mock` (case insensitive) are permitted.\n',
 | 
			
		||||
            ReferenceError
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
};
 | 
			
		||||
FUNCTIONS.unmock = args => args.length === 1 && args[0].isStringLiteral();
 | 
			
		||||
FUNCTIONS.deepUnmock = args => args.length === 1 && args[0].isStringLiteral();
 | 
			
		||||
FUNCTIONS.disableAutomock = FUNCTIONS.enableAutomock = args =>
 | 
			
		||||
  args.length === 0;
 | 
			
		||||
const createJestObjectGetter = (0, _template().statement)`
 | 
			
		||||
function GETTER_NAME() {
 | 
			
		||||
  const { JEST_GLOBALS_MODULE_JEST_EXPORT_NAME } = require("JEST_GLOBALS_MODULE_NAME");
 | 
			
		||||
  GETTER_NAME = () => JEST_GLOBALS_MODULE_JEST_EXPORT_NAME;
 | 
			
		||||
  return JEST_GLOBALS_MODULE_JEST_EXPORT_NAME;
 | 
			
		||||
}
 | 
			
		||||
`;
 | 
			
		||||
const isJestObject = expression => {
 | 
			
		||||
  // global
 | 
			
		||||
  if (
 | 
			
		||||
    expression.isIdentifier() &&
 | 
			
		||||
    expression.node.name === JEST_GLOBAL_NAME &&
 | 
			
		||||
    !expression.scope.hasBinding(JEST_GLOBAL_NAME)
 | 
			
		||||
  ) {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  // import { jest } from '@jest/globals'
 | 
			
		||||
  if (
 | 
			
		||||
    expression.referencesImport(
 | 
			
		||||
      JEST_GLOBALS_MODULE_NAME,
 | 
			
		||||
      JEST_GLOBALS_MODULE_JEST_EXPORT_NAME
 | 
			
		||||
    )
 | 
			
		||||
  ) {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  // import * as JestGlobals from '@jest/globals'
 | 
			
		||||
  if (
 | 
			
		||||
    expression.isMemberExpression() &&
 | 
			
		||||
    !expression.node.computed &&
 | 
			
		||||
    expression.get('object').referencesImport(JEST_GLOBALS_MODULE_NAME, '*') &&
 | 
			
		||||
    expression.node.property.type === 'Identifier' &&
 | 
			
		||||
    expression.node.property.name === JEST_GLOBALS_MODULE_JEST_EXPORT_NAME
 | 
			
		||||
  ) {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
};
 | 
			
		||||
const extractJestObjExprIfHoistable = expr => {
 | 
			
		||||
  if (!expr.isCallExpression()) {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
  const callee = expr.get('callee');
 | 
			
		||||
  const args = expr.get('arguments');
 | 
			
		||||
  if (!callee.isMemberExpression() || callee.node.computed) {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
  const object = callee.get('object');
 | 
			
		||||
  const property = callee.get('property');
 | 
			
		||||
  const propertyName = property.node.name;
 | 
			
		||||
  const jestObjExpr = isJestObject(object)
 | 
			
		||||
    ? object
 | 
			
		||||
    : // The Jest object could be returned from another call since the functions are all chainable.
 | 
			
		||||
      extractJestObjExprIfHoistable(object)?.path;
 | 
			
		||||
  if (!jestObjExpr) {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Important: Call the function check last
 | 
			
		||||
  // It might throw an error to display to the user,
 | 
			
		||||
  // which should only happen if we're already sure it's a call on the Jest object.
 | 
			
		||||
  const functionIsHoistable = FUNCTIONS[propertyName]?.(args) ?? false;
 | 
			
		||||
  let functionHasHoistableScope = functionIsHoistable;
 | 
			
		||||
  for (
 | 
			
		||||
    let path = expr;
 | 
			
		||||
    path && !functionHasHoistableScope;
 | 
			
		||||
    path = path.parentPath
 | 
			
		||||
  ) {
 | 
			
		||||
    functionHasHoistableScope = hoistedJestExpressions.has(
 | 
			
		||||
      // @ts-expect-error: it's ok if path.node is not an Expression, .has will
 | 
			
		||||
      // just return false.
 | 
			
		||||
      path.node
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
  if (functionHasHoistableScope) {
 | 
			
		||||
    hoistedJestExpressions.add(expr.node);
 | 
			
		||||
    return {
 | 
			
		||||
      hoist: functionIsHoistable,
 | 
			
		||||
      path: jestObjExpr
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
  return null;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* eslint-disable sort-keys */
 | 
			
		||||
function jestHoist() {
 | 
			
		||||
  return {
 | 
			
		||||
    pre({path: program}) {
 | 
			
		||||
      this.declareJestObjGetterIdentifier = () => {
 | 
			
		||||
        if (this.jestObjGetterIdentifier) {
 | 
			
		||||
          return this.jestObjGetterIdentifier;
 | 
			
		||||
        }
 | 
			
		||||
        this.jestObjGetterIdentifier =
 | 
			
		||||
          program.scope.generateUidIdentifier('getJestObj');
 | 
			
		||||
        program.unshiftContainer('body', [
 | 
			
		||||
          createJestObjectGetter({
 | 
			
		||||
            GETTER_NAME: this.jestObjGetterIdentifier.name,
 | 
			
		||||
            JEST_GLOBALS_MODULE_JEST_EXPORT_NAME,
 | 
			
		||||
            JEST_GLOBALS_MODULE_NAME
 | 
			
		||||
          })
 | 
			
		||||
        ]);
 | 
			
		||||
        return this.jestObjGetterIdentifier;
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
    visitor: {
 | 
			
		||||
      ExpressionStatement(exprStmt) {
 | 
			
		||||
        const jestObjInfo = extractJestObjExprIfHoistable(
 | 
			
		||||
          exprStmt.get('expression')
 | 
			
		||||
        );
 | 
			
		||||
        if (jestObjInfo) {
 | 
			
		||||
          const jestCallExpr = (0, _types().callExpression)(
 | 
			
		||||
            this.declareJestObjGetterIdentifier(),
 | 
			
		||||
            []
 | 
			
		||||
          );
 | 
			
		||||
          jestObjInfo.path.replaceWith(jestCallExpr);
 | 
			
		||||
          if (jestObjInfo.hoist) {
 | 
			
		||||
            hoistedJestGetters.add(jestCallExpr);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    // in `post` to make sure we come after an import transform and can unshift above the `require`s
 | 
			
		||||
    post({path: program}) {
 | 
			
		||||
      visitBlock(program);
 | 
			
		||||
      program.traverse({
 | 
			
		||||
        BlockStatement: visitBlock
 | 
			
		||||
      });
 | 
			
		||||
      function visitBlock(block) {
 | 
			
		||||
        // use a temporary empty statement instead of the real first statement, which may itself be hoisted
 | 
			
		||||
        const [varsHoistPoint, callsHoistPoint] = block.unshiftContainer(
 | 
			
		||||
          'body',
 | 
			
		||||
          [(0, _types().emptyStatement)(), (0, _types().emptyStatement)()]
 | 
			
		||||
        );
 | 
			
		||||
        block.traverse({
 | 
			
		||||
          CallExpression: visitCallExpr,
 | 
			
		||||
          VariableDeclarator: visitVariableDeclarator,
 | 
			
		||||
          // do not traverse into nested blocks, or we'll hoist calls in there out to this block
 | 
			
		||||
          blacklist: ['BlockStatement']
 | 
			
		||||
        });
 | 
			
		||||
        callsHoistPoint.remove();
 | 
			
		||||
        varsHoistPoint.remove();
 | 
			
		||||
        function visitCallExpr(callExpr) {
 | 
			
		||||
          if (hoistedJestGetters.has(callExpr.node)) {
 | 
			
		||||
            const mockStmt = callExpr.getStatementParent();
 | 
			
		||||
            if (mockStmt) {
 | 
			
		||||
              const mockStmtParent = mockStmt.parentPath;
 | 
			
		||||
              if (mockStmtParent.isBlock()) {
 | 
			
		||||
                const mockStmtNode = mockStmt.node;
 | 
			
		||||
                mockStmt.remove();
 | 
			
		||||
                callsHoistPoint.insertBefore(mockStmtNode);
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        function visitVariableDeclarator(varDecl) {
 | 
			
		||||
          if (hoistedVariables.has(varDecl.node)) {
 | 
			
		||||
            // should be assert function, but it's not. So let's cast below
 | 
			
		||||
            varDecl.parentPath.assertVariableDeclaration();
 | 
			
		||||
            const {kind, declarations} = varDecl.parent;
 | 
			
		||||
            if (declarations.length === 1) {
 | 
			
		||||
              varDecl.parentPath.remove();
 | 
			
		||||
            } else {
 | 
			
		||||
              varDecl.remove();
 | 
			
		||||
            }
 | 
			
		||||
            varsHoistPoint.insertBefore(
 | 
			
		||||
              (0, _types().variableDeclaration)(kind, [varDecl.node])
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
/* eslint-enable */
 | 
			
		||||
		Reference in New Issue
	
	Block a user