Skip to content

Conversation

asamuzaK
Copy link
Contributor

@asamuzaK asamuzaK commented Sep 8, 2025

Part of #235
Rebased #243

Fixes #242, fixes #247, fixes jsdom/jsdom#3939, fixes jsdom/jsdom#3940
I'll include wpt style tests later (when I submit a PR to jsdom to update the cssstyle)

Spec: https://drafts.csswg.org/cssom/#the-cssstyledeclaration-interface

  • Breaking change: the functionality provided by CSSStyleDeclaration is now provided by CSSStyleProperties, i.e. use new CSSStyleProperties() to create an instance.
  • Breaking change: the arguments to new CSSStyleProperties() are different from the arguments to new CSSStyleDeclaration().
    • The first argument is a Window.
    • The second argument is an options object.
      • The on change callback previously received as the first argument should be included in the options object using onChange key.
    const node = document.createElement("div");
    const callback = cssText => {
      console.log(cssText);
    };
    const style = new CSSStyleProperties(window, {
      onChange: callback
    });
  • Switched main entry point from ./lib/CSSStyleDeclaration.js to ./lib/index.js.
    • Exporting 3 files from index.js.
      • CSSStyleDeclaration.js
      • CSSStypeProperties.js
      • propertyList.js
        • List of supported properties and their definitions.
  • Updated dependencies and devDependencies.

@asamuzaK asamuzaK marked this pull request as draft September 8, 2025 14:04
@asamuzaK asamuzaK force-pushed the style2 branch 5 times, most recently from 3ae525e to ab291f8 Compare September 9, 2025 21:17
@asamuzaK asamuzaK force-pushed the style2 branch 7 times, most recently from 1a3321e to 46b08ca Compare September 14, 2025 06:07
@asamuzaK asamuzaK marked this pull request as ready for review September 14, 2025 06:56
@asamuzaK asamuzaK requested a review from domenic September 14, 2025 06:56
@asamuzaK
Copy link
Contributor Author

Back to draft, will enable after jsdom@27 issues are addressed.

@asamuzaK asamuzaK marked this pull request as draft September 19, 2025 11:55
@asamuzaK asamuzaK force-pushed the style2 branch 2 times, most recently from 8c0a95d to e115115 Compare October 3, 2025 00:44
@asamuzaK asamuzaK marked this pull request as ready for review October 3, 2025 23:36
@asamuzaK
Copy link
Contributor Author

asamuzaK commented Oct 3, 2025

Ready for review.

Copy link
Member

@domenic domenic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tested this with a local fork of jsdom yet? It's probably best to merge and release only once we know it works.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain the purpose of this file in a longer comment at the top of it? I'm curious about questions like:

  • Why is lru-cache alone not good enough?
  • What is the deal with null cache items? How do they differ from storing "null", or not storing anything at all?
  • Why do we need a custom JSON stringification instead of using the default? Why is JSON involved at all?

constructor(onChangeCallback, opt = {}) {
// Make constructor and internals non-enumerable.
constructor(globalObject = globalThis, opt = {}) {
// Make internals non-enumerable.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This extra work should no longer be necessary in the new architecture. We can just set properties normally.

this._readonly = true;
} else if (context.nodeType === 1 && Object.hasOwn(context, "style")) {
this._global = context.ownerDocument.defaultView;
if (context.nodeType === 1) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please declare a constant for this at the top of the file.

}
if (typeof onChangeCallback === "function") {
this._onChange = onChangeCallback;
if (typeof opt.onChange === "function") {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably best to assume such a function is always passed.

}

// Non-standard
setOptions(opt = {}) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a comment for what this will be used for? (In general, changing options after creation seems unusual, so documenting it is good.)

}

const propertyNamesJSON = JSON.stringify(Array.from(propertyNames), undefined, 2);
const propertyNamesJSON = JSON.stringify([...propertyNames], null, 2);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: prefer undefined to null for triggering defaults.

Suggested change
const propertyNamesJSON = JSON.stringify([...propertyNames], null, 2);
const propertyNamesJSON = JSON.stringify([...propertyNames], undefined, 2);

);
const dateToday = new Date();
const [dateTodayFormatted] = dateToday.toISOString().split("T");
const [dateTodayFormatted] = new Date().toISOString().split("T");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I find this part of JavaScript very confusing so I prefer parentheses.

Suggested change
const [dateTodayFormatted] = new Date().toISOString().split("T");
const [dateTodayFormatted] = (new Date()).toISOString().split("T");

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this file is separate from CSSStyleProperties.test.js? Maybe one or both of them should get a comment, if the separation is intentional?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants