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

Add module.loaded, and module.require should not be enumerable #4623

Merged
merged 3 commits into from
Oct 7, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 = {|
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be type Module = typeof module to get the type definitions from flow itself (it would have yelled at us for missing loaded, for instance). A bit more work though as it also doesn't like that require is added the way it is in this PR. Can revisit later

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