diff options
Diffstat (limited to 'node_modules/babel-plugin-jest-hoist')
| -rw-r--r-- | node_modules/babel-plugin-jest-hoist/LICENSE | 21 | ||||
| -rw-r--r-- | node_modules/babel-plugin-jest-hoist/README.md | 33 | ||||
| -rw-r--r-- | node_modules/babel-plugin-jest-hoist/build/index.d.ts | 13 | ||||
| -rw-r--r-- | node_modules/babel-plugin-jest-hoist/build/index.js | 389 | ||||
| -rw-r--r-- | node_modules/babel-plugin-jest-hoist/package.json | 41 | 
5 files changed, 497 insertions, 0 deletions
diff --git a/node_modules/babel-plugin-jest-hoist/LICENSE b/node_modules/babel-plugin-jest-hoist/LICENSE new file mode 100644 index 0000000..b96dcb0 --- /dev/null +++ b/node_modules/babel-plugin-jest-hoist/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Facebook, Inc. and its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/babel-plugin-jest-hoist/README.md b/node_modules/babel-plugin-jest-hoist/README.md new file mode 100644 index 0000000..1a90bbe --- /dev/null +++ b/node_modules/babel-plugin-jest-hoist/README.md @@ -0,0 +1,33 @@ +# babel-plugin-jest-hoist + +Babel plugin to hoist `jest.disableAutomock`, `jest.enableAutomock`, `jest.unmock`, `jest.mock`, calls above `import` statements. This plugin is automatically included when using [babel-jest](https://github.com/facebook/jest/tree/main/packages/babel-jest). + +## Installation + +```sh +$ yarn add --dev babel-plugin-jest-hoist +``` + +## Usage + +### Via `babel.config.js` (Recommended) + +```js +module.exports = { +  plugins: ['jest-hoist'], +}; +``` + +### Via CLI + +```sh +$ babel --plugins jest-hoist script.js +``` + +### Via Node API + +```javascript +require('@babel/core').transform('code', { +  plugins: ['jest-hoist'], +}); +``` diff --git a/node_modules/babel-plugin-jest-hoist/build/index.d.ts b/node_modules/babel-plugin-jest-hoist/build/index.d.ts new file mode 100644 index 0000000..007cc55 --- /dev/null +++ b/node_modules/babel-plugin-jest-hoist/build/index.d.ts @@ -0,0 +1,13 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ +import type { PluginObj } from '@babel/core'; +import { Identifier } from '@babel/types'; +export default function jestHoist(): PluginObj<{ +    declareJestObjGetterIdentifier: () => Identifier; +    jestObjGetterIdentifier?: Identifier; +}>; diff --git a/node_modules/babel-plugin-jest-hoist/build/index.js b/node_modules/babel-plugin-jest-hoist/build/index.js new file mode 100644 index 0000000..d8b74e5 --- /dev/null +++ b/node_modules/babel-plugin-jest-hoist/build/index.js @@ -0,0 +1,389 @@ +'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) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * 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(); // 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(global) +  ].sort() +); +const IDVisitor = { +  ReferencedIdentifier(path, {ids}) { +    ids.add(path); +  }, + +  blacklist: ['TypeAnnotation', 'TSTypeAnnotation', '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]) { +          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 !== null && +            binding !== void 0 && +            binding.path.isVariableDeclarator() +          ) { +            const {node} = binding.path; +            const initNode = node.init; + +            if (initNode && binding.constant && scope.isPure(initNode, true)) { +              hoistedVariables.add(node); +              isAllowedIdentifier = true; +            } +          } +        } + +        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 => { +  var _FUNCTIONS$propertyNa; + +  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); + +  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 functionLooksHoistable = +    (_FUNCTIONS$propertyNa = FUNCTIONS[propertyName]) === null || +    _FUNCTIONS$propertyNa === void 0 +      ? void 0 +      : _FUNCTIONS$propertyNa.call(FUNCTIONS, args); +  return functionLooksHoistable ? jestObjExpr : 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 jestObjExpr = extractJestObjExprIfHoistable( +          exprStmt.get('expression') +        ); + +        if (jestObjExpr) { +          jestObjExpr.replaceWith( +            (0, _types().callExpression)( +              this.declareJestObjGetterIdentifier(), +              [] +            ) +          ); +        } +      } +    }, + +    // in `post` to make sure we come after an import transform and can unshift above the `require`s +    post({path: program}) { +      const self = this; +      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) { +          var _self$jestObjGetterId; + +          const { +            node: {callee} +          } = callExpr; + +          if ( +            (0, _types().isIdentifier)(callee) && +            callee.name === +              ((_self$jestObjGetterId = self.jestObjGetterIdentifier) === +                null || _self$jestObjGetterId === void 0 +                ? void 0 +                : _self$jestObjGetterId.name) +          ) { +            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 */ diff --git a/node_modules/babel-plugin-jest-hoist/package.json b/node_modules/babel-plugin-jest-hoist/package.json new file mode 100644 index 0000000..2d45b7b --- /dev/null +++ b/node_modules/babel-plugin-jest-hoist/package.json @@ -0,0 +1,41 @@ +{ +  "name": "babel-plugin-jest-hoist", +  "version": "27.5.1", +  "repository": { +    "type": "git", +    "url": "https://github.com/facebook/jest.git", +    "directory": "packages/babel-plugin-jest-hoist" +  }, +  "engines": { +    "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" +  }, +  "license": "MIT", +  "main": "./build/index.js", +  "types": "./build/index.d.ts", +  "exports": { +    ".": { +      "types": "./build/index.d.ts", +      "default": "./build/index.js" +    }, +    "./package.json": "./package.json" +  }, +  "dependencies": { +    "@babel/template": "^7.3.3", +    "@babel/types": "^7.3.3", +    "@types/babel__core": "^7.0.0", +    "@types/babel__traverse": "^7.0.6" +  }, +  "devDependencies": { +    "@babel/core": "^7.11.6", +    "@babel/preset-react": "^7.12.1", +    "@types/babel__template": "^7.0.2", +    "@types/node": "*", +    "@types/prettier": "^2.0.0", +    "babel-plugin-tester": "^10.0.0", +    "prettier": "^2.1.1" +  }, +  "publishConfig": { +    "access": "public" +  }, +  "gitHead": "67c1aa20c5fec31366d733e901fee2b981cb1850" +}  | 
