Skip to content

[cssom] Properties that allow access to parsed-but-invalid syntactic constructs (declarations, rules, etc) as a low-fi way to make polyfills easier #13186

@LeaVerou

Description

@LeaVerou

In past discussions, it was always asserted that UAs need to throw away invalid tokens (properties, declarations, atrules, etc) encountered during parsing, which in turn has led to the problems around developing CSS polyfills as they need to handle fetching and reparsing entire stylesheets. Then, we end up designing entire new complex APIs to solve this problem such as the one presented in Paris in August (which I've failed to find now despite looking for a while, any help welcome).

I’m wondering if we have tested that assumption. It seems odd that there would be such vast amounts of invalid CSS code that keeping it around even in minimally processed form would incur such a significant performance impact. The UA has already done the parsing to figure out what the syntactic components are, so all we need to preserve is what has already been processed, the rest can be done lazily.

E.g. what would be the performance impact of the CSSOM having properties like:

  • CSSStyleDeclaration.prototype.source / CSSStyleRule.prototype.source / CSSStyleSheet.prototype.source : CSS code that produced the object, before parsing. Akin to ES internal [[SourceText]].
  • CSSStyleRule.prototype.rawStyle: like .style but would include all parsed declarations, whether valid or not. It doesn't need to be the same data structure as .style, e.g. with a data structure that supports multiple values per key (a la URLSearchParams) it could even preserve overidden declarations.
  • CSSStyleSheet.prototype.rawCSSRules: like .cssRules but would include invalid (but parseable) rules, with a CSSUnknownAtRule for unknown atrules (a la HTML's HTMLUnknownElement).
  • etc

Alternatively, we could have properties that only hold invalid syntax, though then figuring out how it interleaves with valid syntax becomes difficult to impossible.

These would be:

  • Lazily instantiated when accessed for the first time, so that the only thing the UA really needs to keep around is their source text, which seems fairly lightweight
  • Non enumerable to minimize accidental reads
  • Any objects pointing to valid syntactic components would be shared with the regular CSSOM

Later down the line we could introduce actual primitives that make polyfills even easier, such as:

  • Query the tree for certain things without full traversal (e.g. which rules include a certain property?)
  • Actually register certain properties/pseudo-classes/atrules/etc
  • etc

But even without that, simply preserving these constructs and having a way to access them would immediately make polyfills tremendously easier, and seems relatively easy to design and ship. It could also be immensely useful for devtools and other tooling.

Additionally, these properties can ship independently and each one immediately improves the situation even without the others.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions