Skip to content

Commit

Permalink
move the last resolving & decoding out of virtual-content
Browse files Browse the repository at this point in the history
  • Loading branch information
ef4 committed Dec 20, 2024
1 parent 8c378b3 commit 454be9f
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 62 deletions.
40 changes: 28 additions & 12 deletions packages/core/src/module-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import makeDebug from 'debug';
import assertNever from 'assert-never';
import { externalName } from '@embroider/reverse-exports';
import { exports as resolveExports } from 'resolve.exports';

import { fastbootSwitch, decodeFastbootSwitch } from './virtual-content';
import { Memoize } from 'typescript-memoize';
import { describeExports } from './describe-exports';
import { readFileSync } from 'fs';
Expand Down Expand Up @@ -248,14 +246,10 @@ export class Resolver {
configFile: false,
});
let switchFile = fastbootSwitch(candidate, resolve(pkg.root, 'package.json'), names);
if (switchFile === request.fromFile) {
if (switchFile.specifier === request.fromFile) {
return logTransition('internal lookup from fastbootSwitch', request);
} else {
return logTransition(
'shadowed app fastboot',
request,
request.virtualize({ type: 'fastboot-switch', specifier: switchFile })
);
return logTransition('shadowed app fastboot', request, request.virtualize(switchFile));
}
} else {
return logTransition(
Expand Down Expand Up @@ -1325,10 +1319,7 @@ export class Resolver {
);
}
let { names } = describeExports(readFileSync(foundAppJS.filename, 'utf8'), { configFile: false });
return request.virtualize({
type: 'fastboot-switch',
specifier: fastbootSwitch(matched.matched, resolve(engine.root, 'package.json'), names),
});
return request.virtualize(fastbootSwitch(matched.matched, resolve(engine.root, 'package.json'), names));
}
}

Expand Down Expand Up @@ -1425,3 +1416,28 @@ function engineRelativeName(pkg: Package, filename: string): string | undefined
return '.' + outsideName.slice(pkg.name.length);
}
}

const fastbootSwitchSuffix = '/embroider_fastboot_switch';

function fastbootSwitch(specifier: string, fromFile: string, names: Set<string>) {
let filename = `${resolve(dirname(fromFile), specifier)}${fastbootSwitchSuffix}`;
let virtualSpecifier: string;
if (names.size > 0) {
virtualSpecifier = `${filename}?names=${[...names].join(',')}`;
} else {
virtualSpecifier = filename;
}
return {
type: 'fastboot-switch' as const,
specifier: virtualSpecifier,
names,
hasDefaultExport: 'x',
};
}

function decodeFastbootSwitch(filename: string) {
let index = filename.indexOf(fastbootSwitchSuffix);
if (index >= 0) {
return { filename: filename.slice(0, index) };
}
}
70 changes: 20 additions & 50 deletions packages/core/src/virtual-content.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
import { dirname, resolve, posix, sep, join } from 'path';
import { posix, sep, join } from 'path';
import type { Resolver, AddonPackage, Package } from '.';
import { extensionsPattern } from '.';
import { compile } from './js-handlebars';
import { renderImplicitTestScripts } from './virtual-test-support';
import { renderTestSupportStyles } from './virtual-test-support-styles';
import { renderImplicitTestScripts, type TestSupportResponse } from './virtual-test-support';
import { renderTestSupportStyles, type TestSupportStylesResponse } from './virtual-test-support-styles';
import { renderVendor, type VirtualVendorResponse } from './virtual-vendor';
import { renderVendorStyles, type VirtualVendorStylesResponse } from './virtual-vendor-styles';

import { type EntrypointResponse, renderEntrypoint } from './virtual-entrypoint';
import { renderRouteEntrypoint, type RouteEntrypointResponse } from './virtual-route-entrypoint';
import assertNever from 'assert-never';

export type VirtualResponse = { specifier: string } & (
| {
type: 'fastboot-switch';
}
| FastbootSwitchResponse
| ImplicitModulesResponse
| EntrypointResponse
| RouteEntrypointResponse
| { type: 'test-support-js' }
| { type: 'test-support-css' }
| TestSupportResponse
| TestSupportStylesResponse
| VirtualVendorResponse
| VirtualVendorStylesResponse
| VirtualPairResponse
Expand Down Expand Up @@ -52,16 +51,11 @@ export function virtualContent(response: VirtualResponse, resolver: Resolver): V
return renderImplicitModules(response, resolver);
case 'route-entrypoint':
return renderRouteEntrypoint(response, resolver);
case 'fastboot-switch':
return renderFastbootSwitchTemplate(response);
default:
throw assertNever(response);
}

let filename = response.specifier;

let fb = decodeFastbootSwitch(filename);
if (fb) {
return renderFastbootSwitchTemplate(fb);
}

throw new Error(`not an @embroider/core virtual file: ${filename}`);
}

interface PairedComponentShimParams {
Expand Down Expand Up @@ -113,41 +107,17 @@ export interface VirtualPairResponse {
debugName: string;
}

const fastbootSwitchSuffix = '/embroider_fastboot_switch';
const fastbootSwitchPattern = /(?<original>.+)\/embroider_fastboot_switch(?:\?names=(?<names>.+))?$/;
export function fastbootSwitch(specifier: string, fromFile: string, names: Set<string>): string {
let filename = `${resolve(dirname(fromFile), specifier)}${fastbootSwitchSuffix}`;
if (names.size > 0) {
return `${filename}?names=${[...names].join(',')}`;
} else {
return filename;
}
}

export function decodeFastbootSwitch(filename: string) {
// Performance: avoid paying regex exec cost unless needed
if (!filename.includes(fastbootSwitchSuffix)) {
return;
}
let match = fastbootSwitchPattern.exec(filename);
if (match) {
let names = match.groups?.names?.split(',') ?? [];
return {
names: names.filter(name => name !== 'default'),
hasDefaultExport: names.includes('default'),
filename: match.groups!.original,
};
}
}

interface FastbootSwitchParams {
names: string[];
hasDefaultExport: boolean;
interface FastbootSwitchResponse {
type: 'fastboot-switch';
names: Set<string>;
}

function renderFastbootSwitchTemplate(params: FastbootSwitchParams): VirtualContentResult {
function renderFastbootSwitchTemplate(params: FastbootSwitchResponse): VirtualContentResult {
return {
src: fastbootSwitchTemplate(params),
src: fastbootSwitchTemplate({
names: [...params.names].filter(name => name !== 'default'),
hasDefaultExport: params.names.has('default'),
}),
watches: [],
};
}
Expand All @@ -166,7 +136,7 @@ export default mod.default;
{{#each names as |name|}}
export const {{name}} = mod.{{name}};
{{/each}}
`) as (params: FastbootSwitchParams) => string;
`) as (params: { names: string[]; hasDefaultExport: boolean }) => string;

export interface ImplicitModulesResponse {
type: 'implicit-modules' | 'implicit-test-modules';
Expand Down

0 comments on commit 454be9f

Please sign in to comment.