


























@@ -19,16 +19,9 @@ import {
1919writeFileSync,
2020} from "node:fs";
2121import { homedir, tmpdir } from "node:os";
22-import {
23-basename,
24-dirname,
25-isAbsolute,
26-join,
27-posix,
28-relative,
29-resolve as pathResolve,
30-} from "node:path";
22+import { basename, dirname, isAbsolute, join, relative, resolve as pathResolve } from "node:path";
3123import { fileURLToPath, pathToFileURL } from "node:url";
24+import { expandPackageDistImportClosure } from "./lib/package-dist-imports.mjs";
32253326const __dirname = dirname(fileURLToPath(import.meta.url));
3427const DEFAULT_PACKAGE_ROOT = join(__dirname, "..");
@@ -400,145 +393,6 @@ export function pruneLegacyPluginRuntimeDepsState(params = {}) {
400393return removed;
401394}
402395403-const JS_DIST_FILE_RE = /^dist\/.*\.(?:cjs|js|mjs)$/u;
404-405-function stripSpecifierSuffix(value) {
406-return value.replace(/[?#].*$/u, "");
407-}
408-409-function resolveDistImportPath(importerPath, specifier) {
410-if (!specifier.startsWith(".")) {
411-return null;
412-}
413-const stripped = stripSpecifierSuffix(specifier);
414-if (!stripped) {
415-return null;
416-}
417-return posix.normalize(posix.join(posix.dirname(importerPath), stripped));
418-}
419-420-function findStatementStart(source, index) {
421-return (
422-Math.max(
423-source.lastIndexOf(";", index),
424-source.lastIndexOf("{", index),
425-source.lastIndexOf("}", index),
426-source.lastIndexOf("\n", index),
427-source.lastIndexOf("\r", index),
428-) + 1
429-);
430-}
431-432-function isImportSpecifierContext(source, index) {
433-const dynamicPrefix = source.slice(Math.max(0, index - 32), index);
434-if (/\bimport\s*\(\s*$/u.test(dynamicPrefix)) {
435-return true;
436-}
437-const statementPrefix = source.slice(findStatementStart(source, index), index).trimStart();
438-return (
439-/^(?:import|export)\b[\s\S]*\bfrom\s*$/u.test(statementPrefix) ||
440-/^import\s*$/u.test(statementPrefix)
441-);
442-}
443-444-function collectImportSpecifiers(source) {
445-const specifiers = [];
446-let inBlockComment = false;
447-let inLineComment = false;
448-for (let index = 0; index < source.length; index += 1) {
449-if (inBlockComment) {
450-if (source[index] === "*" && source[index + 1] === "/") {
451-inBlockComment = false;
452-index += 1;
453-}
454-continue;
455-}
456-if (inLineComment) {
457-if (source[index] === "\n" || source[index] === "\r") {
458-inLineComment = false;
459-}
460-continue;
461-}
462-if (source[index] === "/" && source[index + 1] === "*") {
463-inBlockComment = true;
464-index += 1;
465-continue;
466-}
467-if (source[index] === "/" && source[index + 1] === "/") {
468-inLineComment = true;
469-index += 1;
470-continue;
471-}
472-473-const quote = source[index];
474-if (quote !== '"' && quote !== "'") {
475-continue;
476-}
477-478-let cursor = index + 1;
479-let value = "";
480-while (cursor < source.length) {
481-const char = source[cursor];
482-if (char === "\\") {
483-value += source.slice(cursor, cursor + 2);
484-cursor += 2;
485-continue;
486-}
487-if (char === quote) {
488-break;
489-}
490-value += char;
491-cursor += 1;
492-}
493-if (cursor >= source.length) {
494-break;
495-}
496-497-if (value.startsWith(".") && isImportSpecifierContext(source, index)) {
498-specifiers.push(value);
499-}
500-index = cursor;
501-}
502-return specifiers;
503-}
504-505-function expandInstalledDistImportClosure(params) {
506-const files = [...new Set(params.files)];
507-const fileSet = new Set(files);
508-const expectedSet = new Set(params.seedFiles);
509-let changed = true;
510-511-while (changed) {
512-changed = false;
513-for (const importerPath of [...expectedSet]
514-.filter((file) => fileSet.has(file))
515-.toSorted((left, right) => left.localeCompare(right))) {
516-if (!JS_DIST_FILE_RE.test(importerPath) || importerPath.includes("/node_modules/")) {
517-continue;
518-}
519-let source;
520-try {
521-source = params.readText(importerPath);
522-} catch (error) {
523-if (error?.code === "ENOENT") {
524-continue;
525-}
526-throw error;
527-}
528-for (const specifier of collectImportSpecifiers(source)) {
529-const importedPath = resolveDistImportPath(importerPath, specifier);
530-if (!importedPath || !fileSet.has(importedPath) || expectedSet.has(importedPath)) {
531-continue;
532-}
533-expectedSet.add(importedPath);
534-changed = true;
535-}
536-}
537-}
538-539-return [...expectedSet].toSorted((left, right) => left.localeCompare(right));
540-}
541-542396export function pruneInstalledPackageDist(params = {}) {
543397const packageRoot = params.packageRoot ?? DEFAULT_PACKAGE_ROOT;
544398const removeFile = params.unlinkSync ?? unlinkSync;
@@ -569,11 +423,18 @@ export function pruneInstalledPackageDist(params = {}) {
569423const installedFiles = listInstalledDistFiles(params);
570424const readFile = params.readFileSync ?? readFileSync;
571425expectedFiles = new Set(
572-expandInstalledDistImportClosure({
426+expandPackageDistImportClosure({
573427files: installedFiles,
574428seedFiles: [...expectedFiles],
575429readText(relativePath) {
576-return readFile(join(packageRoot, relativePath), "utf8");
430+try {
431+return readFile(join(packageRoot, relativePath), "utf8");
432+} catch (error) {
433+if (error?.code === "ENOENT") {
434+return "";
435+}
436+throw error;
437+}
577438},
578439}),
579440);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。