@php-wasm/universal 1.2.0 → 1.2.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/lib/api.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- import * as Comlink from 'comlink';
2
- import type { NodeEndpoint } from 'comlink/dist/esm/node-adapter';
1
+ import { type NodeEndpoint, type Remote, type IsomorphicMessagePort } from './comlink-sync';
3
2
  export type WithAPIState = {
4
3
  /**
5
4
  * Resolves to true when the remote API is ready for
@@ -12,7 +11,9 @@ export type WithAPIState = {
12
11
  */
13
12
  isReady: () => Promise<void>;
14
13
  };
15
- export type RemoteAPI<T> = Comlink.Remote<T> & WithAPIState;
14
+ export type RemoteAPI<T> = Remote<T> & WithAPIState;
15
+ export declare function consumeAPISync<APIType>(remote: IsomorphicMessagePort): Promise<APIType>;
16
16
  export declare function consumeAPI<APIType>(remote: Worker | Window | NodeEndpoint, context?: undefined | EventTarget): RemoteAPI<APIType>;
17
17
  export type PublicAPI<Methods, PipedAPI = unknown> = RemoteAPI<Methods & PipedAPI>;
18
18
  export declare function exposeAPI<Methods, PipedAPI>(apiMethods?: Methods, pipedApi?: PipedAPI, targetWorker?: NodeEndpoint): [() => void, (e: Error) => void, PublicAPI<Methods, PipedAPI>];
19
+ export declare function exposeSyncAPI<Methods>(apiMethods: Methods, port: IsomorphicMessagePort): Promise<[() => void, (e: Error) => void, Methods]>;
@@ -0,0 +1,297 @@
1
+ /// <reference types="node" />
2
+ import type { MessagePort as NodeMessagePort } from 'worker_threads';
3
+ /**
4
+ * Comlink library protocol extension to use synchronous messaging.
5
+ *
6
+ * Debugging Asyncify is too much of a burden. This extension enables exchanging
7
+ * messages between threads synchronously so that we don't need to rely on Asyncify.
8
+ *
9
+ * Upsides:
10
+ *
11
+ * * Saves dozens-to-hundreds of hours on debugging Asyncify issues
12
+ * * Increased reliability
13
+ * * Useful stack traces when errors do happen.
14
+ *
15
+ * Downsides:
16
+ *
17
+ * * Fragmentation: Both synchronous and asynchronous handlers exist to get the best our of both
18
+ * Asyncify and JSPI. * Node.js-only: This extension does not implement a Safari-friendly
19
+ * transport. SharedArrayBuffer is an option, but
20
+ * it requires more restrictive CORP+COEP headers which breaks, e.g., YouTube
21
+ * embeds. Synchronous XHR might work if we really need Safari support for one of
22
+ * the new asynchronous features, but other than that let's just skip adding new
23
+ * asynchronous WASM features to Safari until WebKit supports stack switching.
24
+ * * Message passing between workers is slow. Avoid using synchronous messaging for syscalls that
25
+ * are invoked frequently and
26
+ * handled asynchronously in the same worker.
27
+ *
28
+ * @see https://github.com/adamziel/js-synchronous-messaging for additional ideas.
29
+ * @see https://github.com/WordPress/wordpress-playground/blob/9a9262cc62cc161d220a9992706b9ed2817f2eb5/packages/docs/site/docs/developers/23-architecture/07-wasm-asyncify.md
30
+ */
31
+ interface SyncMessage {
32
+ /** original Comlink envelope */
33
+ id?: string;
34
+ type: MessageType;
35
+ /** existing Comlink fields … */
36
+ [k: string]: any;
37
+ /** new part that carries the latch */
38
+ notifyBuffer?: SharedArrayBuffer;
39
+ }
40
+ interface SyncTransport {
41
+ afterResponseSent(ev: MessageEvent): void;
42
+ send(ep: IsomorphicMessagePort, msg: Omit<SyncMessage, 'id' | 'notifyBuffer'>, transferables?: Transferable[]): WireValue;
43
+ }
44
+ export declare function exposeSync(obj: any, ep: Endpoint, transport: SyncTransport, allowedOrigins?: (string | RegExp)[]): void;
45
+ export declare function wrapSync<T>(ep: IsomorphicMessagePort, transport: SyncTransport): T;
46
+ export type IsomorphicMessagePort = MessagePort | NodeMessagePort;
47
+ export declare class NodeSABSyncReceiveMessageTransport {
48
+ private static receiveMessageOnPort;
49
+ static create(): Promise<NodeSABSyncReceiveMessageTransport>;
50
+ private constructor();
51
+ afterResponseSent(ev: MessageEvent): void;
52
+ send(ep: IsomorphicMessagePort, msg: Omit<SyncMessage, 'id' | 'notifyBuffer'>, transferables?: Transferable[]): WireValue;
53
+ }
54
+ /**
55
+ * Original, unmodified Comlink library from Google:
56
+ *
57
+ * @license
58
+ * Copyright 2019 Google LLC
59
+ * SPDX-License-Identifier: Apache-2.0
60
+ */
61
+ export declare const proxyMarker: unique symbol;
62
+ export declare const createEndpoint: unique symbol;
63
+ export declare const releaseProxy: unique symbol;
64
+ export declare const finalizer: unique symbol;
65
+ /**
66
+ * @license
67
+ * Copyright 2019 Google LLC
68
+ * SPDX-License-Identifier: Apache-2.0
69
+ */
70
+ export interface EventSource {
71
+ addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: object): void;
72
+ removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: object): void;
73
+ }
74
+ export interface PostMessageWithOrigin {
75
+ postMessage(message: any, targetOrigin: string, transfer?: Transferable[]): void;
76
+ }
77
+ export interface Endpoint extends EventSource {
78
+ postMessage(message: any, transfer?: Transferable[]): void;
79
+ start?: () => void;
80
+ }
81
+ export declare const WireValueType: {
82
+ readonly RAW: "RAW";
83
+ readonly PROXY: "PROXY";
84
+ readonly THROW: "THROW";
85
+ readonly HANDLER: "HANDLER";
86
+ };
87
+ export type WireValueType = typeof WireValueType;
88
+ export interface RawWireValue {
89
+ id?: string;
90
+ type: WireValueType['RAW'];
91
+ value: any;
92
+ }
93
+ export interface HandlerWireValue {
94
+ id?: string;
95
+ type: WireValueType['HANDLER'];
96
+ name: string;
97
+ value: unknown;
98
+ }
99
+ export type WireValue = RawWireValue | HandlerWireValue;
100
+ export type MessageID = string;
101
+ export declare const MessageType: {
102
+ readonly GET: "GET";
103
+ readonly SET: "SET";
104
+ readonly APPLY: "APPLY";
105
+ readonly CONSTRUCT: "CONSTRUCT";
106
+ readonly ENDPOINT: "ENDPOINT";
107
+ readonly RELEASE: "RELEASE";
108
+ };
109
+ export type MessageType = typeof MessageType;
110
+ export interface GetMessage {
111
+ id?: MessageID;
112
+ type: MessageType['GET'];
113
+ path: string[];
114
+ }
115
+ export interface SetMessage {
116
+ id?: MessageID;
117
+ type: MessageType['SET'];
118
+ path: string[];
119
+ value: WireValue;
120
+ }
121
+ export interface ApplyMessage {
122
+ id?: MessageID;
123
+ type: MessageType['APPLY'];
124
+ path: string[];
125
+ argumentList: WireValue[];
126
+ }
127
+ export interface ConstructMessage {
128
+ id?: MessageID;
129
+ type: MessageType['CONSTRUCT'];
130
+ path: string[];
131
+ argumentList: WireValue[];
132
+ }
133
+ export interface EndpointMessage {
134
+ id?: MessageID;
135
+ type: MessageType['ENDPOINT'];
136
+ }
137
+ export interface ReleaseMessage {
138
+ id?: MessageID;
139
+ type: MessageType['RELEASE'];
140
+ }
141
+ export type Message = GetMessage | SetMessage | ApplyMessage | ConstructMessage | EndpointMessage | ReleaseMessage;
142
+ /**
143
+ * Interface of values that were marked to be proxied with `comlink.proxy()`.
144
+ * Can also be implemented by classes.
145
+ */
146
+ export interface ProxyMarked {
147
+ [proxyMarker]: true;
148
+ }
149
+ /**
150
+ * Takes a type and wraps it in a Promise, if it not already is one.
151
+ * This is to avoid `Promise<Promise<T>>`.
152
+ *
153
+ * This is the inverse of `Unpromisify<T>`.
154
+ */
155
+ type Promisify<T> = T extends Promise<unknown> ? T : Promise<T>;
156
+ /**
157
+ * Takes a type that may be Promise and unwraps the Promise type.
158
+ * If `P` is not a Promise, it returns `P`.
159
+ *
160
+ * This is the inverse of `Promisify<T>`.
161
+ */
162
+ type Unpromisify<P> = P extends Promise<infer T> ? T : P;
163
+ /**
164
+ * Takes the raw type of a remote property and returns the type that is visible to the local thread
165
+ * on the proxy.
166
+ *
167
+ * Note: This needs to be its own type alias, otherwise it will not distribute over unions.
168
+ * See https://www.typescriptlang.org/docs/handbook/advanced-types.html#distributive-conditional-types
169
+ */
170
+ type RemoteProperty<T> = T extends Function | ProxyMarked ? Remote<T> : Promisify<T>;
171
+ /**
172
+ * Takes the raw type of a property as a remote thread would see it through a proxy (e.g. when
173
+ * passed in as a function argument) and returns the type that the local thread has to supply.
174
+ *
175
+ * This is the inverse of `RemoteProperty<T>`.
176
+ *
177
+ * Note: This needs to be its own type alias, otherwise it will not distribute over unions. See
178
+ * https://www.typescriptlang.org/docs/handbook/advanced-types.html#distributive-conditional-types
179
+ */
180
+ type LocalProperty<T> = T extends Function | ProxyMarked ? Local<T> : Unpromisify<T>;
181
+ /**
182
+ * Proxies `T` if it is a `ProxyMarked`, clones it otherwise (as handled by structured cloning and
183
+ * transfer handlers).
184
+ */
185
+ export type ProxyOrClone<T> = T extends ProxyMarked ? Remote<T> : T;
186
+ /**
187
+ * Inverse of `ProxyOrClone<T>`.
188
+ */
189
+ export type UnproxyOrClone<T> = T extends RemoteObject<ProxyMarked> ? Local<T> : T;
190
+ /**
191
+ * Takes the raw type of a remote object in the other thread and returns the type as it is visible
192
+ * to the local thread when proxied with `Comlink.proxy()`.
193
+ *
194
+ * This does not handle call signatures, which is handled by the more general `Remote<T>` type.
195
+ *
196
+ * @template T The raw type of a remote object as seen in the other thread.
197
+ */
198
+ export type RemoteObject<T> = {
199
+ [P in keyof T]: RemoteProperty<T[P]>;
200
+ };
201
+ /**
202
+ * Takes the type of an object as a remote thread would see it through a proxy (e.g. when passed in
203
+ * as a function argument) and returns the type that the local thread has to supply.
204
+ *
205
+ * This does not handle call signatures, which is handled by the more general `Local<T>` type.
206
+ *
207
+ * This is the inverse of `RemoteObject<T>`.
208
+ *
209
+ * @template T The type of a proxied object.
210
+ */
211
+ export type LocalObject<T> = {
212
+ [P in keyof T]: LocalProperty<T[P]>;
213
+ };
214
+ /**
215
+ * Additional special comlink methods available on each proxy returned by `Comlink.wrap()`.
216
+ */
217
+ export interface ProxyMethods {
218
+ [createEndpoint]: () => Promise<MessagePort>;
219
+ [releaseProxy]: () => void;
220
+ }
221
+ /**
222
+ * Takes the raw type of a remote object, function or class in the other thread and returns the
223
+ * type as it is visible to the local thread from the proxy return value of `Comlink.wrap()` or
224
+ * `Comlink.proxy()`.
225
+ */
226
+ export type Remote<T> = RemoteObject<T> & (T extends (...args: infer TArguments) => infer TReturn ? (...args: {
227
+ [I in keyof TArguments]: UnproxyOrClone<TArguments[I]>;
228
+ }) => Promisify<ProxyOrClone<Unpromisify<TReturn>>> : unknown) & (T extends {
229
+ new (...args: infer TArguments): infer TInstance;
230
+ } ? {
231
+ new (...args: {
232
+ [I in keyof TArguments]: UnproxyOrClone<TArguments[I]>;
233
+ }): Promisify<Remote<TInstance>>;
234
+ } : unknown) & ProxyMethods;
235
+ /**
236
+ * Expresses that a type can be either a sync or async.
237
+ */
238
+ type MaybePromise<T> = Promise<T> | T;
239
+ /**
240
+ * Takes the raw type of a remote object, function or class as a remote thread would see it through
241
+ * a proxy (e.g. when passed in as a function argument) and returns the type the local thread has
242
+ * to supply.
243
+ *
244
+ * This is the inverse of `Remote<T>`. It takes a `Remote<T>` and returns its original input `T`.
245
+ */
246
+ export type Local<T> = Omit<LocalObject<T>, keyof ProxyMethods> & (T extends (...args: infer TArguments) => infer TReturn ? (...args: {
247
+ [I in keyof TArguments]: ProxyOrClone<TArguments[I]>;
248
+ }) => MaybePromise<UnproxyOrClone<Unpromisify<TReturn>>> : unknown) & (T extends {
249
+ new (...args: infer TArguments): infer TInstance;
250
+ } ? {
251
+ new (...args: {
252
+ [I in keyof TArguments]: ProxyOrClone<TArguments[I]>;
253
+ }): MaybePromise<Local<Unpromisify<TInstance>>>;
254
+ } : unknown);
255
+ /**
256
+ * Customizes the serialization of certain values as determined by `canHandle()`.
257
+ *
258
+ * @template T The input type being handled by this transfer handler.
259
+ * @template S The serialized type sent over the wire.
260
+ */
261
+ export interface TransferHandler<T, S> {
262
+ /**
263
+ * Gets called for every value to determine whether this transfer handler
264
+ * should serialize the value, which includes checking that it is of the right
265
+ * type (but can perform checks beyond that as well).
266
+ */
267
+ canHandle(value: unknown): value is T;
268
+ /**
269
+ * Gets called with the value if `canHandle()` returned `true` to produce a
270
+ * value that can be sent in a message, consisting of structured-cloneable
271
+ * values and/or transferrable objects.
272
+ */
273
+ serialize(value: T): [S, Transferable[]];
274
+ /**
275
+ * Gets called to deserialize an incoming value that was serialized in the
276
+ * other thread with this transfer handler (known through the name it was
277
+ * registered under).
278
+ */
279
+ deserialize(value: S): T;
280
+ }
281
+ /**
282
+ * Allows customizing the serialization of certain values.
283
+ */
284
+ export declare const transferHandlers: Map<string, TransferHandler<unknown, unknown>>;
285
+ export declare function expose(obj: any, ep?: Endpoint, allowedOrigins?: (string | RegExp)[], afterResponseSent?: (ev: MessageEvent) => void): void;
286
+ export declare function wrap<T>(ep: Endpoint, target?: any): Remote<T>;
287
+ export declare function transfer<T>(obj: T, transfers: Transferable[]): T;
288
+ export declare function proxy<T extends object>(obj: T): T & ProxyMarked;
289
+ export declare function windowEndpoint(w: PostMessageWithOrigin, context?: EventSource, targetOrigin?: string): Endpoint;
290
+ export interface NodeEndpoint {
291
+ postMessage(message: any, transfer?: any[]): void;
292
+ on(type: string, listener: EventListenerOrEventListenerObject, options?: object): void;
293
+ off(type: string, listener: EventListenerOrEventListenerObject, options?: object): void;
294
+ start?: () => void;
295
+ }
296
+ export declare function nodeEndpoint(nep: NodeEndpoint): Endpoint;
297
+ export {};
@@ -5,5 +5,5 @@
5
5
  * @returns True if the error appears to represent an exit code or status
6
6
  */
7
7
  export declare function isExitCode(e: any): e is {
8
- exitCode: number;
8
+ status: number;
9
9
  };
@@ -1,4 +1,4 @@
1
- import type { Remote } from 'comlink';
1
+ import type { Remote } from './comlink-sync';
2
2
  import type { LimitedPHPApi } from './php-worker';
3
3
  /**
4
4
  * Represents an event related to the PHP request.
@@ -38,13 +38,17 @@ export type PHPEvent = PHPRequestEndEvent | PHPRequestErrorEvent | PHPRuntimeIni
38
38
  export type PHPEventListener = (event: PHPEvent) => void;
39
39
  export type UniversalPHP = LimitedPHPApi | Remote<LimitedPHPApi>;
40
40
  export type MessageListener = (data: string) => Promise<string | Uint8Array | void> | string | void;
41
- interface EventEmitter {
41
+ export interface EventEmitter {
42
42
  on(event: string, listener: (...args: any[]) => void): this;
43
43
  emit(event: string, ...args: any[]): boolean;
44
44
  }
45
- type ChildProcess = EventEmitter & {
45
+ export type ChildProcess = EventEmitter & {
46
46
  stdout: EventEmitter;
47
47
  stderr: EventEmitter;
48
+ stdin: EventEmitter & {
49
+ write: (data: Uint8Array, encoding: string, cb: (err: Error | null) => void) => void;
50
+ end: () => void;
51
+ };
48
52
  };
49
53
  export type SpawnHandler = (command: string, args: string[]) => ChildProcess;
50
54
  export type HTTPMethod = 'GET' | 'POST' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'PUT' | 'DELETE';
@@ -118,4 +122,3 @@ export interface PHPOutput {
118
122
  /** Stderr lines */
119
123
  stderr: string[];
120
124
  }
121
- export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@php-wasm/universal",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "PHP.wasm – emscripten bindings for PHP",
5
5
  "repository": {
6
6
  "type": "git",
@@ -37,19 +37,18 @@
37
37
  "module": "./index.js",
38
38
  "types": "index.d.ts",
39
39
  "license": "GPL-2.0-or-later",
40
- "gitHead": "b16d08b0c59d561eb392069ca9208515b9925401",
40
+ "gitHead": "aca5a878610532b47b07a5922fb6056993df0642",
41
41
  "engines": {
42
42
  "node": ">=20.18.3",
43
43
  "npm": ">=10.1.0"
44
44
  },
45
45
  "dependencies": {
46
- "comlink": "^4.4.2",
47
46
  "ini": "4.1.2",
48
- "@php-wasm/node-polyfills": "1.2.0",
49
- "@php-wasm/logger": "1.2.0",
50
- "@php-wasm/util": "1.2.0",
51
- "@php-wasm/stream-compression": "1.2.0",
52
- "@php-wasm/progress": "1.2.0"
47
+ "@php-wasm/node-polyfills": "1.2.2",
48
+ "@php-wasm/logger": "1.2.2",
49
+ "@php-wasm/util": "1.2.2",
50
+ "@php-wasm/stream-compression": "1.2.2",
51
+ "@php-wasm/progress": "1.2.2"
53
52
  },
54
53
  "overrides": {
55
54
  "rollup": "^4.34.6",