Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error when different file than rewired gets loaded #149

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
84 changes: 47 additions & 37 deletions lib/moduleEnv.js
Expand Up @@ -51,7 +51,7 @@ function load(targetModule) {
targetModule.require = requireProxy;
currentModule = targetModule;

registerExtensions();
registerExtensions(targetModule.id);
targetModule.load(targetModule.id);

// This is only necessary if nothing has been required within the module
Expand Down Expand Up @@ -80,7 +80,7 @@ function requireProxy(path) {
return nodeRequire.call(currentModule, path); // node's require only works when "this" points to the module
}

function registerExtensions() {
function registerExtensions(targetFilename) {
var originalJsExtension = require.extensions[".js"];
var originalCoffeeExtension = require.extensions[".coffee"];

Expand All @@ -90,8 +90,8 @@ function registerExtensions() {
if (originalCoffeeExtension) {
originalExtensions.coffee = originalCoffeeExtension;
}
require.extensions[".js"] = jsExtension;
require.extensions[".coffee"] = coffeeExtension;
require.extensions[".js"] = jsExtension(targetFilename);
require.extensions[".coffee"] = coffeeExtension(targetFilename);
}

function restoreExtensions() {
Expand All @@ -107,44 +107,54 @@ function isNoConstAssignMessage(message) {
return message.ruleId === "no-const-assign";
}

function jsExtension(module, filename) {
var _compile = module._compile;

module._compile = function (content, filename) {
var noConstAssignMessage = linter.verify(content, eslintOptions).find(isNoConstAssignMessage);
var line;
var column;

if (noConstAssignMessage !== undefined) {
line = noConstAssignMessage.line;
column = noConstAssignMessage.column;
throw new TypeError(`Assignment to constant variable at ${ filename }:${ line }:${ column }`);
function jsExtension(targetFilename) {
return function (module, filename) {
if (targetFilename !== filename) {
throw new Error(`Required module ${filename} rather than expected ${targetFilename}`)
}

_compile.call(
module,
content.replace(matchConst, "$1let $2"), // replace const with let, while maintaining the column width
filename
);
};

restoreExtensions();
originalExtensions.js(module, filename);
var _compile = module._compile;

module._compile = function (content, filename) {
var noConstAssignMessage = linter.verify(content, eslintOptions).find(isNoConstAssignMessage);
var line;
var column;

if (noConstAssignMessage !== undefined) {
line = noConstAssignMessage.line;
column = noConstAssignMessage.column;
throw new TypeError(`Assignment to constant variable at ${ filename }:${ line }:${ column }`);
}

_compile.call(
module,
content.replace(matchConst, "$1let $2"), // replace const with let, while maintaining the column width
filename
);
};

restoreExtensions();
originalExtensions.js(module, filename);
}
}

function coffeeExtension(module, filename) {
if (!coffee) {
throw new Error("Cannot rewire module written in CoffeeScript: Please install 'coffeescript' package first.");
}
function coffeeExtension(targetFilename) {
return function (module, filename) {
if (targetFilename !== filename) {
throw new Error(`Required module ${filename} rather than expected ${targetFilename}`)
}
if (!coffee) {
throw new Error("Cannot rewire module written in CoffeeScript: Please install 'coffeescript' package first.");
}

var content = stripBOM(fs.readFileSync(filename, "utf8"));
var content = stripBOM(fs.readFileSync(filename, "utf8"));

restoreExtensions();
content = coffee.compile(content, {
filename: filename,
bare: true
});
module._compile(content, filename);
restoreExtensions();
content = coffee.compile(content, {
filename: filename,
bare: true
});
module._compile(content, filename);
}
}

/**
Expand Down
21 changes: 21 additions & 0 deletions test/rewire.test.js
Expand Up @@ -16,7 +16,9 @@ describe("rewire", function () {
fs.renameSync(fakeNodeModules, path.resolve(__dirname, "../testLib/node_modules"));
}
});

require("../testLib/sharedTestCases.js")();

it("should also work with CoffeeScript", function () {
var coffeeModule;

Expand All @@ -29,4 +31,23 @@ describe("rewire", function () {
});
expect(coffeeModule.readFileSync()).to.be("It works!");
});

it("should work with file types without loaders", function () {
var jsxModule;

rewire = require("../");
jsxModule = rewire("../testLib/module.jsx");
jsxModule.__set__("testModuleB", "Different Thing");
expect(jsxModule.testModuleB()).to.be("Different Thing");

});

it("should NOT work with file types which do have loaders", function () {
var tsModule;
require.extensions['.ts'] = require.extensions['.js'];

rewire = require("../");
tsModule = rewire.bind(null, "../testLib/module.ts");
expect(tsModule).to.throwException(/rather than expected/);
});
});
5 changes: 5 additions & 0 deletions testLib/module.jsx
@@ -0,0 +1,5 @@
var testModuleB = require("./moduleB");

exports.testModuleB = function() {
return testModuleB;
};
5 changes: 5 additions & 0 deletions testLib/module.ts
@@ -0,0 +1,5 @@
const testModuleB = require("./moduleC.js");

exports.testModuleB = function() {
return testModuleB;
};
137 changes: 137 additions & 0 deletions testLib/moduleC.js
@@ -0,0 +1,137 @@
"use strict"; // run code in ES5 strict mode

var someOtherModule = require("./someOtherModule.js"),
myNumber = 0, // copy by value
myObj = {}, // copy by reference
env = "bla",
fs;

// We need getters and setters for private vars to check if our injected setters and getters actual work
function setMyNumber(newNumber) {
myNumber = newNumber;
}

function getMyNumber() {
return myNumber;
}

function setMyObj(newObj) {
myObj = newObj;
}

function getMyObj() {
return myObj;
}

function readFileSync() {
fs.readFileSync("bla.txt", "utf8");
}

function checkSomeGlobals() {
var isLowerIE,
typeOfGlobalFunc;

if (typeof navigator !== "undefined") {
isLowerIE = /MSIE [6-8]\.[0-9]/g.test(navigator.userAgent);
}
if (isLowerIE) {
typeOfGlobalFunc = "object";
} else {
typeOfGlobalFunc = "function";
}

if (typeof global !== "object") {
throw new ReferenceError("global is not an object");
}
if (typeof console !== "object") {
throw new ReferenceError("console is not an object");
}
if (typeof require !== "function") {
throw new ReferenceError("require is not a function");
}
if (typeof module !== "object") {
throw new ReferenceError("module is not an object");
}
if (typeof exports !== "object") {
throw new ReferenceError("exports is not an object");
}
if (module.exports === exports) {
throw new Error("module.exports === exports returns true");
}
if (typeof __dirname !== "string") {
throw new ReferenceError("__dirname is not a string");
}
if (typeof __filename !== "string") {
throw new ReferenceError("__filename is not a string");
}
if (typeof setTimeout !== typeOfGlobalFunc) {
throw new ReferenceError("setTimeout is not a function");
}
if (typeof clearTimeout !== typeOfGlobalFunc) {
throw new ReferenceError("clearTimeout is not a function");
}
if (typeof setInterval !== typeOfGlobalFunc) {
throw new ReferenceError("setInterval is not a function");
}
if (typeof clearInterval !== typeOfGlobalFunc) {
throw new ReferenceError("clearInterval is not a function");
}
if (typeof Error !== "function") {
throw new ReferenceError("Error is not a function");
}
if (typeof parseFloat !== "function") {
throw new ReferenceError("parseFloat is not a function");
}
if (typeof parseInt !== "function") {
throw new ReferenceError("parseInt is not a function");
}
if (typeof window === "undefined") {
if (typeof process !== "object") {
throw new ReferenceError("process is not an object");
}
if (typeof Buffer !== "function") {
throw new ReferenceError("Buffer is not a function");
}
} else {
if (typeof encodeURIComponent !== "function") {
throw new ReferenceError("encodeURIComponent is not a function");
}
if (typeof decodeURIComponent !== "function") {
throw new ReferenceError("decodeURIComponent is not a function");
}
if (typeof document !== "object") {
throw new ReferenceError("document is not an object");
}
}
}

function getConsole() {
return console;
}

function getFilename() {
return __filename;
}

function getBuffer() {
return Buffer;
}

function getDocument() {
return document;
}

// different styles of exports in moduleA.js and moduleB.js
module.exports = {
setMyNumber: setMyNumber,
getMyNumber: getMyNumber,
setMyObj: setMyObj,
getMyObj: getMyObj,
readFileSync: readFileSync,
checkSomeGlobals: checkSomeGlobals,
getConsole: getConsole,
getFilename: getFilename,
getBuffer: getBuffer,
getDocument: getDocument,
someOtherModule: someOtherModule
};