Skip to content

Commit

Permalink
module: move test reporter loading
Browse files Browse the repository at this point in the history
Move the logic for handling --test-reporter out of the general module loader
and into the test_runner subsystem.
  • Loading branch information
GeoffreyBooth committed Dec 20, 2022
1 parent 8398f85 commit 722fb95
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 61 deletions.
5 changes: 4 additions & 1 deletion doc/api/test.md
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ The following built-reporters are supported:
The `spec` reporter outputs the test results in a human-readable format.

* `dot`
The `dot` reporter outputs the test results in a comact format,
The `dot` reporter outputs the test results in a compact format,
where each passing test is represented by a `.`,
and each failing test is represented by a `X`.

Expand Down Expand Up @@ -591,6 +591,8 @@ module.exports = async function * customReporter(source) {
};
```

The value given for `--test-reporter` follows the same rules as [`--import`][].

### Multiple reporters

The [`--test-reporter`][] flag can be specified multiple times to report test
Expand Down Expand Up @@ -1585,6 +1587,7 @@ added:
aborted.

[TAP]: https://testanything.org/
[`--import`]: cli.md#--importmodule
[`--test-name-pattern`]: cli.md#--test-name-pattern
[`--test-only`]: cli.md#--test-only
[`--test-reporter-destination`]: cli.md#--test-reporter-destination
Expand Down
26 changes: 25 additions & 1 deletion lib/internal/modules/run_main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

const {
ObjectCreate,
StringPrototypeEndsWith,
} = primordials;

const { getOptionValue } = require('internal/options');
const path = require('path');
const { shouldUseESMLoader } = require('internal/modules/utils');

function resolveMainPath(main) {
// Note extension resolution for the main entry point can be deprecated in a
Expand All @@ -23,6 +24,29 @@ function resolveMainPath(main) {
return mainPath;
}

function shouldUseESMLoader(mainPath) {
/**
* @type {string[]} userLoaders A list of custom loaders registered by the user
* (or an empty list when none have been registered).
*/
const userLoaders = getOptionValue('--experimental-loader');
/**
* @type {string[]} userImports A list of preloaded modules registered by the user
* (or an empty list when none have been registered).
*/
const userImports = getOptionValue('--import');
if (userLoaders.length > 0 || userImports.length > 0)
return true;
const { readPackageScope } = require('internal/modules/cjs/loader');
// Determine the module format of the main
if (mainPath && StringPrototypeEndsWith(mainPath, '.mjs'))
return true;
if (!mainPath || StringPrototypeEndsWith(mainPath, '.cjs'))
return false;
const pkg = readPackageScope(mainPath);
return pkg && pkg.data.type === 'module';
}

function runMainESM(mainPath) {
const { loadESM } = require('internal/process/esm_loader');
const { pathToFileURL } = require('internal/url');
Expand Down
55 changes: 0 additions & 55 deletions lib/internal/modules/utils.js
Original file line number Diff line number Diff line change
@@ -1,55 +0,0 @@
'use strict';

const {
ObjectCreate,
StringPrototypeEndsWith,
} = primordials;
const { getOptionValue } = require('internal/options');


function shouldUseESMLoader(filePath) {
/**
* @type {string[]} userLoaders A list of custom loaders registered by the user
* (or an empty list when none have been registered).
*/
const userLoaders = getOptionValue('--experimental-loader');
/**
* @type {string[]} userImports A list of preloaded modules registered by the user
* (or an empty list when none have been registered).
*/
const userImports = getOptionValue('--import');
if (userLoaders.length > 0 || userImports.length > 0)
return true;
// Determine the module format of the main
if (filePath && StringPrototypeEndsWith(filePath, '.mjs'))
return true;
if (!filePath || StringPrototypeEndsWith(filePath, '.cjs'))
return false;
const { readPackageScope } = require('internal/modules/cjs/loader');
const pkg = readPackageScope(filePath);
return pkg?.data?.type === 'module';
}

/**
* @param {string} filePath
* @returns {any}
* requireOrImport imports a module if the file is an ES module, otherwise it requires it.
*/
function requireOrImport(filePath) {
const useESMLoader = shouldUseESMLoader(filePath);
if (useESMLoader) {
const { esmLoader } = require('internal/process/esm_loader');
const { pathToFileURL } = require('internal/url');
const { isAbsolute } = require('path');
const file = isAbsolute(filePath) ? pathToFileURL(filePath).href : filePath;
return esmLoader.import(file, undefined, ObjectCreate(null));
}
const { Module } = require('internal/modules/cjs/loader');

return new Module._load(filePath, null, false);
}

module.exports = {
shouldUseESMLoader,
requireOrImport,
};
11 changes: 8 additions & 3 deletions lib/internal/test_runner/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ const {
RegExpPrototypeExec,
SafeMap,
} = primordials;
const { basename } = require('path');
const { basename, isAbsolute } = require('path');
const { createWriteStream } = require('fs');
const { createDeferredPromise } = require('internal/util');
const { getOptionValue } = require('internal/options');
const { requireOrImport } = require('internal/modules/utils');

const {
codes: {
Expand Down Expand Up @@ -103,7 +102,13 @@ const kDefaultDestination = 'stdout';
async function getReportersMap(reporters, destinations) {
return SafePromiseAllReturnArrayLike(reporters, async (name, i) => {
const destination = kBuiltinDestinations.get(destinations[i]) ?? createWriteStream(destinations[i]);
let reporter = await requireOrImport(kBuiltinReporters.get(name) ?? name);

// Load the test reporter passed to --test-reporter
let reporterPath = kBuiltinReporters.get(name) ?? name;
const { esmLoader } = require('internal/process/esm_loader');
const { pathToFileURL } = require('internal/url');
const file = isAbsolute(reporterPath) ? pathToFileURL(reporterPath).href : reporterPath;
let reporter = await esmLoader.import(file, undefined, { __proto__: null });

if (reporter?.default) {
reporter = reporter.default;
Expand Down
1 change: 0 additions & 1 deletion test/parallel/test-bootstrap-modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ const expectedModules = new Set([
'NativeModule internal/idna',
'NativeModule internal/linkedlist',
'NativeModule internal/modules/cjs/loader',
'NativeModule internal/modules/utils',
'NativeModule internal/modules/esm/utils',
'NativeModule internal/modules/helpers',
'NativeModule internal/modules/package_json_reader',
Expand Down

0 comments on commit 722fb95

Please sign in to comment.