From e89627f3e06deb664ac23406e88806d6d49127b1 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Fri, 10 Jul 2020 17:19:28 -0400 Subject: [PATCH 1/3] Change MessagePort owner from incumbent to current The "owner" of a MessagePort is set a lot, but only *used* for determining what document (if any) should be associated with that MessagePort's tasks. I.e., it ensures that when that document becomes not-fully-active, the tasks are not run. Tests [1] show that the use of incumbent settings object for the owner of MessageChannel-created MessagePorts was incorrect. In fact, the current settings object is used. This allows for a dramatic simplification, as it means that the MessagePort's owner is always equal to its relevant settings object. Thus, we can entirely delete the owner concept, and the associated specialized "create a new MessagePort object" algorithm. This does require tweaking the examples of how the incumbent concept works, now that a simple constructor is no longer available to demonstrate the point. This also modernizes the definition of MessageChannel. Closes #4340. Helps with #1430. [1]: https://github.com/web-platform-tests/wpt/pull/24566 --- source | 207 +++++++++++++++++++++++++++------------------------------ 1 file changed, 99 insertions(+), 108 deletions(-) diff --git a/source b/source index 1e6cb4bad30..290c0624b94 100644 --- a/source +++ b/source @@ -2644,6 +2644,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
  • callback context
  • frozen array and creating a frozen array
  • +
  • create a new object implementing the interface
  • callback this value
  • converting between Web IDL types and JS types
  • invoking and @@ -87795,33 +87796,50 @@ interface ApplicationCache : EventTarget {

    The following series of examples is intended to make it clear how all of the different mechanisms contribute to the definition of the incumbent concept:

    -
    -

    Consider the following very simple example:

    +
    +

    Consider the following starter example:

    <!DOCTYPE html>
     <iframe></iframe>
     <script>
    -  new frames[0].MessageChannel();
    +  frames[0].postMessage("some data", "*");
     </script>
    -

    When the MessageChannel() constructor looks up the - incumbent settings object to use as the owner of the new MessagePort objects, the - topmost script-having execution context will be that corresponding to the - script element: it was pushed onto the JavaScript execution context - stack as part of ScriptEvaluation during the - run a classic script algorithm. Since there are no Web IDL callback invocations - involved, the context's skip-when-determining-incumbent counter is zero, so it is - used to determine the incumbent settings object; the result is the environment - settings object of window.

    +

    There are two interesting environment settings + objects here: that of window, and that of frames[0]. Our concern is: what is the incumbent settings object at + the time that the algorithm for postMessage() + executes?

    + +

    It should be that of window, to capture the intuitive notion that the + author script responsible for causing the algorithm to happen is executing in window, not frames[0]. This makes sense: the window + post message steps use the incumbent settings object to determine the source property of the resulting + MessageEvent, and in this case window is definitely the + source of the message.

    + +

    Let us now explain how the steps given above give us our intuitively-desired result of window's relevant settings object.

    + +

    When the window post message steps look up the incumbent settings + object, the topmost script-having execution context will be that + corresponding to the script element: it was pushed onto the JavaScript + execution context stack as part of ScriptEvaluation during the run a classic script + algorithm. Since there are no Web IDL callback invocations involved, the context's + skip-when-determining-incumbent counter is zero, so it is used to determine the + incumbent settings object; the result is the environment settings + object of window.

    -

    (In this example, the environment settings object of frames[0] is not involved at all. It is the current settings - object, but the MessageChannel() constructor - cares only about the incumbent, not current.)

    +

    (Note how the environment settings object of frames[0] is + the relevant settings object of this at the time the postMessage() method is called, and thus is involved in + figuring out the target of the message. Whereas the incumbent is used for figuring out + the source.)

    -
    +

    Consider the following more complicated example:

    <!DOCTYPE html>
    @@ -87831,25 +87849,17 @@ interface ApplicationCache : EventTarget {
       window.setTimeout(bound);
     </script>
    -

    There are two interesting environment settings - objects here: that of window, and that of frames[0]. Our concern is: what is the incumbent settings object at - the time that the algorithm for postMessage() - executes?

    - -

    It should be that of window, to capture the intuitive notion that the - author script responsible for causing the algorithm to happen is executing in window, not frames[0]. Another way of capturing the - intuition here is that invoking algorithms asynchronously (in this case via setTimeout()) should not change the This example is very similar to the previous one, but with an extra indirection through Function.prototype.bind as well as setTimeout(). But, the answer should be the same: invoking + algorithms asynchronously should not change the incumbent concept.

    -

    Let us now explain how the steps given above give us our intuitively-desired result of window's relevant settings object.

    +

    This time, the result involves more complicated mechanisms:

    When bound is converted to a Web IDL callback type, the incumbent settings object is that corresponding to window (in the same manner as in our simple example above). Web IDL stores this + data-x="">window (in the same manner as in our starter example above). Web IDL stores this as the resulting callback value's callback context.

    When the task posted by ApplicationCache : EventTarget { algorithm.

    -
    +

    Consider this final, even more convoluted example:

    <!-- a.html -->
    @@ -87888,9 +87898,9 @@ interface ApplicationCache : EventTarget {
     <script>
     const bound = frames[0].location.assign.bind(frames[0].location, "https://example.com/");
     document.querySelector("button").addEventListener("click", bound);
    -</script>
    +</script>
    -<!-- b.html --> +
    <!-- b.html -->
     <!DOCTYPE html>
     <iframe src="a.html"></iframe>
     <script>
    @@ -92871,8 +92881,8 @@ enum DOMParserSupportedType {
     
       
    -

    The DOMParser() constructor steps - are to do nothing.

    +

    The new DOMParser() constructor + steps are to do nothing.

    The parseFromString(string, type) method steps are:

    @@ -97700,35 +97710,30 @@ interface MessageChannel {
    -

    When the MessageChannel() constructor is - called, it must run the following algorithm:

    - -
      -
    1. Create a new MessagePort object whose owner is the incumbent settings object, and let - port1 be that object.

    2. - -
    3. Create a new MessagePort object whose owner is the incumbent settings object, and let - port2 be that object.

    4. +

      A MessageChannel object has an associated port 1 and an associated + port 2, both MessagePort objects.

      -
    5. Entangle the port1 and port2 objects.

    6. - -
    7. Instantiate a new MessageChannel object, and let channel be that - object.

    8. +

      The new MessageChannel() constructor steps + are:

      -
    9. Let the port1 attribute of the - channel object be port1.

      +
        +
      1. Set this's port 1 to a new + MessagePort in the current + Realm.

      2. -
      3. Let the port2 attribute of the - channel object be port2.

        +
      4. Set this's port 2 to a new + MessagePort in the current + Realm.

      5. -
      6. Return channel.

      7. +
      8. Entangle this's port 1 and this's + port 2.

      -

      The port1 and port2 attributes must return the values they were - assigned when the MessageChannel object was created.

      +

      The port1 getter steps are to return + this's port 1.

      + +

      The port2 getter steps are to return + this's port 2.

    @@ -97782,29 +97787,28 @@ dictionary PostMessageOptions { disabled, and is initially disabled. Once enabled, a port can never be disabled again (though messages in the queue can get moved to another queue or removed altogether, which has much the same effect). A MessagePort also has a has been shipped flag, which must - initially be false, and an owner, which is a settings - object set when the object is created, as described below.

    + initially be false.

    When a port's port message queue is enabled, the event loop must use - it as one of its task sources. When a port's owner's responsible event loop is a window - event loop, all tasks queued on its port message queue must be associated with the port's - owner's responsible document.

    - -

    If the port's owner's responsible - document is fully active, but the event listeners all have scripts whose settings objects specify responsible documents that are not fully active, then the - messages will be lost.

    + it as one of its task sources. When a port's relevant + global object is a Window, all tasks queued on its port message queue must be associated with + the port's relevant global object's associated + Document.

    + +

    If the document is fully active, but the event listeners all have + scripts whose settings objects specify responsible documents that are not fully + active, then the messages will be lost.

    Each event loop has a task source called the unshipped port message queue. This is a virtual task source: it must act as if it contained the tasks of each port message queue of each MessagePort whose has been shipped flag is false, whose port - message queue is enabled, and whose owner's - responsible event loop is that event loop, in the order in which they - were added to their respective task source. When a is enabled, and whose relevant agent's event loop is that event loop, in the order + in which they were added to their respective task source. When a task would be removed from the unshipped port message queue, it must instead be removed from its port message queue.

    @@ -97818,11 +97822,6 @@ dictionary PostMessageOptions { first-class task source, unaffected to any unshipped port message queue.

    -

    When the user agent is to create a new MessagePort object with a - particular environment settings object as its owner, it must instantiate - a new MessagePort object, and let its owner - be owner.

    -

    When the user agent is to entangle two MessagePort objects, it must run the following steps:

    @@ -97881,18 +97880,13 @@ dictionary PostMessageOptions {
    1. Set value's has been shipped flag to true.

    2. -
    3. Set value's owner to value's relevant settings - object.

    4. -
    5. Move all the tasks that are to fire message events in dataHolder.[[PortMessageQueue]] to the - port message queue of value, if any, leaving - value's port message queue in its initial disabled state, and, if - value's owner's responsible event - loop is a window event loop, associating the moved tasks with value's owner's responsible document.

    6. + port message queue of value, if any, leaving value's + port message queue in its initial disabled state, and, if value's + relevant global object is a Window, associating the moved tasks with value's relevant global object's + associated Document.

    7. If dataHolder.[[RemotePort]] is not null, then entangle dataHolder.[[RemotePort]] and value. (This will disentangle @@ -98057,11 +98051,10 @@ dictionary PostMessageOptions {

      -

      When a MessagePort object o is entangled, user agents must - either act as if o's entangled MessagePort object has a strong - reference to o, or as if the global - object specified by o's owner has a - strong reference to o.

      +

      When a MessagePort object o is entangled, user agents must either act + as if o's entangled MessagePort object has a strong reference to + o, or as if o's relevant global object has a strong reference + to o.

      @@ -99311,9 +99304,9 @@ interface SharedWorkerGlobalScope : WorkerGlobalScope {
    8. Associate worker with worker global scope.

    9. -
    10. Create a new MessagePort object whose owner is inside settings. Let inside - port be this new object.

    11. +
    12. Let inside port be a new MessagePort object in + inside settings's Realm.

    13. Associate inside port with worker global scope.

    14. @@ -99738,9 +99731,8 @@ enum WorkerType { "classic", "module" };
    15. Let worker be a new Worker object.

    16. -
    17. Create a new MessagePort object whose owner is outside settings. Let this be the - outside port.

    18. +
    19. Let outside port be a new MessagePort in outside + settings's Realm.

    20. Associate the outside port with worker.

    21. @@ -99838,9 +99830,8 @@ interface SharedWorker : EventTarget {
    22. Let worker be a new SharedWorker object.

    23. -
    24. Create a new MessagePort object whose owner is outside settings. Let this be the - outside port.

    25. +
    26. Let outside port be a new MessagePort in outside + settings's Realm.

    27. Assign outside port to the port attribute of worker.

    28. @@ -99912,9 +99903,9 @@ interface SharedWorker : EventTarget {
    29. Associate worker with worker global scope.

    30. -
    31. Create a new MessagePort object whose owner is settings object. Let this be - the inside port.

    32. +
    33. Let inside port be a new MessagePort in + settings object's Realm.

    34. Entangle outside port and inside port.

    35. From 86557d47258e1c332154608ecb1fcd9bfeb53ffa Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Mon, 13 Jul 2020 12:11:05 -0400 Subject: [PATCH 2/3] Easy fixes --- source | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source b/source index 290c0624b94..d6e51d79a13 100644 --- a/source +++ b/source @@ -87835,8 +87835,8 @@ interface ApplicationCache : EventTarget {

      (Note how the environment settings object of frames[0] is the relevant settings object of this at the time the postMessage() method is called, and thus is involved in - figuring out the target of the message. Whereas the incumbent is used for figuring out - the source.) + determining the target of the message. Whereas the incumbent is used to determine the + source.)

    @@ -97799,8 +97799,8 @@ dictionary PostMessageOptions {

    If the document is fully active, but the event listeners all have scripts whose settings objects specify responsible documents that are not fully - active, then the messages will be lost.

    + active, then the messages will not be recieved unless and until the documents become + fully active again.

    Each event loop has a task source called the unshipped port message queue. This is a virtual task source: it must act as if it contained From 9158c6a2d1014bb7c740ce25246eb1a8fcac59eb Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Mon, 13 Jul 2020 13:41:46 -0400 Subject: [PATCH 3/3] relevant realm instead --- source | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source b/source index d6e51d79a13..d08d40db7ba 100644 --- a/source +++ b/source @@ -97718,11 +97718,11 @@ interface MessageChannel {

    1. Set this's port 1 to a new - MessagePort in the current + MessagePort in this's relevant Realm.

    2. Set this's port 2 to a new - MessagePort in the current + MessagePort in this's relevant Realm.

    3. Entangle this's port 1 and this's