From c0a7bb5aba676466943a3d645e42a12f10e04b99 Mon Sep 17 00:00:00 2001 From: Simon Pieters Date: Tue, 5 May 2020 14:26:42 +0200 Subject: [PATCH 01/14] Check intersection of lazy images from "update the rendering" Fixes #5236. --- source | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/source b/source index addfb3a9d48..2ec68af6bed 100644 --- a/source +++ b/source @@ -27456,12 +27456,7 @@ was an English <a href="/wiki/Music_hall">music hall</a> singer, ...

If img's lazy loading attribute is in the Lazy state, img does not intersect the - viewport, and img is not about to intersect the viewport, then - return true.

- -

This allows for fetching the image during scrolling, when it does not, but is - about to intersect the viewport.

+ data-x="attr-loading-lazy-state">Lazy state, then return true.

  • Return false.

  • @@ -27471,6 +27466,45 @@ was an English <a href="/wiki/Music_hall">music hall</a> singer, ...in parallel, it needs to queue a task to do so.

    +

    Each img element have a boolean flag ready to be lazy loaded, initially + false.

    + +

    For img elements that will + lazy load, this flag can be set to true in the update the rendering steps, + which causes the image to load by continuing the update the image data steps.

    + +

    Each Document has a list of list of lazy loading images that + need intersection observation, initially empty.

    + +

    This list is added to in the update the image data steps, and checked + in the run the lazy load intersection steps, which is called from the update + the rendering steps.

    + +

    The run the lazy load intersection steps steps for a Document are as + follows:

    + +
      +
    1. +

      For each img in the Document's + list of lazy loading images that need intersection observation:

      + +
        +
      1. +

        If img intersects the + viewport, or img is about to intersect the viewport, then set + img's ready to be lazy loaded flag to true.

        + +

        This allows for fetching the image during scrolling, when it does not, but is + about to intersect the viewport.

        +
      2. +
      3. Otherwise, observe img for intersection.

      4. +
      +
    2. + +
    3. Empty the list of lazy loading images + that need intersection observation.

    4. +
    +

    When the user agent is to update the image data of an img element, optionally with the restart animations flag set, it must run the following steps:

    @@ -27692,11 +27726,19 @@ was an English <a href="/wiki/Music_hall">music hall</a> singer, ...
      +
    1. Add the img element to its node document's list of + lazy loading images that need intersection observation, if it isn't already + present.

    2. +
    3. Continue running this algorithm in parallel.

    4. -
    5. Wait until the will lazy load image steps no longer return true, given the +

    6. Wait until the img's ready to be lazy loaded flag is + true, or until the will lazy load image steps no longer return true, given the img.

    7. +
    8. Remove the img element from its node document's list of + lazy loading images that need intersection observation, if it is present.

    9. +
    10. Queue an element task on the DOM manipulation task source given the img element to continue running the rest of this algorithm.

    @@ -89317,6 +89359,10 @@ dictionary PromiseRejectionEventInit : EventInit { the animation frame callbacks for that Document, passing in now as the timestamp.

    +
  • For each fully active Document in docs, run + the lazy load intersection steps for that Document, passing in + now as the timestamp.

  • +
  • For each fully active Document in docs, run the update intersection observations steps for that Document, passing in now as the timestamp.

  • From 40a543c8cddfe751fdb188734fc5e719887fd544 Mon Sep 17 00:00:00 2001 From: Simon Pieters Date: Thu, 7 May 2020 15:31:54 +0200 Subject: [PATCH 02/14] Use IntersectionObserver directly. Move lazy load processing out of update the image data section --- source | 193 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 119 insertions(+), 74 deletions(-) diff --git a/source b/source index 2ec68af6bed..606f65dfc1d 100644 --- a/source +++ b/source @@ -3746,6 +3746,10 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute @@ -6906,6 +6910,117 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute data-x="invalid value default">invalid value default are both the Eager state.

    +
    Processing model for lazy loading attributes
    + +

    The will lazy load image steps, given an img element img, + are as follows:

    + +
      +
    1. +

      If scripting is disabled for img, return + false.

      + +

      This is an anti-tracking measure, because if a user agent supported lazy loading + when scripting is disabled, it would still be possible for a site to track a user's approximate + scroll position throughout a session, by strategically placing images in a page's markup such + that a server can track how many images are requested and when.

      +
    2. + +
    3. +

      If img's lazy loading attribute is in the Lazy state, then return true.

      +
    4. + +
    5. Return false.

    6. +
    + +

    This algorithm cannot be called from steps running in parallel. If + a user agent needs to call this algorithm from steps running in parallel, it needs to + queue a task to do so.

    + +

    Each img element have a boolean flag ready to be lazy loaded, initially + false.

    + +

    For img elements that will + lazy load, this flag can be set to true in the lazy load intersection + observer's callback, which causes the image to load by continuing the update the + image data steps.

    + +

    Each Document has a lazy load intersection observer, initially set to + null but can be set to an IntersectionObserver instance.

    + +

    To start intersection-observing a lazy loading element element, run these + steps:

    + +
      +
    1. Let doc be element's node document.

    2. + +
    3. +

      If doc's lazy load intersection observer is null, set it to a new + IntersectionObserver instance, initialized as follows:

      + +
        +
      • +

        The callback is these steps, with arguments entries and observer:

        + +
          +
        1. +

          For each entry in entries: + +

            +
          1. Set entry's ready to be lazy loaded flag to true.

          2. + +
          3. Call observer's unobserve method with entry + as the argument.

          4. +
          +
        2. +
        +
      • + +
      • +

        The options is an IntersectionObserverInit dictionary with the + following dictionary members:

        + +
        +
        root
        +

        Set to doc.

        + +
        rootMargin
        +
        +

        UA-defined. See whatwg/html issue #5408.

        + +

        This allows for fetching the image during scrolling, when it does not, but + is about to intersect the viewport.

        +
        + +
        threshold
        +
        UA-defined.
        +
        +
      • +
      +
    4. + +
    5. Call doc's lazy load intersection observer's observe method with element as the + argument.

    6. +
    + +

    To stop intersection-observing a lazy loading element element, run these + steps:

    + +
      +
    1. Let doc be element's node document.

    2. + +
    3. Assert: doc's lazy load intersection observer is not + null.

    4. + +
    5. Call doc's lazy load intersection observer unobserve method with element as + the argument.

    6. +
    +

    Common DOM interfaces

    @@ -27440,71 +27555,6 @@ was an English <a href="/wiki/Music_hall">music hall</a> singer, ...Updating the image data -

    The will lazy load image steps, given an img element img, - are as follows:

    - -
      -
    1. -

      If scripting is disabled for img, return - false.

      - -

      This is an anti-tracking measure, because if a user agent supported lazy loading - when scripting is disabled, it would still be possible for a site to track a user's approximate - scroll position throughout a session, by strategically placing images in a page's markup such - that a server can track how many images are requested and when.

      -
    2. - -
    3. -

      If img's lazy loading attribute is in the Lazy state, then return true.

      -
    4. - -
    5. Return false.

    6. -
    - -

    This algorithm cannot be called from steps running in parallel. If - a user agent needs to call this algorithm from steps running in parallel, it needs to - queue a task to do so.

    - -

    Each img element have a boolean flag ready to be lazy loaded, initially - false.

    - -

    For img elements that will - lazy load, this flag can be set to true in the update the rendering steps, - which causes the image to load by continuing the update the image data steps.

    - -

    Each Document has a list of list of lazy loading images that - need intersection observation, initially empty.

    - -

    This list is added to in the update the image data steps, and checked - in the run the lazy load intersection steps, which is called from the update - the rendering steps.

    - -

    The run the lazy load intersection steps steps for a Document are as - follows:

    - -
      -
    1. -

      For each img in the Document's - list of lazy loading images that need intersection observation:

      - -
        -
      1. -

        If img intersects the - viewport, or img is about to intersect the viewport, then set - img's ready to be lazy loaded flag to true.

        - -

        This allows for fetching the image during scrolling, when it does not, but is - about to intersect the viewport.

        -
      2. -
      3. Otherwise, observe img for intersection.

      4. -
      -
    2. - -
    3. Empty the list of lazy loading images - that need intersection observation.

    4. -
    -

    When the user agent is to update the image data of an img element, optionally with the restart animations flag set, it must run the following steps:

    @@ -27726,9 +27776,8 @@ was an English <a href="/wiki/Music_hall">music hall</a> singer, ...
      -
    1. Add the img element to its node document's list of - lazy loading images that need intersection observation, if it isn't already - present.

    2. +
    3. Start intersection-observing a lazy loading element for the + img element.

    4. Continue running this algorithm in parallel.

    5. @@ -27736,8 +27785,8 @@ was an English <a href="/wiki/Music_hall">music hall</a> singer, ...will lazy load image steps no longer return true, given the img.

      -
    6. Remove the img element from its node document's list of - lazy loading images that need intersection observation, if it is present.

    7. +
    8. Stop intersection-observing a lazy loading element for the img + element.

    9. Queue an element task on the DOM manipulation task source given the img element to continue running the rest of this algorithm.

    10. @@ -89359,10 +89408,6 @@ dictionary PromiseRejectionEventInit : EventInit { the animation frame callbacks for that Document, passing in now as the timestamp.

      -
    11. For each fully active Document in docs, run - the lazy load intersection steps for that Document, passing in - now as the timestamp.

    12. -
    13. For each fully active Document in docs, run the update intersection observations steps for that Document, passing in now as the timestamp.

    14. From f99f55c15173239fb49aa32205cd220d041cb6cf Mon Sep 17 00:00:00 2001 From: Simon Pieters Date: Thu, 7 May 2020 22:02:18 +0200 Subject: [PATCH 03/14] have -> has --- source | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source b/source index 606f65dfc1d..c9c1b9ff4a1 100644 --- a/source +++ b/source @@ -6938,7 +6938,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute a user agent needs to call this algorithm from steps running in parallel, it needs to queue a task to do so.

      -

      Each img element have a boolean flag ready to be lazy loaded, initially +

      Each img element has a boolean flag ready to be lazy loaded, initially false.

      For img elements that will From 1bf73107f4f640783be3a8f386e29aa8d35b0bf5 Mon Sep 17 00:00:00 2001 From: Simon Pieters Date: Thu, 7 May 2020 22:04:03 +0200 Subject: [PATCH 04/14] Move note about in parallel back to updating the image data --- source | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source b/source index c9c1b9ff4a1..b111766ae14 100644 --- a/source +++ b/source @@ -6934,10 +6934,6 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

    15. Return false.

    -

    This algorithm cannot be called from steps running in parallel. If - a user agent needs to call this algorithm from steps running in parallel, it needs to - queue a task to do so.

    -

    Each img element has a boolean flag ready to be lazy loaded, initially false.

    @@ -27555,6 +27551,10 @@ was an English <a href="/wiki/Music_hall">music hall</a> singer, ...Updating the image data +

    This algorithm cannot be called from steps running in parallel. If + a user agent needs to call this algorithm from steps running in parallel, it needs to + queue a task to do so.

    +

    When the user agent is to update the image data of an img element, optionally with the restart animations flag set, it must run the following steps:

    From 2b09bf0f6531496282c8ad0366e439befac44854 Mon Sep 17 00:00:00 2001 From: Dominic Farolino Date: Wed, 13 May 2020 13:33:26 -0600 Subject: [PATCH 05/14] Address reviews --- source | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/source b/source index b111766ae14..42c92f6d6bf 100644 --- a/source +++ b/source @@ -3750,6 +3750,8 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
  • IntersectionObserverInit
  • observe
  • unobserve
  • +
  • isIntersecting
  • +
  • target
  • @@ -6964,11 +6966,10 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

    For each entry in entries:

      -
    1. Set entry's ready to be lazy loaded flag to true.

    2. - -
    3. Call observer's unobserve method with entry - as the argument.

    4. +
    5. If entry.isIntersecting is true, set + entry.target's + ready to be lazy loaded flag to true.

    @@ -6979,9 +6980,6 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute following dictionary members:

    -
    root
    -

    Set to doc.

    -
    rootMargin

    UA-defined. See This allows for fetching the image during scrolling, when it does not, but is about to intersect the viewport.

    - -
    threshold
    -
    UA-defined.
    From ae8a9175f78da73edf9e45fe1dae934206da0171 Mon Sep 17 00:00:00 2001 From: Dominic Farolino Date: Thu, 14 May 2020 23:25:14 -0600 Subject: [PATCH 06/14] Address annevk review --- source | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/source b/source index 42c92f6d6bf..df1ac931379 100644 --- a/source +++ b/source @@ -6928,16 +6928,14 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute that a server can track how many images are requested and when.

    -
  • -

    If img's lazy loading attribute is in the Lazy state, then return true.

    -
  • +
  • If img's lazy loading attribute is in the Lazy state, then return true.

  • Return false.

  • -

    Each img element has a boolean flag ready to be lazy loaded, initially - false.

    +

    Each img element has an associated ready to be lazy loaded boolean, + initially false.

    For img elements that will lazy load, this flag can be set to true in the lazy load intersection @@ -6957,6 +6955,13 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

    If doc's lazy load intersection observer is null, set it to a new IntersectionObserver instance, initialized as follows:

    +

    The intention here is to use the original value of the + IntersectionObserver constructor, however we're forced to use the + JavaScript-exposed constructor in this specification, until IntersectionObserver exposes + low-level hooks for use in specifications. See bug w3c/IntersectionObserver#427 + which tracks this.

    + -
  • Call doc's lazy load intersection observer's observe method with element as the - argument.

  • +
  • +

    Call doc's lazy load intersection observer's observe method with element as the + argument.

    + +

    The intention is to use the original value of the observe method. See w3c/IntersectionObserver#427. +

    +
  • To stop intersection-observing a lazy loading element element, run these @@ -7012,9 +7029,16 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

  • Assert: doc's lazy load intersection observer is not null.

  • -
  • Call doc's lazy load intersection observer unobserve method with element as - the argument.

  • +
  • +

    Call doc's lazy load intersection observer unobserve method with element as + the argument.

    + +

    The intention is to use the original value of the unobserve method. See w3c/IntersectionObserver#427. +

    +
  • From 01b8c3ca0ea5d300fc88b3b959c7951aa38de53d Mon Sep 17 00:00:00 2001 From: Simon Pieters Date: Mon, 18 May 2020 23:23:45 +0200 Subject: [PATCH 08/14] Use
    instead of subsection --- source | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source b/source index 48c098316c1..e0652fb60a2 100644 --- a/source +++ b/source @@ -6912,7 +6912,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute data-x="invalid value default">invalid value default are both the Eager state.

    -
    Processing model for lazy loading attributes
    +

    The will lazy load image steps, given an img element img, are as follows:

    From 14c163742231b77713e947a0a3bca8f8bab8e264 Mon Sep 17 00:00:00 2001 From: Simon Pieters Date: Mon, 18 May 2020 23:30:08 +0200 Subject: [PATCH 09/14] Rename will lazy load image steps to will lazy load element steps --- source | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source b/source index e0652fb60a2..9f7d7060798 100644 --- a/source +++ b/source @@ -6914,13 +6914,13 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
    -

    The will lazy load image steps, given an img element img, +

    The will lazy load element steps, given an element element, are as follows:

    1. -

      If scripting is disabled for img, return - false.

      +

      If scripting is disabled for element, + then return false.

      This is an anti-tracking measure, because if a user agent supported lazy loading when scripting is disabled, it would still be possible for a site to track a user's approximate @@ -6928,7 +6928,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute that a server can track how many images are requested and when.

    2. -
    3. If img's lazy loading attribute is in the

      If element's lazy loading attribute is in the Lazy state, then return true.

    4. Return false.

    5. @@ -6937,7 +6937,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

      Each img element has an associated ready to be lazy loaded boolean, initially false.

      -

      For img elements that will +

      For img elements that will lazy load, this flag can be set to true in the lazy load intersection observer's callback, which causes the image to load by continuing the update the image data steps.

      @@ -27796,7 +27796,7 @@ was an English <a href="/wiki/Music_hall">music hall</a> singer, ...
    6. -

      If the will lazy load image steps given the img return true, +

      If the will lazy load element steps given the img return true, then:

        @@ -27806,7 +27806,7 @@ was an English <a href="/wiki/Music_hall">music hall</a> singer, ...

        Continue running this algorithm in parallel.

      1. Wait until the img's ready to be lazy loaded flag is - true, or until the will lazy load image steps no longer return true, given the + true, or until the will lazy load element steps no longer return true, given the img.

      2. Stop intersection-observing a lazy loading element for the img From dfdcec61212320666bfd40524db32cec113c00f1 Mon Sep 17 00:00:00 2001 From: Simon Pieters Date: Mon, 18 May 2020 23:34:53 +0200 Subject: [PATCH 10/14] Linebreak --- source | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source b/source index 9f7d7060798..a0523c7a4db 100644 --- a/source +++ b/source @@ -6937,8 +6937,8 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

        Each img element has an associated ready to be lazy loaded boolean, initially false.

        -

        For img elements that will - lazy load, this flag can be set to true in the lazy load intersection +

        For img elements that will lazy load, this flag can be set to true in the lazy load intersection observer's callback, which causes the image to load by continuing the update the image data steps.

        From f776326d0572903e1e97406bb853a3a1ff94b2ef Mon Sep 17 00:00:00 2001 From: Simon Pieters Date: Mon, 18 May 2020 23:39:17 +0200 Subject: [PATCH 11/14] Remove word 'flag'; formatting --- source | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source b/source index a0523c7a4db..8bea82c9d7a 100644 --- a/source +++ b/source @@ -6938,7 +6938,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute initially false.

        For img elements that will lazy load, this flag can be set to true in the lazy load intersection + steps">will lazy load, this can be set to true in the lazy load intersection observer's callback, which causes the image to load by continuing the update the image data steps.

        @@ -6956,9 +6956,9 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute IntersectionObserver instance, initialized as follows:

        The intention is to use the original value of the - IntersectionObserver constructor, however we're forced to use the - JavaScript-exposed constructor in this specification, until IntersectionObserver exposes - low-level hooks for use in specifications. See bug IntersectionObserver constructor. However, we're forced to use the + JavaScript-exposed constructor in this specification, until Intersection Observer + exposes low-level hooks for use in specifications. See bug w3c/IntersectionObserver#427 which tracks this.

        From c432c9d37d85f3e833ca45ab5b07a76ec580a239 Mon Sep 17 00:00:00 2001 From: Simon Pieters Date: Mon, 18 May 2020 23:58:59 +0200 Subject: [PATCH 12/14] Add 'XXX' annotation; replace
        with ordered map syntax --- source | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/source b/source index 8bea82c9d7a..da9dc233eed 100644 --- a/source +++ b/source @@ -6969,8 +6969,9 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
        1. -

          For each entry in entries (using a method of iteration which does - not trigger developer-modifiable array accessors or iteration hooks): +

          For each entry in entries using a method of + iteration which does not trigger developer-modifiable array accessors or + iteration hooks:

          1. @@ -6992,18 +6993,14 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
          2. The options is an IntersectionObserverInit dictionary with the - following dictionary members:

            + following dictionary members: «[ "rootMargin" → an + implementation-defined value ]»

            -
            -
            rootMargin
            -
            -

            UA-defined. See whatwg/html issue #5408.

            +

            See whatwg/html issue #5408.

            -

            This allows for fetching the image during scrolling, when it does not, but - is about to intersect the viewport.

            -
            -
            +

            This allows for fetching the image during scrolling, when it does not, but + is about to intersect the viewport.

          3. From 581c24025aa85a25ccbbd7c40d7739a764ff0cde Mon Sep 17 00:00:00 2001 From: Simon Pieters Date: Mon, 18 May 2020 23:59:48 +0200 Subject: [PATCH 13/14] Remove 'whatwg/html' in issue link text --- source | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source b/source index da9dc233eed..da55a41379b 100644 --- a/source +++ b/source @@ -6997,7 +6997,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute implementation-defined value ]»

            See whatwg/html issue #5408.

            + href="https://github.com/whatwg/html/issues/5408">issue #5408.

            This allows for fetching the image during scrolling, when it does not, but is about to intersect the viewport.

            From 8a764c799d35e6a6a212c12e82f3c47d98d9af62 Mon Sep 17 00:00:00 2001 From: Simon Pieters Date: Tue, 19 May 2020 00:01:34 +0200 Subject: [PATCH 14/14] Wording tweak: but is about to --- source | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source b/source index da55a41379b..a054fe5e503 100644 --- a/source +++ b/source @@ -6999,8 +6999,8 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

            See issue #5408.

            -

            This allows for fetching the image during scrolling, when it does not, but - is about to intersect the viewport.

            +

            This allows for fetching the image during scrolling, when it does not yet — + but is about to — intersect the viewport.