w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.42k stars 647 forks source link

[css-shadow-parts] confirm browser support #2368

Open fergald opened 6 years ago

fergald commented 6 years ago

I am planning to implement the ::part() half of the shadow parts spec in Blink. In order to send an Intert To Implement for this (as an experimental feature), I need to know what support there is from other browsers. My understanding is that is that there is broad support for the basics of ::part from supported by Edge, Safari and Firefox. It would be very helpful if you could confirm this here. Thanks.

@travisleithead @smaug @rniwa

hayatoito commented 6 years ago

Thanks @fergald

@travisleithead @SmauG @rniwa Could you help @fergald to know other browser's position about shadow parts spec?

I think the details of the spec don't matter here. We can fix the spec if something in detail is wrong. What matters here is that we can have a rough consensus that shadow parts spec's approach is worth to implement as an experiment, given that we abandoned /deep/ combinator.

hayatoito commented 6 years ago

This explainer, https://meowni.ca/posts/part-theme-explainer/, would be helpful to understand the motivation.

hayatoito commented 6 years ago

cc-ing: @tabatkins just in case.

rniwa commented 6 years ago

Apple supports the general idea of ::part and ::theme but not necessarily specifics of the current proposal.

hayatoito commented 6 years ago

I guess we notified the wrong smaug. We are sorry for that. @smaug---- should be correct.

smaug---- commented 6 years ago

@emilio @dbaron

emilio commented 6 years ago

I feel like the problem it tries to solve is valid, but the general mechanism seems somewhat hairy.

In particular (maybe I misread how it works), doesn't all the part-forwarding stuff mean that a ::part(..) selector matches differently depending on which scope the selector is declared? Or should ::part(confirm-label) match even if such selector is in the <x-button> component, as long as it's nested in a <x-panel> component (using the spec examples)?

Anyway, personally I think Mozilla should take a similar position to Apple here, of supporting the general idea but not any specifics, but I opened https://github.com/mozilla/standards-positions/issues/59 to get a proper official position here.

fergald commented 6 years ago

Yes, the part forwarding stuff does mean exactly that as far as I can tell. The Chromium design doc is here

https://docs.google.com/document/d/1eFekJxcNlkKHN2BwFwiwv6FoLrlRnuct_TGB2cKomW8/edit#heading=h.6je7wsyqhc05

and discusses this a bit.

rniwa commented 6 years ago

We don't want any nested shadow boundaries to be automatically crossed. If a component chooses to expose its internal as a part, it should have the opportunity to make that decision.

Having said that, we can provide a mechanism for a component to expose its inter-component's part as its own part.

tabatkins commented 6 years ago

In particular (maybe I misread how it works), doesn't all the part-forwarding stuff mean that a ::part(..) selector matches differently depending on which scope the selector is declared?

No, there's nothing scope-specific about it at all. Could you point to what gave you that impression, so I can fix it in the spec? The parts that an element exposes are just a part of the element's API, like its class list or its ID. Each shadow host just has a parts map, which maps part names to a list of elements (either from its own shadow tree, or a descendant tree if they're forwarding).

Anyway, personally I think Mozilla should take a similar position to Apple here, of supporting the general idea but not any specifics, but I opened mozilla/standards-positions#59 to get a proper official position here.

Directing this towards both Moz and Apple: this isn't a useful position to take. :/ We're currently proceeding in implementation on the assumption of support, based on previous statements from both of y'all's companies. "Like the idea, don't know about any details" means you don't like the spec and don't want us to implement, right? Because if we do implement, things'll gradually freeze, so you better make sure all the details you're unsure about are indeed something you'd like to see.

emilio commented 6 years ago

Directing this towards both Moz and Apple: this isn't a useful position to take. :/ We're currently proceeding in implementation on the assumption of support, based on previous statements from both of y'all's companies. "Like the idea, don't know about any details" means you don't like the spec and don't want us to implement, right? Because if we do implement, things'll gradually freeze, so you better make sure all the details you're unsure about are indeed something you'd like to see.

I want to insist that that was a personal position, not nothing official, fwiw. I don't have the cycles right now to be able to review the spec as carefully as it deserves, and thus I don't want to say I support specifics that may have implications that I haven't actually grasped fully.

No, there's nothing scope-specific about it at all. Could you point to what gave you that impression, so I can fix it in the spec? The parts that an element exposes are just a part of the element's API, like its class list or its ID. Each shadow host just has a parts map, which maps part names to a list of elements (either from its own shadow tree, or a descendant tree if they're forwarding).

That means that selectors in an descendant shadow tree that specify a part that that is forwarded from an outer shadow tree should match, is that right? (See my example in that comment).

If so, that seems reasonable to me, but that is not in the specification (nor it seems the most obvious interpretation, given @fergald seems to have read the spec the same way I did). I can file an issue for that if you want.

tabatkins commented 6 years ago

Ah, I see what Fergal said. Looked at from the perspective of the element that ::part() refers to, sure, it can have different names. They're still not about scope, tho, they're about what shadow host you're drawing it from. The argument to ::part() is entirely a function of the originating element of the ::part() pseudo - the shadow host that has a parts map. The element that the pseudo points to has no choice in the matter.

That means that selectors in an descendant shadow tree that specify a part that that is forwarded from an outer shadow tree should match, is that right? (See my example in that comment).

Can you restate the example with some markup? It's not clear to me from your previous post what exact scenario you're asking about here.

dbaron commented 6 years ago

I had some comments in both mozilla/standards-positions#59 and w3ctag/design-reviews#230. I think my biggest concern is that ::part() and ::theme() feel too related to each other to have completely unrelated names. (::theme() almost feels like a combinator that could be attached to ::part().) I'm also a little concerned about the complexity of the part-forwarding microsyntax. I had one suggestion, although I don't know think it actually helps very much. I haven't had much time to dig in to the spec yet, though.

emilio commented 6 years ago

So, let's say I have nested components <x-foo>, <x-bar>, <x-baz> and <x-quux>, the last of which has a part="label" element.

For simplicity, all forward with the relevant name, that is, in x-foo, we have: <x-bar part="* => bar-*"> (did I get the syntax right?), in x-bar we have <x-baz part="* => baz-*">, and so on.

That means I can target the label from the outer scope like:

::part(bar-baz-quux-label) { /* stuff */ }

Right?

My question is, would that same selector match the same label, even if it was declared in one of the inner scopes? I guess the intention is that it does not, and that's the bit that makes a ::part(..) selector depend on where the selector is declared / in which scope it does live. In particular, in the design doc linked by @fergald, this is the problematic condition (emphasis mine):

Having reached the scope containing the selector succeed if any of the names of the element in this scope match the name in ::part() component.

I'm not saying it's impossible to implement or anything like that, I just think that's a somewhat new requirement that deserves some thought. What should:

shadowRoot.querySelector("[part=label]").matches("::part(label)")

return?

What about:

shadowRoot.querySelector("[part=label]").matches("::part(bar-baz-quux-label)")

Does something like :host::part work, thus allowing you to style parts from inside the component?

emilio commented 6 years ago

The argument to ::part() is entirely a function of the originating element of the ::part() pseudo - the shadow host that has a parts map. The element that the pseudo points to has no choice in the matter.

The issue is that ::part has multiple originating elements, depending on which scope are you matching from, if you allow forwarding.

tabatkins commented 6 years ago

My question is, would that same selector match the same label, even if it was declared in one of the inner scopes? I guess the intention is that it does not, and that's the bit that makes a ::part(..) selector depend on where the selector is declared / in which scope it does live.

It doesn't match, but that nothing do with scopes like you're implying. It's because, like I said in my previous comment, the part names are associated with the shadow host, not the element that the ::part() pseudo is pointing to.

The x-foo element has a bar-baz-quux-label part. The x-bar element has a baz-quux-label part. The x-baz element has a quux-label part. And the x-quux element has a label part. The fact that all of these parts end up pointing to the same deeply-nested element is irrelevant; they're completely independent facts associated with different shadow hosts.

shadowRoot.querySelector("[part=label]").matches("::part(label)")

This will be false - it's the shadow root's host element that has a "label" part, and will match ::part(label). And thus, since this selector is being run inside of the shadow root, and the host element is featureless, there's nothing you can put on the LHS of that pseudo-element that'll match. (You could write :host::part(label); that would be true.

(This is assuming that .matches() can ever return true when comparing elements and pseudo-element selectors; pseudo-elements that point to real elements is a pretty recent thing, and I don't know that this is well-defined. But it does make sense to me for this to work.)

shadowRoot.querySelector("[part=label]").matches("::part(bar-baz-quux-label)")

Since this is being run inside the x-quux's shadow root, apparently, there is no element that can match that selector even if you use :host (since the host element is x-quux, which doesn't have a "bar-baz-quux-label" part in its map).

The issue is that ::part has multiple originating elements, depending on which scope are you matching from, if you allow forwarding.

This is the "pseudo-elements that point to real elements are new" confusion I just mentioned. The originating element of a pseudo-element is the thing matched by the compound selector to its left. In ::part(), that's just the implicit *, but of course it can be more. All four of the ::part() examples you list are different pseudo-elements, each originating from a different host. They just all happen to point to the same element.

emilio commented 6 years ago

This is the "pseudo-elements that point to real elements are new" confusion I just mentioned. The originating element of a pseudo-element is the thing matched by the compound selector to its left. In ::part(), that's just the implicit *, but of course it can be more. All four of the ::part() examples you list are different pseudo-elements, each originating from a different host. They just all happen to point to the same element.

That's fair, though in practice no UA will / can implement it that way as far as I can tell.

So in practice, at least to the implementations I know (WebKit / Blink / Servo / Gecko), it imposes the requirement of knowing where the selector has been declared / where the rule comes from, so we can know which shadow root does it come from / which shadow host matches it.

Other question as I look more through this... Where do these rules fit in the cascade? After normal author rules? How do these interact with ::slotted, in particular where nested slots and forwarding interact? All those need to be well defined for the spec to be implementable.

tabatkins commented 6 years ago

So in practice, at least to the implementations I know (WebKit / Blink / Servo / Gecko), it imposes the requirement of knowing where the selector has been declared / where the rule comes from, so we can know which shadow root does it come from / which shadow host matches it.

I'm still not seeing this. The context of the selector has absolutely nothing to do with this; it's purely about which element the ::part is descending from. As I explained in your examples earlier, a given part name can match an element from inside (:host::part(bar)) or outside (x-foo::part(bar)) a particular shadow tree, which shows that the tree context has no relevance here. (It just happens that, due to the way we've restricted selectors and shadow trees, a given element is only directly reachable from certain contexts.)

If you store the part-name information on the target element, rather than the shadow host, then yeah, you'll need to store it as a (shadow host, part name) tuple, but that's still got nothing to do with the selector's context. ^_^

Other question as I look more through this... Where do these rules fit in the cascade? After normal author rules? How do these interact with ::slotted, in particular where nested slots and forwarding interact? All those need to be well defined for the spec to be implementable.

How selectors reaching across shadow trees work in the cascade is already well-defined by the Shadow DOM spec. Unless we specifically want some special effect, there is no need to define anything further.

rniwa commented 6 years ago

Here's one concrete feedback.

There should be no difference between closed and open shadow trees for ::theme. ::theme should always penetrate shadow boundaries. Otherwise, it defeats the primary use case of ::theme.

emilio commented 6 years ago

I'm still not seeing this. The context of the selector has absolutely nothing to do with this; it's purely about which element the ::part is descending from. As I explained in your examples earlier, a given part name can match an element from inside (:host::part(bar)) or outside (x-foo::part(bar)) a particular shadow tree, which shows that the tree context has no relevance here. (It just happens that, due to the way we've restricted selectors and shadow trees, a given element is only directly reachable from certain contexts.)

Ok, I think I see what you mean now, and I see how it can be implemented without caring about the context of the selector, thanks for bearing with me :).

I think CSSOM should probably not return true ever for something that contains a ::part pseudo, though. That means that if you do something like element.matches("x-bar::part(foo), you need to actually check it against all possible originating elements, which sounds somewhat annoying and special-case-y compared to how all other selectors work. But that's probably worth another issue.

emilio commented 6 years ago

I think CSSOM should probably not return true ever for something that contains a ::part pseudo, though. That means that if you do something like element.matches("x-bar::part(foo), you need to actually check it against all possible originating elements, which sounds somewhat annoying and special-case-y compared to how all other selectors work. But that's probably worth another issue.

Maybe this isn't even actually that bad... Anyway, will think more about it. Thanks @tabatkins :)

tabatkins commented 6 years ago

There should be no difference between closed and open shadow trees for ::theme. ::theme should always penetrate shadow boundaries. Otherwise, it defeats the primary use case of ::theme.

Interesting. I'd think that letting ::theme penetrate defeats the primary purpose of closed shadow trees. ^_^

I'll open a separate issue for this, tho.

fergald commented 6 years ago

Pinging this issue again. Chrome has implemented part and partmap attributes and ::part selector behind a flag. The spec is in line with chrome's implementation draft spec.

At this point I would like to gather any more feedback on the spec and the issues listed there and here

I will also solicit feedback from custom-element-using devs too and then bring the end result to a CSSWG conference call and move towards shipping it in Chrome.

The theme section of the spec has not had much attention, feedback is welcome on that but I am hoping to move forward with part without blocking on theme.

@hober

fergald commented 6 years ago

@dbaron you had some comments in other issues on naming and overlap between part and theme. I don't know how to capture them. Do you feel they are blockers for moving forward with part?

rniwa commented 6 years ago

The biggest blocker for us is https://github.com/w3c/csswg-drafts/issues/2411 We can't implement this without knowing the syntax for the content attribute and the semantics of IDL attribute.

fergald commented 5 years ago

Polling once more for vendor support. Spec has been updated quite a bit. I would like to take this to CSS-WG (perhaps next week).

Here's a list of things that I hope are resolved or can be resolve in WG:

@rniwa @hober @annevk @tabatkins @domenic @FremyCompany @gregwhitworth @dbaron

rniwa commented 5 years ago

I don't think "exposed parts" makes sense as its name. Given how much time we've spent discussing names & semantics for parts mapping, perhaps we should just postpone that and just focus on getting part right. I really don't see a path forward to having part mapping in a short term at this point.

fergald commented 5 years ago

The semantics of the simple cases of declaring and forwarding a single part are clear (as far as I am aware), they haven't changed at all since I started on this and nobody has suggested that they should.

There has been a lot of the discussion on naming and syntax. Syntax appears settled (no complaints or alternative suggestions have been offered or requested beyond the CSS selectors version). Naming is not settled, that's fine, we can settle it. What else do you see as blocking the path?

What do you see as needing to be got right with part?

rniwa commented 5 years ago

Naming is not settled, that's fine, we can settle it. What else do you see as blocking the path?

The semantics of IDL attribute isn't clear at all. I've stated that renaming IDL attribute WOULD help but never conceded my point that it should really a map in https://github.com/w3c/csswg-drafts/issues/2414. To that end, there is no consensus about the semantics of IDL attribute at all as far as I'm concerned.

rniwa commented 5 years ago

In general, I'm not at all confident the currently proposed forwarding mechanism provides a good developer ergonomics. It's unclear which name is getting mapped to which (is the first name one in the inner shadow or the second one?), and having to do string manipulation in JS just to update the mapping seems outright insane.

I'm a lot more interested in getting something simple spec'ed and shipped, which we can do immediately if we focused on part itself.

fergald commented 5 years ago

I don't think anyone disagrees that there should be a map-like API eventually. A string-based API to start with does not preclude a map one coming later and renaming was done for exactly that reason. I don't see that this blocks moving forward unless you think we will regret adding the string-API in the future. I would prefer to go with no IDL attributes than block on designing DOMTokenMap.

In my mind, exposedparts is something that's set at element creation time and remains static. If you're updating it, you're probably doing something wrong. I haven't seen any examples that would require that except *-forwarding but that's an argument for implementing *-forwarding not for adding DOMTokenMap.

It's unclear which name is getting mapped to which (is the first name one in the inner shadow or the second one?) Right, you cannot tell just by looking at it, whether the inner or outer name part name comes first. However, we have documented which it is and people will soon remember. Are you suggesting it should be self-describing? The only way I can think of that makes it self-describing without making the value much more verbose and harder to parse is to rename the attribute. E.g. innertooutertparts="foo bar, ..." at which point it's probably clear that inner comes first. We could also try `exportpartas="foo as bar, ...". I'm not really a fan of either of them. Do you have a suggestion?

domenic commented 5 years ago

Part of the disconnect here, I believe, is that we (the Chrome team) have been doing a lot of developer and partner outreach around these features. We've heard a few times that the feature is much less useful without part forwarding. We've also heard from people who need string reflection (because they are using frameworks that abstract the DOM and assume every attribute has a corresponding property), and the proposal for map reflection was seen as unnecessary and would not be used.

But we haven't done a good job getting those partners to speak up to the CSSWG on this repository. We can work on that, which can help steer the discussion. If nothing else, several of them will be attending TPAC.

If necessary, we can also break off features which need more data into a separate incubation repository and spec. Then we can work on shipping them and gathering in-the-field data on their usefulness. Or not---if it turns out early feedback was wrong, and people don't use those features or need them changed, then we can revise the incubating features before anyone else invests energy in shipping.

rniwa commented 5 years ago

I don't see that this blocks moving forward unless you think we will regret adding the string-API in the future. I would prefer to go with no IDL attributes than block on designing DOMTokenMap.

I'm sure you don't but we do.

But we haven't done a good job getting those partners to speak up to the CSSWG on this repository. We can work on that, which can help steer the discussion. If nothing else, several of them will be attending TPAC.

I don't think that kind of voicing would affect our overall objection to the current proposal.

If necessary, we can also break off features which need more data into a separate incubation repository and spec. Then we can work on shipping them and gathering in-the-field data on their usefulness.

I think we would be a lot more willing to show our support if we got rid of the part forwarding and focused on the rest because the rest is completely uncontroversial. Heck, we might be able to implement the rest in a couple of days by hooking it up to our existing pseudo element mechanism we have.

annevk commented 5 years ago

It didn't ever became part of https://www.w3.org/TR/html-design-principles/ unfortunately, but I think @rniwa's point, and what the "baby steps" principle was meant to convey, of doing things in small incremental steps, is a good one.

You all might remember there were similar claims of demand for multiple shadow roots per shadow host. That in part ended up delaying agreement around shadow trees for years and the need for it thus far hasn't resurfaced.

domenic commented 5 years ago

I think the more relevant design principle in this case is authors over implementers. It's easier for @rniwa to implement something smaller, but without the ability to style nested custom elements, ::part is not very useful for authors. As I said, we can make that more concrete via developer feedback and if necessary moving things to incubation.

annevk commented 5 years ago

It's easier for everyone to implement something smaller, no need for condescension. And I don't see how the principles are in conflict. Authors over implementers would only disagree with baby steps if the smaller and larger feature set were actually in conflict.

tabatkins commented 5 years ago

If Apple wants to implement a subset for now, that's fine, incremental building towards the full feature set is fine. But part forwarding is absolutely a necessary aspect of the eventual feature.

Without it, we have only two possible worlds:

  1. You just plain can't style sub-components of your components. You're able to use ::part() on a component's parts, but have to continue to use custom properties to style sub-components. (AKA you either don't use sub-components at all, or all components continue to use custom properties as their primary styling mechanism, as maintaining two types of styling mechanisms is annoying.)

  2. We let you chain ::part(), so you can access all of the sub-components of every component you're using. This is the same over-exposure of internal details that we're trying to prevent with Shadow DOM in the first place! It means that the outside world knows whether you've implemented some piece of your component yourself or via a sub-component (and thus you can't change this without risking breakage), and the outside world has full access to all of the parts of your sub-components (so your subcomponent can't change without risking breakage).

If we aim for world 2, with the idea that we'll add some way to restrict what sub-parts are exposed, congratulations, you've just reinvented part forwarding with a less convenient syntax (have to use ::part()::part() now rather than just ::part()). If we aim for world 1, that's an obviously bad world that we don't want authors to land in.


We can quibble over the details of part forwarding still; I'd be fine with removing any DOM API for it from this level, beyond basic getAttribute()/setAttribute() usage. But forwarding, itself, is an absolute necessity for a reasonable API for authors. If you disagree, please state which of the two above worlds you'd like for us to land in, or provide a plausible third possibility.

(There were plausible worlds without multiple shadow trees; trying to use that as an example doesn't work.)

FremyCompany commented 5 years ago

Hey, I haven't read all the issues that have ever been discussed here, it would be nice if we could discuss this at the f2f if there is a list of contentious things on which feedback would be welcome, but I however gave the spec another look. And wow at a personal level I'm super excited about this spec!

I furthermore don't see any reason why Microsoft wouldn't support this spec moving forward as a prototype implementation in Blink. We can always learn from implementation experience and feedback, but this seems like a solid start.

That being said, I do have some minor feedback. The spec mentions part="confirm-button, * => confirm-*" as something that exits, but the syntax of part doesn't seem to allow this. Should this be added there?

Also, I would tend to try to keep the part mapping syntax close to the desugaring syntax in javascript, so I'd voice a weak preference for part="keepAlike, oldName:newName" and by extension oldName-*:newName-*. I do see very valid use cases for exposedparts to perform prefixing operations for sub-components, I'd strongly suggest to keep this in v1.

Additionally, -- and I realize this doesn't have to be part of v1, -- something I would enjoy having along this would be something like :of-part(label) which could be use within a tree to match any element that is in that tree and whose closest ancestor with the part attribute defined has value label (similar to how :lang works today) maybe with :in-part(label) which would select if any ancestor has part=label (both of these would not cross shadow tree boundaries).

Finally, -- still a possible v2 addition, -- I wouldn't mind if we were able to add 'states' to parts. Something like button[secondary disabled] whose secondary and disabled states would be able to be targeted as ::part(button[disabled]) as a single class, and would naturally follow the button along with its eventual remapping like ::part(confim-button[disabled]).

FremyCompany commented 5 years ago

Oh, one more thing.

For example, x-panel::part(confirm-button)::part(label) never matches anything. This is because doing so would expose more structural information than is intended.

I do agree with this, but I have a weak opinion we should probably allow something like x-panel::part(confirm-button)::theme(label) and I don't think the spec is very clear on that.

[EDIT] I say this because I'd probably use ::theme to set thematic non-inherited custom properties, and I might want to do that per component part; I guess it is possible not to use themes and set inherited custom properties on the part, but being able to set a theme for a part seems useful to me as this is already possible using custom properties today.

tabatkins commented 5 years ago

Also, I would tend to try to keep the part mapping syntax close to the desugaring syntax in javascript, so I'd voice a weak preference for part="keepAlike, oldName:newName" and by extension oldName-:newName-. I do see very valid use cases for exposedparts to perform prefixing operations for sub-components, I'd strongly suggest to keep this in v1.

Ooh, that's a pretty reasonable critique. While I do often find myself having to think for a moment to remember the correct ordering for destructuring, having CSS use a related syntax at least means that I'd only have to learn this once. @fergald , @rniwa, what do y'all think?

Additionally, -- and I realize this doesn't have to be part of v1, -- something I would enjoy having along this would be something like :of-part(label) which could be use within a tree to match any element that is in that tree and whose closest ancestor with the part attribute defined has value label (similar to how :lang works today) maybe with :in-part(label) which would select if any ancestor has part=label (both of these would not cross shadow tree boundaries).

Already doable today by just giving the part multiple names. You can say part="button, button-disabled" for instance, then both ::part(button) and ::part(button-disabled) will work.

FremyCompany commented 5 years ago

Already doable today by just giving the part multiple names. You can say part="button, button-disabled" for instance, then both ::part(button) and ::part(button-disabled) will work.

Yeah, but that is verbose if you have a lot of them. Also you have to forward them all in exposedparts which then becomes verbose too. I agree [] is just syntactic sugar but it seems like a very convenient one to me. Maybe doesn't need to be in ::part() and just in the attribute syntax though, didn't think this through.

tabatkins commented 5 years ago

Yeah, happy to discuss that in v2; the fact that it could come along "for free" when you forward the part, without you having to manually forward all the sub-states, does indeed seem useful.

rniwa commented 5 years ago

Also, I would tend to try to keep the part mapping syntax close to the desugaring syntax in javascript, so I'd voice a weak preference for part="keepAlike, oldName:newName" and by extension oldName-:newName-. I do see very valid use cases for exposedparts to perform prefixing operations for sub-components, I'd strongly suggest to keep this in v1.

Ooh, that's a pretty reasonable critique. While I do often find myself having to think for a moment to remember the correct ordering for destructuring, having CSS use a related syntax at least means that I'd only have to learn this once. @fergald , @rniwa, what do y'all think?

Yeah, @grorg and I had some discussion today, and came up with almost identical syntax with exportparts content attribute. So it would read like <sub-component exportparts="a:b c"> would mean that exporting the part "a" defined in the subcomponent as part "b" of this component, and forward-declare "c". I think that's probably the best syntax we've come up with so far.

tabatkins commented 5 years ago

Comma-separated, hopefully?

rniwa commented 5 years ago

Right, comma separated.

fergald commented 5 years ago

So that's "outer1 : inner1, outer2 : inner2, same1, same2"?

FremyCompany commented 5 years ago

I think the javascript-compatible way is inner1: outer1 if I understand inner and outer as you do

tabatkins commented 5 years ago

Yeah. oldName:newName is how JS works:

const {foo: bar} = {foo: 1};
// same as:
const bar = ({foo: 1}).foo;
rniwa commented 5 years ago

Yeah, since it's called exportparts, inner: outer since we're exporting inner as outer.

fergald commented 5 years ago

OK, spec and explainer are updated to exportparts="inner : outer".

Here's a list of things that I'd like to confirm: