diff --git a/CHANGELOG.md b/CHANGELOG.md index 76970f89d6ef..b5db60d539e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,9 @@ - `[jest-core]` Pass project config to `globalSetup`/`globalTeardown` function as second argument ([#12440](https://github.com/facebook/jest/pull/12440)) - `[jest-environment-jsdom]` [**BREAKING**] Upgrade jsdom to 19.0.0 ([#12290](https://github.com/facebook/jest/pull/12290)) - `[jest-environment-jsdom]` [**BREAKING**] Add default `browser` condition to `exportConditions` for `jsdom` environment ([#11924](https://github.com/facebook/jest/pull/11924)) +- `[jest-environment-jsdom]` [**BREAKING**] Pass global config to Jest environment constructor for `jsdom` environment ([#12461](https://github.com/facebook/jest/pull/12461)) - `[jest-environment-node]` [**BREAKING**] Add default `node` and `node-addon` conditions to `exportConditions` for `node` environment ([#11924](https://github.com/facebook/jest/pull/11924)) +- `[jest-environment-node]` [**BREAKING**] Pass global config to Jest environment constructor for `node` environment ([#12461](https://github.com/facebook/jest/pull/12461)) - `[@jest/expect]` New module which extends `expect` with `jest-snapshot` matchers ([#12404](https://github.com/facebook/jest/pull/12404), [#12410](https://github.com/facebook/jest/pull/12410), [#12418](https://github.com/facebook/jest/pull/12418)) - `[@jest/expect-utils]` New module exporting utils for `expect` ([#12323](https://github.com/facebook/jest/pull/12323)) - `[jest-mock]` Improve `isMockFunction` to infer types of passed function ([#12442](https://github.com/facebook/jest/pull/12442)) diff --git a/docs/Configuration.md b/docs/Configuration.md index 7b2e51385fff..fafdbb34bbfc 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -1090,7 +1090,7 @@ test('use jsdom in this test file', () => { }); ``` -You can create your own module that will be used for setting up the test environment. The module must export a class with `setup`, `teardown` and `getVmContext` methods. You can also pass variables from this module to your test suites by assigning them to `this.global` object – this will make them available in your test suites as global variables. +You can create your own module that will be used for setting up the test environment. The module must export a class with `setup`, `teardown` and `getVmContext` methods. You can also pass variables from this module to your test suites by assigning them to `this.global` object – this will make them available in your test suites as global variables. The constructor is passed [global config](https://github.com/facebook/jest/blob/491e7cb0f2daa8263caccc72d48bdce7ba759b11/packages/jest-types/src/Config.ts#L284) and [project config](https://github.com/facebook/jest/blob/491e7cb0f2daa8263caccc72d48bdce7ba759b11/packages/jest-types/src/Config.ts#L349) as its first argument, and [`testEnvironmentContext`](https://github.com/facebook/jest/blob/491e7cb0f2daa8263caccc72d48bdce7ba759b11/packages/jest-environment/src/index.ts#L13) as its second. The class may optionally expose an asynchronous `handleTestEvent` method to bind to events fired by [`jest-circus`](https://github.com/facebook/jest/tree/main/packages/jest-circus). Normally, `jest-circus` test runner would pause until a promise returned from `handleTestEvent` gets fulfilled, **except for the next events**: `start_describe_definition`, `finish_describe_definition`, `add_hook`, `add_test` or `error` (for the up-to-date list you can look at [SyncEvent type in the types definitions](https://github.com/facebook/jest/tree/main/packages/jest-types/src/Circus.ts)). That is caused by backward compatibility reasons and `process.on('unhandledRejection', callback)` signature, but that usually should not be a problem for most of the use cases. @@ -1115,6 +1115,8 @@ const NodeEnvironment = require('jest-environment-node').default; class CustomEnvironment extends NodeEnvironment { constructor(config, context) { super(config, context); + console.log(config.globalConfig); + console.log(config.projectConfig); this.testPath = context.testPath; this.docblockPragmas = context.docblockPragmas; } diff --git a/e2e/test-environment/EsmDefaultEnvironment.js b/e2e/test-environment/EsmDefaultEnvironment.js index 696b9722995e..1526a1b8c042 100644 --- a/e2e/test-environment/EsmDefaultEnvironment.js +++ b/e2e/test-environment/EsmDefaultEnvironment.js @@ -14,6 +14,8 @@ class Env extends NodeEnvironment { constructor(config, options) { super(config, options); this.global.property = 'value'; + this.global.var1 = config.globalConfig.watch; + this.global.var2 = config.projectConfig.cache; } } diff --git a/e2e/test-environment/__tests__/esmDefault.test.js b/e2e/test-environment/__tests__/esmDefault.test.js index a978d0b9e1f6..368f119d0807 100644 --- a/e2e/test-environment/__tests__/esmDefault.test.js +++ b/e2e/test-environment/__tests__/esmDefault.test.js @@ -10,4 +10,6 @@ test('access env', () => { expect(property).toBe('value'); // eslint-disable-line no-undef + expect(var1).toBe(false); // eslint-disable-line no-undef + expect(var2).toBe(true); // eslint-disable-line no-undef }); diff --git a/packages/jest-environment-jsdom/src/__tests__/jsdom_environment.test.ts b/packages/jest-environment-jsdom/src/__tests__/jsdom_environment.test.ts index 5bb9238c3cd9..dfc48b6ab017 100644 --- a/packages/jest-environment-jsdom/src/__tests__/jsdom_environment.test.ts +++ b/packages/jest-environment-jsdom/src/__tests__/jsdom_environment.test.ts @@ -5,12 +5,15 @@ * LICENSE file in the root directory of this source tree. */ -import {makeProjectConfig} from '@jest/test-utils'; +import {makeGlobalConfig, makeProjectConfig} from '@jest/test-utils'; import JSDomEnvironment from '../'; describe('JSDomEnvironment', () => { it('should configure setTimeout/setInterval to use the browser api', () => { - const env = new JSDomEnvironment(makeProjectConfig()); + const env = new JSDomEnvironment({ + globalConfig: makeGlobalConfig(), + projectConfig: makeProjectConfig(), + }); env.fakeTimers!.useFakeTimers(); @@ -23,19 +26,23 @@ describe('JSDomEnvironment', () => { }); it('has modern fake timers implementation', () => { - const env = new JSDomEnvironment(makeProjectConfig()); + const env = new JSDomEnvironment({ + globalConfig: makeGlobalConfig(), + projectConfig: makeProjectConfig(), + }); expect(env.fakeTimersModern).toBeDefined(); }); it('should respect userAgent option', () => { - const env = new JSDomEnvironment( - makeProjectConfig({ + const env = new JSDomEnvironment({ + globalConfig: makeGlobalConfig(), + projectConfig: makeProjectConfig({ testEnvironmentOptions: { userAgent: 'foo', }, }), - ); + }); expect(env.dom.window.navigator.userAgent).toEqual('foo'); }); @@ -53,7 +60,10 @@ describe('JSDomEnvironment', () => { * will be called, so please make sure the global.document is still available at this point. */ it('should not set the global.document to null too early', () => { - const env = new JSDomEnvironment(makeProjectConfig()); + const env = new JSDomEnvironment({ + globalConfig: makeGlobalConfig(), + projectConfig: makeProjectConfig(), + }); const originalCloseFn = env.global.close.bind(env.global); env.global.close = () => { diff --git a/packages/jest-environment-jsdom/src/index.ts b/packages/jest-environment-jsdom/src/index.ts index bd860659e71e..27f0c6dde71d 100644 --- a/packages/jest-environment-jsdom/src/index.ts +++ b/packages/jest-environment-jsdom/src/index.ts @@ -7,9 +7,13 @@ import type {Context} from 'vm'; import {JSDOM, ResourceLoader, VirtualConsole} from 'jsdom'; -import type {EnvironmentContext, JestEnvironment} from '@jest/environment'; +import type { + EnvironmentContext, + JestEnvironment, + JestEnvironmentConfig, +} from '@jest/environment'; import {LegacyFakeTimers, ModernFakeTimers} from '@jest/fake-timers'; -import type {Config, Global} from '@jest/types'; +import type {Global} from '@jest/types'; import {ModuleMocker} from 'jest-mock'; import {installCommonGlobals} from 'jest-util'; @@ -30,25 +34,26 @@ export default class JSDOMEnvironment implements JestEnvironment { private errorEventListener: ((event: Event & {error: Error}) => void) | null; moduleMocker: ModuleMocker | null; - constructor(config: Config.ProjectConfig, options?: EnvironmentContext) { + constructor(config: JestEnvironmentConfig, options?: EnvironmentContext) { + const {projectConfig} = config; this.dom = new JSDOM( - typeof config.testEnvironmentOptions.html === 'string' - ? config.testEnvironmentOptions.html + typeof projectConfig.testEnvironmentOptions.html === 'string' + ? projectConfig.testEnvironmentOptions.html : '', { pretendToBeVisual: true, resources: - typeof config.testEnvironmentOptions.userAgent === 'string' + typeof projectConfig.testEnvironmentOptions.userAgent === 'string' ? new ResourceLoader({ - userAgent: config.testEnvironmentOptions.userAgent, + userAgent: projectConfig.testEnvironmentOptions.userAgent, }) : undefined, runScripts: 'dangerously', - url: config.testURL, + url: projectConfig.testURL, virtualConsole: new VirtualConsole().sendTo( options?.console || console, ), - ...config.testEnvironmentOptions, + ...projectConfig.testEnvironmentOptions, }, ); const global = (this.global = this.dom.window.document @@ -64,7 +69,7 @@ export default class JSDOMEnvironment implements JestEnvironment { // Node's error-message stack size is limited at 10, but it's pretty useful // to see more than that when a test fails. this.global.Error.stackTraceLimit = 100; - installCommonGlobals(global as any, config.globals); + installCommonGlobals(global as any, projectConfig.globals); // TODO: remove this ASAP, but it currently causes tests to run really slow global.Buffer = Buffer; @@ -107,14 +112,14 @@ export default class JSDOMEnvironment implements JestEnvironment { }; this.fakeTimers = new LegacyFakeTimers({ - config, + config: projectConfig, global: global as unknown as typeof globalThis, moduleMocker: this.moduleMocker, timerConfig, }); this.fakeTimersModern = new ModernFakeTimers({ - config, + config: projectConfig, global: global as unknown as typeof globalThis, }); } diff --git a/packages/jest-environment-node/src/__tests__/node_environment.test.ts b/packages/jest-environment-node/src/__tests__/node_environment.test.ts index ffe4e7c3e5ba..9426ce475438 100644 --- a/packages/jest-environment-node/src/__tests__/node_environment.test.ts +++ b/packages/jest-environment-node/src/__tests__/node_environment.test.ts @@ -5,31 +5,44 @@ * LICENSE file in the root directory of this source tree. */ -import {makeProjectConfig} from '@jest/test-utils'; +import {makeGlobalConfig, makeProjectConfig} from '@jest/test-utils'; import NodeEnvironment from '../'; describe('NodeEnvironment', () => { it('uses a copy of the process object', () => { - const env1 = new NodeEnvironment(makeProjectConfig()); - const env2 = new NodeEnvironment(makeProjectConfig()); + const testEnvConfig = { + globalConfig: makeGlobalConfig(), + projectConfig: makeProjectConfig(), + }; + const env1 = new NodeEnvironment(testEnvConfig); + const env2 = new NodeEnvironment(testEnvConfig); expect(env1.global.process).not.toBe(env2.global.process); }); it('exposes process.on', () => { - const env1 = new NodeEnvironment(makeProjectConfig()); + const env1 = new NodeEnvironment({ + globalConfig: makeGlobalConfig(), + projectConfig: makeProjectConfig(), + }); expect(env1.global.process.on).not.toBe(null); }); it('exposes global.global', () => { - const env1 = new NodeEnvironment(makeProjectConfig()); + const env1 = new NodeEnvironment({ + globalConfig: makeGlobalConfig(), + projectConfig: makeProjectConfig(), + }); expect(env1.global.global).toBe(env1.global); }); it('should configure setTimeout/setInterval to use the node api', () => { - const env1 = new NodeEnvironment(makeProjectConfig()); + const env1 = new NodeEnvironment({ + globalConfig: makeGlobalConfig(), + projectConfig: makeProjectConfig(), + }); env1.fakeTimers!.useFakeTimers(); @@ -44,7 +57,10 @@ describe('NodeEnvironment', () => { }); it('has modern fake timers implementation', () => { - const env = new NodeEnvironment(makeProjectConfig()); + const env = new NodeEnvironment({ + globalConfig: makeGlobalConfig(), + projectConfig: makeProjectConfig(), + }); expect(env.fakeTimersModern).toBeDefined(); }); diff --git a/packages/jest-environment-node/src/index.ts b/packages/jest-environment-node/src/index.ts index 7689502a1ef1..21382dacd404 100644 --- a/packages/jest-environment-node/src/index.ts +++ b/packages/jest-environment-node/src/index.ts @@ -6,9 +6,9 @@ */ import {Context, createContext, runInContext} from 'vm'; -import type {JestEnvironment} from '@jest/environment'; +import type {JestEnvironment, JestEnvironmentConfig} from '@jest/environment'; import {LegacyFakeTimers, ModernFakeTimers} from '@jest/fake-timers'; -import type {Config, Global} from '@jest/types'; +import type {Global} from '@jest/types'; import {ModuleMocker} from 'jest-mock'; import {installCommonGlobals} from 'jest-util'; @@ -25,11 +25,12 @@ export default class NodeEnvironment implements JestEnvironment { global: Global.Global; moduleMocker: ModuleMocker | null; - constructor(config: Config.ProjectConfig) { + constructor(config: JestEnvironmentConfig) { + const {projectConfig} = config; this.context = createContext(); const global = (this.global = runInContext( 'this', - Object.assign(this.context, config.testEnvironmentOptions), + Object.assign(this.context, projectConfig.testEnvironmentOptions), )); global.global = global; global.clearInterval = clearInterval; @@ -81,7 +82,7 @@ export default class NodeEnvironment implements JestEnvironment { global.atob = atob; global.btoa = btoa; } - installCommonGlobals(global, config.globals); + installCommonGlobals(global, projectConfig.globals); this.moduleMocker = new ModuleMocker(global); @@ -104,13 +105,16 @@ export default class NodeEnvironment implements JestEnvironment { }; this.fakeTimers = new LegacyFakeTimers({ - config, + config: projectConfig, global, moduleMocker: this.moduleMocker, timerConfig, }); - this.fakeTimersModern = new ModernFakeTimers({config, global}); + this.fakeTimersModern = new ModernFakeTimers({ + config: projectConfig, + global, + }); } async setup(): Promise {} diff --git a/packages/jest-environment/src/index.ts b/packages/jest-environment/src/index.ts index 01695b50fb5a..1cfd2f47f473 100644 --- a/packages/jest-environment/src/index.ts +++ b/packages/jest-environment/src/index.ts @@ -28,8 +28,13 @@ export type ModuleWrapper = ( ...extraGlobals: Array ) => unknown; +export interface JestEnvironmentConfig { + projectConfig: Config.ProjectConfig; + globalConfig: Config.GlobalConfig; +} + export declare class JestEnvironment { - constructor(config: Config.ProjectConfig, context?: EnvironmentContext); + constructor(config: JestEnvironmentConfig, context?: EnvironmentContext); global: Global.Global; fakeTimers: LegacyFakeTimers | null; fakeTimersModern: ModernFakeTimers | null; diff --git a/packages/jest-repl/src/cli/runtime-cli.ts b/packages/jest-repl/src/cli/runtime-cli.ts index a90c47f2982e..909a30a067cf 100644 --- a/packages/jest-repl/src/cli/runtime-cli.ts +++ b/packages/jest-repl/src/cli/runtime-cli.ts @@ -63,22 +63,27 @@ export async function run( const options = await readConfig(argv, root); const globalConfig = options.globalConfig; // Always disable automocking in scripts. - const config: Config.ProjectConfig = { + const projectConfig: Config.ProjectConfig = { ...options.projectConfig, automock: false, }; try { - const hasteMap = await Runtime.createContext(config, { + const hasteMap = await Runtime.createContext(projectConfig, { maxWorkers: Math.max(cpus().length - 1, 1), watchman: globalConfig.watchman, }); - const transformer = await createScriptTransformer(config); + const transformer = await createScriptTransformer(projectConfig); const Environment: typeof JestEnvironment = - await transformer.requireAndTranspileModule(config.testEnvironment); + await transformer.requireAndTranspileModule( + projectConfig.testEnvironment, + ); - const environment = new Environment(config); + const environment = new Environment({ + globalConfig, + projectConfig, + }); setGlobal( environment.global as unknown as typeof globalThis, 'console', @@ -87,7 +92,7 @@ export async function run( setGlobal( environment.global as unknown as typeof globalThis, 'jestProjectConfig', - config, + projectConfig, ); setGlobal( environment.global as unknown as typeof globalThis, @@ -96,7 +101,7 @@ export async function run( ); const runtime = new Runtime( - config, + projectConfig, environment, hasteMap.resolver, transformer, @@ -112,7 +117,7 @@ export async function run( filePath, ); - for (const path of config.setupFiles) { + for (const path of projectConfig.setupFiles) { const esm = runtime.unstable_shouldLoadAsEsm(path); if (esm) { diff --git a/packages/jest-runner/src/runTest.ts b/packages/jest-runner/src/runTest.ts index e734262d81cb..83c0c7695571 100644 --- a/packages/jest-runner/src/runTest.ts +++ b/packages/jest-runner/src/runTest.ts @@ -77,7 +77,7 @@ function freezeConsole( async function runTestInternal( path: string, globalConfig: Config.GlobalConfig, - config: Config.ProjectConfig, + projectConfig: Config.ProjectConfig, resolver: Resolver, context?: TestRunnerContext, sendMessageToJest?: TestFileEvent, @@ -86,7 +86,7 @@ async function runTestInternal( const docblockPragmas = docblock.parse(docblock.extract(testSource)); const customEnvironment = docblockPragmas['jest-environment']; - let testEnvironment = config.testEnvironment; + let testEnvironment = projectConfig.testEnvironment; if (customEnvironment) { if (Array.isArray(customEnvironment)) { @@ -97,14 +97,14 @@ async function runTestInternal( ); } testEnvironment = resolveTestEnvironment({ - ...config, + ...projectConfig, requireResolveFunction: require.resolve, testEnvironment: customEnvironment, }); } const cacheFS = new Map([[path, testSource]]); - const transformer = await createScriptTransformer(config, cacheFS); + const transformer = await createScriptTransformer(projectConfig, cacheFS); const TestEnvironment: typeof JestEnvironment = await transformer.requireAndTranspileModule(testEnvironment); @@ -112,11 +112,11 @@ async function runTestInternal( await transformer.requireAndTranspileModule( process.env.JEST_JASMINE === '1' ? require.resolve('jest-jasmine2') - : config.testRunner, + : projectConfig.testRunner, ); const Runtime: typeof RuntimeClass = interopRequireDefault( - config.moduleLoader - ? require(config.moduleLoader) + projectConfig.moduleLoader + ? require(projectConfig.moduleLoader) : require('jest-runtime'), ).default; @@ -125,7 +125,7 @@ async function runTestInternal( getConsoleOutput( // 4 = the console call is buried 4 stack frames deep BufferedConsole.write([], type, message, 4), - config, + projectConfig, globalConfig, ); @@ -139,11 +139,17 @@ async function runTestInternal( testConsole = new BufferedConsole(); } - const environment = new TestEnvironment(config, { - console: testConsole, - docblockPragmas, - testPath: path, - }); + const environment = new TestEnvironment( + { + globalConfig, + projectConfig, + }, + { + console: testConsole, + docblockPragmas, + testPath: path, + }, + ); if (typeof environment.getVmContext !== 'function') { console.error( @@ -152,7 +158,7 @@ async function runTestInternal( process.exit(1); } - const leakDetector = config.detectLeaks + const leakDetector = projectConfig.detectLeaks ? new LeakDetector(environment) : null; @@ -163,7 +169,7 @@ async function runTestInternal( ); const runtime = new Runtime( - config, + projectConfig, environment, resolver, transformer, @@ -182,7 +188,7 @@ async function runTestInternal( const start = Date.now(); - for (const path of config.setupFiles) { + for (const path of projectConfig.setupFiles) { const esm = runtime.unstable_shouldLoadAsEsm(path); if (esm) { @@ -236,7 +242,7 @@ async function runTestInternal( const formattedError = formatExecError( error, - config, + projectConfig, {noStackTrace: false}, undefined, true, @@ -264,7 +270,7 @@ async function runTestInternal( } result = await testFramework( globalConfig, - config, + projectConfig, environment, runtime, path, @@ -281,7 +287,7 @@ async function runTestInternal( } } - freezeConsole(testConsole, config); + freezeConsole(testConsole, projectConfig); const testCount = result.numPassingTests + @@ -294,13 +300,13 @@ async function runTestInternal( result.perfStats = { end, runtime: testRuntime, - slow: testRuntime / 1000 > config.slowTestThreshold, + slow: testRuntime / 1000 > projectConfig.slowTestThreshold, start, }; result.testFilePath = path; result.console = testConsole.getBuffer(); result.skipped = testCount === result.numPendingTests; - result.displayName = config.displayName; + result.displayName = projectConfig.displayName; const coverage = runtime.getAllCoverageInfoCopy(); if (coverage) { diff --git a/packages/jest-runtime/src/__mocks__/createRuntime.js b/packages/jest-runtime/src/__mocks__/createRuntime.js index 771204ea03da..17d1d2c9f93b 100644 --- a/packages/jest-runtime/src/__mocks__/createRuntime.js +++ b/packages/jest-runtime/src/__mocks__/createRuntime.js @@ -7,7 +7,7 @@ import {tmpdir} from 'os'; import path from 'path'; -import {makeProjectConfig} from '@jest/test-utils'; +import {makeGlobalConfig, makeProjectConfig} from '@jest/test-utils'; import {createScriptTransformer} from '@jest/transform'; import NodeEnvironment from 'jest-environment-node'; import {tryRealpath} from 'jest-util'; @@ -48,13 +48,13 @@ const setupTransform = (config, rootDir) => { return [['^.+\\.[jt]sx?$', require.resolve('babel-jest')]]; }; -module.exports = async function createRuntime(filename, config) { +module.exports = async function createRuntime(filename, projectConfig) { const rootDir = path.resolve(path.dirname(filename), 'test_root'); - const moduleNameMapper = setupModuleNameMapper(config, rootDir); - const transform = setupTransform(config, rootDir); + const moduleNameMapper = setupModuleNameMapper(projectConfig, rootDir); + const transform = setupTransform(projectConfig, rootDir); - config = makeProjectConfig({ + projectConfig = makeProjectConfig({ cacheDirectory: getCacheDirectory(), cwd: path.resolve(__dirname, '..', '..', '..', '..'), haste: { @@ -73,30 +73,36 @@ module.exports = async function createRuntime(filename, config) { moduleFileExtensions: ['js', 'jsx', 'ts', 'tsx', 'json', 'node'], name: 'Runtime-' + filename.replace(/\W/, '-') + '.tests', rootDir, - ...config, + ...projectConfig, moduleNameMapper, transform, }); - if (!config.roots.length) { - config.roots = [config.rootDir]; + if (!projectConfig.roots.length) { + projectConfig.roots = [projectConfig.rootDir]; } - const environment = new NodeEnvironment(config); + const environment = new NodeEnvironment({ + globalConfig: makeGlobalConfig(), + projectConfig, + }); environment.global.console = console; - const hasteMap = await Runtime.createHasteMap(config, { + const hasteMap = await Runtime.createHasteMap(projectConfig, { maxWorkers: 1, resetCache: false, }).build(); const cacheFS = new Map(); - const scriptTransformer = await createScriptTransformer(config, cacheFS); + const scriptTransformer = await createScriptTransformer( + projectConfig, + cacheFS, + ); const runtime = new Runtime( - config, + projectConfig, environment, - Runtime.createResolver(config, hasteMap.moduleMap), + Runtime.createResolver(projectConfig, hasteMap.moduleMap), scriptTransformer, cacheFS, { @@ -110,7 +116,7 @@ module.exports = async function createRuntime(filename, config) { filename, ); - for (const path of config.setupFiles) { + for (const path of projectConfig.setupFiles) { const esm = runtime.unstable_shouldLoadAsEsm(path); if (esm) { @@ -120,9 +126,9 @@ module.exports = async function createRuntime(filename, config) { } } - runtime.__mockRootPath = path.join(config.rootDir, 'root.js'); + runtime.__mockRootPath = path.join(projectConfig.rootDir, 'root.js'); runtime.__mockSubdirPath = path.join( - config.rootDir, + projectConfig.rootDir, 'subdir2', 'module_dir', 'module_dir_module.js',