capnweb 0.0.0-c2bb17b → 0.0.0-cfa1b95

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.cts CHANGED
@@ -12,18 +12,26 @@ import { IncomingMessage, ServerResponse, OutgoingHttpHeaders, OutgoingHttpHeade
12
12
  // accept `WorkerEntrypoint` from `cloudflare:workers`, not any other class with the same shape)
13
13
  declare const __RPC_STUB_BRAND: '__RPC_STUB_BRAND';
14
14
  declare const __RPC_TARGET_BRAND: '__RPC_TARGET_BRAND';
15
+ // Distinguishes mapper placeholders from regular values so param unwrapping can accept them.
16
+ declare const __RPC_MAP_VALUE_BRAND: unique symbol;
15
17
  interface RpcTargetBranded {
16
18
  [__RPC_TARGET_BRAND]: never;
17
19
  }
18
20
 
19
21
  // Types that can be used through `Stub`s
20
- type Stubable = RpcTargetBranded | ((...args: any[]) => any);
22
+ // `never[]` preserves compatibility with strongly-typed function signatures without introducing
23
+ // `any` into inference.
24
+ type Stubable = RpcTargetBranded | ((...args: never[]) => unknown);
25
+
26
+ type IsUnknown<T> = unknown extends T ? ([T] extends [unknown] ? true : false) : false;
21
27
 
22
28
  // Types that can be passed over RPC
23
29
  // The reason for using a generic type here is to build a serializable subset of structured
24
30
  // cloneable composite types. This allows types defined with the "interface" keyword to pass the
25
31
  // serializable check as well. Otherwise, only types defined with the "type" keyword would pass.
26
32
  type RpcCompatible<T> =
33
+ // Allow `unknown` as a leaf so records/interfaces with `unknown` fields remain compatible.
34
+ | (IsUnknown<T> extends true ? unknown : never)
27
35
  // Structured cloneables
28
36
  | BaseType
29
37
  // Structured cloneable composites
@@ -45,7 +53,7 @@ type RpcCompatible<T> =
45
53
 
46
54
  // Base type for all RPC stubs, including common memory management methods.
47
55
  // `T` is used as a marker type for unwrapping `Stub`s later.
48
- interface StubBase<T extends RpcCompatible<T>> extends Disposable {
56
+ interface StubBase<T = unknown> extends Disposable {
49
57
  [__RPC_STUB_BRAND]: T;
50
58
  dup(): this;
51
59
  onRpcBroken(callback: (error: any) => void): void;
@@ -102,7 +110,7 @@ type Stubify<T> =
102
110
  : T extends ReadonlyArray<infer V> ? ReadonlyArray<Stubify<V>>
103
111
  : T extends BaseType ? T
104
112
  // When using "unknown" instead of "any", interfaces are not stubified.
105
- : T extends { [key: string | number]: any } ? { [K in keyof T]: Stubify<T[K]> }
113
+ : T extends { [key: string | number]: any } ? { [K in keyof T as K extends string | number ? K : never]: Stubify<T[K]> }
106
114
  : T;
107
115
 
108
116
  // Recursively rewrite all `Stub<T>`s with the corresponding `T`s.
@@ -110,7 +118,10 @@ type Stubify<T> =
110
118
  // `Stub` depends on `Provider`, which depends on `Unstubify`, which would depend on `Stub`.
111
119
  // prettier-ignore
112
120
  type UnstubifyInner<T> =
113
- T extends StubBase<infer V> ? (T | V) // can provide either stub or local RpcTarget
121
+ // Preserve local RpcTarget acceptance, but avoid needless `Stub | Value` unions when the stub
122
+ // is already assignable to the value type (important for callback contextual typing).
123
+ T extends StubBase<infer V> ? (T extends V ? UnstubifyInner<V> : (T | UnstubifyInner<V>))
124
+ : T extends Promise<infer U> ? UnstubifyInner<U>
114
125
  : T extends Map<infer K, infer V> ? Map<Unstubify<K>, Unstubify<V>>
115
126
  : T extends Set<infer V> ? Set<Unstubify<V>>
116
127
  : T extends [] ? []
@@ -120,14 +131,30 @@ type UnstubifyInner<T> =
120
131
  : T extends Array<infer V> ? Array<Unstubify<V>>
121
132
  : T extends ReadonlyArray<infer V> ? ReadonlyArray<Unstubify<V>>
122
133
  : T extends BaseType ? T
123
- : T extends { [key: string | number]: unknown } ? { [K in keyof T]: Unstubify<T[K]> }
134
+ : T extends { [key: string | number]: unknown } ? { [K in keyof T as K extends string | number ? K : never]: Unstubify<T[K]> }
124
135
  : T;
125
136
 
126
137
  // You can put promises anywhere in the params and they'll be resolved before delivery.
127
138
  // (This also covers RpcPromise, because it's defined as being a Promise.)
128
- type Unstubify<T> = UnstubifyInner<T> | Promise<UnstubifyInner<T>>
139
+ // Map placeholders are also allowed so primitive map callback inputs can be forwarded directly
140
+ // into RPC params.
141
+ //
142
+ // Keep raw non-stub members so generic assignability still works when UnstubifyInner<T> is deferred.
143
+ // Remove stub members from mixed unions so callback params don’t get both stub and unstubbed signatures.
144
+ // Marker carried by map() callback inputs. This lets primitive placeholders flow through params.
145
+ type Unstubify<T> =
146
+ | NonStubMembers<T>
147
+ | UnstubifyInner<T>
148
+ | Promise<UnstubifyInner<T>>
149
+ | MapValuePlaceholder<UnstubifyInner<T>>;
150
+
151
+ type UnstubifyAll<A extends readonly unknown[]> = { [I in keyof A]: Unstubify<A[I]> };
129
152
 
130
- type UnstubifyAll<A extends any[]> = { [I in keyof A]: Unstubify<A[I]> };
153
+ interface MapValuePlaceholder<T> {
154
+ [__RPC_MAP_VALUE_BRAND]: T;
155
+ }
156
+
157
+ type NonStubMembers<T> = Exclude<T, StubBase<any>>;
131
158
 
132
159
  // Utility type for adding `Disposable`s to `object` types only.
133
160
  // Note `unknown & T` is equivalent to `T`.
@@ -142,17 +169,22 @@ type MaybeDisposable<T> = T extends object ? Disposable : unknown;
142
169
  // Intersecting with `(Maybe)Provider` allows pipelining.
143
170
  // prettier-ignore
144
171
  type Result<R> =
145
- R extends Stubable ? Promise<Stub<R>> & Provider<R> & StubBase<R>
172
+ IsAny<R> extends true ? UnknownResult
173
+ : IsUnknown<R> extends true ? UnknownResult
174
+ : R extends Stubable ? Promise<Stub<R>> & Provider<R> & StubBase<R>
146
175
  : R extends RpcCompatible<R> ? Promise<Stubify<R> & MaybeDisposable<R>> & Provider<R> & StubBase<R>
147
176
  : never;
148
177
 
178
+ type IsAny<T> = 0 extends (1 & T) ? true : false;
179
+ type UnknownResult = Promise<unknown> & Provider<unknown> & StubBase<unknown>;
180
+
149
181
  // Type for method or property on an RPC interface.
150
182
  // For methods, unwrap `Stub`s in parameters, and rewrite returns to be `Result`s.
151
183
  // Unwrapping `Stub`s allows calling with `Stubable` arguments.
152
184
  // For properties, rewrite types to be `Result`s.
153
185
  // In each case, unwrap `Promise`s.
154
186
  type MethodOrProperty<V> = V extends (...args: infer P) => infer R
155
- ? (...args: UnstubifyAll<P>) => Result<Awaited<R>>
187
+ ? (...args: UnstubifyAll<P>) => IsAny<R> extends true ? UnknownResult : Result<Awaited<R>>
156
188
  : Result<Awaited<V>>;
157
189
 
158
190
  // Type for the callable part of an `Provider` if `T` is callable.
@@ -161,22 +193,62 @@ type MaybeCallableProvider<T> = T extends (...args: any[]) => any
161
193
  ? MethodOrProperty<T>
162
194
  : unknown;
163
195
 
196
+ type TupleIndexKeys<T extends ReadonlyArray<unknown>> = Extract<keyof T, `${number}`>;
197
+ type MapCallbackValue<T> =
198
+ // `Omit` removes call signatures, so re-intersect callable provider behavior.
199
+ T extends unknown
200
+ ? Omit<Result<T>, keyof Promise<unknown>> &
201
+ MaybeCallableProvider<T> &
202
+ MapValuePlaceholder<T>
203
+ : never;
204
+ type InvalidNativePromiseInMapResult<T, Seen = never> =
205
+ T extends unknown ? InvalidNativePromiseInMapResultImpl<T, Seen> : never;
206
+ type InvalidNativePromiseInMapResultImpl<T, Seen> =
207
+ [T] extends [Seen] ? never
208
+ // RpcPromise is modeled as Promise & StubBase, so allow promise-like stub values.
209
+ : T extends StubBase<any> ? never
210
+ // Native thenables cannot be represented in map recordings, even when typed as PromiseLike.
211
+ : T extends PromiseLike<unknown> ? T
212
+ : T extends Map<infer K, infer V>
213
+ ? InvalidNativePromiseInMapResult<K, Seen | T> |
214
+ InvalidNativePromiseInMapResult<V, Seen | T>
215
+ : T extends Set<infer V> ? InvalidNativePromiseInMapResult<V, Seen | T>
216
+ : T extends readonly [] ? never
217
+ : T extends readonly [infer Head, ...infer Tail]
218
+ ? InvalidNativePromiseInMapResult<Head, Seen | T> |
219
+ InvalidNativePromiseInMapResult<Tail[number], Seen | T>
220
+ : T extends ReadonlyArray<infer V> ? InvalidNativePromiseInMapResult<V, Seen | T>
221
+ : T extends { [key: string | number]: unknown }
222
+ ? InvalidNativePromiseInMapResult<
223
+ T[Extract<keyof T, string | number>],
224
+ Seen | T
225
+ >
226
+ : never;
227
+ type MapCallbackReturn<T> =
228
+ InvalidNativePromiseInMapResult<T> extends never ? T : never;
229
+ type ArrayProvider<E> = {
230
+ [K in number]: MethodOrProperty<E>;
231
+ } & {
232
+ map<V>(callback: (elem: MapCallbackValue<E>) => MapCallbackReturn<V>): Result<Array<V>>;
233
+ };
234
+ type TupleProvider<T extends ReadonlyArray<unknown>> = {
235
+ [K in TupleIndexKeys<T>]: MethodOrProperty<T[K]>;
236
+ } & ArrayProvider<T[number]>;
237
+
164
238
  // Base type for all other types providing RPC-like interfaces.
165
239
  // Rewrites all methods/properties to be `MethodOrProperty`s, while preserving callable types.
166
240
  type Provider<T> = MaybeCallableProvider<T> &
167
- (T extends Array<infer U>
168
- ? {
169
- [key: number]: MethodOrProperty<U>;
170
- } & {
171
- map<V>(callback: (elem: U) => V): Result<Array<V>>;
172
- }
241
+ (T extends ReadonlyArray<unknown>
242
+ ? number extends T["length"] ? ArrayProvider<T[number]> : TupleProvider<T>
173
243
  : {
174
244
  [K in Exclude<
175
245
  keyof T,
176
246
  symbol | keyof StubBase<never>
177
247
  >]: MethodOrProperty<T[K]>;
178
248
  } & {
179
- map<V>(callback: (value: NonNullable<T>) => V): Result<Array<V>>;
249
+ map<V>(
250
+ callback: (value: MapCallbackValue<NonNullable<T>>) => MapCallbackReturn<V>
251
+ ): Result<Array<V>>;
180
252
  });
181
253
 
182
254
  /**
package/dist/index.d.ts CHANGED
@@ -12,18 +12,26 @@ import { IncomingMessage, ServerResponse, OutgoingHttpHeaders, OutgoingHttpHeade
12
12
  // accept `WorkerEntrypoint` from `cloudflare:workers`, not any other class with the same shape)
13
13
  declare const __RPC_STUB_BRAND: '__RPC_STUB_BRAND';
14
14
  declare const __RPC_TARGET_BRAND: '__RPC_TARGET_BRAND';
15
+ // Distinguishes mapper placeholders from regular values so param unwrapping can accept them.
16
+ declare const __RPC_MAP_VALUE_BRAND: unique symbol;
15
17
  interface RpcTargetBranded {
16
18
  [__RPC_TARGET_BRAND]: never;
17
19
  }
18
20
 
19
21
  // Types that can be used through `Stub`s
20
- type Stubable = RpcTargetBranded | ((...args: any[]) => any);
22
+ // `never[]` preserves compatibility with strongly-typed function signatures without introducing
23
+ // `any` into inference.
24
+ type Stubable = RpcTargetBranded | ((...args: never[]) => unknown);
25
+
26
+ type IsUnknown<T> = unknown extends T ? ([T] extends [unknown] ? true : false) : false;
21
27
 
22
28
  // Types that can be passed over RPC
23
29
  // The reason for using a generic type here is to build a serializable subset of structured
24
30
  // cloneable composite types. This allows types defined with the "interface" keyword to pass the
25
31
  // serializable check as well. Otherwise, only types defined with the "type" keyword would pass.
26
32
  type RpcCompatible<T> =
33
+ // Allow `unknown` as a leaf so records/interfaces with `unknown` fields remain compatible.
34
+ | (IsUnknown<T> extends true ? unknown : never)
27
35
  // Structured cloneables
28
36
  | BaseType
29
37
  // Structured cloneable composites
@@ -45,7 +53,7 @@ type RpcCompatible<T> =
45
53
 
46
54
  // Base type for all RPC stubs, including common memory management methods.
47
55
  // `T` is used as a marker type for unwrapping `Stub`s later.
48
- interface StubBase<T extends RpcCompatible<T>> extends Disposable {
56
+ interface StubBase<T = unknown> extends Disposable {
49
57
  [__RPC_STUB_BRAND]: T;
50
58
  dup(): this;
51
59
  onRpcBroken(callback: (error: any) => void): void;
@@ -102,7 +110,7 @@ type Stubify<T> =
102
110
  : T extends ReadonlyArray<infer V> ? ReadonlyArray<Stubify<V>>
103
111
  : T extends BaseType ? T
104
112
  // When using "unknown" instead of "any", interfaces are not stubified.
105
- : T extends { [key: string | number]: any } ? { [K in keyof T]: Stubify<T[K]> }
113
+ : T extends { [key: string | number]: any } ? { [K in keyof T as K extends string | number ? K : never]: Stubify<T[K]> }
106
114
  : T;
107
115
 
108
116
  // Recursively rewrite all `Stub<T>`s with the corresponding `T`s.
@@ -110,7 +118,10 @@ type Stubify<T> =
110
118
  // `Stub` depends on `Provider`, which depends on `Unstubify`, which would depend on `Stub`.
111
119
  // prettier-ignore
112
120
  type UnstubifyInner<T> =
113
- T extends StubBase<infer V> ? (T | V) // can provide either stub or local RpcTarget
121
+ // Preserve local RpcTarget acceptance, but avoid needless `Stub | Value` unions when the stub
122
+ // is already assignable to the value type (important for callback contextual typing).
123
+ T extends StubBase<infer V> ? (T extends V ? UnstubifyInner<V> : (T | UnstubifyInner<V>))
124
+ : T extends Promise<infer U> ? UnstubifyInner<U>
114
125
  : T extends Map<infer K, infer V> ? Map<Unstubify<K>, Unstubify<V>>
115
126
  : T extends Set<infer V> ? Set<Unstubify<V>>
116
127
  : T extends [] ? []
@@ -120,14 +131,30 @@ type UnstubifyInner<T> =
120
131
  : T extends Array<infer V> ? Array<Unstubify<V>>
121
132
  : T extends ReadonlyArray<infer V> ? ReadonlyArray<Unstubify<V>>
122
133
  : T extends BaseType ? T
123
- : T extends { [key: string | number]: unknown } ? { [K in keyof T]: Unstubify<T[K]> }
134
+ : T extends { [key: string | number]: unknown } ? { [K in keyof T as K extends string | number ? K : never]: Unstubify<T[K]> }
124
135
  : T;
125
136
 
126
137
  // You can put promises anywhere in the params and they'll be resolved before delivery.
127
138
  // (This also covers RpcPromise, because it's defined as being a Promise.)
128
- type Unstubify<T> = UnstubifyInner<T> | Promise<UnstubifyInner<T>>
139
+ // Map placeholders are also allowed so primitive map callback inputs can be forwarded directly
140
+ // into RPC params.
141
+ //
142
+ // Keep raw non-stub members so generic assignability still works when UnstubifyInner<T> is deferred.
143
+ // Remove stub members from mixed unions so callback params don’t get both stub and unstubbed signatures.
144
+ // Marker carried by map() callback inputs. This lets primitive placeholders flow through params.
145
+ type Unstubify<T> =
146
+ | NonStubMembers<T>
147
+ | UnstubifyInner<T>
148
+ | Promise<UnstubifyInner<T>>
149
+ | MapValuePlaceholder<UnstubifyInner<T>>;
150
+
151
+ type UnstubifyAll<A extends readonly unknown[]> = { [I in keyof A]: Unstubify<A[I]> };
129
152
 
130
- type UnstubifyAll<A extends any[]> = { [I in keyof A]: Unstubify<A[I]> };
153
+ interface MapValuePlaceholder<T> {
154
+ [__RPC_MAP_VALUE_BRAND]: T;
155
+ }
156
+
157
+ type NonStubMembers<T> = Exclude<T, StubBase<any>>;
131
158
 
132
159
  // Utility type for adding `Disposable`s to `object` types only.
133
160
  // Note `unknown & T` is equivalent to `T`.
@@ -142,17 +169,22 @@ type MaybeDisposable<T> = T extends object ? Disposable : unknown;
142
169
  // Intersecting with `(Maybe)Provider` allows pipelining.
143
170
  // prettier-ignore
144
171
  type Result<R> =
145
- R extends Stubable ? Promise<Stub<R>> & Provider<R> & StubBase<R>
172
+ IsAny<R> extends true ? UnknownResult
173
+ : IsUnknown<R> extends true ? UnknownResult
174
+ : R extends Stubable ? Promise<Stub<R>> & Provider<R> & StubBase<R>
146
175
  : R extends RpcCompatible<R> ? Promise<Stubify<R> & MaybeDisposable<R>> & Provider<R> & StubBase<R>
147
176
  : never;
148
177
 
178
+ type IsAny<T> = 0 extends (1 & T) ? true : false;
179
+ type UnknownResult = Promise<unknown> & Provider<unknown> & StubBase<unknown>;
180
+
149
181
  // Type for method or property on an RPC interface.
150
182
  // For methods, unwrap `Stub`s in parameters, and rewrite returns to be `Result`s.
151
183
  // Unwrapping `Stub`s allows calling with `Stubable` arguments.
152
184
  // For properties, rewrite types to be `Result`s.
153
185
  // In each case, unwrap `Promise`s.
154
186
  type MethodOrProperty<V> = V extends (...args: infer P) => infer R
155
- ? (...args: UnstubifyAll<P>) => Result<Awaited<R>>
187
+ ? (...args: UnstubifyAll<P>) => IsAny<R> extends true ? UnknownResult : Result<Awaited<R>>
156
188
  : Result<Awaited<V>>;
157
189
 
158
190
  // Type for the callable part of an `Provider` if `T` is callable.
@@ -161,22 +193,62 @@ type MaybeCallableProvider<T> = T extends (...args: any[]) => any
161
193
  ? MethodOrProperty<T>
162
194
  : unknown;
163
195
 
196
+ type TupleIndexKeys<T extends ReadonlyArray<unknown>> = Extract<keyof T, `${number}`>;
197
+ type MapCallbackValue<T> =
198
+ // `Omit` removes call signatures, so re-intersect callable provider behavior.
199
+ T extends unknown
200
+ ? Omit<Result<T>, keyof Promise<unknown>> &
201
+ MaybeCallableProvider<T> &
202
+ MapValuePlaceholder<T>
203
+ : never;
204
+ type InvalidNativePromiseInMapResult<T, Seen = never> =
205
+ T extends unknown ? InvalidNativePromiseInMapResultImpl<T, Seen> : never;
206
+ type InvalidNativePromiseInMapResultImpl<T, Seen> =
207
+ [T] extends [Seen] ? never
208
+ // RpcPromise is modeled as Promise & StubBase, so allow promise-like stub values.
209
+ : T extends StubBase<any> ? never
210
+ // Native thenables cannot be represented in map recordings, even when typed as PromiseLike.
211
+ : T extends PromiseLike<unknown> ? T
212
+ : T extends Map<infer K, infer V>
213
+ ? InvalidNativePromiseInMapResult<K, Seen | T> |
214
+ InvalidNativePromiseInMapResult<V, Seen | T>
215
+ : T extends Set<infer V> ? InvalidNativePromiseInMapResult<V, Seen | T>
216
+ : T extends readonly [] ? never
217
+ : T extends readonly [infer Head, ...infer Tail]
218
+ ? InvalidNativePromiseInMapResult<Head, Seen | T> |
219
+ InvalidNativePromiseInMapResult<Tail[number], Seen | T>
220
+ : T extends ReadonlyArray<infer V> ? InvalidNativePromiseInMapResult<V, Seen | T>
221
+ : T extends { [key: string | number]: unknown }
222
+ ? InvalidNativePromiseInMapResult<
223
+ T[Extract<keyof T, string | number>],
224
+ Seen | T
225
+ >
226
+ : never;
227
+ type MapCallbackReturn<T> =
228
+ InvalidNativePromiseInMapResult<T> extends never ? T : never;
229
+ type ArrayProvider<E> = {
230
+ [K in number]: MethodOrProperty<E>;
231
+ } & {
232
+ map<V>(callback: (elem: MapCallbackValue<E>) => MapCallbackReturn<V>): Result<Array<V>>;
233
+ };
234
+ type TupleProvider<T extends ReadonlyArray<unknown>> = {
235
+ [K in TupleIndexKeys<T>]: MethodOrProperty<T[K]>;
236
+ } & ArrayProvider<T[number]>;
237
+
164
238
  // Base type for all other types providing RPC-like interfaces.
165
239
  // Rewrites all methods/properties to be `MethodOrProperty`s, while preserving callable types.
166
240
  type Provider<T> = MaybeCallableProvider<T> &
167
- (T extends Array<infer U>
168
- ? {
169
- [key: number]: MethodOrProperty<U>;
170
- } & {
171
- map<V>(callback: (elem: U) => V): Result<Array<V>>;
172
- }
241
+ (T extends ReadonlyArray<unknown>
242
+ ? number extends T["length"] ? ArrayProvider<T[number]> : TupleProvider<T>
173
243
  : {
174
244
  [K in Exclude<
175
245
  keyof T,
176
246
  symbol | keyof StubBase<never>
177
247
  >]: MethodOrProperty<T[K]>;
178
248
  } & {
179
- map<V>(callback: (value: NonNullable<T>) => V): Result<Array<V>>;
249
+ map<V>(
250
+ callback: (value: MapCallbackValue<NonNullable<T>>) => MapCallbackReturn<V>
251
+ ): Result<Array<V>>;
180
252
  });
181
253
 
182
254
  /**
package/dist/index.js CHANGED
@@ -24,6 +24,7 @@ var RpcTarget = workersModule ? workersModule.RpcTarget : class {
24
24
  };
25
25
  var AsyncFunction = (async function() {
26
26
  }).constructor;
27
+ var BUFFER_PROTOTYPE = typeof Buffer !== "undefined" ? Buffer.prototype : void 0;
27
28
  function typeForRpc(value) {
28
29
  switch (typeof value) {
29
30
  case "boolean":
@@ -55,11 +56,18 @@ function typeForRpc(value) {
55
56
  case Date.prototype:
56
57
  return "date";
57
58
  case Uint8Array.prototype:
59
+ case BUFFER_PROTOTYPE:
58
60
  return "bytes";
59
61
  case WritableStream.prototype:
60
62
  return "writable";
61
63
  case ReadableStream.prototype:
62
64
  return "readable";
65
+ case Headers.prototype:
66
+ return "headers";
67
+ case Request.prototype:
68
+ return "request";
69
+ case Response.prototype:
70
+ return "response";
63
71
  // TODO: All other structured clone types.
64
72
  case RpcStub.prototype:
65
73
  return "stub";
@@ -613,6 +621,22 @@ var RpcPayload = class _RpcPayload {
613
621
  this.hooks.push(hook);
614
622
  return stream;
615
623
  }
624
+ case "headers":
625
+ return new Headers(value);
626
+ case "request": {
627
+ let req = value;
628
+ if (req.body) {
629
+ this.deepCopy(req.body, req, "body", req, dupStubs, owner);
630
+ }
631
+ return new Request(req);
632
+ }
633
+ case "response": {
634
+ let resp = value;
635
+ if (resp.body) {
636
+ this.deepCopy(resp.body, resp, "body", resp, dupStubs, owner);
637
+ }
638
+ return new Response(resp.body, resp);
639
+ }
616
640
  default:
617
641
  throw new Error("unreachable");
618
642
  }
@@ -792,6 +816,18 @@ var RpcPayload = class _RpcPayload {
792
816
  }
793
817
  case "rpc-thenable":
794
818
  return;
819
+ case "headers":
820
+ return;
821
+ case "request": {
822
+ let req = value;
823
+ if (req.body) this.disposeImpl(req.body, req);
824
+ return;
825
+ }
826
+ case "response": {
827
+ let resp = value;
828
+ if (resp.body) this.disposeImpl(resp.body, resp);
829
+ return;
830
+ }
795
831
  case "writable": {
796
832
  let stream = value;
797
833
  let hook = this.rpcTargets?.get(stream);
@@ -847,6 +883,9 @@ var RpcPayload = class _RpcPayload {
847
883
  case "rpc-target":
848
884
  case "writable":
849
885
  case "readable":
886
+ case "headers":
887
+ case "request":
888
+ case "response":
850
889
  return;
851
890
  case "array": {
852
891
  let array = value;
@@ -930,6 +969,9 @@ function followPath(value, parent, path, owner) {
930
969
  case "bytes":
931
970
  case "date":
932
971
  case "error":
972
+ case "headers":
973
+ case "request":
974
+ case "response":
933
975
  value = void 0;
934
976
  break;
935
977
  case "undefined":
@@ -1344,12 +1386,86 @@ var Devaluator = class _Devaluator {
1344
1386
  let bytes = value;
1345
1387
  if (bytes.toBase64) {
1346
1388
  return ["bytes", bytes.toBase64({ omitPadding: true })];
1347
- } else {
1348
- return [
1349
- "bytes",
1350
- btoa(String.fromCharCode.apply(null, bytes).replace(/=*$/, ""))
1351
- ];
1352
1389
  }
1390
+ let b64;
1391
+ if (typeof Buffer !== "undefined") {
1392
+ let buf = bytes instanceof Buffer ? bytes : Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
1393
+ b64 = buf.toString("base64");
1394
+ } else {
1395
+ let binary = "";
1396
+ for (let i = 0; i < bytes.length; i++) {
1397
+ binary += String.fromCharCode(bytes[i]);
1398
+ }
1399
+ b64 = btoa(binary);
1400
+ }
1401
+ return ["bytes", b64.replace(/=+$/, "")];
1402
+ }
1403
+ case "headers":
1404
+ return ["headers", [...value]];
1405
+ case "request": {
1406
+ let req = value;
1407
+ let init = {};
1408
+ if (req.method !== "GET") init.method = req.method;
1409
+ let headers = [...req.headers];
1410
+ if (headers.length > 0) {
1411
+ init.headers = headers;
1412
+ }
1413
+ if (req.body) {
1414
+ init.body = this.devaluateImpl(req.body, req, depth + 1);
1415
+ init.duplex = req.duplex || "half";
1416
+ } else if (req.body === void 0 && !["GET", "HEAD", "OPTIONS", "TRACE", "DELETE"].includes(req.method)) {
1417
+ let bodyPromise = req.arrayBuffer();
1418
+ let readable = new ReadableStream({
1419
+ async start(controller) {
1420
+ try {
1421
+ controller.enqueue(new Uint8Array(await bodyPromise));
1422
+ controller.close();
1423
+ } catch (err) {
1424
+ controller.error(err);
1425
+ }
1426
+ }
1427
+ });
1428
+ let hook = streamImpl.createReadableStreamHook(readable);
1429
+ let importId = this.exporter.createPipe(readable, hook);
1430
+ init.body = ["readable", importId];
1431
+ init.duplex = req.duplex || "half";
1432
+ }
1433
+ if (req.cache && req.cache !== "default") init.cache = req.cache;
1434
+ if (req.redirect !== "follow") init.redirect = req.redirect;
1435
+ if (req.integrity) init.integrity = req.integrity;
1436
+ if (req.mode && req.mode !== "cors") init.mode = req.mode;
1437
+ if (req.credentials && req.credentials !== "same-origin") {
1438
+ init.credentials = req.credentials;
1439
+ }
1440
+ if (req.referrer && req.referrer !== "about:client") init.referrer = req.referrer;
1441
+ if (req.referrerPolicy) init.referrerPolicy = req.referrerPolicy;
1442
+ if (req.keepalive) init.keepalive = req.keepalive;
1443
+ let cfReq = req;
1444
+ if (cfReq.cf) init.cf = cfReq.cf;
1445
+ if (cfReq.encodeResponseBody && cfReq.encodeResponseBody !== "automatic") {
1446
+ init.encodeResponseBody = cfReq.encodeResponseBody;
1447
+ }
1448
+ return ["request", req.url, init];
1449
+ }
1450
+ case "response": {
1451
+ let resp = value;
1452
+ let body = this.devaluateImpl(resp.body, resp, depth + 1);
1453
+ let init = {};
1454
+ if (resp.status !== 200) init.status = resp.status;
1455
+ if (resp.statusText) init.statusText = resp.statusText;
1456
+ let headers = [...resp.headers];
1457
+ if (headers.length > 0) {
1458
+ init.headers = headers;
1459
+ }
1460
+ let cfResp = resp;
1461
+ if (cfResp.cf) init.cf = cfResp.cf;
1462
+ if (cfResp.encodeBody && cfResp.encodeBody !== "automatic") {
1463
+ init.encodeBody = cfResp.encodeBody;
1464
+ }
1465
+ if (cfResp.webSocket) {
1466
+ throw new TypeError("Can't serialize a Response containing a webSocket.");
1467
+ }
1468
+ return ["response", body, init];
1353
1469
  }
1354
1470
  case "error": {
1355
1471
  let e = value;
@@ -1450,6 +1566,14 @@ var NullImporter = class {
1450
1566
  }
1451
1567
  };
1452
1568
  var NULL_IMPORTER = new NullImporter();
1569
+ function fixBrokenRequestBody(request, body) {
1570
+ let promise = new Response(body).arrayBuffer().then((arrayBuffer) => {
1571
+ let bytes = new Uint8Array(arrayBuffer);
1572
+ let result = new Request(request, { body: bytes });
1573
+ return new PayloadStubHook(RpcPayload.fromAppReturn(result));
1574
+ });
1575
+ return new RpcPromise(new PromiseStubHook(promise), []);
1576
+ }
1453
1577
  var Evaluator = class _Evaluator {
1454
1578
  constructor(importer) {
1455
1579
  this.importer = importer;
@@ -1490,10 +1614,11 @@ var Evaluator = class _Evaluator {
1490
1614
  }
1491
1615
  break;
1492
1616
  case "bytes": {
1493
- let b64 = Uint8Array;
1494
1617
  if (typeof value[1] == "string") {
1495
- if (b64.fromBase64) {
1496
- return b64.fromBase64(value[1]);
1618
+ if (typeof Buffer !== "undefined") {
1619
+ return Buffer.from(value[1], "base64");
1620
+ } else if (Uint8Array.fromBase64) {
1621
+ return Uint8Array.fromBase64(value[1]);
1497
1622
  } else {
1498
1623
  let bs = atob(value[1]);
1499
1624
  let len = bs.length;
@@ -1527,6 +1652,56 @@ var Evaluator = class _Evaluator {
1527
1652
  return -Infinity;
1528
1653
  case "nan":
1529
1654
  return NaN;
1655
+ case "headers":
1656
+ if (value.length === 2 && value[1] instanceof Array) {
1657
+ return new Headers(value[1]);
1658
+ }
1659
+ break;
1660
+ case "request": {
1661
+ if (value.length !== 3 || typeof value[1] !== "string") break;
1662
+ let url = value[1];
1663
+ let init = value[2];
1664
+ if (typeof init !== "object" || init === null) break;
1665
+ if (init.body) {
1666
+ init.body = this.evaluateImpl(init.body, init, "body");
1667
+ if (init.body === null || typeof init.body === "string" || init.body instanceof Uint8Array || init.body instanceof ReadableStream) ; else {
1668
+ throw new TypeError("Request body must be of type ReadableStream.");
1669
+ }
1670
+ }
1671
+ if (init.signal) {
1672
+ init.signal = this.evaluateImpl(init.signal, init, "signal");
1673
+ if (!(init.signal instanceof AbortSignal)) {
1674
+ throw new TypeError("Request siganl must be of type AbortSignal.");
1675
+ }
1676
+ }
1677
+ if (init.headers && !(init.headers instanceof Array)) {
1678
+ throw new TypeError("Request headers must be serialized as an array of pairs.");
1679
+ }
1680
+ let result = new Request(url, init);
1681
+ if (init.body instanceof ReadableStream && result.body === void 0) {
1682
+ let promise = fixBrokenRequestBody(result, init.body);
1683
+ this.promises.push({ promise, parent, property });
1684
+ return promise;
1685
+ } else {
1686
+ return result;
1687
+ }
1688
+ }
1689
+ case "response": {
1690
+ if (value.length !== 3) break;
1691
+ let body = this.evaluateImpl(value[1], parent, property);
1692
+ if (body === null || typeof body === "string" || body instanceof Uint8Array || body instanceof ReadableStream) ; else {
1693
+ throw new TypeError("Response body must be of type ReadableStream.");
1694
+ }
1695
+ let init = value[2];
1696
+ if (typeof init !== "object" || init === null) break;
1697
+ if (init.webSocket) {
1698
+ throw new TypeError("Can't deserialize a Response containing a webSocket.");
1699
+ }
1700
+ if (init.headers && !(init.headers instanceof Array)) {
1701
+ throw new TypeError("Request headers must be serialized as an array of pairs.");
1702
+ }
1703
+ return new Response(body, init);
1704
+ }
1530
1705
  case "import":
1531
1706
  case "pipeline": {
1532
1707
  if (value.length < 2 || value.length > 4) {