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:
@@ -162,22 +162,27 @@ describe('style elements', () => {
|
||||
it('should serialize all rules of stylesheet when the sheet has a single child node', () => {
|
||||
const styleEl = render(`<style>body { color: red; }</style>`);
|
||||
styleEl.sheet?.insertRule('section { color: blue; }');
|
||||
expect(serializeNode(styleEl.childNodes[0])).toMatchObject({
|
||||
isStyle: true,
|
||||
expect(serializeNode(styleEl)).toMatchObject({
|
||||
rootId: undefined,
|
||||
textContent: 'section {color: blue;}body {color: red;}',
|
||||
type: 3,
|
||||
attributes: {
|
||||
_cssText: 'section {color: blue;}body {color: red;}',
|
||||
},
|
||||
type: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it('should serialize individual text nodes on stylesheets with multiple child nodes', () => {
|
||||
it('should serialize all rules on stylesheets with mix of insertion type', () => {
|
||||
const styleEl = render(`<style>body { color: red; }</style>`);
|
||||
styleEl.sheet?.insertRule('section.lost { color: unseeable; }'); // browser throws this away after append
|
||||
styleEl.append(document.createTextNode('section { color: blue; }'));
|
||||
expect(serializeNode(styleEl.childNodes[1])).toMatchObject({
|
||||
isStyle: true,
|
||||
styleEl.sheet?.insertRule('section.working { color: pink; }');
|
||||
expect(serializeNode(styleEl)).toMatchObject({
|
||||
rootId: undefined,
|
||||
textContent: 'section { color: blue; }',
|
||||
type: 3,
|
||||
attributes: {
|
||||
_cssText:
|
||||
'section.working {color: pink;}body {color: red;}/* rr_split */section {color: blue;}',
|
||||
},
|
||||
type: 2,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user