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:
Diffstat (limited to 'lib')
-rw-r--r--lib/getLeakingSrc.js20
-rw-r--r--lib/getMonkeyPatchSrc.js33
-rw-r--r--lib/index.js13
-rw-r--r--lib/trick.js64
4 files changed, 130 insertions, 0 deletions
diff --git a/lib/getLeakingSrc.js b/lib/getLeakingSrc.js
new file mode 100644
index 0000000..c827411
--- /dev/null
+++ b/lib/getLeakingSrc.js
@@ -0,0 +1,20 @@
+"use strict"; // run code in ES5 strict mode
+
+function getLeakingSrc(leaks) {
+ var src = "exports.__ = {",
+ varName,
+ i;
+
+ for (i = 0; i < leaks.length; i++) {
+ varName = leaks[i];
+ src += (varName + ":" + varName + ",");
+ }
+ if (i > 0) {
+ src = src.slice(0, -1); // trim last comma
+ }
+ src += "};";
+
+ return src;
+}
+
+module.exports = getLeakingSrc;
diff --git a/lib/getMonkeyPatchSrc.js b/lib/getMonkeyPatchSrc.js
new file mode 100644
index 0000000..408b6ee
--- /dev/null
+++ b/lib/getMonkeyPatchSrc.js
@@ -0,0 +1,33 @@
+"use strict"; // run code in ES5 strict mode
+
+var toSrc = require("toSrc");
+
+function getMonkeyPatchSrc(obj) {
+ function walkObj(obj, level) {
+ var key,
+ value,
+ src = "";
+
+ for (key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ value = obj[key];
+ if (typeof value === "object" && Array.isArray(value) === false) {
+ src += key + ".";
+ src += walkObj(value, level + 1);
+ } else {
+ if (level === 0) {
+ src += "var "; // in the top level, we need a var statement to override variables
+ }
+ src += key + "=" + toSrc(value, 9999) + ";";
+ }
+ }
+ }
+
+
+ return src;
+ }
+
+ return walkObj(obj, 0);
+}
+
+module.exports = getMonkeyPatchSrc; \ No newline at end of file
diff --git a/lib/index.js b/lib/index.js
new file mode 100644
index 0000000..f8f57ca
--- /dev/null
+++ b/lib/index.js
@@ -0,0 +1,13 @@
+"use strict"; // run code in ES5 strict mode
+
+var trick = require("./trick.js");
+
+module.exports = function (request, mocks, injections, leaks, cache) {
+ delete require.cache[__filename]; // deleting self from module cache so the parent module is always up to date
+
+ if (cache === undefined) {
+ cache = true;
+ }
+
+ return trick(module.parent, request, mocks, injections, leaks, cache);
+}; \ No newline at end of file
diff --git a/lib/trick.js b/lib/trick.js
new file mode 100644
index 0000000..36644be
--- /dev/null
+++ b/lib/trick.js
@@ -0,0 +1,64 @@
+"use strict"; // run code in ES5 strict mode
+
+var Module = require("module"),
+ nodeWrapper0 = Module.wrapper[0], // caching original wrapper
+ nodeWrapper1 = Module.wrapper[1],
+ getLeakingSrc = require("./getLeakingSrc.js"),
+ getMonkeyPatchSrc = require("./getMonkeyPatchSrc.js");
+
+function restoreOriginalWrappers() {
+ Module.wrapper[0] = nodeWrapper0;
+ Module.wrapper[1] = nodeWrapper1;
+}
+
+function trick(parentModule, filename, mocks, injections, leaks, cache) {
+ var testModule,
+ nodeRequire;
+
+ function requireTrick(path) {
+ restoreOriginalWrappers(); // we need to restore the wrappers now so we don't influence other modules
+
+ if (mocks && mocks.hasOwnProperty(path)) {
+ return mocks[path];
+ } else {
+ return nodeRequire.call(testModule, path); // node's require only works when "this" points to the module
+ }
+ }
+
+ // Checking params
+ if (typeof filename !== "string") {
+ throw new TypeError("Filename must be a string");
+ }
+
+ // Init vars
+ filename = Module._resolveFilename(filename, parentModule); // resolve full filename relative to the parent module
+ testModule = new Module(filename, parentModule);
+ nodeRequire = testModule.require; // caching original node require
+
+ // Prepare module for injection
+ if (typeof injections === "object") {
+ Module.wrapper[0] = nodeWrapper0 + getMonkeyPatchSrc(injections);
+ } else if (typeof injections === "string") {
+ Module.wrapper[0] = nodeWrapper0 + injections;
+ }
+
+ // Prepare module for leaking private vars
+ if (Array.isArray(leaks)) {
+ Module.wrapper[1] = getLeakingSrc(leaks) + nodeWrapper1;
+ }
+
+ // Mocking module.require-function
+ testModule.require = requireTrick;
+ // Loading module
+ testModule.load(testModule.id);
+
+ if (cache) {
+ require.cache[filename] = testModule;
+ }
+
+ restoreOriginalWrappers(); // this is only necessary if nothing has been required within the module
+
+ return testModule.exports;
+}
+
+module.exports = trick; \ No newline at end of file