@swiftbrowser/native 0.18.3 → 0.21.0

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.
Files changed (102) hide show
  1. package/README.md +53 -11
  2. package/bin/swiftbrowser-native.mjs +47 -0
  3. package/dist/blob.d.ts +85 -11
  4. package/dist/blob.d.ts.map +1 -1
  5. package/dist/blob.js +184 -34
  6. package/dist/blob.js.map +1 -1
  7. package/dist/bridge.d.ts +66 -8
  8. package/dist/bridge.d.ts.map +1 -1
  9. package/dist/bridge.js.map +1 -1
  10. package/dist/encoding.d.ts +13 -0
  11. package/dist/encoding.d.ts.map +1 -1
  12. package/dist/encoding.js +24 -0
  13. package/dist/encoding.js.map +1 -1
  14. package/dist/fetch.d.ts +27 -13
  15. package/dist/fetch.d.ts.map +1 -1
  16. package/dist/fetch.js +117 -45
  17. package/dist/fetch.js.map +1 -1
  18. package/dist/hostRequests.d.ts +24 -6
  19. package/dist/hostRequests.d.ts.map +1 -1
  20. package/dist/hostRequests.js +108 -15
  21. package/dist/hostRequests.js.map +1 -1
  22. package/dist/index.d.ts +1 -2
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +1 -2
  25. package/dist/index.js.map +1 -1
  26. package/dist/ios.d.ts +79 -0
  27. package/dist/ios.d.ts.map +1 -0
  28. package/dist/ios.js +181 -0
  29. package/dist/ios.js.map +1 -0
  30. package/dist/runtime.d.ts.map +1 -1
  31. package/dist/runtime.js +16 -7
  32. package/dist/runtime.js.map +1 -1
  33. package/dist/subtle.d.ts +1 -1
  34. package/dist/subtle.d.ts.map +1 -1
  35. package/dist/subtle.js +9 -5
  36. package/dist/subtle.js.map +1 -1
  37. package/dist/webSocket.d.ts +12 -5
  38. package/dist/webSocket.d.ts.map +1 -1
  39. package/dist/webSocket.js +37 -11
  40. package/dist/webSocket.js.map +1 -1
  41. package/package.json +7 -3
  42. package/src/blob.ts +215 -34
  43. package/src/bridge.ts +56 -8
  44. package/src/encoding.ts +22 -0
  45. package/src/fetch.ts +111 -48
  46. package/src/hostRequests.ts +129 -22
  47. package/src/index.ts +1 -2
  48. package/src/ios.ts +253 -0
  49. package/src/runtime.ts +23 -8
  50. package/src/subtle.ts +10 -6
  51. package/src/webSocket.ts +37 -13
  52. package/swift/Packages/SwiftBrowserDSP/Package.swift +31 -0
  53. package/swift/Packages/SwiftBrowserDSP/README.md +42 -0
  54. package/swift/Packages/SwiftBrowserDSP/Sources/SwiftBrowserDSP/ProgramNode.swift +306 -0
  55. package/swift/Packages/SwiftBrowserDSP/Sources/SwiftBrowserDSP/ScopeView.swift +79 -0
  56. package/swift/Packages/SwiftBrowserDSP/Sources/SwiftBrowserDSPCore/Machine.swift +1561 -0
  57. package/swift/Packages/SwiftBrowserDSP/Sources/SwiftBrowserDSPCore/Program.swift +483 -0
  58. package/swift/Packages/SwiftBrowserLocalModel/Package.swift +35 -0
  59. package/swift/Packages/SwiftBrowserLocalModel/README.md +66 -0
  60. package/swift/Packages/SwiftBrowserLocalModel/Sources/SwiftBrowserLocalModel/LlamaEngine.swift +223 -0
  61. package/swift/Packages/SwiftBrowserLocalModel/Sources/SwiftBrowserLocalModel/LocalLanguageModel.swift +409 -0
  62. package/swift/Packages/SwiftBrowserShader/Package.swift +31 -0
  63. package/swift/Packages/SwiftBrowserShader/README.md +45 -0
  64. package/swift/Packages/SwiftBrowserShader/Sources/SwiftBrowserShader/ShaderRenderer.swift +103 -0
  65. package/swift/Packages/SwiftBrowserShader/Sources/SwiftBrowserShader/ShaderView.swift +168 -0
  66. package/swift/Packages/SwiftBrowserShader/Sources/SwiftBrowserShaderCore/ShaderProps.swift +120 -0
  67. package/swift/Sources/SwiftBrowserNative/Host/AudioEngineBridge.swift +921 -0
  68. package/swift/Sources/SwiftBrowserNative/Host/AudioEngineNodes.swift +70 -0
  69. package/swift/Sources/SwiftBrowserNative/Host/BodyStream.swift +166 -0
  70. package/swift/Sources/SwiftBrowserNative/Host/FilesBridge.swift +144 -10
  71. package/swift/Sources/SwiftBrowserNative/Host/HostBridge.swift +151 -27
  72. package/swift/Sources/SwiftBrowserNative/Host/HostRequestBridge.swift +139 -40
  73. package/swift/Sources/SwiftBrowserNative/Host/JSHost.swift +116 -0
  74. package/swift/Sources/SwiftBrowserNative/Host/JavaScriptCoreHost.swift +141 -2
  75. package/swift/Sources/SwiftBrowserNative/Host/LanguageModelBridge.swift +511 -0
  76. package/swift/Sources/SwiftBrowserNative/Host/LanguageModelProvider.swift +195 -0
  77. package/swift/Sources/SwiftBrowserNative/Host/WebSocketBridge.swift +24 -11
  78. package/swift/Sources/SwiftBrowserNative/Host/WorkerHost.swift +3 -2
  79. package/swift/Sources/SwiftBrowserNative/Runtime/NativeFunctions.swift +1 -1
  80. package/swift/Sources/SwiftBrowserNative/Runtime/ViewRegistry.swift +57 -0
  81. package/swift/Sources/SwiftBrowserNative/Views/ElementView.swift +12 -7
  82. package/swift/Sources/SwiftBrowserNative/Views/Kinds/Controls.swift +18 -1
  83. package/swift/Sources/SwiftBrowserNative/Views/Kinds/Drawing.swift +378 -0
  84. package/swift/Sources/SwiftBrowserNative/Views/Kinds/Lists.swift +41 -1
  85. package/swift/Sources/SwiftBrowserNative/Views/Kinds/More.swift +88 -17
  86. package/swift/Sources/SwiftBrowserNative/Views/Kinds/Navigation.swift +87 -21
  87. package/swift/Sources/SwiftBrowserNative/Views/Kinds/PinchTracker.swift +200 -0
  88. package/swift/Sources/SwiftBrowserNative/Views/Kinds/PopTap.swift +103 -0
  89. package/swift/Sources/SwiftBrowserNative/Views/Kinds/Stacks.swift +3 -2
  90. package/swift/Sources/SwiftBrowserNative/Views/StyleModifier.swift +146 -0
  91. package/swift/Sources/SwiftBrowserProtocol/Drawing.swift +306 -0
  92. package/swift/Sources/SwiftBrowserProtocol/Props.swift +31 -2
  93. package/swift/Sources/SwiftBrowserProtocol/RendererEvent.swift +24 -3
  94. package/swift/Sources/SwiftBrowserProtocol/Style.swift +87 -0
  95. package/swift/Sources/SwiftBrowserTree/OpTree.swift +25 -0
  96. package/wasm/SwiftBrowserNative.wasm +2 -2
  97. package/dist/native.d.ts +0 -19
  98. package/dist/native.d.ts.map +0 -1
  99. package/dist/native.js +0 -17
  100. package/dist/native.js.map +0 -1
  101. package/src/native.ts +0 -35
  102. package/swift/Sources/SwiftBrowserNative/Runtime/NativeRegistry.swift +0 -53
@@ -1 +1 @@
1
- {"version":3,"file":"subtle.js","sourceRoot":"","sources":["../src/subtle.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"subtle.js","sourceRoot":"","sources":["../src/subtle.ts"],"names":[],"mappings":"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"}
@@ -26,7 +26,12 @@ export interface NativeWebSocketEvent {
26
26
  protocol?: string;
27
27
  text?: string;
28
28
  /** Base64. */
29
- binary?: string;
29
+ /** Base64, or `{ $bytes: 0 }` naming the `Uint8Array` after the event's JSON. */
30
+ binary?: string | {
31
+ $bytes: number;
32
+ };
33
+ /** The views that came after the JSON. */
34
+ bytes?: ArrayBufferView[];
30
35
  message?: string;
31
36
  code?: number;
32
37
  reason?: string;
@@ -64,10 +69,12 @@ export declare class NativeWebSocket {
64
69
  dispatchEvent(event: WebSocketEventLike): boolean;
65
70
  /** The bridge's event for this socket. */
66
71
  receive(event: NativeWebSocketEvent): void;
67
- /** The bridge's `__sbWebSocketEvent(id, json)`. */
68
- static receive(id: number, json: string | NativeWebSocketEvent): void;
69
- /** Points the sockets at the bridge (the runtime, once per install). */
70
- static install(native: WebSocketBridge): void;
72
+ /** The bridge's `__sbWebSocketEvent(id, json, ...bytes)`: a binary message's bytes after the JSON that names them. */
73
+ static receive(id: number, json: string | NativeWebSocketEvent, ...bytes: ArrayBufferView[]): void;
74
+ /** Points the sockets at the bridge (the runtime, once per install); `bytes`: the host carries typed arrays. */
75
+ static install(native: WebSocketBridge, options?: {
76
+ bytes?: boolean;
77
+ }): void;
71
78
  }
72
79
  export {};
73
80
  //# sourceMappingURL=webSocket.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"webSocket.d.ts","sourceRoot":"","sources":["../src/webSocket.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"webSocket.d.ts","sourceRoot":"","sources":["../src/webSocket.ts"],"names":[],"mappings":"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"}
package/dist/webSocket.js CHANGED
@@ -8,11 +8,13 @@
8
8
  * `onmessage`, `onerror`, `onclose`, `addEventListener`, `readyState`,
9
9
  * `binaryType` (`blob` by default, or `arraybuffer`).
10
10
  */
11
- import { SimpleBlob } from './blob';
12
- import { base64Decode, base64Encode } from './encoding';
11
+ import { blobBytes, LazyFile, SimpleBlob } from './blob';
12
+ import { base64Encode, bridgedBytes } from './encoding';
13
13
  const sockets = new Map();
14
14
  let nextId = 1;
15
15
  let bridge = null;
16
+ /** Whether binary crosses as views beside the JSON (a host that carries bytes) rather than base64. */
17
+ let carriesBytes = false;
16
18
  export class NativeWebSocket {
17
19
  static CONNECTING = 0;
18
20
  static OPEN = 1;
@@ -43,7 +45,11 @@ export class NativeWebSocket {
43
45
  this.url = href;
44
46
  this.id = nextId++;
45
47
  sockets.set(this.id, this);
46
- bridge.wsOpen(this.id, href, typeof protocols === 'string' ? [protocols] : [...protocols]);
48
+ const list = typeof protocols === 'string' ? [protocols] : [...protocols];
49
+ if (carriesBytes)
50
+ bridge.wsOpen(this.id, href, list, true);
51
+ else
52
+ bridge.wsOpen(this.id, href, list);
47
53
  }
48
54
  send(data) {
49
55
  if (this.readyState === NativeWebSocket.CONNECTING)
@@ -54,8 +60,27 @@ export class NativeWebSocket {
54
60
  bridge?.wsSend(this.id, JSON.stringify({ text: data }));
55
61
  return;
56
62
  }
57
- const bytes = data instanceof SimpleBlob ? data.bytes() : data instanceof ArrayBuffer ? new Uint8Array(data) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
58
- bridge?.wsSend(this.id, JSON.stringify({ binary: base64Encode(bytes) }));
63
+ if (data instanceof LazyFile) {
64
+ // A picked file on disk: read it, then send (the frame goes out when the read lands; order among lazy sends is the reads').
65
+ void blobBytes(data).then((bytes) => {
66
+ if (this.readyState !== NativeWebSocket.OPEN)
67
+ return;
68
+ if (carriesBytes)
69
+ bridge?.wsSend(this.id, JSON.stringify({ binary: { $bytes: 0 } }), bytes);
70
+ else
71
+ bridge?.wsSend(this.id, JSON.stringify({ binary: base64Encode(bytes) }));
72
+ });
73
+ return;
74
+ }
75
+ const bytes = data instanceof SimpleBlob
76
+ ? data.bytes()
77
+ : data instanceof ArrayBuffer
78
+ ? new Uint8Array(data)
79
+ : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
80
+ if (carriesBytes)
81
+ bridge?.wsSend(this.id, JSON.stringify({ binary: { $bytes: 0 } }), bytes);
82
+ else
83
+ bridge?.wsSend(this.id, JSON.stringify({ binary: base64Encode(bytes) }));
59
84
  }
60
85
  close(code, reason) {
61
86
  if (code !== undefined && code !== 1000 && !(code >= 3000 && code <= 4999))
@@ -98,7 +123,7 @@ export class NativeWebSocket {
98
123
  return;
99
124
  let data = event.text ?? '';
100
125
  if (event.binary !== undefined) {
101
- const bytes = base64Decode(event.binary);
126
+ const bytes = bridgedBytes(typeof event.binary === 'string' ? event.binary : event.bytes?.[event.binary.$bytes]);
102
127
  data = this.binaryType === 'arraybuffer' ? bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength) : new SimpleBlob([bytes]);
103
128
  }
104
129
  this.dispatchEvent({ type: 'message', target: this, data });
@@ -116,8 +141,8 @@ export class NativeWebSocket {
116
141
  return;
117
142
  }
118
143
  }
119
- /** The bridge's `__sbWebSocketEvent(id, json)`. */
120
- static receive(id, json) {
144
+ /** The bridge's `__sbWebSocketEvent(id, json, ...bytes)`: a binary message's bytes after the JSON that names them. */
145
+ static receive(id, json, ...bytes) {
121
146
  const socket = sockets.get(id);
122
147
  if (!socket)
123
148
  return;
@@ -128,11 +153,12 @@ export class NativeWebSocket {
128
153
  catch {
129
154
  return;
130
155
  }
131
- socket.receive(event);
156
+ socket.receive(bytes.length ? { ...event, bytes } : event);
132
157
  }
133
- /** Points the sockets at the bridge (the runtime, once per install). */
134
- static install(native) {
158
+ /** Points the sockets at the bridge (the runtime, once per install); `bytes`: the host carries typed arrays. */
159
+ static install(native, options = {}) {
135
160
  bridge = native;
161
+ carriesBytes = options.bytes === true;
136
162
  }
137
163
  }
138
164
  /** A `DOMException` stand-in: an error with the browser's name. */
@@ -1 +1 @@
1
- {"version":3,"file":"webSocket.js","sourceRoot":"","sources":["../src/webSocket.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"webSocket.js","sourceRoot":"","sources":["../src/webSocket.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swiftbrowser/native",
3
- "version": "0.18.3",
3
+ "version": "0.21.0",
4
4
  "type": "module",
5
5
  "description": "Run a @swiftbrowser/react app natively: the runtime a JavaScriptCore-hosted app needs (timers, console, fetch and the other web globals over the SwiftBrowser Native bridge), the `run` entry that renders into the native SwiftUI renderer, and the bundler that builds app.js for the Xcode target.",
6
6
  "repository": {
@@ -30,6 +30,10 @@
30
30
  "./wasm-host": {
31
31
  "types": "./dist/wasmHost.d.ts",
32
32
  "default": "./dist/wasmHost.js"
33
+ },
34
+ "./ios": {
35
+ "types": "./dist/ios.d.ts",
36
+ "default": "./dist/ios.js"
33
37
  }
34
38
  },
35
39
  "bin": {
@@ -59,8 +63,8 @@
59
63
  },
60
64
  "dependencies": {
61
65
  "@babel/core": "^7.29.7",
62
- "@swiftbrowser/react": "0.18.3",
63
- "@swiftbrowser/web": "0.18.3",
66
+ "@swiftbrowser/react": "0.21.0",
67
+ "@swiftbrowser/web": "0.21.0",
64
68
  "esbuild": "^0.28.2",
65
69
  "react-refresh": "^0.17.0"
66
70
  },
package/src/blob.ts CHANGED
@@ -1,15 +1,21 @@
1
1
  /**
2
2
  * `Blob`, `File` and `FormData` for the native app: bytes with a type, a
3
- * named one, and a form whose entries `fetch` sends as multipart. A body is
4
- * still whole (no streams); `URL.createObjectURL` gives a `data:` URL, which
5
- * the host's image loader and `URLSession` both read, and
6
- * `revokeObjectURL` has nothing to free.
3
+ * named one, and a form whose entries `fetch` sends as multipart. A blob is
4
+ * a list of parts, each bytes in memory or a range of a file on disk (a
5
+ * `LazyFile`, as the pickers and drops answer), so a `Blob` built from
6
+ * picked files' slices holds nothing in memory and `fetch` streams it from
7
+ * disk (fetch.ts). `URL.createObjectURL` gives a `data:` URL, which the
8
+ * host's image loader and `URLSession` both read, and `revokeObjectURL` has
9
+ * nothing to free.
7
10
  */
8
11
 
9
12
  import { base64Encode, utf8Decode, utf8Encode } from './encoding';
10
13
 
11
14
  export type BlobPartLike = string | ArrayBuffer | ArrayBufferView | SimpleBlob;
12
15
 
16
+ /** What a blob, and so a request body, is made of: bytes here, or a range of a file on disk. */
17
+ export type BodyPart = { bytes: Uint8Array } | { file: LazyFile };
18
+
13
19
  export interface BlobOptions {
14
20
  type?: string;
15
21
  }
@@ -18,12 +24,25 @@ export interface FileOptions extends BlobOptions {
18
24
  lastModified?: number;
19
25
  }
20
26
 
21
- function partBytes(part: BlobPartLike): Uint8Array {
22
- if (typeof part === 'string') return utf8Encode(part);
23
- if (part instanceof SimpleBlob) return part.bytes();
24
- if (part instanceof ArrayBuffer) return new Uint8Array(part.slice(0));
25
- if (ArrayBuffer.isView(part)) return new Uint8Array(part.buffer.slice(part.byteOffset, part.byteOffset + part.byteLength));
26
- return utf8Encode(String(part));
27
+ /** A constructor part as body parts: a blob's own parts are taken as they are (a file on disk stays there). */
28
+ function toParts(part: BlobPartLike): BodyPart[] {
29
+ if (typeof part === 'string') return [{ bytes: utf8Encode(part) }];
30
+ if (part instanceof SimpleBlob) return part.parts();
31
+ if (part instanceof ArrayBuffer) return [{ bytes: new Uint8Array(part.slice(0)) }];
32
+ if (ArrayBuffer.isView(part)) return [{ bytes: new Uint8Array(part.buffer.slice(part.byteOffset, part.byteOffset + part.byteLength)) }];
33
+ return [{ bytes: utf8Encode(String(part)) }];
34
+ }
35
+
36
+ export const partSize = (part: BodyPart): number => ('bytes' in part ? part.bytes.byteLength : part.file.size);
37
+
38
+ /** Whether any part is a file on disk, which only an asynchronous read reaches. */
39
+ export const partsAreLazy = (parts: readonly BodyPart[]): boolean => parts.some((part) => 'file' in part);
40
+
41
+ /** The parts' bytes, whole: those on disk read through the files bridge. */
42
+ export async function partsBytes(parts: readonly BodyPart[]): Promise<Uint8Array> {
43
+ const read: Uint8Array[] = [];
44
+ for (const part of parts) read.push('bytes' in part ? part.bytes : await part.file.bytesAsync());
45
+ return concat(read);
27
46
  }
28
47
 
29
48
  function concat(parts: Uint8Array[]): Uint8Array {
@@ -37,39 +56,78 @@ function concat(parts: Uint8Array[]): Uint8Array {
37
56
  return out;
38
57
  }
39
58
 
40
- /** The browser's `Blob`: bytes and a MIME type. */
59
+ /** The browser's `Blob`: parts (bytes, or files on disk) and a MIME type. */
41
60
  export class SimpleBlob {
42
- private readonly data: Uint8Array;
61
+ private readonly parts_: BodyPart[];
62
+ /** The parts joined, once asked for (a blob with nothing on disk). */
63
+ private joined: Uint8Array | null = null;
43
64
  readonly type: string;
44
65
 
45
66
  constructor(parts: Iterable<BlobPartLike> = [], options: BlobOptions = {}) {
46
- this.data = concat([...parts].map(partBytes));
67
+ this.parts_ = [...parts].flatMap(toParts);
47
68
  // As the browser does: lowercased, and empty when it is not printable ASCII.
48
69
  const type = options.type ?? '';
49
70
  this.type = /^[\x20-\x7e]*$/.test(type) ? type.toLowerCase() : '';
50
71
  }
51
72
 
73
+ /** A blob straight from parts (a slice). */
74
+ protected static fromParts(parts: BodyPart[], type: string): SimpleBlob {
75
+ const blob = new SimpleBlob([], { type });
76
+ blob.parts_.push(...parts);
77
+ return blob;
78
+ }
79
+
52
80
  get size(): number {
53
- return this.data.byteLength;
81
+ return this.parts_.reduce((sum, part) => sum + partSize(part), 0);
54
82
  }
55
83
 
56
- /** The bytes (a view; callers must not write into it). */
84
+ /** The parts, in order: what a request body sends, each from memory or from disk. */
85
+ parts(): BodyPart[] {
86
+ return [...this.parts_];
87
+ }
88
+
89
+ /** Whether any part is still on disk, so `bytes()` cannot answer and `bytesAsync()` reads it. */
90
+ get isLazy(): boolean {
91
+ return partsAreLazy(this.parts_);
92
+ }
93
+
94
+ /** The bytes (a view; callers must not write into it). Throws for a blob holding a file on disk: read it with `bytesAsync`. */
57
95
  bytes(): Uint8Array {
58
- return this.data;
96
+ if (this.isLazy) throw new Error('unsupported: the blob holds a picked file, which is read asynchronously (arrayBuffer); it is not in memory');
97
+ if (!this.joined) this.joined = this.parts_.length === 1 && 'bytes' in this.parts_[0]! ? this.parts_[0].bytes : concat(this.parts_.map((part) => ('bytes' in part ? part.bytes : new Uint8Array(0))));
98
+ return this.joined;
99
+ }
100
+
101
+ /** The bytes, the parts on disk read now. */
102
+ async bytesAsync(): Promise<Uint8Array> {
103
+ return this.isLazy ? partsBytes(this.parts_) : this.bytes();
59
104
  }
60
105
 
61
106
  slice(start = 0, end = this.size, contentType = ''): SimpleBlob {
62
- const from = start < 0 ? Math.max(this.size + start, 0) : Math.min(start, this.size);
63
- const to = end < 0 ? Math.max(this.size + end, 0) : Math.min(end, this.size);
64
- return new SimpleBlob([this.data.subarray(from, Math.max(from, to))], { type: contentType });
107
+ const size = this.size;
108
+ const from = start < 0 ? Math.max(size + start, 0) : Math.min(start, size);
109
+ const to = Math.max(from, end < 0 ? Math.max(size + end, 0) : Math.min(end, size));
110
+ const out: BodyPart[] = [];
111
+ let at = 0;
112
+ for (const part of this.parts_) {
113
+ const length = partSize(part);
114
+ const partStart = at;
115
+ at += length;
116
+ if (at <= from || partStart >= to) continue;
117
+ const a = Math.max(from, partStart) - partStart;
118
+ const b = Math.min(to, at) - partStart;
119
+ out.push('bytes' in part ? { bytes: part.bytes.subarray(a, b) } : { file: part.file.slice(a, b) });
120
+ }
121
+ return SimpleBlob.fromParts(out, contentType);
65
122
  }
66
123
 
67
124
  async arrayBuffer(): Promise<ArrayBuffer> {
68
- return this.data.buffer.slice(this.data.byteOffset, this.data.byteOffset + this.data.byteLength) as ArrayBuffer;
125
+ const bytes = await this.bytesAsync();
126
+ return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength) as ArrayBuffer;
69
127
  }
70
128
 
71
129
  async text(): Promise<string> {
72
- return utf8Decode(this.data);
130
+ return utf8Decode(await this.bytesAsync());
73
131
  }
74
132
 
75
133
  get [Symbol.toStringTag](): string {
@@ -93,6 +151,98 @@ export class SimpleFile extends SimpleBlob {
93
151
  }
94
152
  }
95
153
 
154
+ /**
155
+ * A file the viewer picked or dropped, still on disk: its name, type and size
156
+ * are known, its bytes are read through the host's files bridge only when
157
+ * asked (`arrayBuffer`, `bytesAsync`, or a `fetch` body), a range at a time
158
+ * for a `slice`, so a large file never sits in memory whole. `fileManager.write`
159
+ * copies one on disk instead of reading it. `bytes()` (synchronous) is not
160
+ * available: it throws, as the bytes are not here.
161
+ */
162
+ export class LazyFile extends SimpleFile {
163
+ /** The `file:` URL the host reads it at. */
164
+ readonly url: string;
165
+ /** The range of the file on disk this stands for (`slice` narrows it). */
166
+ readonly start: number;
167
+ readonly end: number;
168
+ private readonly reader: (url: string, start: number, end: number) => Promise<Uint8Array>;
169
+
170
+ constructor(
171
+ url: string,
172
+ name: string,
173
+ size: number,
174
+ reader: (url: string, start: number, end: number) => Promise<Uint8Array>,
175
+ options: FileOptions = {},
176
+ range: { start: number; end: number } = { start: 0, end: size },
177
+ ) {
178
+ super([], name, options);
179
+ this.url = url;
180
+ this.reader = reader;
181
+ this.start = range.start;
182
+ this.end = range.end;
183
+ }
184
+
185
+ /** Whether this is the whole file on disk, not a slice of it. */
186
+ get isWhole(): boolean {
187
+ return this.start === 0 && this.end === this.sizeOnDisk;
188
+ }
189
+
190
+ private sizeOnDisk = 0;
191
+
192
+ /** Sets the file's size on disk (the constructor's `size`); the range defaults to all of it. */
193
+ static make(url: string, name: string, size: number, reader: (url: string, start: number, end: number) => Promise<Uint8Array>, options: FileOptions = {}): LazyFile {
194
+ const file = new LazyFile(url, name, size, reader, options);
195
+ file.sizeOnDisk = size;
196
+ return file;
197
+ }
198
+
199
+ override get size(): number {
200
+ return this.end - this.start;
201
+ }
202
+
203
+ override parts(): BodyPart[] {
204
+ return [{ file: this }];
205
+ }
206
+
207
+ override get isLazy(): boolean {
208
+ return true;
209
+ }
210
+
211
+ override bytes(): Uint8Array {
212
+ throw new Error('unsupported: a picked file is read asynchronously (arrayBuffer); it is not in memory');
213
+ }
214
+
215
+ /** The bytes, read from disk now. */
216
+ override async bytesAsync(): Promise<Uint8Array> {
217
+ return this.reader(this.url, this.start, this.end);
218
+ }
219
+
220
+ override slice(start = 0, end = this.size, contentType = ''): LazyFile {
221
+ const size = this.size;
222
+ const from = start < 0 ? Math.max(size + start, 0) : Math.min(start, size);
223
+ const to = end < 0 ? Math.max(size + end, 0) : Math.min(end, size);
224
+ const sliced = new LazyFile(this.url, this.name, this.sizeOnDisk, this.reader, { type: contentType, lastModified: this.lastModified }, {
225
+ start: this.start + from,
226
+ end: this.start + Math.max(from, to),
227
+ });
228
+ sliced.sizeOnDisk = this.sizeOnDisk;
229
+ return sliced;
230
+ }
231
+
232
+ /** The same file under another name (a form's `filename`), still on disk. */
233
+ renamed(name: string): LazyFile {
234
+ const copy = new LazyFile(this.url, name, this.sizeOnDisk, this.reader, { type: this.type, lastModified: this.lastModified }, { start: this.start, end: this.end });
235
+ copy.sizeOnDisk = this.sizeOnDisk;
236
+ return copy;
237
+ }
238
+
239
+ }
240
+
241
+ /** A blob's bytes, read from disk where it holds a `LazyFile`. */
242
+ export async function blobBytes(blob: SimpleBlob): Promise<Uint8Array> {
243
+ return blob.bytesAsync();
244
+ }
245
+
96
246
  export type FormDataEntryValueLike = string | SimpleFile;
97
247
 
98
248
  /** The browser's `FormData`, as far as a request body needs it. */
@@ -102,11 +252,17 @@ export class SimpleFormData {
102
252
  private static value(value: unknown, filename?: string): FormDataEntryValueLike {
103
253
  if (value instanceof SimpleBlob) {
104
254
  const name = filename ?? (value instanceof SimpleFile ? value.name : 'blob');
255
+ if (value instanceof LazyFile) return filename === undefined ? value : value.renamed(filename);
105
256
  return value instanceof SimpleFile && filename === undefined ? value : new SimpleFile([value], name, { type: value.type });
106
257
  }
107
258
  return String(value);
108
259
  }
109
260
 
261
+ /** Whether an entry is a picked file still on disk (or a blob holding one), which the form's body streams from there. */
262
+ get hasLazyFiles(): boolean {
263
+ return this.entries_.some(([, value]) => typeof value !== 'string' && value.isLazy);
264
+ }
265
+
110
266
  append(name: string, value: unknown, filename?: string): void {
111
267
  this.entries_.push([String(name), SimpleFormData.value(value, filename)]);
112
268
  }
@@ -164,23 +320,48 @@ export class SimpleFormData {
164
320
  }
165
321
  }
166
322
 
167
- /** A multipart/form-data body for the form, with the boundary `random` makes unique. */
168
- export function encodeMultipart(form: SimpleFormData, random: (count: number) => Uint8Array): { bytes: Uint8Array; contentType: string } {
169
- const boundary = `----SwiftBrowserFormBoundary${Array.from(random(16), (byte) => byte.toString(16).padStart(2, '0')).join('')}`;
323
+ /** The boundary of a multipart body, unique by `random`'s bytes. */
324
+ export function multipartBoundary(random: (count: number) => Uint8Array): string {
325
+ return `----SwiftBrowserFormBoundary${Array.from(random(16), (byte) => byte.toString(16).padStart(2, '0')).join('')}`;
326
+ }
327
+
328
+ function multipartHead(boundary: string, name: string, value: FormDataEntryValueLike): Uint8Array {
170
329
  const escape = (text: string): string => text.replace(/\r/g, '%0D').replace(/\n/g, '%0A').replace(/"/g, '%22');
171
- const parts: Uint8Array[] = [];
330
+ const head = [`--${boundary}`, `Content-Disposition: form-data; name="${escape(name)}"` + (typeof value === 'string' ? '' : `; filename="${escape(value.name)}"`)];
331
+ if (typeof value !== 'string') head.push(`Content-Type: ${value.type || 'application/octet-stream'}`);
332
+ return utf8Encode(`${head.join('\r\n')}\r\n\r\n`);
333
+ }
334
+
335
+ /**
336
+ * A multipart/form-data body for the form, with the boundary `random` makes
337
+ * unique, as parts: the heads and the fields in memory, a file still on disk
338
+ * as the range of it (`fetch` streams those from disk, or reads them first
339
+ * for a host that cannot).
340
+ */
341
+ export function encodeMultipart(form: SimpleFormData, random: (count: number) => Uint8Array, boundary = multipartBoundary(random)): { parts: BodyPart[]; contentType: string } {
342
+ const parts: BodyPart[] = [];
172
343
  for (const [name, value] of form.entries()) {
173
- const head = [`--${boundary}`, `Content-Disposition: form-data; name="${escape(name)}"` + (typeof value === 'string' ? '' : `; filename="${escape(value.name)}"`)];
174
- if (typeof value !== 'string') head.push(`Content-Type: ${value.type || 'application/octet-stream'}`);
175
- parts.push(utf8Encode(`${head.join('\r\n')}\r\n\r\n`));
176
- parts.push(typeof value === 'string' ? utf8Encode(value) : value.bytes());
177
- parts.push(utf8Encode('\r\n'));
178
- }
179
- parts.push(utf8Encode(`--${boundary}--\r\n`));
180
- return { bytes: concat(parts), contentType: `multipart/form-data; boundary=${boundary}` };
344
+ parts.push({ bytes: multipartHead(boundary, name, value) });
345
+ if (typeof value === 'string') parts.push({ bytes: utf8Encode(value) });
346
+ else parts.push(...value.parts());
347
+ parts.push({ bytes: utf8Encode('\r\n') });
348
+ }
349
+ parts.push({ bytes: utf8Encode(`--${boundary}--\r\n`) });
350
+ return { parts, contentType: `multipart/form-data; boundary=${boundary}` };
351
+ }
352
+
353
+ /** `encodeMultipart` with the body whole: a form's files on disk are read first. */
354
+ export async function encodeMultipartAsync(
355
+ form: SimpleFormData,
356
+ random: (count: number) => Uint8Array,
357
+ boundary = multipartBoundary(random),
358
+ ): Promise<{ bytes: Uint8Array; contentType: string }> {
359
+ const { parts, contentType } = encodeMultipart(form, random, boundary);
360
+ return { bytes: await partsBytes(parts), contentType };
181
361
  }
182
362
 
183
- /** `URL.createObjectURL`: a `data:` URL holding the blob. */
363
+ /** `URL.createObjectURL`: a `data:` URL holding the blob; a picked file still on disk is its own `file:` URL. */
184
364
  export function objectURL(blob: SimpleBlob): string {
365
+ if (blob instanceof LazyFile && blob.isWhole) return blob.url;
185
366
  return `data:${blob.type || 'application/octet-stream'};base64,${base64Encode(blob.bytes())}`;
186
367
  }