Skip to content

Commit 878014e

Browse files
cpojerfacebook-github-bot-6
authored andcommitted
Simplify module execution.
Summary: Pulled out from #599. Closes #636 Reviewed By: vjeux Differential Revision: D2731701 fb-gh-sync-id: 23fbcc618dc9e0cfb79fb96a8d02302b3276466a
1 parent bea5507 commit 878014e

File tree

3 files changed

+43
-79
lines changed

3 files changed

+43
-79
lines changed

src/HasteModuleLoader/HasteModuleLoader.js

Lines changed: 39 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ const os = require('os');
1818
const path = require('path');
1919
const resolve = require('resolve');
2020
const transform = require('../lib/transform');
21-
const utils = require('../lib/utils');
2221

23-
const COVERAGE_STORAGE_VAR_NAME = '____JEST_COVERAGE_DATA____';
2422
const NODE_PATH =
2523
(process.env.NODE_PATH ? process.env.NODE_PATH.split(path.delimiter) : null);
2624
const IS_PATH_BASED_MODULE_NAME = /^(?:\.\.?\/|\/)/;
@@ -168,52 +166,58 @@ class Loader {
168166
* objects.
169167
*/
170168
_execModule(moduleObj) {
171-
const modulePath = moduleObj.__filename;
172-
let moduleContent = transform(modulePath, this._config);
169+
// If the environment was disposed, prevent this module from
170+
// being executed.
171+
if (!this._environment.global) {
172+
return;
173+
}
174+
175+
const filename = moduleObj.__filename;
176+
let moduleContent = transform(filename, this._config);
177+
let collectorStore;
173178

174-
// Every module, if loaded for jest, should have a parent
175-
// so they don't think they are run standalone
179+
// Every module receives a mock parent so they don't assume they are run
180+
// standalone.
176181
moduleObj.parent = mockParentModule;
177-
moduleObj.require = this.constructBoundRequire(modulePath);
178-
179-
const moduleLocalBindings = {
180-
module: moduleObj,
181-
exports: moduleObj.exports,
182-
require: moduleObj.require,
183-
__dirname: path.dirname(modulePath),
184-
__filename: modulePath,
185-
global: this._environment.global,
186-
jest: this._createRuntimeFor(modulePath),
187-
};
182+
moduleObj.require = this.constructBoundRequire(filename);
188183

189184
const onlyCollectFrom = this._config.collectCoverageOnlyFrom;
190185
const shouldCollectCoverage =
191-
this._config.collectCoverage === true && !onlyCollectFrom
192-
|| (onlyCollectFrom && onlyCollectFrom[modulePath] === true);
186+
(this._config.collectCoverage === true && !onlyCollectFrom) ||
187+
(onlyCollectFrom && onlyCollectFrom[filename] === true);
193188

194189
if (shouldCollectCoverage) {
195-
if (!hasOwnProperty.call(this._coverageCollectors, modulePath)) {
196-
this._coverageCollectors[modulePath] =
197-
new this._CoverageCollector(moduleContent, modulePath);
190+
if (!hasOwnProperty.call(this._coverageCollectors, filename)) {
191+
this._coverageCollectors[filename] =
192+
new this._CoverageCollector(moduleContent, filename);
198193
}
199-
const collector = this._coverageCollectors[modulePath];
200-
moduleLocalBindings[COVERAGE_STORAGE_VAR_NAME] =
201-
collector.getCoverageDataStore();
194+
const collector = this._coverageCollectors[filename];
195+
collectorStore = collector.getCoverageDataStore();
202196
moduleContent =
203-
collector.getInstrumentedSource(COVERAGE_STORAGE_VAR_NAME);
197+
collector.getInstrumentedSource('____JEST_COVERAGE_DATA____');
204198
}
205199

206200
const lastExecutingModulePath = this._currentlyExecutingModulePath;
207-
this._currentlyExecutingModulePath = modulePath;
208-
201+
this._currentlyExecutingModulePath = filename;
209202
const origCurrExecutingManualMock = this._isCurrentlyExecutingManualMock;
210-
this._isCurrentlyExecutingManualMock = modulePath;
211-
212-
utils.runContentWithLocalBindings(
213-
this._environment,
214-
moduleContent,
215-
modulePath,
216-
moduleLocalBindings
203+
this._isCurrentlyExecutingManualMock = filename;
204+
205+
// Use this name for the module wrapper for consistency with node.
206+
const evalResultVariable = 'Object.<anonymous>';
207+
const wrapper = 'this["' + evalResultVariable + '"] = function(module, exports, require, __dirname, __filename, global, jest, ____JEST_COVERAGE_DATA____) {' + moduleContent + '\n};';
208+
this._environment.runSourceText(wrapper, filename);
209+
const wrapperFunc = this._environment.global[evalResultVariable];
210+
delete this._environment.global[evalResultVariable];
211+
wrapperFunc.call(
212+
moduleObj.exports, // module context
213+
moduleObj,
214+
moduleObj.exports,
215+
moduleObj.require,
216+
path.dirname(filename),
217+
filename,
218+
this._environment.global,
219+
this._createRuntimeFor(filename),
220+
collectorStore
217221
);
218222

219223
this._isCurrentlyExecutingManualMock = origCurrExecutingManualMock;

src/environments/__mocks__/JSDOMEnvironment.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ JSDOMEnvironment.mockImplementation(function(config) {
1111
this.global = {
1212
console: {},
1313
mockClearTimers: jest.genMockFn(),
14-
JSON: JSON,
14+
JSON,
1515
};
1616

1717
const globalValues = utils.deepCopy(config.globals);
@@ -21,9 +21,9 @@ JSDOMEnvironment.mockImplementation(function(config) {
2121
});
2222

2323
JSDOMEnvironment.prototype.runSourceText.mockImplementation(
24-
function(codeStr, fileName) {
25-
vm.runInNewContext(codeStr, this.global, {
26-
filename: fileName,
24+
function(sourceText, filename) {
25+
vm.runInNewContext(sourceText, this.global, {
26+
filename,
2727
displayErrors: false,
2828
});
2929
}

src/lib/utils.js

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,6 @@ const DEFAULT_CONFIG_VALUES = {
4545
useStderr: false,
4646
};
4747

48-
// This shows up in the stack trace when a test file throws an unhandled error
49-
// when evaluated. Node's require prints Object.<anonymous> when initializing
50-
// modules, so do the same here solely for visual consistency.
51-
const EVAL_RESULT_VARIABLE = 'Object.<anonymous>';
52-
5348
function _replaceRootDirTags(rootDir, config) {
5449
switch (typeof config) {
5550
case 'object':
@@ -367,40 +362,6 @@ function loadConfigFromPackageJson(filePath) {
367362
});
368363
}
369364

370-
function runContentWithLocalBindings(environment, scriptContent, scriptPath,
371-
bindings) {
372-
const boundIdents = Object.keys(bindings);
373-
try {
374-
const wrapperScript = 'this["' + EVAL_RESULT_VARIABLE + '"] = ' +
375-
'function (' + boundIdents.join(',') + ') {' +
376-
scriptContent +
377-
'\n};';
378-
environment.runSourceText(
379-
wrapperScript,
380-
scriptPath
381-
);
382-
} catch (e) {
383-
e.message = scriptPath + ': ' + e.message;
384-
throw e;
385-
}
386-
387-
try {
388-
const wrapperFunc = environment.global[EVAL_RESULT_VARIABLE];
389-
delete environment.global[EVAL_RESULT_VARIABLE];
390-
391-
const bindingValues = boundIdents.map(function(ident) {
392-
return bindings[ident];
393-
});
394-
395-
// Node modules are executed with the `exports` as context.
396-
// If not a node module then this should be undefined.
397-
wrapperFunc.apply(bindings.exports, bindingValues);
398-
} catch (e) {
399-
e.message = scriptPath + ': ' + e.message;
400-
throw e;
401-
}
402-
}
403-
404365
/**
405366
* Given a test result, return a human readable string representing the
406367
* failures.
@@ -503,5 +464,4 @@ exports.getLinePercentCoverageFromCoverageInfo =
503464
exports.loadConfigFromFile = loadConfigFromFile;
504465
exports.loadConfigFromPackageJson = loadConfigFromPackageJson;
505466
exports.normalizeConfig = normalizeConfig;
506-
exports.runContentWithLocalBindings = runContentWithLocalBindings;
507467
exports.formatFailureMessage = formatFailureMessage;

0 commit comments

Comments
 (0)