- From: Dael Jackson <daelcss@gmail.com>
- Date: Sun, 9 Oct 2016 20:39:15 -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
--------
- RESOLVED: StyleValue must be immutable.
- RESOLVED: Specified style map should be live.
- RESOLVED: Computed style map is live.
Stringification behavior
------------------------
- There were three options presented for what to stringify:
1) Minimal representation, which when reading it back it would
be a different value than if you go through the old API.
2) Try and reproduce behavior of old OM (which wasn't
consistent across browsers).
3) Always use source string.
- RESOLVED: For computed style we'll use the minimal
representation. This will give the same serialization
as the CSSOM does for computed style when the values
match.
- A resolution wasn't reached for specified style, but the
proposal was to re-serialize and pull out the string.
CR for Paint
------------
- RESOLVED: Move global name resolution out of Paint level 1 to a
future spec.
- RESOLVED: Match canvas, transparent by default.
- RESOLVED: Issue #1 resolved by matching properties/values syntax
and adding input arguments.
- RESOLVED: Paint API level 1 to CR (pending edits)
Appropriate string representation to use in specified style
-----------------------------------------------------------
- shane presented three options:
1. use string as-is
2. round-trip through CSS parser
3. minimal representation
- There was a push to make sure that whatever approach is taken
won't later become something we have to deal with for
backwards compat.
===== FULL MINUTES BELOW ======
Agenda: https://github.com/w3c/css-houdini-drafts/wiki/TPAC-F2F-September-2016
Scribe: eae
Typed OM
========
<dbaron> https://drafts.css-houdini.org/css-typed-om/
Should StyleValues be immutable?
--------------------------------
shane: Two questions we couldn't resolve through issues on github
that it would be good to have an answer for.
shane: First up, "Should StyleValues be immutable?"
shane: StyleValues are the values that are stored in the style
map. Currently immutable. Cannot be changed, to update the
value in the style map you have to create a new style
value. I think this is the right solution but it is
different from early assumptions.
plinss: Difference between not being a live value and immutable.
shane: One advantage of immutable is that it is obvious it is not
live.
dbaron: How do you make a new one?
shane: Lots of constructors.
shane: There are also parsers, from DOM Strings, for each type. So
you could pass a Length type.
dbaron: What does the parser look like in the spec?
* shane presents the spec *
dbaron: I see a from method on CSSLength
dbaron: Some of the others don't have that.
shane: We haven't finished it yet.
TabAtkins: Everything will have a from.
shane: There will be a from method on every subclass that takes a
DOMString.
shane: CSSStyleValue objects have a parse method which takes a
property name and the string to parse.
TabAtkins: The use case for this is to represent, as a css style
value, anything we don't have a type for. Instead you
can parse it with this and the value of it will be a
cssvalue object.
shane: Then there are more specific constructors for things like
from(double value), from(Dictionary) etc
shane: Lots of different ways to construct. Could have discussion
about slimming that down.
shane: Low cost of maintaining.
plinss: What's the point of the dictionary?
shane: Things like calc, takes a dictionary of values.
TabAtkins: calc length stores as a sequence of just single unit
values. If you want to do multiplication you have to do
it on your own or do string parsing. Or use
CSSLengthValue::multiple and friends.
dbaron: There are a bunch of things that take a
Sequence<CSSValue>. Can you have a Sequence of Sequences?
TabAtkins: All are comma separated lists; one level.
shane: We don't do things like transform. Doesn't make sense to
consider first value of transform in isolation. Unlike
background where the first value means something.
dbaron: If you have something complicated as box shadow?
TabAtkins: Would be a sequence of style values. Would be list of
things where each thing represents a box shadow.
shane: In the future there would be a box shadow type.
dbaron: Is there a need for a definition of each type?
TabAtkins: Not at the moment, needs to have some description.
Opacity is easy, has one value, box shadow more complex.
TabAtkins: If more complicated than a single value or comma
separated list it would be represented by a style
object.
SimonSapin: There is one for each property?
shane: There is a type for each grammar thing.
TabAtkins: Right now we can only handle properties with a single
production.
TabAtkins: Eventually there will be things like a sequence of
these types for box shadow.
SimonSapin: Similar to have transition have specific text about it.
TabAtkins: Yes. Specialized type that it would return.
shane: Fundamentally quite similar.
Rossen: Going back to the issue.
shane: Question: Should these be immutable?
shane: Anyone think otherwise?
plinss: Not sure it's a bad idea; across the platform we have
somethings that are live objects, some dead, some
immutable. We should be consistent with the current trend
wrt dead vs immutable.
SimonSapin: Would sequences be immutable as well?
TabAtkins: Yes, all attributes of things.
shane: Can you make sequences immutable?
TabAtkins: Frozen array?
SimonSapin: Reconstruct each time? Is that easy?
TabAtkins: Yes.
SimonSapin: Okay.
dbaron: I feel that there are a couple of things here being
underspecified.
TabAtkins: Yes, but hopefully not surprising.
dbaron: How do you convert background position right 50% bottom
30px into an appropriate thing?
TabAtkins: We potentially loose some detail from specified values.
Would get a calc length that specifies something.
dbaron: calc length assumes we would never extend the syntax.
TabAtkins: Not necessarily, let's talk about it later.
shane: We wanted to talk about stringification. Maybe we can leave
that at overflow and get back to later.
dino: Examples would be nice.
TabAtkins: We describe positions as a set of calc offsets
<TabAtkins> background-position: top 10px right 10px;
<TabAtkins> ==>
<TabAtkins> el.styleMap.get('background-position')
<TabAtkins> CSSPositionVAlue(CSSSimpleLength(10, 'px'),
CSSCalcLength({px: -10, percent: 100}))
SimonSapin: If we get a value that can be either calc length or a
value, how do you tell the type?
TabAtkins: Check type of object.
SimonSapin: How?
TabAtkins: Using standard js syntax, instanceOf
JakeA: With background position, right 0 is the right hand side of
the image. Is that represented here?
TabAtkins: Yes, would be a 100% which is also right aligned.
shane: Reasonably happy it being immutable?
RESOLVED: Style value must be immutable.
How dead should the style maps be?
----------------------------------
<nainar> https://github.com/w3c/css-houdini-drafts/issues/149
shane: How dead is too dead.
TabAtkins: When you pull a style map up, is the entire map dead or
just the values?
dbaron: The style map for specified style allows mutation.
dbaron: You're asking whether to remove that?
TabAtkins: We still need to be able to construct style maps
appropriately
[TabAtkins shows example from issue 149, comment from shane on Jul
27.]
var map = el.styleMap;
map.get('height') // for argument's sake, CSSSimpleLength(100,
'px')
el.style.height = '200px';
map.get('height') // will still return CSSSimpleLength(100,
'px')
shane: This seems strange, the computed style objects are not
immutable. Having them be live is expensive?
SimonSapin: Why would it be expensive?
ojan: Would require style recalculation.
dbaron: For gecko the non-live implementation for computed style
would be easy.
dbaron: In gecko when it changes style it get a new object.
ojan: I think that matches the webkit and blink implementation.
ojan: Computed style is cheap if it has already been computed.
Non-live.
ojan: Would be confusing for authors if it flushed style recalc.
esprehn: Not sure how we wouldn't do that?
esprehn: Need to resolve percentages?
dbaron: Layout flushes.
dbaron: getComputedStyle is live.
SimonSapin: Depends on if you want computed values
TabAtkins: Our intention is to use actual computed values, not
resolved values.
SimonSapin: So percentages stay that way.
dbaron: One of the other question, does the style map get a flush?
shane: I think it has to.
dbaron: I think so too.
gregwhitworth: So, what would that be in the example? 200px?
ojan: Yes.
dbaron: More complicated issue, if the element set style way
before to 50px and here (line 2) you set it to 100px, If
this line didn't flush it could still be 50px, or it
flushed on line 2 and it's 100px, if it flushes later you
might get 200
shane: How live is it?
gregwhitworth: To me, when you called it, it should be computed
before me it's what will be returned.
TabAtkins: Flushed non-live?
esprehn: If you want be non-live it should be a method.
esprehn: .getStyleMap(), returns a new map every time. Ergonomics
would be bad.
esprehn: Would be hard, we lazy compute a lot.
TabAtkins: Specified style should be live so you can set things?
shane: So that you can set.
ojan: We have element.styleMap is live, .getComputedStyleMap() is
not a live thing. Has a snapshot problem.
dbaron: Gecko doesn't have the snapshot problem. Most other
implementations would.
shane: Even across style updates?
shane: What if I call element.getComputedStyleMap then do
something to change it, is that reflect in the returned
style map?
esprehn: Yes, has to be, or we need to snapshot, which is
expensive.
esprehn: We do a lot lazily today, if we snapshot all lazily
computed values must be computed at time of snapshot.
Would be very expensive. We do it for limited things,
alignment, user select etc.
shane: I'm fine with it being live.
ojan: I'm sad about it flushing style recalc on every getter
gregwhitworth: We've been talking about this for two years. We
want to fix it but not realistic.
surma: What if make the developer specify the values they want? So
that we don't have to compute all of them?
ojan: Would make me happy.
dbaron: Similar to having it be live.
ojan: For user agents that already compute it would be similar.
Much easier for other implementations.
ojan: element.getComputedStyleMap('list of properties')
SimonSapin: Isn't that the same as .get?
ojan: You could call get 15 minutes from now.
dbaron: I don't think users will understand what is expensive or
not.
esprehn: Only protecting you against flushes on the same element.
Not sure that would save one from much.
ojan: Quite common I feel.
shane: Why not just move getComputedStyleValue? So that the
element is the map for the computed value?
<shane> element.getComputedStyleMap().get('height');
<shane> ^ NOOOOO
<shane> element.getComputedStyleValue('height');
<shane> ^ \o/
ojan: Has same problem with interleaved read/writes.
dbaron: The second one isn't that different from a live object.
shane: Except the element is already live, we're not adding more
live object.
TabAtkins: Except it would still cause a flush for each ready if
the developer isn't careful.
shane: Idea of list of properties would be to return a guaranteed
snapshot causing at most one flush. What's the downside?
surma: List of properties.
dbaron: A lot of work to avoid flushing, if that is what we want
to avoid we should design for that explicitly.
shane: Like a flag? avoidFlush?
dbaron: Something like run this code without flushes with a
callback?
ojan: Can of worms.
JakeA: Dom transactions kind of thing?
iank: Yes, let's not get into that.
JakeA: Making this API harder to deal with to try to solve dom
transactions seems wrong
TabAtkins: Three options. A) Live objects, B) Snapshot, expensive,
C) snapshot for a few properties.
ojan: Specified one should be live. No objections? Yay!
RESOLVED: Specified style map should be live.
[group votes for computed style map]
<TabAtkins> C, then A
<shane> A
<surma> C > A
<dbaron> A
<eae> A
<iank> NOT B
<JakeA> A - but I don't know a ton about the problem
<dino> C, but the API is very sucky so I don't like it.
<nainar> A
<Rossen> C
<atotic> C
<SimonSapin> A
<iank> OMG NO WAIT!
<ojan> what dino said!
<dino> element.style.getComputedStyleMap('width').get('width') //
yuck
shane: No strong consensus. B can be ruled out.
esprehn: Can we leave it as live for now? And then experiment with
snapshotting?
shane: Can I make a suggestion for C?
<shane> element.style.getComputedStyleMap('width', 'height',
'...') --> { width: ..., height: ...., }
dino: Still seems really bad, element.style.getComputedStyleMap
('width', 'height', '...').width. Yick.
<JakeA> const [width, height] = getComputedStylesThingy(['width',
'height'])
<TabAtkins> JakeA: Or `const {width, height} = ...`
shane: A it is.
RESOLVED: Computed style map is live. We are all sad.
shane: That is all for typed om.
SimonSapin: Getters over attributes communicates that it is more
expensive.
Stringification behavior
========================
<eae> https://github.com/w3c/css-houdini-drafts/issues/268
shane: There are three different behaviors we could stringify.
shane: First option is a minimal representation. Downside is that
reading it back it would be a different value than if you
go through the old API.
shane: The second option would be to try to reproduce the behavior
in the old OM.
shane: It's not consistent across browsers.
dbaron: Neither specified.
shane: I don't want to do that UNLESS it comes straight from a
stylesheet. Makes sense there.
shane: Third option; always use the source string.
shane: Currently speced is a combination of the three. Not ideal.
We should pick one.
shane: Would anyone object to always going with the minimal
representation?
dbaron: In a room full of implementors I don't think anyone is
going to object.
shane: Let's ask devrel?
surma: I'd prefer numeric representation
ojan: Need more examples.
Rossen: What about colors?
<shane> color: red;
<shane> color: rgba(255, 0, 0, 1)
ojan: Color is a good example of... depends on how you use it.
eae: Helpful if you want to animate or manipulate it to get
numeric value.
ojan: Unexpected for authors.
iank: I think rgb is OK. A lot of use cases are for quality
testing. At least that is one use case.
ojan: People do things like read out the value, if (color ==
'red') etc.
surma: but then they could skip the typed OM all together.
aleks: Is there an option to do both?
shane: Let's not do that.
Rossen: When we're talking about css values, which are we talking
about? Specified? Computed?
Rossen: For computed there is no point in having original values
(i.e. red). For specified on the other hand it makes a lot
more sense.
TabAtkins: You are proposing, values pulled out of stylesheets
gets the parsed representation?
Rossen: Right
gregwhitworth: That is already not true. If you pull out color you
get rgb.
gregwhitworth: I don't want getComputedStyle to not return
computed. Specified should stay specified.
shane: We did this for color already, color names are aliases.
Some browsers do it during parse.
gregwhitworth: We should check with developers about use cases.
shane: Keeping specified would be expensive.
gregwhitworth: Don't we do that already for devtools?
shane: Only with devtools open.
shane: It's the most sane but I do not want to commit to it
without investigation. Might be expensive or use a lot of
extra memory.
gregwhitworth: I feel like we need author feedback on this.
shane: I think it's clear that we do not always want the minimal
representation.
shane: For computed style we DO want minimal.
dbaron: Is this different from the minimal representation in
getComputedStyle?
ojan: This would not be resolved style. For width: auto you would
get "auto".
TabAtkins: Would only be different when the VALUES are different.
shane: Serialization would be the same.
RESOLVED: For computed style we'll use the minimal representation.
This will give the same serialization as the CSSOM does
for computed style when the values match.
Rossen: Good! How about for specified?
shane: There are again three cases.
shane: We can't do anything for the first case, when you use a
style value constructor. Minimal is only option.
shane: Second case is using a parser, the most sensible options
would be either minimal representation (same as for
construct) or fateful string representation.
TabAtkins: Minimal seems more consistent.
shane: Would potentially change as you instantiate more types.
shane: Without type we can only do the fateful representation,
when we add type it would switch to minimal.
TabAtkins: OM defines how to serialize.
ojan: We're forced to use the string representation for types
without an implementation. We don't want to change it when
we add a new type.
TabAtkins: OM already defines how to serialize, so we know how to
do it.
dbaron: Are we talking about computed or specified now?
TabAtkins: Specified.
<TabAtkins> CSSStyleVAlue.parse('box-shadow', "...")
shane: Proposal re-serialize and pull out the string.
ojan: Authors underestimate the memory overhead of keeping the
strings.
<dbaron> I think ojan convinced me that CSSStyleValue.parse()
needs to serialize in specified values the same as things
from a style sheet or a string-based setter -- but that
doesn't necessarily apply to CSSLengthValue.from()
<eae> dbaron++
esprehn: One of the key problems with things like rgb is that it's
hard for developers to know what it is and do comparison.
With typed om we're fixing that so that one can compare
and determine that it's red.
[break for lunch]
Scribe: jet
CR for Paint
============
Rossen: Let's go over open issues.
iank: A few issues from bz, heycam review back in June.
iank: 17 open issues in GitHub.
iank: A lot are text fixups.
Should registered paint names be limited to shadow trees they are in?
---------------------------------------------------------------------
<nainar> https://github.com/w3c/css-houdini-drafts/issues/223
iank: non-editorial bug ^
esprehn: Global name resolution seems very hard.
iank: Can move to CSS Paint API level 2
TabAtkins: We already treat animations this way (via inheritance)
esprehn: Does it work with variables?
esprehn: Would be nice to solve this for CSS globally
RESOLVED: move out of Paint level 1 to a future spec
Add "alpha" as an option
------------------------
iank: Issue 220.
<nainar> https://github.com/w3c/css-houdini-drafts/issues/220
iank: Currently no alpha on an all-black canvas.
ojan: If you know you're opaque you can optimize.
TabAtkins: How about instead of alpha, you specify a BG color.
TabAtkins: rgba color.
TabAtkins: So we can paint something even when Paint callbacks
aren't ready.
iank: Currently we paint black on throws.
TabAtkins: Default to transparent default image?
TabAtkins: Before paint runs for the first time.
dbaron: Even if default is opaque, if authors don't want that,
people will turn off the optimization
*anti-aliasing on opaque surfaces discussion ensues*
iank: summary: what do we think about opaque by default?
plinss: aka opt-in for alpha.
JakeA: Canvas is transparent by default.
surma: Opt-in is fine.
surma: Can we match the behavior of having a transparent image by
default?
JakeA: We can have LCD anti-aliasing by default if opaque.
ojan: I think this is true for all implementors who have LCD AA.
surma: Matching canvas is desirable.
<eae> having lcd aa with transparent backgrounds would require
alpha per channel => a lot of extra memory.
dbaron: Spec should mention both anti-aliasing of text and
performance optimizations for things that are opaque.
ojan: Background animated images occluded by transparency is a
common use/perf hit.
bz: Background size calls paint again?
TabAtkins: yes
RESOLVED: Match canvas, transparent by default
RESOLVED: Issue #1 resolved by matching properties/values syntax
and adding input arguments
Rossen: Also add example for conic gradients
RESOLVED: Paint API level 1 to CR (pending edits)
Appropriate string representation to use in specified style
===========================================================
shane: 1. use string as-is
shane: 2. round-trip through CSS parser
shane: 3. minimal representation
shane: issue: which option to use?
TabAtkins: Minimal representation can be safe but CSSOM may depend
on things not represented
TabAtkins: Probably safer to use as-is input string.
TabAtkins: When we later add a box-shadow type, you'll get a
minimal representation
TabAtkins: for future types we can throw away the string.
SimonSapin: Does this string get preserved after going through the
style map?
SimonSapin: Is this an exact string with whitespace/comments?
TabAtkins: #1 preserves, #2 doesn't.
TabAtkins: Better to retain a token stream?
dbaron: Should test current implementations.
shane: We resolved to not expose token streams in CSS.
TabAtkins: Custom properties uses exact representation per CSS.
TabAtkins: CSS.parse() preserves the original string
TabAtkins: For memory, better to keep token stream or original
string?
esprehn: Give an example?
TabAtkins: CSSStyleVale.parse(box-shadow: black)
TabAtkins: Should we preserve the whitespace?
esprehn: If we don't care about whitespace, save token stream.
<TabAtkins> CSSStyleVAlue.parse('color', ' red')
<TabAtkins> Does this give:
<TabAtkins> 'red'
<TabAtkins> or ' red'
dbaron: We don't use token stream now, we use a typed value
representation.
dbaron: eg, specified style.
dbaron: If you call CSSTRansformValue's constructor, then you get
the specified style back, you need to construct a
canonical string somehow
dbaron: eg., for shadow: color, blur, x,y , spread.
dbaron: If blur defaults to 0.0 you may omit it from the string.
dbaron: Do you then use the constructAStringFromCSSStyleValue
operation only when you call the constructor, or in other
cases?
dbaron: TabAtkins wants to use it in other cases.
dbaron: Bad idea to use from shadowValue.parse() if we add
properties later.
dbaron: Currently records empty vs. zero
dbaron: we may end up omitting or adding later.
dbaron: We should follow CSSOM string generation rules though need
better spec.
<dbaron> or at least, we should unless we have a good reason to
construct yet a different set of rules
<esprehn> I'd prefer 'red', otherwise a CSSColorValue needs to
have storage for the string
<esprehn> trying to understand under what cases the space at the
start matters
<glazou> +1 to what esprehn said
<glazou> esprehn: matters if you build a css-like language but
still want to parse whitespace
<TabAtkins> esprehn: It *probably doesn't* matter. I don't care
about that. But the spaces stick around if we spec
that you hold onto the original string.
<TabAtkins> And they might not, if we spec that you just hold onto
some value representation (probably token stream).
<glazou> wait...
<glazou> if we have a css parser
<glazou> it should allow non-css languages based on css general
syntax
<Rossen> glazou, right, so you're agreeing we should keep the
original input string
<glazou> I agree that we should be able at least to detect there
are leading ws
<TabAtkins> glazou: That's a totes different topic.
<glazou> one way or another
<Rossen> glazou, agreed
<glazou> in other terms, s* should be detected
<glazou> FWIW, my jscssp parser preserves the original string on
each construct *and* can detect ws and comments and
report them individually
TabAtkins: How about: if we build something out of a string, use
CSSOM rules otherwise minimal representation.
shane: This sounds horrible to implement.
<shane> position: center center
shane: In typed OM, I'd expect two length values 50% 50%.
dbaron: Whatever we do today for specified style, let's use that
and not make a new representation.
shane: For typed OM center center isn't useful.
dbaron: Typed OM should return 50% 50% but the style map should
return what it does today.
<TabAtkins> el.style.backgroundPosition = "center center"; print(
el.styleMap.get("background-position") + ""); //yields
"center center"
<TabAtkins> Because print(el.style.backgroundPosition) also does.
<esprehn> typedom CSSStyleValue today does: virtual String
cssText() const { return toCSSValue()->cssText(); }
<esprehn> so it converts to the old internal representation and
returns that
<TabAtkins> el.styleMap.set("background-position",
CSSPositionValue.from("center center"); print(
el.styleMap.get("background-position" + ""); // yields
"center center"
<TabAtkins> el.styleMap.set("background-position", CSSPositionValue
(CSSLengthValue(50, "%"), CSSLengthValue(50, "%"));
print(el.styleMap.get("background-position") + ""); //
yields "50% 50%"
dbaron: We wouldn't be here if we had types for all CSS values but
we currently don't
dbaron: but when we do, we shouldn't change and break
backwards-compat.
*chromium internals spoken here*
<glazou> have you guys discussed access to the parser only or the
lexer too ?
<TabAtkins> glazou: Not yet. But look at
https://github.com/WICG/CSS-Parser-API
<glazou> thx TabAtkins
<TabAtkins> glazou: Better: http://wicg.github.io/CSS-Parser-API/
<glazou> TabAtkins woah
<gregwhitworth> http://jsbin.com/jupewavidi/edit?css,js,console,output
<gregwhitworth> ^ testcase showing background-position
TabAtkins: When we take a string straight to TypedOM without going
thru the legacy system, do we reconstruct or return
as-is?
TabAtkins: if/when we change that CSSOM system, this will also
change if we use the same system.
Aleks: What is the use case for the string API?
Received on Monday, 10 October 2016 00:40:15 UTC