Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
WIKIPEDIA
/
nodejs
/
daily_store_reports_nodejs
/
node_modules
/
proxyquire
/
lib
:
proxyquire.js
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
'use strict' /* jshint laxbreak:true, loopfunc:true */ var Module = require('module') var path = require('path') var resolve = require('resolve') var ProxyquireError = require('./proxyquire-error') var is = require('./is') var assert = require('assert') var fillMissingKeys = require('fill-keys') var moduleNotFoundError = require('module-not-found-error') var hasOwnProperty = Object.prototype.hasOwnProperty function validateArguments (request, stubs) { var msg = (function getMessage () { if (!request) { return 'Missing argument: "request". Need it to resolve desired module.' } if (!stubs) { return 'Missing argument: "stubs". If no stubbing is needed, use regular require instead.' } if (!is.String(request)) { return 'Invalid argument: "request". Needs to be a requirable string that is the module to load.' } if (!is.Object(stubs)) { return 'Invalid argument: "stubs". Needs to be an object containing overrides e.g., {"path": { extname: function () { ... } } }.' } })() if (msg) throw new ProxyquireError(msg) } function Proxyquire (parent) { var self = this var fn = self.load.bind(self) var proto = Proxyquire.prototype this._parent = parent this._preserveCache = true Object.keys(proto) .forEach(function (key) { if (is.Function(proto[key])) fn[key] = self[key].bind(self) }) self.fn = fn return fn } /** * Disables call thru, which determines if keys of original modules will be used * when they weren't stubbed out. * @name noCallThru * @function * @private * @return {object} The proxyquire function to allow chaining */ Proxyquire.prototype.noCallThru = function () { this._noCallThru = true return this.fn } /** * Enables call thru, which determines if keys of original modules will be used * when they weren't stubbed out. * @name callThru * @function * @private * @return {object} The proxyquire function to allow chaining */ Proxyquire.prototype.callThru = function () { this._noCallThru = false return this.fn } /** * Will make proxyquire remove the requested modules from the `require.cache` in order to force * them to be reloaded the next time they are proxyquired. * This behavior differs from the way nodejs `require` works, but for some tests this maybe useful. * * @name noPreserveCache * @function * @private * @return {object} The proxyquire function to allow chaining */ Proxyquire.prototype.noPreserveCache = function () { this._preserveCache = false return this.fn } /** * Restores proxyquire caching behavior to match the one of nodejs `require` * * @name preserveCache * @function * @private * @return {object} The proxyquire function to allow chaining */ Proxyquire.prototype.preserveCache = function () { this._preserveCache = true return this.fn } /** * Loads a module using the given stubs instead of their normally resolved required modules. * @param request The requirable module path to load. * @param stubs The stubs to use. e.g., { "path": { extname: function () { ... } } } * @return {*} A newly resolved module with the given stubs. */ Proxyquire.prototype.load = function (request, stubs) { validateArguments(request, stubs) // Find out if any of the passed stubs are global overrides for (var key in stubs) { var stub = stubs[key] if (stub === null) continue if (typeof stub === 'undefined') { throw new ProxyquireError('Invalid stub: "' + key + '" cannot be undefined') } if (hasOwnProperty.call(stub, '@global')) { this._containsGlobal = true } if (hasOwnProperty.call(stub, '@runtimeGlobal')) { this._containsGlobal = true this._containsRuntimeGlobal = true } } // Ignore the module cache when return the requested module return this._withoutCache(this._parent, stubs, request, this._parent.require.bind(this._parent, request)) } // Resolves a stub relative to a module. // `baseModule` is the module we're resolving from. `pathToResolve` is the // module we want to resolve (i.e. the string passed to `require()`). Proxyquire.prototype._resolveModule = function (baseModule, pathToResolve, stubs) { try { return resolve.sync(pathToResolve, { basedir: path.dirname(baseModule), extensions: Object.keys(require.extensions), paths: Module.globalPaths }) } catch (err) { // If this is not a relative path (e.g. "foo" as opposed to "./foo"), and // we couldn't resolve it, then we just let the path through unchanged. // It's safe to do this, because if two different modules require "foo", // they both expect to get back the same thing. if (pathToResolve[0] !== '.') { return pathToResolve } // If `pathToResolve` is relative, then it is *not* safe to return it, // since a file in one directory that requires "./foo" expects to get // back a different module than one that requires "./foo" from another // directory. However, if !this._preserveCache, then we don't want to // throw, since we can resolve modules that don't exist. Resolve as // best we can. We also need to check if the relative module has @noCallThru. var resolvedPath = path.resolve(path.dirname(baseModule), pathToResolve) var moduleNoCallThru if (hasOwnProperty.call(stubs, pathToResolve) && stubs[pathToResolve]) { // pathToResolve is currently relative on stubs from _withoutCache() call moduleNoCallThru = hasOwnProperty.call(stubs[pathToResolve], '@noCallThru') ? stubs[pathToResolve]['@noCallThru'] : undefined } else if (hasOwnProperty.call(stubs, resolvedPath) && stubs[resolvedPath]) { // after _withoutCache() alters stubs paths to be absolute moduleNoCallThru = hasOwnProperty.call(stubs[resolvedPath], '@noCallThru') ? stubs[resolvedPath]['@noCallThru'] : undefined } if (!this._preserveCache || this._noCallThru || moduleNoCallThru) { return resolvedPath } throw err } } // This replaces a module's require function Proxyquire.prototype._require = function (module, stubs, path) { assert(typeof path === 'string', 'path must be a string') assert(path, 'missing path') var resolvedPath = this._resolveModule(module.filename, path, stubs) if (hasOwnProperty.call(stubs, resolvedPath)) { var stub = stubs[resolvedPath] if (stub === null) { // Mimic the module-not-found exception thrown by node.js. throw moduleNotFoundError(path) } if (hasOwnProperty.call(stub, '@noCallThru') ? !stub['@noCallThru'] : !this._noCallThru) { fillMissingKeys(stub, Module._load(path, module)) } // We are top level or this stub is marked as global if (module.parent === this._parent || hasOwnProperty.call(stub, '@global') || hasOwnProperty.call(stub, '@runtimeGlobal')) { return stub } } // Only ignore the cache if we have global stubs if (this._containsRuntimeGlobal) { return this._withoutCache(module, stubs, path, Module._load.bind(Module, path, module)) } else { return Module._load(path, module) } } Proxyquire.prototype._withoutCache = function (module, stubs, path, func) { // Temporarily disable the cache - either per-module or globally if we have global stubs var restoreCache = this._disableCache(module, path) var resolvedPath = Module._resolveFilename(path, module) // Resolve all stubs to absolute paths. stubs = Object.keys(stubs) .reduce(function (result, stubPath) { var resolvedStubPath = this._resolveModule(resolvedPath, stubPath, stubs) result[resolvedStubPath] = stubs[stubPath] return result }.bind(this), {}) // Override all require extension handlers var restoreExtensionHandlers = this._overrideExtensionHandlers(module, stubs) try { // Execute the function that needs the module cache disabled return func() } finally { // Restore the cache if we are preserving it if (this._preserveCache) { restoreCache() } else { var ids = [resolvedPath].concat(Object.keys(stubs).filter(Boolean)) ids.forEach(function (id) { delete require.cache[id] }) } // Finally restore the original extension handlers restoreExtensionHandlers() } } Proxyquire.prototype._disableCache = function (module, path) { if (this._containsGlobal) { // empty the require cache because if we are stubbing C but requiring A, // and if A requires B and B requires C, then B and C might be cached already // and we'll never get the chance to return our stub return this._disableGlobalCache() } // Temporarily delete the SUT from the require cache return this._disableModuleCache(path, module) } Proxyquire.prototype._disableGlobalCache = function () { var cache = require.cache require.cache = Module._cache = {} for (var id in cache) { // Keep native modules (i.e. `.node` files). // Otherwise, Node.js would throw a “Module did not self-register” // error upon requiring it a second time. // See https://github.com/nodejs/node/issues/5016. if (/\.node$/.test(id)) { require.cache[id] = cache[id] } } // Return a function that will undo what we just did return function () { // Keep native modules which were added to the cache in the meantime. for (var id in require.cache) { if (/\.node$/.test(id)) { cache[id] = require.cache[id] } } require.cache = Module._cache = cache } } Proxyquire.prototype._disableModuleCache = function (path, module) { // Find the ID (location) of the SUT, relative to the parent var id = Module._resolveFilename(path, module) var cached = Module._cache[id] delete Module._cache[id] // Return a function that will undo what we just did return function () { if (cached) { Module._cache[id] = cached } else { delete Module._cache[id] } } } Proxyquire.prototype._overrideExtensionHandlers = function (module, resolvedStubs) { /* eslint node/no-deprecated-api: [error, {ignoreGlobalItems: ["require.extensions"]}] */ var originalExtensions = {} var self = this Object.keys(require.extensions).forEach(function (extension) { // Store the original so we can restore it later if (!originalExtensions[extension]) { originalExtensions[extension] = require.extensions[extension] } // Override the default handler for the requested file extension require.extensions[extension] = function (module, filename) { // Override the require method for this module module.require = self._require.bind(self, module, resolvedStubs) return originalExtensions[extension](module, filename) } }) // Return a function that will undo what we just did return function () { Object.keys(originalExtensions).forEach(function (extension) { require.extensions[extension] = originalExtensions[extension] }) } } module.exports = Proxyquire