From 00a7a261bcf4438b06984879185e0e7c02da0bd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=AA=E3=81=A4=E3=81=8D?= Date: Tue, 16 Apr 2024 21:49:21 -0700 Subject: [PATCH] Emulate base importer inside LegacyImporterWrapper to track access to containingUrl --- lib/src/legacy/importer.ts | 26 +++++++++++++++++++++++++- lib/src/legacy/index.ts | 19 ++++++++++++++----- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/lib/src/legacy/importer.ts b/lib/src/legacy/importer.ts index 97ef9117..5977a3d5 100644 --- a/lib/src/legacy/importer.ts +++ b/lib/src/legacy/importer.ts @@ -86,10 +86,34 @@ export class LegacyImporterWrapper canonicalize( url: string, - options: {fromImport: boolean} + options: {fromImport: boolean; containingUrl: URL | null} ): PromiseOr { 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) diff --git a/lib/src/legacy/index.ts b/lib/src/legacy/index.ts index 404937cf..d7543e35 100644 --- a/lib/src/legacy/index.ts +++ b/lib/src/legacy/index.ts @@ -184,11 +184,20 @@ function convertStringOptions( ): StringOptions & {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 | FileImporter; + // 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,