Skip to content

layout: Do not consider iframe fragments as contentful for paint timing#42498

Merged
mrobinson merged 2 commits intoservo:mainfrom
shubhamg13:iframe_fcp
Feb 11, 2026
Merged

layout: Do not consider iframe fragments as contentful for paint timing#42498
mrobinson merged 2 commits intoservo:mainfrom
shubhamg13:iframe_fcp

Conversation

@shubhamg13
Copy link
Copy Markdown
Member

@shubhamg13 shubhamg13 commented Feb 10, 2026

This aligns first-contentful-paint about iframe according to specs, Step: 10.2.1.

NOTE: A parent frame should not be aware of the paint events from its child iframes, and vice versa. This means that a frame that contains just iframes will have first paint (due to the enclosing boxes of the iframes) but no first contentful paint.

Testing: Update WPT tests expectations.

@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Feb 10, 2026
Copy link
Copy Markdown
Contributor

@TimvdLippe TimvdLippe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with 1 nit

let style = iframe.base.style();
match style.get_inherited_box().visibility {
Visibility::Visible => {
builder.mark_is_contentful();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: please add the spec text as comment here to explain why we aren't calling this anymore.

Copy link
Copy Markdown
Member Author

@shubhamg13 shubhamg13 Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I don't have a good feeling about adding a comment for not doing something unless it is TODO or else.

IMHO, it should be other way around mentioning which are contentful.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense for people reading the code that there is a comment explaining this. Consider that without the comment someone will think it is a bug that an <iframe> isn't considered contentful.

I am curious about this though. Is it that <iframe>s are not considered contentful or simply that <iframe>s that haven't loaded yet are not considered contentful?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A parent frame should not be aware of the paint events from its child iframes

iframe should send FCP to its own browsing context, not top level browser context.

Chrome: Reports FCP to iframe's context (not top level browser context).
image

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A parent frame should not be aware of the paint events from its child iframes

iframe should send FCP to its own browsing context, not top level browser context.

The Fragment::IFrame list is not actually the interior contents of the <iframe>. It is a slot that the child frame's display list will be inserted into during the final paint pass. It doesn't have anything to do with paint events that happen in that child iframe, which happen when the child iframe's display list is built for the child iframe's Document.

@servo-highfive servo-highfive removed the S-awaiting-review There is new code that needs to be reviewed. label Feb 10, 2026
@mrobinson
Copy link
Copy Markdown
Member

mrobinson commented Feb 10, 2026

@shubhamg13 For what it's worth, it's a bit rude to simply refuse a reviewer's request because you disagree. If a reviewer is mistaken (this isn't unusual), then generally you try to resolve the misunderstanding or miscommunication. To simply say, "I don't want to do this" is, in general, not a great way to interact in the project.

@shubhamg13
Copy link
Copy Markdown
Member Author

shubhamg13 commented Feb 10, 2026

Ahh my intention was not that to refuse that. I didn't mean to sound rude.

Let me correct that comment.

Added a TODO.

@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Feb 10, 2026
@shubhamg13 shubhamg13 changed the title layout: iframe should not fire first-contentful-paint layout: iframe should not fire first-contentful-paint in top level browsing context Feb 10, 2026
match style.get_inherited_box().visibility {
Visibility::Visible => {
builder.mark_is_contentful();
// TODO: Send FCP for iframe to its own browsing context.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, is this not happening? Each <iframe> is a pipeline and each pipeline has a display list. Each display list checks whether it is contentful or not and then tells the pipeline when the first contentful paint happened.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far I remember, currently any FCP reported irrespective of display list is sent to global scope, ideally FCP from iframe should be sent to iframe scope instead.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If that's an issue though, this change is not fixing it. The presence of this display list item is only applicable to the Document that it is found in. It doesn't have anything to do with the display list of the child frame, other than providing a slot for it in the final rendering.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clarify, this fragment is about the wrapper <iframe> in the parent document and doesn't have anything to do with the display list of the child <iframe>. It is not affected at all by paint events that happen in the child <iframe>.

Copy link
Copy Markdown
Member Author

@shubhamg13 shubhamg13 Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your last comment sounds little confusing.

In simplified manner, My motive with this patch is stop firing FCP for any iframe either in parent document or child iframe as of now.

@mrobinson
Copy link
Copy Markdown
Member

@shubhamg13 Out of curiosity, is this change solving an actual issue that you are seeing?

@shubhamg13
Copy link
Copy Markdown
Member Author

@shubhamg13 Out of curiosity, is this change solving an actual issue that you are seeing?

Actually it is solving Intermittent behaviour by not reporting FCP of iframe (to global scope by default).

Yeah, it needs some more efforts and time to properly align as per specs. But as far this seems quite reasonable for now to me. WDYS?

@mrobinson
Copy link
Copy Markdown
Member

Actually it is solving Intermittent behaviour by not reporting FCP of iframe (to global scope by default).

When you say intermittent behavior are you referring to tests that are no longer intermittent with this change?

@shubhamg13
Copy link
Copy Markdown
Member Author

shubhamg13 commented Feb 10, 2026

Actually it is solving Intermittent behaviour by not reporting FCP of iframe (to global scope by default).

When you say intermittent behavior are you referring to tests that are no longer intermittent with this change?

Yes, that's what I mean. This will still require a revisit. That's why I added a TODO.

cc: @xiaochengh

@mrobinson
Copy link
Copy Markdown
Member

When you say intermittent behavior are you referring to tests that are no longer intermittent with this change?

Yes, that's what I mean. This will still require a revisit. That's why I added a TODO.

Sorry, I meant to also ask which tests those were specifically? Are they WPT tests?

Copy link
Copy Markdown
Member

@mrobinson mrobinson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, with one change:

match style.get_inherited_box().visibility {
Visibility::Visible => {
builder.mark_is_contentful();
// TODO: Send FCP for iframe to its own browsing context.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the TODO is probably wrong, as it's already the case that paint events are sent to their browsing context, right? That said, I think @TimvdLippe original suggestion was to just put the specification text here, so let's do that:

Suggested change
// TODO: Send FCP for iframe to its own browsing context.
// From <https://www.w3.org/TR/paint-timing/>:
// > A parent frame should not be aware of the paint events from its child iframes, and
// > vice versa. This means that a frame that contains just iframes will have first paint
// > (due to the enclosing boxes of the iframes) but no first contentful paint.

@servo-highfive servo-highfive added S-needs-code-changes Changes have not yet been made that were requested by a reviewer. and removed S-awaiting-review There is new code that needs to be reviewed. labels Feb 10, 2026
@servo-highfive servo-highfive added S-awaiting-review There is new code that needs to be reviewed. and removed S-needs-code-changes Changes have not yet been made that were requested by a reviewer. labels Feb 11, 2026
@shubhamg13 shubhamg13 changed the title layout: iframe should not fire first-contentful-paint in top level browsing context layout: Mark first-contentful-paint for iframe only in its own pipeline Feb 11, 2026
@shubhamg13 shubhamg13 requested a review from mrobinson February 11, 2026 04:05
// > A parent frame should not be aware of the paint events from its child iframes, and
// > vice versa.
if builder.webrender_display_list_builder.pipeline_id ==
iframe.pipeline_id.into()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check doesn't make sense to me—an iframe will never contain the pipeline that the current display list builder is building for.

Copy link
Copy Markdown
Member Author

@shubhamg13 shubhamg13 Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that's my concern. (But it saves from marking other pipelines as contentful)

You got my intent, any tip how to achieve that.

Copy link
Copy Markdown
Member

@jdm jdm Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like you're focusing on this specification text:

A parent frame should not be aware of the paint events from its child iframes, and vice versa. This means that a frame that contains just iframes will have first paint (due to the enclosing boxes of the iframes) but no first contentful paint.

But the reason for making the change in this PR is not related to this text; the current implementation isn't sending FCP notifications for a child frame to the parent frame. Instead, we should focus on this text:

  1. If document should report first contentful paint, then:

which links to this text:

  1. If document contains at least one element that is both paintable and contentful, then return true.

which links to https://www.w3.org/TR/paint-timing/#contentful, which does not include any steps that treat an iframe element as contentful.

Therefore, from my reading, we should never mark the display list as contentful when processing an iframe fragment.

Copy link
Copy Markdown
Member Author

@shubhamg13 shubhamg13 Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Completely agree with all your explanations.

If I understood completely. Following is summary:

  1. if iframe contains an image, it will mark FCP within its own scope without notifying parent.
  2. As iframe will be treated as a separate document, it should have its own paint timings irrespective of parent document.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That matches my understanding!

@shubhamg13 shubhamg13 marked this pull request as draft February 11, 2026 04:10
@shubhamg13 shubhamg13 marked this pull request as ready for review February 11, 2026 04:12
@shubhamg13 shubhamg13 marked this pull request as draft February 11, 2026 05:30
@shubhamg13 shubhamg13 marked this pull request as ready for review February 11, 2026 05:58
@shubhamg13 shubhamg13 changed the title layout: Mark first-contentful-paint for iframe only in its own pipeline layout: iframe should not fire first-contentful-paint in top level browsing context Feb 11, 2026
@shubhamg13 shubhamg13 requested a review from jdm February 11, 2026 06:00
@mrobinson mrobinson changed the title layout: iframe should not fire first-contentful-paint in top level browsing context layout: Do not consider iframe fragments at contentful for paint timing Feb 11, 2026
@servo-highfive servo-highfive removed the S-awaiting-review There is new code that needs to be reviewed. label Feb 11, 2026
@mrobinson mrobinson added this pull request to the merge queue Feb 11, 2026
@servo-highfive servo-highfive added the S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. label Feb 11, 2026
@shubhamg13 shubhamg13 changed the title layout: Do not consider iframe fragments at contentful for paint timing layout: Do not consider iframe fragments as contentful for paint timing Feb 11, 2026
Merged via the queue into servo:main with commit dbc8a7f Feb 11, 2026
33 checks passed
@servo-highfive servo-highfive removed the S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. label Feb 11, 2026
@shubhamg13 shubhamg13 deleted the iframe_fcp branch February 11, 2026 10:59
github-merge-queue bot pushed a commit that referenced this pull request Mar 23, 2026
`iframe` should be considered for `first-paint`. 

TODO of: #42975
Synced: web-platform-tests/wpt#58243
Refer for some history: #42498

Testing: 

- `wpt/paint-timing/first-paint-only/child-painting-first-image.html`
- `wpt/paint-timing/first-paint-only/sibling-painting-first-image.html`

Fixes: #42455

---------

Signed-off-by: Shubham Gupta <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants