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

fix resolution of files with .hbs extensions #1463

Merged
merged 3 commits into from
Jun 13, 2023
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
36 changes: 22 additions & 14 deletions packages/core/src/module-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,8 @@ export class Resolver {

let pkg = this.owningPackage(match.filename);
if (pkg) {
let rel = withoutJSExt(explicitRelative(pkg.root, match.filename));
let entry = this.mergeMap.get(pkg.root)?.get(rel);
let rel = explicitRelative(pkg.root, match.filename);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To drop withoutJSExt here you must replace it with the search over all resolvable extensions. That's what's causing the failure in the engine-relative resolving > file exists in both app-js and fastboot-js test.

I would suggest taking your implementation in searchAppTree and making it a utility method that you can use here too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one, I completely missed that there was something else checking the mergemap 👍

let entry = this.getEntryFromMergeMap(rel, pkg.root);
if (entry?.type === 'both') {
return request.alias(entry[section].localPath).rehome(resolve(entry[section].packageRoot, 'package.json'));
}
Expand Down Expand Up @@ -504,7 +504,6 @@ export class Resolver {
`addon ${addon.name} declares app-js in its package.json with the illegal name "${inAddonName}". It must start with "./" to make it clear that it's relative to the addon`
);
}
inEngineName = withoutJSExt(inEngineName);
let prevEntry = engineModules.get(inEngineName);
switch (prevEntry?.type) {
case undefined:
Expand Down Expand Up @@ -549,7 +548,6 @@ export class Resolver {
`addon ${addon.name} declares fastboot-js in its package.json with the illegal name "${inAddonName}". It must start with "./" to make it clear that it's relative to the addon`
);
}
inEngineName = withoutJSExt(inEngineName);
let prevEntry = engineModules.get(inEngineName);
switch (prevEntry?.type) {
case undefined:
Expand Down Expand Up @@ -928,13 +926,31 @@ export class Resolver {
return logTransition('fallbackResolve final exit', request);
}

private getEntryFromMergeMap(inEngineSpecifier: string, root: string): MergeEntry | undefined {
let entry: MergeEntry | undefined;

if (inEngineSpecifier.match(/\.(hbs|js|hbs\.js)$/)) {
entry = this.mergeMap.get(root)?.get(inEngineSpecifier);
} else {
// try looking up .hbs .js and .hbs.js in that order for specifiers without extenstions
['.hbs', '.js', '.hbs.js'].forEach(ext => {
if (entry) {
return;
}

entry = this.mergeMap.get(root)?.get(`${inEngineSpecifier}${ext}`);
});
}
return entry;
}

private searchAppTree<R extends ModuleRequest>(
request: R,
engine: EngineConfig,
inEngineSpecifier: string
): R | undefined {
inEngineSpecifier = withoutJSExt(inEngineSpecifier);
let entry = this.mergeMap.get(engine.root)?.get(inEngineSpecifier);
let entry = this.getEntryFromMergeMap(inEngineSpecifier, engine.root);

switch (entry?.type) {
case undefined:
return undefined;
Expand Down Expand Up @@ -1060,11 +1076,3 @@ function external<R extends ModuleRequest>(label: string, request: R, specifier:
let filename = virtualExternalModule(specifier);
return logTransition(label, request, request.virtualize(filename));
}

// this is specifically for app-js handling, where only .js and .hbs are legal
// extensiosn, and only .js is allowed to be an *implied* extension (.hbs must
// be explicit). So when normalizing such paths, it's only a .js suffix that we
// must remove.
function withoutJSExt(filename: string): string {
return filename.replace(/\.js$/, '');
}
18 changes: 18 additions & 0 deletions tests/scenarios/core-resolver-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,24 @@ Scenarios.fromProject(() => new Project())
.to('./node_modules/my-addon/_app_/hello-world.js');
});

test('hbs in addon is found', async function () {
givenFiles({
'node_modules/my-addon/_app_/templates/hello-world.hbs': '',
'app.js': `import "my-app/templates/hello-world"`,
});

await configure({
addonMeta: {
'app-js': { './templates/hello-world.hbs': './_app_/templates/hello-world.hbs' },
},
});

expectAudit
.module('./app.js')
.resolves('my-app/templates/hello-world')
.to('./node_modules/my-addon/_app_/templates/hello-world.hbs');
});

test(`relative import in addon's app tree resolves to app`, async function () {
givenFiles({
'node_modules/my-addon/_app_/hello-world.js': `import "./secondary"`,
Expand Down