@swifttui/web 0.4.0 → 0.4.2
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/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/src/AccessibilityTree.js +10 -2
- package/dist/src/AccessibilityTree.js.map +1 -1
- package/dist/src/CanvasSurfacePainter.d.ts +16 -0
- package/dist/src/CanvasSurfacePainter.js +162 -16
- package/dist/src/CanvasSurfacePainter.js.map +1 -1
- package/dist/src/DomSurfacePainter.d.ts +17 -3
- package/dist/src/DomSurfacePainter.js +63 -10
- package/dist/src/DomSurfacePainter.js.map +1 -1
- package/dist/src/SurfacePainterConformanceControl.js +13 -0
- package/dist/src/SurfacePainterConformanceControl.js.map +1 -0
- package/dist/src/SurfaceRenderer.d.ts +3 -2
- package/dist/src/SurfaceRenderer.js.map +1 -1
- package/dist/src/WebHostSceneRuntime.d.ts +3 -1
- package/dist/src/WebHostSceneRuntime.js +16 -7
- package/dist/src/WebHostSceneRuntime.js.map +1 -1
- package/dist/src/WebHostSurfaceTransport.d.ts +63 -6
- package/dist/src/WebHostSurfaceTransport.js +186 -9
- package/dist/src/WebHostSurfaceTransport.js.map +1 -1
- package/dist/src/WebSocketSceneBridge.d.ts +2 -0
- package/dist/src/WebSocketSceneBridge.js +30 -5
- package/dist/src/WebSocketSceneBridge.js.map +1 -1
- package/dist/src/normalizeWireTokens.d.ts +5 -0
- package/dist/src/normalizeWireTokens.js +41 -0
- package/dist/src/normalizeWireTokens.js.map +1 -0
- package/dist/src/wasi/BrowserWASIBridge.d.ts +8 -0
- package/dist/src/wasi/BrowserWASIBridge.js +31 -4
- package/dist/src/wasi/BrowserWASIBridge.js.map +1 -1
- package/dist/src/wasi/SharedInputQueue.d.ts +2 -0
- package/dist/src/wasi/SharedInputQueue.js +22 -0
- package/dist/src/wasi/SharedInputQueue.js.map +1 -1
- package/dist/src/wasi/StdIOPipe.d.ts +2 -2
- package/dist/src/wasi/StdIOPipe.js +5 -3
- package/dist/src/wasi/StdIOPipe.js.map +1 -1
- package/dist/src/wasi/WasmSceneRuntime.js +24 -4
- package/dist/src/wasi/WasmSceneRuntime.js.map +1 -1
- package/dist/src/wasi/WasmSceneWorker.js +1 -1
- package/dist/testing.d.ts +2 -1
- package/dist/wasi.js +1 -1
- package/package.json +2 -1
|
@@ -16,7 +16,7 @@ type WebHostSurfaceCell = [x: number, text: string, span: number, styleIndex: nu
|
|
|
16
16
|
type WebHostSurfaceRect = [x: number, y: number, width: number, height: number];
|
|
17
17
|
type WebHostSurfaceSize = [width: number, height: number];
|
|
18
18
|
type WebHostAccessibilityPoint = [x: number, y: number];
|
|
19
|
-
type WebHostAccessibilityLiveRegion =
|
|
19
|
+
type WebHostAccessibilityLiveRegion = string;
|
|
20
20
|
interface WebHostAccessibilityNode {
|
|
21
21
|
id: string;
|
|
22
22
|
parentId?: string;
|
|
@@ -37,7 +37,7 @@ interface WebHostAccessibilityNode {
|
|
|
37
37
|
type WebHostSurfaceLinkRun = [x: number, span: number, targetIndex: number];
|
|
38
38
|
/** Hyperlink runs for one row: [rowIndex, runs]. */
|
|
39
39
|
type WebHostSurfaceLinkRow = [row: number, runs: WebHostSurfaceLinkRun[]];
|
|
40
|
-
type WebHostFocusSemantics =
|
|
40
|
+
type WebHostFocusSemantics = string;
|
|
41
41
|
/**
|
|
42
42
|
* The settled focus presentation for a committed frame — the same derivation
|
|
43
43
|
* the Android host consumes (`prefersTextInput` gates its IME).
|
|
@@ -52,13 +52,20 @@ interface WebHostAccessibilityAnnouncement {
|
|
|
52
52
|
message: string;
|
|
53
53
|
politeness: WebHostAccessibilityLiveRegion;
|
|
54
54
|
}
|
|
55
|
-
type WebHostSurfaceImageFormat =
|
|
55
|
+
type WebHostSurfaceImageFormat = string;
|
|
56
|
+
/**
|
|
57
|
+
* Reports locally unresolved image IDs to a recovery-capable host. The first
|
|
58
|
+
* branch lets bounded hosts return the admitted subset; the explicit legacy
|
|
59
|
+
* void branch preserves contextual typing for concise callbacks that return
|
|
60
|
+
* incidental values such as `array.push(...)`.
|
|
61
|
+
*/
|
|
62
|
+
type WebHostImagePayloadRequestHandler = ((ids: readonly string[]) => readonly string[]) | ((ids: readonly string[]) => void);
|
|
56
63
|
interface WebHostSurfaceImage {
|
|
57
64
|
id: string;
|
|
58
65
|
format: WebHostSurfaceImageFormat;
|
|
59
66
|
bounds: WebHostSurfaceRect;
|
|
60
67
|
visibleBounds: WebHostSurfaceRect;
|
|
61
|
-
scalingMode:
|
|
68
|
+
scalingMode: string;
|
|
62
69
|
pixelSize?: WebHostSurfaceSize;
|
|
63
70
|
dataBase64?: string;
|
|
64
71
|
}
|
|
@@ -89,6 +96,8 @@ interface WebHostScrollRegion {
|
|
|
89
96
|
}
|
|
90
97
|
interface WebHostSurfaceFrame {
|
|
91
98
|
version: 1 | 2;
|
|
99
|
+
epoch?: number;
|
|
100
|
+
gen?: number;
|
|
92
101
|
sequence?: number;
|
|
93
102
|
width: number;
|
|
94
103
|
height: number;
|
|
@@ -109,6 +118,9 @@ type WebHostSurfaceDeltaRow = [row: number, cells: WebHostSurfaceCell[]];
|
|
|
109
118
|
interface WebHostSurfaceDeltaFrame {
|
|
110
119
|
version: 3;
|
|
111
120
|
encoding: "delta";
|
|
121
|
+
epoch?: number;
|
|
122
|
+
gen?: number;
|
|
123
|
+
baselineGen?: number;
|
|
112
124
|
sequence?: number;
|
|
113
125
|
width: number;
|
|
114
126
|
height: number;
|
|
@@ -150,12 +162,21 @@ type WebHostOutputRecord = {
|
|
|
150
162
|
} | {
|
|
151
163
|
type: "frameDiagnostic";
|
|
152
164
|
diagnostic: WebHostFrameDiagnosticRecord;
|
|
165
|
+
} | {
|
|
166
|
+
type: "surfaceDropped";
|
|
167
|
+
reason: "noBaseline" | "staleBaseline";
|
|
153
168
|
} | {
|
|
154
169
|
type: "text";
|
|
155
170
|
text: string;
|
|
156
171
|
};
|
|
172
|
+
type WebHostResyncRequest = {
|
|
173
|
+
scope: "keyframe";
|
|
174
|
+
} | {
|
|
175
|
+
scope: "images";
|
|
176
|
+
ids?: string[];
|
|
177
|
+
};
|
|
157
178
|
interface WebHostOutputSink {
|
|
158
|
-
presentSurface(frame: WebHostSurfaceFrame): void;
|
|
179
|
+
presentSurface(frame: WebHostSurfaceFrame, recoveredImagePayloadIds?: readonly string[]): void;
|
|
159
180
|
writeClipboard?(text: string): void | Promise<void>;
|
|
160
181
|
notifyRuntimeIssue?(issue: WebHostRuntimeIssue): void;
|
|
161
182
|
recordFrameDiagnostic?(diagnostic: WebHostFrameDiagnosticRecord): void;
|
|
@@ -176,6 +197,10 @@ interface WebHostMouseInput {
|
|
|
176
197
|
deltaY?: number;
|
|
177
198
|
modifiers?: number;
|
|
178
199
|
}
|
|
200
|
+
/** Limits wire-derived recovery state and keeps every single-ID WASI request bounded. */
|
|
201
|
+
declare const MAX_IMAGE_RECOVERY_ID_BYTES = 1024;
|
|
202
|
+
declare const MAX_OUTSTANDING_IMAGE_RECOVERY_IDS = 1024;
|
|
203
|
+
declare function isWebHostImageRecoveryId(id: string): boolean;
|
|
179
204
|
/**
|
|
180
205
|
* The newest `surface` record version this runtime understands. Unknown
|
|
181
206
|
* additive object keys are ignored by design (older runtimes render newer
|
|
@@ -189,17 +214,49 @@ declare class WebHostOutputDecoder {
|
|
|
189
214
|
private readonly textDecoder;
|
|
190
215
|
private bufferedText;
|
|
191
216
|
private lastSurfaceFrame?;
|
|
217
|
+
private lastEpoch?;
|
|
218
|
+
private lastGen?;
|
|
219
|
+
private lastPresentedEpoch?;
|
|
220
|
+
private keyframeResyncOutstanding;
|
|
221
|
+
private keyframeResyncPending;
|
|
222
|
+
private readonly imageResyncOutstandingIds;
|
|
223
|
+
private readonly imageResyncPendingIds;
|
|
192
224
|
feed(chunk: Uint8Array): WebHostOutputRecord[];
|
|
193
225
|
flush(): WebHostOutputRecord[];
|
|
226
|
+
takeResyncRequest(maximumEncodedBytes?: number): WebHostResyncRequest | undefined;
|
|
227
|
+
/**
|
|
228
|
+
* Adds locally unresolved image IDs to this epoch's recovery set. IDs remain
|
|
229
|
+
* outstanding after delivery, so repeat painter misses cannot create storms;
|
|
230
|
+
* a payload-bearing record or epoch re-anchor releases them. Returns the IDs
|
|
231
|
+
* now tracked (new or already outstanding); callers should suppress repeats
|
|
232
|
+
* only for this admitted subset.
|
|
233
|
+
*/
|
|
234
|
+
requestImagePayloads(ids: Iterable<string>): readonly string[];
|
|
235
|
+
/**
|
|
236
|
+
* Advances image recovery immediately before one decoded surface reaches its
|
|
237
|
+
* presenter. Payload arrival and epoch reset therefore follow delivery order
|
|
238
|
+
* rather than `feed`'s parse-ahead order across a multi-record chunk. The
|
|
239
|
+
* return value identifies payloads that answer an outstanding image request,
|
|
240
|
+
* so presenters can open exactly one fresh local decode generation even when
|
|
241
|
+
* content-addressed retransmission uses identical bytes.
|
|
242
|
+
*/
|
|
243
|
+
prepareToPresentSurface(frame: WebHostSurfaceFrame): readonly string[];
|
|
244
|
+
resyncRequestDeliveryFailed(request: WebHostResyncRequest): void;
|
|
194
245
|
private decodeLine;
|
|
246
|
+
private requestKeyframeResync;
|
|
247
|
+
private resetImageResyncForEpoch;
|
|
248
|
+
private clearArrivedImagePayloads;
|
|
249
|
+
private recoveredImagePayloadIds;
|
|
250
|
+
private sweepImageResyncForPresentedImages;
|
|
195
251
|
private materializeDeltaFrame;
|
|
196
252
|
}
|
|
197
253
|
declare function encodeResizeControlMessage(columns: number, rows: number, cellWidth?: number, cellHeight?: number): Uint8Array;
|
|
198
254
|
declare function encodeRenderStyleControlMessage(style: WebHostTerminalStyle): Uint8Array;
|
|
199
255
|
declare function encodeCapabilitiesControlMessage(): Uint8Array;
|
|
256
|
+
declare function encodeResyncControlMessage(request: WebHostResyncRequest): Uint8Array;
|
|
200
257
|
declare function encodeKeyInputMessage(input: WebHostKeyInput): Uint8Array;
|
|
201
258
|
declare function encodePasteInputMessage(text: string): Uint8Array;
|
|
202
259
|
declare function encodeMouseInputMessage(input: WebHostMouseInput): Uint8Array;
|
|
203
260
|
//#endregion
|
|
204
|
-
export { SUPPORTED_SURFACE_VERSION, WebHostAccessibilityAnnouncement, WebHostAccessibilityLiveRegion, WebHostAccessibilityNode, WebHostAccessibilityPoint, WebHostFocusPresentation, WebHostFocusSemantics, WebHostFrameDiagnosticRecord, WebHostKeyInput, WebHostMouseInput, WebHostOutputDecoder, WebHostOutputRecord, WebHostOutputSink, WebHostRuntimeIssue, WebHostScrollRegion, WebHostSurfaceCell, WebHostSurfaceDamage, WebHostSurfaceDamageRange, WebHostSurfaceDamageTextRow, WebHostSurfaceDeltaFrame, WebHostSurfaceDeltaRow, WebHostSurfaceFrame, WebHostSurfaceImage, WebHostSurfaceImageFormat, WebHostSurfaceLineStyle, WebHostSurfaceLinkRow, WebHostSurfaceLinkRun, WebHostSurfaceRect, WebHostSurfaceSize, WebHostSurfaceStyle, encodeCapabilitiesControlMessage, encodeKeyInputMessage, encodeMouseInputMessage, encodePasteInputMessage, encodeRenderStyleControlMessage, encodeResizeControlMessage };
|
|
261
|
+
export { MAX_IMAGE_RECOVERY_ID_BYTES, MAX_OUTSTANDING_IMAGE_RECOVERY_IDS, SUPPORTED_SURFACE_VERSION, WebHostAccessibilityAnnouncement, WebHostAccessibilityLiveRegion, WebHostAccessibilityNode, WebHostAccessibilityPoint, WebHostFocusPresentation, WebHostFocusSemantics, WebHostFrameDiagnosticRecord, WebHostImagePayloadRequestHandler, WebHostKeyInput, WebHostMouseInput, WebHostOutputDecoder, WebHostOutputRecord, WebHostOutputSink, WebHostResyncRequest, WebHostRuntimeIssue, WebHostScrollRegion, WebHostSurfaceCell, WebHostSurfaceDamage, WebHostSurfaceDamageRange, WebHostSurfaceDamageTextRow, WebHostSurfaceDeltaFrame, WebHostSurfaceDeltaRow, WebHostSurfaceFrame, WebHostSurfaceImage, WebHostSurfaceImageFormat, WebHostSurfaceLineStyle, WebHostSurfaceLinkRow, WebHostSurfaceLinkRun, WebHostSurfaceRect, WebHostSurfaceSize, WebHostSurfaceStyle, encodeCapabilitiesControlMessage, encodeKeyInputMessage, encodeMouseInputMessage, encodePasteInputMessage, encodeRenderStyleControlMessage, encodeResizeControlMessage, encodeResyncControlMessage, isWebHostImageRecoveryId };
|
|
205
262
|
//# sourceMappingURL=WebHostSurfaceTransport.d.ts.map
|
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
import { encodeWebHostTerminalRenderStyleBase64 } from "./WebHostTerminalStyle.js";
|
|
2
2
|
//#region src/WebHostSurfaceTransport.ts
|
|
3
|
+
/**
|
|
4
|
+
* Browser consumer for SwiftTUI's host wire. The normative cross-host
|
|
5
|
+
* contract lives upstream:
|
|
6
|
+
* https://github.com/SwiftTUI/swift-tui/blob/main/docs/HOST-WIRE-CONTRACT.md
|
|
7
|
+
*/
|
|
3
8
|
const recordPrefix = "";
|
|
4
9
|
const textEncoder = new TextEncoder();
|
|
10
|
+
/** Limits wire-derived recovery state and keeps every single-ID WASI request bounded. */
|
|
11
|
+
const MAX_IMAGE_RECOVERY_ID_BYTES = 1024;
|
|
12
|
+
const MAX_OUTSTANDING_IMAGE_RECOVERY_IDS = 1024;
|
|
13
|
+
function isWebHostImageRecoveryId(id) {
|
|
14
|
+
return id.length > 0 && id.length <= 1024 && textEncoder.encode(id).byteLength <= 1024;
|
|
15
|
+
}
|
|
5
16
|
/**
|
|
6
17
|
* The newest `surface` record version this runtime understands. Unknown
|
|
7
18
|
* additive object keys are ignored by design (older runtimes render newer
|
|
@@ -15,6 +26,13 @@ var WebHostOutputDecoder = class {
|
|
|
15
26
|
textDecoder = new TextDecoder();
|
|
16
27
|
bufferedText = "";
|
|
17
28
|
lastSurfaceFrame;
|
|
29
|
+
lastEpoch;
|
|
30
|
+
lastGen;
|
|
31
|
+
lastPresentedEpoch;
|
|
32
|
+
keyframeResyncOutstanding = false;
|
|
33
|
+
keyframeResyncPending = false;
|
|
34
|
+
imageResyncOutstandingIds = /* @__PURE__ */ new Set();
|
|
35
|
+
imageResyncPendingIds = /* @__PURE__ */ new Set();
|
|
18
36
|
feed(chunk) {
|
|
19
37
|
this.bufferedText += this.textDecoder.decode(chunk, { stream: true });
|
|
20
38
|
const records = [];
|
|
@@ -40,6 +58,69 @@ var WebHostOutputDecoder = class {
|
|
|
40
58
|
this.bufferedText = "";
|
|
41
59
|
return [this.decodeLine(text)];
|
|
42
60
|
}
|
|
61
|
+
takeResyncRequest(maximumEncodedBytes) {
|
|
62
|
+
if (this.keyframeResyncPending) {
|
|
63
|
+
this.keyframeResyncPending = false;
|
|
64
|
+
return { scope: "keyframe" };
|
|
65
|
+
}
|
|
66
|
+
if (this.imageResyncPendingIds.size === 0) return;
|
|
67
|
+
const { ids, rejectedIds } = boundedImageResyncIds([...this.imageResyncPendingIds].sort(), maximumEncodedBytes);
|
|
68
|
+
for (const id of rejectedIds) {
|
|
69
|
+
this.imageResyncPendingIds.delete(id);
|
|
70
|
+
this.imageResyncOutstandingIds.delete(id);
|
|
71
|
+
}
|
|
72
|
+
for (const id of ids) this.imageResyncPendingIds.delete(id);
|
|
73
|
+
if (ids.length === 0) return;
|
|
74
|
+
return {
|
|
75
|
+
scope: "images",
|
|
76
|
+
ids
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Adds locally unresolved image IDs to this epoch's recovery set. IDs remain
|
|
81
|
+
* outstanding after delivery, so repeat painter misses cannot create storms;
|
|
82
|
+
* a payload-bearing record or epoch re-anchor releases them. Returns the IDs
|
|
83
|
+
* now tracked (new or already outstanding); callers should suppress repeats
|
|
84
|
+
* only for this admitted subset.
|
|
85
|
+
*/
|
|
86
|
+
requestImagePayloads(ids) {
|
|
87
|
+
const acceptedIds = /* @__PURE__ */ new Set();
|
|
88
|
+
for (const id of ids) {
|
|
89
|
+
if (!isWebHostImageRecoveryId(id)) continue;
|
|
90
|
+
if (this.imageResyncOutstandingIds.has(id)) {
|
|
91
|
+
acceptedIds.add(id);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (this.imageResyncOutstandingIds.size >= 1024) continue;
|
|
95
|
+
this.imageResyncOutstandingIds.add(id);
|
|
96
|
+
this.imageResyncPendingIds.add(id);
|
|
97
|
+
acceptedIds.add(id);
|
|
98
|
+
}
|
|
99
|
+
return [...acceptedIds];
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Advances image recovery immediately before one decoded surface reaches its
|
|
103
|
+
* presenter. Payload arrival and epoch reset therefore follow delivery order
|
|
104
|
+
* rather than `feed`'s parse-ahead order across a multi-record chunk. The
|
|
105
|
+
* return value identifies payloads that answer an outstanding image request,
|
|
106
|
+
* so presenters can open exactly one fresh local decode generation even when
|
|
107
|
+
* content-addressed retransmission uses identical bytes.
|
|
108
|
+
*/
|
|
109
|
+
prepareToPresentSurface(frame) {
|
|
110
|
+
const recoveredImagePayloadIds = this.recoveredImagePayloadIds(frame.images);
|
|
111
|
+
this.resetImageResyncForEpoch(frame.epoch);
|
|
112
|
+
this.sweepImageResyncForPresentedImages(frame.images);
|
|
113
|
+
this.clearArrivedImagePayloads(frame.images);
|
|
114
|
+
if (frame.epoch !== void 0) this.lastPresentedEpoch = frame.epoch;
|
|
115
|
+
return recoveredImagePayloadIds;
|
|
116
|
+
}
|
|
117
|
+
resyncRequestDeliveryFailed(request) {
|
|
118
|
+
if (request.scope === "keyframe") {
|
|
119
|
+
if (this.keyframeResyncOutstanding) this.keyframeResyncPending = true;
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
for (const id of request.ids ?? []) if (this.imageResyncOutstandingIds.has(id)) this.imageResyncPendingIds.add(id);
|
|
123
|
+
}
|
|
43
124
|
decodeLine(line) {
|
|
44
125
|
if (line.startsWith(`${recordPrefix}clipboard:`)) {
|
|
45
126
|
try {
|
|
@@ -97,15 +178,36 @@ var WebHostOutputDecoder = class {
|
|
|
97
178
|
};
|
|
98
179
|
if (isWebHostSurfaceFrame(frame)) {
|
|
99
180
|
this.lastSurfaceFrame = frame;
|
|
181
|
+
this.lastEpoch = frame.epoch;
|
|
182
|
+
this.lastGen = frame.gen;
|
|
183
|
+
this.keyframeResyncOutstanding = false;
|
|
184
|
+
this.keyframeResyncPending = false;
|
|
100
185
|
return {
|
|
101
186
|
type: "surface",
|
|
102
187
|
frame
|
|
103
188
|
};
|
|
104
189
|
}
|
|
105
190
|
if (isWebHostSurfaceDeltaFrame(frame)) {
|
|
191
|
+
const carriesDeliveryStamps = frame.epoch !== void 0 || frame.gen !== void 0 || frame.baselineGen !== void 0;
|
|
192
|
+
if (!this.lastSurfaceFrame || this.lastSurfaceFrame.width !== frame.width || this.lastSurfaceFrame.height !== frame.height) {
|
|
193
|
+
if (carriesDeliveryStamps) this.requestKeyframeResync();
|
|
194
|
+
return {
|
|
195
|
+
type: "surfaceDropped",
|
|
196
|
+
reason: "noBaseline"
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
if (carriesDeliveryStamps && (frame.epoch === void 0 || frame.gen === void 0 || frame.baselineGen === void 0 || frame.epoch !== this.lastEpoch || frame.baselineGen !== this.lastGen)) {
|
|
200
|
+
this.requestKeyframeResync();
|
|
201
|
+
return {
|
|
202
|
+
type: "surfaceDropped",
|
|
203
|
+
reason: "staleBaseline"
|
|
204
|
+
};
|
|
205
|
+
}
|
|
106
206
|
const materialized = this.materializeDeltaFrame(frame);
|
|
107
207
|
if (materialized) {
|
|
108
208
|
this.lastSurfaceFrame = materialized;
|
|
209
|
+
this.lastEpoch = frame.epoch;
|
|
210
|
+
this.lastGen = frame.gen;
|
|
109
211
|
return {
|
|
110
212
|
type: "surface",
|
|
111
213
|
frame: materialized
|
|
@@ -118,9 +220,40 @@ var WebHostOutputDecoder = class {
|
|
|
118
220
|
text: `${line}\n`
|
|
119
221
|
};
|
|
120
222
|
}
|
|
223
|
+
requestKeyframeResync() {
|
|
224
|
+
if (this.keyframeResyncOutstanding) return;
|
|
225
|
+
this.keyframeResyncOutstanding = true;
|
|
226
|
+
this.keyframeResyncPending = true;
|
|
227
|
+
}
|
|
228
|
+
resetImageResyncForEpoch(epoch) {
|
|
229
|
+
if (epoch === void 0 || epoch === this.lastPresentedEpoch) return;
|
|
230
|
+
this.imageResyncOutstandingIds.clear();
|
|
231
|
+
this.imageResyncPendingIds.clear();
|
|
232
|
+
}
|
|
233
|
+
clearArrivedImagePayloads(images) {
|
|
234
|
+
for (const image of images ?? []) {
|
|
235
|
+
if (image.dataBase64 === void 0) continue;
|
|
236
|
+
this.imageResyncOutstandingIds.delete(image.id);
|
|
237
|
+
this.imageResyncPendingIds.delete(image.id);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
recoveredImagePayloadIds(images) {
|
|
241
|
+
const recoveredIds = /* @__PURE__ */ new Set();
|
|
242
|
+
for (const image of images ?? []) if (image.dataBase64 !== void 0 && this.imageResyncOutstandingIds.has(image.id)) recoveredIds.add(image.id);
|
|
243
|
+
return [...recoveredIds].sort();
|
|
244
|
+
}
|
|
245
|
+
sweepImageResyncForPresentedImages(images) {
|
|
246
|
+
const presentedIds = /* @__PURE__ */ new Set();
|
|
247
|
+
for (const image of images ?? []) if (this.imageResyncOutstandingIds.has(image.id)) presentedIds.add(image.id);
|
|
248
|
+
for (const id of this.imageResyncOutstandingIds) {
|
|
249
|
+
if (presentedIds.has(id)) continue;
|
|
250
|
+
this.imageResyncOutstandingIds.delete(id);
|
|
251
|
+
this.imageResyncPendingIds.delete(id);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
121
254
|
materializeDeltaFrame(frame) {
|
|
122
255
|
const baseline = this.lastSurfaceFrame;
|
|
123
|
-
if (!baseline
|
|
256
|
+
if (!baseline) return;
|
|
124
257
|
const rows = baseline.rows.slice();
|
|
125
258
|
for (const [row, cells] of frame.deltaRows) {
|
|
126
259
|
if (!Number.isSafeInteger(row) || row < 0 || row >= frame.height) return;
|
|
@@ -128,6 +261,8 @@ var WebHostOutputDecoder = class {
|
|
|
128
261
|
}
|
|
129
262
|
return {
|
|
130
263
|
version: baseline.version,
|
|
264
|
+
epoch: frame.epoch,
|
|
265
|
+
gen: frame.gen,
|
|
131
266
|
sequence: frame.sequence,
|
|
132
267
|
width: frame.width,
|
|
133
268
|
height: frame.height,
|
|
@@ -146,6 +281,38 @@ var WebHostOutputDecoder = class {
|
|
|
146
281
|
};
|
|
147
282
|
}
|
|
148
283
|
};
|
|
284
|
+
function boundedImageResyncIds(sortedIds, maximumEncodedBytes) {
|
|
285
|
+
if (maximumEncodedBytes === void 0 || !Number.isFinite(maximumEncodedBytes)) return {
|
|
286
|
+
ids: sortedIds,
|
|
287
|
+
rejectedIds: []
|
|
288
|
+
};
|
|
289
|
+
const emptyRequestBytes = encodeResyncControlMessage({
|
|
290
|
+
scope: "images",
|
|
291
|
+
ids: []
|
|
292
|
+
}).byteLength;
|
|
293
|
+
const normalizedMaximum = Math.max(0, Math.floor(maximumEncodedBytes));
|
|
294
|
+
const ids = [];
|
|
295
|
+
const rejectedIds = [];
|
|
296
|
+
let encodedBytes = emptyRequestBytes;
|
|
297
|
+
for (const id of sortedIds) {
|
|
298
|
+
const separatorBytes = ids.length === 0 ? 0 : 1;
|
|
299
|
+
const idBytes = textEncoder.encode(JSON.stringify(id)).byteLength;
|
|
300
|
+
if (encodedBytes + separatorBytes + idBytes > normalizedMaximum) {
|
|
301
|
+
if (ids.length === 0) {
|
|
302
|
+
rejectedIds.push(id);
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
307
|
+
ids.push(id);
|
|
308
|
+
encodedBytes += separatorBytes + idBytes;
|
|
309
|
+
if (encodedBytes >= normalizedMaximum) break;
|
|
310
|
+
}
|
|
311
|
+
return {
|
|
312
|
+
ids,
|
|
313
|
+
rejectedIds
|
|
314
|
+
};
|
|
315
|
+
}
|
|
149
316
|
function declaresNewerSurfaceVersion(value) {
|
|
150
317
|
if (!value || typeof value !== "object") return false;
|
|
151
318
|
const version = value.version;
|
|
@@ -177,6 +344,13 @@ function encodeRenderStyleControlMessage(style) {
|
|
|
177
344
|
function encodeCapabilitiesControlMessage() {
|
|
178
345
|
return textEncoder.encode(`${recordPrefix}caps:{"acceptsDeltaFrames":true}\n`);
|
|
179
346
|
}
|
|
347
|
+
function encodeResyncControlMessage(request) {
|
|
348
|
+
const payload = request.scope === "keyframe" ? { scope: "keyframe" } : {
|
|
349
|
+
scope: "images",
|
|
350
|
+
...request.ids === void 0 ? {} : { ids: request.ids }
|
|
351
|
+
};
|
|
352
|
+
return textEncoder.encode(`${recordPrefix}resync:${JSON.stringify(payload)}\n`);
|
|
353
|
+
}
|
|
180
354
|
function encodeKeyInputMessage(input) {
|
|
181
355
|
const modifiers = Math.max(0, Math.round(input.modifiers ?? 0));
|
|
182
356
|
if (input.key === "character") return textEncoder.encode(`${recordPrefix}key:character:${encodeURIComponent(input.character ?? "")}:${modifiers}\n`);
|
|
@@ -208,14 +382,17 @@ function isWebHostSurfaceFrame(value) {
|
|
|
208
382
|
function isWebHostSurfaceDeltaFrame(value) {
|
|
209
383
|
if (!value || typeof value !== "object") return false;
|
|
210
384
|
const frame = value;
|
|
211
|
-
return frame.version === 3 && frame.encoding === "delta" && (frame.sequence === void 0 || Number.isSafeInteger(frame.sequence) && frame.sequence >= 0) && typeof frame.width === "number" && typeof frame.height === "number" && Array.isArray(frame.styles) && Array.isArray(frame.deltaRows) && frame.deltaRows.every(isWebHostSurfaceDeltaRow) && (frame.images === void 0 || isWebHostSurfaceImages(frame.images)) && (frame.damage === void 0 || isWebHostSurfaceDamage(frame.damage)) && (frame.accessibilityTree === void 0 || isWebHostAccessibilityNodes(frame.accessibilityTree)) && (frame.accessibilityAnnouncements === void 0 || isWebHostAccessibilityAnnouncements(frame.accessibilityAnnouncements)) && (frame.scrollRegions === void 0 || isWebHostScrollRegions(frame.scrollRegions)) && hasValidAdditiveFrameFields(frame);
|
|
385
|
+
return frame.version === 3 && frame.encoding === "delta" && (frame.sequence === void 0 || Number.isSafeInteger(frame.sequence) && frame.sequence >= 0) && typeof frame.width === "number" && typeof frame.height === "number" && Array.isArray(frame.styles) && Array.isArray(frame.deltaRows) && frame.deltaRows.every(isWebHostSurfaceDeltaRow) && isOptionalSafeInteger(frame.baselineGen) && (frame.images === void 0 || isWebHostSurfaceImages(frame.images)) && (frame.damage === void 0 || isWebHostSurfaceDamage(frame.damage)) && (frame.accessibilityTree === void 0 || isWebHostAccessibilityNodes(frame.accessibilityTree)) && (frame.accessibilityAnnouncements === void 0 || isWebHostAccessibilityAnnouncements(frame.accessibilityAnnouncements)) && (frame.scrollRegions === void 0 || isWebHostScrollRegions(frame.scrollRegions)) && hasValidAdditiveFrameFields(frame);
|
|
212
386
|
}
|
|
213
387
|
/**
|
|
214
388
|
* The F19 additive fields shared by the full and delta record shapes. Absent
|
|
215
389
|
* means "feature not present" — servers older than the field omit it.
|
|
216
390
|
*/
|
|
217
391
|
function hasValidAdditiveFrameFields(frame) {
|
|
218
|
-
return (frame.links === void 0 || isWebHostSurfaceLinks(frame.links)) && (frame.linkTargets === void 0 || isWebHostSurfaceLinkTargets(frame.linkTargets)) && (frame.focusPresentation === void 0 || isWebHostFocusPresentation(frame.focusPresentation)) && (frame.preferredGridWidth === void 0 || Number.isSafeInteger(frame.preferredGridWidth) && frame.preferredGridWidth >= 0) && (frame.preferredGridHeight === void 0 || Number.isSafeInteger(frame.preferredGridHeight) && frame.preferredGridHeight >= 0);
|
|
392
|
+
return isOptionalSafeInteger(frame.epoch) && isOptionalSafeInteger(frame.gen) && (frame.links === void 0 || isWebHostSurfaceLinks(frame.links)) && (frame.linkTargets === void 0 || isWebHostSurfaceLinkTargets(frame.linkTargets)) && (frame.focusPresentation === void 0 || isWebHostFocusPresentation(frame.focusPresentation)) && (frame.preferredGridWidth === void 0 || Number.isSafeInteger(frame.preferredGridWidth) && frame.preferredGridWidth >= 0) && (frame.preferredGridHeight === void 0 || Number.isSafeInteger(frame.preferredGridHeight) && frame.preferredGridHeight >= 0);
|
|
393
|
+
}
|
|
394
|
+
function isOptionalSafeInteger(value) {
|
|
395
|
+
return value === void 0 || Number.isSafeInteger(value);
|
|
219
396
|
}
|
|
220
397
|
function isWebHostSurfaceLinks(value) {
|
|
221
398
|
return Array.isArray(value) && value.every(isWebHostSurfaceLinkRow);
|
|
@@ -234,7 +411,7 @@ function isWebHostSurfaceLinkTargets(value) {
|
|
|
234
411
|
function isWebHostFocusPresentation(value) {
|
|
235
412
|
if (!value || typeof value !== "object") return false;
|
|
236
413
|
const presentation = value;
|
|
237
|
-
return (presentation.focusedIdentity === void 0 || typeof presentation.focusedIdentity === "string") &&
|
|
414
|
+
return (presentation.focusedIdentity === void 0 || typeof presentation.focusedIdentity === "string") && typeof presentation.semantics === "string" && typeof presentation.prefersTextInput === "boolean" && typeof presentation.hasFocusedRegion === "boolean";
|
|
238
415
|
}
|
|
239
416
|
function isWebHostSurfaceDeltaRow(value) {
|
|
240
417
|
return Array.isArray(value) && value.length === 2 && Number.isSafeInteger(value[0]) && value[0] >= 0 && isWebHostSurfaceRow(value[1]);
|
|
@@ -251,7 +428,7 @@ function isWebHostAccessibilityNodes(value) {
|
|
|
251
428
|
function isWebHostAccessibilityNode(value) {
|
|
252
429
|
if (!value || typeof value !== "object") return false;
|
|
253
430
|
const node = value;
|
|
254
|
-
return typeof node.id === "string" && (node.parentId === void 0 || typeof node.parentId === "string") && isWebHostSurfaceRect(node.rect) && typeof node.role === "string" && (node.label === void 0 || typeof node.label === "string") && (node.hint === void 0 || typeof node.hint === "string") && (node.hidden === void 0 || typeof node.hidden === "boolean") && (node.liveRegion === void 0 ||
|
|
431
|
+
return typeof node.id === "string" && (node.parentId === void 0 || typeof node.parentId === "string") && isWebHostSurfaceRect(node.rect) && typeof node.role === "string" && (node.label === void 0 || typeof node.label === "string") && (node.hint === void 0 || typeof node.hint === "string") && (node.hidden === void 0 || typeof node.hidden === "boolean") && (node.liveRegion === void 0 || typeof node.liveRegion === "string") && (node.cursorAnchor === void 0 || isWebHostAccessibilityPoint(node.cursorAnchor)) && (node.isFocused === void 0 || typeof node.isFocused === "boolean");
|
|
255
432
|
}
|
|
256
433
|
function isWebHostAccessibilityPoint(value) {
|
|
257
434
|
return Array.isArray(value) && value.length === 2 && value.every((entry) => typeof entry === "number");
|
|
@@ -262,7 +439,7 @@ function isWebHostAccessibilityAnnouncements(value) {
|
|
|
262
439
|
function isWebHostAccessibilityAnnouncement(value) {
|
|
263
440
|
if (!value || typeof value !== "object") return false;
|
|
264
441
|
const announcement = value;
|
|
265
|
-
return typeof announcement.message === "string" &&
|
|
442
|
+
return typeof announcement.message === "string" && typeof announcement.politeness === "string";
|
|
266
443
|
}
|
|
267
444
|
function isWebHostSurfaceImages(value) {
|
|
268
445
|
return Array.isArray(value) && value.every(isWebHostSurfaceImage);
|
|
@@ -284,7 +461,7 @@ function isWebHostSurfaceDamageRange(value) {
|
|
|
284
461
|
return Array.isArray(value) && value.length === 2 && typeof value[0] === "number" && typeof value[1] === "number";
|
|
285
462
|
}
|
|
286
463
|
function isWebHostSurfaceImageFormat(value) {
|
|
287
|
-
return
|
|
464
|
+
return typeof value === "string";
|
|
288
465
|
}
|
|
289
466
|
function isWebHostScrollRegions(value) {
|
|
290
467
|
return Array.isArray(value) && value.every(isWebHostScrollRegion);
|
|
@@ -301,9 +478,9 @@ function isWebHostSurfaceSize(value) {
|
|
|
301
478
|
return Array.isArray(value) && value.length === 2 && value.every((entry) => typeof entry === "number");
|
|
302
479
|
}
|
|
303
480
|
function isWebHostSurfaceScalingMode(value) {
|
|
304
|
-
return
|
|
481
|
+
return typeof value === "string";
|
|
305
482
|
}
|
|
306
483
|
//#endregion
|
|
307
|
-
export { SUPPORTED_SURFACE_VERSION, WebHostOutputDecoder, encodeCapabilitiesControlMessage, encodeKeyInputMessage, encodeMouseInputMessage, encodePasteInputMessage, encodeRenderStyleControlMessage, encodeResizeControlMessage };
|
|
484
|
+
export { MAX_IMAGE_RECOVERY_ID_BYTES, MAX_OUTSTANDING_IMAGE_RECOVERY_IDS, SUPPORTED_SURFACE_VERSION, WebHostOutputDecoder, encodeCapabilitiesControlMessage, encodeKeyInputMessage, encodeMouseInputMessage, encodePasteInputMessage, encodeRenderStyleControlMessage, encodeResizeControlMessage, encodeResyncControlMessage, isWebHostImageRecoveryId };
|
|
308
485
|
|
|
309
486
|
//# sourceMappingURL=WebHostSurfaceTransport.js.map
|