The attack unfortunately still slows us down, but this prevents us from
OOMing. Currently, we don't save the value of `var(--foo)` after
computing it once, so in this example, we end up computing `--prop1` 4
times to compute `--prop3`, but then we start again from scratch when
computing `--prop4`:
```css
--prop1: lol;
--prop2: var(--prop1) var(--prop1);
--prop3: var(--prop2) var(--prop2);
--prop4: var(--prop3) var(--prop3);
}
```
This should be solvable later if we update the computed values as we go.
"Arbitrary substitution functions" are a family of functions that
includes var() and attr(). All of them resolve to an arbitrary set of
component values that are not known at parse-time, so they have to be
substituted at computed-value time.
Besides it being nice to follow the spec closely, this means we'll be
able to implement the others (such as `if()` and `inherit()`) more
easily.
The main omission here is the new "spread syntax", which can be
implemented in the future.