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