Skip to content

Commit 0277294

Browse files
authoredJun 11, 2024
Merge pull request #1974 from embroider-build/esbuild-virtual-relative
esbuild-resolver: handle relative imports in virtual files
2 parents e5ef9b9 + 4464aad commit 0277294

File tree

1 file changed

+32
-5
lines changed

1 file changed

+32
-5
lines changed
 

‎packages/vite/src/esbuild-resolver.ts

+32-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import type { Plugin as EsBuildPlugin } from 'esbuild';
22
import { type PluginItem, transform } from '@babel/core';
3-
import { ResolverLoader, virtualContent, locateEmbroiderWorkingDir } from '@embroider/core';
3+
import { ResolverLoader, virtualContent, locateEmbroiderWorkingDir, explicitRelative } from '@embroider/core';
44
import { readFileSync, readJSONSync } from 'fs-extra';
55
import { EsBuildModuleRequest } from './esbuild-request';
66
import assertNever from 'assert-never';
7-
import { resolve } from 'path';
7+
import { dirname, isAbsolute, resolve } from 'path';
88
import { hbsToJS } from '@embroider/core';
99
import { Preprocessor } from 'content-tag';
1010

@@ -32,10 +32,11 @@ export function esBuildResolver(root = process.cwd()): EsBuildPlugin {
3232
let firstFailure;
3333

3434
for (let candidate of candidates(path)) {
35-
let result = await build.resolve(candidate, {
35+
let { specifier, fromFile } = adjustVirtualImport(candidate, importer);
36+
let result = await build.resolve(specifier, {
3637
namespace,
3738
resolveDir,
38-
importer,
39+
importer: fromFile,
3940
kind,
4041
pluginData: { ...pluginData, embroiderExtensionSearch: true },
4142
});
@@ -52,7 +53,8 @@ export function esBuildResolver(root = process.cwd()): EsBuildPlugin {
5253
return firstFailure;
5354
});
5455
build.onResolve({ filter: /./ }, async ({ path, importer, pluginData, kind }) => {
55-
let request = EsBuildModuleRequest.from(build, kind, path, importer, pluginData);
56+
let { specifier, fromFile } = adjustVirtualImport(path, importer);
57+
let request = EsBuildModuleRequest.from(build, kind, specifier, fromFile, pluginData);
5658
if (!request) {
5759
return null;
5860
}
@@ -132,3 +134,28 @@ function runMacros(src: string, filename: string, macrosConfig: PluginItem): str
132134
plugins: [macrosConfig],
133135
})!.code!;
134136
}
137+
138+
// esbuild's resolve does not like when we resolve from virtual paths. That is,
139+
// a request like "../thing.js" from "/a/real/path/VIRTUAL_SUBDIR/virtual.js"
140+
// has an unambiguous target of "/a/real/path/thing.js", but esbuild won't do
141+
// that path adjustment until after checking whether VIRTUAL_SUBDIR actually
142+
// exists.
143+
//
144+
// We can do the path adjustments before doing resolve.
145+
function adjustVirtualImport(specifier: string, fromFile: string): { specifier: string; fromFile: string } {
146+
let fromDir = dirname(fromFile);
147+
if (!isAbsolute(specifier) && specifier.startsWith('.')) {
148+
let targetPath = resolve(fromDir, specifier);
149+
let newFromDir = dirname(targetPath);
150+
if (fromDir !== newFromDir) {
151+
return {
152+
specifier: explicitRelative(newFromDir, targetPath),
153+
// we're resolving *from* the destination, because we need to resolve
154+
// from a file that exists, and we know that (if this was supposed to
155+
// succeed at all) that file definitely does
156+
fromFile: targetPath,
157+
};
158+
}
159+
}
160+
return { specifier, fromFile };
161+
}

0 commit comments

Comments
 (0)
Failed to load comments.