@rollup/plugin-node-resolve 15.1.0 → 15.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/es/index.js CHANGED
@@ -8,7 +8,7 @@ import { pathToFileURL, fileURLToPath } from 'url';
8
8
  import resolve$1 from 'resolve';
9
9
  import { createFilter } from '@rollup/pluginutils';
10
10
 
11
- var version = "15.1.0";
11
+ var version = "15.2.1";
12
12
  var peerDependencies = {
13
13
  rollup: "^2.78.0||^3.0.0"
14
14
  };
@@ -17,18 +17,17 @@ promisify(fs.access);
17
17
  const readFile$1 = promisify(fs.readFile);
18
18
  const realpath = promisify(fs.realpath);
19
19
  const stat = promisify(fs.stat);
20
-
21
20
  async function fileExists(filePath) {
22
- try {
23
- const res = await stat(filePath);
24
- return res.isFile();
25
- } catch {
26
- return false;
27
- }
21
+ try {
22
+ const res = await stat(filePath);
23
+ return res.isFile();
24
+ }
25
+ catch {
26
+ return false;
27
+ }
28
28
  }
29
-
30
29
  async function resolveSymlink(path) {
31
- return (await fileExists(path)) ? realpath(path) : path;
30
+ return (await fileExists(path)) ? realpath(path) : path;
32
31
  }
33
32
 
34
33
  const onError = (error) => {
@@ -304,303 +303,372 @@ function normalizeInput(input) {
304
303
  }
305
304
 
306
305
  /* eslint-disable no-await-in-loop */
307
-
308
306
  function isModuleDir(current, moduleDirs) {
309
- return moduleDirs.some((dir) => current.endsWith(dir));
307
+ return moduleDirs.some((dir) => current.endsWith(dir));
310
308
  }
311
-
312
309
  async function findPackageJson(base, moduleDirs) {
313
- const { root } = path.parse(base);
314
- let current = base;
315
-
316
- while (current !== root && !isModuleDir(current, moduleDirs)) {
317
- const pkgJsonPath = path.join(current, 'package.json');
318
- if (await fileExists(pkgJsonPath)) {
319
- const pkgJsonString = fs.readFileSync(pkgJsonPath, 'utf-8');
320
- return { pkgJson: JSON.parse(pkgJsonString), pkgPath: current, pkgJsonPath };
310
+ const { root } = path.parse(base);
311
+ let current = base;
312
+ while (current !== root && !isModuleDir(current, moduleDirs)) {
313
+ const pkgJsonPath = path.join(current, 'package.json');
314
+ if (await fileExists(pkgJsonPath)) {
315
+ const pkgJsonString = fs.readFileSync(pkgJsonPath, 'utf-8');
316
+ return { pkgJson: JSON.parse(pkgJsonString), pkgPath: current, pkgJsonPath };
317
+ }
318
+ current = path.resolve(current, '..');
321
319
  }
322
- current = path.resolve(current, '..');
323
- }
324
- return null;
320
+ return null;
325
321
  }
326
-
327
322
  function isUrl(str) {
328
- try {
329
- return !!new URL(str);
330
- } catch (_) {
331
- return false;
332
- }
323
+ try {
324
+ return !!new URL(str);
325
+ }
326
+ catch (_) {
327
+ return false;
328
+ }
333
329
  }
334
-
330
+ /**
331
+ * Conditions is an export object where all keys are conditions like 'node' (aka do not with '.')
332
+ */
335
333
  function isConditions(exports) {
336
- return typeof exports === 'object' && Object.keys(exports).every((k) => !k.startsWith('.'));
334
+ return typeof exports === 'object' && Object.keys(exports).every((k) => !k.startsWith('.'));
337
335
  }
338
-
336
+ /**
337
+ * Mappings is an export object where all keys start with '.
338
+ */
339
339
  function isMappings(exports) {
340
- return typeof exports === 'object' && !isConditions(exports);
340
+ return typeof exports === 'object' && !isConditions(exports);
341
341
  }
342
-
342
+ /**
343
+ * Check for mixed exports, which are exports where some keys start with '.' and some do not
344
+ */
343
345
  function isMixedExports(exports) {
344
- const keys = Object.keys(exports);
345
- return keys.some((k) => k.startsWith('.')) && keys.some((k) => !k.startsWith('.'));
346
+ const keys = Object.keys(exports);
347
+ return keys.some((k) => k.startsWith('.')) && keys.some((k) => !k.startsWith('.'));
346
348
  }
347
-
348
349
  function createBaseErrorMsg(importSpecifier, importer) {
349
- return `Could not resolve import "${importSpecifier}" in ${importer}`;
350
+ return `Could not resolve import "${importSpecifier}" in ${importer}`;
350
351
  }
351
-
352
- function createErrorMsg(context, reason, internal) {
353
- const { importSpecifier, importer, pkgJsonPath } = context;
354
- const base = createBaseErrorMsg(importSpecifier, importer);
355
- const field = internal ? 'imports' : 'exports';
356
- return `${base} using ${field} defined in ${pkgJsonPath}.${reason ? ` ${reason}` : ''}`;
352
+ function createErrorMsg(context, reason, isImports) {
353
+ const { importSpecifier, importer, pkgJsonPath } = context;
354
+ const base = createBaseErrorMsg(importSpecifier, importer);
355
+ const field = isImports ? 'imports' : 'exports';
356
+ return `${base} using ${field} defined in ${pkgJsonPath}.${reason ? ` ${reason}` : ''}`;
357
+ }
358
+ class ResolveError extends Error {
357
359
  }
358
-
359
- class ResolveError extends Error {}
360
-
361
360
  class InvalidConfigurationError extends ResolveError {
362
- constructor(context, reason) {
363
- super(createErrorMsg(context, `Invalid "exports" field. ${reason}`));
364
- }
361
+ constructor(context, reason) {
362
+ super(createErrorMsg(context, `Invalid "exports" field. ${reason}`));
363
+ }
365
364
  }
366
-
367
365
  class InvalidModuleSpecifierError extends ResolveError {
368
- constructor(context, internal, reason) {
369
- super(createErrorMsg(context, reason, internal));
370
- }
366
+ constructor(context, isImports, reason) {
367
+ super(createErrorMsg(context, reason, isImports));
368
+ }
371
369
  }
372
-
373
370
  class InvalidPackageTargetError extends ResolveError {
374
- constructor(context, reason) {
375
- super(createErrorMsg(context, reason));
376
- }
371
+ constructor(context, reason) {
372
+ super(createErrorMsg(context, reason));
373
+ }
377
374
  }
378
375
 
379
376
  /* eslint-disable no-await-in-loop, no-undefined */
380
-
377
+ /**
378
+ * Check for invalid path segments
379
+ */
381
380
  function includesInvalidSegments(pathSegments, moduleDirs) {
382
- return pathSegments
383
- .split('/')
384
- .slice(1)
385
- .some((t) => ['.', '..', ...moduleDirs].includes(t));
381
+ const invalidSegments = ['', '.', '..', ...moduleDirs];
382
+ // contains any "", ".", "..", or "node_modules" segments, including percent encoded variants
383
+ return pathSegments.some((v) => invalidSegments.includes(v) || invalidSegments.includes(decodeURI(v)));
386
384
  }
387
-
388
- async function resolvePackageTarget(context, { target, subpath, pattern, internal }) {
389
- if (typeof target === 'string') {
390
- if (!pattern && subpath.length > 0 && !target.endsWith('/')) {
391
- throw new InvalidModuleSpecifierError(context);
385
+ async function resolvePackageTarget(context, { target, patternMatch, isImports }) {
386
+ // If target is a String, then
387
+ if (typeof target === 'string') {
388
+ // If target does not start with "./", then
389
+ if (!target.startsWith('./')) {
390
+ // If isImports is false, or if target starts with "../" or "/", or if target is a valid URL, then
391
+ if (!isImports || ['/', '../'].some((p) => target.startsWith(p)) || isUrl(target)) {
392
+ // Throw an Invalid Package Target error.
393
+ throw new InvalidPackageTargetError(context, `Invalid mapping: "${target}".`);
394
+ }
395
+ // If patternMatch is a String, then
396
+ if (typeof patternMatch === 'string') {
397
+ // Return PACKAGE_RESOLVE(target with every instance of "*" replaced by patternMatch, packageURL + "/")
398
+ const result = await context.resolveId(target.replace(/\*/g, patternMatch), context.pkgURL.href);
399
+ return result ? pathToFileURL(result.location).href : null;
400
+ }
401
+ // Return PACKAGE_RESOLVE(target, packageURL + "/").
402
+ const result = await context.resolveId(target, context.pkgURL.href);
403
+ return result ? pathToFileURL(result.location).href : null;
404
+ }
405
+ // TODO: Drop if we do not support Node <= 16 anymore
406
+ // This behavior was removed in Node 17 (deprecated in Node 14), see DEP0148
407
+ if (context.allowExportsFolderMapping) {
408
+ target = target.replace(/\/$/, '/*');
409
+ }
410
+ // If target split on "/" or "\"
411
+ {
412
+ const pathSegments = target.split(/\/|\\/);
413
+ // after the first "." segment
414
+ const firstDot = pathSegments.indexOf('.');
415
+ firstDot !== -1 && pathSegments.slice(firstDot);
416
+ if (firstDot !== -1 &&
417
+ firstDot < pathSegments.length - 1 &&
418
+ includesInvalidSegments(pathSegments.slice(firstDot + 1), context.moduleDirs)) {
419
+ throw new InvalidPackageTargetError(context, `Invalid mapping: "${target}".`);
420
+ }
421
+ }
422
+ // Let resolvedTarget be the URL resolution of the concatenation of packageURL and target.
423
+ const resolvedTarget = new URL(target, context.pkgURL);
424
+ // Assert: resolvedTarget is contained in packageURL.
425
+ if (!resolvedTarget.href.startsWith(context.pkgURL.href)) {
426
+ throw new InvalidPackageTargetError(context, `Resolved to ${resolvedTarget.href} which is outside package ${context.pkgURL.href}`);
427
+ }
428
+ // If patternMatch is null, then
429
+ if (!patternMatch) {
430
+ // Return resolvedTarget.
431
+ return resolvedTarget;
432
+ }
433
+ // If patternMatch split on "/" or "\" contains invalid segments
434
+ if (includesInvalidSegments(patternMatch.split(/\/|\\/), context.moduleDirs)) {
435
+ // throw an Invalid Module Specifier error.
436
+ throw new InvalidModuleSpecifierError(context);
437
+ }
438
+ // Return the URL resolution of resolvedTarget with every instance of "*" replaced with patternMatch.
439
+ return resolvedTarget.href.replace(/\*/g, patternMatch);
392
440
  }
393
-
394
- if (!target.startsWith('./')) {
395
- if (internal && !['/', '../'].some((p) => target.startsWith(p)) && !isUrl(target)) {
396
- // this is a bare package import, remap it and resolve it using regular node resolve
397
- if (pattern) {
398
- const result = await context.resolveId(
399
- target.replace(/\*/g, subpath),
400
- context.pkgURL.href
401
- );
402
- return result ? pathToFileURL(result.location).href : null;
441
+ // Otherwise, if target is an Array, then
442
+ if (Array.isArray(target)) {
443
+ // If _target.length is zero, return null.
444
+ if (target.length === 0) {
445
+ return null;
403
446
  }
404
-
405
- const result = await context.resolveId(`${target}${subpath}`, context.pkgURL.href);
406
- return result ? pathToFileURL(result.location).href : null;
407
- }
408
- throw new InvalidPackageTargetError(context, `Invalid mapping: "${target}".`);
447
+ let lastError = null;
448
+ // For each item in target, do
449
+ for (const item of target) {
450
+ // Let resolved be the result of PACKAGE_TARGET_RESOLVE of the item
451
+ // continuing the loop on any Invalid Package Target error.
452
+ try {
453
+ const resolved = await resolvePackageTarget(context, {
454
+ target: item,
455
+ patternMatch,
456
+ isImports
457
+ });
458
+ // If resolved is undefined, continue the loop.
459
+ // Else Return resolved.
460
+ if (resolved !== undefined) {
461
+ return resolved;
462
+ }
463
+ }
464
+ catch (error) {
465
+ if (!(error instanceof InvalidPackageTargetError)) {
466
+ throw error;
467
+ }
468
+ else {
469
+ lastError = error;
470
+ }
471
+ }
472
+ }
473
+ // Return or throw the last fallback resolution null return or error
474
+ if (lastError) {
475
+ throw lastError;
476
+ }
477
+ return null;
409
478
  }
410
-
411
- if (includesInvalidSegments(target, context.moduleDirs)) {
412
- throw new InvalidPackageTargetError(context, `Invalid mapping: "${target}".`);
479
+ // Otherwise, if target is a non-null Object, then
480
+ if (target && typeof target === 'object') {
481
+ // For each property of target
482
+ for (const [key, value] of Object.entries(target)) {
483
+ // If exports contains any index property keys, as defined in ECMA-262 6.1.7 Array Index, throw an Invalid Package Configuration error.
484
+ // TODO: We do not check if the key is a number here...
485
+ // If key equals "default" or conditions contains an entry for the key, then
486
+ if (key === 'default' || context.conditions.includes(key)) {
487
+ // Let targetValue be the value of the property in target.
488
+ // Let resolved be the result of PACKAGE_TARGET_RESOLVE of the targetValue
489
+ const resolved = await resolvePackageTarget(context, {
490
+ target: value,
491
+ patternMatch,
492
+ isImports
493
+ });
494
+ // If resolved is equal to undefined, continue the loop.
495
+ // Return resolved.
496
+ if (resolved !== undefined) {
497
+ return resolved;
498
+ }
499
+ }
500
+ }
501
+ // Return undefined.
502
+ return undefined;
413
503
  }
414
-
415
- const resolvedTarget = new URL(target, context.pkgURL);
416
- if (!resolvedTarget.href.startsWith(context.pkgURL.href)) {
417
- throw new InvalidPackageTargetError(
418
- context,
419
- `Resolved to ${resolvedTarget.href} which is outside package ${context.pkgURL.href}`
420
- );
504
+ // Otherwise, if target is null, return null.
505
+ if (target === null) {
506
+ return null;
421
507
  }
508
+ // Otherwise throw an Invalid Package Target error.
509
+ throw new InvalidPackageTargetError(context, `Invalid exports field.`);
510
+ }
422
511
 
423
- if (includesInvalidSegments(subpath, context.moduleDirs)) {
424
- throw new InvalidModuleSpecifierError(context);
512
+ /* eslint-disable no-await-in-loop */
513
+ /**
514
+ * Implementation of Node's `PATTERN_KEY_COMPARE` function
515
+ */
516
+ function nodePatternKeyCompare(keyA, keyB) {
517
+ // Let baseLengthA be the index of "*" in keyA plus one, if keyA contains "*", or the length of keyA otherwise.
518
+ const baseLengthA = keyA.includes('*') ? keyA.indexOf('*') + 1 : keyA.length;
519
+ // Let baseLengthB be the index of "*" in keyB plus one, if keyB contains "*", or the length of keyB otherwise.
520
+ const baseLengthB = keyB.includes('*') ? keyB.indexOf('*') + 1 : keyB.length;
521
+ // if baseLengthA is greater, return -1, if lower 1
522
+ const rval = baseLengthB - baseLengthA;
523
+ if (rval !== 0)
524
+ return rval;
525
+ // If keyA does not contain "*", return 1.
526
+ if (!keyA.includes('*'))
527
+ return 1;
528
+ // If keyB does not contain "*", return -1.
529
+ if (!keyB.includes('*'))
530
+ return -1;
531
+ // If the length of keyA is greater than the length of keyB, return -1.
532
+ // If the length of keyB is greater than the length of keyA, return 1.
533
+ // Else Return 0.
534
+ return keyB.length - keyA.length;
535
+ }
536
+ async function resolvePackageImportsExports(context, { matchKey, matchObj, isImports }) {
537
+ // If matchKey is a key of matchObj and does not contain "*", then
538
+ if (!matchKey.includes('*') && matchKey in matchObj) {
539
+ // Let target be the value of matchObj[matchKey].
540
+ const target = matchObj[matchKey];
541
+ // Return the result of PACKAGE_TARGET_RESOLVE(packageURL, target, null, isImports, conditions).
542
+ const resolved = await resolvePackageTarget(context, { target, patternMatch: '', isImports });
543
+ return resolved;
425
544
  }
426
-
427
- if (pattern) {
428
- return resolvedTarget.href.replace(/\*/g, subpath);
545
+ // Let expansionKeys be the list of keys of matchObj containing only a single "*"
546
+ const expansionKeys = Object.keys(matchObj)
547
+ // Assert: ends with "/" or contains only a single "*".
548
+ .filter((k) => k.endsWith('/') || k.includes('*'))
549
+ // sorted by the sorting function PATTERN_KEY_COMPARE which orders in descending order of specificity.
550
+ .sort(nodePatternKeyCompare);
551
+ // For each key expansionKey in expansionKeys, do
552
+ for (const expansionKey of expansionKeys) {
553
+ const indexOfAsterisk = expansionKey.indexOf('*');
554
+ // Let patternBase be the substring of expansionKey up to but excluding the first "*" character.
555
+ const patternBase = indexOfAsterisk === -1 ? expansionKey : expansionKey.substring(0, indexOfAsterisk);
556
+ // If matchKey starts with but is not equal to patternBase, then
557
+ if (matchKey.startsWith(patternBase) && matchKey !== patternBase) {
558
+ // Let patternTrailer be the substring of expansionKey from the index after the first "*" character.
559
+ const patternTrailer = indexOfAsterisk !== -1 ? expansionKey.substring(indexOfAsterisk + 1) : '';
560
+ // If patternTrailer has zero length,
561
+ if (patternTrailer.length === 0 ||
562
+ // or if matchKey ends with patternTrailer and the length of matchKey is greater than or equal to the length of expansionKey, then
563
+ (matchKey.endsWith(patternTrailer) && matchKey.length >= expansionKey.length)) {
564
+ // Let target be the value of matchObj[expansionKey].
565
+ const target = matchObj[expansionKey];
566
+ // Let patternMatch be the substring of matchKey starting at the index of the length of patternBase up to the length
567
+ // of matchKey minus the length of patternTrailer.
568
+ const patternMatch = matchKey.substring(patternBase.length, matchKey.length - patternTrailer.length);
569
+ // Return the result of PACKAGE_TARGET_RESOLVE
570
+ const resolved = await resolvePackageTarget(context, {
571
+ target,
572
+ patternMatch,
573
+ isImports
574
+ });
575
+ return resolved;
576
+ }
577
+ }
429
578
  }
430
- return new URL(subpath, resolvedTarget).href;
431
- }
432
-
433
- if (Array.isArray(target)) {
434
- let lastError;
435
- for (const item of target) {
436
- try {
437
- const resolved = await resolvePackageTarget(context, {
438
- target: item,
439
- subpath,
440
- pattern,
441
- internal
442
- });
579
+ throw new InvalidModuleSpecifierError(context, isImports);
580
+ }
443
581
 
444
- // return if defined or null, but not undefined
445
- if (resolved !== undefined) {
446
- return resolved;
582
+ /**
583
+ * Implementation of PACKAGE_EXPORTS_RESOLVE
584
+ */
585
+ async function resolvePackageExports(context, subpath, exports) {
586
+ // If exports is an Object with both a key starting with "." and a key not starting with "."
587
+ if (isMixedExports(exports)) {
588
+ // throw an Invalid Package Configuration error.
589
+ throw new InvalidConfigurationError(context, 'All keys must either start with ./, or without one.');
590
+ }
591
+ // If subpath is equal to ".", then
592
+ if (subpath === '.') {
593
+ // Let mainExport be undefined.
594
+ let mainExport;
595
+ // If exports is a String or Array, or an Object containing no keys starting with ".", then
596
+ if (typeof exports === 'string' || Array.isArray(exports) || isConditions(exports)) {
597
+ // Set mainExport to exports
598
+ mainExport = exports;
599
+ // Otherwise if exports is an Object containing a "." property, then
447
600
  }
448
- } catch (error) {
449
- if (!(error instanceof InvalidPackageTargetError)) {
450
- throw error;
451
- } else {
452
- lastError = error;
601
+ else if (isMappings(exports)) {
602
+ // Set mainExport to exports["."]
603
+ mainExport = exports['.'];
453
604
  }
454
- }
455
- }
456
-
457
- if (lastError) {
458
- throw lastError;
605
+ // If mainExport is not undefined, then
606
+ if (mainExport) {
607
+ // Let resolved be the result of PACKAGE_TARGET_RESOLVE with target = mainExport
608
+ const resolved = await resolvePackageTarget(context, {
609
+ target: mainExport,
610
+ patternMatch: '',
611
+ isImports: false
612
+ });
613
+ // If resolved is not null or undefined, return resolved.
614
+ if (resolved) {
615
+ return resolved;
616
+ }
617
+ }
618
+ // Otherwise, if exports is an Object and all keys of exports start with ".", then
459
619
  }
460
- return null;
461
- }
462
-
463
- if (target && typeof target === 'object') {
464
- for (const [key, value] of Object.entries(target)) {
465
- if (key === 'default' || context.conditions.includes(key)) {
466
- const resolved = await resolvePackageTarget(context, {
467
- target: value,
468
- subpath,
469
- pattern,
470
- internal
620
+ else if (isMappings(exports)) {
621
+ // Let resolved be the result of PACKAGE_IMPORTS_EXPORTS_RESOLVE
622
+ const resolvedMatch = await resolvePackageImportsExports(context, {
623
+ matchKey: subpath,
624
+ matchObj: exports,
625
+ isImports: false
471
626
  });
472
-
473
- // return if defined or null, but not undefined
474
- if (resolved !== undefined) {
475
- return resolved;
627
+ // If resolved is not null or undefined, return resolved.
628
+ if (resolvedMatch) {
629
+ return resolvedMatch;
476
630
  }
477
- }
478
631
  }
479
- return undefined;
480
- }
481
-
482
- if (target === null) {
483
- return null;
484
- }
485
-
486
- throw new InvalidPackageTargetError(context, `Invalid exports field.`);
632
+ // Throw a Package Path Not Exported error.
633
+ throw new InvalidModuleSpecifierError(context);
487
634
  }
488
635
 
489
- /* eslint-disable no-await-in-loop */
490
-
491
- async function resolvePackageImportsExports(context, { matchKey, matchObj, internal }) {
492
- if (!matchKey.endsWith('*') && matchKey in matchObj) {
493
- const target = matchObj[matchKey];
494
- const resolved = await resolvePackageTarget(context, { target, subpath: '', internal });
495
- return resolved;
496
- }
497
-
498
- const expansionKeys = Object.keys(matchObj)
499
- .filter((k) => k.endsWith('/') || k.endsWith('*'))
500
- .sort((a, b) => b.length - a.length);
501
-
502
- for (const expansionKey of expansionKeys) {
503
- const prefix = expansionKey.substring(0, expansionKey.length - 1);
504
-
505
- if (expansionKey.endsWith('*') && matchKey.startsWith(prefix)) {
506
- const target = matchObj[expansionKey];
507
- const subpath = matchKey.substring(expansionKey.length - 1);
508
- const resolved = await resolvePackageTarget(context, {
509
- target,
510
- subpath,
511
- pattern: true,
512
- internal
513
- });
514
- return resolved;
636
+ async function resolvePackageImports({ importSpecifier, importer, moduleDirs, conditions, resolveId }) {
637
+ const result = await findPackageJson(importer, moduleDirs);
638
+ if (!result) {
639
+ throw new Error(`${createBaseErrorMsg(importSpecifier, importer)}. Could not find a parent package.json.`);
515
640
  }
516
-
517
- if (matchKey.startsWith(expansionKey)) {
518
- const target = matchObj[expansionKey];
519
- const subpath = matchKey.substring(expansionKey.length);
520
-
521
- const resolved = await resolvePackageTarget(context, { target, subpath, internal });
522
- return resolved;
641
+ const { pkgPath, pkgJsonPath, pkgJson } = result;
642
+ const pkgURL = pathToFileURL(`${pkgPath}/`);
643
+ const context = {
644
+ importer,
645
+ importSpecifier,
646
+ moduleDirs,
647
+ pkgURL,
648
+ pkgJsonPath,
649
+ conditions,
650
+ resolveId
651
+ };
652
+ // Assert: specifier begins with "#".
653
+ if (!importSpecifier.startsWith('#')) {
654
+ throw new InvalidModuleSpecifierError(context, true, 'Invalid import specifier.');
523
655
  }
524
- }
525
-
526
- throw new InvalidModuleSpecifierError(context, internal);
527
- }
528
-
529
- async function resolvePackageExports(context, subpath, exports) {
530
- if (isMixedExports(exports)) {
531
- throw new InvalidConfigurationError(
532
- context,
533
- 'All keys must either start with ./, or without one.'
534
- );
535
- }
536
-
537
- if (subpath === '.') {
538
- let mainExport;
539
- // If exports is a String or Array, or an Object containing no keys starting with ".", then
540
- if (typeof exports === 'string' || Array.isArray(exports) || isConditions(exports)) {
541
- mainExport = exports;
542
- } else if (isMappings(exports)) {
543
- mainExport = exports['.'];
656
+ // If specifier is exactly equal to "#" or starts with "#/", then
657
+ if (importSpecifier === '#' || importSpecifier.startsWith('#/')) {
658
+ // Throw an Invalid Module Specifier error.
659
+ throw new InvalidModuleSpecifierError(context, true, 'Invalid import specifier.');
544
660
  }
545
-
546
- if (mainExport) {
547
- const resolved = await resolvePackageTarget(context, { target: mainExport, subpath: '' });
548
- if (resolved) {
549
- return resolved;
550
- }
661
+ const { imports } = pkgJson;
662
+ if (!imports) {
663
+ throw new InvalidModuleSpecifierError(context, true);
551
664
  }
552
- } else if (isMappings(exports)) {
553
- const resolvedMatch = await resolvePackageImportsExports(context, {
554
- matchKey: subpath,
555
- matchObj: exports
665
+ // Let packageURL be the result of LOOKUP_PACKAGE_SCOPE(parentURL).
666
+ // If packageURL is not null, then
667
+ return resolvePackageImportsExports(context, {
668
+ matchKey: importSpecifier,
669
+ matchObj: imports,
670
+ isImports: true
556
671
  });
557
-
558
- if (resolvedMatch) {
559
- return resolvedMatch;
560
- }
561
- }
562
-
563
- throw new InvalidModuleSpecifierError(context);
564
- }
565
-
566
- async function resolvePackageImports({
567
- importSpecifier,
568
- importer,
569
- moduleDirs,
570
- conditions,
571
- resolveId
572
- }) {
573
- const result = await findPackageJson(importer, moduleDirs);
574
- if (!result) {
575
- throw new Error(createBaseErrorMsg('. Could not find a parent package.json.'));
576
- }
577
-
578
- const { pkgPath, pkgJsonPath, pkgJson } = result;
579
- const pkgURL = pathToFileURL(`${pkgPath}/`);
580
- const context = {
581
- importer,
582
- importSpecifier,
583
- moduleDirs,
584
- pkgURL,
585
- pkgJsonPath,
586
- conditions,
587
- resolveId
588
- };
589
-
590
- const { imports } = pkgJson;
591
- if (!imports) {
592
- throw new InvalidModuleSpecifierError(context, true);
593
- }
594
-
595
- if (importSpecifier === '#' || importSpecifier.startsWith('#/')) {
596
- throw new InvalidModuleSpecifierError(context, true, 'Invalid import specifier.');
597
- }
598
-
599
- return resolvePackageImportsExports(context, {
600
- matchKey: importSpecifier,
601
- matchObj: imports,
602
- internal: true
603
- });
604
672
  }
605
673
 
606
674
  const resolveImportPath = promisify(resolve$1);
@@ -705,7 +773,8 @@ async function resolveWithExportMap({
705
773
  moduleDirectories,
706
774
  modulePaths,
707
775
  rootDir,
708
- ignoreSideEffectsForRoot
776
+ ignoreSideEffectsForRoot,
777
+ allowExportsFolderMapping
709
778
  }) {
710
779
  if (importSpecifier.startsWith('#')) {
711
780
  // this is a package internal import, resolve using package imports field
@@ -794,6 +863,7 @@ async function resolveWithExportMap({
794
863
  moduleDirs: moduleDirectories,
795
864
  pkgURL,
796
865
  pkgJsonPath,
866
+ allowExportsFolderMapping,
797
867
  conditions: exportConditions
798
868
  };
799
869
  const resolvedPackageExport = await resolvePackageExports(context, subpath, pkgJson.exports);
@@ -874,7 +944,8 @@ async function resolveImportSpecifiers({
874
944
  moduleDirectories,
875
945
  modulePaths,
876
946
  rootDir,
877
- ignoreSideEffectsForRoot
947
+ ignoreSideEffectsForRoot,
948
+ allowExportsFolderMapping
878
949
  }) {
879
950
  try {
880
951
  const exportMapRes = await resolveWithExportMap({
@@ -890,7 +961,8 @@ async function resolveImportSpecifiers({
890
961
  moduleDirectories,
891
962
  modulePaths,
892
963
  rootDir,
893
- ignoreSideEffectsForRoot
964
+ ignoreSideEffectsForRoot,
965
+ allowExportsFolderMapping
894
966
  });
895
967
  if (exportMapRes) return exportMapRes;
896
968
  } catch (error) {
@@ -977,7 +1049,9 @@ const defaults = {
977
1049
  extensions: ['.mjs', '.js', '.json', '.node'],
978
1050
  resolveOnly: [],
979
1051
  moduleDirectories: ['node_modules'],
980
- ignoreSideEffectsForRoot: false
1052
+ ignoreSideEffectsForRoot: false,
1053
+ // TODO: set to false in next major release or remove
1054
+ allowExportsFolderMapping: true
981
1055
  };
982
1056
  const DEFAULTS = deepFreeze(deepMerge({}, defaults));
983
1057
 
@@ -1123,7 +1197,8 @@ function nodeResolve(opts = {}) {
1123
1197
  moduleDirectories,
1124
1198
  modulePaths,
1125
1199
  rootDir,
1126
- ignoreSideEffectsForRoot
1200
+ ignoreSideEffectsForRoot,
1201
+ allowExportsFolderMapping: options.allowExportsFolderMapping
1127
1202
  });
1128
1203
 
1129
1204
  const importeeIsBuiltin = isBuiltinModule(importee);
@@ -1241,7 +1316,7 @@ function nodeResolve(opts = {}) {
1241
1316
  // `moduleSideEffects` information.
1242
1317
  const resolvedResolved = await this.resolve(resolved.id, importer, {
1243
1318
  ...resolveOptions,
1244
- custom: { ...custom, 'node-resolve': { ...custom['node-resolve'], resolved } }
1319
+ custom: { ...custom, 'node-resolve': { ...custom['node-resolve'], resolved, importee } }
1245
1320
  });
1246
1321
  if (resolvedResolved) {
1247
1322
  // Handle plugins that manually make the result external