Skip to content

Commit 86d9414

Browse files
authored
Make Client.postMessage to unloaded client not throw (#1293)
cf834f0 clarified the target object can be null, and it must throw in that case. But #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.
1 parent b3a1328 commit 86d9414

File tree

2 files changed

+32
-24
lines changed

2 files changed

+32
-24
lines changed

docs/index.bs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,19 +1071,23 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
10711071

10721072
The <dfn method for="Client"><code>postMessage(|message|, |options|)</code></dfn> method *must* run these steps:
10731073

1074-
1. Let |sourceSettings| be the <a>context object</a>'s <a>relevant settings object</a>.
1075-
1. Let |destination| be the {{ServiceWorkerContainer}} object whose [=ServiceWorkerContainer/service worker client=] is the <a>context object</a>'s [=Client/service worker client=], or null if no match is found.
1076-
1. If |destination| is null, <a>throw</a> an "{{InvalidStateError}}" {{DOMException}}.
1074+
1. Let |sourceSettings| be the [=context object=]'s [=relevant settings object=].
10771075
1. Let |serializeWithTransferResult| be <a abstract-op>StructuredSerializeWithTransfer</a>(|message|, |options|.transfer). Rethrow any exceptions.
1078-
1. Add a <a>task</a> that runs the following steps to |destination|'s [=ServiceWorkerContainer/client message queue=]:
1079-
1. Let |origin| be the [=Unicode serialization of an origin|Unicode serialization=] of |sourceSettings|'s [=environment settings object/origin=].
1080-
1. Let |source| be a {{ServiceWorker}} object, which represents the [=ServiceWorkerGlobalScope/service worker=] associated with |sourceSettings|'s [=environment settings object/global object=].
1081-
1. Let |deserializeRecord| be <a abstract-op>StructuredDeserializeWithTransfer</a>(|serializeWithTransferResult|, |destination|'s [=relevant Realm=]).
1082-
1083-
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.
1084-
1. Let |messageClone| be |deserializeRecord|.\[[Deserialized]].
1085-
1. Let |newPorts| be a new [=frozen array type|frozen array=] consisting of all {{MessagePort}} objects in |deserializeRecord|.\[[TransferredValues]], if any.
1086-
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|.
1076+
1. Run the following steps [=in parallel=]:
1077+
1. Let |targetClient| be null.
1078+
1. For each [=/service worker client=] |client|:
1079+
1. If |client| is the [=context object=]'s [=Client/service worker client=], set |targetClient| to |client|, and [=break=].
1080+
1. If |targetClient| is null, return.
1081+
1. Let |destination| be the {{ServiceWorkerContainer}} object whose associated [=ServiceWorkerContainer/service worker client=] is |targetClient|.
1082+
1. Add a [=task=] that runs the following steps to |destination|'s [=ServiceWorkerContainer/client message queue=]:
1083+
1. Let |origin| be the [=Unicode serialization of an origin|Unicode serialization=] of |sourceSettings|'s [=environment settings object/origin=].
1084+
1. Let |source| be a {{ServiceWorker}} object, which represents the [=ServiceWorkerGlobalScope/service worker=] associated with |sourceSettings|'s [=environment settings object/global object=].
1085+
1. Let |deserializeRecord| be <a abstract-op>StructuredDeserializeWithTransfer</a>(|serializeWithTransferResult|, |destination|'s [=relevant Realm=]).
1086+
1087+
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.
1088+
1. Let |messageClone| be |deserializeRecord|.\[[Deserialized]].
1089+
1. Let |newPorts| be a new [=frozen array type|frozen array=] consisting of all {{MessagePort}} objects in |deserializeRecord|.\[[TransferredValues]], if any.
1090+
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|.
10871091
</section>
10881092

10891093
<section>

docs/v1/index.bs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -983,19 +983,23 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
983983

984984
The <dfn method for="Client"><code>postMessage(|message|, |transfer|)</code></dfn> method *must* run these steps:
985985

986-
1. Let |sourceSettings| be the <a>context object</a>'s <a>relevant settings object</a>.
987-
1. Let |destination| be the {{ServiceWorkerContainer}} object whose [=ServiceWorkerContainer/service worker client=] is the <a>context object</a>'s [=Client/service worker client=], or null if no match is found.
988-
1. If |destination| is null, <a>throw</a> an "{{InvalidStateError}}" {{DOMException}}.
986+
1. Let |sourceSettings| be the [=context object=]'s [=relevant settings object=].
989987
1. Let |serializeWithTransferResult| be <a abstract-op>StructuredSerializeWithTransfer</a>(|message|, |transfer|). Rethrow any exceptions.
990-
1. Add a <a>task</a> that runs the following steps to |destination|'s [=ServiceWorkerContainer/client message queue=]:
991-
1. Let |origin| be the [=Unicode serialization of an origin|Unicode serialization=] of |sourceSettings|'s [=environment settings object/origin=].
992-
1. Let |source| be a {{ServiceWorker}} object, which represents the [=ServiceWorkerGlobalScope/service worker=] associated with |sourceSettings|'s [=environment settings object/global object=].
993-
1. Let |deserializeRecord| be <a abstract-op>StructuredDeserializeWithTransfer</a>(|serializeWithTransferResult|, |destination|'s [=relevant Realm=]).
994-
995-
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.
996-
1. Let |messageClone| be |deserializeRecord|.\[[Deserialized]].
997-
1. Let |newPorts| be a new [=frozen array type|frozen array=] consisting of all {{MessagePort}} objects in |deserializeRecord|.\[[TransferredValues]], if any.
998-
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|.
988+
1. Run the following steps [=in parallel=]:
989+
1. Let |targetClient| be null.
990+
1. For each [=/service worker client=] |client|:
991+
1. If |client| is the [=context object=]'s [=Client/service worker client=], set |targetClient| to |client|, and [=break=].
992+
1. If |targetClient| is null, return.
993+
1. Let |destination| be the {{ServiceWorkerContainer}} object whose associated [=ServiceWorkerContainer/service worker client=] is |targetClient|.
994+
1. Add a [=task=] that runs the following steps to |destination|'s [=ServiceWorkerContainer/client message queue=]:
995+
1. Let |origin| be the [=Unicode serialization of an origin|Unicode serialization=] of |sourceSettings|'s [=environment settings object/origin=].
996+
1. Let |source| be a {{ServiceWorker}} object, which represents the [=ServiceWorkerGlobalScope/service worker=] associated with |sourceSettings|'s [=environment settings object/global object=].
997+
1. Let |deserializeRecord| be <a abstract-op>StructuredDeserializeWithTransfer</a>(|serializeWithTransferResult|, |destination|'s [=relevant Realm=]).
998+
999+
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.
1000+
1. Let |messageClone| be |deserializeRecord|.\[[Deserialized]].
1001+
1. Let |newPorts| be a new [=frozen array type|frozen array=] consisting of all {{MessagePort}} objects in |deserializeRecord|.\[[TransferredValues]], if any.
1002+
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|.
9991003
</section>
10001004

10011005
<section>

0 commit comments

Comments
 (0)