Skip to content

Commit ce42c05

Browse files
authored
Merge pull request #642 from embroider-build/renamed-modules-support
Renamed modules support
2 parents 2a2d239 + 11dc23b commit ce42c05

File tree

7 files changed

+151
-60
lines changed

7 files changed

+151
-60
lines changed

packages/ember-auto-import/ts/auto-import.ts

+59-14
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Splitter from './splitter';
22
import { Bundler, debugBundler } from './bundler';
33
import Analyzer from './analyzer';
44
import type { TreeType } from './analyzer';
5-
import Package from './package';
5+
import Package, { V2AddonResolver } from './package';
66
import BroccoliDebug from 'broccoli-debug';
77
import BundleConfig from './bundle-config';
88
import type { Node } from 'broccoli-node-api';
@@ -12,6 +12,7 @@ import {
1212
AppInstance,
1313
findTopmostAddon,
1414
isDeepAddonInstance,
15+
PackageCache,
1516
} from '@embroider/shared-internals';
1617
import WebpackBundler from './webpack';
1718
import { Memoize } from 'typescript-memoize';
@@ -49,6 +50,7 @@ export interface AutoImportSharedAPI {
4950

5051
export default class AutoImport implements AutoImportSharedAPI {
5152
private packages: Set<Package> = new Set();
53+
private packageCache: PackageCache;
5254
private env: 'development' | 'test' | 'production';
5355
private consoleWrite: (msg: string) => void;
5456
private analyzers: Map<Analyzer, Package> = new Map();
@@ -67,7 +69,13 @@ export default class AutoImport implements AutoImportSharedAPI {
6769

6870
constructor(addonInstance: AddonInstance) {
6971
let topmostAddon = findTopmostAddon(addonInstance);
70-
this.packages.add(Package.lookupParentOf(topmostAddon));
72+
this.packageCache = PackageCache.shared(
73+
'ember-auto-import',
74+
topmostAddon.project.root
75+
);
76+
this.packages.add(
77+
Package.lookupParentOf(topmostAddon, this.v2AddonResolver)
78+
);
7179
let host = topmostAddon.app;
7280

7381
this.installAppFilter(host);
@@ -108,7 +116,7 @@ export default class AutoImport implements AutoImportSharedAPI {
108116
treeType?: TreeType,
109117
supportsFastAnalyzer?: true
110118
) {
111-
let pack = Package.lookupParentOf(addon);
119+
let pack = Package.lookupParentOf(addon, this.v2AddonResolver);
112120
this.packages.add(pack);
113121
let analyzer = new Analyzer(
114122
debugTree(tree, `preprocessor:input-${this.analyzers.size}`),
@@ -124,17 +132,55 @@ export default class AutoImport implements AutoImportSharedAPI {
124132
this.v2Addons.set(packageName, packageRoot);
125133
}
126134

127-
private makeBundler(allAppTree: Node): Bundler {
128-
// this is a concession to compatibility with ember-cli's treeForApp
129-
// merging. Addons are allowed to inject modules into the app, and it's
130-
// extremely common that those modules want to import from the addons
131-
// themselves, even though this jumps arbitrarily many levels in the
132-
// dependency graph.
133-
//
134-
// Since we handle v2 addons, we need to make sure all v2 addons function as
135-
// "dependencies" of the app even though they're not really.
136-
this.rootPackage.magicDeps = this.v2Addons;
135+
get v2AddonResolver(): V2AddonResolver {
136+
return {
137+
hasV2Addon: (name: string): boolean => {
138+
return this.v2Addons.has(name);
139+
},
140+
141+
v2AddonRoot: (name: string): string | undefined => {
142+
return this.v2Addons.get(name);
143+
},
144+
145+
handleRenaming: (name: string): string => {
146+
let hit = this.renamedModules().get(name);
147+
if (hit) {
148+
return hit;
149+
}
150+
hit = this.renamedModules().get(name + '.js');
151+
if (hit) {
152+
return hit;
153+
}
154+
hit = this.renamedModules().get(name + '/index.js');
155+
if (hit) {
156+
return hit;
157+
}
158+
return name;
159+
},
160+
};
161+
}
137162

163+
private _renamedModules: Map<string, string> | undefined;
164+
165+
private renamedModules(): Map<string, string> {
166+
if (!this._renamedModules) {
167+
this._renamedModules = new Map();
168+
for (let packageRoot of this.v2Addons.values()) {
169+
let pkg = this.packageCache.get(packageRoot);
170+
if (pkg.isV2Addon()) {
171+
let renamedModules = pkg.meta['renamed-modules'];
172+
if (renamedModules) {
173+
for (let [from, to] of Object.entries(renamedModules)) {
174+
this._renamedModules.set(from, to);
175+
}
176+
}
177+
}
178+
}
179+
}
180+
return this._renamedModules;
181+
}
182+
183+
private makeBundler(allAppTree: Node): Bundler {
138184
// The Splitter takes the set of imports from the Analyzer and
139185
// decides which ones to include in which bundles
140186
let splitter = new Splitter({
@@ -166,7 +212,6 @@ export default class AutoImport implements AutoImportSharedAPI {
166212
consoleWrite: this.consoleWrite,
167213
bundles: this.bundles,
168214
webpack,
169-
v2Addons: this.v2Addons,
170215
rootPackage: this.rootPackage,
171216
});
172217
}

packages/ember-auto-import/ts/bundler.ts

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ export interface BundlerOptions {
1515
packages: Set<Package>;
1616
bundles: BundleConfig;
1717
webpack: typeof webpack;
18-
v2Addons: Map<string, string>;
1918
rootPackage: Package;
2019
}
2120

packages/ember-auto-import/ts/package.ts

+21-16
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ export interface Options {
4646

4747
export interface DepResolution {
4848
type: 'package';
49-
path: string;
5049
packageName: string;
5150
packageRoot: string;
51+
resolvedSpecifier: string;
5252
}
5353

5454
interface LocalResolution {
@@ -71,6 +71,12 @@ type Resolution =
7171
| URLResolution
7272
| ImpreciseResolution;
7373

74+
export type V2AddonResolver = {
75+
hasV2Addon(name: string): boolean;
76+
v2AddonRoot(name: string): string | undefined;
77+
handleRenaming(name: string): string;
78+
};
79+
7480
export default class Package {
7581
public name: string;
7682
public root: string;
@@ -87,21 +93,26 @@ export default class Package {
8793
private pkgGeneration: number;
8894
private pkgCache: any;
8995
private macrosConfig: MacrosConfig | undefined;
96+
private extraResolve: V2AddonResolver;
9097

91-
static lookupParentOf(child: AddonInstance): Package {
98+
static lookupParentOf(
99+
child: AddonInstance,
100+
extraResolve: V2AddonResolver
101+
): Package {
92102
if (!parentCache.has(child)) {
93103
let pkg = packageCache.get(child.parent);
94104
if (!pkg) {
95-
pkg = new this(child);
105+
pkg = new this(child, extraResolve);
96106
packageCache.set(child.parent, pkg);
97107
}
98108
parentCache.set(child, pkg);
99109
}
100110
return parentCache.get(child)!;
101111
}
102112

103-
constructor(child: AddonInstance) {
113+
constructor(child: AddonInstance, extraResolve: V2AddonResolver) {
104114
this.name = child.parent.pkg.name;
115+
this.extraResolve = extraResolve;
105116

106117
if (isDeepAddonInstance(child)) {
107118
this.root = this.pkgRoot = child.parent.root;
@@ -233,19 +244,13 @@ export default class Package {
233244
return `${this.name}/${this.isAddon ? 'addon' : 'app'}`;
234245
}
235246

236-
// extra dependencies that must be treated as if they were really dependencies
237-
// of this package. sigh.
238-
//
239-
// maps from packageName to packageRoot
240-
magicDeps: Map<string, string> | undefined;
241-
242247
hasDependency(name: string): boolean {
243248
let { pkg } = this;
244249
return Boolean(
245250
pkg.dependencies?.[name] ||
246251
pkg.devDependencies?.[name] ||
247252
pkg.peerDependencies?.[name] ||
248-
this.magicDeps?.get(name)
253+
this.extraResolve.hasV2Addon(name)
249254
);
250255
}
251256

@@ -269,7 +274,7 @@ export default class Package {
269274
return Boolean(
270275
pkg.dependencies?.[name] ||
271276
pkg.peerDependencies?.[name] ||
272-
this.magicDeps?.has(name)
277+
this.extraResolve.hasV2Addon(name)
273278
);
274279
}
275280

@@ -319,7 +324,7 @@ export default class Package {
319324
break;
320325
}
321326

322-
let path = this.aliasFor(importedPath);
327+
let path = this.extraResolve.handleRenaming(this.aliasFor(importedPath));
323328
let packageName = getPackageName(path);
324329
if (!packageName) {
325330
// this can only happen if the user supplied an alias that points at a
@@ -344,9 +349,9 @@ export default class Package {
344349
) {
345350
return {
346351
type: 'package',
347-
path: localPath,
348352
packageName: this.name,
349353
packageRoot: join(this.root, 'app'),
354+
resolvedSpecifier: path,
350355
};
351356
}
352357
}
@@ -368,7 +373,7 @@ export default class Package {
368373
}
369374

370375
if (!packageRoot) {
371-
packageRoot = this.magicDeps?.get(packageName);
376+
packageRoot = this.extraResolve.v2AddonRoot(packageName);
372377
}
373378

374379
if (packageRoot == null) {
@@ -384,9 +389,9 @@ export default class Package {
384389
this.assertAllowedDependency(packageName, fromPath);
385390
return {
386391
type: 'package',
387-
path,
388392
packageName,
389393
packageRoot,
394+
resolvedSpecifier: path,
390395
};
391396
}
392397

packages/ember-auto-import/ts/splitter.ts

+10-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import { satisfies } from 'semver';
1010
const debug = makeDebug('ember-auto-import:splitter');
1111

1212
export interface ResolvedImport {
13-
specifier: string;
13+
requestedSpecifier: string;
14+
resolvedSpecifier: string;
1415
packageName: string;
1516
packageRoot: string;
1617
importedBy: LiteralImport[];
@@ -115,7 +116,8 @@ export default class Splitter {
115116
seenAlready.importedBy.push(imp);
116117
} else {
117118
targets.set(imp.specifier, {
118-
specifier: imp.specifier,
119+
requestedSpecifier: imp.specifier,
120+
resolvedSpecifier: target.resolvedSpecifier,
119121
packageName: target.packageName,
120122
packageRoot: target.packageRoot,
121123
importedBy: [imp],
@@ -284,9 +286,11 @@ export default class Splitter {
284286
}
285287

286288
private sortBundle(bundle: BundleDependencies) {
287-
bundle.staticImports.sort((a, b) => a.specifier.localeCompare(b.specifier));
289+
bundle.staticImports.sort((a, b) =>
290+
a.requestedSpecifier.localeCompare(b.requestedSpecifier)
291+
);
288292
bundle.dynamicImports.sort((a, b) =>
289-
a.specifier.localeCompare(b.specifier)
293+
a.requestedSpecifier.localeCompare(b.requestedSpecifier)
290294
);
291295
bundle.dynamicTemplateImports.sort((a, b) =>
292296
a.cookedQuasis[0].localeCompare(b.cookedQuasis[0])
@@ -329,7 +333,8 @@ class LazyPrintDeps {
329333

330334
private describeResolvedImport(imp: ResolvedImport) {
331335
return {
332-
specifier: imp.specifier,
336+
requestedSpecifier: imp.requestedSpecifier,
337+
resolvedSpecifier: imp.resolvedSpecifier,
333338
packageRoot: imp.packageRoot,
334339
importedBy: imp.importedBy.map(this.describeImport.bind(this)),
335340
};

0 commit comments

Comments
 (0)