From 869abdb2ce6c725d963e91c254dd015650630ef5 Mon Sep 17 00:00:00 2001 From: clover caruso Date: Fri, 12 Dec 2025 03:17:53 -0800 Subject: [PATCH] chore: delete unused files suspense is moved to `kolmxrtq`, to be revived later --- framework/test-fixture/Component.marko | 4 - framework/test-fixture/UseComponent.marko | 6 -- suspense.test.tsx | 40 -------- suspense.ts | 116 ---------------------- 4 files changed, 166 deletions(-) delete mode 100644 framework/test-fixture/Component.marko delete mode 100644 framework/test-fixture/UseComponent.marko delete mode 100644 suspense.test.tsx delete mode 100644 suspense.ts diff --git a/framework/test-fixture/Component.marko b/framework/test-fixture/Component.marko deleted file mode 100644 index 5c1e5978baf9085bded35d8915ba34174d3f6af0..0000000000000000000000000000000000000000 --- a/framework/test-fixture/Component.marko +++ /dev/null @@ -1,4 +0,0 @@ -
-
- wait(${null}) -
diff --git a/framework/test-fixture/UseComponent.marko b/framework/test-fixture/UseComponent.marko deleted file mode 100644 index d116695bf3273346aa1f1891d543fc5d4dee7853..0000000000000000000000000000000000000000 --- a/framework/test-fixture/UseComponent.marko +++ /dev/null @@ -1,6 +0,0 @@ -import Component from './Component.marko'; - -

web page

- - - diff --git a/suspense.test.tsx b/suspense.test.tsx deleted file mode 100644 index 1750c5e7f514b8587023b689eef860ccb0b1f97b..0000000000000000000000000000000000000000 --- a/suspense.test.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { test } from "node:test"; -import { renderStreaming, Suspense } from "./suspense.ts"; - -test("sanity", async (t) => { - let resolve: () => void = null!; - - // @ts-expect-error - async function AsyncComponent() { - await new Promise((done) => resolve = done); - return ; - } - - const example = ( -
-

app shell

- - - -
(c) 2025
-
- ); - - const iterator = renderStreaming(example); - const assertContinue = (actual: unknown, value: unknown) => - t.assert.deepEqual(actual, { done: false, value }); - - assertContinue( - await iterator.next(), - "", - ); - t.assert.ok(resolve !== null), resolve(); - assertContinue( - await iterator.next(), - "", - ); - t.assert.deepEqual( - await iterator.next(), - { done: true, value: {} }, - ); -}); diff --git a/suspense.ts b/suspense.ts deleted file mode 100644 index ab6b52a941cbc199a36ec3640ec2ff3a22b4900c..0000000000000000000000000000000000000000 --- a/suspense.ts +++ /dev/null @@ -1,116 +0,0 @@ -// TODO: revive the suspense renderer -/** - * This file implements out-of-order HTML streaming, mimicking the React - * Suspense API. To use, place Suspense around an expensive async component - * and render the page with 'renderStreaming'. - * - * Implementation of this article: - * https://lamplightdev.com/blog/2024/01/10/streaming-html-out-of-order-without-javascript/ - * - * I would link to an article from Next.js or React, but their examples - * are too verbose and not informative to what they actually do. - * @module - */ -const userData = render.userData(() => null); - -export interface Input { - children: render.Node; - fallback?: render.Node; -} - -/** - * When used in combination with `Suspense.renderStreaming`, this component - * displays `fallback` until the async `children` `Node` has resolved.. - * - * return
- *

page shell

- * - * - * - *
; - */ -export function Suspense({ children, fallback }: Input): render.Node { - const state = userData.get(); - if (!state) return children; - if (state.nested) throw new Error(" cannot be nested"); - const parent = UNWRAP(render.current); - const r = render.init(true, { [userData.key]: { nested: true } }); - const resolved = render.resolveNode(r, children); - if (r.async == 0) return render.raw(resolved); - const name = "suspended_" + ++state.nextId; - state.nested = true; - const ip: [render.ResolvedNode] = [ - render.resolvedElement( - "slot", - { name }, - fallback ? render.resolveNode(parent, fallback) : "", - ), - ]; - state.nested = false; - r.asyncDone = () => { - const rejections = r.rejections; - if (rejections && rejections.length > 0) throw new Error("TODO"); - state.pushChunk?.(name, ip[0] = resolved); - }; - return render.raw(ip); -} - -// TODO: add a User-Agent parameter, which is used to determine if a -// fallback path must be used. -// - Before ~2024 needs to use a JS implementation. -// - IE should probably bail out entirely. -export async function* renderStreaming< - T extends render.Addons = Record, ->(node: render.Node, addon: T = {} as T) { - const { - text: begin, - addon: { [userData.key]: state, ...addonOutput }, - } = await render.async(node, { - ...addon, - [userData.key]: { - nested: false, - nextId: 0, - completed: 0, - pushChunk: () => {}, - } satisfies State as State, - }); - if (state.nextId === 0) { - yield begin; - return addonOutput as unknown as T; - } - let resolve: (() => void) | null = null; - let chunks: string[] = []; - state.pushChunk = (slot, node) => { - while (node.length === 1 && Array.isArray(node)) node = UNWRAP(node[0]); - if (node[0] === render.kElement) { - (node as render.ResolvedElement)[2].slot = slot; - } else { - node = render.resolvedElement("clover-suspense", { - style: "display:contents", - slot, - }, node); - } - chunks.push(render.stringifyNode(node)); - resolve?.(); - }; - yield ``; - do { - await new Promise((done) => (resolve = done)); - yield* chunks; - chunks = []; - } while (state!.nextId < state!.completed); - return addonOutput as unknown as T; -} - -interface State { - nested: boolean; - nextId: number; - completed: number; - pushChunk(name: string, node: render.ResolvedNode): void; -} - -export declare namespace Suspense { - export type { Input }; -} - -import * as render from "lib/render.ts"; -- 2.54.0