-
Notifications
You must be signed in to change notification settings - Fork 711
[css-highlight-api] maplike vs setlike #5910
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
Comments
Yeah, setlike should only be used if object identity is sufficient for membership. (Or, if a derived key is instead used for uniqueness, adding something else with the same derived key causes replacement, but that's treading on thin ice.) If uniqueness depends on a derived key and replacement isn't allowed, then it's not a setlike at all, it's a registration map with write-once semantics, and should be a maplike. |
The original explainer did use maplike for this (the type was originally called That's why we went with the current approach. Do you think one of the other options is better, or do you have any suggestions for a different solution? |
@sanketj Just so I understand the problem: what was the issue with having the same highlight object registered multiple times under multiple names? Why did this need to be prevented? |
Even if we allowed the same highlight object to be registered under multiple names, only one name can be reliably used to style the highlight. If the highlight were to be styled using multiple names, in the case of conflicting styles, the styles for the last registered name would always be painted on top and there would be no way to 'prioritize' the styles for names that were registered earlier. This could be confusing for authors because the paint order may not reflect the expected cascade order. For example, consider the following style rules where the same highlight object is registered with names 'foo' and 'bar', and 'bar' was the last registered name:
Each rule targets the same highlight and has the same specificity, therefore authors may expect the last rule to win and the color of the highlighted content to be green. In reality, Though this is technically not a cascade violation, it is definitely confusing behavior. So I think it is best to enforce that a highlight object can only be registered with a single unique name. |
In short:
Another alternative could be to switch back to a map, and do something if an already registered highlight gets registered again under a new name (throw? remove the older one?). Maybe you can help me think through something here: can we reliably test object equality in JS? Or maybe we switch back to map, and allow duplicate entries (with at most, a warning in the console), and just advise authors not to do that… |
@sanketj Isn't this the same in terms of author experience as a new highlight being registered that spans the same text as another highlight? (which is allowed)
It depends. What kind of equality would you like to test? |
@LeaVerou It is different from the overlapping highlight case because those are actually separate highlight objects. Authors will expect the styles for the two highlights to be independent, and they have the option to control which styles paint on top via the That said, if all we are debating is maplike vs. setlike, I do agree with @frivoal that we could switch back to maplike and override the 'set' operation to throw if we try to register a previously registered name. |
Summarizing a few approaches based on this thread for our vF2F discussions: Approach 1 (what is currently spec'ed): Approach 2: Approach 3: |
I'm not convinced this is a conceptual difference for authors vs an implementation detail.
This sounds like it highlights a problem with the current design, rather than a reason to create an error condition. It sounds like the I'm also not sure the inability to specify the priority for this edge case is that much of a problem. |
The CSS Working Group just discussed
The full IRC log of that discussion<Rossen_> Topic: maplike vs setlike<Rossen_> github: https://github.com//issues/5910 <TabAtkins> fantasai: A custom highlight is made of three things: the Highlight object (a bunch of ranges), then a priority to know where it stacks, then a name so it's addressable from teh stylesheet <TabAtkins> s/fantasai/florian/ <TabAtkins> florian: Question is how to group these <TabAtkins> florian: Could say priority is an attribute of the highlight object <TabAtkins> florian: But what about the name? <TabAtkins> florian: One is a Map where key is name and vlaue is Highlight <TabAtkins> florian: Another is a Set where name is a property of Highlight. <Rossen_> s/maplike vs setlike/Highlight API collection, maplike vs setlike/ <TabAtkins> florian: If you use a Map, you coudl potentially register the same highlight multiple times under multiple names. <TabAtkins> florian: Has some odd ergonomics for user. <TabAtkins> florian: You style ::custom-spelling and ::custom-grammar, but they have the same priority, it's got some odd stacking. <TabAtkins> florian: Not *hard* to explain or implement, just unintuitive. We consider it a footgun. <TabAtkins> florian: So we decided to make it impossible to set up the same highlight multiple times. <hober> q+ <TabAtkins> florian: So we switched to a Set that throws if you register multiple times. We could also have a Set that just ignores if you set multiple. <TabAtkins> florian: Or a Map that throws if you register multiple. <TabAtkins> florian: Or we could just ignore it all and let it happen. <leaverou_> q+ <TabAtkins> florian: Currently the spec has it as a Set where name is an attribute, and it throws if you register the same thing twice. <TabAtkins> florian: But that's unusual. <TabAtkins> florian: Simplest is a Map that doesn't throw, but that might not make sense. But maybe that's fine. <TabAtkins> hober: This came up in a TAG review <Rossen_> ack hober <TabAtkins> hober: been several months so convo is swapped out by now... <TabAtkins> hober: But i remember being surprised about, it would be common to write code that says "have I registered this yet? No? then add it" <TabAtkins> hober: Might have a few libraries that use highlights for various purposes, and they don't want to clobber themselves <TabAtkins> hober: With a Map that's super easy <TabAtkins> hober: just check the key <TabAtkins> hober: With a set you have to iterate <TabAtkins> hober: We thought that's weird, we expected checking to see if it's registered to be a common op <TabAtkins> hober: I think we saw the ergonomic downside as more of dev inconvenience than the dev registering the same thing multiple times <TabAtkins> hober: So I think we're inclined to just let the dev hurt themselves if they want to register things twice <TabAtkins> hober: Not a hill we want to die on, just want common operations to be easy. <sanketj> q+ <TabAtkins> florian: With time that has passed since original decision, sounds good to me <Rossen_> ack leaverou_ <TabAtkins> leaverou_: Agree with hober, she said most of what I wanted to <TabAtkins> leaverou_: I think using try/catch every time you register a highlight isn't ideal <TabAtkins> leaverou_: I think there might even be use-cases for doing this - providing aliases for the same highlight <TabAtkins> leaverou_: Sanket pointed out the problem is the priority (can't set it in that case), but that sounds like priority is associated with the name rather than the Highlight... maybe it's misplaced? <TabAtkins> florian: I thougth about that, but then how would you set it? <TabAtkins> sanketj: Design I had in mind originally was every Highlight has one name and one priority, and that's reflected in the spec we have today. <TabAtkins> sanketj: You could say the prio is associated with the name rather than the highlight, but you'd need a different data structure <TabAtkins> Rossen_: What's your position on the change to use Map? <iank_> sanketj: likely want an options arg for the ctor, e.g. "new Highlight({name: 'hi', priority: 2})" <TabAtkins> Yeah, it'd take a sequence or options object instead, i guess <iank_> can't it be a maplike with an additional convenince function? <TabAtkins> sanketj: hober and leaverou_'s argumetns make sense. And I think associating prio with highlight is convenient; I'd prefer not to change that if there's not a big reason to <TabAtkins> sanketj: If we do allow a highlight to have multiple names, what's the messaging around it? <TabAtkins> sanketj: Lea mentioned a use-case; I always thought about this as making a separate Highlight object, then they can prio against each other properly <TabAtkins> sanketj: Sounds like you were suggesting having the same highlight be prio'd two different ways, which might be more complicated <Rossen_> q? <TabAtkins> florian: I think the proposal is to just do it the naive way - same highligh under two names would share prio <TabAtkins> florian: So painting order would use the fallback of registration order <TabAtkins> florian: A bit limiting, but it's not there *because* of the use-case, it's just the natural fallout. <TabAtkins> florian: And if people find ways to make it nice for them, sure. <leaverou_> +1 to florian <TabAtkins> florian: Probably it's a footgun, but possibly there's good things to come out of it <iank_> e.g. ```interface Highlights { readonly maplike<string, Highlight>; addHighlight(Highlight or HightlightDictionary); }``` <TabAtkins> sanketj: Do we want something in the spec warning against it? <leaverou_> Yes, this would need to be a note in the spec <TabAtkins> sanketj: Seems could be unexpected results <TabAtkins> florian: Don't think we should have a normative thing, but a Note saying this would be odd if you did it woudl be approriate <TabAtkins> leaverou_: agreed <TabAtkins> sanketj: We could just document the case from the issue <TabAtkins> sanketj: Seems fine <TabAtkins> Rossen_: Sounds like we're approaching a reoslution? <TabAtkins> iank_: I left some IRC comments <TabAtkins> iank_: You don't need to strictly make it a setlike - could add convenience functions <TabAtkins> iank_: Dunno if this changes the discussion particularly <TabAtkins> florian: Not sure what's being proposed to help here <TabAtkins> iank_: could make it a readonly maplike, then provide an add() that takes a Highlight, plus a remove() <TabAtkins> florian: Does that bring us back to what we have today? <TabAtkins> sanketj: I think the impl is that the name would live on the highlight, and also be exposed as a key on the readonly maplike <TabAtkins> TabAtkins: I don't think the3re's enough worth innovating in data structures, versus just letting authors do this <TabAtkins> porposed resolution: Switch Highlights back to a maplike of (name)=> Highlight, add a Note about what happens if you register the same highlight with multiple names <TabAtkins> leaverou_: Just wnat to make sure that if you register to an existing key, it doesn't throw - that was mentioned in the ear4ly options <TabAtkins> florian: Right, normal Map behavior <TabAtkins> RESOLVED: Switch Highlights back to a maplike of (name)=> Highlight, add a Note about what happens if you register the same highlight with multiple names |
Making some updates to the implementation because the specs changed https://drafts.csswg.org/css-highlight-api-1. - Convert HighlightRegistry from setlike to maplike. - Highlight doesn't contain the highlight name anymore. - HighlightRegistry::setForBinding() doesn't throw anymore when inserting an existing key again. Relevant discussion: w3c/csswg-drafts#5910 Bug: 1197739 Change-Id: I24f69b5a09938fcda5af353cbd41899dc736cbf1
Making some updates to the implementation because the specs changed https://drafts.csswg.org/css-highlight-api-1. - Convert HighlightRegistry from setlike to maplike. - Highlight doesn't contain the highlight name anymore. - HighlightRegistry::setForBinding() doesn't throw anymore when inserting an existing key again. Relevant discussion: w3c/csswg-drafts#5910 Bug: 1197739 Change-Id: I24f69b5a09938fcda5af353cbd41899dc736cbf1
Making some updates to the implementation because the specs changed https://drafts.csswg.org/css-highlight-api-1. - Convert HighlightRegistry from setlike to maplike. - Highlight doesn't contain the highlight name anymore. - HighlightRegistry::setForBinding() doesn't throw anymore when inserting an existing key again. Relevant discussion: w3c/csswg-drafts#5910 Bug: 1197739 Change-Id: I24f69b5a09938fcda5af353cbd41899dc736cbf1
Making some updates to the implementation because the specs changed https://drafts.csswg.org/css-highlight-api-1. - Convert HighlightRegistry from setlike to maplike. - Highlight doesn't contain the highlight name anymore. - HighlightRegistry::setForBinding() doesn't throw anymore when inserting an existing key again. Relevant discussion: w3c/csswg-drafts#5910 Bug: 1197739 Change-Id: I24f69b5a09938fcda5af353cbd41899dc736cbf1
Making some updates to the implementation because the specs changed https://drafts.csswg.org/css-highlight-api-1. - Convert HighlightRegistry from setlike to maplike. - Highlight doesn't contain the highlight name anymore. - HighlightRegistry::setForBinding() doesn't throw anymore when inserting an existing key again. Relevant discussion: w3c/csswg-drafts#5910 Bug: 1197739 Change-Id: I24f69b5a09938fcda5af353cbd41899dc736cbf1
Making some updates to the implementation because the specs changed https://drafts.csswg.org/css-highlight-api-1. - Convert HighlightRegistry from setlike to maplike. - Highlight doesn't contain the highlight name anymore. - HighlightRegistry::setForBinding() doesn't throw anymore when inserting an existing key again. Relevant discussion: w3c/csswg-drafts#5910 Bug: 1197739 Change-Id: I24f69b5a09938fcda5af353cbd41899dc736cbf1
Making some updates to the implementation because the specs changed https://drafts.csswg.org/css-highlight-api-1. - Convert HighlightRegistry from setlike to maplike. - Highlight doesn't contain the highlight name anymore. - HighlightRegistry::setForBinding() doesn't throw anymore when inserting an existing key again. Relevant discussion: w3c/csswg-drafts#5910 Bug: 1197739 Change-Id: I24f69b5a09938fcda5af353cbd41899dc736cbf1 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2980201 Commit-Queue: Fernando Fiori <ffiori@microsoft.com> Reviewed-by: Sanket Joshi <sajos@microsoft.com> Reviewed-by: Dan Clark <daniec@microsoft.com> Reviewed-by: Xianzhu Wang <wangxianzhu@chromium.org> Reviewed-by: Yoshifumi Inoue <yosin@chromium.org> Cr-Commit-Position: refs/heads/master@{#897554}
Making some updates to the implementation because the specs changed https://drafts.csswg.org/css-highlight-api-1. - Convert HighlightRegistry from setlike to maplike. - Highlight doesn't contain the highlight name anymore. - HighlightRegistry::setForBinding() doesn't throw anymore when inserting an existing key again. Relevant discussion: w3c/csswg-drafts#5910 Bug: 1197739 Change-Id: I24f69b5a09938fcda5af353cbd41899dc736cbf1 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2980201 Commit-Queue: Fernando Fiori <ffiori@microsoft.com> Reviewed-by: Sanket Joshi <sajos@microsoft.com> Reviewed-by: Dan Clark <daniec@microsoft.com> Reviewed-by: Xianzhu Wang <wangxianzhu@chromium.org> Reviewed-by: Yoshifumi Inoue <yosin@chromium.org> Cr-Commit-Position: refs/heads/master@{#897554}
Making some updates to the implementation because the specs changed https://drafts.csswg.org/css-highlight-api-1. - Convert HighlightRegistry from setlike to maplike. - Highlight doesn't contain the highlight name anymore. - HighlightRegistry::setForBinding() doesn't throw anymore when inserting an existing key again. Relevant discussion: w3c/csswg-drafts#5910 Bug: 1197739 Change-Id: I24f69b5a09938fcda5af353cbd41899dc736cbf1 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2980201 Commit-Queue: Fernando Fiori <ffiori@microsoft.com> Reviewed-by: Sanket Joshi <sajos@microsoft.com> Reviewed-by: Dan Clark <daniec@microsoft.com> Reviewed-by: Xianzhu Wang <wangxianzhu@chromium.org> Reviewed-by: Yoshifumi Inoue <yosin@chromium.org> Cr-Commit-Position: refs/heads/master@{#897554}
… to a maplike, a=testonly Automatic update from web-platform-tests Highlight API: Convert HighlightRegistry to a maplike Making some updates to the implementation because the specs changed https://drafts.csswg.org/css-highlight-api-1. - Convert HighlightRegistry from setlike to maplike. - Highlight doesn't contain the highlight name anymore. - HighlightRegistry::setForBinding() doesn't throw anymore when inserting an existing key again. Relevant discussion: w3c/csswg-drafts#5910 Bug: 1197739 Change-Id: I24f69b5a09938fcda5af353cbd41899dc736cbf1 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2980201 Commit-Queue: Fernando Fiori <ffiori@microsoft.com> Reviewed-by: Sanket Joshi <sajos@microsoft.com> Reviewed-by: Dan Clark <daniec@microsoft.com> Reviewed-by: Xianzhu Wang <wangxianzhu@chromium.org> Reviewed-by: Yoshifumi Inoue <yosin@chromium.org> Cr-Commit-Position: refs/heads/master@{#897554} -- wpt-commits: e06897f89fb3bc2ae7a6a205ce6f08452999e278 wpt-pr: 29466
… to a maplike, a=testonly Automatic update from web-platform-tests Highlight API: Convert HighlightRegistry to a maplike Making some updates to the implementation because the specs changed https://drafts.csswg.org/css-highlight-api-1. - Convert HighlightRegistry from setlike to maplike. - Highlight doesn't contain the highlight name anymore. - HighlightRegistry::setForBinding() doesn't throw anymore when inserting an existing key again. Relevant discussion: w3c/csswg-drafts#5910 Bug: 1197739 Change-Id: I24f69b5a09938fcda5af353cbd41899dc736cbf1 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2980201 Commit-Queue: Fernando Fiori <ffiori@microsoft.com> Reviewed-by: Sanket Joshi <sajos@microsoft.com> Reviewed-by: Dan Clark <daniec@microsoft.com> Reviewed-by: Xianzhu Wang <wangxianzhu@chromium.org> Reviewed-by: Yoshifumi Inoue <yosin@chromium.org> Cr-Commit-Position: refs/heads/master@{#897554} -- wpt-commits: e06897f89fb3bc2ae7a6a205ce6f08452999e278 wpt-pr: 29466
from w3ctag/design-reviews#584 (comment)
The text was updated successfully, but these errors were encountered: