Skip to content
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

perf(engine-dom): use adoptedStyleSheets.push #2683

Merged
merged 1 commit into from Feb 10, 2022

Conversation

nolanlawson
Copy link
Contributor

@nolanlawson nolanlawson commented Feb 7, 2022

Details

Chrome recently made adoptedStyleSheets mutable (see this post and WICG/construct-stylesheets#45). The idea is that, instead of doing:

shadowRoot.adoptedStyleSheets = [...adoptedStyleSheets, sheet]

...you can do:

shadowRoot.adoptedStyleSheets.push(sheet)

Benchmarking

In prior testing (WICG/construct-stylesheets#94 (comment)), I indeed found some overhead from cloning and re-assigning the array. This is actually why we don't use adoptedStyleSheets at the document level – it tends to have so many stylesheets that the perf cost of repeatedly cloning the array is too high.

Just to be sure, I wrote a new microbenchmark. It confirms that calling push is indeed faster than re-assigning the array. With 1000 components and 100 stylesheets per component, testing the median of 5 runs on Chrome Canary 100, I got 4491.3ms (re-assignment) vs 334.5ms (push), so it's a pretty big difference.

Feature detection

Unfortunately, there doesn't seem to be a straightforward way of testing that adoptedStyleSheets.push is supported. In the old (frozen) array, it has all of the mutation methods (push, shift, pop, etc.), but if you call them, they throw an error:

TypeError: Cannot add property 0, object is not extensible

The most succinct detection method I found is:

const supported = Object.getOwnPropertyDescriptor(document.adoptedStyleSheets, 'length').writable

This is correctly true in Chrome Canary 100 and false in Chrome 97. It's also correctly false in Firefox Nightly 98 with the constructable stylesheets flag enabled.

Does this pull request introduce a breaking change?

  • ✅ No, it does not introduce a breaking change.

Does this pull request introduce an observable change?

  • ✅ No, it does not introduce an observable change.

@nolanlawson
Copy link
Contributor Author

FWIW, I also ran all our Karma tests through Chrome Canary 100 with DISABLE_SYNTHETIC=1 to make sure they pass.

Copy link
Member

@ekashida ekashida left a comment

Choose a reason for hiding this comment

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

Nit: Instead of relying on the implementation of length, maybe we should instead invoke the push() in a try-catch to determine whether we can use it? No strong feelings about this either way.

@nolanlawson
Copy link
Contributor Author

@ekashida Yeah, I waffled between the two, but the length trick is much shorter. And it seems like... if it's mutable, then setting length should work? It works with normal arrays:

const arr = [1,2,3]
arr.length = 0
arr // []

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

Successfully merging this pull request may close these issues.

None yet

2 participants