-
-
Notifications
You must be signed in to change notification settings - Fork 80
Refactor CSSStyleDeclaration #284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This all looks very nice, just one question and a few potential simplifications. I appreciate this small incremental commit.
lib/CSSStyleDeclaration.js
Outdated
| enumerable: false, | ||
| writable: true | ||
| }, | ||
| const { context } = opt; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shorten these lines by doing constructor(onChangeCallback, { context }) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I meant to type constructor(onChangeCallback, { context } = {})
lib/CSSStyleDeclaration.js
Outdated
| }, | ||
| // Internals for jsdom | ||
| this._global = globalThis; | ||
| this._onChange = typeof onChangeCallback === "function" ? onChangeCallback : null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
lib/CSSStyleDeclaration.js
Outdated
| throw new this._global.DOMException(msg, name); | ||
| } | ||
| Array.prototype.splice.call(this, 0, this._length); | ||
| this._clearIndexedProperties(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like these improvements to indexed property handling. Centralizing that all makes it much more clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please take a look.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, this is very cool!
Let's add something like
// TODO: refactor handlers to not require `.call()` for the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
lib/CSSStyleDeclaration.js
Outdated
| } | ||
| 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am confused how this could happen... Does it ever happen during our tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This block has been around for a long time so I've never verified it, but it appears to be dead code.
Removed.
lib/CSSStyleDeclaration.js
Outdated
| 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per the above simplification let's just do if (this._onChange && ...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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