Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deflate AdjustImportsOptions #907

Merged
merged 1 commit into from
Jul 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions packages/compat/src/compat-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import walkSync from 'walk-sync';
import { join } from 'path';
import { JSDOM } from 'jsdom';
import { V1Config } from './v1-config';
import { statSync, readdirSync } from 'fs';
import { statSync, readdirSync, writeFileSync } from 'fs';
import Options, { optionsWithDefaults } from './options';
import CompatResolver from './resolver';
import { activePackageRules, PackageRules, expandModuleRules } from './dependency-rules';
Expand All @@ -36,6 +36,7 @@ import { pathExistsSync } from 'fs-extra';
import { tmpdir } from '@embroider/shared-internals';
import { Options as AdjustImportsOptions } from '@embroider/core/src/babel-plugin-adjust-imports';
import { getEmberExports } from '@embroider/core/src/load-ember-template-compiler';

import semver from 'semver';

interface TreeNames {
Expand Down Expand Up @@ -337,15 +338,23 @@ class CompatAppAdapter implements AppAdapter<TreeNames> {
podModulePrefix: this.podModulePrefix(),
options: this.options,
activePackageRules: this.activeRules(),
adjustImportsOptions: this.adjustImportsOptions(),
adjustImportsOptionsFile: this.adjustImportsOptionsFile(),
});
}

@Memoize()
adjustImportsOptionsFile(): string {
let file = join(this.root, '_adjust_imports.json');
writeFileSync(file, JSON.stringify(this.adjustImportsOptions()));
return file;
}

@Memoize()
adjustImportsOptions(): AdjustImportsOptions {
return this.makeAdjustImportOptions(true);
}

// this gets serialized out by babel plugin and ast plugin
private makeAdjustImportOptions(outer: boolean): AdjustImportsOptions {
let renamePackages = Object.assign({}, ...this.allActiveAddons.map(dep => dep.meta['renamed-packages']));
let renameModules = Object.assign({}, ...this.allActiveAddons.map(dep => dep.meta['renamed-modules']));
Expand Down
39 changes: 26 additions & 13 deletions packages/compat/src/resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import Options from './options';
import { ResolvedDep } from '@embroider/core/src/resolver';
import { dasherize } from './dasherize-component-name';
import { makeResolverTransform } from './resolver-transform';
import { pathExistsSync } from 'fs-extra';
import { pathExistsSync, readFileSync } from 'fs-extra';
import resolve from 'resolve';

export interface ComponentResolution {
Expand Down Expand Up @@ -110,15 +110,24 @@ function extractOptions(options: Required<Options> | ResolverOptions): ResolverO
};
}

interface RehydrationParams {
interface RehydrationParamsBase {
root: string;
modulePrefix: string;
podModulePrefix?: string;
options: ResolverOptions;
activePackageRules: ActivePackageRules[];
}

interface RehydrationParamsWithFile extends RehydrationParamsBase {
adjustImportsOptionsFile: string;
}

interface RehydrationParamsWithOptions extends RehydrationParamsBase {
adjustImportsOptions: AdjustImportsOptions;
}

type RehydrationParams = RehydrationParamsWithFile | RehydrationParamsWithOptions;

export function rehydrate(params: RehydrationParams) {
return new CompatResolver(params);
}
Expand Down Expand Up @@ -173,7 +182,7 @@ export default class CompatResolver implements Resolver {
// "inherit" the rules that are attached to their corresonding JS module.
if (absPath.endsWith('.hbs')) {
let stem = absPath.slice(0, -4);
for (let ext of this.params.adjustImportsOptions.resolvableExtensions) {
for (let ext of this.adjustImportsOptions.resolvableExtensions) {
if (ext !== '.hbs') {
let rules = this.rules.components.get(stem + ext);
if (rules) {
Expand All @@ -189,6 +198,14 @@ export default class CompatResolver implements Resolver {
return this.rules.ignoredComponents.includes(dasherizedName);
}

@Memoize()
get adjustImportsOptions(): AdjustImportsOptions {
const { params } = this;
return 'adjustImportsOptionsFile' in params
? JSON.parse(readFileSync(params.adjustImportsOptionsFile, 'utf8'))
: params.adjustImportsOptions;
}

@Memoize()
private get rules() {
if (!this.templateCompiler) {
Expand Down Expand Up @@ -357,7 +374,7 @@ export default class CompatResolver implements Resolver {
try {
absPath = resolve.sync(path, {
basedir: dirname(from),
extensions: this.params.adjustImportsOptions.resolvableExtensions,
extensions: this.adjustImportsOptions.resolvableExtensions,
});
} catch (err) {
return;
Expand All @@ -372,14 +389,14 @@ export default class CompatResolver implements Resolver {

@Memoize()
private get resolvableExtensionsPattern() {
return extensionsPattern(this.params.adjustImportsOptions.resolvableExtensions);
return extensionsPattern(this.adjustImportsOptions.resolvableExtensions);
}

absPathToRuntimePath(absPath: string, owningPackage?: { root: string; name: string }) {
let pkg = owningPackage || PackageCache.shared('embroider-stage3').ownerOfFile(absPath);
if (pkg) {
let packageRuntimeName = pkg.name;
for (let [runtimeName, realName] of Object.entries(this.params.adjustImportsOptions.renamePackages)) {
for (let [runtimeName, realName] of Object.entries(this.adjustImportsOptions.renamePackages)) {
if (realName === packageRuntimeName) {
packageRuntimeName = runtimeName;
break;
Expand Down Expand Up @@ -408,7 +425,7 @@ export default class CompatResolver implements Resolver {
}

private tryHelper(path: string, from: string): Resolution | null {
for (let extension of this.params.adjustImportsOptions.resolvableExtensions) {
for (let extension of this.adjustImportsOptions.resolvableExtensions) {
let absPath = join(this.params.root, 'helpers', path) + extension;
if (pathExistsSync(absPath)) {
return {
Expand All @@ -426,10 +443,6 @@ export default class CompatResolver implements Resolver {
return null;
}

get adjustImportsOptions() {
return this.params.adjustImportsOptions;
}

@Memoize()
private get appPackage(): AppPackagePlaceholder {
return { root: this.params.root, name: this.params.modulePrefix };
Expand All @@ -440,7 +453,7 @@ export default class CompatResolver implements Resolver {
if (parts.length > 1 && parts[0].length > 0) {
let cache = PackageCache.shared('embroider-stage3');
let packageName = parts[0];
let renamed = this.params.adjustImportsOptions.renamePackages[packageName];
let renamed = this.adjustImportsOptions.renamePackages[packageName];
if (renamed) {
packageName = renamed;
}
Expand All @@ -462,7 +475,7 @@ export default class CompatResolver implements Resolver {
// as a key into the rules, and we want to be able to find our rules when
// checking from our own template (among other times).

let extensions = ['.hbs', ...this.params.adjustImportsOptions.resolvableExtensions.filter(e => e !== '.hbs')];
let extensions = ['.hbs', ...this.adjustImportsOptions.resolvableExtensions.filter(e => e !== '.hbs')];

let componentModules = [] as string[];

Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ export interface AppAdapter<TreeNames> {
// compatibility
adjustImportsOptions(): AdjustImportsOptions;

adjustImportsOptionsFile(): string;

// The template preprocessor plugins that are configured in the app.
htmlbarsPlugins(): TemplateCompilerPlugins;

Expand Down Expand Up @@ -417,7 +419,7 @@ export class AppBuilder<TreeNames> {
}
return [
require.resolve('./babel-plugin-adjust-imports'),
Object.assign({}, this.adapter.adjustImportsOptions(), { relocatedFiles }),
{ adjustImportsOptionsFile: this.adapter.adjustImportsOptionsFile(), relocatedFiles },
];
}

Expand Down
77 changes: 45 additions & 32 deletions packages/core/src/babel-plugin-adjust-imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,43 @@ import { join, dirname, resolve } from 'path';
import type { NodePath } from '@babel/traverse';
import type * as t from '@babel/types';
import { PackageCache, Package, V2Package, explicitRelative } from '@embroider/shared-internals';
import { outputFileSync } from 'fs-extra';
import { outputFileSync, readFileSync } from 'fs-extra';
import { Memoize } from 'typescript-memoize';
import { compile } from './js-handlebars';
import { handleImportDeclaration } from './mini-modules-polyfill';

interface State {
adjustFile: AdjustFile;
opts: {
renamePackages: {
[fromName: string]: string;
};
renameModules: {
[fromName: string]: string;
};
extraImports: {
absPath: string;
target: string;
runtimeName?: string;
}[];
externalsDir: string;
activeAddons: {
[packageName: string]: string;
};
relocatedFiles: { [relativePath: string]: string };
resolvableExtensions: string[];
emberNeedsModulesPolyfill: boolean;
};
opts: Options | DeflatedOptions;
}

export interface DeflatedOptions {
adjustImportsOptionsFile: string;
relocatedFiles: { [relativePath: string]: string };
}

type BabelTypes = typeof t;

export type Options = State['opts'];
export interface Options {
renamePackages: {
[fromName: string]: string;
};
renameModules: {
[fromName: string]: string;
};
extraImports: {
absPath: string;
target: string;
runtimeName?: string;
}[];
externalsDir: string;
activeAddons: {
[packageName: string]: string;
};
relocatedFiles: { [relativePath: string]: string };
resolvableExtensions: string[];
emberNeedsModulesPolyfill: boolean;
}

const packageCache = PackageCache.shared('embroider-stage3');

Expand Down Expand Up @@ -99,7 +104,7 @@ function adjustSpecifier(specifier: string, file: AdjustFile, opts: Options, isD
return specifier;
}

function handleRenaming(specifier: string, sourceFile: AdjustFile, opts: State['opts']) {
function handleRenaming(specifier: string, sourceFile: AdjustFile, opts: Options) {
let packageName = getPackageName(specifier);
if (!packageName) {
return specifier;
Expand Down Expand Up @@ -342,8 +347,9 @@ export default function main(babel: unknown) {
visitor: {
Program: {
enter(path: NodePath<t.Program>, state: State) {
let opts = ensureOpts(state);
state.adjustFile = new AdjustFile(path.hub.file.opts.filename, state.opts.relocatedFiles);
addExtraImports(t, path, state.opts.extraImports);
addExtraImports(t, path, opts.extraImports);
},
exit(path: NodePath<t.Program>, state: State) {
for (let child of path.get('body')) {
Expand All @@ -356,7 +362,7 @@ export default function main(babel: unknown) {
CallExpression(path: NodePath<t.CallExpression>, state: State) {
if (isImportSyncExpression(t, path) || isDynamicImportExpression(t, path)) {
const [source] = path.get('arguments');
let { opts } = state;
let opts = ensureOpts(state);
let specifier = adjustSpecifier((source.node as any).value, state.adjustFile, opts, true);
source.replaceWith(t.stringLiteral(specifier));
return;
Expand All @@ -374,7 +380,7 @@ export default function main(babel: unknown) {
);
}

let { opts } = state;
let opts = ensureOpts(state);

const dependencies = path.node.arguments[1];

Expand Down Expand Up @@ -411,7 +417,7 @@ function rewriteTopLevelImport(
path: NodePath<t.ImportDeclaration | t.ExportNamedDeclaration | t.ExportAllDeclaration>,
state: State
) {
let { opts } = state;
let opts = ensureOpts(state);
const { source } = path.node;
if (source === null || source === undefined) {
return;
Expand All @@ -435,11 +441,7 @@ function rewriteTopLevelImport(
return join(__dirname, '..');
};

function addExtraImports(
t: BabelTypes,
path: NodePath<t.Program>,
extraImports: Required<State['opts']>['extraImports']
) {
function addExtraImports(t: BabelTypes, path: NodePath<t.Program>, extraImports: Required<Options>['extraImports']) {
let counter = 0;
for (let { absPath, target, runtimeName } of extraImports) {
if (absPath === path.hub.file.opts.filename) {
Expand Down Expand Up @@ -491,6 +493,17 @@ class AdjustFile {
}
}

function ensureOpts(state: State): Options {
let { opts } = state;
if ('adjustImportsOptionsFile' in opts) {
let inflated = JSON.parse(readFileSync(opts.adjustImportsOptionsFile, 'utf8'));
inflated.relocatedFiles = opts.relocatedFiles;
state.opts = inflated;
return inflated;
}
return opts;
}

// we don't want to allow things that resolve only by accident that are likely
// to break in other setups. For example: import your dependencies'
// dependencies, or importing your own name from within a monorepo (which will
Expand Down