Meeting minutes
<astearns> what is the doc where scribing is happening?
leo: presenting slideas
leo: the proposal is a new FormControlRange, extending AbstractRange
leo: FormControlRange is live and automatically updates, like how Range tracks changes
leo: this is inspired by Keith Cirkel's Richer Text Fields proposal
leo: it's different enough from Range to justify creating a new type
leo: would like to get your thoughts on this
leo: there are restrictions on the start/end point that are hard to enforce with the Range API
leo: if we did use Range, maybe we could add a parameter to all methods, but that seems messy
leo: that's the context
rniwa: Range.selectNodeContents() isn't on AbstractRange I think
anne: if use Range directly we have a bunch of problems like this
leo: what we're proposing is this (presenting Example 1)
rniwa: should the Selection API be updated?
leo: it would be live
leo: but would getSelection() getters return these new objects?
leo: I would say yes, return this new FormControlRange
smaug: I'm not sure we want to change what those things return
emilio: is that interoperable right now?
smaug: no, there are differences
rniwa: there may be some compatibility issues then, needs to be discussed in conjunction with the Selection API
smaug: I thought this was more about the Highlight API
leo: custom highlight, yes
rniwa: calling it custom highlights and not interacting with selection is an option
anne: we could also have that be an opt-in
emilio: something added to getRangeAt()
anne: or flip a bit on the Selection object
zcorpan: or a new method
smaug: something something Shadow DOM
rniwa: form-associated custom elements wouldn't be able to work with this API
leo: how can we overcome that?
rniwa: need to make it more generic so that custom elements can use this
rniwa: maybe it wouldn't be called FormControlRange
leo: do we have consensus that a new interface is needed?
rniwa: my concern is a brand new API that doesn't work with custom elements, but if we make it work that would be OK.
emilio: one more option is something that operates directly on a single text node, these controls effectively operate on a string.
emilio: that could also work with contenteditable=plaintext-only
emilio: this new Range isn't very special, except that you don't have access to the string it's pointing into
anne: StringRange, TextRange?
emilio: yes.
anne: maybe set the range through ElementInternals?
rniwa: ideally we want to be able to map the selection from within the shadow root dynamically
rniwa: if it's a calendar widget you want a selection in date/month/year separately, so it's not necessarily a 1:1 map.
smaug: but this is only for text inputs
emilio: it feels like a regular range that operates on a text node.
emilio: maybe 3 different text ranges for date/month/year in that case, and the custom element exposes all 3?
emilio: maybe it's also useful for cases where you do have access to the underlying node
schenney: the issue links to Keith's doc with a bunch of use cases for this
https://
leo: our original intention was to start with just text and be open to custom elements in the future
smaug: there is a risk that we'd have to introduce another range type
anne: it depends on whether custom elements just need parity with built-in elements or need to do more than that
rniwa: we probably don't want to expose the Text node itself
anne: no
emilio: how about PlainTextRange?
<LeoL> https://
emilio: we could easily create a constructor to create a PlainTextRange from a Text node?
emilio: I'm not sure why input and textarea can't just have a getter returning the live range for the current selection? why a constructor?
smaug: because there can be multiple ones for highlighting
rniwa: regular ranges have a clone() method
rniwa: but it would be awkward to create new ranges with offsets, need to clone and edit
leo: we're trying to align with the current APIs
cwilso, can you encourage usage of the queue?
<emilio> To be clear, what I'm proposing, something like: `TextRange HTMLTextAreaElement.getTextRange(unsigned start, unsigned end);`
rniwa: my question is if we have an interface with a constructor taking a host and two numbers, that only works for text field-like custom elements
rniwa: is there an alterantive where it would work with multiple editable regions?
<emilio> And then custom elements could do something like `new TextRange(); textRange.setTextRange(myMonthNode, 0, 2); return textRange;` or so
rniwa: ideally we'd have one solution that would work for multiple use cases
leo: you're saying it doesn't work because it doesn't work with multiple ranges?
rniwa: maybe we could add a name that specifies which selectable area it refers to
emilio: I pasted the example above of what I mean
emilio: as long as we don't expose the actual Text node in the interface I think it would work on both inputs and custom elements
rniwa: that might be a good design
rniwa: one thing to consider is a calendar widget is some way to "forward"... but maybe it's OK
anne: then the other properties can't expose the boundary points, because they'd be in the shadow tree
anne: not sure what abstract range currently does
emilio: that would be important
rniwa: we could also return a host
zcorpan: makes more sense than returning <body> which is what Range does :)
zcorpan: maybe the constructor needs to have a parameter for the host?
emilio: the other alterantive would be to just return the text node, but that exposes it from the text node
anne: we can't do that
zcorpan: return the text node data?
[scribe is having difficulties scribing back and forth]
cwilso: we are at time!
leo: are we closer to a solution?
anne: I think we need a design for the form-associated case, but it doesn't need to be included in v0
anne: we have some alterantives
rniwa: I think we can come up with something
[general rejoicing and optimism in the room]
leo: we'll go back and have a look
anne: I'm happy to help
AsyncContext
andreubotella: Proposal tc39/
andreubotella: trying to figure out integration between tc39 and whatwg
<Jxck> tc39/
andreubotella: Open question how the stages processes map to each other
andreubotella: What AsyncContext does, it propagates... has AsyncContext.Variable class
andreubotella: run() method
andreubotella: showing await example
andreubotella: gets propagated through await
andreubotella: set a new value in the stack
andreubotella: setTimeout example
andreubotella: asyncVar.get() returns same value from setTimeout() in run() as sync in run()
andreubotella: useful to keep track of state across disconnected parts of an application, calling to other third-party code
andreubotella: which async operation they are in
andreubotella: which async branch
andreubotella: parallel to localStorage
andreubotella: used to instrument ThreadLocalStorage in C++, not to the web localStorage
<nicolo-ribaudo> For the minutes: the parallel was to ThreadLocalStorage in C++, not to the web localStorage
andreubotella: would allow authors to instrument their applications, would be more performant for users
andreubotella: trying to see if this works as an explainer for the whatwg stages process
nicolo-ribaudo: tc39 want to be formal about stages
nicolo-ribaudo: suggest being loose on whatwg side
nicolo-ribaudo: advance roughly at the same time
andreubotella: for stage 3 it signals that it's ready for implementation, should be in sync
andreubotella: tc39 might advance to stage 3 at the time whatwg advances
andreubotella: whatwg stage 3 could signal tc39 stage 2.7
<Zakim> nicolo-ribaudo, you wanted to ask if we have stage 1
nicolo-ribaudo: requesting whatwg stage 1
nicolo-ribaudo: believe the proposal fulfills the requirements
cwilso: in general, bring it to the triage meeting, group can object or agree
rniwa: what happens with multiple values
andreubotella: have single map to a value
andreubotella: if you use immutable map, do await or setTimeout, store reference
andreubotella: multiple values are variable
anne: can you use multiple Variables?
andreubotella: yes
jridgewell: restored after await
andreubotella: single asynccontext are variable. Have internal map, not user exposed
<nicolo-ribaudo> (name of the person who spoke is jridgewell, for the minutes)
andreubotella: better if it's mutable
anne: better if you didn't explain in terms of impl
anne: explain what web dev can observe
rniwa: want to have multiple values, return some unique value, map to some value at that moment
nicolo-ribaudo: map is internal impl detail
nicolo-ribaudo: multiple variables, multiple keys
nicolo-ribaudo: set them one by one
mmocny: Similar to normal valiables
smaug: status, i think stage 1 is fine
smaug: hoping webkit folks would review, from integration with web apis POV, and memory management
nicolo-ribaudo: do you think we can go through the current document
nicolo-ribaudo: setTimeout has an obvious answer
smaug: need to go through all apis
nicolo-ribaudo: would be good to have participation from all browser engines
anne: should there be something for AbortSignals?
nicolo-ribaudo: just an event?
anne: yes
andreubotella: events are most complicated part
andreubotella: work different in different situations
andreubotella: events are sync, (missed),
andreubotella: loadend event
andreubotella: there are many of those events, if we decide to propagate those, from the same agent and same origin it's propagated
<jridgewell> s/(misssed),/browser originated events have no obvious context to propagate, like `onload`
andreubotella: maybe not expected by developers
andreubotella: observers, not fully figured out
andreubotella: to be discussed during stage 1
andreubotella: maybe can simplify if it's too complicated
andreubotella: a lot of web apis that do async things
domfarolino: the notes says, propagating .... same result as ...
domfarolino: idea is, the snapshot is taken after callback is run
domfarolino: can snapshot happen different time?
domfarolino: ran callback ...
nicolo-ribaudo: difficult to do from different context
domfarolino: do something after callback has run
domfarolino: is it possible to get disconnected from scheduler api
nicolo-ribaudo: if you postmessage a worker
domfarolino: how would this work with observables
domfarolino: create an observable in callback
domfarolino: later on, run subscribe
domfarolino: what is the value of Variable?
domfarolino: overridden by run?
nicolo-ribaudo: when you call next() it propagates
domfarolino: wondering if there's something that makes sense
domfarolino: not obvious what the right behavior is
smaug: general issue
domfarolino: some apis are tricky
snek: precise semantics how asynccontext works
<rniwa> q>
snek: any ambiguities, documentation about what we want to happen
domfarolino: it is what we define for each api
snek: if observable is going through a web api, but in other cases can define from first principles for the api
<Zakim> cwilso, you wanted to break
jridgewell: similar issue already for observer-type apis
OpenUI/WHATWG issues
<ntim> where is the agenda
fantasai: These issues are all related, mainly about anchor positioning. Affordances useful for accessibility
… create a connection with popover API for accessibility, also with anchor positioning for presentation
fantasai: what about non popovers? how to express those relationships
(popovers use popovertarget)
domfarolino: IIUC, do we need markup to associate non-popover to its anchor?
fantasai: ARIA has a lot of mental load. Anchor positioning has both presentational use cases where the bindings shouldn't be expressed, and has cases like popover where the link needs to be expressed in the a11y tree. There are going to be cases where the semantic relationship needs to be expressed, but it is not a popover. What is the markup for those?
<tantek> +1 fantasai. making the anchoring relationship more explicit in markup with a more memorable attribute (for both popover and non-popover), rather than re-using ARIA, is a more developer-ergonomic approach.
kizu: What are the use cases? tooltips, common use case is where side notes where you position notes on the left of the content. There are many potential use cases where the content is always visible, and does not pop over. You want to put notes that is displayed along side the main content. On mobile, you could use display: none to make them popover, but if you display them as side notes, keyboard order is not going to be the same.
kizu: So if we had this mapping, it would be useful
kizu: two ideas: still use popover, removing the default style of display: none, e.g. making it visible, but not a popover by default.
we need to think about aria/keyboard order
second idea: allow making a popover open by default, but semantically different from just an in-flow element.
How do we handle an use case like side notes ?
anne: I like the use cases
anne: it doesn't work if you have multiple notes for one content
kizu: anchor positioning can do this with min/max calculations
<tantek> +1 anne. multiple footnotes for the same content / point in the text (I've had examples of this in my blog, and this is common in Wikipedia too)
kizu: one issue is the bottom of the doc, where overlapping can happen
fantasai: point is, we have a layout mechanism but not markup support for it
<TabAtkins> `.sidenote { anchor-name: --sidenode; top: max(anchor(--note1 top), calc(1em + anchor(--sidenote bottom))); }`
<TabAtkins> ^^^ Sit next to the anchor, or below any preceding sidenotes.
anne: using popover seems a bit wrong, i could imagine the aria mapping could get jarring for assistive tools
domfarolino: you probably don't want the top layer stuff
fantasai: you might want to introduce something else than popover, but what would that be
<fantasai> whatwg/
fantasai: there's an existing PR for the anchor attribute but only does rendering bindings
<tantek> +1 anne. being able to go from the ref to the footnote to the footnote and back to the ref. this is a common Wikipedia use-case.
anne: maybe it should impact focus, in addition to layout. The other thing you want for footnotes is going back to the content.
fantasai: There's two types of navigations if you have footnotes, you might want to navigate and skip through the notes, or you want to see the footnote now.
domfarolino: could we do something that expands the anchor attribute to handle focus stuff?
anne: needs more thought
<anne> See WICG/
<anne> [foolip is going over the details]
foolip: Text is a complex problem. People currently have to ship HarfBuzz to render text properly on canvas
foolip: it's hard to make accessible
[foolip loads a demo]
foolip: Chrome Canary, you can test this
foolip: What I'm showing here is a bunch of form controls rendered into a <canvas>. It looks just like if it was rendered outside the canvas.
foolip: The markup is just all the form controls wrapped in a <canvas>
foolip: And we call JS context.drawElement(...)
foolip: And I can interact with the element, edit the text, interact with the form controls, etc. because the hit testing is wired up to make it work
foolip: Here's a more complicated example, obvious it's not just HTML
foolip: We're seeing some text rotated 30deg. It has alink, Arabic, vertical Chinese, an nline image, svg, emojis, etc.
foolip: Source is just a <div> with all the text, svg, etc. marked up all inside a <canvas>
foolip: As you can see, hyperlinks work. You can right-click and save the wolf image here. Everything Just Works!
foolip: here's another demo. Two cards, one on the left, one on the right.
foolip: In between the cards I've painted a circle. You can mix canvas content and HTML, because your'e drawing these things.
foolip: That's the point.
foolip: We had a proposal to add a specific hit-testing API, but we found a better idea recently, so I will show the source
foolip: Source is the two cards, each is a <div> that's the child of the <canvas>
foolip: By default, all elements are painted at the top left (0,0) so if we want them elsewhere we have to move them.
foolip: We draw the element, adjust by devicePixelRatio, and then use a CSS transform property to move it.
foolip: But this is something, we would like to just call getTransform and have it do the right thing
foolip: But need to work on this. Set up the transform automatically when you call drawEleentImage or something
foolip: Hoping to also discuss the internals of this, implementation concerns in other engines to make this work
<anne> foolip: Want to discuss hit testing and the processing model.
foolip: This paints the element immediately, and then you can read back the pixels, so you need a clean layout state
foolip: Given how we expect devs to use it, we don't think it's going to be a problem, since theyr'e likely to use resizeObserver etc.
foolip: But there's some concerns around timing
foolip: So that's the demo! Let's do some discussing!
<anne> masonf: how are the elements exposed in the AT tree?
masonf: Can you talk a bit aobut how the elements are exposed in the a11y tree?
foolip: Both hit testing and a11y tree, there's an opt in here. There's a new attribute on the <canvas> element (currently called 'layoutsubtree'). The attribute lets us change some defaults.
foolip: if you use the attribute, everything will be hit tested, and everything will be exposed to a11y tree
masonf: Only children, or all?
foolip: Problem is we can't know when you stop drawing an element
foolip: So rather than putting it in the a11y tree and hit testing when you draw it
foolip: Would need to hide it or something
foolip: We want a very strong incentive to keep that subtree in sync with reality
foolip: ...
foolip: Making them hit-testable, people will be more likely to notice there's a problem and remove them from the tree as they should.
emilio: Seems to assume you can paint on main thread with all the CSS rendering, and do synchronously
… it constrains how you can implement it
… We've made a lot of effort to move a lot of rendering to the GPU, and this prevents or causes a synchronous round trip to compositor, which is not great
… forces us to draw on main thread
… Definitely better than what people do now for small stuff
… but if point of this API is to make these interactive use cases very easy to do
… people will inevitably use it for a lot of interactive stuff
… and problem with canvas is then you need to repaint every frame
… and you don't get a lot of the painting optimizations you'd otherwis eget
… I think it would be better if we came up with a way that you could still draw the element on the compositor
… It's annoying for WebGL, because you need the texture size up from, but seems workable
… API shape would need to change
… but if you say hey, drawElement, it could stash a reference ot the element in a way and re-use the normal rendering pipeline to eventually get that into the <canvas>
… That's a bunch of constraints like you can't immediately read pixels...
jake: why does it need to be synchronous?
emilio: also the fact that you're supposed to draw the element in the current state that you need to paint. You drawElement and then change innerText. Can't wait for regular rendering to update
… want to use the same compositing round trip
foolip: Would love to hear from other impls
smaug: cross-origin iframes creates a problem
… not even painting, but just hit-testing is an issue
foolip: What should happen is having no effect that you can observe
… should be as if not there
schenney: In Chrome right now cross-origin iframes are not drawn and not hit-tested
<Zakim> Jamie, you wanted to ask about how content outside of HTML-in-canvas is exposed to accessibility, canvas fallback content
Jamie: So it's hit-testable the same way normal HTML is hit-testable. That would translate to a11y just fine
… But ocntent outside the HTML canvas, not accessible. Except fallback which is not hit-testable
… If we are seeing more content insied HTML <canvas> that's not accessible, seems a problem
foolip: Do you mean for cases that mix fallback content and rendered content?
Jamie: [missed explanation]
… Seems like we'd get only half the accessibility
foolip: Let's say it's complicate, and game with WebGL menu
<schenney> I can answer to some extent.
foolip: you'd have a problem with how to expose those bits
Jamie: We'd say the stuff inside is accessible, but not the other stuff
foolip: Expose other content
Jamie: Then you'd have a hit-testing problem
Jamie: We need to solve this one way or another. Happy to be part of the conversation.
foolip: People talking about using this, use case where you have UI drawn in canvas is not that big
… more like text with some graphical effects
Jamie: Yes, but if people can use it they wil
schenney: Follow up on a11y
… we definitely won't be making it any worse
… One advantage of hit-testing canvas children is that you're more likely to notice if your fallback content is incorrect because you'll hit-test it
… Weak argument but worse to not see at all
… If you want HTML to stack right to hit test, you'd need to put some DIV or something to represent the canvas in the middle
… You will need some text to put in that node to put in that drawn layer
… So that will also help
… By no means do we claim this will fix all the canvas a11y problems, definitely more to be done there.
ntim: I heard some talk around cross-origin iframes. Are there any security considerations?
jake: Anything sensitive isn't drawn. Cross-origin images, iframes, not drawn.
foolip: [shows spec] This is list of things we would not draw: cross-origin data, system colors, spelliing and grammar markers, search text, visited link info, autofill info
jake: You lose functionality if you paint a form
foolip: A little bit yes, but with ?? options is to build everything with JS or they use system theme color in those form previes
… but we're building form for other peopel to use. If it has default style, it's stil lusable
… But [missed]
emilio: Is the attack here being able to read the pixels, or more subtle like timing attack?
… As a developer it might be a good compromise to ...
… similarly, async thing, that needs to prevent readback, but that forces you to keep your ocntent unmodified if you want it to be drawn
… otherwise your hit testing breaks, if you drawElement, change content, and drawElement again
foolip: Issue is you can't taint WebGL. It goes into a shader, can extract information
… So we want to work without tainting first
… but open to a tainting mode
… but trying to make as useful as possible without tainting, and it looks like we can get pretty far
zcorpan: Have you thought about not leaking sensitive info injected by web extensions?
<tantek-projector> +1 zcorpan
schenney: I'd have to think about that
chrishtr: If injected into DOM, the site can read it anyway
emilio: Could put it into a closed shadow root
<br type=lunch>
Some recent Naivgation API spec issues
Some recent Navigation API spec issues
Some recent Navigation API spec issues
<westbrook> smaug: Navigation API is part of Interop 2025
<westbrook> smaug: it's been in the spec many years as well as some tests
<westbrook> smaug: however, those tests don't _always_ match the spec
<westbrook> smaug: specifically in some timing issues
<westbrook> smaug: how do we ensure that when we write tests they follow the spec and how do you get right to submitting an issue when we find issues with the spec
<westbrook> smaug: is there something in our processes that do not require us to review the tests that we write?
<westbrook> smaug: are we not following the active changes of the specs over time?
<westbrook> anne: we mainly trust the implementation process, which isn't always great
<westbrook> anne: sometimes even coverage isn't sufficient to follow the actual implementation/spec in other implementations
<westbrook> anne: these cross implementation processes are hard, so following the other engines in their native processes can be awkward
<westbrook> smaug: what can each of our orgs do to make this easier for other teams
<westbrook> smaug: this has shown itself in various recent things, not just the Navigation API spec
<westbrook> anne: in this case, maybe it was igalia that did much of the early implementation
<westbrook> anne: webkit maybe simply followed the tests when they came behind
<westbrook> noamr: when we make tentative tests into non-tentative tests, maybe this is a better point to align across implementors and spec on these features
<westbrook> noamr: coverages, correctness, etc. before getting into phase 3
<westbrook> noamr: it's possible in large specs like Navigation API might not be possible to fix
<westbrook> noamr: the bigger the change, the bigger the chance for human error
<westbrook> noamr: the first implementation has a large number of interaction loops (internal, with the spec, with origin trials, etc) that can lead to misalignment in general
<westbrook> anne: I've seen the same with Scoped Custom Element Registries, being ahead of others at implementation time can be difficult
<westbrook> foolip: chromium looking into what a "comprehensive test suite" looks like in ensuring that their contributions are hitting some similar bars in this area
<westbrook> foolip: can share examples
<westbrook> foolip: experimentally, I've attempted to use AI to test alignment between specs and WPT tests that reports bugs, misalignments, etc as a high level comparison
<westbrook> foolip: won't internalize how things work or intersect with each other, but can call out "ooopsies" around things not tested, etc.
<westbrook> foolip: possible that this sort of process with even a 20% failure rate would be a good step up from current approaches
<foolip> example report from the AI tool: https://
<westbrook> zcorpan: if there's a review item that involves relating changes in the implementations back to spec issues/changes that would be helpful
<westbrook> zcorpan: maybe as implementation gets further from the core of a team this isn't happening quite as much
<westbrook> zcorpan: less likely to happen during incubation time
<foolip> This is the kind of prompt that I used, which also includes our WIP definition of "comprehensive test suite": https://
<westbrook> smaug: mozilla has started doing line by line comments around what they've implemented and how it related to the spec
<westbrook> domfarolino: trying to pair fast iteration locally with tests in WPT
<westbrook> domfarolino: this API is huge and the fact that it came together with just 14 bugs is great
<westbrook> smaug: yes, but why was the next implementor required to open them
<westbrook> smaug: realized this reality quite late in the process
<westbrook> domfarolino: did Chromium maybe not run into the same issue that Gecko did during implementation time
<westbrook> domfarolino: did igalia do most of the implementation?
<westbrook> anne: igalia not here after most of the work, but webkit follow behind what was there
<westbrook> foolip: in interop when tests are in a specific area that don't match the spec then we take them out
<westbrook> foolip: there's a test change proposal process for changing them and keeping them, but start with getting them off the sheet if they're not inline with the spec
<westbrook> foolip: that doesn't resolve the larger interop problem between the implementations
<westbrook> smaug: should we then exclude these 7 failing tests?
<westbrook> smaug: would the 4 after that need to change?
<westbrook> smaug: foolip: shared an additional test beyond that that is misaligned
<westbrook> smaug: the spec is very clear, but the tests are testing chromium's implementation
<westbrook> smaug: there's an extra microtask in the implementation there
<westbrook> noamr: I wanted to make sure that I agree with that process because it is the only spec'd case where there's only one microtask instead of 2
<westbrook> noamr: we can decide on either, no strong opinnion
<westbrook> miketaylr: this process issue, is it more acute during "Interop" or is it general across other APIs
<westbrook> smaug: see trusted types, even though there were a lot of tests, they we're all in alignments/passing in implementations
<westbrook> miketaylr: can we then simply correct the tests
<westbrook> anne: sometimes yes, but that hurts "Interop" and _sometimes_ web compat.
<westbrook> noamr: yes, we want to ensure that following the spec allows for not breaking compat.
<westbrook> foolip: have you submitted PR with the changes required to match the spec?
<westbrook> foolip: that would be needed at some point.
<westbrook> foolip: you might just merge the PR, and if it just gets blocked on interop the team will review it on about the weekly basis
<westbrook> foolip: there's less paper work that way
<westbrook> anne: if you do that, if you upstream updated tests from your local implementation doesn't that cause issues?
<westbrook> foolip: we have this with chromium, things being blocked for a week aren't that big of a deal
<westbrook> anne: what if there are further tests?
<westbrook> foolip: harder, requires the team to interceed, but doesn't happen that much
<westbrook> noamr: the removal of "waitforall" woudl likely be best at the Interop level, so we have time to confirm we don't break compat
<westbrook> noamr: we can find the places that require the current timing and x-browser confirm their reliance on it
<westbrook> zcorpan: we've run similar and not found issues so far
<westbrook> foolip: is the issue that waitforall is one microtask or two?
<westbrook> noamr: alters the order of events and nativations
<westbrook> zcorpan: especially if you have two sync navigations
<westbrook> zcorpan: changes the communicated results of the algorithm
<westbrook> noamr: but still mostly an edge case.
<westbrook> smaug: feels a little better running through these things together
<westbrook> smaug: we'll submit PRs removing these tests
<westbrook> noamr: not failing sites that use these APIs make removing these from Interop feel good.
<westbrook> foolip: then can we just change the tests?
<westbrook> noamr: change the tests and exclude them!
<noamr4> ScribeNick noamr4
Optimization to avoid duplicate navigations
Rakina: Rakina from Chrome, optimizing navigations
… navigation, and soon after another one
<noamr> ... potentially wasteful. first request sent, second is a dup
<noamr> ... proposal is to not waste the ongoing navigation. based on some criteria
<noamr> ... url, initiator, cookies, headers, start delta within a timeframe
<noamr> ... decreases the response from the server. decreases latency
<noamr> ... we see decreases in exact duplicates, server responses that were never shown to the user (tested by a beacon)
<noamr> ... various approaches on how to do this; ignoring the 2nd nav entirely; this is web observable
<noamr> ... e.g. webdriver events, service workers, navigation timing timestamps, click handler fired twice but navigated once
<noamr> ... opt-in? URL with specific params? headers? needs to be before. URL
<noamr> ... approach 2: transform the first nav to be the 2nd nav. pretend that the first cancel the first nav, but really ignore the 2nd and transform the 1st to the 2nd
<noamr> ... can also be weird if fetchStart/navigationStart are flipped
<noamr> ... approach 3: network layer. cancel the 1st navigation but pass the network pipe to the second navigation
<noamr> ... can be kind of like prefetch
<noamr> ... complex in spec/impl
<noamr> anne: how is this different from 2?
<noamr> rakina: it's updating the properties of the navigation
<noamr> ... in all those approaches SW is not visible
<noamr> ... wanted to get some thoughts
<noamr> ... which layer? navigation layer? network layer? criteria?
<noamr> ... same URL, referer, history, GET, <=3s, cookies
<noamr> domfarolino: 1 vs. 2, we're still dropping one of the navs.
<noamr> rakina: 1/2 mostly matters in implementation
<noamr> rakina: for (2) we actually cancel the 1st navigation
<noamr> domfarolino: (1) seems more logical. it's weird to cancel the 1st
<noamr> ... hard to judge the differences
<noamr> anne: all this only applies before the navigaiton is committed
<noamr> domfarolino: with (3) what would be the navigation timing
<noamr> ... do we get 2 results?
<noamr> rakina: it's only visible once you committed
<noamr> e.g. fetchStart
<noamr> rakina: maybe (1) is the simplest approach
<noamr> anne: the problem with (1) is that the cookie check is async
<noamr> domfarolino: either way it would be parallel
<noamr> smaug: about the problem itself, I wonder if this is just a UI issue
<noamr> ...: you probably don't know that you're navigating/loading anything
<noamr> rakina: might be. sometimes it's a matter of milliseconds
<noamr> rakina: we collect the timestamps when initiating the navigations
<noamr> euclid: so usage statitics?
<noamr> rakina: yes
<noamr> zcorpan: in option 2/3 re. navigationStart, would it be from the 2nd navigation in (2) (3) and the 1st navigation for (1)?
<noamr> rakina: we might need to expose navigationStart
noamr: specwise we can do this already, deal with it as if it was the HTTP cahce.
… someplaces we do things differently, since fetch doesn't specify exactly what the cache is.
… in some case, the response might not be there already.
… it's vague what's happening in HTTP cache.
zcorpan: it's the model with the cache, stored with the full response, use it while streaming
noamr: I guess that's not allowed in the model, but that's what we want, too.
… it would look like there are two separate fetches, the second would be an immediate navigation.that would expose that it wasn't immediate.
… I think we should do something similar to option 3. there are some places where in flight you could call this...???
… preloads are before service workers.
anne: fetch describes fetch layer and network layer separately.
noamr: with preload specifically it doesn't do another fetch
<zcorpan> maybe pretend that the first navigation was a nav prefetch
<noamr> kouhei: strong for option (1) is that it's most straightforward
<noamr> kouhei: service worker is before HTTP cache, so it would be before SW, so a new cache layer
<noamr> ... so my preference would be option (1)
<noamr> domfarolino: also for option 1
<noamr> zcourpan: we can pretend it's a speculationrules prefetch
<noamr> zcorpan: only in the web exposed sense
<noamr> zcorpan: like option (1), and add activationStart for the timing of the 2nd navigation
<noamr> domfarolino: what does webdriver do?
<noamr> zcorpan: if we cancel (2), it would look like the 2nd nav was cancelled
<noamr> domfarolino: why expose it as a prefetch?
<noamr> zcorpan: it's the closest thing I could think of
<noamr> domfarolino: I think we should cancel the 2nd navigation and point navigation timing to the 1st. It's the most consistent
<noamr> anne: could we race the navigation? do you have metrics like network topology changing between navigations? What if the user ends up pressing refresh? Is that a bypass?
<noamr> rakina: there is a time threshold
<noamr> kouhei: can we leave some of this to be implementation defined?
<noamr> domfarolino: I would be fine with that
<kouhei> ^ specifically about the timing threshold
<noamr> zcorpan: I prefer it to be specified and interoperable
<noamr> zcorpan: might be web compat issues
<noamr> takashi: what if the nav opens a new tab
<noamr> rakina: we check if the frame is the same
<noamr> domfarolino: can we resolve on option 1, and try to spec that with some threshold we agree on later in an offline discussion?
<noamr> rakina: currently it applies also to programattic navigations
<noamr> domfarolino: we should not do this for user-involved navigations
<noamr> anne: not sure about that
<noamr> cwilso: let's follow up on this as a detail
<noamr> whatwg/
Allow deferring commit of a same-origin cross-document navigation
[noamr explains the link above]
noamr: we want to experiment with pre-rendering the subsequent document in the background
noamr: and we want to let the old document delay the navigation commit so it can finish some processing
noamr: all of this with the goal of reducing the transition time between two same-origin documents the end user navigates between
anne: with the possible usage example, how does the deferCommit know when the next document is ready?
noamr: it doesn't, it only renders a skeleton
noamr: this is not directly related to view transitions, but it's useful for view transitions
noamr: as. they're the only API that let's you customize the navigation experience
sisidovski: what's nextDocumentReadyToRender?
noamr: I think bfcache or pre-rendered
jake: what happens if you go back, as now the skeleton would be there which makes the document unusable
noamr: example is incomplete, you'd need to do more
noamr: could use some improvement
Takeshi(?): do you have more future plans or if you just want to do this we could also extend view transitions?
noamr: you might want to defer for non-UI reasons, such as storing app state
noamr: I'll make it a proposal and propose for Stage 1
Out-of-order HTML streaming #11542
out of order html streaming
github: whatwg/
<foolip> presenting https://
noamr: this is about out of order streaming, discussed at WHATNOT a few times
… a lot of frameworks / websites do
… they put some parts of the HTML first, and as the server knows more stuff they bring that stuff in
… right now that works with inline script tags and such, which is not as fast as it should
… so would be good if sites wouldn't have to reinvent it
… we settled on this approach, a placeholder with contentname
… and a template with contentmethod attribute
… the internal children would have the same tagname and contentname, and children would stream directly into the placeholder
… forcing the same tagname causes the parser not to change considerably
… don't have to change raw text or anything like that
… we have 4 content methods
… replacechildren, replacewith, prepend and append
… this is about it in terms of content for the first iteration of it
foolip: [screenshares example]
foolip: lots of internal details we could talk about
emilio: in this replace example, would you actually replace the domnode or just change the attributes?
foolip: we have this wireframe example with the classname
… and replace would end up "removing the attribute"
anne: This would change the node identity
emilio: that was the question, thanks
westbrook: you can get this by attaching a shadow root on the body and attach out of order content via slots
noamr: that solves only some of the use cases
westbrook: what's the use case for append / prepend
<jridgewell> Incrementally streaming unknowably many children into the content, interleaved with streaming to other content
ann: can you elaborate on the slot stuff?
emilio: you can have a shadow root on the <body> with different <slot>s and stream the body content into each slot separately
… which achieves the same thing
YY: looks like this example the parsing comes before
… we try to do the patching after the rendering
<westbrook> Example of the above shadow DOM approach: https://
YY: and patching would change the contents
foolip: you mean after the document would be parsed already?
noamr: Rendering can happen during this time, but if you finished parsing already you can't [...]
… we first had it as one proposal, with javascript streaming, which would do what you want
… we made those proposal totally different in terms of spec or api
foolip: for your use case just keeping the stream open for longer would be more useful
YY: I want to just render a template but after rendering patching the contents
… is that supported?
noam: As long as the response didn't close yes
… whether that's the optimal architecture vs closing and starting a new stream not sure, not opinionated
foolip: you could combine it with the JS API to stream templates to modify the existing document too
… and use the same markup
rniwa: one question, in the example you had a template element instead of an <aside for the contentform>
… why is this not in the <template>?
foolip: It's important that we handle the parser ??
… let's say the first thing was a table
anne: insertion mode inside a table depends on the first tag
noam: script is a mess
… you need to put that in a special text mode
… and then if you don't support the feature you interpret it
rniwa: but you only support one element within a template?
foolip: no, multiple
rniwa: how does replace deal with this?
noam: The template content method means this is a batch, each child within is separate
… if you have another <aside> with a content name it'd be like a new replace
foolip: so let's say you have two different things
… then you patch them in whatever order
rniwa: so what if the element name with the attribute is different from the original?
foolip: different ways to write it in the spec, but the rule is look up the first element in the tree using contentname
… then the local name and namespace have to match, if they don't then you don't keep looking for other elements
keithamus: Curious about script, what happens if I replace a script?
… e.g. <template contentmethod=replace><script contentfor="...">...</script></template>
foolip: same rules apply, you have script with no children and pass it a text child it'd execute, but it falls out of that situation
keithamus: what happened if I modify the dom before reaching the template
… like adding a contentname?
foolip: just works, would use the dom at that time
keithamus: this is like htmx and ??, have you asked those developers and see what's missing?
noamr: Yeah also github, we have various responses, some are public in the repo
… a lot of this is after all those feedback
… there was another feature request to replace a range not between elements, which could be an extension to this
… we've given lot of discussions between people that are doing
keithamus: any feedback on what's missing?
noamr: yeah the range thing and script comes up
keithamus: I can introspect the template after the parsing is done?
foolip: just like <template shadowrootmode>, that's not re-inserted, additional nodes go in the void
keithamus: so silent failures if I made a typo?
noamr: Yeah I think we need to come up with error event
hsivonen: the <script> topic is very concerning
… if the parser flushes within a text node that'd cause a partial script to be executed
… the model for script should be closer to the regular execution, you run it at the end tag instead of allowing partial insertion of text nodes
… there was a remark about whether the html comes from the document is distinct from the JS
… the streaming sanitizer supposed to work with the JS API or is it also expected to interact with the network stream?
foolip: sanitizer applies for streamHTML (the js api)
… the main parser doesn't have a sanitizer, there's a need that would be worth discussing
… first question about <script> is a great point, not 100% sure what does per spec or as implemented, we shouldn't do that
noamr: would be a bug to fix
hsivonen: if the method is not append / replacechildren, what is the reference point in the document that we'll be inserting to?
… if the <aside> element previous siblings and next siblings, what is the insertion point?
… replace replaces the element itself, is it always going to be one element of the template, or can you replace a node with multiple?
foolip: it'd replace multiple times
… prepend is the trickier case
… the way it currently works is when we find the content name, then save the first child of the content target, and then when we insert before that node as long as it's still under the same node
noamr: insertBefore semantics, and if it's not valid it errors the whole thing
hsivonen: is this something existing libraries are demanding
noamr: Replacing a range was the main use case
hsivonen: why is it important to be able to replace a range without a wrapper?
noamr: rows of a table or <meta> in <head>
anne: if there's a lot of content at the end the load wouldn't fire, is that problematic?
foolip: then you'd use the JS API
(mainly DOMContentLoaded, but yes)
foolip: this is not intended to long wait, just waiting for the backend to fill the content
westbrook: would this recurse, e.g. if I replace with a child that had contentfor...
foolip: no, the parser is going to insert an element
noamr: It recurses the root for looking up the name is the parent of the template
westbrook: so if I have contentname=first and replace that with <div contentname=first><div contentname=second></div>
… would it recurse if I have a <div contentname=second> on the template?
foolip: it wouldn't recurse just apply the same thing again
westbrook: would that work?
<masonf> but who's on first
foolip: yes, we'd look by contentname
keithamus: you said the template parent's children?
… or descendants?
noamr: descendants of the template
… exception would be if the template is a child of the <body> where the root would be the whole doc
JakeA: The same issue with <script> happens with <style>
… and maybe <media>
foolip: video resource selection is weird but that makes it work in this case
JakeA: what happens during innerHTML
noamr: It works but the parent of the template is what you're inserting into
… so you're only patching what's on your template
keithamus: weird that it works with innerHTML because declarative shadow root doesn't
… would be good to double-check why
zcorpan: the reason for that would be to specify which shadow root
rniwa: main concern was script execution, a template insertion shouldn't execute script
anne: we should do the same here
hsivonen: is the patching itself intended to be streaming, in the <aside> example, do we first replace, then stream contents, or replace with the whole <aside>?
foolip: it's streaming
… which means the example is a bit weird because the wireframe has 3 and if the parser stops in the middle it jumps
… maybe we should look into that
clarifying worker lifetime relationship
Further clarify worker lifetime relationships
dom: this is a feature to extend the lifetime of workers
dom: people currently run into issues doing work at this time as it's unreliable. Some are moving this work to service workers, but that makes the service worker less responsive.
dom: two ideas: 1) PageHideWorklet 2) small extension to shared workers
dom: there's a specification PR for the second of these ideas and some tentative support from Mozilla
dom: there's an open discussion on the bfcache
[scribe missed a bit]
dom: how do you avoid holding the lock forever?
[missed]
dom: Chromium is experimenting with this
Yoshisato: current implementation doesn't care much about Web Locks or bfcache
Yoshisato: it currently doesn't bfcache, so extended lifetime kinda works
dom: does Chromium not evict documents?
?: we do
dom: the current behavior in Chromium is that when the shared worker terminates and all the client documents are in bfcache, they are evicted
?: the freezing just solves the eviction, it doesn't help with the locks
dom: if there's a reasonable answer for bfcache, can we have support from Mozilla?
zcorpan: yes
dom: need to be more rigorous about bfcache and then we can merge it
anne: don't forget about tests
?: extended lifetime is 5min in Chromium
dom: could maybe add some WebDriver API
<rakina> ? is fergal
fergal (? above): it'd be good to have more WebDriver coverages in specifications
dom: I'm happy
Bikeshed (away)
foolip: HTML is written in a dialect of HTML called Wattsi
foolip: nobody that's still around really knows how it works, but Mike(tm) knows a fair bit
foolip: as such I've been looking into a shift to Bikeshed
[foolip shows the setup]
[quickly pushes a WIP branch so people can try it at home]
foolip: when building you currently hit 50k of warnings/errors
foolip: but you don't need to worry about that [I think we should]
[foolip is quite proud of the HTML standard kinda working :-p]
foolip: Wattsi uses data-x attributes for uniqueness (with text content fallback) and Bikeshed is quite different from that with lt and for attributes, and more
<smaug> Does this bring the rather bad animation (speced/
anne: we need to manually set the IDs to data-x so that the IDs are preserved
dom: do you create nested structures with for attributes and such as is ideally the case?
foolip: thus far I've not tried to account for that
anne: I think we might have to investigate existing `<dfn>`s so we can do this properly
anne: we already did this work for most of the IDL members so it seems tractable
zcorpan: cross-specification xrefs are also different, need to be removed from HTML as Bikeshed handles them
foolip: I was thinking of doing that after to make the diffing better
foolip: I also want to compare the generated DOM which is tricky
TabAtkins: multi-page output is next on my list
foolip: lxml?
TabAtkins: very close
foolip: replacing html5lib with lxml was a good speedup
[shows some graphics on screen]
foolip: a broken build is possible in <10s [hmm]
zcorpan: 10s seems acceptable to me [presumably if the output is non-broken]
Mike(tm): what's the wall-clock time? I need ms
TabAtkins: on my crusty laptop it's 65s without any kind of improvements; should be substantially faster with these improvements
Mike(tm): Wattsi is 12s for me, 60s seems very slow
TabAtkins: there's also some Rust conversion going on that might make it even quicker
<TabAtkins> "might", it definitely will make it significantly faster
keithamus: I think we should move ahead even if it's slow because it can be faster
dom: I think it needs to be faster
Mike(tm): I don't feel strongly about the perf, I was trying to paraphrase Domenic whose workflow needs a quick turnaround
dom: 24s seems acceptable
zcorpan: ditto
zcorpan: I'm assuming here we're going to improve beyond 24s
TabAtkins: I'm hoping we can get to 10s if we do all the todos
dom: how is the race between fixing issues and perf going to work out?
foolip: fixing issues is going to win
TabAtkins: agreed
foolip: how much Bikeshed Markdown should we adopt?
Mike(tm): I think for contributors full Markdown would be the biggest win, if we could get their eventually
zcorpan: not sure HTML should do block-level Markdown
anne: I care mainly about doing the `<dfn>`s and such properly; syntax feels secondary, but if it makes it easier we can convert the lot I suppose
Mike(tm): what about SVG?
TabAtkins: multi-page input already works, but multi-page output doesn't
TabAtkins: but that's being fixed
zcorpan: HTML Dev Edition?
foolip: TBD
TabAtkins: you can use the Status feature