Skip to content

Commit 0fb446e

Browse files
aduh95targos
authored andcommitted
esm: do not interpret "main" as a URL
As documented, its value is a path. PR-URL: #55003 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
1 parent 0999b5e commit 0fb446e

File tree

3 files changed

+26
-46
lines changed

3 files changed

+26
-46
lines changed

lib/internal/modules/esm/resolve.js

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const {
2222
StringPrototypeStartsWith,
2323
encodeURIComponent,
2424
} = primordials;
25+
const assert = require('internal/assert');
2526
const internalFS = require('internal/fs/utils');
2627
const { BuiltinModule } = require('internal/bootstrap/realm');
2728
const { realpathSync } = require('fs');
@@ -117,18 +118,17 @@ function emitInvalidSegmentDeprecation(target, request, match, pjsonUrl, interna
117118
* Emits a deprecation warning if the given URL is a module and
118119
* the package.json file does not define a "main" or "exports" field.
119120
* @param {URL} url - The URL of the module being resolved.
120-
* @param {URL} packageJSONUrl - The URL of the package.json file for the module.
121+
* @param {string} path - The path of the module being resolved.
122+
* @param {string} pkgPath - The path of the parent dir of the package.json file for the module.
121123
* @param {string | URL} [base] - The base URL for the module being resolved.
122124
* @param {string} [main] - The "main" field from the package.json file.
123125
*/
124-
function emitLegacyIndexDeprecation(url, packageJSONUrl, base, main) {
126+
function emitLegacyIndexDeprecation(url, path, pkgPath, base, main) {
125127
if (process.noDeprecation) {
126128
return;
127129
}
128130
const format = defaultGetFormatWithoutErrors(url);
129131
if (format !== 'module') { return; }
130-
const path = fileURLToPath(url);
131-
const pkgPath = fileURLToPath(new URL('.', packageJSONUrl));
132132
const basePath = fileURLToPath(base);
133133
if (!main) {
134134
process.emitWarning(
@@ -196,20 +196,19 @@ const legacyMainResolveExtensionsIndexes = {
196196
* @returns {URL}
197197
*/
198198
function legacyMainResolve(packageJSONUrl, packageConfig, base) {
199-
const packageJsonUrlString = packageJSONUrl.href;
200-
201-
if (typeof packageJsonUrlString !== 'string') {
202-
throw new ERR_INVALID_ARG_TYPE('packageJSONUrl', ['URL'], packageJSONUrl);
203-
}
199+
assert(isURL(packageJSONUrl));
200+
const pkgPath = fileURLToPath(new URL('.', packageJSONUrl));
204201

205202
const baseStringified = isURL(base) ? base.href : base;
206203

207-
const resolvedOption = FSLegacyMainResolve(packageJsonUrlString, packageConfig.main, baseStringified);
204+
const resolvedOption = FSLegacyMainResolve(pkgPath, packageConfig.main, baseStringified);
208205

209-
const baseUrl = resolvedOption <= legacyMainResolveExtensionsIndexes.kResolvedByMainIndexNode ? `./${packageConfig.main}` : '';
210-
const resolvedUrl = new URL(baseUrl + legacyMainResolveExtensions[resolvedOption], packageJSONUrl);
206+
const maybeMain = resolvedOption <= legacyMainResolveExtensionsIndexes.kResolvedByMainIndexNode ?
207+
packageConfig.main || './' : '';
208+
const resolvedPath = resolve(pkgPath, maybeMain + legacyMainResolveExtensions[resolvedOption]);
209+
const resolvedUrl = pathToFileURL(resolvedPath);
211210

212-
emitLegacyIndexDeprecation(resolvedUrl, packageJSONUrl, base, packageConfig.main);
211+
emitLegacyIndexDeprecation(resolvedUrl, resolvedPath, pkgPath, base, packageConfig.main);
213212

214213
return resolvedUrl;
215214
}
@@ -790,8 +789,8 @@ function packageResolve(specifier, base, conditions) {
790789
// ResolveSelf
791790
const packageConfig = packageJsonReader.getPackageScopeConfig(base);
792791
if (packageConfig.exists) {
793-
const packageJSONUrl = pathToFileURL(packageConfig.pjsonPath);
794792
if (packageConfig.exports != null && packageConfig.name === packageName) {
793+
const packageJSONUrl = pathToFileURL(packageConfig.pjsonPath);
795794
return packageExportsResolve(
796795
packageJSONUrl, packageSubpath, packageConfig, base, conditions);
797796
}

src/node_file.cc

Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3236,37 +3236,18 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
32363236
Environment* env = Environment::GetCurrent(args);
32373237
auto isolate = env->isolate();
32383238

3239-
Utf8Value utf8_package_json_url(isolate, args[0]);
3240-
auto package_json_url =
3241-
ada::parse<ada::url_aggregator>(utf8_package_json_url.ToStringView());
3242-
3243-
if (!package_json_url) {
3244-
THROW_ERR_INVALID_URL(isolate, "Invalid URL");
3245-
return;
3246-
}
3239+
auto utf8_package_path = Utf8Value(isolate, args[0]).ToString();
32473240

32483241
std::string package_initial_file = "";
32493242

3250-
ada::result<ada::url_aggregator> file_path_url;
32513243
std::optional<std::string> initial_file_path;
32523244
std::string file_path;
32533245

32543246
if (args.Length() >= 2 && args[1]->IsString()) {
32553247
auto package_config_main = Utf8Value(isolate, args[1]).ToString();
32563248

3257-
file_path_url = ada::parse<ada::url_aggregator>(
3258-
std::string("./") + package_config_main, &package_json_url.value());
3259-
3260-
if (!file_path_url) {
3261-
THROW_ERR_INVALID_URL(isolate, "Invalid URL");
3262-
return;
3263-
}
3264-
3265-
initial_file_path = node::url::FileURLToPath(env, *file_path_url);
3266-
if (!initial_file_path.has_value()) {
3267-
return;
3268-
}
3269-
3249+
initial_file_path =
3250+
PathResolve(env, {utf8_package_path, package_config_main});
32703251
FromNamespacedPath(&initial_file_path.value());
32713252

32723253
package_initial_file = *initial_file_path;
@@ -3297,15 +3278,7 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
32973278
}
32983279
}
32993280

3300-
file_path_url =
3301-
ada::parse<ada::url_aggregator>("./index", &package_json_url.value());
3302-
3303-
if (!file_path_url) {
3304-
THROW_ERR_INVALID_URL(isolate, "Invalid URL");
3305-
return;
3306-
}
3307-
3308-
initial_file_path = node::url::FileURLToPath(env, *file_path_url);
3281+
initial_file_path = PathResolve(env, {utf8_package_path, "./index"});
33093282
if (!initial_file_path.has_value()) {
33103283
return;
33113284
}

test/es-module/test-cjs-legacyMainResolve.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ describe('legacyMainResolve', () => {
8282
{},
8383
''
8484
),
85-
{ message: /instance of URL/, code: 'ERR_INVALID_ARG_TYPE' },
85+
{ code: 'ERR_INTERNAL_ASSERTION' },
8686
);
8787
});
8888

@@ -166,4 +166,12 @@ describe('legacyMainResolve', () => {
166166
{ message: /"base" argument must be/, code: 'ERR_INVALID_ARG_TYPE' },
167167
);
168168
});
169+
170+
it('should interpret main as a path, not a URL', () => {
171+
const packageJsonUrl = fixtures.fileURL('/es-modules/legacy-main-resolver/package.json');
172+
assert.deepStrictEqual(
173+
legacyMainResolve(packageJsonUrl, { main: '../folder%25with percentage#/' }, packageJsonUrl),
174+
fixtures.fileURL('/es-modules/folder%25with percentage#/index.js'),
175+
);
176+
});
169177
});

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy