@async/framework 0.11.19 → 0.11.23

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/jsx/types.d.ts ADDED
@@ -0,0 +1,108 @@
1
+ // Generated by scripts/build-framework-bundle.js. Do not edit by hand.
2
+ // Shared JSX type declarations for @async/framework JSX profiles.
3
+
4
+ export type AsyncJsxProfile = "runtime" | "buildtime";
5
+ export type AsyncJSXElementType = string | ((props: Record<string, unknown>) => unknown);
6
+ export type AsyncJSXElement = { readonly kind?: "async-jsx-node"; readonly type?: AsyncJSXElementType; readonly props?: Record<string, unknown>; readonly key?: string | number | null } | unknown;
7
+ export type AsyncJSXChild = AsyncJSXElement | string | number | boolean | null | undefined;
8
+ export type AsyncJSXChildren = AsyncJSXChild | readonly AsyncJSXChild[];
9
+ export type AsyncEventHandler<E = Event, T extends EventTarget = EventTarget> = string | ((event: E & { currentTarget: T }) => unknown);
10
+ export interface WritableSignal<T> {
11
+ readonly kind: "signal";
12
+ value: T;
13
+ }
14
+ export interface ComputedSignal<T> {
15
+ readonly kind: "computed";
16
+ readonly value: T;
17
+ }
18
+ export interface AsyncSignal<T> {
19
+ readonly kind: "asyncSignal";
20
+ readonly value: T | undefined;
21
+ readonly pending: boolean;
22
+ readonly error: unknown;
23
+ readonly version: number;
24
+ }
25
+ export interface JsxSignalIntent<T = unknown> {
26
+ readonly kind: "async-jsx-signal";
27
+ readonly source: T;
28
+ }
29
+ export type Signal<T> = WritableSignal<T> | ComputedSignal<T> | AsyncSignal<T>;
30
+ export type SignalValue<T = unknown> = T | Signal<T> | JsxSignalIntent<T>;
31
+ export type PrimitiveAttributeValue = string | number | boolean | null | undefined;
32
+ export type DataAttributes = { [K in `data-${string}`]?: PrimitiveAttributeValue };
33
+ export type AriaAttributes = { [K in `aria-${string}`]?: PrimitiveAttributeValue };
34
+ export type CommonAttributes = DataAttributes & AriaAttributes & {
35
+ id?: string;
36
+ class?: string;
37
+ className?: string;
38
+ style?: string | Partial<CSSStyleDeclaration>;
39
+ title?: string;
40
+ role?: string;
41
+ tabIndex?: number;
42
+ hidden?: boolean;
43
+ children?: AsyncJSXChildren;
44
+ key?: string | number;
45
+ };
46
+ export type RuntimeProtocolEventProps = { [K in `on:${string}`]?: AsyncEventHandler | readonly unknown[] };
47
+ export type RuntimeSignalBindingProps = { [K in `signal:${string}`]?: SignalValue };
48
+ export type RuntimeClassToggleProps = { [K in `class:${string}`]?: boolean | SignalValue<boolean> };
49
+ export type BuildtimeEventName = "Click" | "Input" | "Change" | "Submit" | "PointerEnter" | "PointerLeave" | "PointerDown" | "PointerUp" | "KeyDown" | "KeyUp" | "Focus" | "Blur";
50
+ export type BuildtimeEventProps<T extends EventTarget = EventTarget> = { [K in `on${BuildtimeEventName}`]?: AsyncEventHandler<Event, T> };
51
+ export type HTMLAttributeProps<T extends EventTarget> = CommonAttributes & {
52
+ value?: SignalValue<string | number | readonly string[]>;
53
+ checked?: SignalValue<boolean>;
54
+ disabled?: SignalValue<boolean>;
55
+ name?: string;
56
+ type?: string;
57
+ href?: string;
58
+ src?: string;
59
+ alt?: string;
60
+ width?: string | number;
61
+ height?: string | number;
62
+ for?: string;
63
+ htmlFor?: string;
64
+ placeholder?: string;
65
+ target?: string;
66
+ rel?: string;
67
+ ref?: T | ((element: T) => void);
68
+ };
69
+ export type SVGAttributeProps<T extends EventTarget> = CommonAttributes & {
70
+ viewBox?: string;
71
+ xmlns?: string;
72
+ fill?: string;
73
+ stroke?: string;
74
+ d?: string;
75
+ cx?: string | number;
76
+ cy?: string | number;
77
+ r?: string | number;
78
+ x?: string | number;
79
+ y?: string | number;
80
+ ref?: T | ((element: T) => void);
81
+ };
82
+ export type AsyncHTMLProps<Profile extends AsyncJsxProfile, T extends EventTarget = HTMLElement> = HTMLAttributeProps<T> & (Profile extends "runtime" ? RuntimeProtocolEventProps & RuntimeSignalBindingProps & RuntimeClassToggleProps : BuildtimeEventProps<T>);
83
+ export type AsyncSVGProps<Profile extends AsyncJsxProfile, T extends EventTarget = SVGElement> = SVGAttributeProps<T> & (Profile extends "runtime" ? RuntimeProtocolEventProps & RuntimeSignalBindingProps & RuntimeClassToggleProps : BuildtimeEventProps<T>);
84
+ export type AsyncHTMLElements<Profile extends AsyncJsxProfile> = { [Tag in keyof HTMLElementTagNameMap]: AsyncHTMLProps<Profile, HTMLElementTagNameMap[Tag]> } & { [Tag in `${string}-${string}`]: AsyncHTMLProps<Profile, HTMLElement> };
85
+ export type AsyncSVGElements<Profile extends AsyncJsxProfile> = { [Tag in keyof SVGElementTagNameMap]: AsyncSVGProps<Profile, SVGElementTagNameMap[Tag]> };
86
+ export type RuntimeIntrinsicElements = AsyncHTMLElements<"runtime"> & AsyncSVGElements<"runtime">;
87
+ export type BuildtimeIntrinsicElements = AsyncHTMLElements<"buildtime"> & AsyncSVGElements<"buildtime">;
88
+ export type PropsOf<Tag extends keyof RuntimeIntrinsicElements | keyof BuildtimeIntrinsicElements, Profile extends AsyncJsxProfile = "buildtime"> = Profile extends "runtime" ? RuntimeIntrinsicElements[Extract<Tag, keyof RuntimeIntrinsicElements>] : BuildtimeIntrinsicElements[Extract<Tag, keyof BuildtimeIntrinsicElements>];
89
+ export namespace AsyncJSX {
90
+ type Element = AsyncJSXElement;
91
+ interface ElementChildrenAttribute {
92
+ children: AsyncJSXChildren;
93
+ }
94
+ }
95
+ export namespace RuntimeJSX {
96
+ type Element = AsyncJSXElement;
97
+ interface ElementChildrenAttribute {
98
+ children: AsyncJSXChildren;
99
+ }
100
+ type IntrinsicElements = RuntimeIntrinsicElements;
101
+ }
102
+ export namespace BuildtimeJSX {
103
+ type Element = AsyncJSXElement;
104
+ interface ElementChildrenAttribute {
105
+ children: AsyncJSXChildren;
106
+ }
107
+ type IntrinsicElements = BuildtimeIntrinsicElements;
108
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@async/framework",
3
- "version": "0.11.19",
3
+ "version": "0.11.23",
4
4
  "description": "No-build Loader app runtime with browser and server entrypoints, signals, command events, route partials, cache split, SSR activation, and streaming boundaries.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -65,6 +65,36 @@
65
65
  "import": "./jsx.js",
66
66
  "default": "./jsx.js"
67
67
  },
68
+ "./jsx/runtime": {
69
+ "types": "./jsx/runtime.d.ts",
70
+ "import": "./jsx/runtime.js",
71
+ "default": "./jsx/runtime.js"
72
+ },
73
+ "./jsx/runtime/jsx-runtime": {
74
+ "types": "./jsx/runtime/jsx-runtime.d.ts",
75
+ "import": "./jsx/runtime/jsx-runtime.js",
76
+ "default": "./jsx/runtime/jsx-runtime.js"
77
+ },
78
+ "./jsx/runtime/jsx-dev-runtime": {
79
+ "types": "./jsx/runtime/jsx-dev-runtime.d.ts",
80
+ "import": "./jsx/runtime/jsx-dev-runtime.js",
81
+ "default": "./jsx/runtime/jsx-dev-runtime.js"
82
+ },
83
+ "./jsx/buildtime": {
84
+ "types": "./jsx/buildtime.d.ts",
85
+ "import": "./jsx/buildtime.js",
86
+ "default": "./jsx/buildtime.js"
87
+ },
88
+ "./jsx/buildtime/jsx-runtime": {
89
+ "types": "./jsx/buildtime/jsx-runtime.d.ts",
90
+ "import": "./jsx/buildtime/jsx-runtime.js",
91
+ "default": "./jsx/buildtime/jsx-runtime.js"
92
+ },
93
+ "./jsx/buildtime/jsx-dev-runtime": {
94
+ "types": "./jsx/buildtime/jsx-dev-runtime.d.ts",
95
+ "import": "./jsx/buildtime/jsx-dev-runtime.js",
96
+ "default": "./jsx/buildtime/jsx-dev-runtime.js"
97
+ },
68
98
  "./vite": {
69
99
  "types": "./vite.d.ts",
70
100
  "import": "./vite.js",
@@ -102,11 +132,25 @@
102
132
  "package.json",
103
133
  "server.js",
104
134
  "jsx.d.ts",
135
+ "jsx/runtime.d.ts",
136
+ "jsx/runtime/jsx-runtime.d.ts",
137
+ "jsx/runtime/jsx-dev-runtime.d.ts",
138
+ "jsx/buildtime.d.ts",
139
+ "jsx/buildtime/jsx-runtime.d.ts",
140
+ "jsx/buildtime/jsx-dev-runtime.d.ts",
141
+ "jsx/types.d.ts",
105
142
  "vite.d.ts",
106
143
  "runtime.d.ts",
107
144
  "runtime/signals.d.ts",
108
145
  "runtime/events.d.ts",
109
146
  "jsx.js",
147
+ "jsx/runtime.js",
148
+ "jsx/runtime/jsx-runtime.js",
149
+ "jsx/runtime/jsx-dev-runtime.js",
150
+ "jsx/buildtime.js",
151
+ "jsx/buildtime/jsx-runtime.js",
152
+ "jsx/buildtime/jsx-dev-runtime.js",
153
+ "jsx/jsx-runtime.js",
110
154
  "vite.js",
111
155
  "build-profile.js",
112
156
  "build-optimizer.js",
package/server.js CHANGED
@@ -2044,10 +2044,11 @@ const __componentModule = (() => {
2044
2044
  const { createLazyRegistry, isLazyDescriptor } = __lazyRegistryModule;
2045
2045
  const componentKind = Symbol.for("@async/framework.component");
2046
2046
  let componentCounter = 0;
2047
+ let defineComponentWarned = false;
2047
2048
 
2048
- function defineComponent(fn) {
2049
+ function component(fn) {
2049
2050
  if (typeof fn !== "function") {
2050
- throw new TypeError("defineComponent(fn) requires a function.");
2051
+ throw new TypeError("component(fn) requires a function.");
2051
2052
  }
2052
2053
  Object.defineProperty(fn, componentKind, {
2053
2054
  configurable: true,
@@ -2056,7 +2057,13 @@ const __componentModule = (() => {
2056
2057
  return fn;
2057
2058
  }
2058
2059
 
2059
- const component = defineComponent;
2060
+ function defineComponent(fn) {
2061
+ if (!defineComponentWarned) {
2062
+ defineComponentWarned = true;
2063
+ console.warn?.("defineComponent(...) is deprecated. Use component(...) instead.");
2064
+ }
2065
+ return component(fn);
2066
+ }
2060
2067
 
2061
2068
  function createComponentRegistry(initialMap = {}, options = {}) {
2062
2069
  const registryStore = options.registry ?? createRegistryStore();
@@ -2255,10 +2262,11 @@ const __componentModule = (() => {
2255
2262
  }
2256
2263
 
2257
2264
  function createComponentContext({ runtime, scope, cleanups, attachHooks, visibleHooks, intersectionHooks, destroyHooks, renderScopedTemplate }) {
2258
- const { signals, handlers, loader, server, router, cache, scheduler } = runtime;
2265
+ const { signals, handlers, loader, server, router, cache, components, scheduler } = runtime;
2259
2266
  const generatedHandlers = new WeakMap();
2260
2267
  let generatedHandlerCounter = 0;
2261
2268
  let generatedSignalCounter = 0;
2269
+ let generatedSlotCounter = 0;
2262
2270
  const context = {
2263
2271
  scope,
2264
2272
  signals,
@@ -2267,6 +2275,7 @@ const __componentModule = (() => {
2267
2275
  server,
2268
2276
  router,
2269
2277
  cache,
2278
+ components,
2270
2279
  scheduler,
2271
2280
 
2272
2281
  signal(name, initial) {
@@ -2346,6 +2355,38 @@ const __componentModule = (() => {
2346
2355
  return rawHtml(child.html);
2347
2356
  },
2348
2357
 
2358
+ slot(Child, propsOrFn = {}) {
2359
+ let target;
2360
+ let latestProps = {};
2361
+ const renderSlot = () => {
2362
+ if (!target) {
2363
+ return;
2364
+ }
2365
+ loader.mount(target, Child, latestProps);
2366
+ };
2367
+ const attach = registerScopedHandler(`slot.${++generatedSlotCounter}.attach`, function ({ element }) {
2368
+ target = element;
2369
+ renderSlot();
2370
+ return () => {
2371
+ target = undefined;
2372
+ };
2373
+ });
2374
+ const cleanup = signals.effect(() => {
2375
+ latestProps = typeof propsOrFn === "function" ? propsOrFn.call(context) : propsOrFn;
2376
+ renderSlot();
2377
+ }, {
2378
+ scheduler,
2379
+ phase: "effect",
2380
+ scope,
2381
+ key: `slot:${generatedSlotCounter}`
2382
+ });
2383
+ cleanups.push(cleanup);
2384
+ return {
2385
+ attach,
2386
+ render: renderSlot
2387
+ };
2388
+ },
2389
+
2349
2390
  suspense(signalRef, views) {
2350
2391
  const id = signalRef?.id;
2351
2392
  if (!id) {
@@ -2465,7 +2506,7 @@ const __componentModule = (() => {
2465
2506
  function componentName(Component) {
2466
2507
  return Component.displayName || Component.name || "anonymous";
2467
2508
  }
2468
- return { defineComponent, createComponentRegistry, isComponent, renderComponent, component };
2509
+ return { component, defineComponent, createComponentRegistry, isComponent, renderComponent };
2469
2510
  })();
2470
2511
 
2471
2512
  const __serverModule = (() => {
@@ -3522,7 +3563,7 @@ const __loaderModule = (() => {
3522
3563
  const { matchAttribute, normalizeAttributeConfig, readAttribute } = __attributesModule;
3523
3564
  const inlineBindingPrefix = "__async:inline:";
3524
3565
 
3525
- function Loader({ root, signals, handlers, server, router, cache, attributes, scheduler } = {}) {
3566
+ function Loader({ root, signals, handlers, server, router, cache, components, attributes, scheduler } = {}) {
3526
3567
  const documentRef = root?.ownerDocument ?? root ?? globalThis.document;
3527
3568
  const rootNode = root ?? documentRef;
3528
3569
  const signalRegistry = signals ?? createSignalRegistry();
@@ -3538,6 +3579,7 @@ const __loaderModule = (() => {
3538
3579
  const intersectionBindings = new WeakMap();
3539
3580
  const boundaryState = new WeakMap();
3540
3581
  const renderingBoundaries = new WeakSet();
3582
+ const componentBindings = new WeakSet();
3541
3583
  const inlineBindings = new Map();
3542
3584
  const scopedCleanups = new WeakMap();
3543
3585
  let inlineBindingCounter = 0;
@@ -3550,6 +3592,7 @@ const __loaderModule = (() => {
3550
3592
  server,
3551
3593
  router,
3552
3594
  cache,
3595
+ components,
3553
3596
  scheduler: schedulerInstance,
3554
3597
  attributes: attributeConfig,
3555
3598
 
@@ -3566,6 +3609,7 @@ const __loaderModule = (() => {
3566
3609
  bindClassAttributes(rootOrFragment);
3567
3610
  bindEventAttributes(rootOrFragment);
3568
3611
  bindBoundaries(rootOrFragment);
3612
+ bindComponentAttributes(rootOrFragment);
3569
3613
  runPseudoEvents(rootOrFragment);
3570
3614
  return api;
3571
3615
  },
@@ -3591,6 +3635,7 @@ const __loaderModule = (() => {
3591
3635
  server: api.server,
3592
3636
  router: api.router,
3593
3637
  cache: api.cache,
3638
+ components: api.components,
3594
3639
  scheduler: schedulerInstance,
3595
3640
  attributes: attributeConfig
3596
3641
  });
@@ -3885,6 +3930,32 @@ const __loaderModule = (() => {
3885
3930
  }
3886
3931
  }
3887
3932
 
3933
+ function bindComponentAttributes(scope) {
3934
+ for (const element of elementsIn(scope)) {
3935
+ const id = readAttribute(element, attributeConfig, "async", "component");
3936
+ if (id == null) {
3937
+ continue;
3938
+ }
3939
+ if (componentBindings.has(element)) {
3940
+ continue;
3941
+ }
3942
+ if (!components?.resolve) {
3943
+ throw new Error(`Component "${id}" cannot be mounted because no component registry is available.`);
3944
+ }
3945
+ const Component = components.resolve(id);
3946
+ if (!Component) {
3947
+ throw new Error(`Component "${id}" was not found.`);
3948
+ }
3949
+ componentBindings.add(element);
3950
+ try {
3951
+ api.mount(element, Component);
3952
+ } catch (error) {
3953
+ componentBindings.delete(element);
3954
+ throw error;
3955
+ }
3956
+ }
3957
+ }
3958
+
3888
3959
  function renderBoundary(boundary) {
3889
3960
  const state = boundaryState.get(boundary);
3890
3961
  if (!state) {
@@ -5264,9 +5335,12 @@ const __appModule = (() => {
5264
5335
  const registry = createRegistryStore(undefined, { target: "browser" });
5265
5336
  const runtimes = new Set();
5266
5337
  const createRuntime = options.createRuntime ?? createApp;
5338
+ const loaderFacade = createLoaderFacade();
5339
+ let currentRuntime;
5267
5340
 
5268
5341
  const app = {
5269
5342
  registry,
5343
+ loader: loaderFacade,
5270
5344
 
5271
5345
  use(typeOrModule, entries) {
5272
5346
  const normalized = normalizeUse(typeOrModule, entries);
@@ -5283,7 +5357,7 @@ const __appModule = (() => {
5283
5357
 
5284
5358
  start(options = {}) {
5285
5359
  const runtime = createRuntime(app, options).start();
5286
- app.runtime = runtime;
5360
+ setCurrentRuntime(runtime);
5287
5361
  return runtime;
5288
5362
  },
5289
5363
 
@@ -5292,12 +5366,12 @@ const __appModule = (() => {
5292
5366
  },
5293
5367
 
5294
5368
  detachRoot(root) {
5295
- return app.runtime?.detachRoot(root) ?? app;
5369
+ return currentRuntime?.detachRoot(root) ?? app;
5296
5370
  },
5297
5371
 
5298
5372
  applySnapshot(snapshot, snapshotOptions = {}) {
5299
- if (app.runtime) {
5300
- app.runtime.applySnapshot(snapshot, snapshotOptions);
5373
+ if (currentRuntime) {
5374
+ currentRuntime.applySnapshot(snapshot, snapshotOptions);
5301
5375
  return app;
5302
5376
  }
5303
5377
  appendSnapshotDeclarations(registry, snapshot, snapshotOptions);
@@ -5305,7 +5379,11 @@ const __appModule = (() => {
5305
5379
  },
5306
5380
 
5307
5381
  inspectRoots() {
5308
- return app.runtime?.inspectRoots() ?? { count: 0, roots: [] };
5382
+ return currentRuntime?.inspectRoots() ?? { count: 0, roots: [] };
5383
+ },
5384
+
5385
+ inspectRuntime() {
5386
+ return inspectRuntimeState(currentRuntime, loaderFacade);
5309
5387
  },
5310
5388
 
5311
5389
  _attach(runtime) {
@@ -5315,14 +5393,36 @@ const __appModule = (() => {
5315
5393
 
5316
5394
  _detach(runtime) {
5317
5395
  runtimes.delete(runtime);
5396
+ if (currentRuntime === runtime) {
5397
+ currentRuntime = latestRuntime(runtimes);
5398
+ }
5318
5399
  }
5319
5400
  };
5320
5401
 
5402
+ Object.defineProperties(app, {
5403
+ _runtime: {
5404
+ get() {
5405
+ return currentRuntime;
5406
+ }
5407
+ },
5408
+ _setRuntime: {
5409
+ value(runtime) {
5410
+ setCurrentRuntime(runtime);
5411
+ }
5412
+ }
5413
+ });
5414
+
5321
5415
  if (initial) {
5322
5416
  app.use(initial);
5323
5417
  }
5324
5418
 
5325
5419
  return app;
5420
+
5421
+ function setCurrentRuntime(runtime) {
5422
+ if (runtime) {
5423
+ currentRuntime = runtime;
5424
+ }
5425
+ }
5326
5426
  }
5327
5427
 
5328
5428
  function createApp(appOrDefinition = Async, options = {}) {
@@ -5385,6 +5485,7 @@ const __appModule = (() => {
5385
5485
  return runtime;
5386
5486
  }
5387
5487
  started = true;
5488
+ app._setRuntime?.(runtime);
5388
5489
 
5389
5490
  if (target !== "server") {
5390
5491
  configureServerContext({ cache: browserCache });
@@ -5394,6 +5495,7 @@ const __appModule = (() => {
5394
5495
  registerRootLoader(loader.root, loader);
5395
5496
  loader.start();
5396
5497
  startRouterFor(loader.root);
5498
+ app.loader._setCurrent(runtime.loader);
5397
5499
  } else if (startupRoot != null) {
5398
5500
  runtime.attachRoot(startupRoot);
5399
5501
  }
@@ -5430,6 +5532,7 @@ const __appModule = (() => {
5430
5532
  handlers,
5431
5533
  server,
5432
5534
  cache: browserCache,
5535
+ components,
5433
5536
  scheduler,
5434
5537
  attributes
5435
5538
  });
@@ -5438,6 +5541,7 @@ const __appModule = (() => {
5438
5541
  configureServerContext({ cache: browserCache });
5439
5542
  signals._setContext?.({ server, loader: runtime.loader, cache: browserCache, scheduler });
5440
5543
  startRouterFor(root);
5544
+ app.loader._setCurrent(runtime.loader);
5441
5545
  return runtime;
5442
5546
  },
5443
5547
 
@@ -5447,6 +5551,7 @@ const __appModule = (() => {
5447
5551
  return runtime;
5448
5552
  }
5449
5553
  if (root == null) {
5554
+ const detachedLoaders = [...new Set(rootLoaders.values())];
5450
5555
  for (const rootLoader of new Set(rootLoaders.values())) {
5451
5556
  rootLoader.destroy?.();
5452
5557
  }
@@ -5457,6 +5562,7 @@ const __appModule = (() => {
5457
5562
  loader = undefined;
5458
5563
  runtime.loader = undefined;
5459
5564
  runtime.router = undefined;
5565
+ app.loader._clearCurrent(detachedLoaders);
5460
5566
  return runtime;
5461
5567
  }
5462
5568
  const rootLoader = rootLoaders.get(root);
@@ -5475,6 +5581,9 @@ const __appModule = (() => {
5475
5581
  runtime.router = undefined;
5476
5582
  if (next) {
5477
5583
  startRouterFor(next.root);
5584
+ app.loader._setCurrent(next);
5585
+ } else {
5586
+ app.loader._clearCurrent(rootLoader);
5478
5587
  }
5479
5588
  }
5480
5589
  return runtime;
@@ -5562,6 +5671,8 @@ const __appModule = (() => {
5562
5671
  if (loader && !destroyedLoaders.has(loader)) {
5563
5672
  loader?.destroy?.();
5564
5673
  }
5674
+ app.loader._clearCurrent([...destroyedLoaders, loader]);
5675
+ app.loader._rejectPending(new Error("Async loader queue was cleared because the runtime was destroyed."));
5565
5676
  signals.destroy?.();
5566
5677
  if (ownsScheduler) {
5567
5678
  scheduler.destroy();
@@ -5573,6 +5684,22 @@ const __appModule = (() => {
5573
5684
  }
5574
5685
  };
5575
5686
 
5687
+ Object.defineProperties(runtime, {
5688
+ _inspect: {
5689
+ value() {
5690
+ return {
5691
+ active: !destroyed,
5692
+ started,
5693
+ destroyed,
5694
+ target,
5695
+ roots: runtime.inspectRoots(),
5696
+ loader: app.loader.inspect(),
5697
+ router: Boolean(runtime.router)
5698
+ };
5699
+ }
5700
+ }
5701
+ });
5702
+
5576
5703
  server.cache = serverCache;
5577
5704
  runtime.server.cache = serverCache;
5578
5705
  runtime.applySnapshot(initialSnapshot, { strict: options.strictSnapshots ?? true });
@@ -5649,6 +5776,107 @@ const __appModule = (() => {
5649
5776
 
5650
5777
  const Async = defineApp();
5651
5778
 
5779
+ function createLoaderFacade() {
5780
+ let current;
5781
+ const pending = [];
5782
+ const readyWaiters = [];
5783
+
5784
+ const facade = {
5785
+ get current() {
5786
+ return current;
5787
+ },
5788
+
5789
+ ready() {
5790
+ if (current) {
5791
+ return Promise.resolve(current);
5792
+ }
5793
+ return new Promise((resolve, reject) => {
5794
+ readyWaiters.push({ resolve, reject });
5795
+ });
5796
+ },
5797
+
5798
+ scan(rootOrFragment) {
5799
+ return enqueue("scan", [rootOrFragment]);
5800
+ },
5801
+
5802
+ swap(boundaryId, fragmentOrTemplate) {
5803
+ return enqueue("swap", [boundaryId, fragmentOrTemplate]);
5804
+ },
5805
+
5806
+ mount(target, Component, props) {
5807
+ return enqueue("mount", [target, Component, props]);
5808
+ },
5809
+
5810
+ inspect() {
5811
+ return {
5812
+ ready: Boolean(current),
5813
+ pending: pending.length,
5814
+ root: current?.root
5815
+ };
5816
+ }
5817
+ };
5818
+
5819
+ Object.defineProperties(facade, {
5820
+ _setCurrent: {
5821
+ value(loader) {
5822
+ if (!loader) {
5823
+ return;
5824
+ }
5825
+ current = loader;
5826
+ while (readyWaiters.length > 0) {
5827
+ readyWaiters.shift().resolve(loader);
5828
+ }
5829
+ flushPending(loader);
5830
+ }
5831
+ },
5832
+ _clearCurrent: {
5833
+ value(loaderOrLoaders) {
5834
+ if (loaderOrLoaders === undefined) {
5835
+ current = undefined;
5836
+ return;
5837
+ }
5838
+ const loaders = Array.isArray(loaderOrLoaders) ? loaderOrLoaders : [loaderOrLoaders];
5839
+ if (loaders.includes(current)) {
5840
+ current = undefined;
5841
+ }
5842
+ }
5843
+ },
5844
+ _rejectPending: {
5845
+ value(error) {
5846
+ while (pending.length > 0) {
5847
+ pending.shift().reject(error);
5848
+ }
5849
+ while (readyWaiters.length > 0) {
5850
+ readyWaiters.shift().reject(error);
5851
+ }
5852
+ }
5853
+ }
5854
+ });
5855
+
5856
+ return facade;
5857
+
5858
+ function enqueue(method, args) {
5859
+ if (current) {
5860
+ return invoke(current, method, args);
5861
+ }
5862
+ return new Promise((resolve, reject) => {
5863
+ pending.push({ method, args, resolve, reject });
5864
+ });
5865
+ }
5866
+
5867
+ function flushPending(loader) {
5868
+ while (pending.length > 0) {
5869
+ const operation = pending.shift();
5870
+ invoke(loader, operation.method, operation.args)
5871
+ .then(operation.resolve, operation.reject);
5872
+ }
5873
+ }
5874
+
5875
+ async function invoke(loader, method, args) {
5876
+ return loader[method](...args);
5877
+ }
5878
+ }
5879
+
5652
5880
  function readSnapshot(root = globalThis.document, { attributes } = {}) {
5653
5881
  const attributeConfig = normalizeAttributeConfig(attributes);
5654
5882
  const snapshotAttr = attributeName(attributeConfig, "async", "snapshot");
@@ -5799,10 +6027,33 @@ const __appModule = (() => {
5799
6027
  }
5800
6028
 
5801
6029
  function ensureRuntime(app) {
5802
- if (!app.runtime) {
6030
+ if (!app._runtime) {
5803
6031
  app.start();
5804
6032
  }
5805
- return app.runtime;
6033
+ return app._runtime;
6034
+ }
6035
+
6036
+ function latestRuntime(runtimes) {
6037
+ let latest;
6038
+ for (const runtime of runtimes) {
6039
+ latest = runtime;
6040
+ }
6041
+ return latest;
6042
+ }
6043
+
6044
+ function inspectRuntimeState(runtime, loaderFacade) {
6045
+ if (runtime?._inspect) {
6046
+ return runtime._inspect();
6047
+ }
6048
+ return {
6049
+ active: Boolean(runtime),
6050
+ started: Boolean(runtime),
6051
+ destroyed: false,
6052
+ target: runtime?.target,
6053
+ roots: runtime?.inspectRoots?.() ?? { count: 0, roots: [] },
6054
+ loader: loaderFacade.inspect(),
6055
+ router: Boolean(runtime?.router)
6056
+ };
5806
6057
  }
5807
6058
 
5808
6059
  function applySnapshotToRuntime(runtime, snapshot = {}, options = {}) {
@@ -6749,7 +7000,7 @@ const __boundaryReceiverModule = (() => {
6749
7000
  if (options.receiver && typeof options.receiver.apply === "function") {
6750
7001
  return options.receiver;
6751
7002
  }
6752
- const runtime = options.runtime ?? globalThis.Async?.runtime;
7003
+ const runtime = options.runtime ?? globalThis.Async?._runtime;
6753
7004
  const loader = options.loader ?? runtime?.loader;
6754
7005
  if (!loader) {
6755
7006
  throw new TypeError("AsyncStream requires receiver, loader, or runtime.loader.");
@@ -7346,7 +7597,7 @@ const __elementsModule = (() => {
7346
7597
  if (this.__asyncAttached) {
7347
7598
  return;
7348
7599
  }
7349
- const runtime = app.runtime ?? app.start?.();
7600
+ const runtime = app._runtime ?? app.start?.();
7350
7601
  runtime?.attachRoot?.(this);
7351
7602
  this.__asyncRuntime = runtime;
7352
7603
  this.__asyncAttached = true;