From 6399af334edd6000bd394685923df5f0519194ab Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Mon, 2 May 2016 17:09:12 -0400 Subject: [PATCH] Add a new section detailing the various potential realms This adds a new section under scripts detailing the entry, incumbent, current, and relevant concepts with regard to realms/global objects/ environment settings objects. This centralizes information that was previously somewhat spread out, and adds lots of details, as well as an example. This takes care of some of the pain points noted in #473, in particular fixing the definition of entry settings object to be more clearly defined in terms of the JavaScript execution context stack. There is still some work to do in that issue: namely, updating Web IDL with regard to tracking the entry settings object, and also making sure that incumbent settings object is correctly defined. This closes #167 by finally implementing the plan in https://github.com/whatwg/html/issues/167#issuecomment-195478361 for making the correspondences clear. --- source | 410 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 296 insertions(+), 114 deletions(-) diff --git a/source b/source index 03b99205161..be99ee65fa7 100644 --- a/source +++ b/source @@ -3327,6 +3327,17 @@ a.setAttribute('href', 'http://example.com/'); // change the content attribute d +
Battery Status
+ +
+ +

The following features are defined in the Battery Status API specification:

+ + + +
@@ -86906,52 +86917,6 @@ interface NavigatorOnLine { implementations are free to limit its size, e.g. by removing old entries from it when new ones are added.

-
- -

A global object is a JavaScript object that is the [[GlobalObject]] field of a - JavaScript realm.

- -

In this specification, all JavaScript - realms are initialized with global objects that are either Window or - WorkerGlobalScope objects.

- -

There is always a 1:1:1 mapping between JavaScript - realms, global objects, and environment settings objects:

- - - -

The relevant settings object for a non-global platform object - o is the environment settings object whose global object is the global object of the - global environment associated with o.

- -
Fetching scripts

The various script-fetching algorithms below have two hooks that may be customized by their @@ -87357,7 +87322,7 @@ interface NavigatorOnLine { -

Calling scripts
+
Calling scripts

To run a classic script given a classic script s and an optional rethrow errors flag:

@@ -87480,7 +87445,8 @@ interface NavigatorOnLine {
    -
  1. Label settings as a candidate entry settings object.

  2. +
  3. Increment settings's realm execution context's entrance + counter by one.

  4. Push settings's realm execution context onto the JavaScript execution context stack; it is now the running JavaScript execution @@ -87494,12 +87460,12 @@ interface NavigatorOnLine {

      -
    1. Stop labeling settings as a candidate entry settings - object.

    2. -
    3. Assert: settings's realm execution context is the running JavaScript execution context.

    4. +
    5. Decrement settings's realm execution context's entrance + counter by one.

    6. +
    7. Remove settings's realm execution context from the JavaScript execution context stack.

    8. @@ -87521,18 +87487,240 @@ interface NavigatorOnLine {
      -

      A JavaScript execution context's settings object is the - settings object of the script in the [[HostDefined]] field in the - ScriptOrModule component of the given JavaScript execution context.

      +

      Each unit of related similar-origin browsing contexts has a global script + clean-up jobs list, which must initially be empty. A global script clean-up job cannot run + scripts, and cannot be sensitive to the order in which other clean-up jobs are executed. The File + API uses this to release blob: URLs.

      -

      The current settings object is the environment settings object of the current - Realm Record.

      +

      When the user agent is to run the global script clean-up jobs, the user agent must + perform each of the jobs in the global script clean-up jobs list and then empty the + list.

      -

      The entry settings object is the settings object of the topmost entry in the JavaScript execution - context stack whose settings object is labeled as a candidate entry settings object.

      +
      Realms, settings objects, and global objects
      + +

      A global object is a JavaScript object that is the [[GlobalObject]] field of a + JavaScript realm.

      + +

      In this specification, all JavaScript + realms are initialized with global objects that are either Window or + WorkerGlobalScope objects.

      + +

      There is always a 1:1:1 mapping between JavaScript + realms, global objects, and environment settings objects:

      + +
        +
      • A JavaScript realm has a [[HostDefined]] field, which contains the Realm's settings object.

      • + +
      • A JavaScript realm has a [[GlobalObject]] field, which contains the Realm's global object.

      • + +
      • Each global object in this specification is created during the initialization of a corresponding JavaScript + realm, known as the global object's + Realm.

      • + +
      • Each global object in this + specification is created alongside a corresponding environment settings object, + known as its relevant settings object.

        + +
      • An environment settings object's realm execution context's + Realm component is the environment settings + object's Realm.

      • + +
      • An environment settings object's Realm then has a [[GlobalObject]] field, which contains the environment settings object's global + object.

      • +
      + +
      + +

      When defining algorithm steps throughout this specification, it is often important to indicate + what JavaScript realm is to be used—or, equivalently, what global object + or settings object is to be used. In general, there are at least four + possibilities:

      + +
      +
      Entry
      +
      This corresponds to the script that initiated the currently running script action: i.e., + the function or script that the user agent called into when it called into author code.
      + +
      Incumbent
      +
      This corresponds to the most-recently-entered author function or script on the stack.
      + +
      Current
      +
      This corresponds to the currently-running function object, including built-in user-agent + functions which might not be implemented as JavaScript. (It is derived from the current + JavaScript realm.)
      + +
      Relevant
      +
      Every platform object has a relevant + Realm. When writing algorithms, the most prominent platform object whose + relevant Realm might be important is the + this value of the currently-running function object. In some cases, there can be other + important relevant Realms, such as those of any + arguments.
      +
      + +

      Note how the entry, incumbent, and current concepts are usable without qualification, + whereas the relevant concept must be applied to + a particular platform object.

      + +
      + +

      Consider the following pages, with a.html being loaded in a browser + window, b.html being loaded in an iframe as shown, and c.html and d.html omitted (they can simply be empty + documents):

      + +
      <!-- a.html -->
      +<!DOCTYPE html>
      +<html lang="en">
      +<title>Entry page</title>
      +
      +<iframe src="b.html"></iframe>
      +<button onclick="frames[0].hello()">Hello</button>
      +
      +<!--b.html -->
      +<!DOCTYPE html>
      +<html lang="en">
      +<title>Incumbent page</title>
      +
      +<iframe src="c.html" id="c"></iframe>
      +<iframe src="d.html" id="d"></iframe>
      +
      +<script>
      +  const c = document.querySelector("#c").contentWindow;
      +  const d = document.querySelector("#d").contentWindow;
      +
      +  window.hello = () => {
      +    c.print.call(d);
      +  };
      +</script>
      + +

      Each page has its own browsing context, and thus its own JavaScript + realm, global object, and settings object.

      + +

      When the print() method is called in response to pressing the + button in a.html, then:

      + +
        +
      • The entry Realm is that of a.html.

      • +
      • The incumbent Realm is that of b.html.

      • +
      • The current Realm is that of c.html (since it is the print() method from + c.html whose code is running).

      • +
      • The relevant Realm of the object on which + the print() method is being called is that of d.html.

      • +
      +
      + +

      The incumbent and entry concepts should not be used by new specifications, + and we are considering whether we can remove almost all existing uses. See Bugzilla bug 26603 for incumbent, and Bugzilla bug 27203 for entry.

      + +

      Currently, the incumbent + concept is used in some security checks, and the entry concept is sometimes used to obtain, amongst other + things, the API base URL to parse a URL, used in + scripts running in that unit of related similar-origin browsing contexts.

      + +

      In general, the current concept is what should + be used by specifications going forward. There is an important exception, however. If an algorithm + is creating an object that is to be persisted and returned multiple times (instead of simply + returned to author code right away, and never vended again), it should use the relevant concept with regard to the object on which + the method in question is being executed. This prevents cross-realm calls from causing an object + to store objects created in the "wrong" realm.

      + +
      +

      The navigator.getBattery() method creates + promises in the relevant Realm for the + Navigator object on which it is invoked. This has the following impact: + +

      <!-- outer.html -->
      +<!DOCTYPE html>
      +<html lang="en">
      +<title>Relevant Realm demo: outer page</title>
      +<script>
      +  function doTest() {
      +    const promise = navigator.getBattery.call(frames[0].navigator);
      +
      +    console.log(promise instanceof Promise);           // logs false
      +    console.log(promise instanceof frames[0].Promise); // logs true
      +
      +    frames[0].hello();
      +  }
      +</script>
      +<iframe src="inner.html" onload="doTest()"></iframe>
      +
      +<!-- inner.html -->
      +<!DOCTYPE html>
      +<html lang="en">
      +<title>Relevant Realm demo: inner page</title>
      +<script>
      +  function hello() {
      +    const promise = navigator.getBattery();
      +
      +    console.log(promise instanceof Promise);        // logs true
      +    console.log(promise instanceof parent.Promise); // logs false
      +  }
      +</script>
      + +

      If the algorithm for the getBattery() method + had instead used the current Realm, all the results + would be reversed. That is, after the first call to getBattery() in outer.html, the + Navigator object in inner.html would be permanently storing + a Promise object created in outer.html's + JavaScript realm, and calls like that inside the hello() + function would thus return a promise from the "wrong" realm. Since this is undesirable, the + algorithm instead uses the relevant Realm, giving + the sensible results indicated in the comments above.

      +
      + +
      + +

      The rest of this section deals with formally defining the entry, incumbent, current, and relevant concepts.

      + +
      Entry
      + +

      All realm execution contexts must contain, as + part of their code evaluation state, an entrance counter value, which is initially + zero. In the process of calling scripts, this value will be + incremented and decremented.

      + +

      With this in hand, we define the entry execution context to be the most recently + pushed entry in the JavaScript execution context stack whose entrance + counter value is greater than zero. The entry Realm + is the entry execution context's Realm component.

      + +

      Then, the entry settings object is the environment settings object of the entry Realm.

      + +

      Similarly, the entry global object is the global object of the entry + Realm.

      + +
      Incumbent

      The incumbent settings object is determined as follows:

      @@ -87546,69 +87734,59 @@ interface NavigatorOnLine { scriptOrModule's [[HostDefined]] field.

    -
    -

    The entry settings object is used to obtain, amongst other things, the API - base URL to parse a URL, used in scripts running in that - unit of related similar-origin browsing contexts.

    +

    Then, the incumbent Realm is the Realm of the incumbent settings + object.

    -

    The incumbent settings object is used in some security checks.

    -
    - -

    The incumbent settings object concept should not be used by new - specifications, and we are considering whether it can be removed from the platform. See Bugzilla bug 26603.

    +

    Similarly, the incumbent global object is the + global object of the incumbent + settings object.

    -
    +
    Current
    -

    Consider the following two pages, with the first being loaded in a browser window and the - second being loaded in the iframe of the first:

    +

    The JavaScript specification defines the current Realm Record, sometimes + abbreviated to "the current Realm".

    -
    <!-- a/a.html -->
    -<!DOCTYPE HTML>
    -<html lang="en">
    -<title>Outer page</title>
    -<iframe src="../b/b.html"></iframe>
    -<input type=button onclick="frames[0].hello()" value="Hello">
    +

    Then, the current settings object is the environment settings object of the current + Realm Record.

    -
    <!-- b/b.html -->
    -<!DOCTYPE HTML>
    -<html lang="en">
    -<title>Inner page</title>
    -<script>
    - function hello() {
    -   location.assign('c.html');
    - }
    -</script>
    +

    Similarly, the current global object is the global object of the current Realm Record.

    -

    When the button is pressed in the inner frame, the outer page runs script in the inner page. - While the hello() function is running, the entry settings - object is that of the outer file (a/a.html), and the - incumbent settings object is that of the inner file (b/b.html).

    +
    Relevant
    -

    The assign() method uses the entry settings - object to parse the URL, so we end up loading a/c.html, but it uses the incumbent settings object to establish - the source browsing context, from which the referrer is established, so the `Referer` header sent with the request for a/c.html specifies the inner file's URL (the one ending with b/b.html).

    +

    The relevant settings object for a platform object is defined as + follows:

    - +
    +
    If the object is a global object
    +
    Each global object in this specification is created alongside a corresponding + environment settings object; that is its relevant settings object.
    -
    +
    Otherwise
    +
    +

    The relevant settings object for a non-global platform object + o is the environment settings object whose global object is the global object of the + global environment associated with o.

    -
    +

    The "global environment associated with" concept is from the olden + days, before the modern JavaScript specification and its concept of realms. We expect that as the Web IDL specification gets updated, every + platform object will have a Realm associated + with it, and this definition can be re-cast in those terms.

    +
    + -

    Each unit of related similar-origin browsing contexts has a global script - clean-up jobs list, which must initially be empty. A global script clean-up job cannot run - scripts, and cannot be sensitive to the order in which other clean-up jobs are executed. The File - API uses this to release blob: URLs.

    +

    Then, the relevant Realm for a platform + object is the Realm of its + relevant settings object.

    -

    When the user agent is to run the global script clean-up jobs, the user agent must - perform each of the jobs in the global script clean-up jobs list and then empty the - list.

    +

    Similarly, the relevant global object for a + platform object is the global + object of its relevant settings object.

    Killing scripts
    @@ -87683,7 +87861,8 @@ interface NavigatorOnLine {
    1. Assert: queueName is "PromiseJobs". ("ScriptJobs" must not be used by user agents.)

    2. -
    3. Let settings be the current settings object.

    4. +
    5. Let settings be the settings + object of job.[[Realm]].

    6. Queue a microtask, on settings's responsible event loop, to perform the following steps:

      @@ -118564,6 +118743,9 @@ INSERT INTERFACES HERE
      [ATOM]
      (Non-normative) The Atom Syndication Format, M. Nottingham, R. Sayre. IETF.
      +
      [BATTERY]
      +
      (Non-normative) Battery Status API, A. Kostiainen, M. Lamouri. W3C.
      +
      [BCP47]
      Tags for Identifying Languages; Matching of Language Tags, A. Phillips, M. Davis. IETF.
      @@ -118589,7 +118771,7 @@ INSERT INTERFACES HERE
      Unicode Common Locale Data Repository. Unicode.
      [COMPOSITE]
      -
      Compositing and Blending. R. Cabanier, N. Andronikos. W3C.
      +
      Compositing and Blending, R. Cabanier, N. Andronikos. W3C.
      [COMPUTABLE]
      (Non-normative) On computable numbers, with an application to the Entscheidungsproblem, A. Turing. In Proceedings of the London Mathematical Society, series 2, volume 42, pages 230-265. London Mathematical Society, 1937.