Skip to content

Commit

Permalink
Merge pull request #1373 from embroider-build/app-tree-resolving2
Browse files Browse the repository at this point in the history
app tree resolving
  • Loading branch information
ef4 authored Mar 14, 2023
2 parents f04ae3d + d885fd0 commit 936fd63
Show file tree
Hide file tree
Showing 26 changed files with 772 additions and 270 deletions.
4 changes: 3 additions & 1 deletion packages/compat/src/audit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,9 @@ export class AuditResults {
}))
: [],
exports: module.linked?.exports ? [...module.linked.exports] : [],
content: module.parsed?.transpiledContent ? module.parsed?.transpiledContent.toString() : '',
content: module.parsed?.transpiledContent
? module.parsed?.transpiledContent.toString()
: 'module failed to transpile',
};
results.modules[explicitRelative(baseDir, filename)] = publicModule;
}
Expand Down
22 changes: 16 additions & 6 deletions packages/compat/src/babel-plugin-adjust-imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { readJSONSync } from 'fs-extra';
import { CompatResolverOptions } from './resolver-transform';
import { Package, packageName, Resolver, unrelativize } from '@embroider/core';
import { snippetToDasherizedName } from './dasherize-component-name';
import { ActivePackageRules, ComponentRules, ModuleRules, TemplateRules } from './dependency-rules';
import { ActivePackageRules, appTreeRulesDir, ComponentRules, ModuleRules, TemplateRules } from './dependency-rules';

export type Options = { appRoot: string };

Expand Down Expand Up @@ -43,10 +43,11 @@ export default function main(babel: typeof Babel) {
return cached;
}
let resolverOptions: CompatResolverOptions = readJSONSync(join(appRoot, '.embroider', 'resolver.json'));
let resolver = new Resolver(resolverOptions);
cached = {
resolverOptions,
resolver: new Resolver(resolverOptions),
extraImports: preprocessExtraImports(resolverOptions),
resolver,
extraImports: preprocessExtraImports(resolverOptions, resolver),
componentExtraImports: preprocessComponentExtraImports(resolverOptions),
};
return cached;
Expand Down Expand Up @@ -133,7 +134,7 @@ function amdDefine(t: BabelTypes, adder: ImportUtil, path: NodePath<t.Program>,
);
}

function preprocessExtraImports(config: CompatResolverOptions): ExtraImports {
function preprocessExtraImports(config: CompatResolverOptions, resolver: Resolver): ExtraImports {
let extraImports: ExtraImports = {};
for (let rule of config.activePackageRules) {
if (rule.addonModules) {
Expand All @@ -145,7 +146,14 @@ function preprocessExtraImports(config: CompatResolverOptions): ExtraImports {
}
if (rule.appModules) {
for (let [filename, moduleRules] of Object.entries(rule.appModules)) {
expandDependsOnRules(config.appRoot, filename, moduleRules, extraImports);
for (let root of rule.roots) {
// in general v2 addons can keep their app tree stuff in other places
// than "_app_" and we would need to check their package.json to see.
// But this code is only for applying packageRules to auto-upgraded v1
// addons, and those we always organize with their treeForApp output
// in _app_.
expandDependsOnRules(appTreeRulesDir(root, resolver), filename, moduleRules, extraImports);
}
}
}
if (rule.addonTemplates) {
Expand All @@ -157,7 +165,9 @@ function preprocessExtraImports(config: CompatResolverOptions): ExtraImports {
}
if (rule.appTemplates) {
for (let [filename, moduleRules] of Object.entries(rule.appTemplates)) {
expandInvokesRules(config.appRoot, filename, moduleRules, extraImports);
for (let root of rule.roots) {
expandInvokesRules(appTreeRulesDir(root, resolver), filename, moduleRules, extraImports);
}
}
}
}
Expand Down
14 changes: 3 additions & 11 deletions packages/compat/src/compat-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ class CompatAppAdapter implements AppAdapter<TreeNames, CompatResolverOptions> {
@Memoize()
private activeRules() {
return activePackageRules(this.options.packageRules.concat(defaultAddonPackageRules()), [
this.appPackage,
{ name: this.appPackage.name, version: this.appPackage.version, root: this.root },
...this.allActiveAddons.filter(p => p.meta['auto-upgraded']),
]);
}
Expand Down Expand Up @@ -354,24 +354,16 @@ class CompatAppAdapter implements AppAdapter<TreeNames, CompatResolverOptions> {
activeAddons[addon.name] = addon.root;
}

let relocatedFiles: CompatResolverOptions['relocatedFiles'] = {};
for (let { destPath, appFiles } of engines) {
for (let [relativePath, originalPath] of appFiles.relocatedFiles) {
relocatedFiles[join(destPath, relativePath)] = originalPath;
}
}

let config: CompatResolverOptions = {
// this part is the base ModuleResolverOptions as required by @embroider/core
activeAddons,
renameModules,
renamePackages,
relocatedFiles,
resolvableExtensions: this.resolvableExtensions(),
appRoot: this.root,
engines: engines.map(engine => ({
engines: engines.map((engine, index) => ({
packageName: engine.package.name,
root: this.root,
root: index === 0 ? this.root : engine.package.root, // first engine is the app, which has been relocated to this.roto
activeAddons: [...engine.addons]
.map(a => ({
name: a.name,
Expand Down
22 changes: 20 additions & 2 deletions packages/compat/src/dependency-rules.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Package, getOrCreate } from '@embroider/core';
import { getOrCreate, Resolver } from '@embroider/core';
import { resolve } from 'path';
import { satisfies } from 'semver';

export interface PackageRules {
Expand Down Expand Up @@ -205,7 +206,10 @@ export function preprocessComponentRule(componentRules: ComponentRules): Preproc
};
}

export function activePackageRules(packageRules: PackageRules[], activePackages: Package[]): ActivePackageRules[] {
export function activePackageRules(
packageRules: PackageRules[],
activePackages: { name: string; root: string; version: string }[]
): ActivePackageRules[] {
// rule order implies precedence. The first rule that matches a given package
// applies to that package, and no other rule does.
let rootsPerRule = new Map();
Expand All @@ -224,3 +228,17 @@ export function activePackageRules(packageRules: PackageRules[], activePackages:
}
return output;
}

export function appTreeRulesDir(root: string, resolver: Resolver) {
let pkg = resolver.owningPackage(root);
if (pkg?.isV2Addon()) {
// in general v2 addons can keep their app tree stuff in other places than
// "_app_" and we would need to check their package.json to see. But this code
// is only for applying packageRules to auto-upgraded v1 addons and apps, and
// those we always organize predictably.
return resolve(root, '_app_');
} else {
// auto-upgraded apps don't get an exist _app_ dir.
return root;
}
}
5 changes: 4 additions & 1 deletion packages/compat/src/resolver-transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ComponentRules,
PackageRules,
ModuleRules,
appTreeRulesDir,
} from './dependency-rules';
import { Memoize } from 'typescript-memoize';
import type { WithJSUtils } from 'babel-plugin-ember-template-compilation';
Expand Down Expand Up @@ -323,7 +324,9 @@ class TemplateResolver implements ASTPlugin {
if (rule.appTemplates) {
for (let [path, templateRules] of Object.entries(rule.appTemplates)) {
let processedRules = preprocessComponentRule(templateRules);
files.set(join(this.config.appRoot, path), processedRules);
for (let root of rule.roots) {
files.set(join(appTreeRulesDir(root, this.moduleResolver), path), processedRules);
}
}
}
if (rule.addonTemplates) {
Expand Down
1 change: 0 additions & 1 deletion packages/compat/tests/audit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ describe('audit', function () {
root: app.baseDir,
},
],
relocatedFiles: {},
resolvableExtensions,
};

Expand Down
48 changes: 24 additions & 24 deletions packages/core/src/app-differ.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,8 @@ export default class AppDiffer {
private sources: Source[];
private firstFastbootTree = Infinity;

// maps from each filename in the app to the original directory from whence it
// came, if it came from an addon. The mapping allows us to preserve
// resolution semantics so that each of the app files can still resolve
// relative to where it was authored.
//
// files authored within the app map to null
readonly files: Map<string, string | null> = new Map();
// set of filenames logically located in the app
readonly files: Set<string> = new Set();

// true for files that are fastboot-only.
isFastbootOnly: Map<string, boolean> = new Map();
Expand Down Expand Up @@ -107,8 +102,10 @@ export default class AppDiffer {
this.isFastbootOnly.set(relativePath, sourceIndices[0] >= this.firstFastbootTree);
let source = this.sources[sourceIndices[0]];
let sourceFile = source.locate(relativePath);
copySync(sourceFile, outputPath, { dereference: true });
this.updateFiles(relativePath, source, sourceFile);
if (!source.isRelocated) {
copySync(sourceFile, outputPath, { dereference: true });
}
this.updateFiles(relativePath);
} else {
// we have both fastboot and non-fastboot files for this path.
// Because of the way fastbootMerge is written, the first one is the
Expand All @@ -122,13 +119,15 @@ export default class AppDiffer {
let base = basename(relativePath);
let browserDest = `_browser_${base}`;
let fastbootDest = `_fastboot_${base}`;
copySync(browserSourceFile, join(this.outputPath, dir, browserDest), { dereference: true });
copySync(fastbootSourceFile, join(this.outputPath, dir, fastbootDest), { dereference: true });
writeFileSync(
outputPath,
switcher(browserDest, fastbootDest, this.babelParserConfig!, readFileSync(browserSourceFile, 'utf8'))
);
this.updateFiles(relativePath, browserSrc, browserSourceFile);
if (!browserSrc.isRelocated && !fastbootSrc.isRelocated) {
copySync(browserSourceFile, join(this.outputPath, dir, browserDest), { dereference: true });
copySync(fastbootSourceFile, join(this.outputPath, dir, fastbootDest), { dereference: true });
writeFileSync(
outputPath,
switcher(browserDest, fastbootDest, this.babelParserConfig!, readFileSync(browserSourceFile, 'utf8'))
);
}
this.updateFiles(relativePath);
}
break;
default:
Expand All @@ -137,12 +136,8 @@ export default class AppDiffer {
}
}

private updateFiles(relativePath: string, source: Source, sourceFile: string) {
if (source.isRelocated) {
this.files.set(relativePath, sourceFile);
} else {
this.files.set(relativePath, null);
}
private updateFiles(relativePath: string) {
this.files.add(relativePath);
}
}

Expand Down Expand Up @@ -194,8 +189,13 @@ function switcher(
babelParserConfig: TransformOptions,
browserSource: string
): string {
let { names, hasDefaultExport } = describeExports(browserSource, babelParserConfig);
return switcherTemplate({ fastbootDest, browserDest, names: [...names], hasDefaultExport });
let { names } = describeExports(browserSource, babelParserConfig);
return switcherTemplate({
fastbootDest,
browserDest,
names: [...names].filter(name => name !== 'default'),
hasDefaultExport: names.has('default'),
});
}

interface Source extends InputTree {
Expand Down
9 changes: 0 additions & 9 deletions packages/core/src/app-files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export class AppFiles {
readonly modifiers: ReadonlyArray<string>;
private perRoute: RouteFiles;
readonly otherAppFiles: ReadonlyArray<string>;
readonly relocatedFiles: Map<string, string>;
readonly isFastbootOnly: Map<string, boolean>;

constructor(appDiffer: AppDiffer, resolvableExtensions: RegExp, podModulePrefix?: string) {
Expand Down Expand Up @@ -83,14 +82,6 @@ export class AppFiles {
this.helpers = helpers;
this.modifiers = modifiers;
this.otherAppFiles = otherAppFiles;

let relocatedFiles: Map<string, string> = new Map();
for (let [relativePath, owningPath] of appDiffer.files) {
if (owningPath) {
relocatedFiles.set(relativePath, owningPath);
}
}
this.relocatedFiles = relocatedFiles;
this.isFastbootOnly = appDiffer.isFastbootOnly;
}

Expand Down
29 changes: 12 additions & 17 deletions packages/core/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { compile } from './js-handlebars';
import resolve from 'resolve';
import { Memoize } from 'typescript-memoize';
import { copySync, ensureDirSync, outputJSONSync, readJSONSync, statSync, unlinkSync, writeFileSync } from 'fs-extra';
import { dirname, join, resolve as resolvePath, sep } from 'path';
import { dirname, join, resolve as resolvePath, sep, posix } from 'path';
import { debug, warn } from './messages';
import sortBy from 'lodash/sortBy';
import flatten from 'lodash/flatten';
Expand Down Expand Up @@ -1183,7 +1183,7 @@ export class AppBuilder<TreeNames> {
}
lazyRoutes.push({
names: routeNames,
path: this.importPaths(engine, routeEntrypoint, relativePath).buildtime,
path: this.importPaths(engine, routeEntrypoint).buildtime,
});
}
);
Expand All @@ -1192,12 +1192,12 @@ export class AppBuilder<TreeNames> {
let [fastboot, nonFastboot] = partition(excludeDotFiles(flatten(requiredAppFiles)), file =>
appFiles.isFastbootOnly.get(file)
);
let amdModules = nonFastboot.map(file => this.importPaths(engine, file, relativePath));
let fastbootOnlyAmdModules = fastboot.map(file => this.importPaths(engine, file, relativePath));
let amdModules = nonFastboot.map(file => this.importPaths(engine, file));
let fastbootOnlyAmdModules = fastboot.map(file => this.importPaths(engine, file));

// this is a backward-compatibility feature: addons can force inclusion of
// modules.
this.gatherImplicitModules('implicit-modules', relativePath, engine, amdModules);
this.gatherImplicitModules('implicit-modules', engine, amdModules);

let params = { amdModules, fastbootOnlyAmdModules, lazyRoutes, lazyEngines, eagerModules, styles };
if (entryParams) {
Expand All @@ -1220,12 +1220,11 @@ export class AppBuilder<TreeNames> {
return this.adapter.modulePrefix();
}

private importPaths(engine: Engine, engineRelativePath: string, fromFile: string) {
let appRelativePath = join(engine.appRelativePath, engineRelativePath);
private importPaths(engine: Engine, engineRelativePath: string) {
let noHBS = engineRelativePath.replace(this.resolvableExtensionsPattern, '').replace(/\.hbs$/, '');
return {
runtime: `${engine.modulePrefix}/${noHBS}`,
buildtime: explicitRelative(dirname(fromFile), appRelativePath),
buildtime: posix.join(engine.package.name, engineRelativePath),
};
}

Expand All @@ -1235,8 +1234,8 @@ export class AppBuilder<TreeNames> {
let asset: InternalAsset = {
kind: 'in-memory',
source: routeEntryTemplate({
files: nonFastboot.map(f => this.importPaths(engine, f, relativePath)),
fastbootOnlyFiles: fastboot.map(f => this.importPaths(engine, f, relativePath)),
files: nonFastboot.map(f => this.importPaths(engine, f)),
fastbootOnlyFiles: fastboot.map(f => this.importPaths(engine, f)),
}),
relativePath,
};
Expand Down Expand Up @@ -1268,11 +1267,11 @@ export class AppBuilder<TreeNames> {
let amdModules: { runtime: string; buildtime: string }[] = [];
// this is a backward-compatibility feature: addons can force inclusion of
// test support modules.
this.gatherImplicitModules('implicit-test-modules', myName, engine, amdModules);
this.gatherImplicitModules('implicit-test-modules', engine, amdModules);

let { appFiles } = engine;
for (let relativePath of appFiles.tests) {
amdModules.push(this.importPaths(engine, relativePath, myName));
amdModules.push(this.importPaths(engine, relativePath));
}

let source = entryTemplate({
Expand All @@ -1292,7 +1291,6 @@ export class AppBuilder<TreeNames> {

private gatherImplicitModules(
section: 'implicit-modules' | 'implicit-test-modules',
relativeTo: string,
engine: Engine,
lazyModules: { runtime: string; buildtime: string }[]
) {
Expand Down Expand Up @@ -1322,10 +1320,7 @@ export class AppBuilder<TreeNames> {
runtime = runtime.split(sep).join('/');
lazyModules.push({
runtime,
buildtime:
this.options.implicitModulesStrategy === 'packageNames'
? join(packageName, name)
: explicitRelative(dirname(join(this.root, relativeTo)), join(addon.root, name)),
buildtime: posix.join(packageName, name),
});
}
}
Expand Down
Loading

0 comments on commit 936fd63

Please sign in to comment.