Repository navigation
script: Wire element for LargestContentfulPaint - #46553
Conversation
| let address = UntrustedNodeAddress(id as *const c_void); | ||
| let node = unsafe { node::from_untrusted_node_address(address) }; | ||
| DomRoot::downcast::<Element>(node).map(|el| String::from(el.Id())) |
There was a problem hiding this comment.
How do you know that the node is still alive?
In general one should by all means avoid round-tripping a pointer through an integer, since it loses / exposes provenance. Can't we use a different mechanism to lookup the node?
There was a problem hiding this comment.
The element was just painted to screen in same layout so it must be alive.
Please enlighten me on this. This is what I achieved by referencing already implemented components in InspectorHighlight or DocumentShadowRoot.
Here is a open Zulip Topic for same
There was a problem hiding this comment.
The ID is sent from layout to the constellation, then back to the script thread. The element could have been removed from the document in that time and GCed.
There was a problem hiding this comment.
Please enlighten me with better appraoch to this, i am not familiar with this that much.
There was a problem hiding this comment.
In general:
- choose a script thread struct that will store the underlying object until the async notification is received
- create a new ID that can be sent around that is not the pointer (eg. a uuid)
- make it possible to map the ID to the stored object
This could be something like
largest_contentful_paint_candidates: DomRefCell<HashMap<LargestContentfulPaintId, Dom<Element>>>
which could live in ScriptThread, or maybe a single DomRefCell<Option<(LargestContentfulPaintId, Dom<Element>)>> in Document, or maybe there's somewhere else that makes more sense.
There was a problem hiding this comment.
Please take a look at the latest changes. Extracted some changes in #46828
Sorry for Earlier, I think I mixed few concepts and created a mess.
There was a problem hiding this comment.
I explored that idea of having HashMap of largest_contentful_paint_candidates. But I think we need to come back to script layer in one way or other to resolve the element.
But IMO By using Node::is_connected_with_browsing_context, we make sure Node is still alive.
Let me know your thoughts. I am supporting my point with WPTs as well. Please take a look on #46851 as well.
P.S: I will rebase when WPT is merged.
id on LargestContentfulPaintelement for LargestContentfulPaint
| url: url.map(|u| DOMString::from(u.as_str())).unwrap_or_default(), | ||
| element: None, | ||
| element_id: element_id.map(DOMString::from).unwrap_or_default(), | ||
| element: element.map(|el| Dom::from_ref(&*el)), |
There was a problem hiding this comment.
Do not abbreviate variable names here and everywhere else in this change: https://book.servo.org/contributing/style-guide.html#abbreviation
| element: element.map(|el| Dom::from_ref(&*el)), | |
| element: element.map(|element| Dom::from_ref(&*element)), |
|
|
||
| /// <https://www.w3.org/TR/largest-contentful-paint/#dom-largestcontentfulpaint-id> | ||
| fn Id(&self) -> DOMString { | ||
| self.element_id.clone() |
There was a problem hiding this comment.
Can't this just read the id attribute from self.element. Why must the id be passed into layout and then back out again?
| candidate_id, | ||
| } => { | ||
| let mut element: Option<DomRoot<Element>> = None; | ||
| if let Some(candidate) = candidate_id { |
There was a problem hiding this comment.
It's very confusing to rename this, so just call it candidate_id as well:
| if let Some(candidate) = candidate_id { | |
| if let Some(candidate_id) = candidate_id { |
| // captured during display list construction is still | ||
| // valid in the DOM. | ||
| let address = UntrustedNodeAddress(candidate.0 as *const c_void); | ||
| let node = unsafe { node::from_untrusted_node_address(address) }; |
There was a problem hiding this comment.
This is still an OpaqueNode that comes back to the script from an asynchronous message. How can you be sure that's it's still valid? You updated your change, but you didn't explain how your update responded to the concerns raised before, so it's hard to say what the mechanism is.
There was a problem hiding this comment.
By using Node::is_connected_with_browsing_context, we make sure Node is still alive.
IMo, missing WPT test case is the reason for proper testing of raised concerns. So, I added WPT #46851.
There was a problem hiding this comment.
The issue is that the Node might have been garbage collected at this point and the pointer you are dereferencing here might point to freed memory or even at some other allocated memory (even another Node). Nothing you can call on the Node after this dereference is reliable or can fix this issue. I think it's actually just impossible to get a reference to a node based something you calculate from the display list (for good reason...the display list shouldn't prevent garbage collection). It may be the case that to implement LCP properly, it needs to move to script from paint.
There was a problem hiding this comment.
Acknowledged. Yeah I agree. Let me process this information and I will get back to this.
There was a problem hiding this comment.
Now while processing the ReflowResult, OpaqueNode is resolved and Element is stored in HashMap located in document.
Almost identical to how we prcoess handle_pending_images_post_reflow.
|
🤖 Opened new upstream WPT pull request (web-platform-tests/wpt#61595) with upstreamable changes. |
|
📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#61595). |
6b161a3 to
712d27f
Compare
Signed-off-by: Shubham Gupta <shubham.gupta@chromium.org>
Signed-off-by: Shubham Gupta <shubham.gupta@chromium.org>
| fn process_lcp_candidate_post_reflow( | ||
| &self, | ||
| candidate: &LCPCandidate, | ||
| node_id: usize, |
There was a problem hiding this comment.
Let's make this the UntrustedNodeAddres instead.
| /// The LCP candidate during this layout pass, if any. | ||
| pub lcp_candidate: Option<LCPCandidate>, | ||
| /// The OpaqueNode ID for the LCP candidate if any. | ||
| pub lcp_node_id: Option<usize>, |
There was a problem hiding this comment.
This should be a UntrustedNodeAddress instead.
Signed-off-by: Shubham Gupta <shubham.gupta@chromium.org>
Wire the logic for
elementonLargestContentfulPaintusingOpaqueNodeWhile processing the
ReflowResult,OpaqueNodeis resolved andElementis stored in HashMap located indocument.Testing: New WPT Passed (+ To be Added in #46851)
Fixes: Part of #42000