octane 0.2.11 → 0.2.13
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/README.md +5 -0
- package/dist/behavior-root.d.ts +13 -3
- package/dist/behavior-root.js +28 -5
- package/dist/cjs/behavior-root.cjs +32 -6
- package/dist/cjs/class-names.cjs +49 -0
- package/dist/cjs/constants.cjs +9 -0
- package/dist/cjs/context-epoch.cjs +38 -0
- package/dist/cjs/css.cjs +6 -27
- package/dist/cjs/data-encoding.cjs +160 -0
- package/dist/cjs/dom-binding-handoff.cjs +93 -0
- package/dist/cjs/dom-binding-protocol.cjs +115 -0
- package/dist/cjs/dom-binding-styles.cjs +292 -0
- package/dist/cjs/dom-bindings.cjs +700 -0
- package/dist/cjs/dom-focused-move.cjs +66 -0
- package/dist/cjs/dom-stage.cjs +896 -0
- package/dist/cjs/dom-tables.cjs +4 -94
- package/dist/cjs/error-codes.client.generated.cjs +33 -0
- package/dist/cjs/error-codes.server.generated.cjs +24 -0
- package/dist/cjs/hydration/control-capture.cjs +244 -0
- package/dist/cjs/hydration/event-capture.cjs +125 -43
- package/dist/cjs/hydration/interaction-config.cjs +50 -2
- package/dist/cjs/hydration-markers.cjs +37 -0
- package/dist/cjs/independent-hydration-protocol.cjs +106 -0
- package/dist/cjs/index.cjs +9 -0
- package/dist/cjs/runtime.cjs +6397 -1683
- package/dist/cjs/runtime.server.cjs +1465 -213
- package/dist/cjs/server/early-signals.cjs +45 -0
- package/dist/cjs/server/index.cjs +47 -0
- package/dist/cjs/server/rpc-batch.cjs +149 -0
- package/dist/cjs/server/rpc-stream.cjs +146 -0
- package/dist/cjs/server/rpc.cjs +34 -15
- package/dist/cjs/server/signal-query-observation.cjs +158 -0
- package/dist/cjs/server/streamed-region.cjs +52 -0
- package/dist/cjs/server/streamed-signals.cjs +512 -0
- package/dist/cjs/server-call.cjs +103 -0
- package/dist/cjs/server-rpc-batch-client.cjs +141 -0
- package/dist/cjs/server-rpc-client.cjs +94 -27
- package/dist/cjs/server-rpc-protocol.cjs +141 -0
- package/dist/cjs/server-rpc-stream-client.cjs +118 -0
- package/dist/cjs/signals/actions.cjs +474 -0
- package/dist/cjs/signals/client.cjs +4 -1
- package/dist/cjs/signals/computations.cjs +460 -0
- package/dist/cjs/signals/control-binding.cjs +368 -0
- package/dist/cjs/signals/derived-facade.cjs +50 -0
- package/dist/cjs/signals/document-owner.cjs +71 -0
- package/dist/cjs/signals/early-values.cjs +155 -0
- package/dist/cjs/signals/encoding.cjs +6 -95
- package/dist/cjs/signals/engine.cjs +276 -12
- package/dist/cjs/signals/errors.cjs +18 -0
- package/dist/cjs/signals/facade.cjs +477 -0
- package/dist/cjs/signals/graph.cjs +166 -20
- package/dist/cjs/signals/handle-protocol.cjs +36 -0
- package/dist/cjs/signals/index.cjs +81 -2
- package/dist/cjs/signals/native-read-client.cjs +10 -0
- package/dist/cjs/signals/owner-context.cjs +112 -0
- package/dist/cjs/signals/query-attempt-observer.cjs +68 -0
- package/dist/cjs/signals/query-facade.cjs +72 -0
- package/dist/cjs/signals/read-protocol.cjs +54 -0
- package/dist/cjs/signals/requests.cjs +287 -14
- package/dist/cjs/signals/scalar-computations.cjs +76 -0
- package/dist/cjs/signals/server.cjs +4 -1
- package/dist/cjs/signals/transition-candidate.cjs +567 -0
- package/dist/cjs/signals/transition-state.cjs +106 -0
- package/dist/cjs/signals/types.cjs +50 -0
- package/dist/cjs/stream-protocol.cjs +3 -0
- package/dist/cjs/streamed-signals-protocol.cjs +159 -0
- package/dist/cjs/style-values.cjs +122 -0
- package/dist/cjs/trusted-html.cjs +30 -0
- package/dist/cjs/version.cjs +1 -1
- package/dist/class-names.d.ts +5 -0
- package/dist/class-names.js +25 -0
- package/dist/compiler/bundler.js +51 -22
- package/dist/compiler/compile.js +2534 -581
- package/dist/compiler/dom-binding-program.js +935 -0
- package/dist/compiler/dom-binding-request.js +57 -0
- package/dist/compiler/dom-bindings.js +2245 -0
- package/dist/compiler/hook-deps.js +759 -10
- package/dist/compiler/hydrate-boundaries.js +358 -15
- package/dist/compiler/index.d.ts +39 -2
- package/dist/compiler/index.js +1 -0
- package/dist/compiler/native-attribute-reads.js +127 -0
- package/dist/compiler/native-change-diagnostics.js +32 -38
- package/dist/compiler/native-read-diagnostics.js +69 -8
- package/dist/compiler/native-read-types.js +80 -34
- package/dist/compiler/parser.node.js +1 -1
- package/dist/compiler/renderer-boundaries.js +40 -0
- package/dist/compiler/server-context.js +118 -0
- package/dist/compiler/signal-attempt-reads.js +479 -0
- package/dist/compiler/signal-declarations.js +557 -0
- package/dist/compiler/signal-start-reads.js +413 -0
- package/dist/compiler/slot-hooks.d.ts +3 -1
- package/dist/compiler/slot-hooks.js +168 -34
- package/dist/compiler/strong-auto-memo.js +90 -0
- package/dist/compiler/strong-html.js +143 -0
- package/dist/compiler/strong-mode.js +764 -66
- package/dist/compiler/strong-template-policy.js +307 -0
- package/dist/compiler/template-ir.js +200 -0
- package/dist/compiler/typescript.d.ts +2 -0
- package/dist/compiler/typescript.js +2 -0
- package/dist/compiler/vite.d.ts +3 -1
- package/dist/compiler/vite.js +122 -4
- package/dist/compiler/volar.LICENSES.txt +1 -1
- package/dist/compiler/volar.d.ts +6 -1
- package/dist/compiler/volar.js +750 -1433
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +10 -0
- package/dist/context-epoch.d.ts +2 -0
- package/dist/context-epoch.js +13 -0
- package/dist/css.d.ts +2 -5
- package/dist/css.js +2 -23
- package/dist/data-encoding.d.ts +9 -0
- package/dist/data-encoding.js +134 -0
- package/dist/dom-binding-classes.d.ts +15 -0
- package/dist/dom-binding-classes.js +129 -0
- package/dist/dom-binding-controls.d.ts +2 -0
- package/dist/dom-binding-controls.js +6 -0
- package/dist/dom-binding-handoff.d.ts +55 -0
- package/dist/dom-binding-handoff.js +62 -0
- package/dist/dom-binding-program.d.ts +300 -0
- package/dist/dom-binding-program.js +1625 -0
- package/dist/dom-binding-projections.d.ts +15 -0
- package/dist/dom-binding-projections.js +187 -0
- package/dist/dom-binding-protocol.d.ts +13 -0
- package/dist/dom-binding-protocol.js +88 -0
- package/dist/dom-binding-signals.d.ts +21 -0
- package/dist/dom-binding-signals.js +109 -0
- package/dist/dom-binding-styles.d.ts +17 -0
- package/dist/dom-binding-styles.js +272 -0
- package/dist/dom-bindings.d.ts +89 -0
- package/dist/dom-bindings.js +670 -0
- package/dist/dom-focused-move.d.ts +6 -0
- package/dist/dom-focused-move.js +42 -0
- package/dist/dom-stage.d.ts +52 -0
- package/dist/dom-stage.js +872 -0
- package/dist/dom-tables.d.ts +1 -3
- package/dist/dom-tables.js +1 -91
- package/dist/error-codes.client.generated.d.ts +9 -0
- package/dist/error-codes.client.generated.js +33 -0
- package/dist/error-codes.server.generated.d.ts +6 -0
- package/dist/error-codes.server.generated.js +24 -0
- package/dist/hydration/control-capture.d.ts +62 -0
- package/dist/hydration/control-capture.js +223 -0
- package/dist/hydration/document-lifecycle.d.ts +23 -0
- package/dist/hydration/document-lifecycle.js +80 -0
- package/dist/hydration/event-capture.d.ts +20 -1
- package/dist/hydration/event-capture.js +128 -42
- package/dist/hydration/independent-island.d.ts +45 -0
- package/dist/hydration/independent-island.js +233 -0
- package/dist/hydration/index.d.ts +8 -1
- package/dist/hydration/index.js +55 -1
- package/dist/hydration/interaction-config.d.ts +5 -0
- package/dist/hydration/interaction-config.js +44 -1
- package/dist/hydration/stream-delivery.d.ts +32 -0
- package/dist/hydration/stream-delivery.js +333 -0
- package/dist/hydration/stream-receiver.d.ts +26 -0
- package/dist/hydration/stream-receiver.js +204 -0
- package/dist/hydration/stream-result-receiver.d.ts +70 -0
- package/dist/hydration/stream-result-receiver.js +246 -0
- package/dist/hydration/streamed-signals.d.ts +44 -0
- package/dist/hydration/streamed-signals.js +186 -0
- package/dist/hydration/types.d.ts +6 -0
- package/dist/hydration-markers.d.ts +7 -0
- package/dist/hydration-markers.js +10 -0
- package/dist/independent-hydration-protocol.d.ts +31 -0
- package/dist/independent-hydration-protocol.js +80 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +6 -0
- package/dist/internal/signal-read.d.ts +1 -0
- package/dist/internal/signal-read.js +4 -0
- package/dist/jsx-runtime-strong.d.ts +33 -0
- package/dist/jsx-runtime.d.ts +58 -2
- package/dist/public-types.d.ts +15 -1
- package/dist/runtime.d.ts +297 -23
- package/dist/runtime.js +6405 -1679
- package/dist/runtime.server.d.ts +110 -27
- package/dist/runtime.server.js +1458 -213
- package/dist/server/early-signals.d.ts +14 -0
- package/dist/server/early-signals.js +34 -0
- package/dist/server/index.d.ts +11 -2
- package/dist/server/index.js +50 -1
- package/dist/server/rpc-batch.d.ts +17 -0
- package/dist/server/rpc-batch.js +129 -0
- package/dist/server/rpc-stream.d.ts +9 -0
- package/dist/server/rpc-stream.js +125 -0
- package/dist/server/rpc.d.ts +5 -1
- package/dist/server/rpc.js +37 -13
- package/dist/server/signal-query-observation.d.ts +3 -0
- package/dist/server/signal-query-observation.js +134 -0
- package/dist/server/streamed-region.d.ts +15 -0
- package/dist/server/streamed-region.js +30 -0
- package/dist/server/streamed-signals.d.ts +45 -0
- package/dist/server/streamed-signals.js +488 -0
- package/dist/server-call.d.ts +41 -0
- package/dist/server-call.js +75 -0
- package/dist/server-rpc-batch-client.d.ts +7 -0
- package/dist/server-rpc-batch-client.js +119 -0
- package/dist/server-rpc-client.d.ts +3 -1
- package/dist/server-rpc-client.js +99 -27
- package/dist/server-rpc-protocol.d.ts +47 -0
- package/dist/server-rpc-protocol.js +109 -0
- package/dist/server-rpc-stream-client.d.ts +5 -0
- package/dist/server-rpc-stream-client.js +98 -0
- package/dist/signals/actions.d.ts +12 -0
- package/dist/signals/actions.js +466 -0
- package/dist/signals/client.d.ts +2 -0
- package/dist/signals/client.js +1 -0
- package/dist/signals/computations.d.ts +37 -0
- package/dist/signals/computations.js +455 -0
- package/dist/signals/control-binding.d.ts +31 -0
- package/dist/signals/control-binding.js +353 -0
- package/dist/signals/derived-facade.d.ts +3 -0
- package/dist/signals/derived-facade.js +25 -0
- package/dist/signals/document-owner.d.ts +10 -0
- package/dist/signals/document-owner.js +43 -0
- package/dist/signals/early-values.d.ts +24 -0
- package/dist/signals/early-values.js +124 -0
- package/dist/signals/encoding.d.ts +1 -3
- package/dist/signals/encoding.js +3 -93
- package/dist/signals/engine.d.ts +53 -4
- package/dist/signals/engine.js +275 -16
- package/dist/signals/errors.d.ts +7 -0
- package/dist/signals/errors.js +16 -0
- package/dist/signals/facade.d.ts +74 -0
- package/dist/signals/facade.js +452 -0
- package/dist/signals/graph.d.ts +52 -6
- package/dist/signals/graph.js +174 -19
- package/dist/signals/handle-protocol.d.ts +4 -0
- package/dist/signals/handle-protocol.js +11 -0
- package/dist/signals/index.d.ts +12 -3
- package/dist/signals/index.js +71 -2
- package/dist/signals/native-read-client.d.ts +3 -0
- package/dist/signals/native-read-client.js +10 -0
- package/dist/signals/owner-context.d.ts +22 -0
- package/dist/signals/owner-context.js +77 -0
- package/dist/signals/query-attempt-observer.d.ts +49 -0
- package/dist/signals/query-attempt-observer.js +41 -0
- package/dist/signals/query-facade.d.ts +3 -0
- package/dist/signals/query-facade.js +49 -0
- package/dist/signals/read-protocol.d.ts +37 -2
- package/dist/signals/read-protocol.js +44 -0
- package/dist/signals/requests.d.ts +38 -5
- package/dist/signals/requests.js +298 -15
- package/dist/signals/scalar-computations.d.ts +2 -0
- package/dist/signals/scalar-computations.js +60 -0
- package/dist/signals/server.d.ts +2 -0
- package/dist/signals/server.js +1 -0
- package/dist/signals/transition-candidate.d.ts +71 -0
- package/dist/signals/transition-candidate.js +557 -0
- package/dist/signals/transition-state.d.ts +51 -0
- package/dist/signals/transition-state.js +70 -0
- package/dist/signals/types.d.ts +95 -5
- package/dist/signals/types.js +20 -0
- package/dist/stream-protocol.d.ts +0 -5
- package/dist/stream-protocol.js +3 -0
- package/dist/streamed-signals-protocol.d.ts +60 -0
- package/dist/streamed-signals-protocol.js +130 -0
- package/dist/style-values.d.ts +3 -0
- package/dist/style-values.js +96 -0
- package/dist/trusted-html.d.ts +17 -0
- package/dist/trusted-html.js +6 -0
- package/dist/universal-core.d.ts +6 -0
- package/dist/universal-core.js +214 -202
- package/dist/version.js +1 -1
- package/package.json +48 -5
package/dist/signals/types.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** Runtime brands for signal handles and legacy query requests. */
|
|
2
2
|
export declare const SIGNAL_HANDLE: unique symbol;
|
|
3
|
+
export declare const SIGNAL_BINDING_READ: unique symbol;
|
|
4
|
+
export declare const SIGNAL_BINDING_SUBSCRIBE: unique symbol;
|
|
5
|
+
export declare const SIGNAL_BINDING_IDENTITY: unique symbol;
|
|
3
6
|
export declare const QUERY_REQUEST: unique symbol;
|
|
7
|
+
export declare const SIGNAL_OWNER_RESOLVE: unique symbol;
|
|
8
|
+
/** A query selector result that deliberately selects no request. */
|
|
9
|
+
export declare const skip: unique symbol;
|
|
4
10
|
export type ConnectionState = 'none' | 'connecting' | 'open' | 'closed';
|
|
5
11
|
interface SnapshotActivity {
|
|
6
12
|
readonly refreshing: boolean;
|
|
@@ -11,6 +17,8 @@ interface SnapshotActivity {
|
|
|
11
17
|
export type SignalSnapshot<T> = SnapshotActivity & ({
|
|
12
18
|
readonly status: 'ready';
|
|
13
19
|
readonly value: T;
|
|
20
|
+
} | {
|
|
21
|
+
readonly status: 'idle';
|
|
14
22
|
} | {
|
|
15
23
|
readonly status: 'pending';
|
|
16
24
|
} | {
|
|
@@ -18,8 +26,13 @@ export type SignalSnapshot<T> = SnapshotActivity & ({
|
|
|
18
26
|
readonly error: unknown;
|
|
19
27
|
});
|
|
20
28
|
export interface SignalHandle<T> {
|
|
21
|
-
readonly [SIGNAL_HANDLE]:
|
|
29
|
+
readonly [SIGNAL_HANDLE]: true;
|
|
30
|
+
readonly [SIGNAL_BINDING_READ]: () => T;
|
|
31
|
+
/** @internal Observe invalidation; optional teardown replaces the owning scope's final invalidation. */
|
|
32
|
+
readonly [SIGNAL_BINDING_SUBSCRIBE]: (notify: () => void, onRetire?: () => void) => () => void;
|
|
33
|
+
readonly [SIGNAL_BINDING_IDENTITY]: () => SignalBindingIdentity;
|
|
22
34
|
readonly key: string;
|
|
35
|
+
readonly kind: 'signal' | 'derived' | 'async';
|
|
23
36
|
get(): T;
|
|
24
37
|
latest(): T | undefined;
|
|
25
38
|
latest<F>(fallback: F): T | F;
|
|
@@ -27,6 +40,11 @@ export interface SignalHandle<T> {
|
|
|
27
40
|
/** Subscriptions do not deliver an initial notification. */
|
|
28
41
|
subscribe(notify: () => void): () => void;
|
|
29
42
|
}
|
|
43
|
+
/** Stable renderer-facing identity for a direct signal binding. */
|
|
44
|
+
export interface SignalBindingIdentity {
|
|
45
|
+
readonly scope: 'document' | 'instance';
|
|
46
|
+
readonly nodeKey: string;
|
|
47
|
+
}
|
|
30
48
|
export interface WritableSignal<T> extends SignalHandle<T> {
|
|
31
49
|
readonly kind: 'signal';
|
|
32
50
|
set(value: T | ((previous: T) => T)): void;
|
|
@@ -34,14 +52,39 @@ export interface WritableSignal<T> extends SignalHandle<T> {
|
|
|
34
52
|
export interface DerivedSignal<T> extends SignalHandle<T> {
|
|
35
53
|
readonly kind: 'derived';
|
|
36
54
|
}
|
|
55
|
+
export interface AttemptRead {
|
|
56
|
+
<T>(handle$: SignalHandle<T>): Promise<T>;
|
|
57
|
+
}
|
|
58
|
+
export interface DerivedContext {
|
|
59
|
+
readonly signal: AbortSignal;
|
|
60
|
+
readonly read: AttemptRead;
|
|
61
|
+
}
|
|
62
|
+
export interface SignalOptions {
|
|
63
|
+
/** Stable authored identity; the compiler supplies a site when omitted. */
|
|
64
|
+
readonly key?: string;
|
|
65
|
+
}
|
|
66
|
+
export interface DerivedOptions {
|
|
67
|
+
/** Assert that the computation returns synchronously and skip async-shape detection. */
|
|
68
|
+
readonly sync?: boolean;
|
|
69
|
+
}
|
|
70
|
+
export interface QueryOptions {
|
|
71
|
+
readonly kind?: 'promise' | 'stream';
|
|
72
|
+
}
|
|
73
|
+
export type DerivedCompute<T> = (context: DerivedContext) => T | PromiseLike<T | AsyncIterable<T>> | AsyncIterable<T>;
|
|
74
|
+
export type QueryLoadResult<T> = T | PromiseLike<T | AsyncIterable<T>> | AsyncIterable<T>;
|
|
37
75
|
export interface Resource<T> extends SignalHandle<T> {
|
|
38
76
|
readonly kind: 'async';
|
|
39
77
|
retry(options?: {
|
|
40
78
|
pending?: boolean;
|
|
41
79
|
}): void;
|
|
42
80
|
}
|
|
43
|
-
export interface
|
|
81
|
+
export interface QuerySignal<T> extends Resource<T> {
|
|
82
|
+
refetch(): void;
|
|
83
|
+
reset(): void;
|
|
84
|
+
}
|
|
85
|
+
export interface QueryContext<T = unknown> {
|
|
44
86
|
readonly signal: AbortSignal;
|
|
87
|
+
readonly previous?: T;
|
|
45
88
|
}
|
|
46
89
|
export interface QueryRequest<T> {
|
|
47
90
|
readonly [QUERY_REQUEST]: T;
|
|
@@ -99,7 +142,7 @@ export interface ScopeInspection {
|
|
|
99
142
|
readonly nodes: readonly {
|
|
100
143
|
readonly key: string;
|
|
101
144
|
readonly kind: 'signal' | 'derived' | 'async';
|
|
102
|
-
readonly status: 'ready' | 'pending' | 'error' | 'unevaluated';
|
|
145
|
+
readonly status: 'idle' | 'ready' | 'pending' | 'error' | 'unevaluated';
|
|
103
146
|
readonly revision: number;
|
|
104
147
|
readonly subscribers: number;
|
|
105
148
|
readonly retained: boolean;
|
|
@@ -127,7 +170,6 @@ export interface Scope {
|
|
|
127
170
|
readonly retired: boolean;
|
|
128
171
|
signal$<T>(key: string, initial: T): WritableSignal<T>;
|
|
129
172
|
derived$<T>(key: string, compute: (() => T) & (T extends PromiseLike<unknown> ? never : unknown)): DerivedSignal<T>;
|
|
130
|
-
asyncSignal$<T>(key: string, describe: () => QueryRequest<T>): Resource<T>;
|
|
131
173
|
get<T>(handle$: SignalHandle<T>): T;
|
|
132
174
|
set<T>(handle$: WritableSignal<T>, value: T | ((previous: T) => T)): void;
|
|
133
175
|
isPending(read: () => unknown): boolean;
|
|
@@ -138,4 +180,52 @@ export interface Scope {
|
|
|
138
180
|
inspect(): ScopeInspection;
|
|
139
181
|
dispose(): void;
|
|
140
182
|
}
|
|
183
|
+
export interface OwnerBoundSignal<T> extends SignalHandle<T> {
|
|
184
|
+
readonly [SIGNAL_OWNER_RESOLVE]: (owner: Scope) => SignalHandle<T>;
|
|
185
|
+
}
|
|
186
|
+
export interface SignalOwnerEnvironment {
|
|
187
|
+
current(): SignalOwner | null;
|
|
188
|
+
run<T>(owner: SignalOwner, callback: () => T): T;
|
|
189
|
+
capture(owner: SignalOwner): <T>(callback: () => T) => T;
|
|
190
|
+
}
|
|
191
|
+
/** A renderer identity is mapped lazily to a Scope only when signals are used. */
|
|
192
|
+
export interface SignalOwnerIdentity {
|
|
193
|
+
readonly scopeKey: string;
|
|
194
|
+
}
|
|
195
|
+
export interface SignalRendererOwnerIdentity extends SignalOwnerIdentity {
|
|
196
|
+
readonly documentOwner: SignalOwner;
|
|
197
|
+
readonly instanceOwner: object;
|
|
198
|
+
readonly instanceKey: string;
|
|
199
|
+
}
|
|
200
|
+
export type SignalOwner = Scope | SignalOwnerIdentity | SignalRendererOwnerIdentity;
|
|
201
|
+
export interface OptimisticSignal<T> extends WritableSignal<T> {
|
|
202
|
+
}
|
|
203
|
+
export interface OptimisticOptions<T> {
|
|
204
|
+
/**
|
|
205
|
+
* Compare authoritative revisions, not client invocation order or optimistic values.
|
|
206
|
+
* Return a finite positive number only when incoming is newer than current.
|
|
207
|
+
* Equal or older receipts settle their operation without replacing the source.
|
|
208
|
+
* The callback must be pure. Omitted policies reuse an existing source policy;
|
|
209
|
+
* otherwise adoption is unversioned and cannot order concurrent server receipts.
|
|
210
|
+
*/
|
|
211
|
+
readonly compareAuthority?: (incoming: T, current: T) => number;
|
|
212
|
+
}
|
|
213
|
+
export interface ActionUncertain {
|
|
214
|
+
readonly status: 'uncertain';
|
|
215
|
+
readonly operationId: string;
|
|
216
|
+
}
|
|
217
|
+
export interface ActionOperation {
|
|
218
|
+
readonly id: string;
|
|
219
|
+
readonly key: string;
|
|
220
|
+
readonly status: 'pending' | 'confirmed' | 'rejected' | 'uncertain';
|
|
221
|
+
set<T>(signal$: OptimisticSignal<T>, value: T | ((previous: T) => T)): void;
|
|
222
|
+
adopt<T>(value: T): void;
|
|
223
|
+
/** Remove only this operation's intent after a definitive rejection. */
|
|
224
|
+
reject(): void;
|
|
225
|
+
uncertain(): ActionUncertain;
|
|
226
|
+
until(read: () => unknown, options?: {
|
|
227
|
+
timeout?: number;
|
|
228
|
+
}): Promise<void>;
|
|
229
|
+
}
|
|
230
|
+
export type SignalAction<F extends (operation: ActionOperation, ...args: any[]) => any> = (...args: F extends (operation: ActionOperation, ...args: infer A) => any ? A : never) => ReturnType<F>;
|
|
141
231
|
export {};
|
package/dist/signals/types.js
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const SIGNAL_HANDLE = /* @__PURE__ */ Symbol.for("octane.signal-handle");
|
|
2
|
+
const SIGNAL_BINDING_READ = /* @__PURE__ */ Symbol.for("octane.signal-binding-read");
|
|
3
|
+
const SIGNAL_BINDING_SUBSCRIBE = /* @__PURE__ */ Symbol.for(
|
|
4
|
+
"octane.signal-binding-subscribe"
|
|
5
|
+
);
|
|
6
|
+
const SIGNAL_BINDING_IDENTITY = /* @__PURE__ */ Symbol.for(
|
|
7
|
+
"octane.signal-binding-identity"
|
|
8
|
+
);
|
|
9
|
+
const QUERY_REQUEST = /* @__PURE__ */ Symbol.for("octane.query-request");
|
|
10
|
+
const SIGNAL_OWNER_RESOLVE = /* @__PURE__ */ Symbol.for("octane.signal-owner-resolve");
|
|
11
|
+
const skip = /* @__PURE__ */ Symbol.for("octane.query-skip");
|
|
12
|
+
export {
|
|
13
|
+
QUERY_REQUEST,
|
|
14
|
+
SIGNAL_BINDING_IDENTITY,
|
|
15
|
+
SIGNAL_BINDING_READ,
|
|
16
|
+
SIGNAL_BINDING_SUBSCRIBE,
|
|
17
|
+
SIGNAL_HANDLE,
|
|
18
|
+
SIGNAL_OWNER_RESOLVE,
|
|
19
|
+
skip
|
|
20
|
+
};
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tiny client/server streaming protocol subset shared with the lightweight
|
|
3
|
-
* pre-root hydration event capture. Keep this module dependency-free: loading
|
|
4
|
-
* interaction capture before the main runtime must not initialize DOM tables.
|
|
5
|
-
*/
|
|
6
1
|
/** Sentinel <template> attribute marking a pending streamed boundary. */
|
|
7
2
|
export declare const STREAM_BOUNDARY_ATTR = "data-oct-b";
|
|
8
3
|
/** Render-unique token stamped on deferred-hydration owners in a streamed shell. */
|
package/dist/stream-protocol.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { isBindingOpenComment } from "./dom-binding-protocol.js";
|
|
1
2
|
const STREAM_BOUNDARY_ATTR = "data-oct-b";
|
|
2
3
|
const HYDRATE_STREAM_TOKEN_ATTR = "data-octane-stream-token";
|
|
3
4
|
function hydrationMarkerMultiplicity(data, open) {
|
|
4
5
|
const marker = open ? "[" : "]";
|
|
5
6
|
if (data === marker) return 1;
|
|
6
7
|
if (open && (data === "[f0" || data === "[f1")) return 1;
|
|
8
|
+
if (open && (data.startsWith("[b;") || data.startsWith("[f")) && isBindingOpenComment(data))
|
|
9
|
+
return 1;
|
|
7
10
|
if (data.length < 2 || data.charCodeAt(0) !== marker.charCodeAt(0)) return 0;
|
|
8
11
|
const first = data.charCodeAt(1);
|
|
9
12
|
if (first < 49 || first > 57) return 0;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { EncodedSignalValue, ScopeSeed } from './signals/types.js';
|
|
2
|
+
/** Independent resource/HTML channel identity. Arrival order is never freshness. */
|
|
3
|
+
export interface StreamFrameIdentity {
|
|
4
|
+
readonly protocol: 1;
|
|
5
|
+
readonly buildId: string;
|
|
6
|
+
readonly documentId: string;
|
|
7
|
+
readonly ownerKey: string;
|
|
8
|
+
readonly instanceKey: string;
|
|
9
|
+
readonly nodeKey: string;
|
|
10
|
+
readonly selectionKey: string;
|
|
11
|
+
readonly selectionGeneration: number;
|
|
12
|
+
readonly attempt: number;
|
|
13
|
+
}
|
|
14
|
+
interface StreamFrameBase {
|
|
15
|
+
readonly identity: StreamFrameIdentity;
|
|
16
|
+
/** Monotone within one identity and logical channel, beginning at zero. */
|
|
17
|
+
readonly sequence: number;
|
|
18
|
+
}
|
|
19
|
+
export type StreamedSignalResultFrame = StreamFrameBase & ({
|
|
20
|
+
readonly channel: 'result';
|
|
21
|
+
readonly kind: 'open';
|
|
22
|
+
readonly resource: 'promise' | 'stream';
|
|
23
|
+
} | {
|
|
24
|
+
readonly channel: 'result';
|
|
25
|
+
readonly kind: 'value';
|
|
26
|
+
readonly value: EncodedSignalValue;
|
|
27
|
+
} | {
|
|
28
|
+
readonly channel: 'result';
|
|
29
|
+
readonly kind: 'complete';
|
|
30
|
+
} | {
|
|
31
|
+
readonly channel: 'result';
|
|
32
|
+
readonly kind: 'error';
|
|
33
|
+
readonly code: string;
|
|
34
|
+
});
|
|
35
|
+
export type StreamedRegionPlacementFrame = StreamFrameBase & {
|
|
36
|
+
readonly channel: 'placement';
|
|
37
|
+
readonly kind: 'html';
|
|
38
|
+
/** Authoritative monotone revision for the currently selected source. */
|
|
39
|
+
readonly contentRevision: number;
|
|
40
|
+
/** A delta is legal only against this exact already-presented revision. */
|
|
41
|
+
readonly baseRevision?: number;
|
|
42
|
+
readonly mode: 'full' | 'delta';
|
|
43
|
+
/** Renderer-owned artifact. Applications do not pass arbitrary HTML here. */
|
|
44
|
+
readonly html: string;
|
|
45
|
+
/** Exact values read to produce this range, independent of newer live values. */
|
|
46
|
+
readonly historicalFrame: ScopeSeed;
|
|
47
|
+
/** Compiler/bundler style identities that must be ready before reveal. */
|
|
48
|
+
readonly styles: readonly string[];
|
|
49
|
+
};
|
|
50
|
+
export type StreamedRendererFrame = StreamedSignalResultFrame | StreamedRegionPlacementFrame;
|
|
51
|
+
export declare function isStreamFrameIdentity(value: unknown): value is StreamFrameIdentity;
|
|
52
|
+
/** Strictly validate an untrusted decoded frame before any mailbox or DOM mutation. */
|
|
53
|
+
export declare function isStreamedRendererFrame(value: unknown): value is StreamedRendererFrame;
|
|
54
|
+
export declare function decodeStreamedRendererFrame(json: string): StreamedRendererFrame;
|
|
55
|
+
/** Escape a validated frame for a nonced inline receiver call; never evaluate it as source. */
|
|
56
|
+
export declare function encodeStreamedRendererFrameForScript(frame: StreamedRendererFrame): string;
|
|
57
|
+
export declare function sameStreamFrameIdentity(a: StreamFrameIdentity, b: StreamFrameIdentity): boolean;
|
|
58
|
+
/** Stable local map key only; authority still requires field-by-field comparison. */
|
|
59
|
+
export declare function streamFrameIdentityKey(identity: StreamFrameIdentity): string;
|
|
60
|
+
export {};
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
function isRecord(value) {
|
|
2
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
3
|
+
const prototype = Object.getPrototypeOf(value);
|
|
4
|
+
if (prototype !== Object.prototype && prototype !== null) return false;
|
|
5
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
6
|
+
if (typeof key !== "string") return false;
|
|
7
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
8
|
+
if (!descriptor.enumerable || !("value" in descriptor)) return false;
|
|
9
|
+
}
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
function isKey(value) {
|
|
13
|
+
return typeof value === "string" && value.length > 0 && value.length <= 1024;
|
|
14
|
+
}
|
|
15
|
+
function isCounter(value) {
|
|
16
|
+
return Number.isSafeInteger(value) && value >= 0;
|
|
17
|
+
}
|
|
18
|
+
function hasOnly(record, allowed) {
|
|
19
|
+
return Object.keys(record).every((key) => allowed.has(key));
|
|
20
|
+
}
|
|
21
|
+
const IDENTITY_KEYS = /* @__PURE__ */ new Set([
|
|
22
|
+
"protocol",
|
|
23
|
+
"buildId",
|
|
24
|
+
"documentId",
|
|
25
|
+
"ownerKey",
|
|
26
|
+
"instanceKey",
|
|
27
|
+
"nodeKey",
|
|
28
|
+
"selectionKey",
|
|
29
|
+
"selectionGeneration",
|
|
30
|
+
"attempt"
|
|
31
|
+
]);
|
|
32
|
+
function isStreamFrameIdentity(value) {
|
|
33
|
+
if (!isRecord(value) || !hasOnly(value, IDENTITY_KEYS)) return false;
|
|
34
|
+
return value.protocol === 1 && isKey(value.buildId) && isKey(value.documentId) && isKey(value.ownerKey) && isKey(value.instanceKey) && isKey(value.nodeKey) && isKey(value.selectionKey) && isCounter(value.selectionGeneration) && isCounter(value.attempt);
|
|
35
|
+
}
|
|
36
|
+
function isEncodedSignalValue(value, depth = 0) {
|
|
37
|
+
if (depth > 100 || !Array.isArray(value) || typeof value[0] !== "string") return false;
|
|
38
|
+
const tag = value[0];
|
|
39
|
+
if (tag === "undefined" || tag === "null") return value.length === 1;
|
|
40
|
+
if (value.length !== 2) return false;
|
|
41
|
+
if (tag === "boolean") return typeof value[1] === "boolean";
|
|
42
|
+
if (tag === "string") return typeof value[1] === "string";
|
|
43
|
+
if (tag === "number") {
|
|
44
|
+
return value[1] === "-0" || typeof value[1] === "number" && Number.isFinite(value[1]) && !Object.is(value[1], -0);
|
|
45
|
+
}
|
|
46
|
+
if (tag === "array") {
|
|
47
|
+
return Array.isArray(value[1]) && value[1].every((item) => isEncodedSignalValue(item, depth + 1));
|
|
48
|
+
}
|
|
49
|
+
if (tag !== "object" || !Array.isArray(value[1])) return false;
|
|
50
|
+
let previous;
|
|
51
|
+
for (const entry of value[1]) {
|
|
52
|
+
if (!Array.isArray(entry) || entry.length !== 2 || typeof entry[0] !== "string" || previous !== void 0 && entry[0] <= previous || !isEncodedSignalValue(entry[1], depth + 1)) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
previous = entry[0];
|
|
56
|
+
}
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
function isHistoricalFrame(value) {
|
|
60
|
+
return isRecord(value) && value.version === 1 && isKey(value.scopeKey) && Array.isArray(value.entries);
|
|
61
|
+
}
|
|
62
|
+
const RESULT_BASE_KEYS = /* @__PURE__ */ new Set(["identity", "sequence", "channel", "kind"]);
|
|
63
|
+
function isStreamedRendererFrame(value) {
|
|
64
|
+
if (!isRecord(value) || !isStreamFrameIdentity(value.identity) || !isCounter(value.sequence)) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
if (value.channel === "result") {
|
|
68
|
+
if (value.kind === "open") {
|
|
69
|
+
return hasOnly(value, /* @__PURE__ */ new Set([...RESULT_BASE_KEYS, "resource"])) && (value.resource === "promise" || value.resource === "stream");
|
|
70
|
+
}
|
|
71
|
+
if (value.kind === "value") {
|
|
72
|
+
return hasOnly(value, /* @__PURE__ */ new Set([...RESULT_BASE_KEYS, "value"])) && isEncodedSignalValue(value.value);
|
|
73
|
+
}
|
|
74
|
+
if (value.kind === "error") {
|
|
75
|
+
return hasOnly(value, /* @__PURE__ */ new Set([...RESULT_BASE_KEYS, "code"])) && isKey(value.code);
|
|
76
|
+
}
|
|
77
|
+
return value.kind === "complete" && hasOnly(value, RESULT_BASE_KEYS);
|
|
78
|
+
}
|
|
79
|
+
if (value.channel !== "placement" || value.kind !== "html") return false;
|
|
80
|
+
const allowed = /* @__PURE__ */ new Set([
|
|
81
|
+
"identity",
|
|
82
|
+
"sequence",
|
|
83
|
+
"channel",
|
|
84
|
+
"kind",
|
|
85
|
+
"contentRevision",
|
|
86
|
+
"baseRevision",
|
|
87
|
+
"mode",
|
|
88
|
+
"html",
|
|
89
|
+
"historicalFrame",
|
|
90
|
+
"styles"
|
|
91
|
+
]);
|
|
92
|
+
if (!hasOnly(value, allowed) || !isCounter(value.contentRevision) || value.mode !== "full" && value.mode !== "delta" || typeof value.html !== "string" || !isHistoricalFrame(value.historicalFrame) || !Array.isArray(value.styles) || !value.styles.every(isKey) || new Set(value.styles).size !== value.styles.length) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
if (value.mode === "delta") return isCounter(value.baseRevision);
|
|
96
|
+
return value.baseRevision === void 0 || isCounter(value.baseRevision);
|
|
97
|
+
}
|
|
98
|
+
function decodeStreamedRendererFrame(json) {
|
|
99
|
+
const value = JSON.parse(json);
|
|
100
|
+
if (!isStreamedRendererFrame(value)) throw new Error("Invalid Octane streamed renderer frame.");
|
|
101
|
+
return value;
|
|
102
|
+
}
|
|
103
|
+
function encodeStreamedRendererFrameForScript(frame) {
|
|
104
|
+
if (!isStreamedRendererFrame(frame)) throw new Error("Invalid Octane streamed renderer frame.");
|
|
105
|
+
return JSON.stringify(frame).replace(/&/g, "\\u0026").replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
106
|
+
}
|
|
107
|
+
function sameStreamFrameIdentity(a, b) {
|
|
108
|
+
return a.protocol === b.protocol && a.buildId === b.buildId && a.documentId === b.documentId && a.ownerKey === b.ownerKey && a.instanceKey === b.instanceKey && a.nodeKey === b.nodeKey && a.selectionKey === b.selectionKey && a.selectionGeneration === b.selectionGeneration && a.attempt === b.attempt;
|
|
109
|
+
}
|
|
110
|
+
function streamFrameIdentityKey(identity) {
|
|
111
|
+
return JSON.stringify([
|
|
112
|
+
identity.protocol,
|
|
113
|
+
identity.buildId,
|
|
114
|
+
identity.documentId,
|
|
115
|
+
identity.ownerKey,
|
|
116
|
+
identity.instanceKey,
|
|
117
|
+
identity.nodeKey,
|
|
118
|
+
identity.selectionKey,
|
|
119
|
+
identity.selectionGeneration,
|
|
120
|
+
identity.attempt
|
|
121
|
+
]);
|
|
122
|
+
}
|
|
123
|
+
export {
|
|
124
|
+
decodeStreamedRendererFrame,
|
|
125
|
+
encodeStreamedRendererFrameForScript,
|
|
126
|
+
isStreamFrameIdentity,
|
|
127
|
+
isStreamedRendererFrame,
|
|
128
|
+
sameStreamFrameIdentity,
|
|
129
|
+
streamFrameIdentityKey
|
|
130
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
const UNITLESS_STYLE_PROPS = /* @__PURE__ */ new Set();
|
|
2
|
+
for (const base of [
|
|
3
|
+
"animationIterationCount",
|
|
4
|
+
"aspectRatio",
|
|
5
|
+
"borderImageOutset",
|
|
6
|
+
"borderImageSlice",
|
|
7
|
+
"borderImageWidth",
|
|
8
|
+
"boxFlex",
|
|
9
|
+
"boxFlexGroup",
|
|
10
|
+
"boxOrdinalGroup",
|
|
11
|
+
"columnCount",
|
|
12
|
+
"columns",
|
|
13
|
+
"flex",
|
|
14
|
+
"flexGrow",
|
|
15
|
+
"flexPositive",
|
|
16
|
+
"flexShrink",
|
|
17
|
+
"flexNegative",
|
|
18
|
+
"flexOrder",
|
|
19
|
+
"gridArea",
|
|
20
|
+
"gridRow",
|
|
21
|
+
"gridRowEnd",
|
|
22
|
+
"gridRowSpan",
|
|
23
|
+
"gridRowStart",
|
|
24
|
+
"gridColumn",
|
|
25
|
+
"gridColumnEnd",
|
|
26
|
+
"gridColumnSpan",
|
|
27
|
+
"gridColumnStart",
|
|
28
|
+
"fontWeight",
|
|
29
|
+
"lineClamp",
|
|
30
|
+
"lineHeight",
|
|
31
|
+
"opacity",
|
|
32
|
+
"order",
|
|
33
|
+
"orphans",
|
|
34
|
+
"scale",
|
|
35
|
+
"tabSize",
|
|
36
|
+
"widows",
|
|
37
|
+
"zIndex",
|
|
38
|
+
"zoom",
|
|
39
|
+
"fillOpacity",
|
|
40
|
+
"floodOpacity",
|
|
41
|
+
"stopOpacity",
|
|
42
|
+
"strokeDasharray",
|
|
43
|
+
"strokeDashoffset",
|
|
44
|
+
"strokeMiterlimit",
|
|
45
|
+
"strokeOpacity",
|
|
46
|
+
"strokeWidth"
|
|
47
|
+
]) {
|
|
48
|
+
const c = base.toLowerCase();
|
|
49
|
+
UNITLESS_STYLE_PROPS.add(c);
|
|
50
|
+
UNITLESS_STYLE_PROPS.add("webkit" + c);
|
|
51
|
+
UNITLESS_STYLE_PROPS.add("ms" + c);
|
|
52
|
+
UNITLESS_STYLE_PROPS.add("moz" + c);
|
|
53
|
+
UNITLESS_STYLE_PROPS.add("o" + c);
|
|
54
|
+
}
|
|
55
|
+
const unitlessStylePropCache = /* @__PURE__ */ new Map();
|
|
56
|
+
function isUnitlessStyleProp(name) {
|
|
57
|
+
const cached = unitlessStylePropCache.get(name);
|
|
58
|
+
if (cached !== void 0) return cached;
|
|
59
|
+
const result = UNITLESS_STYLE_PROPS.has(name.replaceAll("-", "").toLowerCase());
|
|
60
|
+
unitlessStylePropCache.set(name, result);
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
function cssStyleValue(name, value) {
|
|
64
|
+
if (typeof value === "number" && value !== 0 && name.charCodeAt(0) !== 45 && !isUnitlessStyleProp(name)) {
|
|
65
|
+
return value + "px";
|
|
66
|
+
}
|
|
67
|
+
return typeof value === "string" ? value.trim() : "" + value;
|
|
68
|
+
}
|
|
69
|
+
function hyphenateStyleName(name) {
|
|
70
|
+
if (name === "cssFloat") return "float";
|
|
71
|
+
if (name.charCodeAt(0) === 45) return name;
|
|
72
|
+
let hasUpper = false;
|
|
73
|
+
for (let i = 0; i < name.length; i++) {
|
|
74
|
+
const c = name.charCodeAt(i);
|
|
75
|
+
if (c >= 65 && c <= 90) {
|
|
76
|
+
hasUpper = true;
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (!hasUpper) return name;
|
|
81
|
+
let out = "";
|
|
82
|
+
for (let i = 0; i < name.length; i++) {
|
|
83
|
+
const c = name.charCodeAt(i);
|
|
84
|
+
if (c >= 65 && c <= 90) out += "-" + String.fromCharCode(c + 32);
|
|
85
|
+
else out += name[i];
|
|
86
|
+
}
|
|
87
|
+
if (out.charCodeAt(0) === 109 && out.charCodeAt(1) === 115 && out.charCodeAt(2) === 45) {
|
|
88
|
+
out = "-" + out;
|
|
89
|
+
}
|
|
90
|
+
return out;
|
|
91
|
+
}
|
|
92
|
+
export {
|
|
93
|
+
cssStyleValue,
|
|
94
|
+
hyphenateStyleName,
|
|
95
|
+
isUnitlessStyleProp
|
|
96
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Nominal proof that the application explicitly accepted this HTML as trusted. */
|
|
2
|
+
declare const trustedHTMLBrand: unique symbol;
|
|
3
|
+
/**
|
|
4
|
+
* HTML accepted for an intrinsic element's `dangerouslySetInnerHTML` in Strong
|
|
5
|
+
* mode. The brand is type-only; client rendering and SSR use the ordinary
|
|
6
|
+
* `{ __html }` representation without a per-element runtime check.
|
|
7
|
+
*/
|
|
8
|
+
export interface TrustedHTML {
|
|
9
|
+
readonly __html: string;
|
|
10
|
+
readonly [trustedHTMLBrand]: true;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Explicitly accept HTML from a trusted source or a sanitizer the application
|
|
14
|
+
* owns. This function does not sanitize, escape, or validate its input.
|
|
15
|
+
*/
|
|
16
|
+
export declare function trustHTML(html: string): TrustedHTML;
|
|
17
|
+
export {};
|
package/dist/universal-core.d.ts
CHANGED
|
@@ -42,6 +42,11 @@ export type UniversalKey = string | number | symbol | bigint;
|
|
|
42
42
|
export interface UniversalContext<T> {
|
|
43
43
|
readonly $$kind: symbol;
|
|
44
44
|
readonly defaultValue: T;
|
|
45
|
+
/**
|
|
46
|
+
* Bumped on every committed provider change; each bump must move the shared
|
|
47
|
+
* context epoch too (bumpContextEpoch in context-epoch.ts) — the
|
|
48
|
+
* $$ctxDepsEpoch bail fast path treats an unmoved epoch as "nothing changed".
|
|
49
|
+
*/
|
|
45
50
|
$$version: number;
|
|
46
51
|
}
|
|
47
52
|
export interface UniversalRendererMetadata {
|
|
@@ -284,6 +289,7 @@ export type UniversalHostPropEncoding = {
|
|
|
284
289
|
readonly kind: 'unsupported';
|
|
285
290
|
readonly reason?: string;
|
|
286
291
|
};
|
|
292
|
+
/** One encoding call's context. Codecs may retain it across later props and renders. */
|
|
287
293
|
export interface UniversalHostPropCodecContext<Container = unknown> {
|
|
288
294
|
readonly container: Container;
|
|
289
295
|
readonly renderer: string;
|