Single style capture (#1437)

Support a contrived/rare case where a <style> element has multiple text node children (this is usually only possible to recreate via javascript append) ... this PR fixes cases where there are subsequent text mutations to these nodes; previously these would have been lost

* In this scenario, a new CSS comment may now be inserted into the captured `_cssText` for a <style> element to show where it should be broken up into text elements upon replay: `/* rr_split */`
* The new 'can record and replay style mutations' test is the principal way to the problematic scenarios, and is a detailed 'catch-all' test with many checks to cover most of the ways things can fail
* There are new tests for splitting/rebuilding the css using the rr_split marker
* The prior 'dynamic stylesheet' route is now the main route for serializing a stylesheet; dynamic stylesheet were missed out in #1533 but that case is now covered with this PR

This PR was originally extracted from #1475 so the  initial motivation was to change the approach on stringifying <style> elements to do so in a single place.  This is also the motivating factor for always serializing <style> elements via the `_cssText` attribute rather than in it's childNodes; in #1475 we will be delaying populating `_cssText` for performance and instead recorrding them as assets.

Thanks for the detailed review to  Justin Halsall <Juice10@users.noreply.github.com> & Yun Feng <https://github.com/YunFeng0817>
This commit is contained in:
Eoghan Murray
2024-08-06 13:09:06 +01:00
committed by GitHub
parent 8837fe39aa
commit 5fbb904edb
19 changed files with 1595 additions and 387 deletions

View File

@@ -10,7 +10,7 @@ import {
createCache,
} from '../src/rebuild';
import { NodeType } from '../src/types';
import { createMirror, Mirror } from '../src/utils';
import { createMirror, Mirror, normalizeCssString } from '../src/utils';
const expect = _expect as unknown as {
<T = unknown>(actual: T): {
@@ -20,7 +20,7 @@ const expect = _expect as unknown as {
expect.extend({
toMatchCss: function (received: string, expected: string) {
const pass = normCss(received) === normCss(expected);
const pass = normalizeCssString(received) === normalizeCssString(expected);
const message: () => string = () =>
pass
? ''
@@ -32,10 +32,6 @@ expect.extend({
},
});
function normCss(cssText: string): string {
return cssText.replace(/[\s;]/g, '');
}
function getDuration(hrtime: [number, number]) {
const [seconds, nanoseconds] = hrtime;
return seconds * 1000 + nanoseconds / 1000000;