- From: CSS Meeting Bot via GitHub <sysbot+gh@w3.org>
- Date: Wed, 19 Feb 2025 17:50:45 +0000
- To: public-css-archive@w3.org
The CSS Working Group just discussed `[css-values] Short-circuit if() evaluation`, and agreed to the following: * `RESOLVED: Specify this new parsing behavior for all substitution functions, and some sort of spread-like thing` <details><summary>The full IRC log of that discussion</summary> <emilio> TabAtkins: so... problem that showed up when we started thinking about if() but it applies to other substitutions<br> <emilio> ... in most programming languages, the not taken branch isn't ran<br> <emilio> ... and has no effect and gets ignored<br> <emilio> q+<br> <emilio> TabAtkins: as currently spec'd that's not true for if()<br> <emilio> ... it's expected to fully resolve and then choose<br> <emilio> ... it's not great<br> <emilio> ... invalid variables, expensive things like custom functions<br> <emilio> ... having to run all of the branches to throw all but one of them seems bad<br> <emilio> ... so we'd like to find a way to allow deferred evaluation<br> <emilio> ... so that it also applies to fallbacks and so on<br> <emilio> ... the proposal is to change how substitutions are parsed<br> <emilio> ... two grammars, early and late<br> <emilio> ... early grammar is super wide (<decl>)<br> <emilio> ... and punctuation to separate the structure<br> <emilio> ... so in if() you'd get : and ; to separate values<br> <emilio> ... that's what the initial parse uses<br> <emilio> ... not evaluating or applying any grammar to it<br> <emilio> ... then each function defines how it's executed with it's late grammar<br> <emilio> ... so if it's true it resolves the condition and the if body etc<br> <emilio> ... same would apply to other functions<br> <bradk> I have to leave for another meeting. Just wanted to say I am impressed with Zoom’s automatic (AI) captions and transcripts.<br> <emilio> ... so attr() we could avoid evaluating the fallback<br> <emilio> ... I'd like to apply this universally<br> <emilio> ... maybe var() needs to unconditionally evaluate<br> <emilio> ... so might be compat fallout<br> <emilio> ... but for new functions I'd like to specify in this way<br> <emilio> ... so the gross structure is in the early parse and the function controls how it's parsed<br> <emilio> ... that means vars can no longer supply the punctuation, e.g. a custom function would not be able to expand into arguments<br> <emilio> ... so we'd add syntax like the ... so that we expand it during early parse<br> <emilio> ... by default variables would not resolve until requested<br> <astearns> q+<br> <emilio> ... so if you have a function like --foo(var(--var-1), var(--var-2))<br> <emilio> ... you know there are two args<br> <emilio> ... specially for custom functions there are two arguments if there are commas<br> <kizu> q+<br> <emilio> ... authors need to deffensively wrap in {}<br> <emilio> ... no longer the case now, authors can depend on a var that's 1 argument being 1 argument<br> <emilio> ... this actually solves a footgun that we were somewhat worried about about comma-containing args<br> <emilio> ... most of the time shouldn't have an effect<br> <emilio> ... the implications are meaningful tho<br> <emilio> ... wanted to make sure that it makes sense to other folks<br> <astearns> ack emilio<br> <TabAtkins> emilio: i guess that means cycles are discovered dynamically?<br> <TabAtkins> emilio: can get a bit weird<br> <TabAtkins> TabAtkins: correct<br> <TabAtkins> emilio: worried about things that can create a cycle on an else branch, and theoretically could effect the condition<br> <TabAtkins> emilio: havne't thought too deep about it, but seems sketchy<br> <TabAtkins> emilio: other than that, think it makes sense<br> <TabAtkins> emilio: var() sub tends to get annoying, the more features we add the slower it gets, nice to save some work<br> <TabAtkins> emilio: but i'm a bit wary about cycle detection<br> <TabAtkins> emilio: are we supposed to check the variable names inside beforehand?<br> <emilio> TabAtkins: yea, cycle detection becomes dynamic<br> <emilio> ... you don't do any checking<br> <emilio> ... this allows variable-variables<br> <emilio> ... because that'd be possible now<br> <emilio> ... for the more general thing of the dynamic cyclic graph<br> <emilio> andruud: that's kinda the point of this, not sure what you're worried about right now emilio<br> <emilio> TabAtkins: I suspect he means "say the test for a branch uses a variable and the body produces a cycle for the test you're evaluating"<br> <emilio> andruud: but that's the branch you take right?<br> <emilio> TabAtkins: right but it only becomes cyclic once you evaluate the branch right?<br> <emilio> andruud: you have that problem with if with the existing model don't you<br> <emilio> TabAtkins: yeah they're all eagerly evaluated so you know cycles before-hand<br> <emilio> andruud: we solved the example you had for if<br> <emilio> ... having a custom prop in an if counts for cycle detection<br> <emilio> TabAtkins: right that's the usage emilio is worried about<br> <emilio> ... the first usage "should've been cyclic"<br> <emilio> ... but the execution order gets you a defined behavior<br> <TabAtkins> emilio: does that mean the order you perform prop substitution needs to be well-defined?<br> <TabAtkins> emilio: right now if you have two rules that match with the same var, ... i guess my question is when. the behavior is different if you sub the first if() first, on whether this makes a cycle or not<br> <TabAtkins> emilio: I suppose that means the whole thing is stateful on the set of matched declarations<br> <TabAtkins> emilio: and we need to define reeally well whether we sub properties that are overwritten or not, which currnetly we skip...<br> <TabAtkins> emilio: i think there's a way to make this work, details are jsut confusing<br> <TabAtkins> emilio: but i think figuring out the spec is part of thi sissue, don't need to solve on the call<br> <emilio> astearns: wanted to ask whether the state parsing is separated from the spread function<br> <emilio> TabAtkins: if you stick with current parsing there's no reason to do spread<br> <emilio> ... so would be a no-op of a feature<br> <emilio> astearns: wondering whether variables with punctuation is something we absolutely need to support or not<br> <emilio> TabAtkins: not about vars containing punctuation<br> <emilio> astearns: I thought motivation for spread was getting punctuation for what needs to go in which part of the parsing<br> <emilio> q+<br> <emilio> ack astearns<br> <astearns> ack kizu<br> <emilio> kizu: +1 to almost everything<br> <emilio> ... would be great to have this algorithm, wanted to use var(var( for a long time<br> <TabAtkins> var(var(--propname))<br> <bramus> +1<br> <emilio> ... only concern is if we are able to make the fallback not executed I'm totally fine for if()<br> <emilio> ... for current var() I think there would be many compat issues<br> <emilio> ... but I think it's possible to use this behavior as a conditional<br> <emilio> ... that could be a workaround for the conditions in general<br> <emilio> ... meaning that this behavior could be use as a transpillation target for if()<br> <emilio> ... until we have if this could be used for that<br> <emilio> ... that's the only case where I'd be a bit hesitant<br> <emilio> ... It'd be nice to see if there are compat issues aside from my experiments<br> <astearns> ack emilio<br> <TabAtkins> emilio: i think alan was asking about whether we can work on spread after changing the parsing stuff<br> <TabAtkins> emilio: that seems possible unless we really... as long as we keep doing the same thing for var()<br> <TabAtkins> emilio: i think it woudl be nice to ahve this work for var()<br> <TabAtkins> emilio: i think the place i've meaningfully seen commas be used is things like colors<br> <TabAtkins> emilio: you can do `--foo: 1, 2, 3; color: rgb(var(--foo))`<br> <emilio> TabAtkins: right, this would only change behavior for custom functions / var() / etc and other functions<br> <emilio> ... a bullet that I'm willing to bite<br> <TabAtkins> emilio: i agree, and think it takes mos tof the compat issues with var() away<br> <TabAtkins> emilio: that gives me some hope that we can make var() work<br> <emilio> TabAtkins: the compat issue here is if they are relying on non-substituted fallback triggering cyclicness<br> <emilio> ... I suspect outside of experiments like kizu's it's not an issue in practice<br> <emilio> astearns: I'm a bit concerned about some library depending on kizu's hacks and avoids defeating this<br> <emilio> TabAtkins: andruud is working on this actively<br> <emilio> ... so we'd find out about such things soon<br> <emilio> andruud: var() we need a use counter for first<br> <emilio> ... so I'd do that separately (soon)<br> <emilio> ... and we can resolve on doing it compat-permitting<br> <emilio> kizu: I wonder if there'd be no other compat issues I could see making this change for var() be tied to if() so that we can do at the same time<br> <emilio> ... so you can also implement this along @supports ... if()<br> <emilio> TabAtkins: if anything if() would show up earlier than var()<br> <emilio> kizu: seems fine then<br> <emilio> ... other browsers can do if-first or at the same time as well<br> <emilio> astearns: so proposal is to specify this for all substitution functions and also the spread<br> <emilio> TabAtkins: the spread syntax needs figuring out<br> <emilio> astearns: with the usual caveats<br> <emilio> ... so not a done deal<br> <emilio> PROPOSED RESOLUTION: Specify this new parsing behavior for all subsitution functions, and some sort of spread-like thing<br> <emilio> RESOLVED: Specify this new parsing behavior for all substitution functions, and some sort of spread-like thing<br> </details> -- GitHub Notification of comment by css-meeting-bot Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/11500#issuecomment-2669358882 using your GitHub account -- Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Wednesday, 19 February 2025 17:50:46 UTC