From b63345b74b31b1b7dcb3701b7f49005b43adbeb6 Mon Sep 17 00:00:00 2001 From: Pedro Yamada Date: Thu, 6 Feb 2025 09:31:58 +1100 Subject: [PATCH] Add 'IdentifierRegistry' mechanism for debugging IDs Whenever an ID is generated, we will optionally log it to a file with the data used to generate it. This will help us debug generated identifiers on artefacts or runtime errors. Test Plan: N/A Pull Request: https://github.com/atlassian-labs/atlaspack/pull/333 --- packages/core/core/src/Dependency.js | 5 +++- packages/core/core/src/Environment.js | 8 +++-- packages/core/core/src/IdentifierRegistry.js | 20 +++++++++++++ packages/core/core/src/assetUtils.js | 8 +++-- .../core/src/public/MutableBundleGraph.js | 30 +++++++++++++++---- 5 files changed, 60 insertions(+), 11 deletions(-) create mode 100644 packages/core/core/src/IdentifierRegistry.js diff --git a/packages/core/core/src/Dependency.js b/packages/core/core/src/Dependency.js index 7650efadb..e65277aeb 100644 --- a/packages/core/core/src/Dependency.js +++ b/packages/core/core/src/Dependency.js @@ -20,6 +20,7 @@ import { import {toInternalSourceLocation} from './utils'; import {toProjectPath} from './projectPath'; import assert from 'assert'; +import {identifierRegistry} from './IdentifierRegistry'; type DependencyOpts = {| id?: string, @@ -80,7 +81,9 @@ export function createDependencyId({ priority: priority ? Priority[priority] : Priority.sync, packageConditions, }; - return createDependencyIdRust(params); + const id = createDependencyIdRust(params); + identifierRegistry.addIdentifier('dependency', id, params); + return id; } export function createDependency( diff --git a/packages/core/core/src/Environment.js b/packages/core/core/src/Environment.js index b612c2671..0d430c826 100644 --- a/packages/core/core/src/Environment.js +++ b/packages/core/core/src/Environment.js @@ -9,6 +9,7 @@ import {createEnvironmentId} from '@atlaspack/rust'; import {toInternalSourceLocation} from './utils'; import PublicEnvironment from './public/Environment'; import {environmentToInternalEnvironment} from './public/Environment'; +import {identifierRegistry} from './IdentifierRegistry'; const DEFAULT_ENGINES = { browsers: ['> 0.25%'], @@ -137,7 +138,7 @@ export function mergeEnvironments( } function getEnvironmentHash(env: Environment): string { - return createEnvironmentId({ + const data = { context: env.context, engines: env.engines, includeNodeModules: env.includeNodeModules, @@ -147,5 +148,8 @@ function getEnvironmentHash(env: Environment): string { shouldOptimize: env.shouldOptimize, shouldScopeHoist: env.shouldScopeHoist, sourceMap: env.sourceMap, - }); + }; + const id = createEnvironmentId(data); + identifierRegistry.addIdentifier('environment', id, data); + return id; } diff --git a/packages/core/core/src/IdentifierRegistry.js b/packages/core/core/src/IdentifierRegistry.js new file mode 100644 index 000000000..e48c5dde8 --- /dev/null +++ b/packages/core/core/src/IdentifierRegistry.js @@ -0,0 +1,20 @@ +// @flow strict-local + +import fs from 'fs'; + +export class IdentifierRegistry { + constructor() {} + + addIdentifier(type: string, identifier: string, data: mixed) { + if (process.env.ATLASPACK_IDENTIFIER_DEBUG === 'true') { + fs.appendFile( + './atlaspack-identifiers.txt', + // $FlowFixMe + `${type} ${identifier} ${JSON.stringify(data)}\n`, + () => {}, + ); + } + } +} + +export const identifierRegistry: IdentifierRegistry = new IdentifierRegistry(); diff --git a/packages/core/core/src/assetUtils.js b/packages/core/core/src/assetUtils.js index e828ec277..ff6d08a91 100644 --- a/packages/core/core/src/assetUtils.js +++ b/packages/core/core/src/assetUtils.js @@ -39,6 +39,7 @@ import { import {hashString, createAssetId as createAssetIdRust} from '@atlaspack/rust'; import {BundleBehavior as BundleBehaviorMap} from './types'; import {PluginTracer} from '@atlaspack/profiler'; +import {identifierRegistry} from './IdentifierRegistry'; export type AssetOptions = {| id?: string, @@ -69,7 +70,7 @@ export type AssetOptions = {| |}; export function createAssetIdFromOptions(options: AssetOptions): string { - return createAssetIdRust({ + const data = { environmentId: options.env.id, filePath: options.filePath, code: options.code, @@ -77,7 +78,10 @@ export function createAssetIdFromOptions(options: AssetOptions): string { query: options.query, uniqueKey: options.uniqueKey, fileType: options.type, - }); + }; + const id = createAssetIdRust(data); + identifierRegistry.addIdentifier('asset', id, data); + return id; } export function createAsset( diff --git a/packages/core/core/src/public/MutableBundleGraph.js b/packages/core/core/src/public/MutableBundleGraph.js index 913fd0397..a04ed4471 100644 --- a/packages/core/core/src/public/MutableBundleGraph.js +++ b/packages/core/core/src/public/MutableBundleGraph.js @@ -30,6 +30,24 @@ import {HASH_REF_PREFIX} from '../constants'; import {fromProjectPathRelative} from '../projectPath'; import {BundleBehavior} from '../types'; import BundleGroup, {bundleGroupToInternalBundleGroup} from './BundleGroup'; +import type {ProjectPath} from '../projectPath'; +import {identifierRegistry} from '../IdentifierRegistry'; + +function createBundleId(data: {| + entryAssetId: string | null, + uniqueKey: string | null, + distDir: ProjectPath, + bundleBehavior: string | null, +|}): string { + const {entryAssetId, uniqueKey, distDir, bundleBehavior} = data; + const id = hashString( + `bundle:${String( + entryAssetId != null ? entryAssetId : uniqueKey, + )}${fromProjectPathRelative(distDir)}${bundleBehavior ?? ''}`, + ); + identifierRegistry.addIdentifier('bundle', id, data); + return id; +} export default class MutableBundleGraph extends BundleGraph @@ -181,12 +199,12 @@ export default class MutableBundleGraph : null; let target = targetToInternalTarget(opts.target); - let bundleId = hashString( - 'bundle:' + - (opts.entryAsset ? opts.entryAsset.id : opts.uniqueKey) + - fromProjectPathRelative(target.distDir) + - (opts.bundleBehavior ?? ''), - ); + let bundleId = createBundleId({ + entryAssetId: entryAsset?.id ?? null, + uniqueKey: opts.uniqueKey ?? null, + distDir: target.distDir, + bundleBehavior: opts.bundleBehavior ?? null, + }); let existing = this.#graph._graph.getNodeByContentKey(bundleId); if (existing != null) {