- From: Dael Jackson <daelcss@gmail.com>
- Date: Mon, 15 May 2017 04:41:20 -0400
- To: public-houdini@w3.org
- Cc: www-style@w3.org
================================================= These are the official Houdini Task Force minutes. Unless you're correcting the minutes, please respond by starting a new thread with an appropriate subject line. ================================================= Typed OM -------- - TabAtkins proposed a new approach to numeric values: https://docs.google.com/presentation/d/1s1LgVKntulttemMacBMbErOAc0UQzLbdol4rQbQf-aw/edit?usp=sharing - RESOLVED: Adopt Tab & Shane's new proposal for value API as an improvement over the current proposal; issues around cases requiring an AST might, however, require further revision of the design. [Note: This resolution was overridden by the CSSMathValue one below.] - RESOLVED: Use iterable (option 2) for Array-like CSS interfaces, unless/until Proxies become more performant. See https://docs.google.com/presentation/d/1pXoJ4vqRfjww7xJ8DYTYk8LBu0kGyGyg0yZm88w8xBw/edit?usp=sharing - RESOLVED: inline style attribute map is also live https://github.com/w3c/css-houdini-drafts/issues/149 - RESOLVED: Custom properties that have an initial value show up in computed style, warn authors about perf issues if they type everything all the time - RESOLVED: For inline style, should return the custom properties that are set on the inline style of the current node - RESOLVED: For specified style, should return the custom properties defined in the current rule - RESOLVED: For computed style, should return all defined custom properties on the current node (including inheritance) - RESOLVED: Be consistent about null vs throw in all three .parse() syntax error cases; follow TAG guidelines once they have them. https://github.com/w3c/css-houdini-drafts/issues/305 - RESOLVED: Replace previously-resolved value API with CSSNumericValue tree. * CSSNumericValue has two subclasses: CSSMathValue and CSSUnitValue * CSSMathValue has two members: - operator, a string representing a math op like *, /, min, max, + - operands, a list of CSSNumericValue. * CSSNumericValue has a method called toSum which returns a map of units to numbers representing a sum of those dimensions, as previously discussed in Tab & Shane's proposal above. If the CSSNumericValue cannot be so reduced, it either returns null or throws, whatever the TAG decides. - RESOLVED: Using properties is moved to L2 https://github.com/w3c/css-houdini-drafts/issues/310 - RESOLVED: Name style maps accessed via element.attributeStyleMap and element.computedStyleMap, with attributeStyleMap maybe renamed later. Pseudo-element styles accessed through PseudoElement APIs. https://github.com/w3c/css-houdini-drafts/issues/350 - RESOLVED: Update Typed OM draft on /TR with above edits. ===== FULL MINUTES BELOW ====== Agenda: https://github.com/w3c/css-houdini-drafts/wiki/Tokyo-F2F-April-18-2017 Scribe: fanasai Typed OM ======== Numeric Values Rethink ---------------------- <TabAtkins> https://docs.google.com/presentation/d/1s1LgVKntulttemMacBMbErOAc0UQzLbdol4rQbQf-aw/edit?usp=sharing TabAtkins: Why I changed everything about how we did numeric values. TabAtkins: Previous number type looked like this: attribute double value; TabAtkins: Previous simple length was similar, added readonly LengthType type; TabAtkins: calc() was a structlike structure with em, px, etc. properties. TabAtkins: Angle values were similar to calc() but looked like a length. Automatically converts between units. TabAtkins: This is a problem. TabAtkins: We have 3 different unit things that have dramatically different representations. TabAtkins: Length version is very nice for setting up arbitrary units. Not bound to unit types we have exposed. TabAtkins: No updating needed to support new units. TabAtkins: calc() is nice because it supports sum of values. TabAtkins: And angle has great auto-conversion. TabAtkins: But the differences make the system weird. TabAtkins: ... TabAtkins: Even then, what we added wasn't good enough. TabAtkins: We're adding unit algebra into calc() soon. TabAtkins: px/em needs to remain as px/em, couldn't do that with old calc interface. TabAtkins: And also mixing number. TabAtkins: It also doesn't support custom units. TabAtkins: Could set that in unit type, but can't do it in calc() TabAtkins: Can't do that in angles, same problem. TabAtkins: Bad for various reasons. TabAtkins: So I rewrote everything into a new structure that replaces everything. TabAtkins: Replace it with two classes, plus superclass. TabAtkins: First one is for dimensions/percentages/numbers TabAtkins: Other is for calc. TabAtkins: interface CSSUnitValue: CSSNumericValue { attribute double value; attribute DOMString unit; readonly attribute DOMSTring type; }; TabAtkins: This handles everything that is a dimension TabAtkins: it handles custom units, in future TabAtkins: also handles number and percent. TabAtkins: It becomes a problem if we create a unit named "number" or "percent", but that's unlikely. TabAtkins: Type is used internally to maintain length/angle/number etc. TabAtkins: so that can throw if there's a type mismatch, etc. smfr: What about z-index? TabAtkins: Those are numbers. TabAtkins: Integer inputs will clamp numbers <TabAtkins> calc(5px + 2em) => {"px": 5, "em": 2} <astearns> https://www.irccloud.com/pastebin/Db0ATwfQ/ TabAtkins: ^ represents calc TabAtkins: with input validation. TabAtkins: ... dbaron: How is this going to extend to calc(3px*2vw/2em)? TabAtkins: Each such expression can be turned into simple sum of complex units. TabAtkins: Those will just be strings. several people: :/ <shane {"px*vw/em": 3} TabAtkins: I know of literally no better way to do it. plinss: How are you storing the operators? TabAtkins: Every calc can decompose into a sum of united values. dbaron: Not quite that obvious dbaron: if you have a sum in the denominator. dbaron: It's a logical piece of unit algebra dbaron: We already have a resolution to add unit algebra to L4. <dbaron> calc(4em / (2em + 2px)) fantasai: What about handling min()/max()? shane: ... TabAtkins: Yeah, you can produce expressions that don't reduce well... would need to produce a tree. plinss: You're decomposing multiplication into addition? TabAtkins: No, you distribute TabAtkins: Unless you have a sum in the denominator, would work shane: min/max would need a different approach. shane: Advantage of this interface is that all calc expressions today, and majority in the future, can be represented here. shane: Very useful for interrogating through script. shane: Just says what units are expressed in the calc. shane: It's a compromise between map and string representations. shane: Shame we can't express every single calc expression, but this still captures most of them. TabAtkins: Will have to change some parts of sub-expressions as an AST. <TabAtkins> calc(5px + 2em/(5% + 10px)) => {"px": 5}, + AST for the second half shane: It would be a tree representation. shane: A real pain to deal with in script. <iank> {type: 'div', numerator: {type: 'value', value: '4em'}, dem: {type: 'plus', value: [{type: 'value', value: '5%'}, {type: 'value', value: '10px'}]}} <iank> ^ a bad AST representation of dbaron example jack: So this will be able to represent all? jack: If some will be represented as complex strings, how is that better than now? ... TabAtkins: Every single calc you can express today is decomposable into sum of simple units TabAtkins: so simple units as keys. TabAtkins: Only get arithmetic in the units if doing unit math. shane: ... shane: These are like channels, each unit is a channel. shane: Complex units, except those with sums in the denominator, are the same concept. till: What would be representation for 100% - 50px <TabAtkins> calc(100% - 50px) => {"percent": 100, "px": -50} shane: percent: 100; px: -50 shane: This works nicely if you add, -25% + 50% you end up with 25%. SimonSapin: So the way to output is to make a sum? SimonSapin: That's not obvious, maybe put sum in the name? e.g. CSSCalcSum TabAtkins: Not sure that's necessary fantasai: Seems reasonable to me. We might in future want to represent calc as the tree that it was. fantasai: Since this represents a simplification of the calc, reasonable to express that in the type name. shane: I'm okay with that. shane: I also think that we can extend this to represent the remaining cases that haven't been specced yet by having an AST member in this that represents the full tree. fantasai: That sounds great, but my concern is how are we dealing with min & max? fantasai: Want to see how that fits into this interface. TabAtkins: Didn't draw that up yet. shane: Let's sit down at lunch and figure that out TabAtkins: Just want to point out that old proposal didn't deal with this either, this is an improvement in any case. till: How do vars figure into this? TabAtkins: It's represented as an unparsed value instead. shane: That's only for non-computed style uses. <dbaron> [moved on to slide 10] TabAtkins: Once the var substitutes, you'll get a proper whatever. TabAtkins: Superclass has stuff that all values should be able to do. interface CSSNumericValue : CSSStyleValue { CSSNumericValue add(CSSNumericValue value); CSSNumericValue subtract(CSSNumericValue value); CSSNumericValue multiply(double value); CSSNumericValue divide(double value); bool equals(CSSNumericValue value); CSSNumericValue to(DOMString unit); static CSSNumericValue parse(DOMString cssText); }; TabAtkins: Math is awkward, let's do it for you TabAtkins: When necessary will pop out a calc value, but in simple cases won't. TabAtkins: e.g. adding two px values results in a px value. TabAtkins: adding px plus percent gets you a calc(). TabAtkins: This is very strict at the moment. TabAtkins: Will tell you that 5px and 5px are equal. TabAtkins: Will not tell you that 96px and 1in are equal. TabAtkins: Also won't tell you that a unit value of 5px and calc value of 5px are equal. ChrisL: Why? TabAtkins: Question is why you would want to compare things. TabAtkins: Examples we could tell, probably didn't want to do a loose equality. TabAtkins: That said, okay with adding. ChrisL: Was wondering why. Doesn't seem hard. TabAtkins: Not hard, but didn't seem to fit with uses. fantasai: Seems to me you would want to have the ability to do equivalence matching. TabAtkins: Wanted to match with what would happen with JS value equality. fantasai: That's fine. I think you just probably want both. TabAtkins: If there's even remotely realistic case, would add interface that'll do conversion equality. TabAtkins: We might not need to add that except as a convenience, though TabAtkins: because to() function will convert from one type to another, so long as it's possible. TabAtkins: Throws if it can't, e.g. not enough info. TabAtkins: Loose equality would just be a convenience function, could otherwise convert both things to the same unit. leaverou: ???? TabAtkins: If you're dealing with computed values, already resolved away. If dealing with specified values, keep them as the types that you're looking at and they'll resolve later on. shane: Should to() let you cast to combinations of units as well? TabAtkins: Send it to em+px? Would produce a calc for that? TabAtkins: That's not the worst idea. Open an issue for me? TabAtkins: Last function is parse() TabAtkins: Will turn it into a CSSNumericValue. leaverou: calc(1px + 2px)? TabAtkins: You get calc value of 3px. calc(3px) TabAtkins: Use the math functions if you want ... leaverou: If calc(3px) is equivalent to 3px, should output 3px. TabAtkins: Also logical to maintain the calc() that was your source input. shane: Calc expression at one end and the other, animating between. shane: Just because one of them hits zero at some point in the middle, don't want the calc() wrapper to suddenly disappear. Rossen: Also want to be able to round-trip it for tooling. SimonSapin: parse() function takes CSS syntax? TabAtkins: Yes. Invokes Syntax module algorithm. SimonSapin: Is there a way to create without parsing? TabAtkins: Yes, they all have constructors. TabAtkins: CSSCalcValue has two constructors. Takes a dictionary. TabAtkins: Other one also should take a map iterator, but specifying that in WebIDL is really messy right now. TabAtkins: So put an issue that when WebIDL makes that better, let's add it. till: So if calc() is always for sums, why not call it CSSSumValue? till: Then can have a CSSProductValue. TabAtkins: Don't think we have a CSSProductValue. TabAtkins: Also like that it matches up to the functional notation name. iank: With the to() function, converting 1em to px, that would throw? iank: At some point could add a dictionary to have the conversions iank: So you could specify what an em is. fantasai: You would want to have the layout engine and the JS use different conversion factors? TabAtkins: You would pass an element, or an element and property, for reference on how to convert the units. shane: We have a typed-om-2 label in the issue tracker, so file them. SimonSapin: You mentioned resolving value of an element against a property, including percentages, does that include percentages resolved during layout? TabAtkins: Theoretically? TabAtkins: Definitely L2, can work out details later. SimonSapin: If you do that probably want it to be asynchronous. iank: Could provide utility methods for resolving e.g. inline size. iank: Because we don't want ppl to go through writing modes. ??? iank: ???? TabAtkins: We put it into the ED, if anyone objects, will take it out :) TabAtkins: Meade from Chrome is working on it. astearns: Anyone from Gecko? dbaron: No idea. <till> dbaron: based on https://bugzilla.mozilla.org/show_bug.cgi?id=1278697, I don't think anybody's working on typed OM TabAtkins: This has been in the spec for ~2months <astearns> it wouldn't be the worst idea to have a resolution fantasai: I'm happy to resolve on this, so long as we note that the max/min investigation might result in further revision. SimonSapin: Cases not supported by maplike calc, do we have a plan for another API? TabAtkins: Gonna discuss with shane over lunch TabAtkins: Those parts can hang off in the AST SimonSapin: So some parts of the calc will be represented in the sums, but not all? TabAtkins: Yeah <shane> I think everything would end up in the maplike, it's just some of the bits wouldn't map to numbers. fantasai: That seems really bad. TabAtkins: Previous approach was worse fantasai: happy to replace previous approach with this one, but this one still has issues with calc that we need to fix shane: could have a key for the extra bits Rossen: objections? RESOLVED: Adopt Tab & Shane's new proposal for value API Rossen: Please file those key issues mentioned so the draft doesn't progress without them addressed. Array-like Frustrations ----------------------- <TabAtkins> GitHub Topic: https://github.com/w3c/css-houdini-drafts/issues/239 <TabAtkins> https://docs.google.com/presentation/d/1pXoJ4vqRfjww7xJ8DYTYk8LBu0kGyGyg0yZm88w8xBw/edit?usp=sharing TabAtkins: Couple interfaces in typed OM, e.g. CSSUnparsedValue, CSSTransformValue, that are just sequences of other values. They have other extra data, e.g. transform has an equivalent matrix. TabAtkins: But at their core, they are sequences of values. So they really want to be arrays. TabAtkins: Really want to use array notations. TabAtkins: But making something array-like, only way is to use Proxies, which are slow and not desired by implementers. TabAtkins: Annoying because maps and sets are easily faked. TabAtkins: WebIDL is also broken, can't even do iterables without invoking Proxies. TabAtkins: WebIDL is doing something very stupid for bad reasons. ( I'm gonna be really judgmental here.) TabAtkins: Wanted to go over these issues. SimonSapin: Can we fix WebIDL? TabAtkins: First option is suck it up, use LegacyArrayClass. Invokes Proxy. Not great. TabAtkins: It also means that any Array methods that return an array, return a real array, not an instance of our arraylike. till: That shouldn't be true anymore with species. TabAtkins: That's option 3 :) TabAtkins: I don't want to do Option 1, but it is a possibility. TabAtkins: Option 2 is Use iterable <shane> Not an array, but can be turned into one: let arr = [...cssThing] <shane> As written today, would still invoke Proxy; it’s written to require indexed properties. Totally fixable, just hasn’t been fixed yet in WebIDL. <shane> (kv-iterator doesn’t act badly like this. It can be fixed!) <shane> Probably good enough, at least as a first step. TabAtkins: This lets you iterate in a for loop, or to cast things into an array. TabAtkins: It's okay as a first step. TabAtkins: Fairly easy to get to. TabAtkins: Problem is WebIDL value iterators, which is what we'd use here, still requires Proxy. TabAtkins: .... TabAtkins: So WebIDL needs to be fixed. TabAtkins: This would be okay. TabAtkins: Could also hack around key-value iterator. Doesn't have the problems. But it's a hack. TabAtkins: This is a possible solution, particularly in ES6 casting is easy. TabAtkins: Option 3 is desirable one which is ES spec now has proper subclassable arrays. TabAtkins: Similar to previous step, but it's a real Array. TabAtkins: Will also return the correct subclass from Array methods. ChrisL: Which version of ES spec did that come from, and can you compile this down to ES6? till: It's ES6 and it is implemented in all engines. TabAtkins: Not fixed in WebIDL yet. TabAtkins: Only problem with this is that you still can't intercept a set operation, like you can with maps. TabAtkins: So people can put random crap in your interface TabAtkins: e.g. CSSUnparsedArray is suppoed to only have strings and ?? TabAtkins: Not sure what to do with that, do we throw when you add something that's invalid? TabAtkins: Most of the time you can sanitize at ... leaverou: If the issue is that people can mess with your types, that's just how JS works. TabAtkins: In maplike, in calc(), because it has an impl of set method, can do type checking and tell you if you're doing something wrong right away. TabAtkins: If you're setting an arbitrary object to px key, will throw, because not a number. TabAtkins: Doesn't look correct, and then later when you're setting into a property map, break down. leaverou: That's their own fault. TabAtkins: But we still have to handle correctness. TabAtkins: And we'd have to handle it via checking every set, iterating over it, even in cases where you haven't done anything wrong, which is more computation than is required. TabAtkins: If you're strict at the start, then we don't have to do such extra checks. till: I think you fundamentally want Proxies to implement that. <TabAtkins> AWB had a proposal to let you hook the [] syntax, but that's never gone anywhere. :( shane: At least with proposal 2 the only time we need to check correctness is on construction, and that is very ... shane: We wouldn't be in a situation where every time we need to use contents we typecheck them. TabAtkins: So I think we should go with option 2 for now, and then in future, go into Array subclassing. Rossen: What would prevent us from going to Array subclassing in the future? TabAtkins: Only if you're doing exotic checks on whether it's an array or not. TabAtkins: If just iterating over it, won't notice the difference. till: The performance on Proxies might not be that much of a problem going forward. till: Engines are doing pretty good optimizations nowadays till: If all you have is a set hook, then should be optimization. TabAtkins: I was told that's not the case. iank: I was told we're not going to be able to make Proxies fast anytime soon. till: in the general case, that's true, but this isn't the general case. TabAtkins: If good news comes out, ok to change, but for now would go with option 2. Rossen: So you're proposing to go with option 2. Rossen: Any objections? Rossen: Anyone for option 3 at this point? RESOLVED: Option 2- Use iterable Remaining Typed OM Issues ------------------------- <shane> Issues list: https://docs.google.com/document/d/1NA020gku-tgEHMGK_8xkB6Ksfpd8ieL4z9jFoGchzbA/edit shane: 7 issues that need discussion shane: #239 and #359 just discussed Issue 149: Describe that StylePropertyMaps are not live objects - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <shane> Topic: https://github.com/w3c/css-houdini-drafts/issues/149 shane: We resolved in September of last year that the specified and computed style maps were live. shane: So if you made changes not through typed OM, would see those changes reflected in the map. shane: We did not discuss inline style map. shane: I assume that would be live as well, anyone disagree? dbaron: I consider that one case of the specified style. shane: Same as specified style in the sense that represents specified style, but has different backing model. Rossen: If we're making specified style live, inline is just specified. RESOLVED: inline style attribute map is also live (Issue 149) StylePropertyMaps wrt custom properties - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <shane> Topic: https://github.com/w3c/css-houdini-drafts/issues/276 TabAtkins: We need to clarify how style map works with custom properties. TabAtkins: Suggestion from shane is that for style attributes, custom properties set in style attr should be included. TabAtkins: For style rule, include those custom properties in that style rule. <shane> For inline style, should return the custom properties that are set on the inline style of the current node <shane> For specified style, should return the custom properties defined in the current rule <shane> For computed style, should return all defined custom properties on the current node (including inheritance) TabAtkins: [reads what shane posted] iank: If you register a custom property, it won't show up automatically? TabAtkins: No. shane: What if you registered it with an initial value? iank: That's what I meant. TabAtkins: That's a good question. iank: ... dbaron: That has a computed value then, so it should show up. shane: Just in computed value then, not in specified/inline. shane: I wonder if we want to allow having an invalid initial value? TabAtkins: You can, have an unregistered property with grammar of * SimonSapin: What happens in old style CSSOM? TabAtkins: Undefined, but hopefully consistent. iank: It would make sense that all registered properties appear in computed style maps. TabAtkins: [...] shane: One pattern we've seen with untyped custom properties is that people use them like macros. shane: They put a lot of them at the root node shane: to represent colors that might be used on the page, etc. shane: Not uncommon to see pages with one or more custom properties defined. shane: Relatively easy to keep performant if not referenced much shane: But could be an issue for typed properties if the same pattern used, because significantly increases size of computed value map. shane: It would be bad if people typed their untyped custom properties. shane: At the very least, should provide suggestion that ppl don't do that. shane: But might want to look into CSS API for that. TabAtkins: Currently only JS api for registering, so most of these cases likely won't do that... shane: So, should typed custom properties show up in computed style? RESOLVED: custom properties that have an initial value show up in computed style, warn authors about perf issues if they type everything all the time RESOLVED: For inline style, should return the custom properties that are set on the inline style of the current node RESOLVED: For specified style, should return the custom properties defined in the current rule RESOLVED: For computed style, should return all defined custom properties on the current node (including inheritance) iank: We also may come back later with impl experience to say this was a terrible idea, but we'll see. SSStyleValue.parse(): throw vs return null? - - - - - - - - - - - - - - - - - - - - - - <shane> Topic: https://github.com/w3c/css-houdini-drafts/issues/305 TabAtkins: When you call CSSStyleValue.parse() TabAtkins: parses arbitrary string into typed OM value. TabAtkins: Takes a property name and a value. TabAtkins: Several ways to do something wrong, not sure whether to throw or return null. TabAtkins: 1st case is, property is not even an identifier. SimonSapin: If property is a separate arg, not parsed out from "prop:val" SimonSapin: Then do you even need to parse it? SimonSapin: For CSS.supports(), we have API with 2 variations. SimonSapin: One with colon syntax, uses CSS syntax. SimonSapin: Other one passes prop and value separately SimonSapin: In that case you don't parse it, TabAtkins: ... SimonSapin: Just assume it's an ident, TabAtkins: Yes, that avoids the issue entirely. iank: Might want to throw on the empty string. iank: We throw a SyntaxError on that. SimonSapin: Empty string is not valid property name. iank: It's not a valid function name. SimonSapin: Are we talking about property names. iank: First argument in custom paint is an ident, same issue. shane: What does supports() do with empty string? SimonSapin: Supports method, you can give it custom property, in which case name starts with -- shane: There are 3 different error conditions. shane: 1st, not a valid property name. If that's just empty string, still. shane: 2nd, valid property name, but doesn't exist. Can only happen for non-custom properties. SimonSapin: Could treat those the same. shane: 3rd, valid property name, but value's grammar doesn't match. shane: I thought 2 & 3 were the same, but both of them could be that you're simply running on a browser that hasn't built support for that syntax yet. TabAtkins: Taking the property name makes it not an error. shane: Could treat them all the same, and throw. Rossen: It would be easier to handle null from user side. Rossen: Rather than wrapping everything in try for parsing all over the place. Rossen: 1 & 2 are more of an error than 3. Rossen: 3 is you're parsing a value that you can't parse. shane: But both 2 & 3 could be that you're trying to parse a feature that the browser doesn't yet support. dbaron: It does feel like the more CSS-ish thing to do, not to throw for unsupported values or properties. dbaron: In normal CSS, they get silently dropped dbaron: so null seems more sensible. shane: Note that we throw if you set a value that doesn't parse according to your type already. dbaron: If mistyped things throw, then unknown things should throw. I would agree with that. philipwalton: My intuition is, you don't want to both try-catch and check for null when you're writing code. philipwalton: I think there are many cases you want try-catch, so throwing an error is probably best. <astearns> what about not throwing, but returning a value that throws an error when you try to read it? Could that be the worst idea? <TabAtkins> Worst idea, yes. <TabAtkins> Value that can validly be used, but represents a random property/value. shane: Rossen, you were leaning towards null before. What do you think now? Rossen: Not gonna object, but not gonna love it. iank: What's your hesitation? Rossen: More of a philosophical discussion. Rossen: I'm very biased to the APIs we work on on the Windows platform. Rossen: We have strict principles on what is an error, how to deal with errors, how to make API that is ergonomic for developers. Rossen: Don't want to sprinkle try-catch all over, half is error-handling, half is business logic. Rossen: We have strict rules to guide our APIs. Not gonna impose those here. fantasai: Might be worth having that philosophical discussion fantasai: and codify some principles for our APIs, whether same or different from Windows API principles shane: Inconsistent to return null here. shane: You then set this value, want to throw an error here [missed exactly the nuance there] <dbaron> I think Shane was saying that it's not as inconsistent as he thought it was before. <shane> yup. When we set values we need to throw an exception on error because there's no return value <dbaron> because the other case was setting an object and getting a type mismatch, whereas this is parsing a string. <shane> but here we're getting the result as the return value so we can use null to signal an error iank: Does TAG have any guidance? plinss: We have a document discussing principles for designing APIs, but don't have anything on this topic. Rossen [offers to review that? send feedback? something?] Rossen: So going back. Rossen: Are you reverting your opinion about throwing vs null? shane: Yeah. shane: I'm going back from saying we should throw to not having a strong opinion. Rossen: Does anyone have a strong opinion? philipwalton: Likely to do this in environment where you don't know what you're getting philipwalton: so maybe throw. Rossen: Think about it from a mid-layer library, start exposing some of those. Rossen: First they're going to write their own wrapper that does a throw/catch Rossen: are going to call that so they don't have to deal with throw/catch all over. Rossen: If that's the principle we design around, okay. Rossen: ... fantasai: Sounds like we should table discussion and have your philosophical discussion about throw vs null? plinss: To me, throwing is semantically different than returning an error. plinss: If you pass in a property that isn't an ident, e.g. numbers, can't possibly be a property name. Could see an error. plinss: But if passing a name that's unknown to the engine, then return null. plinss: Not recommending that's what we do, but there's a distinction between throwing errors and returning null, and it's useful to make that distinction. TabAtkins: If you do construct a value that doesn't make any sense, and you return null. Whatever you do with that will throw an error. TabAtkins: All you can do is check for null. plinss: Throwing is for exceptional circumstances like out of memory. plinss: I've tried using it for everything, and that way lies madness. plinss: For a certain class of things, throw exceptions, and be consistent about it. plinss: We need some guidance on that, and we don't have it. iank: I was just looking through a few of the Web apis, like json.parse iank: Dae.parse() does not ... seems like more things throw than silently fail. iank: HTML throws if not well-formed. iank: Could file an issue on the TAG. shane: Let's do that. Rossen: Let's resolve with following -- in all three cases we will be consistent in how we handle the condition. Rossen: And we will follow the TAG guideline on whether to throw or return null. <dbaron> The TAG guidance might not be all that prescriptive... <plinss> https://github.com/w3ctag/design-principles/issues/55 RESOLVED: Be consistent in all three cases; follow TAG guidelines once they have them. <br type = lunch> Numeric Values Rethink Revisited -------------------------------- <dbaron> Github topic: https://github.com/w3c/css-houdini-drafts/issues/359 shane: We came up with a proposal over lunch. shane: Getting rid of previous proposal that we resolved on shane: and replacing it with CSSNumericValue which has two subclasses: CSSMathValue and CSSUnitValue shane: CSSMathValue has two members, operator and operands shane: operator is a string representing a math operator like "*" shane: *, /, min, max, + shane: operands is a list of CSSNumericValue. shane: CSSNumericValue has a method called toSum which returns a map of units to numbers shane: representing a sum of those dimensions, as previously. shane: If the CSSNumericValue cannot be so reduced, it either returns null or throws, whatever the TAG decides. SimonSapin: If the initial syntax uses unnecessary parentheses or calc() inside of calc(), do we want the tree to preserve that information? TabAtkins: I would prefer we don't. <TabAtkins> calc(1px + (2px + 3px)) => CSSMath("+", [1px, 2px, 3px]) fantasai: I agree, because people put parenthesis when they want to clarify something, not just when they have a grouping, e.g. calc(1px + (2*2px)) xidorn: Do we want to distinguish between 3px and calc(3px)? TabAtkins: Yes, and we'll probably default it to the plus operator. plinss: Going back to unnecessary parens, I think we should preserve that structure. plinss: If author wants to reduce, can use toSum() plinss: E.g. 2*3em, they did that for a reason. TabAtkins: Don't have a problem with it, but would mean operator(+,[operator(+, [2px, 3px])]) <TabAtkins> Which would mean calc(1px + (2px + 3px)) => CSSMath("+", [1px, CSSMath("+", [2px, 3px])]) shane: Any code dealing with this would have to recurse anyway. TabAtkins: There's no non-broken code you could write that would break on extra parens being preserved. plinss: So let's preserve structure. SimonSapin: So no distinction between nested calc() and nested parens? TabAtkins: We don't even when serializing, so no. shane: What do you do when animating between calc(5px + (4em + 2%)) and calc(10px + 10em + 10%) TabAtkins: Animations are computed value anyway, and so they're necessarily reduced -- they're produced by the engine, not by the author. TabAtkins: The beginning point can be unit value, endpoint a calc(). What's in between? Engine decides. fantasai: Tab, since you were concerned about typing, could consider CSSMathValue as a listlike type, and .op as the operator member. TabAtkins: No, it's fine. SimonSapin: Earlier were talking about Proxy for arraylike stuff. SimonSapin: if it's not used here, where is it used in CSSOM? TabAtkins: TransformValue and UnparsedValue. SimonSapin: Why do we want to do something different here? TabAtkins: Semantically different -- this is an operator, and arguments to that operator. Those are fundamentally sequences. iank: So this proposal is completely replacing the CSSCalcValue stuff we discussed earlier? TabAtkins: Yep, throw it away. iank: So you wouldn't have any of those complex units like em*ch. iank: Right. TabAtkins: Still want to handle custom units whenever they exist. TabAtkins: Also may want to handle case-insensitivity. fantasai: Custom idents are case-sensitive. TabAtkins: Note in the spec that we don't have custom units yet, but plan to. Rossen: Sounds like ppl are happy with this? fantasai: Share Tab's earlier concern about operator and operand being perhaps a bit too long to type, but otherwise seems okay to me. [SimonSapin asks how percents represented] TabAtkins: As "percent". Didn't use "%" so that it wouldn't be weird to use as a .name plinss: Unitless zero? TabAtkins: Custom stuff can't use unitless zero, only in CSS syntax. TabAtkins: Also calc() can't have unitless zero. SimonSapin: I have some bugs to file then. SimonSapin: Specifically, a "0" value is a <number-token>, which gets typed by calc() to "integer", and you can't add "integer" and "length". TabAtkins: Servo/Stylo works the other way around: you try to parse <length>, unitless 0 and calc() are both valid inputs RESOLVED: Switch to CSSMathValue-based expression tree with toSum() method for returning dictionary of unit types ( as described above). Issue 310: Consider using properties in addition to .get/.set - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <shane> Topic: https://github.com/w3c/css-houdini-drafts/issues/310 shane: I want to either say No or wait until level 2 to consider this. Rossen: I'd be fine for that. RESOLVED: Using properties (issue #310) is moved to L2 Topic 350: Move Houdini APIs to `window.CSS` - - - - - - - - - - - - - - - - - - - - - - <shane> Topic: https://github.com/w3c/css-houdini-drafts/issues/350 shane: Have window.getComputedStyleMap() shane: It should either be CSS.getComputedStyleMap or CSS.getComputedStyle? shane: We called it getComputedStyleMap() earlier so it doesn't collide with getComputedStyle, but now we have an opportunity to use the other name. iank: Does it make sense to move that particular one to CSS from window? dbaron: Why isn't this element.computedStyleMap? dbaron: Putting getComputedStyle() on window was a mistake <shane> 1. Window.getComputedStyleMap() <shane> 2. CSS.getComputedStyleMap() <shane> 3. CSS.getComputedStyle() <shane> 4. Element.computedStyleMap leaverou: Why not just element.computedStyle leaverou: Which is what getComputedStyle should have been in the first place? dbaron: That's more or less what I said in the first place... leaverou: I thought you were proposing a function. dbaron: I think, IIRC, that other things that return style maps end in StyleMap, and wouldn't want to have just one that omits the word Map. dbaron: But should be a getter. leaverou: Especially if it has Map at the end. shane: I quite like element.computedStyleMap. iank: Is this live? TabAtkins: Yes, it's in the minutes. <TabAtkins> (Per the minutes, it's live and we're very sad about it.) SimonSapin: Style maps are live in general, but computedStyle is readonly isn't it? TabAtkins: Yes. SimonSapin: So it doesn't matter if it's live. dbaron: Yes it does, cuz then things are changed. TabAtkins: Nice thing is that values are hidden behind .get call so can compute them lazily. iank: One thing that getComputedStyle has is second argument is optional string for pseudo-element name. dbaron: We had this discussion before 5 years ago dbaron: We specced it all in CSSOM dbaron: But then deleted it because nobody implemented it. dbaron: But we did come up with API we liked for this dbaron: We had a pseudo-element class. birtles: I thought it was defined in two specs, in CSSOM and css-pseudo. fantasai: Stuff in css-pseudo is "here is some stuff as ideas, please comment on it" not ready to impl.. birtles: CSSPseudoElement is used by Web Animations shane: Let's do what dbaron says. shane: If we want to have pseudo-element class and have computed style of them hang off that class, then typed CSSOM might not let you get pseudo element styles. shane: Transiently while we put the rest of the mechanism in place. shane: But I don't think that's an issue given that the typed OM is incomplete in lots of other ways anyway. shane: So I think we should do what dbaron says. Rossen: I think we already established that :) shane: I'm gonna keep saying it until we resolve on it. Rossen: Was there some other option? shane: Yeah, I listed them out: <shane> 1. Window.getComputedStyleMap() <shane> 2. CSS.getComputedStyleMap() <shane> 3. CSS.getComputedStyle() <shane> 4. Element.computedStyleMap ( + pseudoElement mechanisms) Rossen: What's + pseudoElement mechanism? shane: Have an object representing the pseudoElement with a .computedStyleMap dino: Why not just .styleMap? ?: Because that's style attr. dino: But this is the API people actually want. ??: Could call it inlineStyleMap and computedStyleMap to be explicit about it. dino/smfr: People already get confused about .style being style attr and not computed style. TabAtkins: Don't really want to have .style = inlineStyleMap and styleMap = getComputedStyle <shane> 5. 4 + styleMap -> ??bikeshed??StyleMap <SimonSapin> .styleAttrMap / .computedStyleMap ? SimonSapin: Don't want to overload inline, already overloaded <leaverou> 4 (though it depends on the pseudo-element mechanisms) fantasai: I like .styleAttrMap / .computedStyleMap Rossen: attrStyleMap plinss: So that it's always StyleMap iank: No other DOM api abbreviates attribute. Rossen: Okay, we can bikeshed that later. Rossen: So, option #N is adopt element.attrStyleMap and element.computedStyleMap + pseudoElement mechanisms iank: I don't want the attribute thing. Rossen: We'll make it attributeStyleMap. RESOLVED: element.attributeStyleMap and element.computedStyleMap, attributeStyleMap to be renamed later, pseudo-element styles accessed through PseudoElement APIs. dino: Can someone summarize the pseudoElement stuff? TabAtkins: element.pseudos with .. dbaron: was a function pseudo(...) that returns element-like thing leaverou: What about parameterized pseudo elements? <dbaron> element.pseudo(":before").computedStyleMap <TabAtkins> "::before", certainly <fantasai> https://www.w3.org/TR/2013/WD-cssom-20131205/#extensions-to-the-element-interface fantasai: There's a reason we publish periodically to /TR with with dated snapshots :) <dbaron> https://hg.csswg.org/drafts/rev/26e59827f85c removed it <dbaron> It is present in https://www.w3.org/TR/2013/WD-cssom-20131205/#extensions-to-the-element-interface although there may have been later improvements before the removal Typed OM wrapup --------------- Rossen: we need to publish a new draft pending the changes RESOLVED: Update typed om draft on /TR with above edits
Received on Monday, 15 May 2017 08:42:31 UTC