From 86d941499aee42c701b1d6dfc8dab1eeda5ef526 Mon Sep 17 00:00:00 2001 From: Jungkee Song Date: Tue, 28 May 2019 08:36:43 -0700 Subject: [PATCH] Make Client.postMessage to unloaded client not throw (#1293) https://github.com/w3c/ServiceWorker/commit/cf834f052bc0aed0795fbf29cbf1c6f251dd5c9d clarified the target object can be null, and it must throw in that case. But https://github.com/w3c/ServiceWorker/issues/1291 pointed out that we cannot implement that behavior without blocking the service worker process in multi-process browser architectures. This change makes the control return right away if the target client has been unloaded. Fixes #1291. --- docs/index.bs | 28 ++++++++++++++++------------ docs/v1/index.bs | 28 ++++++++++++++++------------ 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/docs/index.bs b/docs/index.bs index ef04a53c..269d4cf0 100644 --- a/docs/index.bs +++ b/docs/index.bs @@ -1071,19 +1071,23 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe The postMessage(|message|, |options|) method *must* run these steps: - 1. Let |sourceSettings| be the context object's relevant settings object. - 1. Let |destination| be the {{ServiceWorkerContainer}} object whose [=ServiceWorkerContainer/service worker client=] is the context object's [=Client/service worker client=], or null if no match is found. - 1. If |destination| is null, throw an "{{InvalidStateError}}" {{DOMException}}. + 1. Let |sourceSettings| be the [=context object=]'s [=relevant settings object=]. 1. Let |serializeWithTransferResult| be StructuredSerializeWithTransfer(|message|, |options|.transfer). Rethrow any exceptions. - 1. Add a task that runs the following steps to |destination|'s [=ServiceWorkerContainer/client message queue=]: - 1. Let |origin| be the [=Unicode serialization of an origin|Unicode serialization=] of |sourceSettings|'s [=environment settings object/origin=]. - 1. Let |source| be a {{ServiceWorker}} object, which represents the [=ServiceWorkerGlobalScope/service worker=] associated with |sourceSettings|'s [=environment settings object/global object=]. - 1. Let |deserializeRecord| be StructuredDeserializeWithTransfer(|serializeWithTransferResult|, |destination|'s [=relevant Realm=]). - - If this throws an exception, catch it, [=fire an event=] named {{messageerror!!event}} at |destination|, using {{MessageEvent}}, with the {{MessageEvent/origin}} attribute initialized to |origin| and the {{MessageEvent/source}} attribute initialized to |source|, and then abort these steps. - 1. Let |messageClone| be |deserializeRecord|.\[[Deserialized]]. - 1. Let |newPorts| be a new [=frozen array type|frozen array=] consisting of all {{MessagePort}} objects in |deserializeRecord|.\[[TransferredValues]], if any. - 1. [=Dispatch|Dispatch an event=] named {{Window/message!!event}} at |destination|, using {{MessageEvent}}, with the {{MessageEvent/origin}} attribute initialized to |origin|, the {{MessageEvent/source}} attribute initialized to |source|, the {{MessageEvent/data}} attribute initialized to |messageClone|, and the {{MessageEvent/ports}} attribute initialized to |newPorts|. + 1. Run the following steps [=in parallel=]: + 1. Let |targetClient| be null. + 1. For each [=/service worker client=] |client|: + 1. If |client| is the [=context object=]'s [=Client/service worker client=], set |targetClient| to |client|, and [=break=]. + 1. If |targetClient| is null, return. + 1. Let |destination| be the {{ServiceWorkerContainer}} object whose associated [=ServiceWorkerContainer/service worker client=] is |targetClient|. + 1. Add a [=task=] that runs the following steps to |destination|'s [=ServiceWorkerContainer/client message queue=]: + 1. Let |origin| be the [=Unicode serialization of an origin|Unicode serialization=] of |sourceSettings|'s [=environment settings object/origin=]. + 1. Let |source| be a {{ServiceWorker}} object, which represents the [=ServiceWorkerGlobalScope/service worker=] associated with |sourceSettings|'s [=environment settings object/global object=]. + 1. Let |deserializeRecord| be StructuredDeserializeWithTransfer(|serializeWithTransferResult|, |destination|'s [=relevant Realm=]). + + If this throws an exception, catch it, [=fire an event=] named {{messageerror!!event}} at |destination|, using {{MessageEvent}}, with the {{MessageEvent/origin}} attribute initialized to |origin| and the {{MessageEvent/source}} attribute initialized to |source|, and then abort these steps. + 1. Let |messageClone| be |deserializeRecord|.\[[Deserialized]]. + 1. Let |newPorts| be a new [=frozen array type|frozen array=] consisting of all {{MessagePort}} objects in |deserializeRecord|.\[[TransferredValues]], if any. + 1. [=Dispatch|Dispatch an event=] named {{Window/message!!event}} at |destination|, using {{MessageEvent}}, with the {{MessageEvent/origin}} attribute initialized to |origin|, the {{MessageEvent/source}} attribute initialized to |source|, the {{MessageEvent/data}} attribute initialized to |messageClone|, and the {{MessageEvent/ports}} attribute initialized to |newPorts|.
diff --git a/docs/v1/index.bs b/docs/v1/index.bs index d3545541..b3c7c7f8 100644 --- a/docs/v1/index.bs +++ b/docs/v1/index.bs @@ -983,19 +983,23 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe The postMessage(|message|, |transfer|) method *must* run these steps: - 1. Let |sourceSettings| be the context object's relevant settings object. - 1. Let |destination| be the {{ServiceWorkerContainer}} object whose [=ServiceWorkerContainer/service worker client=] is the context object's [=Client/service worker client=], or null if no match is found. - 1. If |destination| is null, throw an "{{InvalidStateError}}" {{DOMException}}. + 1. Let |sourceSettings| be the [=context object=]'s [=relevant settings object=]. 1. Let |serializeWithTransferResult| be StructuredSerializeWithTransfer(|message|, |transfer|). Rethrow any exceptions. - 1. Add a task that runs the following steps to |destination|'s [=ServiceWorkerContainer/client message queue=]: - 1. Let |origin| be the [=Unicode serialization of an origin|Unicode serialization=] of |sourceSettings|'s [=environment settings object/origin=]. - 1. Let |source| be a {{ServiceWorker}} object, which represents the [=ServiceWorkerGlobalScope/service worker=] associated with |sourceSettings|'s [=environment settings object/global object=]. - 1. Let |deserializeRecord| be StructuredDeserializeWithTransfer(|serializeWithTransferResult|, |destination|'s [=relevant Realm=]). - - If this throws an exception, catch it, [=fire an event=] named {{messageerror!!event}} at |destination|, using {{MessageEvent}}, with the {{MessageEvent/origin}} attribute initialized to |origin| and the {{MessageEvent/source}} attribute initialized to |source|, and then abort these steps. - 1. Let |messageClone| be |deserializeRecord|.\[[Deserialized]]. - 1. Let |newPorts| be a new [=frozen array type|frozen array=] consisting of all {{MessagePort}} objects in |deserializeRecord|.\[[TransferredValues]], if any. - 1. [=Dispatch|Dispatch an event=] named {{Window/message!!event}} at |destination|, using {{MessageEvent}}, with the {{MessageEvent/origin}} attribute initialized to |origin|, the {{MessageEvent/source}} attribute initialized to |source|, the {{MessageEvent/data}} attribute initialized to |messageClone|, and the {{MessageEvent/ports}} attribute initialized to |newPorts|. + 1. Run the following steps [=in parallel=]: + 1. Let |targetClient| be null. + 1. For each [=/service worker client=] |client|: + 1. If |client| is the [=context object=]'s [=Client/service worker client=], set |targetClient| to |client|, and [=break=]. + 1. If |targetClient| is null, return. + 1. Let |destination| be the {{ServiceWorkerContainer}} object whose associated [=ServiceWorkerContainer/service worker client=] is |targetClient|. + 1. Add a [=task=] that runs the following steps to |destination|'s [=ServiceWorkerContainer/client message queue=]: + 1. Let |origin| be the [=Unicode serialization of an origin|Unicode serialization=] of |sourceSettings|'s [=environment settings object/origin=]. + 1. Let |source| be a {{ServiceWorker}} object, which represents the [=ServiceWorkerGlobalScope/service worker=] associated with |sourceSettings|'s [=environment settings object/global object=]. + 1. Let |deserializeRecord| be StructuredDeserializeWithTransfer(|serializeWithTransferResult|, |destination|'s [=relevant Realm=]). + + If this throws an exception, catch it, [=fire an event=] named {{messageerror!!event}} at |destination|, using {{MessageEvent}}, with the {{MessageEvent/origin}} attribute initialized to |origin| and the {{MessageEvent/source}} attribute initialized to |source|, and then abort these steps. + 1. Let |messageClone| be |deserializeRecord|.\[[Deserialized]]. + 1. Let |newPorts| be a new [=frozen array type|frozen array=] consisting of all {{MessagePort}} objects in |deserializeRecord|.\[[TransferredValues]], if any. + 1. [=Dispatch|Dispatch an event=] named {{Window/message!!event}} at |destination|, using {{MessageEvent}}, with the {{MessageEvent/origin}} attribute initialized to |origin|, the {{MessageEvent/source}} attribute initialized to |source|, the {{MessageEvent/data}} attribute initialized to |messageClone|, and the {{MessageEvent/ports}} attribute initialized to |newPorts|.