@php-wasm/web 0.7.20 → 0.9.10

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 (39) hide show
  1. package/index.d.ts +790 -532
  2. package/index.js +799 -1289
  3. package/kitchen-sink/7_0_33/php_7_0.wasm +0 -0
  4. package/kitchen-sink/7_1_30/php_7_1.wasm +0 -0
  5. package/kitchen-sink/7_2_34/php_7_2.wasm +0 -0
  6. package/kitchen-sink/7_3_33/php_7_3.wasm +0 -0
  7. package/kitchen-sink/7_4_33/php_7_4.wasm +0 -0
  8. package/kitchen-sink/8_0_30/php_8_0.wasm +0 -0
  9. package/kitchen-sink/8_1_23/php_8_1.wasm +0 -0
  10. package/kitchen-sink/8_2_10/php_8_2.wasm +0 -0
  11. package/kitchen-sink/8_3_0/php_8_3.wasm +0 -0
  12. package/kitchen-sink/php_7_0.js +5 -5
  13. package/kitchen-sink/php_7_1.js +5 -5
  14. package/kitchen-sink/php_7_2.js +5 -5
  15. package/kitchen-sink/php_7_3.js +5 -5
  16. package/kitchen-sink/php_7_4.js +5 -5
  17. package/kitchen-sink/php_8_0.js +5 -5
  18. package/kitchen-sink/php_8_1.js +5 -5
  19. package/kitchen-sink/php_8_2.js +5 -5
  20. package/kitchen-sink/php_8_3.js +5 -5
  21. package/light/7_0_33/php_7_0.wasm +0 -0
  22. package/light/7_1_30/php_7_1.wasm +0 -0
  23. package/light/7_2_34/php_7_2.wasm +0 -0
  24. package/light/7_3_33/php_7_3.wasm +0 -0
  25. package/light/7_4_33/php_7_4.wasm +0 -0
  26. package/light/8_0_30/php_8_0.wasm +0 -0
  27. package/light/8_1_23/php_8_1.wasm +0 -0
  28. package/light/8_2_10/php_8_2.wasm +0 -0
  29. package/light/8_3_0/php_8_3.wasm +0 -0
  30. package/light/php_7_0.js +5 -5
  31. package/light/php_7_1.js +5 -5
  32. package/light/php_7_2.js +5 -5
  33. package/light/php_7_3.js +5 -5
  34. package/light/php_7_4.js +5 -5
  35. package/light/php_8_0.js +5 -5
  36. package/light/php_8_1.js +5 -5
  37. package/light/php_8_2.js +5 -5
  38. package/light/php_8_3.js +5 -5
  39. package/package.json +10 -6
package/index.d.ts CHANGED
@@ -23,6 +23,11 @@ export declare function exposeAPI<Methods, PipedAPI>(apiMethods?: Methods, piped
23
23
  (e: Error) => void,
24
24
  PublicAPI<Methods, PipedAPI>
25
25
  ];
26
+ declare class EmscriptenDownloadMonitor extends EventTarget {
27
+ #private;
28
+ expectAssets(assets: Record<string, number>): void;
29
+ monitorFetch(fetchPromise: Promise<Response>): Promise<Response>;
30
+ }
26
31
  export interface PHPResponseData {
27
32
  /**
28
33
  * Response headers.
@@ -71,405 +76,410 @@ declare class PHPResponse implements PHPResponseData {
71
76
  */
72
77
  get text(): string;
73
78
  }
74
- /**
75
- * Represents an event related to the PHP request.
76
- */
77
- export interface PHPRequestEndEvent {
78
- type: "request.end";
79
- }
80
- /**
81
- * Represents an error event related to the PHP request.
82
- */
83
- export interface PHPRequestErrorEvent {
84
- type: "request.error";
85
- error: Error;
86
- source?: "request" | "php-wasm";
87
- }
88
- /**
89
- * Represents a PHP runtime initialization event.
90
- */
91
- export interface PHPRuntimeInitializedEvent {
92
- type: "runtime.initialized";
93
- }
94
- /**
95
- * Represents a PHP runtime destruction event.
96
- */
97
- export interface PHPRuntimeBeforeDestroyEvent {
98
- type: "runtime.beforedestroy";
99
- }
100
- /**
101
- * Represents an event related to the PHP instance.
102
- * This is intentionally not an extension of CustomEvent
103
- * to make it isomorphic between different JavaScript runtimes.
104
- */
105
- export type PHPEvent = PHPRequestEndEvent | PHPRequestErrorEvent | PHPRuntimeInitializedEvent | PHPRuntimeBeforeDestroyEvent;
106
- /**
107
- * A callback function that handles PHP events.
108
- */
109
- export type PHPEventListener = (event: PHPEvent) => void;
110
- export interface IsomorphicLocalPHP {
111
- /** @deprecated Use PHPRequestHandler instead. */
112
- request(request: PHPRequest): Promise<PHPResponse>;
113
- /** @deprecated Use PHPRequestHandler instead. */
114
- pathToInternalUrl(path: string): string;
115
- /** @deprecated Use PHPRequestHandler instead. */
116
- internalUrlToPath(internalUrl: string): string;
117
- /** @deprecated Use PHPRequestHandler instead. */
118
- absoluteUrl: string;
119
- /** @deprecated Use PHPRequestHandler instead. */
120
- documentRoot: string;
121
- /**
122
- * Sets the SAPI name exposed by the PHP module.
123
- * @param newName - The new SAPI name.
124
- */
125
- setSapiName(newName: string): void;
126
- /**
127
- * Defines a constant in the PHP runtime.
128
- * @param key - The name of the constant.
129
- * @param value - The value of the constant.
130
- */
131
- defineConstant(key: string, value: boolean | string | number | null): void;
132
- /**
133
- * Adds an event listener for a PHP event.
134
- * @param eventType - The type of event to listen for.
135
- * @param listener - The listener function to be called when the event is triggered.
136
- */
137
- addEventListener(eventType: PHPEvent["type"], listener: PHPEventListener): void;
138
- /**
139
- * Removes an event listener for a PHP event.
140
- * @param eventType - The type of event to remove the listener from.
141
- * @param listener - The listener function to be removed.
142
- */
143
- removeEventListener(eventType: PHPEvent["type"], listener: PHPEventListener): void;
144
- /**
145
- * Recursively creates a directory with the given path in the PHP filesystem.
146
- * For example, if the path is `/root/php/data`, and `/root` already exists,
147
- * it will create the directories `/root/php` and `/root/php/data`.
148
- *
149
- * @param path - The directory path to create.
150
- */
151
- mkdir(path: string): void;
152
- /**
153
- * @deprecated Use mkdir instead.
154
- */
155
- mkdirTree(path: string): void;
156
- /**
157
- * Reads a file from the PHP filesystem and returns it as a string.
158
- *
159
- * @throws {@link @php-wasm/universal:ErrnoError} – If the file doesn't exist.
160
- * @param path - The file path to read.
161
- * @returns The file contents.
162
- */
163
- readFileAsText(path: string): string;
164
- /**
165
- * Reads a file from the PHP filesystem and returns it as an array buffer.
166
- *
167
- * @throws {@link @php-wasm/universal:ErrnoError} – If the file doesn't exist.
168
- * @param path - The file path to read.
169
- * @returns The file contents.
170
- */
171
- readFileAsBuffer(path: string): Uint8Array;
172
- /**
173
- * Overwrites data in a file in the PHP filesystem.
174
- * Creates a new file if one doesn't exist yet.
175
- *
176
- * @param path - The file path to write to.
177
- * @param data - The data to write to the file.
178
- */
179
- writeFile(path: string, data: string | Uint8Array): void;
180
- /**
181
- * Removes a file from the PHP filesystem.
182
- *
183
- * @throws {@link @php-wasm/universal:ErrnoError} – If the file doesn't exist.
184
- * @param path - The file path to remove.
185
- */
186
- unlink(path: string): void;
187
- /**
188
- * Moves a file or directory in the PHP filesystem to a
189
- * new location.
190
- *
191
- * @param oldPath The path to rename.
192
- * @param newPath The new path.
193
- */
194
- mv(oldPath: string, newPath: string): void;
195
- /**
196
- * Removes a directory from the PHP filesystem.
197
- *
198
- * @param path The directory path to remove.
199
- * @param options Options for the removal.
200
- */
201
- rmdir(path: string, options?: RmDirOptions): void;
79
+ export type PHPRuntimeId = number;
80
+ export type PHPRuntime = any;
81
+ export type PHPLoaderModule = {
82
+ dependencyFilename: string;
83
+ dependenciesTotalSize: number;
84
+ init: (jsRuntime: string, options: EmscriptenOptions) => PHPRuntime;
85
+ };
86
+ export type EmscriptenOptions = {
87
+ onAbort?: (message: string) => void;
202
88
  /**
203
- * Lists the files and directories in the given directory.
204
- *
205
- * @param path - The directory path to list.
206
- * @param options - Options for the listing.
207
- * @returns The list of files and directories in the given directory.
89
+ * Set to true for debugging tricky WebAssembly errors.
208
90
  */
209
- listFiles(path: string, options?: ListFilesOptions): string[];
210
- /**
211
- * Checks if a directory exists in the PHP filesystem.
91
+ debug?: boolean;
92
+ ENV?: Record<string, string>;
93
+ locateFile?: (path: string) => string;
94
+ noInitialRun?: boolean;
95
+ print?: (message: string) => void;
96
+ printErr?: (message: string) => void;
97
+ quit?: (status: number, toThrow: any) => void;
98
+ onRuntimeInitialized?: () => void;
99
+ monitorRunDependencies?: (left: number) => void;
100
+ onMessage?: (listener: EmscriptenMessageListener) => void;
101
+ instantiateWasm?: (info: WebAssembly.Imports, receiveInstance: (instance: WebAssembly.Instance, module: WebAssembly.Module) => void) => void;
102
+ } & Record<string, any>;
103
+ export type EmscriptenMessageListener = (type: string, data: string) => void;
104
+ /** Other WebAssembly declarations, for compatibility with older versions of Typescript */
105
+ export declare namespace Emscripten {
106
+ export interface RootFS extends Emscripten.FileSystemInstance {
107
+ filesystems: Record<string, Emscripten.FileSystemType>;
108
+ }
109
+ export interface FileSystemType {
110
+ mount(mount: FS.Mount): FS.FSNode;
111
+ syncfs(mount: FS.Mount, populate: () => unknown, done: (err?: number | null) => unknown): void;
112
+ }
113
+ export type EnvironmentType = "WEB" | "NODE" | "SHELL" | "WORKER";
114
+ export type JSType = "number" | "string" | "array" | "boolean";
115
+ export type TypeCompatibleWithC = number | string | any[] | boolean;
116
+ export type CIntType = "i8" | "i16" | "i32" | "i64";
117
+ export type CFloatType = "float" | "double";
118
+ export type CPointerType = "i8*" | "i16*" | "i32*" | "i64*" | "float*" | "double*" | "*";
119
+ export type CType = CIntType | CFloatType | CPointerType;
120
+ export interface CCallOpts {
121
+ async?: boolean | undefined;
122
+ }
123
+ type NamespaceToInstance<T> = {
124
+ [K in keyof T]: T[K] extends (...args: any[]) => any ? T[K] : never;
125
+ };
126
+ export type FileSystemInstance = NamespaceToInstance<typeof FS> & {
127
+ mkdirTree(path: string): void;
128
+ lookupPath(path: string, opts?: any): FS.Lookup;
129
+ };
130
+ export interface EmscriptenModule {
131
+ print(str: string): void;
132
+ printErr(str: string): void;
133
+ arguments: string[];
134
+ environment: Emscripten.EnvironmentType;
135
+ preInit: Array<{
136
+ (): void;
137
+ }>;
138
+ preRun: Array<{
139
+ (): void;
140
+ }>;
141
+ postRun: Array<{
142
+ (): void;
143
+ }>;
144
+ onAbort: {
145
+ (what: any): void;
146
+ };
147
+ onRuntimeInitialized: {
148
+ (): void;
149
+ };
150
+ preinitializedWebGLContext: WebGLRenderingContext;
151
+ noInitialRun: boolean;
152
+ noExitRuntime: boolean;
153
+ logReadFiles: boolean;
154
+ filePackagePrefixURL: string;
155
+ wasmBinary: ArrayBuffer;
156
+ destroy(object: object): void;
157
+ getPreloadedPackage(remotePackageName: string, remotePackageSize: number): ArrayBuffer;
158
+ instantiateWasm(imports: WebAssembly.Imports, successCallback: (module: WebAssembly.Instance) => void): WebAssembly.Exports | undefined;
159
+ locateFile(url: string, scriptDirectory: string): string;
160
+ onCustomMessage(event: MessageEvent): void;
161
+ HEAP: Int32Array;
162
+ IHEAP: Int32Array;
163
+ FHEAP: Float64Array;
164
+ HEAP8: Int8Array;
165
+ HEAP16: Int16Array;
166
+ HEAP32: Int32Array;
167
+ HEAPU8: Uint8Array;
168
+ HEAPU16: Uint16Array;
169
+ HEAPU32: Uint32Array;
170
+ HEAPF32: Float32Array;
171
+ HEAPF64: Float64Array;
172
+ HEAP64: BigInt64Array;
173
+ HEAPU64: BigUint64Array;
174
+ TOTAL_STACK: number;
175
+ TOTAL_MEMORY: number;
176
+ FAST_MEMORY: number;
177
+ addOnPreRun(cb: () => any): void;
178
+ addOnInit(cb: () => any): void;
179
+ addOnPreMain(cb: () => any): void;
180
+ addOnExit(cb: () => any): void;
181
+ addOnPostRun(cb: () => any): void;
182
+ preloadedImages: any;
183
+ preloadedAudios: any;
184
+ _malloc(size: number): number;
185
+ _free(ptr: number): void;
186
+ }
187
+ /**
188
+ * A factory function is generated when setting the `MODULARIZE` build option
189
+ * to `1` in your Emscripten build. It return a Promise that resolves to an
190
+ * initialized, ready-to-call `EmscriptenModule` instance.
212
191
  *
213
- * @param path The path to check.
214
- * @returns True if the path is a directory, false otherwise.
215
- */
216
- isDir(path: string): boolean;
192
+ * By default, the factory function will be named `Module`. It's recommended to
193
+ * use the `EXPORT_ES6` option, in which the factory function will be the
194
+ * default export. If used without `EXPORT_ES6`, the factory function will be a
195
+ * global variable. You can rename the variable using the `EXPORT_NAME` build
196
+ * option. It's left to you to export any global variables as needed in your
197
+ * application's types.
198
+ * @param moduleOverrides Default properties for the initialized module.
199
+ */
200
+ export type EmscriptenModuleFactory<T extends EmscriptenModule = EmscriptenModule> = (moduleOverrides?: Partial<T>) => Promise<T>;
201
+ export namespace FS {
202
+ interface Lookup {
203
+ path: string;
204
+ node: FSNode;
205
+ }
206
+ interface Analyze {
207
+ isRoot: boolean;
208
+ exists: boolean;
209
+ error: Error;
210
+ name: string;
211
+ path: Lookup["path"];
212
+ object: Lookup["node"];
213
+ parentExists: boolean;
214
+ parentPath: Lookup["path"];
215
+ parentObject: Lookup["node"];
216
+ }
217
+ interface Mount {
218
+ type: Emscripten.FileSystemType;
219
+ opts: object;
220
+ mountpoint: string;
221
+ mounts: Mount[];
222
+ root: FSNode;
223
+ }
224
+ class FSStream {
225
+ constructor();
226
+ object: FSNode;
227
+ readonly isRead: boolean;
228
+ readonly isWrite: boolean;
229
+ readonly isAppend: boolean;
230
+ flags: number;
231
+ position: number;
232
+ }
233
+ class FSNode {
234
+ parent: FSNode;
235
+ mount: Mount;
236
+ mounted?: Mount;
237
+ id: number;
238
+ name: string;
239
+ mode: number;
240
+ rdev: number;
241
+ readMode: number;
242
+ writeMode: number;
243
+ constructor(parent: FSNode, name: string, mode: number, rdev: number);
244
+ read: boolean;
245
+ write: boolean;
246
+ readonly isFolder: boolean;
247
+ readonly isDevice: boolean;
248
+ }
249
+ interface ErrnoError extends Error {
250
+ name: "ErronoError";
251
+ errno: number;
252
+ code: string;
253
+ }
254
+ function lookupPath(path: string, opts: any): Lookup;
255
+ function getPath(node: FSNode): string;
256
+ function analyzePath(path: string, dontResolveLastLink?: boolean): Analyze;
257
+ function isFile(mode: number): boolean;
258
+ function isDir(mode: number): boolean;
259
+ function isLink(mode: number): boolean;
260
+ function isChrdev(mode: number): boolean;
261
+ function isBlkdev(mode: number): boolean;
262
+ function isFIFO(mode: number): boolean;
263
+ function isSocket(mode: number): boolean;
264
+ function major(dev: number): number;
265
+ function minor(dev: number): number;
266
+ function makedev(ma: number, mi: number): number;
267
+ function registerDevice(dev: number, ops: any): void;
268
+ function syncfs(populate: boolean, callback: (e: any) => any): void;
269
+ function syncfs(callback: (e: any) => any, populate?: boolean): void;
270
+ function mount(type: Emscripten.FileSystemType, opts: any, mountpoint: string): any;
271
+ function unmount(mountpoint: string): void;
272
+ function mkdir(path: string, mode?: number): any;
273
+ function mkdev(path: string, mode?: number, dev?: number): any;
274
+ function symlink(oldpath: string, newpath: string): any;
275
+ function rename(old_path: string, new_path: string): void;
276
+ function rmdir(path: string): void;
277
+ function readdir(path: string): any;
278
+ function unlink(path: string): void;
279
+ function readlink(path: string): string;
280
+ function stat(path: string, dontFollow?: boolean): any;
281
+ function lstat(path: string): any;
282
+ function chmod(path: string, mode: number, dontFollow?: boolean): void;
283
+ function lchmod(path: string, mode: number): void;
284
+ function fchmod(fd: number, mode: number): void;
285
+ function chown(path: string, uid: number, gid: number, dontFollow?: boolean): void;
286
+ function lchown(path: string, uid: number, gid: number): void;
287
+ function fchown(fd: number, uid: number, gid: number): void;
288
+ function truncate(path: string, len: number): void;
289
+ function ftruncate(fd: number, len: number): void;
290
+ function utime(path: string, atime: number, mtime: number): void;
291
+ function open(path: string, flags: string, mode?: number, fd_start?: number, fd_end?: number): FSStream;
292
+ function close(stream: FSStream): void;
293
+ function llseek(stream: FSStream, offset: number, whence: number): any;
294
+ function read(stream: FSStream, buffer: ArrayBufferView, offset: number, length: number, position?: number): number;
295
+ function write(stream: FSStream, buffer: ArrayBufferView, offset: number, length: number, position?: number, canOwn?: boolean): number;
296
+ function allocate(stream: FSStream, offset: number, length: number): void;
297
+ function mmap(stream: FSStream, buffer: ArrayBufferView, offset: number, length: number, position: number, prot: number, flags: number): any;
298
+ function ioctl(stream: FSStream, cmd: any, arg: any): any;
299
+ function readFile(path: string, opts: {
300
+ encoding: "binary";
301
+ flags?: string | undefined;
302
+ }): Uint8Array;
303
+ function readFile(path: string, opts: {
304
+ encoding: "utf8";
305
+ flags?: string | undefined;
306
+ }): string;
307
+ function readFile(path: string, opts?: {
308
+ flags?: string | undefined;
309
+ }): Uint8Array;
310
+ function writeFile(path: string, data: string | ArrayBufferView, opts?: {
311
+ flags?: string | undefined;
312
+ }): void;
313
+ function cwd(): string;
314
+ function chdir(path: string): void;
315
+ function init(input: null | (() => number | null), output: null | ((c: number) => any), error: null | ((c: number) => any)): void;
316
+ function createLazyFile(parent: string | FSNode, name: string, url: string, canRead: boolean, canWrite: boolean): FSNode;
317
+ function createPreloadedFile(parent: string | FSNode, name: string, url: string, canRead: boolean, canWrite: boolean, onload?: () => void, onerror?: () => void, dontCreateFile?: boolean, canOwn?: boolean): void;
318
+ function createDataFile(parent: string | FSNode, name: string, data: ArrayBufferView, canRead: boolean, canWrite: boolean, canOwn: boolean): FSNode;
319
+ }
320
+ export const MEMFS: Emscripten.FileSystemType;
321
+ export const NODEFS: Emscripten.FileSystemType;
322
+ export const IDBFS: Emscripten.FileSystemType;
323
+ type StringToType<R> = R extends Emscripten.JSType ? {
324
+ number: number;
325
+ string: string;
326
+ array: number[] | string[] | boolean[] | Uint8Array | Int8Array;
327
+ boolean: boolean;
328
+ null: null;
329
+ }[R] : never;
330
+ type ArgsToType<T extends Array<Emscripten.JSType | null>> = Extract<{
331
+ [P in keyof T]: StringToType<T[P]>;
332
+ }, any[]>;
333
+ type ReturnToType<R extends Emscripten.JSType | null> = R extends null ? null : StringToType<Exclude<R, null>>;
334
+ export function cwrap<I extends Array<Emscripten.JSType | null> | [
335
+ ], R extends Emscripten.JSType | null>(ident: string, returnType: R, argTypes: I, opts?: Emscripten.CCallOpts): (...arg: ArgsToType<I>) => ReturnToType<R>;
336
+ export function ccall<I extends Array<Emscripten.JSType | null> | [
337
+ ], R extends Emscripten.JSType | null>(ident: string, returnType: R, argTypes: I, args: ArgsToType<I>, opts?: Emscripten.CCallOpts): ReturnToType<R>;
338
+ export function setValue(ptr: number, value: any, type: Emscripten.CType, noSafe?: boolean): void;
339
+ export function getValue(ptr: number, type: Emscripten.CType, noSafe?: boolean): number;
340
+ export function allocate(slab: number[] | ArrayBufferView | number, types: Emscripten.CType | Emscripten.CType[], allocator: number, ptr?: number): number;
341
+ export function stackAlloc(size: number): number;
342
+ export function stackSave(): number;
343
+ export function stackRestore(ptr: number): void;
344
+ export function UTF8ToString(ptr: number, maxBytesToRead?: number): string;
345
+ export function stringToUTF8(str: string, outPtr: number, maxBytesToRead?: number): void;
346
+ export function lengthBytesUTF8(str: string): number;
347
+ export function allocateUTF8(str: string): number;
348
+ export function allocateUTF8OnStack(str: string): number;
349
+ export function UTF16ToString(ptr: number): string;
350
+ export function stringToUTF16(str: string, outPtr: number, maxBytesToRead?: number): void;
351
+ export function lengthBytesUTF16(str: string): number;
352
+ export function UTF32ToString(ptr: number): string;
353
+ export function stringToUTF32(str: string, outPtr: number, maxBytesToRead?: number): void;
354
+ export function lengthBytesUTF32(str: string): number;
355
+ export function intArrayFromString(stringy: string, dontAddNull?: boolean, length?: number): number[];
356
+ export function intArrayToString(array: number[]): string;
357
+ export function writeStringToMemory(str: string, buffer: number, dontAddNull: boolean): void;
358
+ export function writeArrayToMemory(array: number[], buffer: number): void;
359
+ export function writeAsciiToMemory(str: string, buffer: number, dontAddNull: boolean): void;
360
+ export function addRunDependency(id: any): void;
361
+ export function removeRunDependency(id: any): void;
362
+ export function addFunction(func: (...args: any[]) => any, signature?: string): number;
363
+ export function removeFunction(funcPtr: number): void;
364
+ export const ALLOC_NORMAL: number;
365
+ export const ALLOC_STACK: number;
366
+ export const ALLOC_STATIC: number;
367
+ export const ALLOC_DYNAMIC: number;
368
+ export const ALLOC_NONE: number;
369
+ export {};
370
+ }
371
+ export interface RmDirOptions {
217
372
  /**
218
- * Checks if a file (or a directory) exists in the PHP filesystem.
219
- *
220
- * @param path - The file path to check.
221
- * @returns True if the file exists, false otherwise.
373
+ * If true, recursively removes the directory and all its contents.
374
+ * Default: true.
222
375
  */
223
- fileExists(path: string): boolean;
376
+ recursive?: boolean;
377
+ }
378
+ export interface ListFilesOptions {
224
379
  /**
225
- * Changes the current working directory in the PHP filesystem.
226
- * This is the directory that will be used as the base for relative paths.
227
- * For example, if the current working directory is `/root/php`, and the
228
- * path is `data`, the absolute path will be `/root/php/data`.
229
- *
230
- * @param path - The new working directory.
380
+ * If true, prepend given folder path to all file names.
381
+ * Default: false.
231
382
  */
232
- chdir(path: string): void;
383
+ prependPath: boolean;
384
+ }
385
+ export interface SemaphoreOptions {
233
386
  /**
234
- * Runs PHP code.
235
- *
236
- * This low-level method directly interacts with the WebAssembly
237
- * PHP interpreter.
238
- *
239
- * Every time you call run(), it prepares the PHP
240
- * environment and:
241
- *
242
- * * Resets the internal PHP state
243
- * * Populates superglobals ($_SERVER, $_GET, etc.)
244
- * * Handles file uploads
245
- * * Populates input streams (stdin, argv, etc.)
246
- * * Sets the current working directory
247
- *
248
- * You can use run() in two primary modes:
249
- *
250
- * ### Code snippet mode
251
- *
252
- * In this mode, you pass a string containing PHP code to run.
253
- *
254
- * ```ts
255
- * const result = await php.run({
256
- * code: `<?php echo "Hello world!";`
257
- * });
258
- * // result.text === "Hello world!"
259
- * ```
260
- *
261
- * In this mode, information like __DIR__ or __FILE__ isn't very
262
- * useful because the code is not associated with any file.
263
- *
264
- * Under the hood, the PHP snippet is passed to the `zend_eval_string`
265
- * C function.
266
- *
267
- * ### File mode
268
- *
269
- * In the file mode, you pass a scriptPath and PHP executes a file
270
- * found at a that path:
271
- *
272
- * ```ts
273
- * php.writeFile(
274
- * "/www/index.php",
275
- * `<?php echo "Hello world!";"`
276
- * );
277
- * const result = await php.run({
278
- * scriptPath: "/www/index.php"
279
- * });
280
- * // result.text === "Hello world!"
281
- * ```
282
- *
283
- * In this mode, you can rely on path-related information like __DIR__
284
- * or __FILE__.
285
- *
286
- * Under the hood, the PHP file is executed with the `php_execute_script`
287
- * C function.
288
- *
289
- * The `run()` method cannot be used in conjunction with `cli()`.
290
- *
291
- * @example
292
- * ```js
293
- * const result = await php.run(`<?php
294
- * $fp = fopen('php://stderr', 'w');
295
- * fwrite($fp, "Hello, world!");
296
- * `);
297
- * // result.errors === "Hello, world!"
298
- * ```
299
- *
300
- * @param options - PHP runtime options.
387
+ * The maximum number of concurrent locks.
301
388
  */
302
- run(options: PHPRunOptions): Promise<PHPResponse>;
389
+ concurrency: number;
303
390
  /**
304
- * Listens to message sent by the PHP code.
305
- *
306
- * To dispatch messages, call:
307
- *
308
- * post_message_to_js(string $data)
309
- *
310
- * Arguments:
311
- * $data (string) – Data to pass to JavaScript.
312
- *
313
- * @example
314
- *
315
- * ```ts
316
- * const php = await PHP.load('8.0');
317
- *
318
- * php.onMessage(
319
- * // The data is always passed as a string
320
- * function (data: string) {
321
- * // Let's decode and log the data:
322
- * console.log(JSON.parse(data));
323
- * }
324
- * );
325
- *
326
- * // Now that we have a listener in place, let's
327
- * // dispatch a message:
328
- * await php.run({
329
- * code: `<?php
330
- * post_message_to_js(
331
- * json_encode([
332
- * 'post_id' => '15',
333
- * 'post_title' => 'This is a blog post!'
334
- * ])
335
- * ));
336
- * `,
337
- * });
338
- * ```
339
- *
340
- * @param listener Callback function to handle the message.
391
+ * The maximum time to wait for a lock to become available.
341
392
  */
342
- onMessage(listener: MessageListener): void;
393
+ timeout?: number;
343
394
  }
344
- export type MessageListener = (data: string) => Promise<string | Uint8Array | void> | string | void;
345
- export interface EventEmitter {
346
- on(event: string, listener: (...args: any[]) => void): this;
347
- emit(event: string, ...args: any[]): boolean;
395
+ declare class Semaphore {
396
+ private _running;
397
+ private concurrency;
398
+ private timeout?;
399
+ private queue;
400
+ constructor({ concurrency, timeout }: SemaphoreOptions);
401
+ get remaining(): number;
402
+ get running(): number;
403
+ acquire(): Promise<() => void>;
404
+ run<T>(fn: () => T | Promise<T>): Promise<T>;
348
405
  }
349
- export type ChildProcess = EventEmitter & {
350
- stdout: EventEmitter;
351
- stderr: EventEmitter;
406
+ export type PHPFactoryOptions = {
407
+ isPrimary: boolean;
352
408
  };
353
- export type SpawnHandler = (command: string, args: string[]) => ChildProcess;
354
- export type HTTPMethod = "GET" | "POST" | "HEAD" | "OPTIONS" | "PATCH" | "PUT" | "DELETE";
355
- export type PHPRequestHeaders = Record<string, string>;
356
- export interface PHPRequest {
409
+ export type PHPFactory = (options: PHPFactoryOptions) => Promise<PHP>;
410
+ export interface ProcessManagerOptions {
357
411
  /**
358
- * Request method. Default: `GET`.
412
+ * The maximum number of PHP instances that can exist at
413
+ * the same time.
359
414
  */
360
- method?: HTTPMethod;
415
+ maxPhpInstances?: number;
361
416
  /**
362
- * Request path or absolute URL.
417
+ * The number of milliseconds to wait for a PHP instance when
418
+ * we have reached the maximum number of PHP instances and
419
+ * cannot spawn a new one. If the timeout is reached, we assume
420
+ * all the PHP instances are deadlocked and a throw MaxPhpInstancesError.
421
+ *
422
+ * Default: 5000
363
423
  */
364
- url: string;
424
+ timeout?: number;
365
425
  /**
366
- * Request headers.
426
+ * The primary PHP instance that's never killed. This instance
427
+ * contains the reference filesystem used by all other PHP instances.
367
428
  */
368
- headers?: PHPRequestHeaders;
429
+ primaryPhp?: PHP;
369
430
  /**
370
- * Request body.
371
- * If an object is given, the request will be encoded as multipart
372
- * and sent with a `multipart/form-data` header.
431
+ * A factory function used for spawning new PHP instances.
373
432
  */
374
- body?: string | Uint8Array | Record<string, string | Uint8Array | File>;
433
+ phpFactory?: PHPFactory;
375
434
  }
376
- export interface PHPRunOptions {
377
- /**
378
- * Request path following the domain:port part.
379
- */
380
- relativeUri?: string;
381
- /**
382
- * Path of the .php file to execute.
383
- */
384
- scriptPath?: string;
385
- /**
386
- * Request protocol.
387
- */
388
- protocol?: string;
389
- /**
390
- * Request method. Default: `GET`.
391
- */
392
- method?: HTTPMethod;
393
- /**
394
- * Request headers.
395
- */
396
- headers?: PHPRequestHeaders;
397
- /**
398
- * Request body.
399
- */
400
- body?: string | Uint8Array;
401
- /**
402
- * Environment variables to set for this run.
403
- */
404
- env?: Record<string, string>;
405
- /**
406
- * $_SERVER entries to set for this run.
407
- */
408
- $_SERVER?: Record<string, string>;
409
- /**
410
- * The code snippet to eval instead of a php file.
411
- */
412
- code?: string;
435
+ export interface SpawnedPHP {
436
+ php: PHP;
437
+ reap: () => void;
413
438
  }
414
- export interface RmDirOptions {
439
+ declare class PHPProcessManager implements AsyncDisposable {
440
+ private primaryPhp?;
441
+ private primaryIdle;
442
+ private nextInstance;
415
443
  /**
416
- * If true, recursively removes the directory and all its contents.
417
- * Default: true.
444
+ * All spawned PHP instances, including the primary PHP instance.
445
+ * Used for bookkeeping and reaping all instances on dispose.
418
446
  */
419
- recursive?: boolean;
420
- }
421
- export interface ListFilesOptions {
447
+ private allInstances;
448
+ private phpFactory?;
449
+ private maxPhpInstances;
450
+ private semaphore;
451
+ constructor(options?: ProcessManagerOptions);
422
452
  /**
423
- * If true, prepend given folder path to all file names.
424
- * Default: false.
453
+ * Get the primary PHP instance.
454
+ *
455
+ * If the primary PHP instance is not set, it will be spawned
456
+ * using the provided phpFactory.
457
+ *
458
+ * @throws {Error} when called twice before the first call is resolved.
425
459
  */
426
- prependPath: boolean;
427
- }
428
- export type PHPRuntimeId = number;
429
- export type PHPRuntime = any;
430
- export type PHPLoaderModule = {
431
- dependencyFilename: string;
432
- dependenciesTotalSize: number;
433
- init: (jsRuntime: string, options: EmscriptenOptions) => PHPRuntime;
434
- };
435
- export type EmscriptenOptions = {
436
- onAbort?: (message: string) => void;
460
+ getPrimaryPhp(): Promise<PHP>;
437
461
  /**
438
- * Set to true for debugging tricky WebAssembly errors.
462
+ * Get a PHP instance.
463
+ *
464
+ * It could be either the primary PHP instance, an idle disposable PHP instance,
465
+ * or a newly spawned PHP instance – depending on the resource availability.
466
+ *
467
+ * @throws {MaxPhpInstancesError} when the maximum number of PHP instances is reached
468
+ * and the waiting timeout is exceeded.
439
469
  */
440
- debug?: boolean;
441
- ENV?: Record<string, string>;
442
- locateFile?: (path: string) => string;
443
- noInitialRun?: boolean;
444
- print?: (message: string) => void;
445
- printErr?: (message: string) => void;
446
- quit?: (status: number, toThrow: any) => void;
447
- onRuntimeInitialized?: () => void;
448
- monitorRunDependencies?: (left: number) => void;
449
- onMessage?: (listener: EmscriptenMessageListener) => void;
450
- instantiateWasm?: (info: WebAssembly.Imports, receiveInstance: (instance: WebAssembly.Instance, module: WebAssembly.Module) => void) => void;
451
- } & Record<string, any>;
452
- export type EmscriptenMessageListener = (type: string, data: string) => void;
453
- export interface SemaphoreOptions {
470
+ acquirePHPInstance(): Promise<SpawnedPHP>;
454
471
  /**
455
- * The maximum number of concurrent locks.
472
+ * Initiated spawning of a new PHP instance.
473
+ * This function is synchronous on purpose – it needs to synchronously
474
+ * add the spawn promise to the allInstances array without waiting
475
+ * for PHP to spawn.
456
476
  */
457
- concurrency: number;
477
+ private spawn;
458
478
  /**
459
- * The maximum time to wait for a lock to become available.
479
+ * Actually acquires the lock and spawns a new PHP instance.
460
480
  */
461
- timeout?: number;
462
- }
463
- declare class Semaphore {
464
- private _running;
465
- private concurrency;
466
- private timeout?;
467
- private queue;
468
- constructor({ concurrency, timeout }: SemaphoreOptions);
469
- get remaining(): number;
470
- get running(): number;
471
- acquire(): Promise<() => void>;
472
- run<T>(fn: () => T | Promise<T>): Promise<T>;
481
+ private doSpawn;
482
+ [Symbol.asyncDispose](): Promise<void>;
473
483
  }
474
484
  export type RewriteRule = {
475
485
  match: RegExp;
@@ -490,10 +500,10 @@ export interface BaseConfiguration {
490
500
  */
491
501
  rewriteRules?: RewriteRule[];
492
502
  }
493
- export type PHPRequestHandlerFactoryArgs<PHP extends BasePHP> = PHPFactoryOptions & {
494
- requestHandler: PHPRequestHandler<PHP>;
503
+ export type PHPRequestHandlerFactoryArgs = PHPFactoryOptions & {
504
+ requestHandler: PHPRequestHandler;
495
505
  };
496
- export type PHPRequestHandlerConfiguration<PHP extends BasePHP> = BaseConfiguration & ({
506
+ export type PHPRequestHandlerConfiguration = BaseConfiguration & ({
497
507
  /**
498
508
  * PHPProcessManager is required because the request handler needs
499
509
  * to make a decision for each request.
@@ -505,19 +515,19 @@ export type PHPRequestHandlerConfiguration<PHP extends BasePHP> = BaseConfigurat
505
515
  * Dynamic PHP requests, however, require grabbing an available PHP
506
516
  * interpreter, and that's where the PHPProcessManager comes in.
507
517
  */
508
- processManager: PHPProcessManager<PHP>;
518
+ processManager: PHPProcessManager;
509
519
  } | {
510
- phpFactory: (requestHandler: PHPRequestHandlerFactoryArgs<PHP>) => Promise<PHP>;
520
+ phpFactory: (requestHandler: PHPRequestHandlerFactoryArgs) => Promise<PHP>;
511
521
  /**
512
522
  * The maximum number of PHP instances that can exist at
513
523
  * the same time.
514
524
  */
515
525
  maxPhpInstances?: number;
516
526
  });
517
- declare class PHPRequestHandler<PHP extends BasePHP> {
527
+ declare class PHPRequestHandler {
518
528
  #private;
519
529
  rewriteRules: RewriteRule[];
520
- processManager: PHPProcessManager<PHP>;
530
+ processManager: PHPProcessManager;
521
531
  /**
522
532
  * The request handler needs to decide whether to serve a static asset or
523
533
  * run the PHP interpreter. For static assets it should just reuse the primary
@@ -529,7 +539,7 @@ declare class PHPRequestHandler<PHP extends BasePHP> {
529
539
  * @param php - The PHP instance.
530
540
  * @param config - Request Handler configuration.
531
541
  */
532
- constructor(config: PHPRequestHandlerConfiguration<PHP>);
542
+ constructor(config: PHPRequestHandlerConfiguration);
533
543
  getPrimaryPhp(): Promise<PHP>;
534
544
  /**
535
545
  * Converts a path to an absolute URL based at the PHPRequestHandler
@@ -607,10 +617,12 @@ declare class PHPRequestHandler<PHP extends BasePHP> {
607
617
  request(request: PHPRequest): Promise<PHPResponse>;
608
618
  }
609
619
  declare const __private__dont__use: unique symbol;
610
- declare abstract class BasePHP implements IsomorphicLocalPHP, Disposable {
620
+ export type UnmountFunction = (() => Promise<any>) | (() => any);
621
+ export type MountHandler = (php: PHP, FS: Emscripten.RootFS, vfsMountPoint: string) => UnmountFunction | Promise<UnmountFunction>;
622
+ declare class PHP implements Disposable {
611
623
  #private;
612
624
  protected [__private__dont__use]: any;
613
- requestHandler?: PHPRequestHandler<any>;
625
+ requestHandler?: PHPRequestHandler;
614
626
  /**
615
627
  * An exclusive lock that prevent multiple requests from running at
616
628
  * the same time.
@@ -624,197 +636,290 @@ declare abstract class BasePHP implements IsomorphicLocalPHP, Disposable {
624
636
  * @param requestHandlerOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
625
637
  */
626
638
  constructor(PHPRuntimeId?: PHPRuntimeId);
639
+ /**
640
+ * Adds an event listener for a PHP event.
641
+ * @param eventType - The type of event to listen for.
642
+ * @param listener - The listener function to be called when the event is triggered.
643
+ */
627
644
  addEventListener(eventType: PHPEvent["type"], listener: PHPEventListener): void;
645
+ /**
646
+ * Removes an event listener for a PHP event.
647
+ * @param eventType - The type of event to remove the listener from.
648
+ * @param listener - The listener function to be removed.
649
+ */
628
650
  removeEventListener(eventType: PHPEvent["type"], listener: PHPEventListener): void;
629
651
  dispatchEvent<Event extends PHPEvent>(event: Event): void;
630
- /** @inheritDoc */
631
- onMessage(listener: MessageListener): Promise<void>;
632
- /** @inheritDoc */
652
+ /**
653
+ * Listens to message sent by the PHP code.
654
+ *
655
+ * To dispatch messages, call:
656
+ *
657
+ * post_message_to_js(string $data)
658
+ *
659
+ * Arguments:
660
+ * $data (string) – Data to pass to JavaScript.
661
+ *
662
+ * @example
663
+ *
664
+ * ```ts
665
+ * const php = await PHP.load('8.0');
666
+ *
667
+ * php.onMessage(
668
+ * // The data is always passed as a string
669
+ * function (data: string) {
670
+ * // Let's decode and log the data:
671
+ * console.log(JSON.parse(data));
672
+ * }
673
+ * );
674
+ *
675
+ * // Now that we have a listener in place, let's
676
+ * // dispatch a message:
677
+ * await php.run({
678
+ * code: `<?php
679
+ * post_message_to_js(
680
+ * json_encode([
681
+ * 'post_id' => '15',
682
+ * 'post_title' => 'This is a blog post!'
683
+ * ])
684
+ * ));
685
+ * `,
686
+ * });
687
+ * ```
688
+ *
689
+ * @param listener Callback function to handle the message.
690
+ */
691
+ onMessage(listener: MessageListener): void;
633
692
  setSpawnHandler(handler: SpawnHandler | string): Promise<void>;
634
- /** @inheritDoc */
693
+ /** @deprecated Use PHPRequestHandler instead. */
635
694
  get absoluteUrl(): string;
636
- /** @inheritDoc */
695
+ /** @deprecated Use PHPRequestHandler instead. */
637
696
  get documentRoot(): string;
638
- /** @inheritDoc */
697
+ /** @deprecated Use PHPRequestHandler instead. */
639
698
  pathToInternalUrl(path: string): string;
640
- /** @inheritDoc */
699
+ /** @deprecated Use PHPRequestHandler instead. */
641
700
  internalUrlToPath(internalUrl: string): string;
642
701
  initializeRuntime(runtimeId: PHPRuntimeId): void;
643
702
  /** @inheritDoc */
644
703
  setSapiName(newName: string): Promise<void>;
645
- /** @inheritDoc */
704
+ /**
705
+ * Changes the current working directory in the PHP filesystem.
706
+ * This is the directory that will be used as the base for relative paths.
707
+ * For example, if the current working directory is `/root/php`, and the
708
+ * path is `data`, the absolute path will be `/root/php/data`.
709
+ *
710
+ * @param path - The new working directory.
711
+ */
646
712
  chdir(path: string): void;
647
713
  /**
648
714
  * Do not use. Use new PHPRequestHandler() instead.
649
715
  * @deprecated
650
716
  */
651
717
  request(request: PHPRequest): Promise<PHPResponse>;
652
- /** @inheritDoc */
718
+ /**
719
+ * Runs PHP code.
720
+ *
721
+ * This low-level method directly interacts with the WebAssembly
722
+ * PHP interpreter.
723
+ *
724
+ * Every time you call run(), it prepares the PHP
725
+ * environment and:
726
+ *
727
+ * * Resets the internal PHP state
728
+ * * Populates superglobals ($_SERVER, $_GET, etc.)
729
+ * * Handles file uploads
730
+ * * Populates input streams (stdin, argv, etc.)
731
+ * * Sets the current working directory
732
+ *
733
+ * You can use run() in two primary modes:
734
+ *
735
+ * ### Code snippet mode
736
+ *
737
+ * In this mode, you pass a string containing PHP code to run.
738
+ *
739
+ * ```ts
740
+ * const result = await php.run({
741
+ * code: `<?php echo "Hello world!";`
742
+ * });
743
+ * // result.text === "Hello world!"
744
+ * ```
745
+ *
746
+ * In this mode, information like __DIR__ or __FILE__ isn't very
747
+ * useful because the code is not associated with any file.
748
+ *
749
+ * Under the hood, the PHP snippet is passed to the `zend_eval_string`
750
+ * C function.
751
+ *
752
+ * ### File mode
753
+ *
754
+ * In the file mode, you pass a scriptPath and PHP executes a file
755
+ * found at a that path:
756
+ *
757
+ * ```ts
758
+ * php.writeFile(
759
+ * "/www/index.php",
760
+ * `<?php echo "Hello world!";"`
761
+ * );
762
+ * const result = await php.run({
763
+ * scriptPath: "/www/index.php"
764
+ * });
765
+ * // result.text === "Hello world!"
766
+ * ```
767
+ *
768
+ * In this mode, you can rely on path-related information like __DIR__
769
+ * or __FILE__.
770
+ *
771
+ * Under the hood, the PHP file is executed with the `php_execute_script`
772
+ * C function.
773
+ *
774
+ * The `run()` method cannot be used in conjunction with `cli()`.
775
+ *
776
+ * @example
777
+ * ```js
778
+ * const result = await php.run(`<?php
779
+ * $fp = fopen('php://stderr', 'w');
780
+ * fwrite($fp, "Hello, world!");
781
+ * `);
782
+ * // result.errors === "Hello, world!"
783
+ * ```
784
+ *
785
+ * @param options - PHP runtime options.
786
+ */
653
787
  run(request: PHPRunOptions): Promise<PHPResponse>;
788
+ /**
789
+ * Defines a constant in the PHP runtime.
790
+ * @param key - The name of the constant.
791
+ * @param value - The value of the constant.
792
+ */
654
793
  defineConstant(key: string, value: string | boolean | number | null): void;
655
- /** @inheritDoc */
656
- mkdir(path: string): void;
657
- /** @inheritDoc */
658
- mkdirTree(path: string): void;
659
- /** @inheritDoc */
660
- readFileAsText(path: string): string;
661
- /** @inheritDoc */
662
- readFileAsBuffer(path: string): Uint8Array;
663
- /** @inheritDoc */
664
- writeFile(path: string, data: string | Uint8Array): void;
665
- /** @inheritDoc */
666
- unlink(path: string): void;
667
- /** @inheritDoc */
668
- mv(fromPath: string, toPath: string): void;
669
- /** @inheritDoc */
670
- rmdir(path: string, options?: RmDirOptions): void;
671
- /** @inheritDoc */
672
- listFiles(path: string, options?: ListFilesOptions): string[];
673
- /** @inheritDoc */
674
- isDir(path: string): boolean;
675
- /** @inheritDoc */
676
- fileExists(path: string): boolean;
677
794
  /**
678
- * Hot-swaps the PHP runtime for a new one without
679
- * interrupting the operations of this PHP instance.
795
+ * Recursively creates a directory with the given path in the PHP filesystem.
796
+ * For example, if the path is `/root/php/data`, and `/root` already exists,
797
+ * it will create the directories `/root/php` and `/root/php/data`.
680
798
  *
681
- * @param runtime
682
- * @param cwd. Internal, the VFS path to recreate in the new runtime.
683
- * This arg is temporary and will be removed once BasePHP
684
- * is fully decoupled from the request handler and
685
- * accepts a constructor-level cwd argument.
799
+ * @param path - The directory path to create.
686
800
  */
687
- hotSwapPHPRuntime(runtime: number, cwd?: string): void;
688
- exit(code?: number): void;
689
- [Symbol.dispose](): void;
690
- }
691
- export type PHPFactoryOptions = {
692
- isPrimary: boolean;
693
- };
694
- export type PHPFactory<PHP extends BasePHP> = (options: PHPFactoryOptions) => Promise<PHP>;
695
- export interface ProcessManagerOptions<PHP extends BasePHP> {
801
+ mkdir(path: string): void;
696
802
  /**
697
- * The maximum number of PHP instances that can exist at
698
- * the same time.
803
+ * @deprecated Use mkdir instead.
804
+ */
805
+ mkdirTree(path: string): void;
806
+ /**
807
+ * Reads a file from the PHP filesystem and returns it as a string.
808
+ *
809
+ * @throws {@link @php-wasm/universal:ErrnoError} – If the file doesn't exist.
810
+ * @param path - The file path to read.
811
+ * @returns The file contents.
699
812
  */
700
- maxPhpInstances?: number;
813
+ readFileAsText(path: string): string;
701
814
  /**
702
- * The number of milliseconds to wait for a PHP instance when
703
- * we have reached the maximum number of PHP instances and
704
- * cannot spawn a new one. If the timeout is reached, we assume
705
- * all the PHP instances are deadlocked and a throw MaxPhpInstancesError.
815
+ * Reads a file from the PHP filesystem and returns it as an array buffer.
706
816
  *
707
- * Default: 5000
817
+ * @throws {@link @php-wasm/universal:ErrnoError} – If the file doesn't exist.
818
+ * @param path - The file path to read.
819
+ * @returns The file contents.
708
820
  */
709
- timeout?: number;
821
+ readFileAsBuffer(path: string): Uint8Array;
710
822
  /**
711
- * The primary PHP instance that's never killed. This instance
712
- * contains the reference filesystem used by all other PHP instances.
823
+ * Overwrites data in a file in the PHP filesystem.
824
+ * Creates a new file if one doesn't exist yet.
825
+ *
826
+ * @param path - The file path to write to.
827
+ * @param data - The data to write to the file.
713
828
  */
714
- primaryPhp?: PHP;
829
+ writeFile(path: string, data: string | Uint8Array): void;
715
830
  /**
716
- * A factory function used for spawning new PHP instances.
831
+ * Removes a file from the PHP filesystem.
832
+ *
833
+ * @throws {@link @php-wasm/universal:ErrnoError} – If the file doesn't exist.
834
+ * @param path - The file path to remove.
717
835
  */
718
- phpFactory?: PHPFactory<PHP>;
719
- }
720
- export interface SpawnedPHP<PHP extends BasePHP> {
721
- php: PHP;
722
- reap: () => void;
723
- }
724
- declare class PHPProcessManager<PHP extends BasePHP> implements AsyncDisposable {
725
- private primaryPhp?;
726
- private primaryIdle;
727
- private nextInstance;
836
+ unlink(path: string): void;
728
837
  /**
729
- * All spawned PHP instances, including the primary PHP instance.
730
- * Used for bookkeeping and reaping all instances on dispose.
838
+ * Moves a file or directory in the PHP filesystem to a
839
+ * new location.
840
+ *
841
+ * @param oldPath The path to rename.
842
+ * @param newPath The new path.
731
843
  */
732
- private allInstances;
733
- private phpFactory?;
734
- private maxPhpInstances;
735
- private semaphore;
736
- constructor(options?: ProcessManagerOptions<PHP>);
844
+ mv(fromPath: string, toPath: string): void;
737
845
  /**
738
- * Get the primary PHP instance.
846
+ * Removes a directory from the PHP filesystem.
739
847
  *
740
- * If the primary PHP instance is not set, it will be spawned
741
- * using the provided phpFactory.
848
+ * @param path The directory path to remove.
849
+ * @param options Options for the removal.
850
+ */
851
+ rmdir(path: string, options?: RmDirOptions): void;
852
+ /**
853
+ * Lists the files and directories in the given directory.
742
854
  *
743
- * @throws {Error} when called twice before the first call is resolved.
855
+ * @param path - The directory path to list.
856
+ * @param options - Options for the listing.
857
+ * @returns The list of files and directories in the given directory.
744
858
  */
745
- getPrimaryPhp(): Promise<PHP>;
859
+ listFiles(path: string, options?: ListFilesOptions): string[];
746
860
  /**
747
- * Get a PHP instance.
861
+ * Checks if a directory exists in the PHP filesystem.
748
862
  *
749
- * It could be either the primary PHP instance, an idle disposable PHP instance,
750
- * or a newly spawned PHP instance depending on the resource availability.
863
+ * @param path The path to check.
864
+ * @returns True if the path is a directory, false otherwise.
865
+ */
866
+ isDir(path: string): boolean;
867
+ /**
868
+ * Checks if a file (or a directory) exists in the PHP filesystem.
751
869
  *
752
- * @throws {MaxPhpInstancesError} when the maximum number of PHP instances is reached
753
- * and the waiting timeout is exceeded.
870
+ * @param path - The file path to check.
871
+ * @returns True if the file exists, false otherwise.
754
872
  */
755
- acquirePHPInstance(): Promise<SpawnedPHP<PHP>>;
873
+ fileExists(path: string): boolean;
756
874
  /**
757
- * Initiated spawning of a new PHP instance.
758
- * This function is synchronous on purpose – it needs to synchronously
759
- * add the spawn promise to the allInstances array without waiting
760
- * for PHP to spawn.
875
+ * Hot-swaps the PHP runtime for a new one without
876
+ * interrupting the operations of this PHP instance.
877
+ *
878
+ * @param runtime
879
+ * @param cwd. Internal, the VFS path to recreate in the new runtime.
880
+ * This arg is temporary and will be removed once BasePHP
881
+ * is fully decoupled from the request handler and
882
+ * accepts a constructor-level cwd argument.
761
883
  */
762
- private spawn;
884
+ hotSwapPHPRuntime(runtime: number, cwd?: string): void;
763
885
  /**
764
- * Actually acquires the lock and spawns a new PHP instance.
886
+ * Mounts a filesystem to a given path in the PHP filesystem.
887
+ *
888
+ * @param virtualFSPath - Where to mount it in the PHP virtual filesystem.
889
+ * @param mountHandler - The mount handler to use.
890
+ * @return Unmount function to unmount the filesystem.
765
891
  */
766
- private doSpawn;
767
- [Symbol.asyncDispose](): Promise<void>;
768
- }
769
- declare const SupportedPHPVersions: readonly [
770
- "8.3",
771
- "8.2",
772
- "8.1",
773
- "8.0",
774
- "7.4",
775
- "7.3",
776
- "7.2",
777
- "7.1",
778
- "7.0"
779
- ];
780
- export type SupportedPHPVersion = (typeof SupportedPHPVersions)[number];
781
- export interface PHPWebLoaderOptions {
782
- emscriptenOptions?: EmscriptenOptions;
783
- onPhpLoaderModuleLoaded?: (module: PHPLoaderModule) => void;
784
- /** @deprecated To be replaced with `extensions` in the future */
785
- loadAllExtensions?: boolean;
786
- }
787
- export declare class WebPHP extends BasePHP {
892
+ mount(virtualFSPath: string, mountHandler: MountHandler): Promise<UnmountFunction>;
788
893
  /**
789
- * Creates a new PHP instance.
894
+ * Starts a PHP CLI session with given arguments.
790
895
  *
791
- * Dynamically imports the PHP module, initializes the runtime,
792
- * and sets up networking. It's a shorthand for the lower-level
793
- * functions like `getPHPLoaderModule`, `loadPHPRuntime`, and
794
- * `PHP.initializeRuntime`
896
+ * This method can only be used when PHP was compiled with the CLI SAPI
897
+ * and it cannot be used in conjunction with `run()`.
795
898
  *
796
- * @param phpVersion The PHP Version to load
797
- * @param options The options to use when loading PHP
798
- * @returns A new PHP instance
899
+ * Once this method finishes running, the PHP instance is no
900
+ * longer usable and should be discarded. This is because PHP
901
+ * internally cleans up all the resources and calls exit().
902
+ *
903
+ * @param argv - The arguments to pass to the CLI.
904
+ * @returns The exit code of the CLI session.
799
905
  */
800
- static load(phpVersion: SupportedPHPVersion, options?: PHPWebLoaderOptions): Promise<WebPHP>;
801
- static loadRuntime(phpVersion: SupportedPHPVersion, options?: PHPWebLoaderOptions): Promise<number>;
802
- }
803
- declare class EmscriptenDownloadMonitor extends EventTarget {
804
- #private;
805
- expectAssets(assets: Record<string, number>): void;
806
- monitorFetch(fetchPromise: Promise<Response>): Promise<Response>;
906
+ cli(argv: string[]): Promise<number>;
907
+ setSkipShebang(shouldSkip: boolean): void;
908
+ exit(code?: number): void;
909
+ [Symbol.dispose](): void;
807
910
  }
808
- /**
809
- * A PHP client that can be used to run PHP code in the browser.
810
- */
811
- export declare class WebPHPEndpoint implements Omit<IsomorphicLocalPHP, "setSapiName"> {
911
+ export type LimitedPHPApi = Pick<PHP, "request" | "defineConstant" | "addEventListener" | "removeEventListener" | "mkdir" | "mkdirTree" | "readFileAsText" | "readFileAsBuffer" | "writeFile" | "unlink" | "mv" | "rmdir" | "listFiles" | "isDir" | "fileExists" | "chdir" | "run" | "onMessage"> & {
912
+ documentRoot: PHP["documentRoot"];
913
+ absoluteUrl: PHP["absoluteUrl"];
914
+ };
915
+ declare class PHPWorker implements LimitedPHPApi {
812
916
  /** @inheritDoc @php-wasm/universal!RequestHandler.absoluteUrl */
813
917
  absoluteUrl: string;
814
918
  /** @inheritDoc @php-wasm/universal!RequestHandler.documentRoot */
815
919
  documentRoot: string;
816
920
  /** @inheritDoc */
817
- constructor(requestHandler: PHPRequestHandler<WebPHP>, monitor?: EmscriptenDownloadMonitor);
921
+ constructor(requestHandler?: PHPRequestHandler, monitor?: EmscriptenDownloadMonitor);
922
+ __internal_setRequestHandler(requestHandler: PHPRequestHandler): void;
818
923
  /**
819
924
  * @internal
820
925
  * @deprecated
@@ -822,8 +927,8 @@ export declare class WebPHPEndpoint implements Omit<IsomorphicLocalPHP, "setSapi
822
927
  * the web API. It will change or even be removed without
823
928
  * a warning.
824
929
  */
825
- protected __internal_getPHP(): WebPHP | undefined;
826
- setPrimaryPHP(php: WebPHP): Promise<void>;
930
+ protected __internal_getPHP(): PHP | undefined;
931
+ setPrimaryPHP(php: PHP): Promise<void>;
827
932
  /** @inheritDoc @php-wasm/universal!PHPRequestHandler.pathToInternalUrl */
828
933
  pathToInternalUrl(path: string): string;
829
934
  /** @inheritDoc @php-wasm/universal!PHPRequestHandler.internalUrlToPath */
@@ -832,45 +937,170 @@ export declare class WebPHPEndpoint implements Omit<IsomorphicLocalPHP, "setSapi
832
937
  * The onDownloadProgress event listener.
833
938
  */
834
939
  onDownloadProgress(callback: (progress: CustomEvent<ProgressEvent>) => void): Promise<void>;
835
- /** @inheritDoc @php-wasm/universal!IsomorphicLocalPHP.mv */
940
+ /** @inheritDoc @php-wasm/universal!PHP.mv */
836
941
  mv(fromPath: string, toPath: string): Promise<void>;
837
- /** @inheritDoc @php-wasm/universal!IsomorphicLocalPHP.rmdir */
942
+ /** @inheritDoc @php-wasm/universal!PHP.rmdir */
838
943
  rmdir(path: string, options?: RmDirOptions): Promise<void>;
839
944
  /** @inheritDoc @php-wasm/universal!PHPRequestHandler.request */
840
945
  request(request: PHPRequest): Promise<PHPResponse>;
841
- /** @inheritDoc @php-wasm/web!WebPHP.run */
946
+ /** @inheritDoc @php-wasm/universal!/PHP.run */
842
947
  run(request: PHPRunOptions): Promise<PHPResponse>;
843
- /** @inheritDoc @php-wasm/web!WebPHP.chdir */
948
+ /** @inheritDoc @php-wasm/universal!/PHP.chdir */
844
949
  chdir(path: string): void;
845
- /** @inheritDoc @php-wasm/web!WebPHP.setSapiName */
950
+ /** @inheritDoc @php-wasm/universal!/PHP.setSapiName */
846
951
  setSapiName(newName: string): void;
847
- /** @inheritDoc @php-wasm/web!WebPHP.mkdir */
952
+ /** @inheritDoc @php-wasm/universal!/PHP.mkdir */
848
953
  mkdir(path: string): void;
849
- /** @inheritDoc @php-wasm/web!WebPHP.mkdirTree */
954
+ /** @inheritDoc @php-wasm/universal!/PHP.mkdirTree */
850
955
  mkdirTree(path: string): void;
851
- /** @inheritDoc @php-wasm/web!WebPHP.readFileAsText */
956
+ /** @inheritDoc @php-wasm/universal!/PHP.readFileAsText */
852
957
  readFileAsText(path: string): string;
853
- /** @inheritDoc @php-wasm/web!WebPHP.readFileAsBuffer */
958
+ /** @inheritDoc @php-wasm/universal!/PHP.readFileAsBuffer */
854
959
  readFileAsBuffer(path: string): Uint8Array;
855
- /** @inheritDoc @php-wasm/web!WebPHP.writeFile */
960
+ /** @inheritDoc @php-wasm/universal!/PHP.writeFile */
856
961
  writeFile(path: string, data: string | Uint8Array): void;
857
- /** @inheritDoc @php-wasm/web!WebPHP.unlink */
962
+ /** @inheritDoc @php-wasm/universal!/PHP.unlink */
858
963
  unlink(path: string): void;
859
- /** @inheritDoc @php-wasm/web!WebPHP.listFiles */
964
+ /** @inheritDoc @php-wasm/universal!/PHP.listFiles */
860
965
  listFiles(path: string, options?: ListFilesOptions): string[];
861
- /** @inheritDoc @php-wasm/web!WebPHP.isDir */
966
+ /** @inheritDoc @php-wasm/universal!/PHP.isDir */
862
967
  isDir(path: string): boolean;
863
- /** @inheritDoc @php-wasm/web!WebPHP.fileExists */
968
+ /** @inheritDoc @php-wasm/universal!/PHP.fileExists */
864
969
  fileExists(path: string): boolean;
865
- /** @inheritDoc @php-wasm/web!WebPHP.onMessage */
970
+ /** @inheritDoc @php-wasm/universal!/PHP.onMessage */
866
971
  onMessage(listener: MessageListener): void;
867
- /** @inheritDoc @php-wasm/web!WebPHP.defineConstant */
972
+ /** @inheritDoc @php-wasm/universal!/PHP.defineConstant */
868
973
  defineConstant(key: string, value: string | boolean | number | null): void;
869
- /** @inheritDoc @php-wasm/web!WebPHP.addEventListener */
974
+ /** @inheritDoc @php-wasm/universal!/PHP.addEventListener */
870
975
  addEventListener(eventType: PHPEvent["type"], listener: PHPEventListener): void;
871
- /** @inheritDoc @php-wasm/web!WebPHP.removeEventListener */
976
+ /** @inheritDoc @php-wasm/universal!/PHP.removeEventListener */
872
977
  removeEventListener(eventType: PHPEvent["type"], listener: PHPEventListener): void;
873
978
  }
979
+ /**
980
+ * Represents an event related to the PHP request.
981
+ */
982
+ export interface PHPRequestEndEvent {
983
+ type: "request.end";
984
+ }
985
+ /**
986
+ * Represents an error event related to the PHP request.
987
+ */
988
+ export interface PHPRequestErrorEvent {
989
+ type: "request.error";
990
+ error: Error;
991
+ source?: "request" | "php-wasm";
992
+ }
993
+ /**
994
+ * Represents a PHP runtime initialization event.
995
+ */
996
+ export interface PHPRuntimeInitializedEvent {
997
+ type: "runtime.initialized";
998
+ }
999
+ /**
1000
+ * Represents a PHP runtime destruction event.
1001
+ */
1002
+ export interface PHPRuntimeBeforeDestroyEvent {
1003
+ type: "runtime.beforedestroy";
1004
+ }
1005
+ /**
1006
+ * Represents an event related to the PHP instance.
1007
+ * This is intentionally not an extension of CustomEvent
1008
+ * to make it isomorphic between different JavaScript runtimes.
1009
+ */
1010
+ export type PHPEvent = PHPRequestEndEvent | PHPRequestErrorEvent | PHPRuntimeInitializedEvent | PHPRuntimeBeforeDestroyEvent;
1011
+ /**
1012
+ * A callback function that handles PHP events.
1013
+ */
1014
+ export type PHPEventListener = (event: PHPEvent) => void;
1015
+ export type MessageListener = (data: string) => Promise<string | Uint8Array | void> | string | void;
1016
+ export interface EventEmitter {
1017
+ on(event: string, listener: (...args: any[]) => void): this;
1018
+ emit(event: string, ...args: any[]): boolean;
1019
+ }
1020
+ export type ChildProcess = EventEmitter & {
1021
+ stdout: EventEmitter;
1022
+ stderr: EventEmitter;
1023
+ };
1024
+ export type SpawnHandler = (command: string, args: string[]) => ChildProcess;
1025
+ export type HTTPMethod = "GET" | "POST" | "HEAD" | "OPTIONS" | "PATCH" | "PUT" | "DELETE";
1026
+ export type PHPRequestHeaders = Record<string, string>;
1027
+ export interface PHPRequest {
1028
+ /**
1029
+ * Request method. Default: `GET`.
1030
+ */
1031
+ method?: HTTPMethod;
1032
+ /**
1033
+ * Request path or absolute URL.
1034
+ */
1035
+ url: string;
1036
+ /**
1037
+ * Request headers.
1038
+ */
1039
+ headers?: PHPRequestHeaders;
1040
+ /**
1041
+ * Request body.
1042
+ * If an object is given, the request will be encoded as multipart
1043
+ * and sent with a `multipart/form-data` header.
1044
+ */
1045
+ body?: string | Uint8Array | Record<string, string | Uint8Array | File>;
1046
+ }
1047
+ export interface PHPRunOptions {
1048
+ /**
1049
+ * Request path following the domain:port part.
1050
+ */
1051
+ relativeUri?: string;
1052
+ /**
1053
+ * Path of the .php file to execute.
1054
+ */
1055
+ scriptPath?: string;
1056
+ /**
1057
+ * Request protocol.
1058
+ */
1059
+ protocol?: string;
1060
+ /**
1061
+ * Request method. Default: `GET`.
1062
+ */
1063
+ method?: HTTPMethod;
1064
+ /**
1065
+ * Request headers.
1066
+ */
1067
+ headers?: PHPRequestHeaders;
1068
+ /**
1069
+ * Request body.
1070
+ */
1071
+ body?: string | Uint8Array;
1072
+ /**
1073
+ * Environment variables to set for this run.
1074
+ */
1075
+ env?: Record<string, string>;
1076
+ /**
1077
+ * $_SERVER entries to set for this run.
1078
+ */
1079
+ $_SERVER?: Record<string, string>;
1080
+ /**
1081
+ * The code snippet to eval instead of a php file.
1082
+ */
1083
+ code?: string;
1084
+ }
1085
+ declare const SupportedPHPVersions: readonly [
1086
+ "8.3",
1087
+ "8.2",
1088
+ "8.1",
1089
+ "8.0",
1090
+ "7.4",
1091
+ "7.3",
1092
+ "7.2",
1093
+ "7.1",
1094
+ "7.0"
1095
+ ];
1096
+ export type SupportedPHPVersion = (typeof SupportedPHPVersions)[number];
1097
+ interface LoaderOptions {
1098
+ emscriptenOptions?: EmscriptenOptions;
1099
+ onPhpLoaderModuleLoaded?: (module: PHPLoaderModule) => void;
1100
+ /** @deprecated To be replaced with `extensions` in the future */
1101
+ loadAllExtensions?: boolean;
1102
+ }
1103
+ export declare function loadWebRuntime(phpVersion: SupportedPHPVersion, options?: LoaderOptions): Promise<number>;
874
1104
  /**
875
1105
  * Loads the PHP loader module for the given PHP version.
876
1106
  *
@@ -889,7 +1119,21 @@ export declare function getPHPLoaderModule(version?: SupportedPHPVersion, varian
889
1119
  * mismatched with the actual version, the service worker
890
1120
  * will be re-registered.
891
1121
  */
892
- export declare function registerServiceWorker<Client extends Remote<WebPHPEndpoint>>(phpApi: Client, scope: string, scriptUrl: string): Promise<void>;
1122
+ export declare function registerServiceWorker<Client extends Remote<PHPWorker>>(phpApi: Client, scope: string, scriptUrl: string): Promise<void>;
1123
+ /**
1124
+ * Setup a postMessage relay between the parent window and a nested iframe.
1125
+ *
1126
+ * When we're running a Playground instance inside an iframe, sometimes that
1127
+ * iframe will contain another iframe and so on. The parent application, however,
1128
+ * needs to be able to communicate with the innermost iframe. This function relays
1129
+ * the communication both ways. Call it in in every iframe layer between the topmost
1130
+ * window and the innermost iframe.
1131
+ *
1132
+ * @param nestedFrame The nested iframe element
1133
+ * @param expectedOrigin The origin that the nested iframe is expected to be on. If not
1134
+ * provided, any origin is allowed.
1135
+ */
1136
+ export declare function setupPostMessageRelay(nestedFrame: HTMLIFrameElement, expectedOrigin?: string): void;
893
1137
  /**
894
1138
  * Spawns a new Worker Thread.
895
1139
  *
@@ -898,5 +1142,19 @@ export declare function registerServiceWorker<Client extends Remote<WebPHPEndpoi
898
1142
  * @returns The spawned Worker Thread.
899
1143
  */
900
1144
  export declare function spawnPHPWorkerThread(workerUrl: string, startupOptions?: Record<string, string | string[]>): Promise<Worker>;
1145
+ export interface MountOptions {
1146
+ initialSync: {
1147
+ direction?: "opfs-to-memfs" | "memfs-to-opfs";
1148
+ onProgress?: SyncProgressCallback;
1149
+ };
1150
+ }
1151
+ export type SyncProgress = {
1152
+ /** The number of files that have been synced. */
1153
+ files: number;
1154
+ /** The number of all files that need to be synced. */
1155
+ total: number;
1156
+ };
1157
+ export type SyncProgressCallback = (progress: SyncProgress) => void;
1158
+ export declare function createDirectoryHandleMountHandler(handle: FileSystemDirectoryHandle, options?: MountOptions): MountHandler;
901
1159
 
902
1160
  export {};