Skip to content

Commit

Permalink
Emulate base importer inside LegacyImporterWrapper to track access to…
Browse files Browse the repository at this point in the history
… containingUrl
  • Loading branch information
ntkme committed Apr 17, 2024
1 parent 24f095b commit 00a7a26
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 6 deletions.
26 changes: 25 additions & 1 deletion lib/src/legacy/importer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,34 @@ export class LegacyImporterWrapper<sync extends 'sync' | 'async'>

canonicalize(
url: string,
options: {fromImport: boolean}
options: {fromImport: boolean; containingUrl: URL | null}
): PromiseOr<URL | null, sync> {
if (url.startsWith(endOfLoadProtocol)) return new URL(url);

// Emulate a base importer instead of using a real base importer,
// because we want to mark containingUrl as used, which is impossible
// in a real base importer.
if (options.containingUrl !== null) {
try {
const absoluteUrl = new URL(url, options.containingUrl).toString();
const resolved = this.canonicalize(absoluteUrl, {
fromImport: options.fromImport,
containingUrl: null,
});
if (resolved !== null) return resolved;
} catch (error: unknown) {
if (
error instanceof TypeError &&
isErrnoException(error) &&
error.code === 'ERR_INVALID_URL'
) {
// ignore
} else {
throw error;
}
}
}

if (
url.startsWith(legacyImporterProtocolPrefix) ||
url.startsWith(legacyImporterProtocol)
Expand Down
19 changes: 14 additions & 5 deletions lib/src/legacy/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,20 @@ function convertStringOptions<sync extends 'sync' | 'async'>(
): StringOptions<sync> & {legacy: true} {
const modernOptions = convertOptions(options, sync);

// Find the first non-NodePackageImporter to pass as legacy `importer` option.
// NodePackageImporter will be passed in `modernOptions.importers`.
const importer = modernOptions.importers?.find(
_importer => !(_importer instanceof NodePackageImporter)
) as Importer<sync> | FileImporter<sync>;
// Use a no-op base importer, because the LegacyImporterWrapper will emulate
// the base importer by itself in order to mark containingUrl as accessed.
const importer = modernOptions.importers?.some(
importer => importer instanceof LegacyImporterWrapper
)
? {
canonicalize() {
return null;
},
load() {
return null;
},
}
: undefined;

return {
...modernOptions,
Expand Down

0 comments on commit 00a7a26

Please sign in to comment.