Compare commits

...

3 Commits

Author SHA1 Message Date
Shelley Vohr
2c39db3b2f fix: ensure Node.js can resolve |main| in package.json 2024-02-17 10:58:13 +01:00
Shelley Vohr
087593443a fix: newUrl -> newURL.href & typings 2024-02-15 16:38:07 +01:00
Shelley Vohr
27cda155f6 fix: legacyMainResolve with asar 2024-02-15 11:01:09 +01:00
4 changed files with 102 additions and 7 deletions

View File

@@ -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,53 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
return files;
};
const { legacyMainResolve } = internalBinding('fs');
internalBinding('fs').legacyMainResolve = (packageJSONUrl: URL, packageConfigMain: string, base: string) => {
const pathInfo = splitPath(fileURLToPath(packageJSONUrl));
if (!pathInfo.isAsar) return legacyMainResolve(packageJSONUrl, packageConfigMain, base);
const { asarPath, filePath } = pathInfo;
const archive = getOrCreateArchive(asarPath);
if (!archive) {
throw createError(AsarError.INVALID_ARCHIVE, { asarPath });
}
// Copy out the original package.json into a temp directory so
// it can be read.
const tempPackageJSON = archive.copyFileOut(filePath);
if (!tempPackageJSON) {
throw createError(AsarError.NOT_FOUND, { asarPath, filePath });
}
// Get the containing directory for the new faked package.json.
const tempDir = path.dirname(tempPackageJSON);
// Rename the new temp file to package.json so Node.js can find it.
const renamedPackageJson = path.join(tempDir, 'package.json');
fs.renameSync(tempPackageJSON, renamedPackageJson);
// Get the containing directory for |main| in package.json,
// then create it in the temp directory.
const mainFileDir = path.dirname(packageConfigMain);
const tempMainFileDir = path.join(tempDir, mainFileDir);
fs.mkdirSync(tempMainFileDir, { recursive: true });
// Copy the contents of |main| in package.json to a temporary directory.
const packagConfigMainPath = path.join(path.dirname(filePath), packageConfigMain);
const tempMainFile = archive.copyFileOut(packagConfigMainPath);
if (!tempMainFile) {
throw createError(AsarError.NOT_FOUND, { asarPath, filePath: packagConfigMainPath });
}
// Rename |main| in the temp directory to match |main| so Node.js can find it.
fs.renameSync(tempMainFile, path.join(tempMainFileDir, path.basename(packageConfigMain)));
// Create a file URL from the temporary package.json and
// pass that back to the Node.js implementation.
const newURL = new URL(`file://${renamedPackageJson}`);
return legacyMainResolve(newURL.href, packageConfigMain, base);
};
const { internalModuleReadJSON } = internalBinding('fs');
internalBinding('fs').internalModuleReadJSON = (pathArgument: string) => {
const pathInfo = splitPath(pathArgument);

View File

@@ -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);
}

View File

@@ -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) {

View File

@@ -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