@wp-playground/cli 3.1.20 → 3.1.21
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/README.md +2 -1
- package/blueprints-v1/download.d.ts +1 -1
- package/blueprints-v1/worker-thread-v1.d.ts +3 -2
- package/cli.cjs +1 -1
- package/cli.js +1 -1
- package/index.cjs +1 -1
- package/index.js +4 -3
- package/package.json +14 -14
- package/{run-cli-B9kBDU12.js → run-cli-C2bV7mIt.js} +674 -631
- package/run-cli-C2bV7mIt.js.map +1 -0
- package/run-cli-vtAjdYXb.cjs +66 -0
- package/run-cli-vtAjdYXb.cjs.map +1 -0
- package/run-cli.d.ts +19 -4
- package/sqlite-database-integration.zip +0 -0
- package/worker-thread-v1.cjs +2 -2
- package/worker-thread-v1.cjs.map +1 -1
- package/worker-thread-v1.js +71 -68
- package/worker-thread-v1.js.map +1 -1
- package/worker-thread-v2.cjs +1 -1
- package/worker-thread-v2.js +1 -1
- package/run-cli-B6Dm34vQ.cjs +0 -66
- package/run-cli-B6Dm34vQ.cjs.map +0 -1
- package/run-cli-B9kBDU12.js.map +0 -1
package/run-cli.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
/// <reference types="node" />
|
|
3
|
-
import { type Pooled, type PathAlias, type
|
|
3
|
+
import { type Pooled, type PathAlias, type AllPHPVersion } from '@php-wasm/universal';
|
|
4
4
|
import type { BlueprintBundle, BlueprintV1Declaration, BlueprintV2Declaration } from '@wp-playground/blueprints';
|
|
5
5
|
import type { Server } from 'http';
|
|
6
6
|
import { Worker } from 'worker_threads';
|
|
@@ -46,6 +46,14 @@ export declare function parseOptionsAndRunCLI(argsToParse: string[]): Promise<{
|
|
|
46
46
|
cliServer: RunCLIServer;
|
|
47
47
|
};
|
|
48
48
|
}>;
|
|
49
|
+
/**
|
|
50
|
+
* Resolve the --workers flag into a concrete worker count.
|
|
51
|
+
*
|
|
52
|
+
* The Math.max(1, ...) guard covers single-core hosts and restricted
|
|
53
|
+
* environments where `os.cpus()` can return an empty array — without it
|
|
54
|
+
* the default would drop to 0 and no workers would be spawned.
|
|
55
|
+
*/
|
|
56
|
+
export declare function resolveWorkerCount(value: number | 'auto' | undefined): number;
|
|
49
57
|
export interface RunCLIArgs {
|
|
50
58
|
/**
|
|
51
59
|
* `_` holds positional tokens in the order they appeared.
|
|
@@ -59,13 +67,19 @@ export interface RunCLIArgs {
|
|
|
59
67
|
mount?: Mount[];
|
|
60
68
|
'mount-before-install'?: Mount[];
|
|
61
69
|
outfile?: string;
|
|
62
|
-
php?:
|
|
70
|
+
php?: AllPHPVersion;
|
|
63
71
|
port?: number;
|
|
64
72
|
'site-url'?: string;
|
|
65
73
|
quiet?: boolean;
|
|
66
74
|
verbosity?: LogVerbosity;
|
|
67
75
|
wp?: string;
|
|
68
|
-
|
|
76
|
+
/**
|
|
77
|
+
* For the `server` command (and other long-form commands), this is the
|
|
78
|
+
* host path to auto-detect and mount. For the `start` command, this is a
|
|
79
|
+
* boolean toggle: `true` (default) enables auto-detection on the
|
|
80
|
+
* `--path` directory; `false` (i.e. `--no-auto-mount`) disables it.
|
|
81
|
+
*/
|
|
82
|
+
autoMount?: string | boolean;
|
|
69
83
|
pathAliases?: PathAlias[];
|
|
70
84
|
experimentalTrace?: boolean;
|
|
71
85
|
internalCookieStore?: boolean;
|
|
@@ -78,6 +92,8 @@ export interface RunCLIArgs {
|
|
|
78
92
|
experimentalUnsafeIdeIntegration?: string[];
|
|
79
93
|
experimentalDevtools?: boolean;
|
|
80
94
|
'experimental-blueprints-v2-runner'?: boolean;
|
|
95
|
+
workers?: number | 'auto';
|
|
96
|
+
'experimental-multi-worker'?: number;
|
|
81
97
|
wordpressInstallMode?: WordPressInstallMode;
|
|
82
98
|
/**
|
|
83
99
|
* PHP string constants defined via --define flag.
|
|
@@ -108,7 +124,6 @@ export interface RunCLIArgs {
|
|
|
108
124
|
allow?: string;
|
|
109
125
|
path?: string;
|
|
110
126
|
skipBrowser?: boolean;
|
|
111
|
-
noAutoMount?: boolean;
|
|
112
127
|
reset?: boolean;
|
|
113
128
|
}
|
|
114
129
|
export type PlaygroundCliWorker = PlaygroundCliBlueprintV1Worker | PlaygroundCliBlueprintV2Worker;
|
|
Binary file
|
package/worker-thread-v1.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
2
|
-
`)},phpIniEntries:{"openssl.cafile":"/internal/shared/ca-bundle.crt",allow_url_fopen:"1",disable_functions:""},dataSqlPath:
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=require("@php-wasm/node"),b=require("@php-wasm/progress"),n=require("@php-wasm/universal"),I=require("@php-wasm/util"),q=require("@wp-playground/common"),u=require("@wp-playground/wordpress"),W=require("tls"),P=require("worker_threads"),i=require("./run-cli-vtAjdYXb.cjs"),R=require("@php-wasm/logger");function k(r,e,...t){console.log(performance.now().toFixed(6).padStart(15,"0"),r.toString().padStart(16,"0"),I.sprintf(e,...t))}class w extends n.PHPWorker{constructor(e){super(void 0,e),this.bootedRequestHandler=!1,this.bootedWordPress=!1}async useFileLockManager(e){this.fileLockManager=await n.consumeAPISync(e)}async bootWordPress(e,t){if(this.bootedWordPress)throw new Error("WordPress already booted");this.bootedWordPress=!0;const{siteUrl:s,phpVersion:o,wordpressInstallMode:m,wordPressZip:c,sqliteIntegrationPluginZip:d,dataSqlPath:y,constants:g}=e;try{await u.bootWordPress(this.__internal_getRequestHandler(),{siteUrl:s,phpVersion:o,wordpressInstallMode:m,wordPressZip:c!==void 0?new File([c],"wordpress.zip"):void 0,sqliteIntegrationPluginZip:d!==void 0?new File([d],"sqlite-integration-plugin.zip"):void 0,createFiles:{"/internal/shared/ca-bundle.crt":W.rootCertificates.join(`
|
|
2
|
+
`)},phpIniEntries:{"openssl.cafile":"/internal/shared/ca-bundle.crt",allow_url_fopen:"1",disable_functions:""},dataSqlPath:y,constants:g});const a=n.consumeAPI(t);await a.applyPostInstallMountsToAllWorkers(),a[n.releaseApiProxy](),p()}catch(a){throw h(a),a}}async bootRequestHandler(e){if(this.bootedRequestHandler)throw new Error("Playground already booted");this.bootedRequestHandler=!0;try{const t=await u.bootRequestHandler({siteUrl:e.siteUrl,phpVersion:e.phpVersion,maxPhpInstances:1,createPhpRuntime:H(e,this.fileLockManager),onPHPInstanceCreated:async o=>{await i.mountResources(o,e.mountsBeforeWpInstall),this.bootedWordPress&&await i.mountResources(o,e.mountsAfterWpInstall)},sapiName:"cli",cookieStore:!1,pathAliases:e.pathAliases,spawnHandler:()=>n.sandboxedSpawnHandlerFactory(()=>{let o=e;return this.bootedWordPress||(o={...e,mountsAfterWpInstall:[]}),v(o,this.fileLockManager)})});this.__internal_setRequestHandler(t);const s=await t.getPrimaryPhp();await this.setPrimaryPHP(s),p()}catch(t){throw h(t),t}}async mountAfterWordPressInstall(e){this.bootedWordPress=!0,await i.mountResources(this.__internal_getPHP(),e)}async dispose(){await this[Symbol.asyncDispose]()}}function H(r,e){return async()=>await f.loadNodeRuntime(r.phpVersion||q.RecommendedPHPVersion,{fileLockManager:e,emscriptenOptions:{processId:r.processId,trace:r.trace?k:void 0,nativeInternalDirPath:r.nativeInternalDirPath},followSymlinks:r.followSymlinks,withIntl:r.withIntl,withRedis:r.withRedis,withMemcached:r.withMemcached,withXdebug:r.withXdebug})}async function v(r,e){const t=await i.spawnWorkerThread("v1"),s=n.consumeAPI(t.phpPort);return s.useFileLockManager(e),await s.bootRequestHandler({...r,processId:t.processId}),{php:s,reap:()=>{try{s.dispose()}catch{}try{t.worker.terminate()}catch{}}}}process.on("unhandledRejection",r=>{R.logger.error("Unhandled rejection:",r)});const l=new P.MessageChannel,[p,h]=n.exposeAPI(new w(new b.EmscriptenDownloadMonitor),void 0,l.port1);P.parentPort?.postMessage({command:"worker-script-initialized",phpPort:l.port2},[l.port2]);exports.PlaygroundCliBlueprintV1Worker=w;
|
|
3
3
|
//# sourceMappingURL=worker-thread-v1.cjs.map
|
package/worker-thread-v1.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-thread-v1.cjs","sources":["../../../../packages/playground/cli/src/blueprints-v1/worker-thread-v1.ts"],"sourcesContent":["import type { FileLockManager } from '@php-wasm/universal';\nimport { loadNodeRuntime } from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport type { PathAlias, SupportedPHPVersion } from '@php-wasm/universal';\nimport {\n\tPHPWorker,\n\treleaseApiProxy,\n\tconsumeAPI,\n\tconsumeAPISync,\n\texposeAPI,\n\tsandboxedSpawnHandlerFactory,\n} from '@php-wasm/universal';\nimport { sprintf } from '@php-wasm/util';\nimport { RecommendedPHPVersion } from '@wp-playground/common';\nimport {\n\ttype WordPressInstallMode,\n\tbootRequestHandler,\n\tbootWordPress,\n} from '@wp-playground/wordpress';\nimport { rootCertificates } from 'tls';\nimport { MessageChannel, type MessagePort, parentPort } from 'worker_threads';\nimport { mountResources } from '../mounts';\nimport { logger } from '@php-wasm/logger';\nimport { spawnWorkerThread } from '../run-cli';\n\nimport type { Mount } from '@php-wasm/cli-util';\n\nexport type WorkerBootWordPressOptions = {\n\tsiteUrl: string;\n\twpVersion?: string;\n\twordpressInstallMode: WordPressInstallMode;\n\twordPressZip?: ArrayBuffer;\n\tsqliteIntegrationPluginZip?: ArrayBuffer;\n\tdataSqlPath?: string;\n\t/**\n\t * PHP constants to define via php.defineConstant().\n\t */\n\tconstants?: Record<string, string | number | boolean>;\n};\n\ninterface WorkerBootRequestHandlerOptions {\n\tsiteUrl: string;\n\tphpVersion: SupportedPHPVersion;\n\tprocessId: number;\n\ttrace: boolean;\n\tnativeInternalDirPath: string;\n\tmountsBeforeWpInstall: Array<Mount>;\n\tmountsAfterWpInstall: Array<Mount>;\n\tfollowSymlinks: boolean;\n\twithIntl?: boolean;\n\twithRedis?: boolean;\n\twithMemcached?: boolean;\n\twithXdebug?: boolean;\n\tpathAliases?: PathAlias[];\n}\n\n/**\n * Print trace messages from PHP-WASM.\n *\n * @param {number} processId - The process ID.\n * @param {string} format - The format string.\n * @param {...any} args - The arguments.\n */\nfunction tracePhpWasm(processId: number, format: string, ...args: any[]) {\n\t// eslint-disable-next-line no-console\n\tconsole.log(\n\t\tperformance.now().toFixed(6).padStart(15, '0'),\n\t\tprocessId.toString().padStart(16, '0'),\n\t\tsprintf(format, ...args)\n\t);\n}\n\nexport class PlaygroundCliBlueprintV1Worker extends PHPWorker {\n\tbootedRequestHandler = false;\n\tbootedWordPress = false;\n\tfileLockManager: FileLockManager | undefined;\n\n\tconstructor(monitor: EmscriptenDownloadMonitor) {\n\t\tsuper(undefined, monitor);\n\t}\n\n\t/**\n\t * Call this method before boot() to use file locking.\n\t *\n\t * This method is separate from boot() to simplify the related Comlink.transferHandlers\n\t * setup – if an argument is a MessagePort, we're transferring it, not copying it.\n\t *\n\t * @see comlink-sync.ts\n\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t */\n\tasync useFileLockManager(port: MessagePort) {\n\t\tthis.fileLockManager = await consumeAPISync<FileLockManager>(port);\n\t}\n\n\tasync bootWordPress(\n\t\toptions: WorkerBootWordPressOptions,\n\t\tworkerPostInstallMountsPort: MessagePort\n\t) {\n\t\tif (this.bootedWordPress) {\n\t\t\tthrow new Error('WordPress already booted');\n\t\t}\n\t\tthis.bootedWordPress = true;\n\t\tconst {\n\t\t\tsiteUrl,\n\t\t\twordpressInstallMode,\n\t\t\twordPressZip,\n\t\t\tsqliteIntegrationPluginZip,\n\t\t\tdataSqlPath,\n\t\t\tconstants,\n\t\t} = options;\n\n\t\ttry {\n\t\t\tawait bootWordPress(this.__internal_getRequestHandler()!, {\n\t\t\t\tsiteUrl,\n\t\t\t\twordpressInstallMode,\n\t\t\t\twordPressZip:\n\t\t\t\t\twordPressZip !== undefined\n\t\t\t\t\t\t? new File([wordPressZip], 'wordpress.zip')\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsqliteIntegrationPluginZip:\n\t\t\t\t\tsqliteIntegrationPluginZip !== undefined\n\t\t\t\t\t\t? new File(\n\t\t\t\t\t\t\t\t[sqliteIntegrationPluginZip],\n\t\t\t\t\t\t\t\t'sqlite-integration-plugin.zip'\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: undefined,\n\t\t\t\t// TODO: Are these redundant creations?\n\t\t\t\tcreateFiles: {\n\t\t\t\t\t'/internal/shared/ca-bundle.crt':\n\t\t\t\t\t\trootCertificates.join('\\n'),\n\t\t\t\t},\n\t\t\t\tphpIniEntries: {\n\t\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t\t\tallow_url_fopen: '1',\n\t\t\t\t\tdisable_functions: '',\n\t\t\t\t},\n\t\t\t\tdataSqlPath,\n\t\t\t\tconstants,\n\t\t\t});\n\n\t\t\t// Notify all workers to apply post-install mounts.\n\t\t\tconst postInstall = consumeAPI<{\n\t\t\t\tapplyPostInstallMountsToAllWorkers: () => Promise<void>;\n\t\t\t}>(workerPostInstallMountsPort);\n\t\t\tawait postInstall.applyPostInstallMountsToAllWorkers();\n\t\t\tpostInstall[releaseApiProxy]();\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tasync bootRequestHandler(options: WorkerBootRequestHandlerOptions) {\n\t\tif (this.bootedRequestHandler) {\n\t\t\tthrow new Error('Playground already booted');\n\t\t}\n\t\tthis.bootedRequestHandler = true;\n\n\t\ttry {\n\t\t\tconst requestHandler = await bootRequestHandler({\n\t\t\t\tsiteUrl: options.siteUrl,\n\t\t\t\tmaxPhpInstances: 1,\n\t\t\t\tcreatePhpRuntime: createPhpRuntimeFactory(\n\t\t\t\t\toptions,\n\t\t\t\t\tthis.fileLockManager!\n\t\t\t\t),\n\t\t\t\tonPHPInstanceCreated: async (php) => {\n\t\t\t\t\tawait mountResources(php, options.mountsBeforeWpInstall);\n\n\t\t\t\t\t// NOTE: We currently create all request workers up front\n\t\t\t\t\t// and apply post-install mounts to all the workers immediately\n\t\t\t\t\t// following WordPress install. But if we start creating\n\t\t\t\t\t// request-handling workers on-demand, we will to apply post-install\n\t\t\t\t\t// mounts here.\n\t\t\t\t\tif (this.bootedWordPress) {\n\t\t\t\t\t\tawait mountResources(php, options.mountsAfterWpInstall);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcookieStore: false,\n\t\t\t\tpathAliases: options.pathAliases,\n\t\t\t\tspawnHandler: () =>\n\t\t\t\t\tsandboxedSpawnHandlerFactory(() => {\n\t\t\t\t\t\tlet effectiveOptions = options;\n\t\t\t\t\t\tif (!this.bootedWordPress) {\n\t\t\t\t\t\t\t// WordPress is not yet booted so skip the post-install mounts.\n\t\t\t\t\t\t\teffectiveOptions = {\n\t\t\t\t\t\t\t\t...options,\n\t\t\t\t\t\t\t\tmountsAfterWpInstall: [],\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn createPHPWorker(\n\t\t\t\t\t\t\teffectiveOptions,\n\t\t\t\t\t\t\tthis.fileLockManager!\n\t\t\t\t\t\t);\n\t\t\t\t\t}),\n\t\t\t});\n\t\t\tthis.__internal_setRequestHandler(requestHandler);\n\n\t\t\tconst primaryPhp = await requestHandler.getPrimaryPhp();\n\t\t\tawait this.setPrimaryPHP(primaryPhp);\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tasync mountAfterWordPressInstall(mounts: Array<Mount>) {\n\t\t// Make sure workers not involved in the WordPress install\n\t\t// process know whether WordPress booted so they can\n\t\t// apply post-install mounts when spawning new PHP workers.\n\t\tthis.bootedWordPress = true;\n\t\tawait mountResources(this.__internal_getPHP()!, mounts);\n\t}\n\n\t// Provide a named disposal method that can be invoked via comlink.\n\tasync dispose() {\n\t\tawait this[Symbol.asyncDispose]();\n\t}\n}\n\n/**\n * Returns a factory function that starts a new PHP runtime in the currently\n * running process. This is used for rotating the PHP runtime periodically.\n */\nfunction createPhpRuntimeFactory(\n\toptions: WorkerBootRequestHandlerOptions,\n\tfileLockManager: FileLockManager\n) {\n\treturn async () => {\n\t\treturn await loadNodeRuntime(\n\t\t\toptions.phpVersion || RecommendedPHPVersion,\n\t\t\t{\n\t\t\t\tfileLockManager,\n\t\t\t\temscriptenOptions: {\n\t\t\t\t\tprocessId: options.processId,\n\t\t\t\t\ttrace: options.trace ? tracePhpWasm : undefined,\n\t\t\t\t\tnativeInternalDirPath: options.nativeInternalDirPath,\n\t\t\t\t},\n\t\t\t\tfollowSymlinks: options.followSymlinks,\n\t\t\t\twithIntl: options.withIntl,\n\t\t\t\twithRedis: options.withRedis,\n\t\t\t\twithMemcached: options.withMemcached,\n\t\t\t\twithXdebug: options.withXdebug,\n\t\t\t}\n\t\t);\n\t};\n}\n\n/**\n * Spawns a new PHP process to be used in the PHP spawn handler (in proc_open() etc. calls).\n * It boots from this worker-thread-v1.ts file, but is a separate process.\n *\n * We explicitly avoid using PHPProcessManager.acquirePHPInstance() here.\n *\n * Why?\n *\n * Because each PHP instance acquires actual OS-level file locks via fcntl() and LockFileEx()\n * syscalls. Running multiple PHP instances from the same OS process would allow them to\n * acquire overlapping locks. Running every PHP instance in a separate OS process ensures\n * any locks that overlap between PHP instances conflict with each other as expected.\n *\n * @param options - The options for the worker.\n * @param fileLockManager - The file lock manager to use.\n * @returns A promise that resolves to the PHP worker.\n */\nasync function createPHPWorker(\n\t// NOTE: We explicitly remove processId from the options\n\t// type so the type system will catch if we try to reuse\n\t// our parent's process ID.\n\toptions: Omit<WorkerBootRequestHandlerOptions, 'processId'>,\n\tfileLockManager: FileLockManager\n) {\n\tconst spawnedWorker = await spawnWorkerThread('v1');\n\n\tconst handler = consumeAPI<PlaygroundCliBlueprintV1Worker>(\n\t\tspawnedWorker.phpPort\n\t);\n\thandler.useFileLockManager(fileLockManager as any);\n\tawait handler.bootRequestHandler({\n\t\t...options,\n\t\tprocessId: spawnedWorker.processId,\n\t});\n\n\treturn {\n\t\tphp: handler,\n\t\treap: () => {\n\t\t\ttry {\n\t\t\t\thandler.dispose();\n\t\t\t} catch {\n\t\t\t\t/** */\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tspawnedWorker.worker.terminate();\n\t\t\t} catch {\n\t\t\t\t/** */\n\t\t\t}\n\t\t},\n\t};\n}\n\nprocess.on('unhandledRejection', (e: any) => {\n\tlogger.error('Unhandled rejection:', e);\n});\n\nconst phpChannel = new MessageChannel();\n\nconst [setApiReady, setAPIError] = exposeAPI(\n\tnew PlaygroundCliBlueprintV1Worker(new EmscriptenDownloadMonitor()),\n\tundefined,\n\tphpChannel.port1\n);\n\nparentPort?.postMessage(\n\t{\n\t\tcommand: 'worker-script-initialized',\n\t\tphpPort: phpChannel.port2,\n\t},\n\t[phpChannel.port2 as any]\n);\n"],"names":["tracePhpWasm","processId","format","args","sprintf","PlaygroundCliBlueprintV1Worker","PHPWorker","monitor","port","consumeAPISync","options","workerPostInstallMountsPort","siteUrl","wordpressInstallMode","wordPressZip","sqliteIntegrationPluginZip","dataSqlPath","constants","bootWordPress","rootCertificates","postInstall","consumeAPI","releaseApiProxy","setApiReady","e","setAPIError","requestHandler","bootRequestHandler","createPhpRuntimeFactory","php","mountResources","sandboxedSpawnHandlerFactory","effectiveOptions","createPHPWorker","primaryPhp","mounts","fileLockManager","loadNodeRuntime","RecommendedPHPVersion","spawnedWorker","spawnWorkerThread","handler","logger","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"worker-thread-v1.cjs","sources":["../../../../packages/playground/cli/src/blueprints-v1/worker-thread-v1.ts"],"sourcesContent":["import type { FileLockManager } from '@php-wasm/universal';\nimport { loadNodeRuntime } from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport type { AllPHPVersion, PathAlias } from '@php-wasm/universal';\nimport {\n\tPHPWorker,\n\treleaseApiProxy,\n\tconsumeAPI,\n\tconsumeAPISync,\n\texposeAPI,\n\tsandboxedSpawnHandlerFactory,\n} from '@php-wasm/universal';\nimport { sprintf } from '@php-wasm/util';\nimport { RecommendedPHPVersion } from '@wp-playground/common';\nimport {\n\ttype WordPressInstallMode,\n\tbootRequestHandler,\n\tbootWordPress,\n} from '@wp-playground/wordpress';\nimport { rootCertificates } from 'tls';\nimport { MessageChannel, type MessagePort, parentPort } from 'worker_threads';\nimport { mountResources } from '../mounts';\nimport { logger } from '@php-wasm/logger';\nimport { spawnWorkerThread } from '../run-cli';\n\nimport type { Mount } from '@php-wasm/cli-util';\n\nexport type WorkerBootWordPressOptions = {\n\tsiteUrl: string;\n\tphpVersion?: string;\n\twpVersion?: string;\n\twordpressInstallMode: WordPressInstallMode;\n\twordPressZip?: ArrayBuffer;\n\tsqliteIntegrationPluginZip?: ArrayBuffer;\n\tdataSqlPath?: string;\n\t/**\n\t * PHP constants to define via php.defineConstant().\n\t */\n\tconstants?: Record<string, string | number | boolean>;\n};\n\ninterface WorkerBootRequestHandlerOptions {\n\tsiteUrl: string;\n\tphpVersion: AllPHPVersion;\n\tprocessId: number;\n\ttrace: boolean;\n\tnativeInternalDirPath: string;\n\tmountsBeforeWpInstall: Array<Mount>;\n\tmountsAfterWpInstall: Array<Mount>;\n\tfollowSymlinks: boolean;\n\twithIntl?: boolean;\n\twithRedis?: boolean;\n\twithMemcached?: boolean;\n\twithXdebug?: boolean;\n\tpathAliases?: PathAlias[];\n}\n\n/**\n * Print trace messages from PHP-WASM.\n *\n * @param {number} processId - The process ID.\n * @param {string} format - The format string.\n * @param {...any} args - The arguments.\n */\nfunction tracePhpWasm(processId: number, format: string, ...args: any[]) {\n\t// eslint-disable-next-line no-console\n\tconsole.log(\n\t\tperformance.now().toFixed(6).padStart(15, '0'),\n\t\tprocessId.toString().padStart(16, '0'),\n\t\tsprintf(format, ...args)\n\t);\n}\n\nexport class PlaygroundCliBlueprintV1Worker extends PHPWorker {\n\tbootedRequestHandler = false;\n\tbootedWordPress = false;\n\tfileLockManager: FileLockManager | undefined;\n\n\tconstructor(monitor: EmscriptenDownloadMonitor) {\n\t\tsuper(undefined, monitor);\n\t}\n\n\t/**\n\t * Call this method before boot() to use file locking.\n\t *\n\t * This method is separate from boot() to simplify the related Comlink.transferHandlers\n\t * setup – if an argument is a MessagePort, we're transferring it, not copying it.\n\t *\n\t * @see comlink-sync.ts\n\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t */\n\tasync useFileLockManager(port: MessagePort) {\n\t\tthis.fileLockManager = await consumeAPISync<FileLockManager>(port);\n\t}\n\n\tasync bootWordPress(\n\t\toptions: WorkerBootWordPressOptions,\n\t\tworkerPostInstallMountsPort: MessagePort\n\t) {\n\t\tif (this.bootedWordPress) {\n\t\t\tthrow new Error('WordPress already booted');\n\t\t}\n\t\tthis.bootedWordPress = true;\n\t\tconst {\n\t\t\tsiteUrl,\n\t\t\tphpVersion,\n\t\t\twordpressInstallMode,\n\t\t\twordPressZip,\n\t\t\tsqliteIntegrationPluginZip,\n\t\t\tdataSqlPath,\n\t\t\tconstants,\n\t\t} = options;\n\n\t\ttry {\n\t\t\tawait bootWordPress(this.__internal_getRequestHandler()!, {\n\t\t\t\tsiteUrl,\n\t\t\t\tphpVersion,\n\t\t\t\twordpressInstallMode,\n\t\t\t\twordPressZip:\n\t\t\t\t\twordPressZip !== undefined\n\t\t\t\t\t\t? new File([wordPressZip], 'wordpress.zip')\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsqliteIntegrationPluginZip:\n\t\t\t\t\tsqliteIntegrationPluginZip !== undefined\n\t\t\t\t\t\t? new File(\n\t\t\t\t\t\t\t\t[sqliteIntegrationPluginZip],\n\t\t\t\t\t\t\t\t'sqlite-integration-plugin.zip'\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: undefined,\n\t\t\t\t// TODO: Are these redundant creations?\n\t\t\t\tcreateFiles: {\n\t\t\t\t\t'/internal/shared/ca-bundle.crt':\n\t\t\t\t\t\trootCertificates.join('\\n'),\n\t\t\t\t},\n\t\t\t\tphpIniEntries: {\n\t\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t\t\tallow_url_fopen: '1',\n\t\t\t\t\tdisable_functions: '',\n\t\t\t\t},\n\t\t\t\tdataSqlPath,\n\t\t\t\tconstants,\n\t\t\t});\n\n\t\t\t// Notify all workers to apply post-install mounts.\n\t\t\tconst postInstall = consumeAPI<{\n\t\t\t\tapplyPostInstallMountsToAllWorkers: () => Promise<void>;\n\t\t\t}>(workerPostInstallMountsPort);\n\t\t\tawait postInstall.applyPostInstallMountsToAllWorkers();\n\t\t\tpostInstall[releaseApiProxy]();\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tasync bootRequestHandler(options: WorkerBootRequestHandlerOptions) {\n\t\tif (this.bootedRequestHandler) {\n\t\t\tthrow new Error('Playground already booted');\n\t\t}\n\t\tthis.bootedRequestHandler = true;\n\n\t\ttry {\n\t\t\tconst requestHandler = await bootRequestHandler({\n\t\t\t\tsiteUrl: options.siteUrl,\n\t\t\t\tphpVersion: options.phpVersion,\n\t\t\t\tmaxPhpInstances: 1,\n\t\t\t\tcreatePhpRuntime: createPhpRuntimeFactory(\n\t\t\t\t\toptions,\n\t\t\t\t\tthis.fileLockManager!\n\t\t\t\t),\n\t\t\t\tonPHPInstanceCreated: async (php) => {\n\t\t\t\t\tawait mountResources(php, options.mountsBeforeWpInstall);\n\n\t\t\t\t\t// NOTE: We currently create all request workers up front\n\t\t\t\t\t// and apply post-install mounts to all the workers immediately\n\t\t\t\t\t// following WordPress install. But if we start creating\n\t\t\t\t\t// request-handling workers on-demand, we will to apply post-install\n\t\t\t\t\t// mounts here.\n\t\t\t\t\tif (this.bootedWordPress) {\n\t\t\t\t\t\tawait mountResources(php, options.mountsAfterWpInstall);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcookieStore: false,\n\t\t\t\tpathAliases: options.pathAliases,\n\t\t\t\tspawnHandler: () =>\n\t\t\t\t\tsandboxedSpawnHandlerFactory(() => {\n\t\t\t\t\t\tlet effectiveOptions = options;\n\t\t\t\t\t\tif (!this.bootedWordPress) {\n\t\t\t\t\t\t\t// WordPress is not yet booted so skip the post-install mounts.\n\t\t\t\t\t\t\teffectiveOptions = {\n\t\t\t\t\t\t\t\t...options,\n\t\t\t\t\t\t\t\tmountsAfterWpInstall: [],\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn createPHPWorker(\n\t\t\t\t\t\t\teffectiveOptions,\n\t\t\t\t\t\t\tthis.fileLockManager!\n\t\t\t\t\t\t);\n\t\t\t\t\t}),\n\t\t\t});\n\t\t\tthis.__internal_setRequestHandler(requestHandler);\n\n\t\t\tconst primaryPhp = await requestHandler.getPrimaryPhp();\n\t\t\tawait this.setPrimaryPHP(primaryPhp);\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tasync mountAfterWordPressInstall(mounts: Array<Mount>) {\n\t\t// Make sure workers not involved in the WordPress install\n\t\t// process know whether WordPress booted so they can\n\t\t// apply post-install mounts when spawning new PHP workers.\n\t\tthis.bootedWordPress = true;\n\t\tawait mountResources(this.__internal_getPHP()!, mounts);\n\t}\n\n\t// Provide a named disposal method that can be invoked via comlink.\n\tasync dispose() {\n\t\tawait this[Symbol.asyncDispose]();\n\t}\n}\n\n/**\n * Returns a factory function that starts a new PHP runtime in the currently\n * running process. This is used for rotating the PHP runtime periodically.\n */\nfunction createPhpRuntimeFactory(\n\toptions: WorkerBootRequestHandlerOptions,\n\tfileLockManager: FileLockManager\n) {\n\treturn async () => {\n\t\treturn await loadNodeRuntime(\n\t\t\toptions.phpVersion || RecommendedPHPVersion,\n\t\t\t{\n\t\t\t\tfileLockManager,\n\t\t\t\temscriptenOptions: {\n\t\t\t\t\tprocessId: options.processId,\n\t\t\t\t\ttrace: options.trace ? tracePhpWasm : undefined,\n\t\t\t\t\tnativeInternalDirPath: options.nativeInternalDirPath,\n\t\t\t\t},\n\t\t\t\tfollowSymlinks: options.followSymlinks,\n\t\t\t\twithIntl: options.withIntl,\n\t\t\t\twithRedis: options.withRedis,\n\t\t\t\twithMemcached: options.withMemcached,\n\t\t\t\twithXdebug: options.withXdebug,\n\t\t\t}\n\t\t);\n\t};\n}\n\n/**\n * Spawns a new PHP process to be used in the PHP spawn handler (in proc_open() etc. calls).\n * It boots from this worker-thread-v1.ts file, but is a separate process.\n *\n * We explicitly avoid using PHPProcessManager.acquirePHPInstance() here.\n *\n * Why?\n *\n * Because each PHP instance acquires actual OS-level file locks via fcntl() and LockFileEx()\n * syscalls. Running multiple PHP instances from the same OS process would allow them to\n * acquire overlapping locks. Running every PHP instance in a separate OS process ensures\n * any locks that overlap between PHP instances conflict with each other as expected.\n *\n * @param options - The options for the worker.\n * @param fileLockManager - The file lock manager to use.\n * @returns A promise that resolves to the PHP worker.\n */\nasync function createPHPWorker(\n\t// NOTE: We explicitly remove processId from the options\n\t// type so the type system will catch if we try to reuse\n\t// our parent's process ID.\n\toptions: Omit<WorkerBootRequestHandlerOptions, 'processId'>,\n\tfileLockManager: FileLockManager\n) {\n\tconst spawnedWorker = await spawnWorkerThread('v1');\n\n\tconst handler = consumeAPI<PlaygroundCliBlueprintV1Worker>(\n\t\tspawnedWorker.phpPort\n\t);\n\thandler.useFileLockManager(fileLockManager as any);\n\tawait handler.bootRequestHandler({\n\t\t...options,\n\t\tprocessId: spawnedWorker.processId,\n\t});\n\n\treturn {\n\t\tphp: handler,\n\t\treap: () => {\n\t\t\ttry {\n\t\t\t\thandler.dispose();\n\t\t\t} catch {\n\t\t\t\t/** */\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tspawnedWorker.worker.terminate();\n\t\t\t} catch {\n\t\t\t\t/** */\n\t\t\t}\n\t\t},\n\t};\n}\n\nprocess.on('unhandledRejection', (e: any) => {\n\tlogger.error('Unhandled rejection:', e);\n});\n\nconst phpChannel = new MessageChannel();\n\nconst [setApiReady, setAPIError] = exposeAPI(\n\tnew PlaygroundCliBlueprintV1Worker(new EmscriptenDownloadMonitor()),\n\tundefined,\n\tphpChannel.port1\n);\n\nparentPort?.postMessage(\n\t{\n\t\tcommand: 'worker-script-initialized',\n\t\tphpPort: phpChannel.port2,\n\t},\n\t[phpChannel.port2 as any]\n);\n"],"names":["tracePhpWasm","processId","format","args","sprintf","PlaygroundCliBlueprintV1Worker","PHPWorker","monitor","port","consumeAPISync","options","workerPostInstallMountsPort","siteUrl","phpVersion","wordpressInstallMode","wordPressZip","sqliteIntegrationPluginZip","dataSqlPath","constants","bootWordPress","rootCertificates","postInstall","consumeAPI","releaseApiProxy","setApiReady","e","setAPIError","requestHandler","bootRequestHandler","createPhpRuntimeFactory","php","mountResources","sandboxedSpawnHandlerFactory","effectiveOptions","createPHPWorker","primaryPhp","mounts","fileLockManager","loadNodeRuntime","RecommendedPHPVersion","spawnedWorker","spawnWorkerThread","handler","logger","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}
|
package/worker-thread-v1.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { loadNodeRuntime as
|
|
2
|
-
import { EmscriptenDownloadMonitor as
|
|
3
|
-
import { exposeAPI as
|
|
4
|
-
import { sprintf as
|
|
5
|
-
import { RecommendedPHPVersion as
|
|
6
|
-
import { bootWordPress as
|
|
7
|
-
import { rootCertificates as
|
|
8
|
-
import { MessageChannel as
|
|
9
|
-
import {
|
|
10
|
-
import { logger as
|
|
11
|
-
function
|
|
1
|
+
import { loadNodeRuntime as w } from "@php-wasm/node";
|
|
2
|
+
import { EmscriptenDownloadMonitor as f } from "@php-wasm/progress";
|
|
3
|
+
import { exposeAPI as y, PHPWorker as b, consumeAPISync as g, consumeAPI as h, releaseApiProxy as I, sandboxedSpawnHandlerFactory as W } from "@php-wasm/universal";
|
|
4
|
+
import { sprintf as H } from "@php-wasm/util";
|
|
5
|
+
import { RecommendedPHPVersion as R } from "@wp-playground/common";
|
|
6
|
+
import { bootWordPress as k, bootRequestHandler as q } from "@wp-playground/wordpress";
|
|
7
|
+
import { rootCertificates as A } from "tls";
|
|
8
|
+
import { MessageChannel as M, parentPort as _ } from "worker_threads";
|
|
9
|
+
import { b as n, s as v } from "./run-cli-C2bV7mIt.js";
|
|
10
|
+
import { logger as S } from "@php-wasm/logger";
|
|
11
|
+
function F(r, e, ...t) {
|
|
12
12
|
console.log(
|
|
13
13
|
performance.now().toFixed(6).padStart(15, "0"),
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
r.toString().padStart(16, "0"),
|
|
15
|
+
H(e, ...t)
|
|
16
16
|
);
|
|
17
17
|
}
|
|
18
|
-
class
|
|
18
|
+
class x extends b {
|
|
19
19
|
constructor(e) {
|
|
20
20
|
super(void 0, e), this.bootedRequestHandler = !1, this.bootedWordPress = !1;
|
|
21
21
|
}
|
|
@@ -31,22 +31,24 @@ class F extends y {
|
|
|
31
31
|
async useFileLockManager(e) {
|
|
32
32
|
this.fileLockManager = await g(e);
|
|
33
33
|
}
|
|
34
|
-
async bootWordPress(e,
|
|
34
|
+
async bootWordPress(e, t) {
|
|
35
35
|
if (this.bootedWordPress)
|
|
36
36
|
throw new Error("WordPress already booted");
|
|
37
37
|
this.bootedWordPress = !0;
|
|
38
38
|
const {
|
|
39
|
-
siteUrl:
|
|
40
|
-
|
|
39
|
+
siteUrl: o,
|
|
40
|
+
phpVersion: s,
|
|
41
|
+
wordpressInstallMode: m,
|
|
41
42
|
wordPressZip: l,
|
|
42
43
|
sqliteIntegrationPluginZip: d,
|
|
43
|
-
dataSqlPath:
|
|
44
|
-
constants:
|
|
44
|
+
dataSqlPath: u,
|
|
45
|
+
constants: P
|
|
45
46
|
} = e;
|
|
46
47
|
try {
|
|
47
|
-
await
|
|
48
|
-
siteUrl:
|
|
49
|
-
|
|
48
|
+
await k(this.__internal_getRequestHandler(), {
|
|
49
|
+
siteUrl: o,
|
|
50
|
+
phpVersion: s,
|
|
51
|
+
wordpressInstallMode: m,
|
|
50
52
|
wordPressZip: l !== void 0 ? new File([l], "wordpress.zip") : void 0,
|
|
51
53
|
sqliteIntegrationPluginZip: d !== void 0 ? new File(
|
|
52
54
|
[d],
|
|
@@ -54,7 +56,7 @@ class F extends y {
|
|
|
54
56
|
) : void 0,
|
|
55
57
|
// TODO: Are these redundant creations?
|
|
56
58
|
createFiles: {
|
|
57
|
-
"/internal/shared/ca-bundle.crt":
|
|
59
|
+
"/internal/shared/ca-bundle.crt": A.join(`
|
|
58
60
|
`)
|
|
59
61
|
},
|
|
60
62
|
phpIniEntries: {
|
|
@@ -62,13 +64,13 @@ class F extends y {
|
|
|
62
64
|
allow_url_fopen: "1",
|
|
63
65
|
disable_functions: ""
|
|
64
66
|
},
|
|
65
|
-
dataSqlPath:
|
|
66
|
-
constants:
|
|
67
|
+
dataSqlPath: u,
|
|
68
|
+
constants: P
|
|
67
69
|
});
|
|
68
|
-
const
|
|
69
|
-
await
|
|
70
|
-
} catch (
|
|
71
|
-
throw p(
|
|
70
|
+
const a = h(t);
|
|
71
|
+
await a.applyPostInstallMountsToAllWorkers(), a[I](), c();
|
|
72
|
+
} catch (a) {
|
|
73
|
+
throw p(a), a;
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
76
|
async bootRequestHandler(e) {
|
|
@@ -76,35 +78,36 @@ class F extends y {
|
|
|
76
78
|
throw new Error("Playground already booted");
|
|
77
79
|
this.bootedRequestHandler = !0;
|
|
78
80
|
try {
|
|
79
|
-
const
|
|
81
|
+
const t = await q({
|
|
80
82
|
siteUrl: e.siteUrl,
|
|
83
|
+
phpVersion: e.phpVersion,
|
|
81
84
|
maxPhpInstances: 1,
|
|
82
|
-
createPhpRuntime:
|
|
85
|
+
createPhpRuntime: V(
|
|
83
86
|
e,
|
|
84
87
|
this.fileLockManager
|
|
85
88
|
),
|
|
86
|
-
onPHPInstanceCreated: async (
|
|
87
|
-
await n(
|
|
89
|
+
onPHPInstanceCreated: async (s) => {
|
|
90
|
+
await n(s, e.mountsBeforeWpInstall), this.bootedWordPress && await n(s, e.mountsAfterWpInstall);
|
|
88
91
|
},
|
|
89
92
|
sapiName: "cli",
|
|
90
93
|
cookieStore: !1,
|
|
91
94
|
pathAliases: e.pathAliases,
|
|
92
|
-
spawnHandler: () =>
|
|
93
|
-
let
|
|
94
|
-
return this.bootedWordPress || (
|
|
95
|
+
spawnHandler: () => W(() => {
|
|
96
|
+
let s = e;
|
|
97
|
+
return this.bootedWordPress || (s = {
|
|
95
98
|
...e,
|
|
96
99
|
mountsAfterWpInstall: []
|
|
97
100
|
}), C(
|
|
98
|
-
|
|
101
|
+
s,
|
|
99
102
|
this.fileLockManager
|
|
100
103
|
);
|
|
101
104
|
})
|
|
102
105
|
});
|
|
103
|
-
this.__internal_setRequestHandler(
|
|
104
|
-
const
|
|
105
|
-
await this.setPrimaryPHP(
|
|
106
|
-
} catch (
|
|
107
|
-
throw p(
|
|
106
|
+
this.__internal_setRequestHandler(t);
|
|
107
|
+
const o = await t.getPrimaryPhp();
|
|
108
|
+
await this.setPrimaryPHP(o), c();
|
|
109
|
+
} catch (t) {
|
|
110
|
+
throw p(t), t;
|
|
108
111
|
}
|
|
109
112
|
}
|
|
110
113
|
async mountAfterWordPressInstall(e) {
|
|
@@ -115,54 +118,54 @@ class F extends y {
|
|
|
115
118
|
await this[Symbol.asyncDispose]();
|
|
116
119
|
}
|
|
117
120
|
}
|
|
118
|
-
function
|
|
119
|
-
return async () => await
|
|
120
|
-
|
|
121
|
+
function V(r, e) {
|
|
122
|
+
return async () => await w(
|
|
123
|
+
r.phpVersion || R,
|
|
121
124
|
{
|
|
122
125
|
fileLockManager: e,
|
|
123
126
|
emscriptenOptions: {
|
|
124
|
-
processId:
|
|
125
|
-
trace:
|
|
126
|
-
nativeInternalDirPath:
|
|
127
|
+
processId: r.processId,
|
|
128
|
+
trace: r.trace ? F : void 0,
|
|
129
|
+
nativeInternalDirPath: r.nativeInternalDirPath
|
|
127
130
|
},
|
|
128
|
-
followSymlinks:
|
|
129
|
-
withIntl:
|
|
130
|
-
withRedis:
|
|
131
|
-
withMemcached:
|
|
132
|
-
withXdebug:
|
|
131
|
+
followSymlinks: r.followSymlinks,
|
|
132
|
+
withIntl: r.withIntl,
|
|
133
|
+
withRedis: r.withRedis,
|
|
134
|
+
withMemcached: r.withMemcached,
|
|
135
|
+
withXdebug: r.withXdebug
|
|
133
136
|
}
|
|
134
137
|
);
|
|
135
138
|
}
|
|
136
|
-
async function C(
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
+
async function C(r, e) {
|
|
140
|
+
const t = await v("v1"), o = h(
|
|
141
|
+
t.phpPort
|
|
139
142
|
);
|
|
140
|
-
return
|
|
141
|
-
...
|
|
142
|
-
processId:
|
|
143
|
+
return o.useFileLockManager(e), await o.bootRequestHandler({
|
|
144
|
+
...r,
|
|
145
|
+
processId: t.processId
|
|
143
146
|
}), {
|
|
144
|
-
php:
|
|
147
|
+
php: o,
|
|
145
148
|
reap: () => {
|
|
146
149
|
try {
|
|
147
|
-
|
|
150
|
+
o.dispose();
|
|
148
151
|
} catch {
|
|
149
152
|
}
|
|
150
153
|
try {
|
|
151
|
-
|
|
154
|
+
t.worker.terminate();
|
|
152
155
|
} catch {
|
|
153
156
|
}
|
|
154
157
|
}
|
|
155
158
|
};
|
|
156
159
|
}
|
|
157
|
-
process.on("unhandledRejection", (
|
|
158
|
-
|
|
160
|
+
process.on("unhandledRejection", (r) => {
|
|
161
|
+
S.error("Unhandled rejection:", r);
|
|
159
162
|
});
|
|
160
|
-
const i = new
|
|
161
|
-
new
|
|
163
|
+
const i = new M(), [c, p] = y(
|
|
164
|
+
new x(new f()),
|
|
162
165
|
void 0,
|
|
163
166
|
i.port1
|
|
164
167
|
);
|
|
165
|
-
|
|
168
|
+
_?.postMessage(
|
|
166
169
|
{
|
|
167
170
|
command: "worker-script-initialized",
|
|
168
171
|
phpPort: i.port2
|
|
@@ -170,6 +173,6 @@ M?.postMessage(
|
|
|
170
173
|
[i.port2]
|
|
171
174
|
);
|
|
172
175
|
export {
|
|
173
|
-
|
|
176
|
+
x as PlaygroundCliBlueprintV1Worker
|
|
174
177
|
};
|
|
175
178
|
//# sourceMappingURL=worker-thread-v1.js.map
|
package/worker-thread-v1.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-thread-v1.js","sources":["../../../../packages/playground/cli/src/blueprints-v1/worker-thread-v1.ts"],"sourcesContent":["import type { FileLockManager } from '@php-wasm/universal';\nimport { loadNodeRuntime } from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport type { PathAlias, SupportedPHPVersion } from '@php-wasm/universal';\nimport {\n\tPHPWorker,\n\treleaseApiProxy,\n\tconsumeAPI,\n\tconsumeAPISync,\n\texposeAPI,\n\tsandboxedSpawnHandlerFactory,\n} from '@php-wasm/universal';\nimport { sprintf } from '@php-wasm/util';\nimport { RecommendedPHPVersion } from '@wp-playground/common';\nimport {\n\ttype WordPressInstallMode,\n\tbootRequestHandler,\n\tbootWordPress,\n} from '@wp-playground/wordpress';\nimport { rootCertificates } from 'tls';\nimport { MessageChannel, type MessagePort, parentPort } from 'worker_threads';\nimport { mountResources } from '../mounts';\nimport { logger } from '@php-wasm/logger';\nimport { spawnWorkerThread } from '../run-cli';\n\nimport type { Mount } from '@php-wasm/cli-util';\n\nexport type WorkerBootWordPressOptions = {\n\tsiteUrl: string;\n\twpVersion?: string;\n\twordpressInstallMode: WordPressInstallMode;\n\twordPressZip?: ArrayBuffer;\n\tsqliteIntegrationPluginZip?: ArrayBuffer;\n\tdataSqlPath?: string;\n\t/**\n\t * PHP constants to define via php.defineConstant().\n\t */\n\tconstants?: Record<string, string | number | boolean>;\n};\n\ninterface WorkerBootRequestHandlerOptions {\n\tsiteUrl: string;\n\tphpVersion: SupportedPHPVersion;\n\tprocessId: number;\n\ttrace: boolean;\n\tnativeInternalDirPath: string;\n\tmountsBeforeWpInstall: Array<Mount>;\n\tmountsAfterWpInstall: Array<Mount>;\n\tfollowSymlinks: boolean;\n\twithIntl?: boolean;\n\twithRedis?: boolean;\n\twithMemcached?: boolean;\n\twithXdebug?: boolean;\n\tpathAliases?: PathAlias[];\n}\n\n/**\n * Print trace messages from PHP-WASM.\n *\n * @param {number} processId - The process ID.\n * @param {string} format - The format string.\n * @param {...any} args - The arguments.\n */\nfunction tracePhpWasm(processId: number, format: string, ...args: any[]) {\n\t// eslint-disable-next-line no-console\n\tconsole.log(\n\t\tperformance.now().toFixed(6).padStart(15, '0'),\n\t\tprocessId.toString().padStart(16, '0'),\n\t\tsprintf(format, ...args)\n\t);\n}\n\nexport class PlaygroundCliBlueprintV1Worker extends PHPWorker {\n\tbootedRequestHandler = false;\n\tbootedWordPress = false;\n\tfileLockManager: FileLockManager | undefined;\n\n\tconstructor(monitor: EmscriptenDownloadMonitor) {\n\t\tsuper(undefined, monitor);\n\t}\n\n\t/**\n\t * Call this method before boot() to use file locking.\n\t *\n\t * This method is separate from boot() to simplify the related Comlink.transferHandlers\n\t * setup – if an argument is a MessagePort, we're transferring it, not copying it.\n\t *\n\t * @see comlink-sync.ts\n\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t */\n\tasync useFileLockManager(port: MessagePort) {\n\t\tthis.fileLockManager = await consumeAPISync<FileLockManager>(port);\n\t}\n\n\tasync bootWordPress(\n\t\toptions: WorkerBootWordPressOptions,\n\t\tworkerPostInstallMountsPort: MessagePort\n\t) {\n\t\tif (this.bootedWordPress) {\n\t\t\tthrow new Error('WordPress already booted');\n\t\t}\n\t\tthis.bootedWordPress = true;\n\t\tconst {\n\t\t\tsiteUrl,\n\t\t\twordpressInstallMode,\n\t\t\twordPressZip,\n\t\t\tsqliteIntegrationPluginZip,\n\t\t\tdataSqlPath,\n\t\t\tconstants,\n\t\t} = options;\n\n\t\ttry {\n\t\t\tawait bootWordPress(this.__internal_getRequestHandler()!, {\n\t\t\t\tsiteUrl,\n\t\t\t\twordpressInstallMode,\n\t\t\t\twordPressZip:\n\t\t\t\t\twordPressZip !== undefined\n\t\t\t\t\t\t? new File([wordPressZip], 'wordpress.zip')\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsqliteIntegrationPluginZip:\n\t\t\t\t\tsqliteIntegrationPluginZip !== undefined\n\t\t\t\t\t\t? new File(\n\t\t\t\t\t\t\t\t[sqliteIntegrationPluginZip],\n\t\t\t\t\t\t\t\t'sqlite-integration-plugin.zip'\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: undefined,\n\t\t\t\t// TODO: Are these redundant creations?\n\t\t\t\tcreateFiles: {\n\t\t\t\t\t'/internal/shared/ca-bundle.crt':\n\t\t\t\t\t\trootCertificates.join('\\n'),\n\t\t\t\t},\n\t\t\t\tphpIniEntries: {\n\t\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t\t\tallow_url_fopen: '1',\n\t\t\t\t\tdisable_functions: '',\n\t\t\t\t},\n\t\t\t\tdataSqlPath,\n\t\t\t\tconstants,\n\t\t\t});\n\n\t\t\t// Notify all workers to apply post-install mounts.\n\t\t\tconst postInstall = consumeAPI<{\n\t\t\t\tapplyPostInstallMountsToAllWorkers: () => Promise<void>;\n\t\t\t}>(workerPostInstallMountsPort);\n\t\t\tawait postInstall.applyPostInstallMountsToAllWorkers();\n\t\t\tpostInstall[releaseApiProxy]();\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tasync bootRequestHandler(options: WorkerBootRequestHandlerOptions) {\n\t\tif (this.bootedRequestHandler) {\n\t\t\tthrow new Error('Playground already booted');\n\t\t}\n\t\tthis.bootedRequestHandler = true;\n\n\t\ttry {\n\t\t\tconst requestHandler = await bootRequestHandler({\n\t\t\t\tsiteUrl: options.siteUrl,\n\t\t\t\tmaxPhpInstances: 1,\n\t\t\t\tcreatePhpRuntime: createPhpRuntimeFactory(\n\t\t\t\t\toptions,\n\t\t\t\t\tthis.fileLockManager!\n\t\t\t\t),\n\t\t\t\tonPHPInstanceCreated: async (php) => {\n\t\t\t\t\tawait mountResources(php, options.mountsBeforeWpInstall);\n\n\t\t\t\t\t// NOTE: We currently create all request workers up front\n\t\t\t\t\t// and apply post-install mounts to all the workers immediately\n\t\t\t\t\t// following WordPress install. But if we start creating\n\t\t\t\t\t// request-handling workers on-demand, we will to apply post-install\n\t\t\t\t\t// mounts here.\n\t\t\t\t\tif (this.bootedWordPress) {\n\t\t\t\t\t\tawait mountResources(php, options.mountsAfterWpInstall);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcookieStore: false,\n\t\t\t\tpathAliases: options.pathAliases,\n\t\t\t\tspawnHandler: () =>\n\t\t\t\t\tsandboxedSpawnHandlerFactory(() => {\n\t\t\t\t\t\tlet effectiveOptions = options;\n\t\t\t\t\t\tif (!this.bootedWordPress) {\n\t\t\t\t\t\t\t// WordPress is not yet booted so skip the post-install mounts.\n\t\t\t\t\t\t\teffectiveOptions = {\n\t\t\t\t\t\t\t\t...options,\n\t\t\t\t\t\t\t\tmountsAfterWpInstall: [],\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn createPHPWorker(\n\t\t\t\t\t\t\teffectiveOptions,\n\t\t\t\t\t\t\tthis.fileLockManager!\n\t\t\t\t\t\t);\n\t\t\t\t\t}),\n\t\t\t});\n\t\t\tthis.__internal_setRequestHandler(requestHandler);\n\n\t\t\tconst primaryPhp = await requestHandler.getPrimaryPhp();\n\t\t\tawait this.setPrimaryPHP(primaryPhp);\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tasync mountAfterWordPressInstall(mounts: Array<Mount>) {\n\t\t// Make sure workers not involved in the WordPress install\n\t\t// process know whether WordPress booted so they can\n\t\t// apply post-install mounts when spawning new PHP workers.\n\t\tthis.bootedWordPress = true;\n\t\tawait mountResources(this.__internal_getPHP()!, mounts);\n\t}\n\n\t// Provide a named disposal method that can be invoked via comlink.\n\tasync dispose() {\n\t\tawait this[Symbol.asyncDispose]();\n\t}\n}\n\n/**\n * Returns a factory function that starts a new PHP runtime in the currently\n * running process. This is used for rotating the PHP runtime periodically.\n */\nfunction createPhpRuntimeFactory(\n\toptions: WorkerBootRequestHandlerOptions,\n\tfileLockManager: FileLockManager\n) {\n\treturn async () => {\n\t\treturn await loadNodeRuntime(\n\t\t\toptions.phpVersion || RecommendedPHPVersion,\n\t\t\t{\n\t\t\t\tfileLockManager,\n\t\t\t\temscriptenOptions: {\n\t\t\t\t\tprocessId: options.processId,\n\t\t\t\t\ttrace: options.trace ? tracePhpWasm : undefined,\n\t\t\t\t\tnativeInternalDirPath: options.nativeInternalDirPath,\n\t\t\t\t},\n\t\t\t\tfollowSymlinks: options.followSymlinks,\n\t\t\t\twithIntl: options.withIntl,\n\t\t\t\twithRedis: options.withRedis,\n\t\t\t\twithMemcached: options.withMemcached,\n\t\t\t\twithXdebug: options.withXdebug,\n\t\t\t}\n\t\t);\n\t};\n}\n\n/**\n * Spawns a new PHP process to be used in the PHP spawn handler (in proc_open() etc. calls).\n * It boots from this worker-thread-v1.ts file, but is a separate process.\n *\n * We explicitly avoid using PHPProcessManager.acquirePHPInstance() here.\n *\n * Why?\n *\n * Because each PHP instance acquires actual OS-level file locks via fcntl() and LockFileEx()\n * syscalls. Running multiple PHP instances from the same OS process would allow them to\n * acquire overlapping locks. Running every PHP instance in a separate OS process ensures\n * any locks that overlap between PHP instances conflict with each other as expected.\n *\n * @param options - The options for the worker.\n * @param fileLockManager - The file lock manager to use.\n * @returns A promise that resolves to the PHP worker.\n */\nasync function createPHPWorker(\n\t// NOTE: We explicitly remove processId from the options\n\t// type so the type system will catch if we try to reuse\n\t// our parent's process ID.\n\toptions: Omit<WorkerBootRequestHandlerOptions, 'processId'>,\n\tfileLockManager: FileLockManager\n) {\n\tconst spawnedWorker = await spawnWorkerThread('v1');\n\n\tconst handler = consumeAPI<PlaygroundCliBlueprintV1Worker>(\n\t\tspawnedWorker.phpPort\n\t);\n\thandler.useFileLockManager(fileLockManager as any);\n\tawait handler.bootRequestHandler({\n\t\t...options,\n\t\tprocessId: spawnedWorker.processId,\n\t});\n\n\treturn {\n\t\tphp: handler,\n\t\treap: () => {\n\t\t\ttry {\n\t\t\t\thandler.dispose();\n\t\t\t} catch {\n\t\t\t\t/** */\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tspawnedWorker.worker.terminate();\n\t\t\t} catch {\n\t\t\t\t/** */\n\t\t\t}\n\t\t},\n\t};\n}\n\nprocess.on('unhandledRejection', (e: any) => {\n\tlogger.error('Unhandled rejection:', e);\n});\n\nconst phpChannel = new MessageChannel();\n\nconst [setApiReady, setAPIError] = exposeAPI(\n\tnew PlaygroundCliBlueprintV1Worker(new EmscriptenDownloadMonitor()),\n\tundefined,\n\tphpChannel.port1\n);\n\nparentPort?.postMessage(\n\t{\n\t\tcommand: 'worker-script-initialized',\n\t\tphpPort: phpChannel.port2,\n\t},\n\t[phpChannel.port2 as any]\n);\n"],"names":["tracePhpWasm","processId","format","args","sprintf","PlaygroundCliBlueprintV1Worker","PHPWorker","monitor","port","consumeAPISync","options","workerPostInstallMountsPort","siteUrl","wordpressInstallMode","wordPressZip","sqliteIntegrationPluginZip","dataSqlPath","constants","bootWordPress","rootCertificates","postInstall","consumeAPI","releaseApiProxy","setApiReady","e","setAPIError","requestHandler","bootRequestHandler","createPhpRuntimeFactory","php","mountResources","sandboxedSpawnHandlerFactory","effectiveOptions","createPHPWorker","primaryPhp","mounts","fileLockManager","loadNodeRuntime","RecommendedPHPVersion","spawnedWorker","spawnWorkerThread","handler","logger","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"worker-thread-v1.js","sources":["../../../../packages/playground/cli/src/blueprints-v1/worker-thread-v1.ts"],"sourcesContent":["import type { FileLockManager } from '@php-wasm/universal';\nimport { loadNodeRuntime } from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport type { AllPHPVersion, PathAlias } from '@php-wasm/universal';\nimport {\n\tPHPWorker,\n\treleaseApiProxy,\n\tconsumeAPI,\n\tconsumeAPISync,\n\texposeAPI,\n\tsandboxedSpawnHandlerFactory,\n} from '@php-wasm/universal';\nimport { sprintf } from '@php-wasm/util';\nimport { RecommendedPHPVersion } from '@wp-playground/common';\nimport {\n\ttype WordPressInstallMode,\n\tbootRequestHandler,\n\tbootWordPress,\n} from '@wp-playground/wordpress';\nimport { rootCertificates } from 'tls';\nimport { MessageChannel, type MessagePort, parentPort } from 'worker_threads';\nimport { mountResources } from '../mounts';\nimport { logger } from '@php-wasm/logger';\nimport { spawnWorkerThread } from '../run-cli';\n\nimport type { Mount } from '@php-wasm/cli-util';\n\nexport type WorkerBootWordPressOptions = {\n\tsiteUrl: string;\n\tphpVersion?: string;\n\twpVersion?: string;\n\twordpressInstallMode: WordPressInstallMode;\n\twordPressZip?: ArrayBuffer;\n\tsqliteIntegrationPluginZip?: ArrayBuffer;\n\tdataSqlPath?: string;\n\t/**\n\t * PHP constants to define via php.defineConstant().\n\t */\n\tconstants?: Record<string, string | number | boolean>;\n};\n\ninterface WorkerBootRequestHandlerOptions {\n\tsiteUrl: string;\n\tphpVersion: AllPHPVersion;\n\tprocessId: number;\n\ttrace: boolean;\n\tnativeInternalDirPath: string;\n\tmountsBeforeWpInstall: Array<Mount>;\n\tmountsAfterWpInstall: Array<Mount>;\n\tfollowSymlinks: boolean;\n\twithIntl?: boolean;\n\twithRedis?: boolean;\n\twithMemcached?: boolean;\n\twithXdebug?: boolean;\n\tpathAliases?: PathAlias[];\n}\n\n/**\n * Print trace messages from PHP-WASM.\n *\n * @param {number} processId - The process ID.\n * @param {string} format - The format string.\n * @param {...any} args - The arguments.\n */\nfunction tracePhpWasm(processId: number, format: string, ...args: any[]) {\n\t// eslint-disable-next-line no-console\n\tconsole.log(\n\t\tperformance.now().toFixed(6).padStart(15, '0'),\n\t\tprocessId.toString().padStart(16, '0'),\n\t\tsprintf(format, ...args)\n\t);\n}\n\nexport class PlaygroundCliBlueprintV1Worker extends PHPWorker {\n\tbootedRequestHandler = false;\n\tbootedWordPress = false;\n\tfileLockManager: FileLockManager | undefined;\n\n\tconstructor(monitor: EmscriptenDownloadMonitor) {\n\t\tsuper(undefined, monitor);\n\t}\n\n\t/**\n\t * Call this method before boot() to use file locking.\n\t *\n\t * This method is separate from boot() to simplify the related Comlink.transferHandlers\n\t * setup – if an argument is a MessagePort, we're transferring it, not copying it.\n\t *\n\t * @see comlink-sync.ts\n\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t */\n\tasync useFileLockManager(port: MessagePort) {\n\t\tthis.fileLockManager = await consumeAPISync<FileLockManager>(port);\n\t}\n\n\tasync bootWordPress(\n\t\toptions: WorkerBootWordPressOptions,\n\t\tworkerPostInstallMountsPort: MessagePort\n\t) {\n\t\tif (this.bootedWordPress) {\n\t\t\tthrow new Error('WordPress already booted');\n\t\t}\n\t\tthis.bootedWordPress = true;\n\t\tconst {\n\t\t\tsiteUrl,\n\t\t\tphpVersion,\n\t\t\twordpressInstallMode,\n\t\t\twordPressZip,\n\t\t\tsqliteIntegrationPluginZip,\n\t\t\tdataSqlPath,\n\t\t\tconstants,\n\t\t} = options;\n\n\t\ttry {\n\t\t\tawait bootWordPress(this.__internal_getRequestHandler()!, {\n\t\t\t\tsiteUrl,\n\t\t\t\tphpVersion,\n\t\t\t\twordpressInstallMode,\n\t\t\t\twordPressZip:\n\t\t\t\t\twordPressZip !== undefined\n\t\t\t\t\t\t? new File([wordPressZip], 'wordpress.zip')\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsqliteIntegrationPluginZip:\n\t\t\t\t\tsqliteIntegrationPluginZip !== undefined\n\t\t\t\t\t\t? new File(\n\t\t\t\t\t\t\t\t[sqliteIntegrationPluginZip],\n\t\t\t\t\t\t\t\t'sqlite-integration-plugin.zip'\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: undefined,\n\t\t\t\t// TODO: Are these redundant creations?\n\t\t\t\tcreateFiles: {\n\t\t\t\t\t'/internal/shared/ca-bundle.crt':\n\t\t\t\t\t\trootCertificates.join('\\n'),\n\t\t\t\t},\n\t\t\t\tphpIniEntries: {\n\t\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t\t\tallow_url_fopen: '1',\n\t\t\t\t\tdisable_functions: '',\n\t\t\t\t},\n\t\t\t\tdataSqlPath,\n\t\t\t\tconstants,\n\t\t\t});\n\n\t\t\t// Notify all workers to apply post-install mounts.\n\t\t\tconst postInstall = consumeAPI<{\n\t\t\t\tapplyPostInstallMountsToAllWorkers: () => Promise<void>;\n\t\t\t}>(workerPostInstallMountsPort);\n\t\t\tawait postInstall.applyPostInstallMountsToAllWorkers();\n\t\t\tpostInstall[releaseApiProxy]();\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tasync bootRequestHandler(options: WorkerBootRequestHandlerOptions) {\n\t\tif (this.bootedRequestHandler) {\n\t\t\tthrow new Error('Playground already booted');\n\t\t}\n\t\tthis.bootedRequestHandler = true;\n\n\t\ttry {\n\t\t\tconst requestHandler = await bootRequestHandler({\n\t\t\t\tsiteUrl: options.siteUrl,\n\t\t\t\tphpVersion: options.phpVersion,\n\t\t\t\tmaxPhpInstances: 1,\n\t\t\t\tcreatePhpRuntime: createPhpRuntimeFactory(\n\t\t\t\t\toptions,\n\t\t\t\t\tthis.fileLockManager!\n\t\t\t\t),\n\t\t\t\tonPHPInstanceCreated: async (php) => {\n\t\t\t\t\tawait mountResources(php, options.mountsBeforeWpInstall);\n\n\t\t\t\t\t// NOTE: We currently create all request workers up front\n\t\t\t\t\t// and apply post-install mounts to all the workers immediately\n\t\t\t\t\t// following WordPress install. But if we start creating\n\t\t\t\t\t// request-handling workers on-demand, we will to apply post-install\n\t\t\t\t\t// mounts here.\n\t\t\t\t\tif (this.bootedWordPress) {\n\t\t\t\t\t\tawait mountResources(php, options.mountsAfterWpInstall);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcookieStore: false,\n\t\t\t\tpathAliases: options.pathAliases,\n\t\t\t\tspawnHandler: () =>\n\t\t\t\t\tsandboxedSpawnHandlerFactory(() => {\n\t\t\t\t\t\tlet effectiveOptions = options;\n\t\t\t\t\t\tif (!this.bootedWordPress) {\n\t\t\t\t\t\t\t// WordPress is not yet booted so skip the post-install mounts.\n\t\t\t\t\t\t\teffectiveOptions = {\n\t\t\t\t\t\t\t\t...options,\n\t\t\t\t\t\t\t\tmountsAfterWpInstall: [],\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn createPHPWorker(\n\t\t\t\t\t\t\teffectiveOptions,\n\t\t\t\t\t\t\tthis.fileLockManager!\n\t\t\t\t\t\t);\n\t\t\t\t\t}),\n\t\t\t});\n\t\t\tthis.__internal_setRequestHandler(requestHandler);\n\n\t\t\tconst primaryPhp = await requestHandler.getPrimaryPhp();\n\t\t\tawait this.setPrimaryPHP(primaryPhp);\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tasync mountAfterWordPressInstall(mounts: Array<Mount>) {\n\t\t// Make sure workers not involved in the WordPress install\n\t\t// process know whether WordPress booted so they can\n\t\t// apply post-install mounts when spawning new PHP workers.\n\t\tthis.bootedWordPress = true;\n\t\tawait mountResources(this.__internal_getPHP()!, mounts);\n\t}\n\n\t// Provide a named disposal method that can be invoked via comlink.\n\tasync dispose() {\n\t\tawait this[Symbol.asyncDispose]();\n\t}\n}\n\n/**\n * Returns a factory function that starts a new PHP runtime in the currently\n * running process. This is used for rotating the PHP runtime periodically.\n */\nfunction createPhpRuntimeFactory(\n\toptions: WorkerBootRequestHandlerOptions,\n\tfileLockManager: FileLockManager\n) {\n\treturn async () => {\n\t\treturn await loadNodeRuntime(\n\t\t\toptions.phpVersion || RecommendedPHPVersion,\n\t\t\t{\n\t\t\t\tfileLockManager,\n\t\t\t\temscriptenOptions: {\n\t\t\t\t\tprocessId: options.processId,\n\t\t\t\t\ttrace: options.trace ? tracePhpWasm : undefined,\n\t\t\t\t\tnativeInternalDirPath: options.nativeInternalDirPath,\n\t\t\t\t},\n\t\t\t\tfollowSymlinks: options.followSymlinks,\n\t\t\t\twithIntl: options.withIntl,\n\t\t\t\twithRedis: options.withRedis,\n\t\t\t\twithMemcached: options.withMemcached,\n\t\t\t\twithXdebug: options.withXdebug,\n\t\t\t}\n\t\t);\n\t};\n}\n\n/**\n * Spawns a new PHP process to be used in the PHP spawn handler (in proc_open() etc. calls).\n * It boots from this worker-thread-v1.ts file, but is a separate process.\n *\n * We explicitly avoid using PHPProcessManager.acquirePHPInstance() here.\n *\n * Why?\n *\n * Because each PHP instance acquires actual OS-level file locks via fcntl() and LockFileEx()\n * syscalls. Running multiple PHP instances from the same OS process would allow them to\n * acquire overlapping locks. Running every PHP instance in a separate OS process ensures\n * any locks that overlap between PHP instances conflict with each other as expected.\n *\n * @param options - The options for the worker.\n * @param fileLockManager - The file lock manager to use.\n * @returns A promise that resolves to the PHP worker.\n */\nasync function createPHPWorker(\n\t// NOTE: We explicitly remove processId from the options\n\t// type so the type system will catch if we try to reuse\n\t// our parent's process ID.\n\toptions: Omit<WorkerBootRequestHandlerOptions, 'processId'>,\n\tfileLockManager: FileLockManager\n) {\n\tconst spawnedWorker = await spawnWorkerThread('v1');\n\n\tconst handler = consumeAPI<PlaygroundCliBlueprintV1Worker>(\n\t\tspawnedWorker.phpPort\n\t);\n\thandler.useFileLockManager(fileLockManager as any);\n\tawait handler.bootRequestHandler({\n\t\t...options,\n\t\tprocessId: spawnedWorker.processId,\n\t});\n\n\treturn {\n\t\tphp: handler,\n\t\treap: () => {\n\t\t\ttry {\n\t\t\t\thandler.dispose();\n\t\t\t} catch {\n\t\t\t\t/** */\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tspawnedWorker.worker.terminate();\n\t\t\t} catch {\n\t\t\t\t/** */\n\t\t\t}\n\t\t},\n\t};\n}\n\nprocess.on('unhandledRejection', (e: any) => {\n\tlogger.error('Unhandled rejection:', e);\n});\n\nconst phpChannel = new MessageChannel();\n\nconst [setApiReady, setAPIError] = exposeAPI(\n\tnew PlaygroundCliBlueprintV1Worker(new EmscriptenDownloadMonitor()),\n\tundefined,\n\tphpChannel.port1\n);\n\nparentPort?.postMessage(\n\t{\n\t\tcommand: 'worker-script-initialized',\n\t\tphpPort: phpChannel.port2,\n\t},\n\t[phpChannel.port2 as any]\n);\n"],"names":["tracePhpWasm","processId","format","args","sprintf","PlaygroundCliBlueprintV1Worker","PHPWorker","monitor","port","consumeAPISync","options","workerPostInstallMountsPort","siteUrl","phpVersion","wordpressInstallMode","wordPressZip","sqliteIntegrationPluginZip","dataSqlPath","constants","bootWordPress","rootCertificates","postInstall","consumeAPI","releaseApiProxy","setApiReady","e","setAPIError","requestHandler","bootRequestHandler","createPhpRuntimeFactory","php","mountResources","sandboxedSpawnHandlerFactory","effectiveOptions","createPHPWorker","primaryPhp","mounts","fileLockManager","loadNodeRuntime","RecommendedPHPVersion","spawnedWorker","spawnWorkerThread","handler","logger","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}
|
package/worker-thread-v2.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const _=require("@php-wasm/logger"),m=require("@php-wasm/node"),$=require("@php-wasm/progress"),n=require("@php-wasm/universal"),x=require("@php-wasm/util"),S=require("@wp-playground/blueprints"),W=require("@wp-playground/wordpress"),A=require("fs"),y=require("path"),B=require("tls"),R=require("worker_threads"),T=require("./run-cli-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const _=require("@php-wasm/logger"),m=require("@php-wasm/node"),$=require("@php-wasm/progress"),n=require("@php-wasm/universal"),x=require("@php-wasm/util"),S=require("@wp-playground/blueprints"),W=require("@wp-playground/wordpress"),A=require("fs"),y=require("path"),B=require("tls"),R=require("worker_threads"),T=require("./run-cli-vtAjdYXb.cjs");async function g(s,e){for(const t of e)try{s.mkdir(t.vfsPath),await s.mount(t.vfsPath,m.createNodeFsMountHandler(t.hostPath))}catch{i.stderr(`\x1B[31m\x1B[1mError mounting path ${t.hostPath} at ${t.vfsPath}\x1B[0m
|
|
2
2
|
`),process.exit(1)}}function C(s,e,...t){console.log(performance.now().toFixed(6).padStart(15,"0"),s.toString().padStart(16,"0"),x.sprintf(e,...t))}Object.defineProperty(process.stdout,"isTTY",{value:!0});Object.defineProperty(process.stderr,"isTTY",{value:!0});const i={lastWriteWasProgress:!1,progress(s){T.shouldRenderProgress(process.stdout)&&(process.stdout.isTTY?(i.lastWriteWasProgress||process.stdout.write(`
|
|
3
3
|
`),process.stdout.write("\r\x1B[K"+s),i.lastWriteWasProgress=!0):console.log(s))},stdout(s){process.stdout.write(`
|
|
4
4
|
|
package/worker-thread-v2.js
CHANGED
|
@@ -9,7 +9,7 @@ import { existsSync as G } from "fs";
|
|
|
9
9
|
import m from "path";
|
|
10
10
|
import { rootCertificates as Y } from "tls";
|
|
11
11
|
import { MessageChannel as z, parentPort as K } from "worker_threads";
|
|
12
|
-
import { s as J,
|
|
12
|
+
import { s as J, c as Q } from "./run-cli-C2bV7mIt.js";
|
|
13
13
|
async function b(s, e) {
|
|
14
14
|
for (const t of e)
|
|
15
15
|
try {
|