diff --git a/packages/php-wasm/web-service-worker/src/initialize-service-worker.ts b/packages/php-wasm/web-service-worker/src/initialize-service-worker.ts index c693faba70..6c6872256d 100644 --- a/packages/php-wasm/web-service-worker/src/initialize-service-worker.ts +++ b/packages/php-wasm/web-service-worker/src/initialize-service-worker.ts @@ -170,7 +170,8 @@ export async function convertFetchEventToPHPRequest(event: FetchEvent) { message, } ); - phpResponse = await broadcastMessageAwaitReply(message, scope); + const requestId = await broadcastMessageExpectReply(message, scope); + phpResponse = await awaitReply(self, requestId); // X-frame-options gets in a way when PHP is // being displayed in an iframe. @@ -209,18 +210,8 @@ export async function convertFetchEventToPHPRequest(event: FetchEvent) { * @param scope Target worker thread scope. * @returns The request ID to receive the reply. */ -export async function broadcastMessageAwaitReply(message: any, scope: string) { +export async function broadcastMessageExpectReply(message: any, scope: string) { const requestId = getNextRequestId(); - console.log( - 'broadcastMessageAwaitReply(', - message, - scope, - ') {requestId: ', - requestId, - '}' - ); - const responsePromise = awaitReply(self, requestId); - for (const client of await self.clients.matchAll({ // Sometimes the client that triggered the current fetch() // event is considered uncontrolled in Google Chrome. This @@ -241,11 +232,7 @@ export async function broadcastMessageAwaitReply(message: any, scope: string) { requestId, }); } - - console.log('pre await responsePromise'); - const response = await responsePromise; - console.log('post await responsePromise', response); - return response; + return requestId; } interface ServiceWorkerConfiguration { diff --git a/packages/php-wasm/web-service-worker/src/messaging.ts b/packages/php-wasm/web-service-worker/src/messaging.ts index b9e366076c..00cd1209bf 100644 --- a/packages/php-wasm/web-service-worker/src/messaging.ts +++ b/packages/php-wasm/web-service-worker/src/messaging.ts @@ -1,7 +1,69 @@ -const DEFAULT_RESPONSE_TIMEOUT = 5000; +const DEFAULT_RESPONSE_TIMEOUT = 25000; let lastRequestId = 0; +/** + * Posts a message branded with a unique `requestId` to the given `target`. + * Then returns the `requestId` so it can be used to await a reply. + * Effectively, it implements the request/response dynamics on + * of JavaScript's `postMessage` + * + * @example + * + * In the main app: + * + * ```js + * import { postMessageExpectReply, awaitReply } from 'php-wasm-browser'; + * const iframeWindow = iframe.contentWindow; + * const requestId = postMessageExpectReply(iframeWindow, { + * type: "get_php_version" + * }); + * const response = await awaitReply(iframeWindow, requestId); + * console.log(response); + * // "8.0.24" + * ``` + * + * In the iframe: + * + * ```js + * import { responseTo } from 'php-wasm-browser'; + * window.addEventListener('message', (event) => { + * let response = '8.0.24'; + * if(event.data.type === 'get_php_version') { + * response = '8.0.24'; + * } else { + * throw new Error(`Unexpected message type: ${event.data.type}`); + * } + * + * // When `requestId` is present, the other thread expects a response: + * if (event.data.requestId) { + * const response = responseTo(event.data.requestId, response); + * window.parent.postMessage(response, event.origin); + * } + * }); + * ``` + * + * @param target An object that has a `postMessage` method. + * @param message A key-value object that can be serialized to JSON. + * @param postMessageArgs Additional arguments to pass to `postMessage`. + * @returns The message ID for awaitReply(). + */ +export function postMessageExpectReply( + target: PostMessageTarget, + message: Record, + ...postMessageArgs: any[] +): number { + const requestId = getNextRequestId(); + target.postMessage( + { + ...message, + requestId, + }, + ...postMessageArgs + ); + return requestId; +} + export function getNextRequestId() { return ++lastRequestId; } @@ -23,11 +85,8 @@ export function awaitReply( requestId: number, timeout: number = DEFAULT_RESPONSE_TIMEOUT ): Promise { - console.log(`called awaitReply(..., ${requestId}, ${timeout})`); return new Promise((resolve, reject) => { - console.log('I am in a promise', { requestId }); const responseHandler = (event: MessageEvent) => { - console.log('responseHandler(', event, ')'); if ( event.data.type === 'response' && event.data.requestId === requestId @@ -39,14 +98,11 @@ export function awaitReply( }; const failOntimeout = setTimeout(() => { - console.log('failOntimeout()'); reject(new Error('Request timed out')); messageTarget.removeEventListener('message', responseHandler); }, timeout); - console.log('pre messageTarget.addEventListener'); messageTarget.addEventListener('message', responseHandler); - console.log('post messageTarget.addEventListener'); }); } @@ -76,6 +132,10 @@ export interface MessageResponse { response: T; } +interface PostMessageTarget { + postMessage(message: any, ...args: any[]): void; +} + interface IsomorphicEventTarget { addEventListener(type: string, listener: (event: any) => void): void; removeEventListener(type: string, listener: (event: any) => void): void; diff --git a/packages/php-wasm/web/src/lib/api.ts b/packages/php-wasm/web/src/lib/api.ts index d1e428d05b..fc9071d249 100644 --- a/packages/php-wasm/web/src/lib/api.ts +++ b/packages/php-wasm/web/src/lib/api.ts @@ -148,11 +148,9 @@ function setupTransferHandlers() { 'exitCode' in obj && 'httpStatusCode' in obj, serialize(obj: PHPResponse): [PHPResponseData, Transferable[]] { - console.log('Serializing'); return [obj.toRawData(), []]; }, deserialize(responseData: PHPResponseData): PHPResponse { - console.log('Deerializing'); return PHPResponse.fromRawData(responseData); }, }); diff --git a/packages/php-wasm/web/src/lib/web-php-endpoint.ts b/packages/php-wasm/web/src/lib/web-php-endpoint.ts index aef14f3dba..73f6a00a3a 100644 --- a/packages/php-wasm/web/src/lib/web-php-endpoint.ts +++ b/packages/php-wasm/web/src/lib/web-php-endpoint.ts @@ -93,10 +93,7 @@ export class WebPHPEndpoint implements IsomorphicLocalPHP { /** @inheritDoc @php-wasm/universal!RequestHandler.request */ request(request: PHPRequest, redirects?: number): Promise { - console.log('Got request', request, { redirects }); - const resp = _private.get(this)!.php.request(request, redirects); - console.log(resp.then((r) => console.log(r))); - return resp; + return _private.get(this)!.php.request(request, redirects); } /** @inheritDoc @php-wasm/web!WebPHP.run */ diff --git a/packages/playground/blueprints/src/lib/compile.ts b/packages/playground/blueprints/src/lib/compile.ts index a760195d43..a867a21298 100644 --- a/packages/playground/blueprints/src/lib/compile.ts +++ b/packages/playground/blueprints/src/lib/compile.ts @@ -92,10 +92,8 @@ export function compileBlueprint( } for (const { run, step } of compiled) { - console.log('before run', { run, step }); const result = await run(playground); onStepCompleted(result, step); - console.log('after run', { result, step }); } try { await (playground as any).goTo( @@ -112,7 +110,6 @@ export function compileBlueprint( } finally { progress.finish(); } - console.log('Fnished'); }, }; } diff --git a/packages/playground/blueprints/src/lib/steps/login.ts b/packages/playground/blueprints/src/lib/steps/login.ts index 10dc80a27d..d8fb2a984f 100644 --- a/packages/playground/blueprints/src/lib/steps/login.ts +++ b/packages/playground/blueprints/src/lib/steps/login.ts @@ -36,14 +36,9 @@ export const login: StepHandler = async ( progress ) => { progress?.tracker.setCaption(progress?.initialCaption || 'Logging in'); - console.log('Before request'); - playground.request({ - url: '/wp-login.php', - }); await playground.request({ url: '/wp-login.php', }); - console.log('after request'); await playground.request({ url: '/wp-login.php', diff --git a/packages/playground/client/src/index.ts b/packages/playground/client/src/index.ts index fb51565714..fc132d12bd 100644 --- a/packages/playground/client/src/index.ts +++ b/packages/playground/client/src/index.ts @@ -108,21 +108,15 @@ async function doStartPlaygroundWeb( // Connect the Comlink client and wait until the // playground is ready. - console.log('Pre consume API'); const playground = consumeAPI( iframe.contentWindow! ) as PlaygroundClient; - console.log('Post consume API'); await playground.isConnected(); - console.log('isConnected()'); progressTracker.pipe(playground); const downloadPHPandWP = progressTracker.stage(); await playground.onDownloadProgress(downloadPHPandWP.loadingListener); - console.log('downloadProgress()'); await playground.isReady(); - console.log('ready()'); downloadPHPandWP.finish(); - console.log('finish()'); return playground; } diff --git a/packages/playground/remote/project.json b/packages/playground/remote/project.json index 1512f90179..15085c5793 100644 --- a/packages/playground/remote/project.json +++ b/packages/playground/remote/project.json @@ -28,7 +28,8 @@ }, "development-for-website": { "buildTarget": "playground-remote:build:development", - "hmr": true + "hmr": true, + "logLevel": "silent" }, "production": { "buildTarget": "playground-remote:build:production", diff --git a/packages/playground/remote/service-worker.ts b/packages/playground/remote/service-worker.ts index bc3ad5391c..81ff1d62ac 100644 --- a/packages/playground/remote/service-worker.ts +++ b/packages/playground/remote/service-worker.ts @@ -4,11 +4,12 @@ declare const self: ServiceWorkerGlobalScope; import { getURLScope, removeURLScope } from '@php-wasm/scopes'; import { + awaitReply, convertFetchEventToPHPRequest, initializeServiceWorker, seemsLikeAPHPRequestHandlerPath, cloneRequest, - broadcastMessageAwaitReply, + broadcastMessageExpectReply, } from '@php-wasm/web-service-worker'; import { isUploadedFilePath } from './src/lib/is-uploaded-file-path'; @@ -104,12 +105,13 @@ async function rewriteRequest( async function getScopedWpDetails(scope: string): Promise { if (!scopeToWpModule[scope]) { - scopeToWpModule[scope] = await broadcastMessageAwaitReply( + const requestId = await broadcastMessageExpectReply( { method: 'getWordPressModuleDetails', }, scope ); + scopeToWpModule[scope] = await awaitReply(self, requestId); } return scopeToWpModule[scope]; } diff --git a/packages/playground/remote/src/lib/boot-playground-remote.ts b/packages/playground/remote/src/lib/boot-playground-remote.ts index 3331c8a6bc..5ad0246719 100644 --- a/packages/playground/remote/src/lib/boot-playground-remote.ts +++ b/packages/playground/remote/src/lib/boot-playground-remote.ts @@ -162,7 +162,7 @@ export async function bootPlaygroundRemote() { serviceWorkerVersion ); setupPostMessageRelay(wpFrame, getOrigin(await playground.absoluteUrl)); - // wpFrame.src = await playground.pathToInternalUrl('/'); + wpFrame.src = await playground.pathToInternalUrl('/'); setAPIReady(); diff --git a/packages/playground/website/project.json b/packages/playground/website/project.json index 7b1f5da520..4ed4832499 100644 --- a/packages/playground/website/project.json +++ b/packages/playground/website/project.json @@ -47,7 +47,7 @@ "options": { "commands": [ "nx dev playground-remote --configuration=development-for-website", - "sleep 1; nx dev:standalone playground-website --hmr --output-style=stream-without-prefixes" + "nx dev:standalone playground-website --hmr --output-style=stream-without-prefixes" ], "parallel": true, "color": true