123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- /*
- Copyright (c) 2014 Google Inc. All rights reserved.
- Copyright (c) 2012-2013 Johannes Ewald.
- Use of this source code is governed by the MIT License, available in this package's LICENSE file
- or at http://opensource.org/licenses/MIT.
- */
- const _ = require('lodash');
- const fs = require('fs');
- const Module = require('module');
- const originalWrapper = Module.wrapper.slice(0);
- const requizzleWrappers = {
- extras: require('./wrappers/extras'),
- requirePaths: require('./wrappers/requirepaths'),
- strict: require('./wrappers/strict')
- };
- function wrap(wrappers, script) {
- return wrappers[0] + script + wrappers[1];
- }
- function replaceWrapper(wrapperObj) {
- const joiner = '\n';
- const before = wrapperObj.before.join(joiner);
- const after = wrapperObj.after.join(joiner);
- const wrappers = [
- originalWrapper[0] + before,
- after + originalWrapper[1]
- ];
- Module.wrap = wrap.bind(null, wrappers);
- }
- function restoreWrapper() {
- Module.wrap = wrap.bind(null, originalWrapper);
- }
- function createModule(targetPath, parentModule, moduleCache) {
- moduleCache[targetPath] = moduleCache[targetPath] || new Module(targetPath, parentModule);
- return moduleCache[targetPath];
- }
- /**
- * Wrapper for `require()` to prevent the target module's dependencies from being swizzled.
- *
- * @param {!Module} targetModule - The module that is being swizzled.
- * @param {!function} nodeRequire - The original `require()` method for the target module.
- * @param {!string} filepath - The value passed to `require()`.
- * @return {!Module} The requested module dependency.
- */
- function requireProxy(targetModule, nodeRequire, filepath) {
- restoreWrapper();
- targetModule.require = nodeRequire;
- return nodeRequire.call(targetModule, filepath);
- }
- /**
- * Wrapper for `require()` to swizzle the target module's dependencies, using the same settings as
- * the target module.
- *
- * @param {!Module} targetModule - The module that is being swizzled.
- * @param {!Object} opts - The Requizzle options object.
- * @param {!string} filepath - The value passed to `require()`.
- * @return {!Module} The requested module dependency.
- */
- function infectProxy(targetModule, cache, opts, filepath) {
- let moduleExports;
- // loaded here to avoid circular dependencies
- const Requizzle = require('./requizzle');
- let requizzle;
- opts = _.clone(opts);
- opts.parent = targetModule;
- requizzle = new Requizzle(opts, cache);
- moduleExports = requizzle.requizzle(filepath);
- return moduleExports;
- }
- exports.load = function load(targetPath, parentModule, wrapper, cache, options) {
- let nodeRequire;
- let targetModule;
- // Handle circular requires, and avoid reloading modules unnecessarily
- if (cache.module[targetPath]) {
- return cache.module[targetPath];
- }
- targetModule = createModule(targetPath, parentModule, cache.module);
- nodeRequire = targetModule.require;
- if (options.infect) {
- targetModule.require = filepath => infectProxy(targetModule, cache, options, filepath);
- } else {
- targetModule.require = filepath => requireProxy(targetModule, nodeRequire, filepath);
- }
- // update the wrapper before we load the target module
- replaceWrapper(wrapper);
- targetModule.load(targetModule.id);
- // make sure the wrapper is restored even if the target module doesn't load any dependencies
- restoreWrapper();
- return targetModule;
- };
- /**
- * Check whether the entire module includes a `'use strict'` declaration.
- *
- * @param {string} src - The source file to check.
- * @return {boolean} Set to `true` if the module includes a `use strict` declaration.
- */
- function detectStrictMode(src) {
- return (/^\s*(?:["']use strict["'])[ \t]*(?:[\r\n]|;)/g).test(src);
- }
- function loadSource(targetPath, sourceCache) {
- if (sourceCache[targetPath] === undefined) {
- sourceCache[targetPath] = fs.readFileSync(targetPath, 'utf8');
- }
- return sourceCache[targetPath];
- }
- exports.createWrapper = function createWrapper(targetPath, parentModule, cache, options) {
- let src;
- const wrapperObject = {
- before: [],
- after: []
- };
- function add(wrapperFunctions, opts) {
- const params = [targetPath, parentModule, opts];
- ['before', 'after'].forEach(item => {
- const result = wrapperFunctions[item].apply(null, params);
- if (result) {
- wrapperObject[item].push(result);
- }
- });
- }
- // Preserve the module's `use strict` declaration if present
- src = loadSource(targetPath, cache.source);
- if (detectStrictMode(src) === true) {
- add(requizzleWrappers.strict);
- }
- if (options.requirePaths) {
- add(requizzleWrappers.requirePaths, options.requirePaths);
- }
- if (options.extras) {
- add(requizzleWrappers.extras, options.extras);
- }
- return wrapperObject;
- };
|