Skip to content

Commit

Permalink
Merge branch 'master' into pr/origin/127
Browse files Browse the repository at this point in the history
  • Loading branch information
jhnns committed Apr 9, 2018
2 parents 1250667 + b0a2870 commit d124260
Show file tree
Hide file tree
Showing 12 changed files with 1,058 additions and 336 deletions.
1 change: 0 additions & 1 deletion .travis.yml
@@ -1,6 +1,5 @@
language: node_js
node_js:
- "4"
- "6"
- "8"
- "9"
Expand Down
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -5,7 +5,7 @@ rewire
[![](https://img.shields.io/npm/v/rewire.svg)](https://www.npmjs.com/package/rewire)
[![](https://img.shields.io/npm/dm/rewire.svg)](https://www.npmjs.com/package/rewire)
[![Dependency Status](https://david-dm.org/jhnns/rewire.svg)](https://david-dm.org/jhnns/rewire)
[![Build Status](https://travis-ci.org/jhnns/rewire.svg?branch=master)](https://travis-ci.org/rewire/jhnns)
[![Build Status](https://travis-ci.org/jhnns/rewire.svg?branch=master)](https://travis-ci.org/jhnns/rewire)
[![Coverage Status](https://img.shields.io/coveralls/jhnns/rewire.svg)](https://coveralls.io/r/jhnns/rewire?branch=master)

rewire adds a special setter and getter to modules so you can modify their behaviour for better unit testing. You may
Expand Down Expand Up @@ -236,7 +236,7 @@ See [rewire-webpack](https://github.com/jhnns/rewire-webpack)
CoffeeScript
------------

Good news to all caffeine-addicts: rewire works also with [Coffee-Script](http://coffeescript.org/). Note that in this case CoffeeScript needs to be listed in your devDependencies.
Good news to all caffeine-addicts: rewire works also with [Coffee-Script](http://coffeescript.org/). Note that in this case you need to install the `coffeescript` package.

<br />

Expand Down
70 changes: 57 additions & 13 deletions lib/moduleEnv.js
@@ -1,16 +1,48 @@
"use strict";

// TODO: Use https://www.npmjs.com/package/pirates here?

var Module = require("module"),
fs = require("fs"),
babelCore = require("babel-core"),
// Requiring the babel plugin here because otherwise it will be lazy-loaded by Babel during rewire()
transformBlockScoping = require("babel-plugin-transform-es2015-block-scoping"),
eslint = require("eslint"),
coffee;

var moduleWrapper0 = Module.wrapper[0],
moduleWrapper1 = Module.wrapper[1],
originalExtensions = {},
matchCoffeeExt = /\.coffee$/,
linter = new eslint.Linter(),
eslintOptions = {
env: {
es6: true,
},
parserOptions: {
ecmaVersion: 6,
ecmaFeatures: {
globalReturn: true,
jsx: true,
experimentalObjectRestSpread: true
},
},
rules: {
"no-const-assign": 2
}
},
// The following regular expression is used to replace const declarations with let.
// This regex replacement is not 100% safe because transforming JavaScript requires an actual parser.
// However, parsing (e.g. via babel) comes with its own problems because now the parser needs to
// be aware of syntax extensions which might not be supported by the parser, but the underlying
// JavaScript engine. In fact, rewire used to have babel in place here but required an extra
// transform for the object spread operator (check out commit d9a81c0cdacf6995b24d205b4a2068adbd8b34ff
// or see https://github.com/jhnns/rewire/pull/128). It was also notable slower
// (see https://github.com/jhnns/rewire/issues/132).
// There is another issue: replacing const with let is not safe because of their different behavior.
// That's why we also have ESLint in place which tries to identify this error case.
// There is one edge case though: when a new syntax is used *and* a const re-assignment happens,
// rewire would compile happily in this situation but the actual code wouldn't work.
// However, since most projects have a seperate linting step which catches these const re-assignment
// errors anyway, it's probably still a reasonable trade-off.
// Test the regular expresssion at https://regex101.com/r/dvnZPv/2 and also check out testLib/constModule.js.
matchConst = /(^|\s|\}|;)const(\/\*|\s)/gm,
nodeRequire,
currentModule;

Expand Down Expand Up @@ -71,17 +103,29 @@ function restoreExtensions() {
}
}

function isNoConstAssignMessage(message) {
return message.ruleId === "no-const-assign";
}

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

module._compile = function (content, filename) {
content = babelCore.transform(content, {
plugins: [require.resolve("babel-plugin-transform-es2015-block-scoping")],
retainLines: true,
filename: filename,
babelrc: false
}).code;
_compile.call(module, 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();
Expand All @@ -90,7 +134,7 @@ function jsExtension(module, filename) {

function coffeeExtension(module, filename) {
if (!coffee) {
throw new Error("please add 'coffeescript' to your devDependencies");
throw new Error("Cannot rewire module written in CoffeeScript: Please install 'coffeescript' package first.");
}

var content = stripBOM(fs.readFileSync(filename, "utf8"));
Expand Down Expand Up @@ -123,7 +167,7 @@ try {
// Trying to load deprecated package
coffee = require("coffee-script");
} catch (err) {
// We are not able to provide coffee-script support, but that's ok as long as the user doesn't want it.
// We are not able to provide CoffeeScript support, but that's ok as long as the user doesn't want it.
}
}

Expand Down
1 change: 0 additions & 1 deletion lib/rewire.js
@@ -1,6 +1,5 @@
var Module = require("module"),
fs = require("fs"),
path = require("path"),
getImportGlobalsSrc = require("./getImportGlobalsSrc.js"),
getDefinePropertySrc = require("./getDefinePropertySrc.js"),
detectStrictMode = require("./detectStrictMode.js"),
Expand Down

0 comments on commit d124260

Please sign in to comment.