Refactor CSSStyleDeclaration#284
Conversation
|
cssstyle/lib/CSSStyleDeclaration.js Line 131 in 87e5577 This line runs the parser every time set cssText() is called, so caching it here should result in a slight performance improvement. However, this contradicts what was previously stated in #271 (comment). What do you think? |
domenic
left a comment
There was a problem hiding this comment.
This all looks very nice, just one question and a few potential simplifications. I appreciate this small incremental commit.
| enumerable: false, | ||
| writable: true | ||
| }, | ||
| const { context } = opt; |
There was a problem hiding this comment.
Shorten these lines by doing constructor(onChangeCallback, { context }) {
There was a problem hiding this comment.
For now, not making it optional will cause regressions.
I'm planning to change the arguments in a follow-up PR before a major bump, so let us leave it as is.
There was a problem hiding this comment.
Sorry, I meant to type constructor(onChangeCallback, { context } = {})
| }, | ||
| // Internals for jsdom | ||
| this._global = globalThis; | ||
| this._onChange = typeof onChangeCallback === "function" ? onChangeCallback : null; |
There was a problem hiding this comment.
Let's simplify
| this._onChange = typeof onChangeCallback === "function" ? onChangeCallback : null; | |
| this._onChange = onChangeCallback; |
If the caller wants to pass null (or undefined) they can do so directly, instead of allowing any non-function value to trigger this.
| throw new this._global.DOMException(msg, name); | ||
| } | ||
| Array.prototype.splice.call(this, 0, this._length); | ||
| this._clearIndexedProperties(); |
There was a problem hiding this comment.
I really like these improvements to indexed property handling. Centralizing that all makes it much more clear.
There was a problem hiding this comment.
Please take a look.
There was a problem hiding this comment.
Hmm, personally I think it was clearer with two functions, but the new version is fine too.
| this[prop] = ""; | ||
| this.removeProperty(prop); | ||
| if (Object.hasOwn(propertyDescriptors, property)) { | ||
| propertyDescriptors[property].set.call(this, value); |
There was a problem hiding this comment.
Oh, this is very cool!
Let's add something like
// TODO: refactor handlers to not require `.call()` for the future.
| } | ||
| if (this._values.has(property)) { | ||
| const index = this._getIndexOf(property); | ||
| // The property already exists but is not indexed into `this` so add it. |
There was a problem hiding this comment.
I am confused how this could happen... Does it ever happen during our tests?
There was a problem hiding this comment.
This block has been around for a long time so I've never verified it, but it appears to be dead code.
Removed.
| this._priorities.delete(property); | ||
| } | ||
| this._values.set(property, value); | ||
| if (typeof this._onChange === "function" && !this._updating && this.cssText !== originalText) { |
There was a problem hiding this comment.
Per the above simplification let's just do if (this._onChange && ...)
There was a problem hiding this comment.
Done, also elsewhere.
First, I think doing any extra caching should be done in a separate PR from this one. Anyway, my position is similar to that previous comment. We should try to balance the number of caches vs. the performance improvement. I think the best way to balance this would be to benchmark 3 different setups:
When we have those numbers we can make a judgement call. Like, if (3) is 90% as good as (1) or (2), then probably (3) is best. But if (2) gives a 100% performance improvement, then we should just use four caches. Our benchmarks won't be perfect; in particular, as mentioned in #271 (comment), real-world apps might have worse cache access patterns. But we can react to any reports that people send and add them to the benchmarks and reconsider at that time. Until we get such reports, we can treat the benchmarks as our guide, with a small fudge factor like: 10% worse performance is acceptable if it means fewer caches. What do you think of this approach? |
918cb27 to
ce4e10f
Compare
domenic
left a comment
There was a problem hiding this comment.
To avoid extra delay I will integrate the parameter change myself and merge
Motivation
This PR refactors CSSStyleDeclaration to better match the internal architecture requirements for jsdom integration.
Key changes include overhauling the constructor, removing the setter for length, and converting internal methods to class methods.
Part of #255 (comment)
Changes
1. Constructor & Initialization Updates
2. Length Property
3. Internal Methods Refactoring
4. Documentation