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

Make ObservableArray "subclassable" #1342

Open
tabatkins opened this issue Jul 14, 2023 · 3 comments
Open

Make ObservableArray "subclassable" #1342

tabatkins opened this issue Jul 14, 2023 · 3 comments

Comments

@tabatkins
Copy link
Contributor

In w3c/csswg-drafts#8350, @domenic asked for us to make the new CSSStyleRule.cssRules attribute an ObservableArray<CSSRule>, rather than the existing weird legacy array-ish CSSRuleList that we use in similar places. We'd like to keep things consistent across the OM (in fact, we've now specified that CSSStyleRule just inherits from CSSGroupingRule, same as CSSMediaRule and the like), but that means we have to deal with legacy compat. In particular, CSSRuleList has an item() method.

Unfortunately it's not currently possible to add methods to an ObservableArray; you just get the default stuff and that's it. We should add some way to "inherit" from ObservableArray so legacy cases like this can be handled.

Quote from @domenic in the WHATWG chat room:

There are at least two ways you could do it I can think of: something that does actual inheritance (so that x.constructor.name === "CSSRuleList", x.hasOwnProperty("push") === false, but x.hasOwnProperty("item") === true), or something that changes the proxy that ObservableArray uses to have special behavior for the defined properties (i.e., instead of [[GetOwnProperty]] on "item" returning undefined/whatever gets stored there via normal property access, it returns some property descriptor for the method that we conjured up). Both are pretty subtle to actually define and I'm not sure which is best, or if there's a better third option...

I think either is fine, particularly for these sorts of legacy cases. The simple inheritance model might be the easiest, tho - you just put the Proxy object behind it in the prototype chain, and things will continue to Just Work, as far as I can tell? It also means you have the least chance of triggering incidental compat issues, like people branching on instanceof. I suspect it's also the easiest to fit into the existing syntax, as you'd literally just say interface CSSRuleList : ObservableArray<CSSRule>

@tabatkins
Copy link
Contributor Author

Hm, that said, we've (purposely, I believe) moved away from ObservableArrays being constructable objects; instead they're just JS arrays with a proxy wrapped around them. Preserving that quality might be worthwhile, in which case a more focused syntax that just specifies extra operations on the proxy might be better? Like:

ObservableArray<CSSRule> CSSRuleList {
  CSSRule? item(int index);
};

Then you could use CSSRuleList as a type and it's just an ObservableArray with an extra method implemented in the proxy.

@bathos
Copy link
Contributor

bathos commented Jul 14, 2023

Would the handlers implement the methods/attributes with own-property semantics? (perhaps achieved literally in terms of regular own-properties of the [[ProxyTarget]] — there’d be nothing special to do, so traps delegating to OrdinaryWhatever would be enough.)

@tabatkins
Copy link
Contributor Author

I'm not sure, and don't think I particularly care about the details. Whichever is simpler and makes more sense works for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants
@tabatkins @bathos and others