From 3a18af37d991ceed3acbfc3da4c712647b529a3b Mon Sep 17 00:00:00 2001 From: James Garbutt <43081j@users.noreply.github.com> Date: Wed, 27 May 2026 11:39:44 +0100 Subject: [PATCH 1/2] feat: use enginematch to resolve browserslist/engines --- src/analyze/core-js.ts | 20 +++++++++----------- src/analyze/replacements.ts | 12 ++++++++---- src/test/analyze/core-js.test.ts | 2 +- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/analyze/core-js.ts b/src/analyze/core-js.ts index 4d4e3d2..61593c7 100644 --- a/src/analyze/core-js.ts +++ b/src/analyze/core-js.ts @@ -1,6 +1,6 @@ import {glob} from 'tinyglobby'; -import {minVersion} from 'semver'; import {relative, join} from 'path'; +import {resolve} from 'enginematch'; import type {AnalysisContext, ReportPluginResult} from '../types.js'; import {SOURCE_GLOB, SOURCE_IGNORE} from '../utils/source-files.js'; @@ -32,17 +32,15 @@ export async function runCoreJsAnalysis( return {messages}; } - const nodeRange = pkg.engines?.node; - let targetVersion = 'current'; - if (nodeRange) { - const floor = minVersion(nodeRange); - if (floor) { - targetVersion = floor.version; - } + const resolvedTargets = resolve(pkg, { + cwd: context.root + }); + const targets: Record = {}; + for (const [target, version] of resolvedTargets.entries()) { + targets[target.replaceAll('_', '-')] = version; } - const {list: unnecessaryForTarget} = coreJsCompat.compat({ - targets: {node: targetVersion}, + targets, inverse: true }); const unnecessarySet = new Set(unnecessaryForTarget); @@ -79,7 +77,7 @@ export async function runCoreJsAnalysis( messages.push({ severity: 'suggestion', score: 0, - message: `core-js polyfill "${moduleName}" imported in ${filePath} is unnecessary — your Node.js target (>= ${targetVersion}) already supports this natively.` + message: `core-js polyfill "${moduleName}" imported in ${filePath} is unnecessary - your target engines already support this natively.` }); } } diff --git a/src/analyze/replacements.ts b/src/analyze/replacements.ts index 6101ac8..36916af 100644 --- a/src/analyze/replacements.ts +++ b/src/analyze/replacements.ts @@ -4,8 +4,12 @@ import type { EngineConstraint, KnownUrl } from 'module-replacements'; -import {type PackageJson, satisfies} from 'enginematch'; -import type {ReportPluginResult, AnalysisContext} from '../types.js'; +import {satisfies} from 'enginematch'; +import type { + ReportPluginResult, + AnalysisContext, + PackageJsonLike +} from '../types.js'; import {fixableReplacements} from '../commands/fixable-replacements.js'; import {getPackageJson} from '../utils/package-json.js'; import {getManifestForCategories} from '../categories.js'; @@ -34,7 +38,7 @@ function getNodeJSMinVersion(engines?: EngineConstraint[]): string | undefined { function findFirstCompatibleReplacement( replacementIds: string[], defs: Record, - pkg: PackageJson, + pkg: PackageJsonLike, root: string ): ModuleReplacement | undefined { for (const id of replacementIds) { @@ -131,7 +135,7 @@ export async function runReplacements( const firstCompatible = findFirstCompatibleReplacement( mapping.replacements, allReplacementDefs, - packageJson as PackageJson, + packageJson, context.root ); if (!firstCompatible) { diff --git a/src/test/analyze/core-js.test.ts b/src/test/analyze/core-js.test.ts index 799a5ea..c01b994 100644 --- a/src/test/analyze/core-js.test.ts +++ b/src/test/analyze/core-js.test.ts @@ -211,7 +211,7 @@ describe('runCoreJsAnalysis', () => { const result = await runCoreJsAnalysis(context); - expect(result.messages).toHaveLength(0); + expect(result.messages).toEqual([]); }); it('detects core-js in devDependencies', async () => { From bcd931e4a941a95a9dec2ba72f0b608e61456cd2 Mon Sep 17 00:00:00 2001 From: James Garbutt <43081j@users.noreply.github.com> Date: Wed, 27 May 2026 12:31:25 +0100 Subject: [PATCH 2/2] fix: pass targets as-is --- package-lock.json | 8 ++++---- package.json | 2 +- src/analyze/core-js.ts | 6 +----- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index f524db8..6d3d1da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@e18e/web-features-codemods": "^0.2.0", "@publint/pack": "^0.1.4", "core-js-compat": "^3.48.0", - "enginematch": "^0.1.3", + "enginematch": "^0.2.0", "fast-wrap-ansi": "^0.2.2", "fdir": "^6.5.0", "gunshi": "^0.32.0", @@ -2478,9 +2478,9 @@ "license": "ISC" }, "node_modules/enginematch": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/enginematch/-/enginematch-0.1.5.tgz", - "integrity": "sha512-Q1a8Kqxg9LPw4Rr5OV5ggO+XazMYcM+tndr5upq4dJ2F1FNyNhmaQLAUYc/gr09F/vJ28r0k/Tk2CwehdERhrw==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/enginematch/-/enginematch-0.2.0.tgz", + "integrity": "sha512-oJcFsJSeBNcsGQPOy0NWBtZWe1u3ChMKXpY9VqrnXh+l4hSP5r5l8axrzEMLallHlPu9aKrplSx9bcjJABOGUg==", "license": "MIT", "dependencies": { "browserslist": "^4.28.2", diff --git a/package.json b/package.json index 55f170d..03c69ba 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "@e18e/web-features-codemods": "^0.2.0", "@publint/pack": "^0.1.4", "core-js-compat": "^3.48.0", - "enginematch": "^0.1.3", + "enginematch": "^0.2.0", "fast-wrap-ansi": "^0.2.2", "fdir": "^6.5.0", "gunshi": "^0.32.0", diff --git a/src/analyze/core-js.ts b/src/analyze/core-js.ts index 61593c7..06831fa 100644 --- a/src/analyze/core-js.ts +++ b/src/analyze/core-js.ts @@ -35,12 +35,8 @@ export async function runCoreJsAnalysis( const resolvedTargets = resolve(pkg, { cwd: context.root }); - const targets: Record = {}; - for (const [target, version] of resolvedTargets.entries()) { - targets[target.replaceAll('_', '-')] = version; - } const {list: unnecessaryForTarget} = coreJsCompat.compat({ - targets, + targets: Object.fromEntries(resolvedTargets), inverse: true }); const unnecessarySet = new Set(unnecessaryForTarget);