Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Commit d656e7f

Browse files
committed
Enable moduleRoot option for modules: true
This changes which directory Miniflare's automatic module location resolves module names from paths relative to. Note Miniflare's source-mapping support already accounts for `modulesRoot`. Whilst this could've been used to support `__STATIC_CONTENT_MANIFEST` imports in non-root directories, you would still only be able to import the manifest in a single directory, just not the root one.
1 parent 19cd822 commit d656e7f

File tree

4 files changed

+41
-14
lines changed

4 files changed

+41
-14
lines changed

packages/miniflare/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,9 @@ parameter in module format Workers.
234234

235235
- `modulesRoot?: string`
236236

237-
If `modules` is set to an array, modules' "name"s will be their `path`s
238-
relative to this value. This ensures file paths in stack traces are correct.
237+
If `modules` is set to `true` or an array, modules' "name"s will be their
238+
`path`s relative to this value. This ensures file paths in stack traces are
239+
correct.
239240

240241
<!-- prettier-ignore-start -->
241242
<!-- (for disabling `;` insertion in `js` code block) -->

packages/miniflare/src/plugins/core/index.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -563,10 +563,10 @@ function getWorkerScript(
563563
options: SourceOptions,
564564
workerIndex: number
565565
): { serviceWorkerScript: string } | { modules: Worker_Module[] } {
566+
const modulesRoot =
567+
("modulesRoot" in options ? options.modulesRoot : undefined) ?? "";
566568
if (Array.isArray(options.modules)) {
567569
// If `modules` is a manually defined modules array, use that
568-
const modulesRoot =
569-
("modulesRoot" in options ? options.modulesRoot : undefined) ?? "";
570570
return {
571571
modules: options.modules.map((module) =>
572572
convertModuleDefinition(sourceMapRegistry, modulesRoot, module)
@@ -589,7 +589,11 @@ function getWorkerScript(
589589

590590
if (options.modules) {
591591
// If `modules` is `true`, automatically collect modules...
592-
const locator = new ModuleLocator(sourceMapRegistry, options.modulesRules);
592+
const locator = new ModuleLocator(
593+
sourceMapRegistry,
594+
modulesRoot,
595+
options.modulesRules
596+
);
593597
// If `script` and `scriptPath` are set, resolve modules in `script`
594598
// against `scriptPath`.
595599
locator.visitEntrypoint(

packages/miniflare/src/plugins/core/modules.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ export const SourceOptionsSchema = z.union([
8080
modules: z.boolean().optional(),
8181
// How to interpret automatically collected modules
8282
modulesRules: z.array(ModuleRuleSchema).optional(),
83+
// `modules` "name"s will be their paths relative to this value.
84+
// This ensures file paths in stack traces are correct.
85+
modulesRoot: z.string().optional(),
8386
}),
8487
z.object({
8588
scriptPath: z.string(),
@@ -88,6 +91,9 @@ export const SourceOptionsSchema = z.union([
8891
modules: z.boolean().optional(),
8992
// How to interpret automatically collected modules
9093
modulesRules: z.array(ModuleRuleSchema).optional(),
94+
// `modules` "name"s will be their paths relative to this value.
95+
// This ensures file paths in stack traces are correct.
96+
modulesRoot: z.string().optional(),
9197
}),
9298
]);
9399
export type SourceOptions = z.infer<typeof SourceOptionsSchema>;
@@ -123,13 +129,15 @@ function getResolveErrorPrefix(referencingPath: string): string {
123129
}
124130

125131
export class ModuleLocator {
126-
readonly #sourceMapRegistry: SourceMapRegistry;
127132
readonly #compiledRules: CompiledModuleRule[];
128133
readonly #visitedPaths = new Set<string>();
129134
readonly modules: Worker_Module[] = [];
130135

131-
constructor(sourceMapRegistry: SourceMapRegistry, rules?: ModuleRule[]) {
132-
this.#sourceMapRegistry = sourceMapRegistry;
136+
constructor(
137+
private readonly sourceMapRegistry: SourceMapRegistry,
138+
private readonly modulesRoot: string,
139+
rules?: ModuleRule[]
140+
) {
133141
this.#compiledRules = compileModuleRules(rules);
134142
}
135143

@@ -146,8 +154,8 @@ export class ModuleLocator {
146154

147155
#visitJavaScriptModule(code: string, modulePath: string, esModule = true) {
148156
// Register module
149-
const name = path.relative("", modulePath);
150-
code = this.#sourceMapRegistry.register(code, modulePath);
157+
const name = path.relative(this.modulesRoot, modulePath);
158+
code = this.sourceMapRegistry.register(code, modulePath);
151159
this.modules.push(
152160
esModule ? { name, esModule: code } : { name, commonJsModule: code }
153161
);
@@ -255,7 +263,7 @@ ${dim(modulesConfig)}`;
255263

256264
const identifier = path.resolve(path.dirname(referencingPath), spec);
257265
// The runtime requires module identifiers to be relative paths
258-
const name = path.relative("", identifier);
266+
const name = path.relative(this.modulesRoot, identifier);
259267

260268
// If we've already visited this path, return to avoid unbounded recursion
261269
if (this.#visitedPaths.has(identifier)) return;

packages/miniflare/test/plugins/core/errors/index.spec.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,14 @@ test("source maps workers", async (t) => {
114114
{
115115
name: "g",
116116
routes: ["*/g"],
117+
bindings: { MESSAGE: "g" },
118+
modules: true,
119+
modulesRoot: tmp,
120+
scriptPath: modulesPath,
121+
},
122+
{
123+
name: "h",
124+
routes: ["*/h"],
117125
modules: [
118126
// Check importing module with source map (e.g. Wrangler no bundle with built dependencies)
119127
{
@@ -125,7 +133,7 @@ test("source maps workers", async (t) => {
125133
],
126134
},
127135
{
128-
name: "h",
136+
name: "i",
129137
// Generated with `esbuild --sourcemap=inline --sources-content=false worker.ts`
130138
script: `"use strict";
131139
addEventListener("fetch", (event) => {
@@ -174,6 +182,10 @@ addEventListener("fetch", (event) => {
174182
});
175183
t.regex(String(error?.stack), modulesEntryRegexp);
176184
error = await t.throwsAsync(mf.dispatchFetch("http://localhost/g"), {
185+
message: "g",
186+
});
187+
t.regex(String(error?.stack), modulesEntryRegexp);
188+
error = await t.throwsAsync(mf.dispatchFetch("http://localhost/h"), {
177189
instanceOf: TypeError,
178190
message: "Dependency error",
179191
});
@@ -196,6 +208,8 @@ addEventListener("fetch", (event) => {
196208
sources = await getSources(inspectorPort, "core:user:f");
197209
t.deepEqual(sources, [MODULES_ENTRY_PATH, REDUCE_PATH]);
198210
sources = await getSources(inspectorPort, "core:user:g");
211+
t.deepEqual(sources, [MODULES_ENTRY_PATH, REDUCE_PATH]);
212+
sources = await getSources(inspectorPort, "core:user:h");
199213
t.deepEqual(sources, [DEP_ENTRY_PATH, REDUCE_PATH]); // (entry point script overridden)
200214

201215
// Check respects map's existing `sourceRoot`
@@ -216,11 +230,11 @@ addEventListener("fetch", (event) => {
216230
]);
217231

218232
// Check does nothing with URL source mapping URLs
219-
const sourceMapURL = await getSourceMapURL(inspectorPort, "core:user:h");
233+
const sourceMapURL = await getSourceMapURL(inspectorPort, "core:user:i");
220234
t.regex(sourceMapURL, /^data:application\/json;base64/);
221235

222236
// Check adds ignored sources to `x_google_ignoreList`
223-
const sourceMap = await getSourceMap(inspectorPort, "core:user:g");
237+
const sourceMap = await getSourceMap(inspectorPort, "core:user:h");
224238
assert(sourceMap.sourceRoot !== undefined);
225239
assert(sourceMap.x_google_ignoreList?.length === 1);
226240
const ignoredSource = sourceMap.sources[sourceMap.x_google_ignoreList[0]];

0 commit comments

Comments
 (0)