Skip to content

Commit

Permalink
Add module.loaded, and module.require should not be enumerable (#…
Browse files Browse the repository at this point in the history
…4623)

* Make `module.require` non-enumerable

* Add `module.loaded`

* Tighten type definition of `Module`
  • Loading branch information
SimenB authored and cpojer committed Oct 7, 2017
1 parent 7b0e108 commit 88fec3d
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 7 deletions.
34 changes: 32 additions & 2 deletions packages/jest-runtime/src/__tests__/runtime_require_module.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,37 @@ describe('Runtime requireModule', () => {
expect(exports.isRealModule).toBe(true);
}));

it('provides `module` to modules', () =>
createRuntime(__filename).then(runtime => {
const exports = runtime.requireModule(
runtime.__mockRootPath,
'RegularModule',
);
expect(Object.keys(exports.module)).toEqual([
'children',
'exports',
'filename',
'id',
'loaded',
'parent',
'paths',
]);
}));

it('provides `module.parent` to modules', () =>
createRuntime(__filename).then(runtime => {
const exports = runtime.requireModule(
runtime.__mockRootPath,
'RequireRegularModule',
);
expect(Object.keys(exports.parent)).toEqual([
'children',
'exports',
'filename',
'id',
'children',
'loaded',
'parent',
'paths',
'require',
]);
}));

Expand Down Expand Up @@ -74,6 +91,19 @@ describe('Runtime requireModule', () => {
);
}));

it('provides `module.loaded` to modules', () =>
createRuntime(__filename).then(runtime => {
const exports = runtime.requireModule(
runtime.__mockRootPath,
'RegularModule',
);

// `exports.loaded` is set while the module is loaded, so should be `false`
expect(exports.loaded).toEqual(false);
// After the module is loaded we can query `module.loaded` again, at which point it should be `true`
expect(exports.isLoaded()).toEqual(true);
}));

it('provides `module.filename` to modules', () =>
createRuntime(__filename).then(runtime => {
const exports = runtime.requireModule(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,6 @@ exports.object = {};
exports.parent = module.parent;
exports.paths = module.paths;
exports.setModuleStateValue = setModuleStateValue;
exports.module = module;
exports.loaded = module.loaded;
exports.isLoaded = () => module.loaded;
20 changes: 15 additions & 5 deletions packages/jest-runtime/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@ import {run as cilRun} from './cli';
import {options as cliOptions} from './cli/args';

type Module = {|
children?: Array<any>,
children: Array<Module>,
exports: any,
filename: string,
id: string,
loaded: boolean,
parent?: Module,
paths?: Array<Path>,
require?: Function,
require?: (id: string) => any,
|};

type HasteMapOptions = {|
Expand Down Expand Up @@ -311,10 +312,12 @@ class Runtime {
// We must register the pre-allocated module object first so that any
// circular dependencies that may arise while evaluating the module can
// be satisfied.
const localModule = {
const localModule: Module = {
children: [],
exports: {},
filename: modulePath,
id: modulePath,
loaded: false,
};
moduleRegistry[modulePath] = localModule;
if (path.extname(modulePath) === '.json') {
Expand All @@ -327,6 +330,8 @@ class Runtime {
} else {
this._execModule(localModule, options, moduleRegistry, from);
}

localModule.loaded = true;
}
return moduleRegistry[modulePath].exports;
}
Expand Down Expand Up @@ -381,13 +386,16 @@ class Runtime {
}

if (manualMock) {
const localModule = {
const localModule: Module = {
children: [],
exports: {},
filename: modulePath,
id: modulePath,
loaded: false,
};
this._execModule(localModule, undefined, this._mockRegistry, from);
this._mockRegistry[moduleID] = localModule.exports;
localModule.loaded = true;
} else {
// Look for a real module to generate an automock from
this._mockRegistry[moduleID] = this._generateMock(from, moduleName);
Expand Down Expand Up @@ -508,7 +516,9 @@ class Runtime {
);

localModule.paths = this._resolver.getModulePaths(dirname);
localModule.require = this._createRequireImplementation(filename, options);
Object.defineProperty(localModule, 'require', {
value: this._createRequireImplementation(filename, options),
});

const transformedFile = this._scriptTransformer.transform(
filename,
Expand Down

0 comments on commit 88fec3d

Please sign in to comment.