Browse Source

fix: legacyMainResolve with asar

Shelley Vohr 1 year ago
parent
commit
27cda155f6

+ 22 - 2
lib/node/asar-fs-wrapper.ts

@@ -49,7 +49,7 @@ const asarRe = /\.asar/i;
 const { getValidatedPath } = __non_webpack_require__('internal/fs/utils');
 // In the renderer node internals use the node global URL but we do not set that to be
 // the global URL instance.  We need to do instanceof checks against the internal URL impl
-const { URL: NodeURL } = __non_webpack_require__('internal/url');
+const { URL: NodeURL, fileURLToPath } = __non_webpack_require__('internal/url');
 
 // Separate asar package's path from full path.
 const splitPath = (archivePathOrBuffer: string | Buffer | URL) => {
@@ -725,7 +725,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
       throw createError(AsarError.NOT_FOUND, { asarPath, filePath });
     }
 
-    if (options && (options as ReaddirSyncOptions).withFileTypes) {
+    if ((options as ReaddirSyncOptions)?.withFileTypes) {
       const dirents = [];
       for (const file of files) {
         const childPath = path.join(filePath, file);
@@ -741,6 +741,26 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
     return files;
   };
 
+  const { legacyMainResolve } = internalBinding('fs');
+  internalBinding('fs').legacyMainResolve = (packageJSONUrl: any, packageConfig: any, base: any) => {
+    const pathInfo = splitPath(fileURLToPath(packageJSONUrl));
+    if (!pathInfo.isAsar) return legacyMainResolve(packageJSONUrl, packageConfig, base);
+    const { asarPath, filePath } = pathInfo;
+
+    const archive = getOrCreateArchive(asarPath);
+    if (!archive) {
+      throw createError(AsarError.INVALID_ARCHIVE, { asarPath });
+    }
+
+    const newPath = archive.copyFileOut(filePath);
+    if (!newPath) {
+      throw createError(AsarError.NOT_FOUND, { asarPath, filePath });
+    }
+
+    const newURL = new URL(`file://${newPath}/${filePath}`);
+    return legacyMainResolve(newURL, packageConfig, base);
+  };
+
   const { internalModuleReadJSON } = internalBinding('fs');
   internalBinding('fs').internalModuleReadJSON = (pathArgument: string) => {
     const pathInfo = splitPath(pathArgument);

+ 3 - 3
patches/node/fix_expose_the_built-in_electron_module_via_the_esm_loader.patch

@@ -48,10 +48,10 @@ index 5239bc8ed883a54df206d73c5dc0b70942c4f3df..6a15fcae677b3bda58fc85f705862bbc
        ArrayPrototypePush(schemes, 'https', 'http');
      }
 diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js
-index 06a34c11254a2fedd2ea59c4057bfb30c31082a6..66ecfbcdd4fb2c9986e2d4619a381337839979fe 100644
+index 827ade56abe2ebced589159604e697c29b66a96b..869725c2629784c48fab30475e6e44df8a409323 100644
 --- a/lib/internal/modules/esm/resolve.js
 +++ b/lib/internal/modules/esm/resolve.js
-@@ -740,6 +740,8 @@ function packageImportsResolve(name, base, conditions) {
+@@ -739,6 +739,8 @@ function packageImportsResolve(name, base, conditions) {
    throw importNotDefined(name, packageJSONUrl, base);
  }
  
@@ -60,7 +60,7 @@ index 06a34c11254a2fedd2ea59c4057bfb30c31082a6..66ecfbcdd4fb2c9986e2d4619a381337
  /**
   * Returns the package type for a given URL.
   * @param {URL} url - The URL to get the package type for.
-@@ -800,6 +802,11 @@ function packageResolve(specifier, base, conditions) {
+@@ -799,6 +801,11 @@ function packageResolve(specifier, base, conditions) {
      return new URL('node:' + specifier);
    }
  

+ 2 - 2
patches/node/fix_lazyload_fs_in_esm_loaders_to_apply_asar_patches.patch

@@ -38,7 +38,7 @@ index 6a15fcae677b3bda58fc85f705862bbcd9feec9d..449131b9af99744c08d62d73f8d124ce
      const match = RegExpPrototypeExec(DATA_URL_PATTERN, url.pathname);
      if (!match) {
 diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js
-index 66ecfbcdd4fb2c9986e2d4619a381337839979fe..102165af37a42ca0394ec0d4efc21d3b03efe5eb 100644
+index 869725c2629784c48fab30475e6e44df8a409323..6de431f3f03fd0d9b63c94575bd361326ded1e81 100644
 --- a/lib/internal/modules/esm/resolve.js
 +++ b/lib/internal/modules/esm/resolve.js
 @@ -24,7 +24,7 @@ const {
@@ -50,7 +50,7 @@ index 66ecfbcdd4fb2c9986e2d4619a381337839979fe..102165af37a42ca0394ec0d4efc21d3b
  const { getOptionValue } = require('internal/options');
  // Do not eagerly grab .manifest, it may be in TDZ
  const policy = getOptionValue('--experimental-policy') ?
-@@ -266,7 +266,7 @@ function finalizeResolution(resolved, base, preserveSymlinks) {
+@@ -265,7 +265,7 @@ function finalizeResolution(resolved, base, preserveSymlinks) {
    }
  
    if (!preserveSymlinks) {

+ 48 - 0
patches/node/refactor_allow_embedder_overriding_of_internal_fs_calls.patch

@@ -42,6 +42,54 @@ index d4b70bab5e89300bfe6305263d556c986380e2e0..1f3b719048f2477de183e2856b9b8eee
    if (statCache !== null && result >= 0) {
      // Only set cache when `internalModuleStat(filename)` succeeds.
      statCache.set(filename, result);
+diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js
+index 06a34c11254a2fedd2ea59c4057bfb30c31082a6..827ade56abe2ebced589159604e697c29b66a96b 100644
+--- a/lib/internal/modules/esm/resolve.js
++++ b/lib/internal/modules/esm/resolve.js
+@@ -39,7 +39,7 @@ const inputTypeFlag = getOptionValue('--input-type');
+ const { URL, pathToFileURL, fileURLToPath, isURL } = require('internal/url');
+ const { getCWDURL } = require('internal/util');
+ const { canParse: URLCanParse } = internalBinding('url');
+-const { legacyMainResolve: FSLegacyMainResolve } = internalBinding('fs');
++const internalFsBinding = internalBinding('fs');
+ const {
+   ERR_INPUT_TYPE_NOT_ALLOWED,
+   ERR_INVALID_ARG_TYPE,
+@@ -58,7 +58,6 @@ const { Module: CJSModule } = require('internal/modules/cjs/loader');
+ const { getPackageScopeConfig } = require('internal/modules/esm/package_config');
+ const { getConditionsSet } = require('internal/modules/esm/utils');
+ const packageJsonReader = require('internal/modules/package_json_reader');
+-const { internalModuleStat } = internalBinding('fs');
+ 
+ /**
+  * @typedef {import('internal/modules/esm/package_config.js').PackageConfig} PackageConfig
+@@ -211,7 +210,7 @@ function legacyMainResolve(packageJSONUrl, packageConfig, base) {
+ 
+   const baseStringified = isURL(base) ? base.href : base;
+ 
+-  const resolvedOption = FSLegacyMainResolve(packageJsonUrlString, packageConfig.main, baseStringified);
++  const resolvedOption = internalFsBinding.legacyMainResolve(packageJsonUrlString, packageConfig.main, baseStringified);
+ 
+   const baseUrl = resolvedOption <= legacyMainResolveExtensionsIndexes.kResolvedByMainIndexNode ? `./${packageConfig.main}` : '';
+   const resolvedUrl = new URL(baseUrl + legacyMainResolveExtensions[resolvedOption], packageJSONUrl);
+@@ -250,7 +249,7 @@ function finalizeResolution(resolved, base, preserveSymlinks) {
+     throw err;
+   }
+ 
+-  const stats = internalModuleStat(toNamespacedPath(StringPrototypeEndsWith(path, '/') ?
++  const stats = internalFsBinding.internalModuleStat(toNamespacedPath(StringPrototypeEndsWith(path, '/') ?
+     StringPrototypeSlice(path, -1) : path));
+ 
+   // Check for stats.isDirectory()
+@@ -818,7 +817,7 @@ function packageResolve(specifier, base, conditions) {
+   let packageJSONPath = fileURLToPath(packageJSONUrl);
+   let lastPath;
+   do {
+-    const stat = internalModuleStat(toNamespacedPath(StringPrototypeSlice(packageJSONPath, 0,
++    const stat = internalFsBinding.internalModuleStat(toNamespacedPath(StringPrototypeSlice(packageJSONPath, 0,
+                                                                           packageJSONPath.length - 13)));
+     // Check for !stat.isDirectory()
+     if (stat !== 1) {
 diff --git a/lib/internal/modules/package_json_reader.js b/lib/internal/modules/package_json_reader.js
 index 88c079d10d116107aa34dc9281f64c799c48c0b5..146e2e49dc46c7f5302638f75cca4af548509d77 100644
 --- a/lib/internal/modules/package_json_reader.js