Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 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
4 changes: 2 additions & 2 deletions lib/internal/modules/cjs/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ function trySelf(parentPath, request) {
try {
return finalizeEsmResolution(packageExportsResolve(
pathToFileURL(pkgPath + '/package.json'), expansion, pkg,
pathToFileURL(parentPath), cjsConditions).resolved, parentPath, pkgPath);
pathToFileURL(parentPath), cjsConditions), parentPath, pkgPath);
} catch (e) {
if (e.code === 'ERR_MODULE_NOT_FOUND')
throw createEsmNotFoundErr(request, pkgPath + '/package.json');
Expand All @@ -481,7 +481,7 @@ function resolveExports(nmPath, request) {
try {
return finalizeEsmResolution(packageExportsResolve(
pathToFileURL(pkgPath + '/package.json'), '.' + expansion, pkg, null,
cjsConditions).resolved, null, pkgPath);
cjsConditions), null, pkgPath);
} catch (e) {
if (e.code === 'ERR_MODULE_NOT_FOUND')
throw createEsmNotFoundErr(request, pkgPath + '/package.json');
Expand Down
61 changes: 41 additions & 20 deletions lib/internal/modules/esm/get_format.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ const legacyExtensionFormatMap = {
'.node': 'commonjs'
};

let experimentalSpecifierResolutionWarned = false;

if (experimentalWasmModules)
extensionFormatMap['.wasm'] = legacyExtensionFormatMap['.wasm'] = 'wasm';

Expand All @@ -54,30 +56,48 @@ const protocolHandlers = ObjectAssign(ObjectCreate(null), {
return format;
},
'file:'(parsed, url) {
const ext = extname(parsed.pathname);
let format;

if (ext === '.js') {
format = getPackageType(parsed.href) === 'module' ? 'module' : 'commonjs';
} else {
format = extensionFormatMap[ext];
}
if (!format) {
if (experimentalSpecifierResolution === 'node') {
process.emitWarning(
'The Node.js specifier resolution in ESM is experimental.',
'ExperimentalWarning');
format = legacyExtensionFormatMap[ext];
} else {
throw new ERR_UNKNOWN_FILE_EXTENSION(ext, fileURLToPath(url));
}
}

return format || null;
return getModuleFileFormat(parsed, true, url) || null;
},
'node:'() { return 'builtin'; },
});

function throwIfNotExperimentalSpecifierResolution(ext, url) {
if (experimentalSpecifierResolution !== 'node') {
throw new ERR_UNKNOWN_FILE_EXTENSION(ext, fileURLToPath(url));
}
return getLegacyExtensionFormat(ext);
}

function getLegacyExtensionFormat(ext) {
if (
experimentalSpecifierResolution === 'node' &&
!experimentalSpecifierResolutionWarned
) {
process.emitWarning(
'The Node.js specifier resolution in ESM is experimental.',
'ExperimentalWarning');
experimentalSpecifierResolutionWarned = true;
}
return legacyExtensionFormatMap[ext];
}

function getModuleFileFormat(url, throwIfNotResolved, urlForThrow) {
let format;

const ext = extname(url.pathname);
if (ext === '.js') {
format = getPackageType(url) === 'module' ? 'module' : 'commonjs';
Comment thread
aduh95 marked this conversation as resolved.
Outdated
} else {
format = extensionFormatMap[ext] ??
(throwIfNotResolved ?
throwIfNotExperimentalSpecifierResolution(ext, urlForThrow) :
getLegacyExtensionFormat(ext)
);
}

return format;
}

function defaultGetFormat(url, context) {
const parsed = new URL(url);

Expand All @@ -89,5 +109,6 @@ function defaultGetFormat(url, context) {
module.exports = {
defaultGetFormat,
extensionFormatMap,
getModuleFileFormat,
legacyExtensionFormatMap,
};
73 changes: 36 additions & 37 deletions lib/internal/modules/esm/resolve.js
Original file line number Diff line number Diff line change
Expand Up @@ -464,22 +464,6 @@ const patternRegEx = /\*/g;
function resolvePackageTargetString(
target, subpath, match, packageJSONUrl, base, pattern, internal, conditions) {

const composeResult = (resolved) => {
let format;
try {
format = getPackageType(resolved);
} catch (err) {
if (err.code === 'ERR_INVALID_FILE_URL_PATH') {
const invalidModuleErr = new ERR_INVALID_MODULE_SPECIFIER(
resolved, 'must not include encoded "/" or "\\" characters', base);
invalidModuleErr.cause = err;
throw invalidModuleErr;
}
throw err;
}
return { resolved, ...(format !== 'none') && { format } };
};

if (subpath !== '' && !pattern && target[target.length - 1] !== '/')
throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base);

Expand Down Expand Up @@ -512,7 +496,7 @@ function resolvePackageTargetString(
if (!StringPrototypeStartsWith(resolvedPath, packagePath))
throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base);

if (subpath === '') return composeResult(resolved);
if (subpath === '') return resolved;

if (RegExpPrototypeTest(invalidSegmentRegEx, subpath)) {
const request = pattern ?
Expand All @@ -521,12 +505,16 @@ function resolvePackageTargetString(
}

if (pattern) {
return composeResult(new URL(RegExpPrototypeSymbolReplace(patternRegEx,
resolved.href,
() => subpath)));
return new URL(
RegExpPrototypeSymbolReplace(
patternRegEx,
resolved.href,
() => subpath
)
);
}

return composeResult(new URL(subpath, resolved));
return new URL(subpath, resolved);
}

/**
Expand Down Expand Up @@ -753,7 +741,7 @@ function packageImportsResolve(name, base, conditions) {
packageJSONUrl, imports[name], '', name, base, false, true, conditions
);
if (resolveResult != null) {
return resolveResult.resolved;
return resolveResult;
}
} else {
let bestMatch = '';
Expand Down Expand Up @@ -785,7 +773,7 @@ function packageImportsResolve(name, base, conditions) {
bestMatch, base, true,
true, conditions);
if (resolveResult != null) {
return resolveResult.resolved;
return resolveResult;
}
}
}
Expand Down Expand Up @@ -849,7 +837,7 @@ function parsePackageName(specifier, base) {
*/
function packageResolve(specifier, base, conditions) {
if (NativeModule.canBeRequiredByUsers(specifier))
return { resolved: new URL('node:' + specifier) };
return new URL('node:' + specifier);

const { packageName, packageSubpath, isScoped } =
parsePackageName(specifier, base);
Expand Down Expand Up @@ -888,19 +876,14 @@ function packageResolve(specifier, base, conditions) {
packageJSONUrl, packageSubpath, packageConfig, base, conditions);
}
if (packageSubpath === '.') {
return {
resolved: legacyMainResolve(
packageJSONUrl,
packageConfig,
base),
...(packageConfig.type !== 'none') && { format: packageConfig.type }
};
return legacyMainResolve(
packageJSONUrl,
packageConfig,
base
);
}

return {
resolved: new URL(packageSubpath, packageJSONUrl),
...(packageConfig.type !== 'none') && { format: packageConfig.type }
};
return new URL(packageSubpath, packageJSONUrl);
// Cross-platform root check.
} while (packageJSONPath.length !== lastPath.length);

Expand Down Expand Up @@ -933,6 +916,12 @@ function shouldBeTreatedAsRelativeOrAbsolutePath(specifier) {
return isRelativeSpecifier(specifier);
}

function amendFormatToUrl(resolved) {
const format = getModuleFileFormat(resolved, false);

return { resolved, ...(format !== null) && { format } };
Copy link
Copy Markdown
Contributor

@aduh95 aduh95 Dec 19, 2021

Choose a reason for hiding this comment

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

Can you add this code snippet at the top of test/es-module/test-esm-resolve-type.js please?

Reflect.defineProperty(Object.prototype, 'format', {
  get: common.mustNotCall('get Object.prototype.format'),
})

And wrap all assert.strictEqual(resolveResult.format, expectedResolvedFormat); in a if (Object.hasOwn(resolveResult, 'format') || expectedResolvedFormat !== undefined).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I cannot commit this because the tests would fail. For example here.

}

/**
* @param {string} specifier
* @param {string | URL | undefined} base
Expand All @@ -945,6 +934,7 @@ function moduleResolve(specifier, base, conditions, preserveSymlinks) {
// Ok since relative URLs cannot parse as URLs.
let resolved;
let format;

if (shouldBeTreatedAsRelativeOrAbsolutePath(specifier)) {
resolved = new URL(specifier, base);
} else if (specifier[0] === '#') {
Expand All @@ -953,7 +943,13 @@ function moduleResolve(specifier, base, conditions, preserveSymlinks) {
try {
resolved = new URL(specifier);
} catch {
({ resolved, format } = packageResolve(specifier, base, conditions));
({ resolved, format } =
amendFormatToUrl(
Comment thread
guybedford marked this conversation as resolved.
Outdated
packageResolve(
specifier,
base,
conditions
)));
}
}
if (resolved.protocol !== 'file:') {
Expand Down Expand Up @@ -1107,4 +1103,7 @@ module.exports = {
};

// cycle
const { defaultGetFormat } = require('internal/modules/esm/get_format');
const {
defaultGetFormat,
getModuleFileFormat,
} = require('internal/modules/esm/get_format');
Loading