Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/twbs/rewire.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJohannes <johannes.ewald@roomieplanet.de>2012-08-20 04:36:35 +0400
committerJohannes <johannes.ewald@roomieplanet.de>2012-08-20 04:36:35 +0400
commit3cc25aec3698c7becd463bd75524a3b2a319ecab (patch)
treecff8c03016f05a7646ed864ca7238e5f9f09b7ce /lib
parentc5d8fab07f0edc568e45e0747f863afd5876abc2 (diff)
- All tests running
- Added changelog
Diffstat (limited to 'lib')
-rw-r--r--lib/bundlers/browserify/browserifyMiddleware.js76
-rw-r--r--lib/bundlers/browserify/browserifyRewire.js98
-rw-r--r--lib/bundlers/injectRewire.js68
-rw-r--r--lib/bundlers/webpack/configureWebpack.js14
-rw-r--r--lib/bundlers/webpack/webpackPostLoader.js33
-rw-r--r--lib/bundlers/webpack/webpackPostProcessor.js20
-rw-r--r--lib/bundlers/webpack/webpackRewire.js13
-rw-r--r--lib/index.js14
-rw-r--r--lib/internalRewire.js194
9 files changed, 294 insertions, 236 deletions
diff --git a/lib/bundlers/browserify/browserifyMiddleware.js b/lib/bundlers/browserify/browserifyMiddleware.js
index 39d76b1..3c26e96 100644
--- a/lib/bundlers/browserify/browserifyMiddleware.js
+++ b/lib/bundlers/browserify/browserifyMiddleware.js
@@ -5,30 +5,70 @@ var setterSrc = require("../../__set__.js").toString(),
getRewireRequires = require("../getRewireRequires.js"),
rewireIndex = path.resolve(__dirname, "../../index.js"),
+ rewireLib = path.join("rewire", "lib"),
settersAndGettersSrc;
+/**
+ * This function can be added to browserify via b.use().
+ * @see https://github.com/substack/node-browserify/blob/master/doc/methods.markdown#methods
+ *
+ * It injects special code before every module in order to gain access to the private scope
+ * of the module. Additionally it forwards all calls of require("rewire") to the module
+ * browserifyRewire.js. Thus we don't need any cumbersome client/server-switches in the index.js.
+ *
+ * @param {browserify} b the bundle returned by browserify()
+ * @return {browserify} b
+ */
function browserifyMiddleware(b) {
+
+ /**
+ * Does actually the injecting of the special code. It is called by browserify for every
+ * js-module.
+ *
+ * @param {String} src
+ * @param {String} filename
+ * @return {String} src
+ */
function doInjectRewire(src, filename) {
var rewireRequires;
- // Search for all rewire() statements an return the required path.
- rewireRequires = getRewireRequires(src);
+ // We don't want to inject this code at the beginning of a rewire/lib-module. Otherwise
+ // it would cause a black hole that devours our universe.
+ if (filename.indexOf(rewireLib) === -1) {
+ // Search for all rewire() statements an return the required path.
+ rewireRequires = getRewireRequires(src);
+
+ // Add all modules that are loaded by rewire() manually to browserify because browserify's
+ // require-sniffing doesn't work here.
+ rewireRequires.forEach(function forEachRewireRequire(requirePath) {
+
+ // Resolve to absolute paths
+ if (requirePath.charAt(0) === ".") {
+ requirePath = path.resolve(path.dirname(filename), requirePath);
+ }
+ b.require(requirePath);
- // Add all modules that are loaded by rewire() manually to browserify because browserify's
- // require-sniffing doesn't work here.
- rewireRequires.forEach(function forEachRewireRequire(requirePath) {
- // Resolve absolute paths
- if (requirePath.charAt(0) === ".") {
- requirePath = path.resolve(path.dirname(filename), requirePath);
- }
- b.require(requirePath);
- });
+ });
- src = injectRewire(src, filename, settersAndGettersSrc);
+ // Injects the special code
+ src = injectRewire(src, settersAndGettersSrc);
+
+ // Because browserify doesn't create a new, independent module instance each time the module is
+ // executed we have to make it fake-independent. Thus the rewired module doesn't influence the original module.
+ // This is a crazy hack, but: hey don't blame me! Make a pull-request to browserify :)
+ src += ' module = require("rewire").getIndependentModule(module);';
+ }
return src;
}
+ /**
+ * Gets called before each module is loaded.
+ * This function ensures that lib/bundlers/browserify/browserifyRewire.js is returned instead of lib/index.js
+ *
+ * @param {String} filename
+ * @return {String} filename
+ */
function forwardBrowserifyRewire(filename) {
if (filename === rewireIndex) {
filename = __dirname + "/browserifyRewire.js";
@@ -54,14 +94,18 @@ function browserifyMiddleware(b) {
*/
settersAndGettersSrc = (
'var rewire = require("rewire"); ' +
- // Registers the setters and getters of every module according to their filename. The setters and getters must be
- // injected as string here to gain access to the private scope of the module.
- 'rewire.register(__filename, module, ' + setterSrc + ', ' + getterSrc + ');' +
+
+ // Registers the setters and getters of every module according to their filename. These setter and getter
+ // allow us to gain access to the private scope of the module.
+ 'rewire.register(__filename, module, ' + setterSrc + ', ' + getterSrc + '); ' +
+
// Overrides the module internal require with a require proxy. This proxy is necessary to call rewire with the
// module's filename at the first parameter to resolve the path. This way rewire() works exactly like require().
- 'require = rewire.getProxy(require, __dirname);' +
+ 'require = rewire.getProxy(require, __dirname); ' +
+
// Cleaning up
'rewire = undefined;'
+
).replace(/\s+/g, " "); // strip out unnecessary spaces to be unobtrusive in the debug view
module.exports = browserifyMiddleware; \ No newline at end of file
diff --git a/lib/bundlers/browserify/browserifyRewire.js b/lib/bundlers/browserify/browserifyRewire.js
index 2798b69..b09b51a 100644
--- a/lib/bundlers/browserify/browserifyRewire.js
+++ b/lib/bundlers/browserify/browserifyRewire.js
@@ -1,5 +1,5 @@
var pathUtil = require("path"),
- getImportGlobalsSrc = require("./getImportGlobalsSrc.js"); /* must be relative to lib/index.js */
+ getImportGlobalsSrc = require("./getImportGlobalsSrc.js"); // must be relative to lib/index.js because of forwardBrowserifyRewire()
/**
* Clones an object deeply. Used to clone the module-object that is
@@ -33,9 +33,7 @@ function clone(obj) {
}
// Saves all setters and getters for every module according to its filename
-var registry = {},
-// Cache for all rewired modules so it can be reset anytime
- rewiredModules = [];
+var registry = {};
/**
* Executes the given module and adds a special setter and getter that allow you to set and get private variables.
@@ -43,30 +41,31 @@ var registry = {},
*
* @param {!String} parentModulePath __filename of the module, that wants to rewire() another module.
* @param {!String} path path to the module that shall be rewired
- * @param {Boolean=true} cache indicates whether the rewired module should be cached or not
- * @return {Object}
+ * @return {Object} the rewired module
*/
-function browserifyRewire(parentModulePath, path, cache) {
- var originalModule,
+function browserifyRewire(parentModulePath, path) {
+ var cached,
+ originalModule,
+ originalExports,
absPath,
- rewiredExports,
- rewiredModule,
+ rewiredExports = {},
registryEntry,
- _require = require; // hide it from browserify
-
- // Default cache to true
- if (cache === undefined) {
- cache = true;
- }
+ _require = require; // hide it from browserify to avoid annoying console warnings
// Normalize path with file extensions
absPath = pathUtil.resolve(parentModulePath, path);
// Retrieve original module from cache
- originalModule = require.cache[absPath];
+ cached = originalModule = require.cache[absPath];
- if (originalModule && cache) {
- // Delete the original module from the cache so the next call to browserifyRequre()
+ if (cached) {
+ // If there is already a module instance in the cache we have to store the original exports-object
+ // manually so it won't be overwritten by the next execution. This is all necessary due to browserify's
+ // odd way of module creation.
+ originalExports = originalModule.exports;
+ originalModule.exports = rewiredExports;
+
+ // Delete the original module from the cache so the next call to _require()
// executes the module
delete require.cache[absPath];
}
@@ -74,26 +73,24 @@ function browserifyRewire(parentModulePath, path, cache) {
// Require module to trigger rewire.register().
_require(absPath);
+ originalModule = require.cache[absPath];
+
+ // Now we're cloning the exports-obj so later modifications of the rewired module won't influence the
+ // cached, original version of this module.
+ rewiredExports = clone(originalModule.exports);
+
+ if (cached) {
+ // Restore original exports
+ originalModule.exports = originalExports;
+ }
+
// Get registry entry of the target module
registryEntry = registry[absPath];
- originalModule = registryEntry.module;
-
- // Make an independent copy of the original module so we can modify the copy
- // without influencing the original module.
- rewiredModule = clone(originalModule);
- rewiredExports = rewiredModule.exports;
// Apply setter and getters
rewiredExports.__set__ = registryEntry.setter;
rewiredExports.__get__ = registryEntry.getter;
- if (cache) {
- require.cache[absPath] = rewiredModule;
- }
-
- // Store rewired modules for rewire.reset()
- rewiredModules.push(absPath);
-
return rewiredExports;
}
@@ -113,22 +110,6 @@ browserifyRewire.register = function (filename, module, setter, getter) {
};
/**
- * Deletes all rewired modules from the cache
- */
-browserifyRewire.reset = function () {
- var cache = require.cache,
- i,
- absPath;
-
- for (i = 0; i < rewiredModules.length; i++) {
- absPath = rewiredModules[i];
- delete cache[absPath];
- }
-
- rewiredModules = [];
-};
-
-/**
* Provides a special require-proxy. Every module calls require("rewire").getProxy(require, __filename) at the
* beginning and overrides its own require with this proxy.
*
@@ -184,4 +165,25 @@ browserifyRewire.getImportGlobalsSrc = function () {
return getImportGlobalsSrc(['require','module','exports','__dirname','__filename','process']);
};
+/**
+ * Returns a new object that inherits from the original module via prototype inheritance.
+ *
+ * Any changes to the module, e.g. assigning another exports-object will now modify the object
+ * instead of original module.
+ *
+ * @param {Object} originalModule
+ * @return {Object} the independent module
+ */
+browserifyRewire.getIndependentModule = function (originalModule) {
+ var independentModule;
+
+ function IndependentModule() {}
+ IndependentModule.prototype = originalModule;
+
+ independentModule = new IndependentModule();
+ independentModule.exports = originalModule.exports;
+
+ return independentModule;
+};
+
module.exports = browserifyRewire; \ No newline at end of file
diff --git a/lib/bundlers/injectRewire.js b/lib/bundlers/injectRewire.js
index dfd56a4..b6fbef1 100644
--- a/lib/bundlers/injectRewire.js
+++ b/lib/bundlers/injectRewire.js
@@ -6,47 +6,39 @@ var path = require("path"),
/**
* Gets called by the bundler for every module. Injects special code so rewire is able to access private variables.
+ * This module doesn't contain bundler specific code. All bundler specific stuff should be done in the settersAndGettersSrc.
*
- * @param {String} src the module's src
- * @param {String} filename the module's filename
- * @param {String} settersAndGettersSrc source that injects the setters and getters into the module scope
+ * @param {!String} src the module's src
+ * @param {!String} settersAndGettersSrc source that injects the setters and getters into the module scope
* @return {String}
*/
-function injectRewire(src, filename, settersAndGettersSrc) {
- // Convert back slashes to normal slashes on windows.
- if (path.sep !== "/") {
- filename = filename.split(path.sep).join("/");
- }
-
- // We don't want to inject this code at the beginning of a rewire/lib-module. Otherwise
- // it would cause a black hole that devours our universe.
- if (filename.indexOf("/rewire/lib/") === -1) {
- src =
- // Trying to hide the injected line in the debug view with extra whitespaces.
- ' ' +
- '/* this line was injected by rewire() */ ' + // Comment for the curious developer
-
- // Now all global variables are declared with a var statement so they can be changed via __set__()
- // without influencing global objects.
- 'var global = window; ' + // window is our new global object
- 'eval(require("rewire").getImportGlobalsSrc()); ' +
-
- // The module src is wrapped inside a self-executing function.
- // This is necessary to separate the module src from the preceding eval(importGlobalsSrc),
- // because the module src can be in strict mode.
- // In strict mode eval() can only declare vars in the current scope. In this case our setters
- // and getters won't work.
- // @see https://developer.mozilla.org/en/JavaScript/Strict_mode#Making_eval_and_arguments_simpler
- "(function () { " +
-
- // If the module uses strict mode we must ensure that "use strict" stays at the beginning of the function.
- (detectStrictMode(src)? ' "use strict"; ': ' ') +
-
- settersAndGettersSrc + "\n" +
- src +
-
- " })();";
- }
+function injectRewire(src, settersAndGettersSrc) {
+
+ src =
+ // Trying to hide the injected line in the debug view with extra whitespaces.
+ ' ' +
+ '/* this line was injected by rewire() */ ' + // Comment for the curious developer
+
+ // Now all global variables are declared with a var statement so they can be changed via __set__()
+ // without influencing global objects.
+ 'var global = window; ' + // window is our new global object
+ 'eval(require("rewire").getImportGlobalsSrc()); ' +
+
+ // The module src is wrapped inside a self-executing function.
+ // This is necessary to separate the module src from the preceding eval(importGlobalsSrc),
+ // because the module src can be in strict mode.
+ // In strict mode eval() can only declare vars in the current scope. In this case our setters
+ // and getters won't work.
+ // @see https://developer.mozilla.org/en/JavaScript/Strict_mode#Making_eval_and_arguments_simpler
+ "(function () { " +
+
+ // If the module uses strict mode we must ensure that "use strict" stays at the beginning of the function.
+ (detectStrictMode(src)? ' "use strict"; ': ' ') +
+
+ settersAndGettersSrc + "\n" +
+ src +
+
+ " })();";
return src;
}
diff --git a/lib/bundlers/webpack/configureWebpack.js b/lib/bundlers/webpack/configureWebpack.js
index a302d1c..b180fe8 100644
--- a/lib/bundlers/webpack/configureWebpack.js
+++ b/lib/bundlers/webpack/configureWebpack.js
@@ -1,15 +1,23 @@
"use strict"; // run code in ES5 strict mode
+/**
+ * Configures webpack so it can be used with rewire. Make sure that the options aren't modified
+ * after calling this function. It's important that the rewire()-postLoader is the last loader called on a module.
+ *
+ * @see https://github.com/webpack/webpack
+ *
+ * @param {Object} options a webpack option object
+ */
function configureWebpack(options) {
options.resolve = options.resolve || {};
options.postLoaders = options.postLoaders || [];
options.resolve.postprocess = options.resolve.postprocess || {};
options.resolve.postprocess.normal = options.resolve.postprocess.normal || [];
- // @see https://github.com/webpack/webpack/issues/21
- options.context = options.context || process.cwd();
-
+ // Registering the postLoader for injecting the special rewire code
options.postLoaders.push(require("./webpackPostLoader.js"));
+
+ // Registering the postProcessor for resolving paths
options.resolve.postprocess.normal.push(require("./webpackPostProcessor.js"));
}
diff --git a/lib/bundlers/webpack/webpackPostLoader.js b/lib/bundlers/webpack/webpackPostLoader.js
index 620f091..40c8cb2 100644
--- a/lib/bundlers/webpack/webpackPostLoader.js
+++ b/lib/bundlers/webpack/webpackPostLoader.js
@@ -2,20 +2,40 @@
var setterSrc = require("../../__set__.js").toString(),
getterSrc = require("../../__get__.js").toString(),
+ path = require("path"),
injectRewire = require("../injectRewire.js"),
getRewireRegExp = require("../getRewireRegExp.js"),
+ rewireLib = path.join("rewire", "lib"),
+ webpackBuildin = path.join("webpack", "buildin", "__webpack"),
settersAndGettersSrc;
+/**
+ * Injects special code so rewire gains access to the module's private scope.
+ *
+ * Furthermore it changes all calls of rewire("some/path") to rewire("some/path", require("some/path")) so webpack
+ * recognizes the additional dependency. This also enables rewire to resolve the module because webpack replaces all
+ * paths to numeric ids.
+ *
+ * @param {!String} src
+ * @return {String} src
+ */
function webpackLoader(src) {
var filename = this.request.split("!").pop(),
rewireRegExp = getRewireRegExp();
- if (filename.indexOf("/webpack/buildin/__webpack") === -1) {
- src = src.replace(rewireRegExp, '$1rewire("$2", require("$2"))'); // replaces rewire("some/path") into rewire("some/path", require("some/path"))
- src = injectRewire(src, filename, settersAndGettersSrc);
- }
+ // We don't want to inject this code at the beginning of a rewire/lib-module. Otherwise
+ // it would cause a black hole that devours our universe.
+ // We're also omitting webpack's buildin because it doesn't makes sense to rewire these modules. There's also
+ // a bug if the special code is injecting into these modules.
+ if (filename.indexOf(rewireLib) === -1 && filename.indexOf(webpackBuildin) === -1) {
+ // replaces rewire("some/path") into rewire("some/path", require("some/path"))
+ src = src.replace(rewireRegExp, '$1rewire("$2", require("$2"))');
+
+ // Inject special code
+ src = injectRewire(src, settersAndGettersSrc);
+ }
return src;
}
@@ -26,16 +46,17 @@ webpackLoader.test = /\.js$/;
/**
* This string gets injected at the beginning of every module. Its purpose is to
* - register the setters and getters according to the module's filename
- * - override the internal require with a require proxy.
*
* @private
* @type {String}
*/
settersAndGettersSrc = (
'var rewire = require("rewire"); ' +
+
// Registers the setters and getters of every module according to their filename. The setters and getters must be
// injected as string here to gain access to the private scope of the module.
- 'rewire.register(module, ' + setterSrc + ', ' + getterSrc + ');' +
+ 'rewire.register(module, ' + setterSrc + ', ' + getterSrc + '); ' +
+
// Cleaning up
'rewire = undefined;'
).replace(/\s+/g, " "); // strip out unnecessary spaces to be unobtrusive in the debug view
diff --git a/lib/bundlers/webpack/webpackPostProcessor.js b/lib/bundlers/webpack/webpackPostProcessor.js
index e90a4ad..ee10c40 100644
--- a/lib/bundlers/webpack/webpackPostProcessor.js
+++ b/lib/bundlers/webpack/webpackPostProcessor.js
@@ -1,14 +1,20 @@
"use strict"; // run code in ES5 strict mode
-var path = require("path");
+var path = require("path"),
-function webpackPostProcessor(filename, callback) {
- // Convert back slashes to normal slashes on windows.
- if (path.sep !== "/") {
- filename = filename.split(path.sep).join("/");
- }
+ rewireLibIndex = path.join("rewire", "lib", "index.js");
- if (filename.indexOf("/rewire/lib/index.js") !== -1) {
+/**
+ * Gets called before each module is loaded.
+ * This function ensures that lib/bundlers/webpack/webpackRewire.js is returned instead of lib/index.js.
+ *
+ * The callback gets called with (null, filename)
+ *
+ * @param {!String} filename
+ * @param {!Function} callback
+ */
+function webpackPostProcessor(filename, callback) {
+ if (filename.indexOf(rewireLibIndex) !== -1) {
filename = __dirname + "/webpackRewire.js";
}
diff --git a/lib/bundlers/webpack/webpackRewire.js b/lib/bundlers/webpack/webpackRewire.js
index bd86f98..521cf26 100644
--- a/lib/bundlers/webpack/webpackRewire.js
+++ b/lib/bundlers/webpack/webpackRewire.js
@@ -29,11 +29,13 @@ function getIdFromCache(module) {
}
function getIdByExportsObj(moduleExports) {
- var id;
+ var id,
+ entry;
for (id in registry) {
if (registry.hasOwnProperty(id)) {
- if (registry[id].module.exports === moduleExports) {
+ entry = registry[id];
+ if (entry.module.exports === moduleExports) {
return Number(id);
}
}
@@ -44,6 +46,7 @@ function getIdByExportsObj(moduleExports) {
function webpackRewire(path, moduleExports) {
var id = getIdByExportsObj(moduleExports),
+ previousRegistryEntry,
cachedModule,
rewiredModule,
setter,
@@ -53,14 +56,18 @@ function webpackRewire(path, moduleExports) {
throw new Error("(rewire) Sorry, rewiring '" + path + "' is currently not supported.");
}
+ previousRegistryEntry = registry[id];
+
cachedModule = require.cache[id];
delete require.cache[id];
rewiredModule = requireInDisguise(id);
- //require.cache[id] = cachedModule;
+ require.cache[id] = cachedModule;
setter = registry[id].setter;
getter = registry[id].getter;
+ registry[id] = previousRegistryEntry;
+
rewiredModule.__set__ = setter;
rewiredModule.__get__ = getter;
diff --git a/lib/index.js b/lib/index.js
index 4105917..e88d7e5 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -5,19 +5,17 @@ var rewireModule = require("./internalRewire.js");
* call myModule.__set__(name, value) and myModule.__get__(name) to manipulate private variables.
*
* @param {!String} filename Path to the module that shall be rewired. Use it exactly like require().
- * @param {Boolean} cache Indicates whether the rewired module should be cached by node so subsequent calls of require() will return the rewired module. Subsequent calls of rewire() will always overwrite the cache.
* @return {*} the rewired module
*/
-function rewire(filename, cache) {
- if (cache === undefined) {
- cache = true;
- }
-
- return rewireModule(module.parent, filename, cache);
+function rewire(filename) {
+ return rewireModule(module.parent, filename);
}
rewire.reset = rewireModule.reset;
-rewire.browserify = require("./bundlers/browserify/browserifyMiddleware.js");
+rewire.bundlers = {
+ browserify: require("./bundlers/browserify/browserifyMiddleware.js"),
+ webpack: require("./bundlers/webpack/configureWebpack.js")
+};
module.exports = rewire;
diff --git a/lib/internalRewire.js b/lib/internalRewire.js
index b4c8e62..1500e5d 100644
--- a/lib/internalRewire.js
+++ b/lib/internalRewire.js
@@ -1,108 +1,88 @@
-var Module = require("module"),
- fs = require("fs"),
- __get__ = require("./__get__.js"),
- __set__ = require("./__set__.js"),
- getImportGlobalsSrc = require("./getImportGlobalsSrc.js"),
- detectStrictMode = require("./detectStrictMode.js"),
-
- moduleWrapper0 = Module.wrapper[0], // caching original wrapper
- moduleWrapper1 = Module.wrapper[1], // caching original wrapper
- rewiredModules = []; // cache for all rewired modules so it can be reset anytime
-
-function restoreOriginalWrappers() {
- Module.wrapper[0] = moduleWrapper0;
- Module.wrapper[1] = moduleWrapper1;
-}
-
-/**
- * Does actual rewiring the module. For further documentation @see index.js
- */
-function internalRewire(parentModulePath, targetPath, cache) {
- var testModule,
- nodeRequire,
- prepend,
- append,
- src;
-
- /**
- * Proxies the first require call in order to draw back all changes.
- * Thus our changes don't influence other modules
- *
- * @param {!String} path
- */
- function requireProxy(path) {
- restoreOriginalWrappers(); // we need to restore the wrappers now so we don't influence other modules
- testModule.require = nodeRequire; // restoring original nodeRequire
- return nodeRequire.call(testModule, path); // node's require only works when "this" points to the module
- }
-
- // Checking params
- if (typeof targetPath !== "string") {
- throw new TypeError("Filename must be a string");
- }
-
- // Resolve full filename relative to the parent module
- targetPath = Module._resolveFilename(targetPath, parentModulePath);
-
- // Special support for older node versions that returned an array on Module._resolveFilename
- // @see https://github.com/joyent/node/blob/865b077819a9271a29f982faaef99dc635b57fbc/lib/module.js#L319
- if (Array.isArray(targetPath)) {
- targetPath = targetPath[1];
- }
-
- // Create testModule as it would be created by require()
- testModule = new Module(targetPath, parentModulePath);
-
- // Patching requireProxy
- nodeRequire = testModule.require;
- testModule.require = requireProxy;
-
- // We prepend a list of all globals declared with var so they can be overridden (without changing original globals)
- prepend = getImportGlobalsSrc();
-
- // We append our special setter and getter.
- append = "module.exports.__set__ = " + __set__.toString() + "; ";
- append += "module.exports.__get__ = " + __get__.toString() + "; ";
-
- // Check if the module uses the strict mode.
- // If so we must ensure that "use strict"; stays at the beginning of the module.
- src = fs.readFileSync(targetPath, "utf8");
- if (detectStrictMode(src) === true) {
- prepend = ' "use strict"; ' + prepend;
- }
-
- // Apply prepend and appends
- Module.wrapper[0] = moduleWrapper0 + prepend;
- Module.wrapper[1] = append + moduleWrapper1;
-
- //console.log(Module.wrapper);
-
- // Let the show begin
- testModule.load(testModule.id);
-
- // Store the rewired module in the cache when enabled
- if (cache) {
- rewiredModules.push(targetPath); // save in private cache for .reset()
- require.cache[targetPath] = testModule;
- }
-
- // This is only necessary if nothing has been required within the module
- restoreOriginalWrappers();
-
- return testModule.exports;
-}
-
-/**
- * Deletes all rewired modules from the cache
- */
-internalRewire.reset = function () {
- var i;
-
- for (i = 0; i < rewiredModules.length; i++) {
- delete require.cache[rewiredModules[i]];
- }
-
- rewiredModules = [];
-};
-
+var Module = require("module"),
+ fs = require("fs"),
+ __get__ = require("./__get__.js"),
+ __set__ = require("./__set__.js"),
+ getImportGlobalsSrc = require("./getImportGlobalsSrc.js"),
+ detectStrictMode = require("./detectStrictMode.js"),
+
+ moduleWrapper0 = Module.wrapper[0], // caching original wrapper
+ moduleWrapper1 = Module.wrapper[1]; // caching original wrapper
+
+function restoreOriginalWrappers() {
+ Module.wrapper[0] = moduleWrapper0;
+ Module.wrapper[1] = moduleWrapper1;
+}
+
+/**
+ * Does actual rewiring the module. For further documentation @see index.js
+ */
+function internalRewire(parentModulePath, targetPath) {
+ var testModule,
+ nodeRequire,
+ prepend,
+ append,
+ src;
+
+ /**
+ * Proxies the first require call in order to draw back all changes to the Module.wrapper.
+ * Thus our changes don't influence other modules
+ *
+ * @param {!String} path
+ */
+ function requireProxy(path) {
+ restoreOriginalWrappers();
+ testModule.require = nodeRequire;
+ return nodeRequire.call(testModule, path); // node's require only works when "this" points to the module
+ }
+
+ // Checking params
+ if (typeof targetPath !== "string") {
+ throw new TypeError("Filename must be a string");
+ }
+
+ // Resolve full filename relative to the parent module
+ targetPath = Module._resolveFilename(targetPath, parentModulePath);
+
+ // Special support for older node versions that returned an array on Module._resolveFilename
+ // @see https://github.com/joyent/node/blob/865b077819a9271a29f982faaef99dc635b57fbc/lib/module.js#L319
+ if (Array.isArray(targetPath)) {
+ targetPath = targetPath[1];
+ }
+
+ // Create testModule as it would be created by require()
+ testModule = new Module(targetPath, parentModulePath);
+
+ // Patching requireProxy
+ nodeRequire = testModule.require;
+ testModule.require = requireProxy;
+
+ // We prepend a list of all globals declared with var so they can be overridden (without changing original globals)
+ prepend = getImportGlobalsSrc();
+
+ // We append our special setter and getter.
+ append = "module.exports.__set__ = " + __set__.toString() + "; ";
+ append += "module.exports.__get__ = " + __get__.toString() + "; ";
+
+ // Check if the module uses the strict mode.
+ // If so we must ensure that "use strict"; stays at the beginning of the module.
+ src = fs.readFileSync(targetPath, "utf8");
+ if (detectStrictMode(src) === true) {
+ prepend = ' "use strict"; ' + prepend;
+ }
+
+ // Apply prepend and appends
+ Module.wrapper[0] = moduleWrapper0 + prepend;
+ Module.wrapper[1] = append + moduleWrapper1;
+
+ //console.log(Module.wrapper);
+
+ // Let the show begin
+ testModule.load(testModule.id);
+
+ // This is only necessary if nothing has been required within the module
+ restoreOriginalWrappers();
+
+ return testModule.exports;
+}
+
module.exports = internalRewire; \ No newline at end of file