@jundle/cloudflare 0.0.1-15 → 0.0.1-16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/harness.js +54 -1
package/package.json
CHANGED
package/src/harness.js
CHANGED
|
@@ -98,6 +98,28 @@ const evaluated = new Map();
|
|
|
98
98
|
const depText = new Map();
|
|
99
99
|
// Evaluated dep bundles: key -> {exports, failed, error}.
|
|
100
100
|
const depEvaluated = new Map();
|
|
101
|
+
// Serializes dep-text walks (FIFO promise queue):
|
|
102
|
+
// concurrent chunk loads walk the same shared bundles,
|
|
103
|
+
// and ensureDepText's "already fetched" early-return
|
|
104
|
+
// does not wait for an in-flight subtree walk — a
|
|
105
|
+
// second walk can see a bundle's text present, skip its
|
|
106
|
+
// subtree, and evaluate it while the first walk is
|
|
107
|
+
// still fetching its transitive deps ("was not
|
|
108
|
+
// pre-fetched", non-deterministic in which bundle). One
|
|
109
|
+
// walk at a time closes the race; the recursion inside
|
|
110
|
+
// a walk never re-enters the queue, so it cannot
|
|
111
|
+
// deadlock. A failed walk rejects to its caller but
|
|
112
|
+
// resolves the queue slot, so it never poisons later
|
|
113
|
+
// walks.
|
|
114
|
+
let depWalkQueue = Promise.resolve();
|
|
115
|
+
function runDepWalk(fn) {
|
|
116
|
+
const run = depWalkQueue.then(fn);
|
|
117
|
+
depWalkQueue = run.then(
|
|
118
|
+
() => {},
|
|
119
|
+
() => {},
|
|
120
|
+
);
|
|
121
|
+
return run;
|
|
122
|
+
}
|
|
101
123
|
// Parsed JSON values: key `${env}\0${file}` -> value.
|
|
102
124
|
const jsonCache = new Map();
|
|
103
125
|
// Prefetched asset values: key `${env}\0${file}\0${type}` ->
|
|
@@ -298,7 +320,12 @@ async function ensureText(url, visiting = new Set()) {
|
|
|
298
320
|
if (edge.kind === "dev" || edge.kind === "client-ref" || edge.kind === "server-action") {
|
|
299
321
|
await ensureText(edge.url, visiting);
|
|
300
322
|
} else if (edge.kind === "dep") {
|
|
301
|
-
|
|
323
|
+
// Serialized through the dep walk queue: two
|
|
324
|
+
// concurrent dispatches walk the same shared
|
|
325
|
+
// bundles, and an unserialized walk can evaluate a
|
|
326
|
+
// bundle whose subtree another walk is still
|
|
327
|
+
// fetching (same race as loadChunk, below).
|
|
328
|
+
await runDepWalk(() => ensureDepText(edge.url, new Set()));
|
|
302
329
|
} else if (edge.kind === "json") {
|
|
303
330
|
const jk = devKey(edge.url);
|
|
304
331
|
if (!jsonCache.has(jk)) {
|
|
@@ -563,6 +590,16 @@ function requireHook(spec, importerKey) {
|
|
|
563
590
|
const key = `${importerEnv}\0${candidate}`;
|
|
564
591
|
if (jsonCache.has(key)) return jsonCache.get(key);
|
|
565
592
|
}
|
|
593
|
+
// Literal dynamic imports (import("./route")) compile
|
|
594
|
+
// to a require of the raw relative spec (the harness
|
|
595
|
+
// has no async __jundleImport), and the closure walk
|
|
596
|
+
// pre-fetches them via their dev edges — so resolve
|
|
597
|
+
// the spec the same way and evaluate the pre-fetched
|
|
598
|
+
// module. A spec with no pre-fetched text falls
|
|
599
|
+
// through to the loud error below (a truly-dynamic
|
|
600
|
+
// specifier has no static target to pre-fetch).
|
|
601
|
+
const devModuleKey = `${importerEnv}\0${normalized}`;
|
|
602
|
+
if (textCache.has(devModuleKey)) return evaluateDev(devModuleKey).exports;
|
|
566
603
|
}
|
|
567
604
|
throw new Error(
|
|
568
605
|
`ModuleRunner: '${spec}' was not pre-loaded (the closure walk missed it); use a static, literal specifier for this import so the walk pre-loads it; dynamic specifiers are not pre-loaded.`,
|
|
@@ -588,6 +625,22 @@ const hostContext = {
|
|
|
588
625
|
return (await ensureModuleByUrl(resolved.url)).exports;
|
|
589
626
|
},
|
|
590
627
|
loadChunk: async (chunkId) => {
|
|
628
|
+
// Dep chunk ids (the Flight client preloads dep
|
|
629
|
+
// client components by their bundle URL): fetch the
|
|
630
|
+
// dep text on demand — the closure walk does not
|
|
631
|
+
// pre-fetch dep client-ref bundles (their client-ref
|
|
632
|
+
// edges carry a prebundleSpec and are omitted) — then
|
|
633
|
+
// evaluate it, mirroring NodeRunner's hostContext.
|
|
634
|
+
// Serialized through the dep walk queue: concurrent
|
|
635
|
+
// chunk loads share transitive bundles, and an
|
|
636
|
+
// unserialized walk can evaluate a bundle whose
|
|
637
|
+
// subtree another walk is still fetching.
|
|
638
|
+
if (chunkId.startsWith("/@jundle/deps/")) {
|
|
639
|
+
return runDepWalk(async () => {
|
|
640
|
+
await ensureDepText(chunkId);
|
|
641
|
+
return evaluateDep(chunkId).exports;
|
|
642
|
+
});
|
|
643
|
+
}
|
|
591
644
|
const u = new URL(chunkId, "http://dev");
|
|
592
645
|
if (u.pathname !== "/@jundle/module")
|
|
593
646
|
throw new Error(`ModuleRunner: refusing to load chunk (not a dev module URL): ${chunkId}`);
|