Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Should Live Range expose endpoints inside a shadow tree? #1362

Open
dizhang168 opened this issue Feb 27, 2025 · 8 comments
Open

Should Live Range expose endpoints inside a shadow tree? #1362

dizhang168 opened this issue Feb 27, 2025 · 8 comments
Labels
topic: ranges topic: shadow Relates to shadow trees (as defined in DOM)

Comments

@dizhang168
Copy link

What is the issue with the DOM Standard?

While reviewing the Composed Selection Range PR, @annevk brought up a concern about the current spec, which makes it possible for getRangeAt(0) to expose nodes in the shadow DOM.

For example, what happens when a user selects inside a shadow tree only, to boundary points S1 and S2?

Currently, per the steps on how to set the start and end of a live range, this would return a live range at {S1, S2} since the nodes share the same root. That is the behavior in Chrome and Firefox.
Safari returns a Range collapsed at the shadow host.

Anne argues that this range should be rescoped to return the entire shadow host.

However, we (Chrome) are worried that changing this behavior will break sites that depend on getRangeAt(0) returning nodes in the shadow DOM, and don't expect the range to be "rescoped" to the ShadowRoot's host. Changing this behavior in the spec, and in 2/3 implementations, poses a compatibility risk that we think is worth exploring, but are not sure is feasible.

@annevk
Copy link
Member

annevk commented Feb 28, 2025

cc @smaug---- @emilio

@annevk annevk added topic: shadow Relates to shadow trees (as defined in DOM) topic: ranges labels Feb 28, 2025
@domfarolino
Copy link
Member

Thanks for filing, this is great to track. I will say I do think this can be separated from composed selection range work in #1342 and w3c/selection-api#345. Getting composed selection ranges wired up correctly and working across shadow DOMs seems tangential to this, especially since the issue here does not depend on the infrastructure provided by the composed selection work, and there are significant compat differences between the two efforts.

@annevk
Copy link
Member

annevk commented Mar 3, 2025

I don't see it that way. We haven't really attempted to tackle how shadow roots work with selections thus far, though I believe we had a shared understanding that selections would not end up exposing shadow roots. Now that we are in the process of formalizing how selections and shadow roots interact, this should be tackled as part of that (or before).

@domfarolino
Copy link
Member

But aren't the two problems separate? Not all browsers even ship getComposedRanges() and there's no spec infra to support it. Separately, we have the problem of 2/3 browsers exposing shadow roots through getRangeAt(0), and "fixing" it doesn't rely on the getComposedRange() spec work—it's just a decision we need to make based on compat risk.

That's what makes the two seem cosmetically similar, but actually quite separate in terms of feasibility. It'd be a shame to hold the former hostage to the latter, which has more compat risk than the former, and doesn't seem to depend on it either. Do you think it would be possible to land spec infra in DOM that supports getComposedRanges() before tackling this issue?

@smaug----
Copy link
Collaborator

https://github.com/mfreed7/shadow-dom-selection?tab=readme-ov-file#changes-to-existing-selection-apis has the section for Selection.getRangeAt() and that behavior makes sense. Not sure about the "Mutability of live ranges returned from getRangeAt()" part. That is a bit vague.
But what happens currently if getRangeAt(0) range is modified so that its boundary points point to a subtree which doesn't have document as root? I'd expect the range to be removed from selection, and that is how I'd expect the range to work also if one tries to set its boundary points to point to shadow DOM.

@dizhang168
Copy link
Author

But what happens currently if getRangeAt(0) range is modified so that its boundary points point to a subtree which doesn't have document as root? I'd expect the range to be removed from selection, and that is how I'd expect the range to work also if one tries to set its boundary points to point to shadow DOM.

Right now, the range boundary points will be collapsed at the new boundary point. The range will not be removed from the selection.

sel.setBaseAndExtent(container, 0, container, 3);
range = sel.getRangeAt(0);
range.setStart(shadowRoot.firstChild, 0);
console.log(sel.getRangeAt(0) == range); // returns true

@dizhang168
Copy link
Author

In the Selection API spec, the definitions for anchor/focus says:

Each selections also have an anchor and a focus. If the selection's range is null, its anchor and focus are both null. If the selection's range is not null and its direction is forwards, its anchor is the range's start, and its focus is the end. Otherwise, its focus is the start and its anchor is the end.

Note anchor and focus of selection need not to be in the document tree. It could be in a shadow tree of the same document.

Given this, the Selection API does expect the Range API to return endpoints that are within shadow trees.

@domfarolino
Copy link
Member

Given this, the Selection API does expect the Range API to return endpoints that are within shadow trees.

Yep, I think that's what @annevk is saying is a problem that was never really thought through, and should be fixed. I think I agree, but I just think that it can come after we fully specify getComposedRanges().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: ranges topic: shadow Relates to shadow trees (as defined in DOM)
Development

No branches or pull requests

4 participants