diff --git a/package-lock.json b/package-lock.json index 202cd841..b9be2b9e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,6 +32,7 @@ "@ffmpeg-installer/ffmpeg": "^1.1.0", "@google-cloud/bigquery": "^4.1.4", "@google-cloud/firestore": "^7.6.0", + "@opentelemetry/api": "^1.7.0", "@sentry/node": "^5.5.0", "@tpluscode/sparql-builder": "^0.3.12", "@types/bindings": "^1.3.0", @@ -3952,6 +3953,15 @@ "node": ">= 8" } }, + "node_modules/@opentelemetry/api": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.8.0.tgz", + "integrity": "sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/@phc/format": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@phc/format/-/format-1.0.0.tgz", diff --git a/package.json b/package.json index e9292109..80cd5403 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "@ffmpeg-installer/ffmpeg": "^1.1.0", "@google-cloud/bigquery": "^4.1.4", "@google-cloud/firestore": "^7.6.0", + "@opentelemetry/api": "^1.7.0", "@sentry/node": "^5.5.0", "@tpluscode/sparql-builder": "^0.3.12", "@types/bindings": "^1.3.0", diff --git a/src/node-file-trace.ts b/src/node-file-trace.ts index 455f69f6..597cbffd 100644 --- a/src/node-file-trace.ts +++ b/src/node-file-trace.ts @@ -68,6 +68,7 @@ export class Job { public warnings: Set; public reasons: NodeFileTraceReasons = new Map(); private cachedFileSystem: CachedFileSystem; + private remappings: Map> = new Map(); constructor({ base = process.cwd(), @@ -154,6 +155,16 @@ export class Job { this.warnings = new Set(); } + addRemapping(path: string, dep: string) { + if (path === dep) return; + let deps = this.remappings.get(path); + if (!deps) { + deps = new Set(); + this.remappings.set(path, deps); + } + deps.add(dep); + } + async readlink(path: string) { return this.cachedFileSystem.readlink(path); } @@ -316,6 +327,14 @@ export class Job { } this.processed.add(path); + // Additional dependencies. + const additionalDeps = this.remappings.get(path); + if (additionalDeps) { + await Promise.all( + [...additionalDeps].map(async (dep) => this.emitDependency(dep, path)), + ); + } + const emitted = await this.emitFile(path, 'dependency', parent); if (!emitted) return; if (path.endsWith('.json')) return; diff --git a/src/resolve-dependency.ts b/src/resolve-dependency.ts index 6da4458e..826e86c7 100644 --- a/src/resolve-dependency.ts +++ b/src/resolve-dependency.ts @@ -128,6 +128,7 @@ interface PkgCfg { main: string | undefined; exports: PackageTarget; imports: { [key: string]: PackageTarget }; + browser?: string | { [key: string]: string }; } async function getPkgCfg( @@ -250,6 +251,33 @@ function resolveExportsImports( return undefined; } +async function resolveRemappings( + pkgPath: string, + pkgCfg: PkgCfg, + parent: string, + job: Job, +): Promise { + if (job.conditions?.includes('browser')) { + const { browser: pkgBrowser } = pkgCfg; + if (typeof pkgBrowser === 'object') { + for (const [key, value] of Object.entries(pkgBrowser)) { + if (!key.startsWith('./') || !value.startsWith('./')) { + continue; + } + const keyResolved = await resolveFile(pkgPath + sep + key, parent, job); + const valueResolved = await resolveFile( + pkgPath + sep + value, + parent, + job, + ); + if (keyResolved && valueResolved) { + job.addRemapping(keyResolved, valueResolved); + } + } + } + } +} + async function packageImportsResolve( name: string, parent: string, @@ -355,6 +383,16 @@ async function resolvePackage( if (!stat || !stat.isDirectory()) continue; const pkgCfg = await getPkgCfg(nodeModulesDir + sep + pkgName, job); const { exports: pkgExports } = pkgCfg || {}; + + if (pkgCfg) { + await resolveRemappings( + nodeModulesDir + sep + pkgName, + pkgCfg, + parent, + job, + ); + } + if ( job.conditions && pkgExports !== undefined && diff --git a/test/integration/otel-api.js b/test/integration/otel-api.js new file mode 100644 index 00000000..e7feb2f3 --- /dev/null +++ b/test/integration/otel-api.js @@ -0,0 +1,3 @@ +const { trace } = require('@opentelemetry/api'); + +void trace.getTracer('test').startSpan('test'); diff --git a/test/unit.test.js b/test/unit.test.js index d54a50fd..0bf62b1b 100644 --- a/test/unit.test.js +++ b/test/unit.test.js @@ -129,9 +129,20 @@ for (const { testName, isRoot } of unitTests) { inputFileNames.push('input-2.js', 'input-3.js', 'input-4.js'); } + // Type: { conditions?: string[] } + let testOpts = {}; + try { + testOpts = JSON.parse( + fs.readFileSync(join(unitPath, 'test-opts.json')).toString(), + ); + } catch { + // Ignore. + } + const { fileList, reasons } = await nodeFileTrace( inputFileNames.map((file) => join(unitPath, file)), { + conditions: testOpts.conditions, base: isRoot ? '/' : `${__dirname}/../`, processCwd: unitPath, paths: { diff --git a/test/unit/browser-remappings-disabled/.gitignore b/test/unit/browser-remappings-disabled/.gitignore new file mode 100644 index 00000000..a9412d2d --- /dev/null +++ b/test/unit/browser-remappings-disabled/.gitignore @@ -0,0 +1,2 @@ +# include node_modules for testing +!node_modules diff --git a/test/unit/browser-remappings-disabled/input.js b/test/unit/browser-remappings-disabled/input.js new file mode 100644 index 00000000..76b86cf7 --- /dev/null +++ b/test/unit/browser-remappings-disabled/input.js @@ -0,0 +1,2 @@ +require('pkg'); + diff --git a/test/unit/browser-remappings-disabled/node_modules/pkg/index.js b/test/unit/browser-remappings-disabled/node_modules/pkg/index.js new file mode 100644 index 00000000..914a7c58 --- /dev/null +++ b/test/unit/browser-remappings-disabled/node_modules/pkg/index.js @@ -0,0 +1 @@ +module.exports = 'legacy index'; diff --git a/test/unit/browser-remappings-disabled/node_modules/pkg/package.json b/test/unit/browser-remappings-disabled/node_modules/pkg/package.json new file mode 100644 index 00000000..cb18feae --- /dev/null +++ b/test/unit/browser-remappings-disabled/node_modules/pkg/package.json @@ -0,0 +1,16 @@ +{ + "name": "pkg", + "main": "index.js", + "exports": { + ".": { + "import": "./subdir/import-main.js", + "require": "./require-main.cjs" + }, + "./asdf": { + "import": "./subdir/import-main.js" + } + }, + "browser": { + "./subdir/import-main.js": "./subdir/import-main-browser.js" + } +} diff --git a/test/unit/browser-remappings-disabled/node_modules/pkg/require-main.cjs b/test/unit/browser-remappings-disabled/node_modules/pkg/require-main.cjs new file mode 100644 index 00000000..43b69844 --- /dev/null +++ b/test/unit/browser-remappings-disabled/node_modules/pkg/require-main.cjs @@ -0,0 +1,2 @@ +import('pkg/asdf'); +module.exports = 'require main'; diff --git a/test/unit/browser-remappings-disabled/node_modules/pkg/subdir/import-main-browser.js b/test/unit/browser-remappings-disabled/node_modules/pkg/subdir/import-main-browser.js new file mode 100644 index 00000000..72b9016b --- /dev/null +++ b/test/unit/browser-remappings-disabled/node_modules/pkg/subdir/import-main-browser.js @@ -0,0 +1 @@ +export default 'import main browser'; diff --git a/test/unit/browser-remappings-disabled/node_modules/pkg/subdir/import-main.js b/test/unit/browser-remappings-disabled/node_modules/pkg/subdir/import-main.js new file mode 100644 index 00000000..95bc9efa --- /dev/null +++ b/test/unit/browser-remappings-disabled/node_modules/pkg/subdir/import-main.js @@ -0,0 +1 @@ +export default 'import main'; diff --git a/test/unit/browser-remappings-disabled/node_modules/pkg/subdir/package.json b/test/unit/browser-remappings-disabled/node_modules/pkg/subdir/package.json new file mode 100644 index 00000000..6990891f --- /dev/null +++ b/test/unit/browser-remappings-disabled/node_modules/pkg/subdir/package.json @@ -0,0 +1 @@ +{"type": "module"} diff --git a/test/unit/browser-remappings-disabled/output.js b/test/unit/browser-remappings-disabled/output.js new file mode 100644 index 00000000..7f3dbae7 --- /dev/null +++ b/test/unit/browser-remappings-disabled/output.js @@ -0,0 +1,9 @@ +[ + "package.json", + "test/unit/browser-remappings-disabled/input.js", + "test/unit/browser-remappings-disabled/node_modules/pkg/index.js", + "test/unit/browser-remappings-disabled/node_modules/pkg/package.json", + "test/unit/browser-remappings-disabled/node_modules/pkg/require-main.cjs", + "test/unit/browser-remappings-disabled/node_modules/pkg/subdir/import-main.js", + "test/unit/browser-remappings-disabled/node_modules/pkg/subdir/package.json" +] \ No newline at end of file diff --git a/test/unit/browser-remappings-disabled/test-opts.json b/test/unit/browser-remappings-disabled/test-opts.json new file mode 100644 index 00000000..41001520 --- /dev/null +++ b/test/unit/browser-remappings-disabled/test-opts.json @@ -0,0 +1,3 @@ +{ + "conditions": ["node"] +} diff --git a/test/unit/browser-remappings-malformed/.gitignore b/test/unit/browser-remappings-malformed/.gitignore new file mode 100644 index 00000000..a9412d2d --- /dev/null +++ b/test/unit/browser-remappings-malformed/.gitignore @@ -0,0 +1,2 @@ +# include node_modules for testing +!node_modules diff --git a/test/unit/browser-remappings-malformed/input.js b/test/unit/browser-remappings-malformed/input.js new file mode 100644 index 00000000..76b86cf7 --- /dev/null +++ b/test/unit/browser-remappings-malformed/input.js @@ -0,0 +1,2 @@ +require('pkg'); + diff --git a/test/unit/browser-remappings-malformed/node_modules/pkg/index.js b/test/unit/browser-remappings-malformed/node_modules/pkg/index.js new file mode 100644 index 00000000..914a7c58 --- /dev/null +++ b/test/unit/browser-remappings-malformed/node_modules/pkg/index.js @@ -0,0 +1 @@ +module.exports = 'legacy index'; diff --git a/test/unit/browser-remappings-malformed/node_modules/pkg/package.json b/test/unit/browser-remappings-malformed/node_modules/pkg/package.json new file mode 100644 index 00000000..a351498c --- /dev/null +++ b/test/unit/browser-remappings-malformed/node_modules/pkg/package.json @@ -0,0 +1,14 @@ +{ + "name": "pkg", + "main": "index.js", + "exports": { + ".": { + "import": "./subdir/import-main.js", + "require": "./require-main.cjs" + }, + "./asdf": { + "import": "./subdir/import-main.js" + } + }, + "browser": "./subdir/import-main-browser.js" +} diff --git a/test/unit/browser-remappings-malformed/node_modules/pkg/require-main.cjs b/test/unit/browser-remappings-malformed/node_modules/pkg/require-main.cjs new file mode 100644 index 00000000..43b69844 --- /dev/null +++ b/test/unit/browser-remappings-malformed/node_modules/pkg/require-main.cjs @@ -0,0 +1,2 @@ +import('pkg/asdf'); +module.exports = 'require main'; diff --git a/test/unit/browser-remappings-malformed/node_modules/pkg/subdir/import-main-browser.js b/test/unit/browser-remappings-malformed/node_modules/pkg/subdir/import-main-browser.js new file mode 100644 index 00000000..72b9016b --- /dev/null +++ b/test/unit/browser-remappings-malformed/node_modules/pkg/subdir/import-main-browser.js @@ -0,0 +1 @@ +export default 'import main browser'; diff --git a/test/unit/browser-remappings-malformed/node_modules/pkg/subdir/import-main.js b/test/unit/browser-remappings-malformed/node_modules/pkg/subdir/import-main.js new file mode 100644 index 00000000..95bc9efa --- /dev/null +++ b/test/unit/browser-remappings-malformed/node_modules/pkg/subdir/import-main.js @@ -0,0 +1 @@ +export default 'import main'; diff --git a/test/unit/browser-remappings-malformed/node_modules/pkg/subdir/package.json b/test/unit/browser-remappings-malformed/node_modules/pkg/subdir/package.json new file mode 100644 index 00000000..6990891f --- /dev/null +++ b/test/unit/browser-remappings-malformed/node_modules/pkg/subdir/package.json @@ -0,0 +1 @@ +{"type": "module"} diff --git a/test/unit/browser-remappings-malformed/output.js b/test/unit/browser-remappings-malformed/output.js new file mode 100644 index 00000000..70a4f208 --- /dev/null +++ b/test/unit/browser-remappings-malformed/output.js @@ -0,0 +1,9 @@ +[ + "package.json", + "test/unit/browser-remappings-malformed/input.js", + "test/unit/browser-remappings-malformed/node_modules/pkg/index.js", + "test/unit/browser-remappings-malformed/node_modules/pkg/package.json", + "test/unit/browser-remappings-malformed/node_modules/pkg/require-main.cjs", + "test/unit/browser-remappings-malformed/node_modules/pkg/subdir/import-main.js", + "test/unit/browser-remappings-malformed/node_modules/pkg/subdir/package.json" +] \ No newline at end of file diff --git a/test/unit/browser-remappings-malformed/test-opts.json b/test/unit/browser-remappings-malformed/test-opts.json new file mode 100644 index 00000000..9e01628e --- /dev/null +++ b/test/unit/browser-remappings-malformed/test-opts.json @@ -0,0 +1,3 @@ +{ + "conditions": ["browser"] +} diff --git a/test/unit/browser-remappings-malformed2/.gitignore b/test/unit/browser-remappings-malformed2/.gitignore new file mode 100644 index 00000000..a9412d2d --- /dev/null +++ b/test/unit/browser-remappings-malformed2/.gitignore @@ -0,0 +1,2 @@ +# include node_modules for testing +!node_modules diff --git a/test/unit/browser-remappings-malformed2/input.js b/test/unit/browser-remappings-malformed2/input.js new file mode 100644 index 00000000..76b86cf7 --- /dev/null +++ b/test/unit/browser-remappings-malformed2/input.js @@ -0,0 +1,2 @@ +require('pkg'); + diff --git a/test/unit/browser-remappings-malformed2/node_modules/pkg/index.js b/test/unit/browser-remappings-malformed2/node_modules/pkg/index.js new file mode 100644 index 00000000..914a7c58 --- /dev/null +++ b/test/unit/browser-remappings-malformed2/node_modules/pkg/index.js @@ -0,0 +1 @@ +module.exports = 'legacy index'; diff --git a/test/unit/browser-remappings-malformed2/node_modules/pkg/package.json b/test/unit/browser-remappings-malformed2/node_modules/pkg/package.json new file mode 100644 index 00000000..d273579b --- /dev/null +++ b/test/unit/browser-remappings-malformed2/node_modules/pkg/package.json @@ -0,0 +1,20 @@ +{ + "name": "pkg", + "main": "index.js", + "exports": { + ".": { + "import": "./subdir/import-main.js", + "require": "./require-main.cjs" + }, + "./asdf": { + "import": "./subdir/import-main.js" + } + }, + "browser": { + "./subdir/import-main.js": "./invalid.js", + "./require-main.cjs": "invalid.js", + "./invalid.js": "./subdir/import-main-browser.js", + "invalid.js": "./subdir/import-main-browser.js", + "invalid2.js": "unknown.js" + } +} diff --git a/test/unit/browser-remappings-malformed2/node_modules/pkg/require-main.cjs b/test/unit/browser-remappings-malformed2/node_modules/pkg/require-main.cjs new file mode 100644 index 00000000..43b69844 --- /dev/null +++ b/test/unit/browser-remappings-malformed2/node_modules/pkg/require-main.cjs @@ -0,0 +1,2 @@ +import('pkg/asdf'); +module.exports = 'require main'; diff --git a/test/unit/browser-remappings-malformed2/node_modules/pkg/subdir/import-main-browser.js b/test/unit/browser-remappings-malformed2/node_modules/pkg/subdir/import-main-browser.js new file mode 100644 index 00000000..72b9016b --- /dev/null +++ b/test/unit/browser-remappings-malformed2/node_modules/pkg/subdir/import-main-browser.js @@ -0,0 +1 @@ +export default 'import main browser'; diff --git a/test/unit/browser-remappings-malformed2/node_modules/pkg/subdir/import-main.js b/test/unit/browser-remappings-malformed2/node_modules/pkg/subdir/import-main.js new file mode 100644 index 00000000..95bc9efa --- /dev/null +++ b/test/unit/browser-remappings-malformed2/node_modules/pkg/subdir/import-main.js @@ -0,0 +1 @@ +export default 'import main'; diff --git a/test/unit/browser-remappings-malformed2/node_modules/pkg/subdir/package.json b/test/unit/browser-remappings-malformed2/node_modules/pkg/subdir/package.json new file mode 100644 index 00000000..6990891f --- /dev/null +++ b/test/unit/browser-remappings-malformed2/node_modules/pkg/subdir/package.json @@ -0,0 +1 @@ +{"type": "module"} diff --git a/test/unit/browser-remappings-malformed2/output.js b/test/unit/browser-remappings-malformed2/output.js new file mode 100644 index 00000000..1f0940eb --- /dev/null +++ b/test/unit/browser-remappings-malformed2/output.js @@ -0,0 +1,9 @@ +[ + "package.json", + "test/unit/browser-remappings-malformed2/input.js", + "test/unit/browser-remappings-malformed2/node_modules/pkg/index.js", + "test/unit/browser-remappings-malformed2/node_modules/pkg/package.json", + "test/unit/browser-remappings-malformed2/node_modules/pkg/require-main.cjs", + "test/unit/browser-remappings-malformed2/node_modules/pkg/subdir/import-main.js", + "test/unit/browser-remappings-malformed2/node_modules/pkg/subdir/package.json" +] \ No newline at end of file diff --git a/test/unit/browser-remappings-malformed2/test-opts.json b/test/unit/browser-remappings-malformed2/test-opts.json new file mode 100644 index 00000000..9e01628e --- /dev/null +++ b/test/unit/browser-remappings-malformed2/test-opts.json @@ -0,0 +1,3 @@ +{ + "conditions": ["browser"] +} diff --git a/test/unit/browser-remappings/.gitignore b/test/unit/browser-remappings/.gitignore new file mode 100644 index 00000000..a9412d2d --- /dev/null +++ b/test/unit/browser-remappings/.gitignore @@ -0,0 +1,2 @@ +# include node_modules for testing +!node_modules diff --git a/test/unit/browser-remappings/input.js b/test/unit/browser-remappings/input.js new file mode 100644 index 00000000..76b86cf7 --- /dev/null +++ b/test/unit/browser-remappings/input.js @@ -0,0 +1,2 @@ +require('pkg'); + diff --git a/test/unit/browser-remappings/node_modules/pkg/index.js b/test/unit/browser-remappings/node_modules/pkg/index.js new file mode 100644 index 00000000..914a7c58 --- /dev/null +++ b/test/unit/browser-remappings/node_modules/pkg/index.js @@ -0,0 +1 @@ +module.exports = 'legacy index'; diff --git a/test/unit/browser-remappings/node_modules/pkg/package.json b/test/unit/browser-remappings/node_modules/pkg/package.json new file mode 100644 index 00000000..8f6ce0fe --- /dev/null +++ b/test/unit/browser-remappings/node_modules/pkg/package.json @@ -0,0 +1,17 @@ +{ + "name": "pkg", + "main": "index.js", + "exports": { + ".": { + "import": "./subdir/import-main.js", + "require": "./require-main.cjs" + }, + "./asdf": { + "import": "./subdir/import-main.js" + } + }, + "browser": { + "./subdir/import-main.js": "./subdir/import-main-browser.js", + "./unknown.js": "./invalid.js" + } +} diff --git a/test/unit/browser-remappings/node_modules/pkg/require-main.cjs b/test/unit/browser-remappings/node_modules/pkg/require-main.cjs new file mode 100644 index 00000000..43b69844 --- /dev/null +++ b/test/unit/browser-remappings/node_modules/pkg/require-main.cjs @@ -0,0 +1,2 @@ +import('pkg/asdf'); +module.exports = 'require main'; diff --git a/test/unit/browser-remappings/node_modules/pkg/subdir/import-main-browser.js b/test/unit/browser-remappings/node_modules/pkg/subdir/import-main-browser.js new file mode 100644 index 00000000..72b9016b --- /dev/null +++ b/test/unit/browser-remappings/node_modules/pkg/subdir/import-main-browser.js @@ -0,0 +1 @@ +export default 'import main browser'; diff --git a/test/unit/browser-remappings/node_modules/pkg/subdir/import-main.js b/test/unit/browser-remappings/node_modules/pkg/subdir/import-main.js new file mode 100644 index 00000000..95bc9efa --- /dev/null +++ b/test/unit/browser-remappings/node_modules/pkg/subdir/import-main.js @@ -0,0 +1 @@ +export default 'import main'; diff --git a/test/unit/browser-remappings/node_modules/pkg/subdir/package.json b/test/unit/browser-remappings/node_modules/pkg/subdir/package.json new file mode 100644 index 00000000..6990891f --- /dev/null +++ b/test/unit/browser-remappings/node_modules/pkg/subdir/package.json @@ -0,0 +1 @@ +{"type": "module"} diff --git a/test/unit/browser-remappings/output.js b/test/unit/browser-remappings/output.js new file mode 100644 index 00000000..9864d640 --- /dev/null +++ b/test/unit/browser-remappings/output.js @@ -0,0 +1,10 @@ +[ + "package.json", + "test/unit/browser-remappings/input.js", + "test/unit/browser-remappings/node_modules/pkg/index.js", + "test/unit/browser-remappings/node_modules/pkg/package.json", + "test/unit/browser-remappings/node_modules/pkg/require-main.cjs", + "test/unit/browser-remappings/node_modules/pkg/subdir/import-main-browser.js", + "test/unit/browser-remappings/node_modules/pkg/subdir/import-main.js", + "test/unit/browser-remappings/node_modules/pkg/subdir/package.json" +] \ No newline at end of file diff --git a/test/unit/browser-remappings/test-opts.json b/test/unit/browser-remappings/test-opts.json new file mode 100644 index 00000000..9e01628e --- /dev/null +++ b/test/unit/browser-remappings/test-opts.json @@ -0,0 +1,3 @@ +{ + "conditions": ["browser"] +}