From f747a3b6c8ad280bfde177c7eb524cf5cce9373b Mon Sep 17 00:00:00 2001 From: Edward Faulkner Date: Thu, 20 Jun 2024 08:15:25 -0400 Subject: [PATCH] MacrosConfig should sync globalConfigs between copies It's a bug that most of the MacrosConfig state is synchronized between copies of @embroider/macros but the globalConfigs object is not. --- packages/macros/src/macros-config.ts | 43 +++++++++++++++++----------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/packages/macros/src/macros-config.ts b/packages/macros/src/macros-config.ts index 843a6a6d1..641b2eb6c 100644 --- a/packages/macros/src/macros-config.ts +++ b/packages/macros/src/macros-config.ts @@ -22,16 +22,16 @@ export type Merger = ( } ) => object; +interface GlobalSharedEntry { + configs: Map; + globalConfigs: Record; + configSources: WeakMap; + mergers: Map; +} + // Do not change this type signature without pondering deeply the mysteries of // being compatible with unwritten future versions of this library. -type GlobalSharedState = WeakMap< - any, - { - configs: Map; - configSources: WeakMap; - mergers: Map; - } ->; +type GlobalSharedState = WeakMap; // this is a module-scoped cache. If multiple callers ask _this copy_ of // @embroider/macros for a shared MacrosConfig, they'll all get the same one. @@ -93,25 +93,29 @@ export default class MacrosConfig { if (!shared.configSources) { shared.configSources = new WeakMap(); } + + // earlier versions did not include this -- we may need to upgrade the + // format here + if (!shared.globalConfigs) { + shared.globalConfigs = {}; + } } else { shared = { configs: new Map(), + globalConfigs: {}, configSources: new WeakMap(), mergers: new Map(), }; g.__embroider_macros_global__.set(key, shared); } - let config = new MacrosConfig(appRoot); - config.configs = shared.configs; - config.configSources = shared.configSources; - config.mergers = shared.mergers; + let config = new MacrosConfig(appRoot, shared); localSharedState.set(key, config); return config; } private mode: 'compile-time' | 'run-time' = 'compile-time'; - private globalConfig: { [key: string]: unknown } = {}; + private globalConfig: { [key: string]: unknown }; private isDevelopingPackageRoots: Set = new Set(); @@ -150,7 +154,12 @@ export default class MacrosConfig { this._importSyncImplementation = value; } - private constructor(private origAppRoot: string) { + private constructor(private origAppRoot: string, shared: GlobalSharedEntry) { + this.configs = shared.configs; + this.globalConfig = shared.globalConfigs; + this.configSources = shared.configSources; + this.mergers = shared.mergers; + // this uses globalConfig because these things truly are global. Even if a // package doesn't have a dep or peerDep on @embroider/macros, it's legit // for them to want to know the answer to these questions, and there is only @@ -179,9 +188,9 @@ export default class MacrosConfig { } private _configWritable = true; - private configs: Map = new Map(); - private configSources: WeakMap = new WeakMap(); - private mergers: Map = new Map(); + private configs: Map; + private configSources: WeakMap; + private mergers: Map; // Registers a new source of configuration to be given to the named package. // Your config type must be json-serializable. You must always set fromPath to