[css-houdini-drafts] TypedOM returning an array of strings isn't a helpful behavior

FremyCompany has just created a new issue for 
https://github.com/w3c/css-houdini-drafts:

== TypedOM returning an array of strings isn't a helpful behavior ==
@tabatkins, @shans and myself discussed in another thread the 
currently specced behavior of TypedOM when the specified value of a 
property contains a variable reference, or when the property being 
analyzed doesn't have a type which can be expressed in TypedOM.

## Problem
Here are two examples of such situation:
```
height: calc(42px + var(--foo, 15em) + var(--bar, var(--far) + 15px))
```
and
```
--grid-gap-increment: 5px;
```

Let's figure out you want, as an author, to use TypedOM to animate 
those values efficiently, you will find out the spec fails to deliver 
what it promises in the spec abstract:

> Converting CSSOM value strings into meaningfully typed JavaScript 
representations and back can incur a significant performance overhead.
 This specification exposes CSS values as typed JavaScript objects to 
facilitate their performant manipulation.

Indeed, calling ```CSSValue.parse``` or using ```getStyleMap``` on 
those cases will produce a ```CSSTokenStreamValue``` (currently being 
renamed, my proposal being ```CSSUnparsedValue``` or 
```CSSRawValue```, see #193).

The problem is that currently parsing the previous "height" 
declaration returns 
```
[ 
    "calc(42px + ",
    { 
        variableName: "foo", 
        fallback: [ " 15em" ], 
        __proto__: CSSVariableReferenceValue.prototype 
    }, 
    " + ",
    { 
        variableName: "bar", 
        fallback: [ " ", { variableName: "far" ... }, " + 15px" ], 
        __proto__: CSSVariableReferenceValue.prototype 
    },
    ")"
]
```

The problem is that there is not much a JavaScript code can do with 
this. It is easier to parse again the string with a custom-made parser
 than try to interpret the sliced strings, except if you want to 
update the variable references.

Basically, if you want to modify this value in any way in JavaScript, 
you are now forced to parse this string on your own, rendering TypedOM
 impossible to use as it was intended to be used initially in this 
case, which I do not think is an edge case.

Now, because of the variable references, it would be impossible to 
parse this entirely normally, of course. The proposal here would be to
 expose just enough syntax to help authors change numeric values, or 
replace keywords by another keyword easily.

## Proposal
Under my proposal, here is how the returned value for the previous 
height declaration would be:
```
CSSUnparsedValue { cssText: "calc(42px + var(--foo, 15em) + var(--bar,
 var(--far) + 15px))", content: [
   CSSUnparsedFunctionValue { cssText: "calc(42px + var(--foo, 
15em)...", functionName: "calc", content: [ 
        CSSLengthValue "42px", 
        CSSUnparsedValue { cssText: "+" }, 
        CSSVariableReferenceValue { variableName: "bar", fallback: [ 
CSSLengthValue "15em" ] },
        CSSUnparsedValue { cssText: "+" }, 
        CSSVariableReferenceValue { variableName: "bar", fallback: [ 
... ] },   
    ]
}
```

The full proposal would be as follows:
- ```CSSUnparsedValue``` would not be an iterable of string; the 
current iterable would instead live on a property of 
```CSSUnparsedValue``` called ```cssTextSlices```. That would be a L1 
change.
- In addition, in either L1 or L2, ```CSSUnparsedValue``` would get a 
```content``` property, whose value would be an array of 
```CSSUnparsedValue``` (or null if ```CSSUnparsedValue``` cannot be 
divided in smaller parts).
- Inside content, values are at least broken apart by AST roots: 
```5px url(...) center``` would become three values featuring their 
own cssText: ```5px```, ```url(...)``` and ```center```. We can do 
this without loss of generality based on whitespace and block 
processing in css-syntax.
- values like numbers and numbers+units get parsed properly based on 
their unit if it is known, or as ``` CSSUnparsedMeasure { 
value:number, type:string } ``` if not
- blocks and functions can be introspected (blocks as ``` 
CSSUnparsedBlock { openingChar:string, content:CSSUnparsedValue, 
closingChar:string } ``` and functions as ``` CSSUnparsedFunction { 
functionName:string, arguments:CSSUnparsedValue }```)

Everything else ("red", "#foo", ...) remains a dummy atomic 
CSSUnparsedValue value that can only be analyzed through cssText. That
 would be sufficient to solve the efficiency problem when you need to 
update the numeric value of something and needs to resort to string 
manipulation to do so now.

**Calls to action:**
- What do you think about that? 
- Is there anyone else who cares about the issue?

Please view or discuss this issue at 
https://github.com/w3c/css-houdini-drafts/issues/208 using your GitHub
 account

Received on Tuesday, 24 May 2016 05:16:54 UTC