Fix adapt css with split (#1600)
Fix for #1575 where postcss was raising an exception * adapt the entire CSS as a whole in one pass with postcss, rather than adapting each split part separately * break up the postcss output again and assign to individual text nodes (kind of inverse of splitCssText at record side) * impose an upper bound of 30 iterations on the substring searches to preempt possible pathological behavior * add tests to demonstrate the scenario and prevent regression More technical details: * Fix algorithm; checks against `ix_end` within loop were incorrect when `ix_start` was bigger than zero. * Fix that length check against wrong array was causing 'should record style mutations with multiple child nodes and replay them correctly' test to fail. Note on last point: I haven't looked into things more deeply than that the test was complaining about missing .length after `replayer.pause(1000);`
This commit is contained in:
@@ -102,15 +102,44 @@ export function applyCssSplits(
|
||||
// unexpected: remerge the last two so that we don't discard any css
|
||||
cssTextSplits.splice(-2, 2, cssTextSplits.slice(-2).join(''));
|
||||
}
|
||||
let adaptedCss = '';
|
||||
if (hackCss) {
|
||||
adaptedCss = adaptCssForReplay(cssTextSplits.join(''), cache);
|
||||
}
|
||||
let startIndex = 0;
|
||||
for (let i = 0; i < childTextNodes.length; i++) {
|
||||
if (i === cssTextSplits.length) {
|
||||
break;
|
||||
}
|
||||
const childTextNode = childTextNodes[i];
|
||||
const cssTextSection = cssTextSplits[i];
|
||||
if (childTextNode && cssTextSection) {
|
||||
// id will be assigned when these child nodes are
|
||||
// iterated over in buildNodeWithSN
|
||||
childTextNode.textContent = hackCss
|
||||
? adaptCssForReplay(cssTextSection, cache)
|
||||
: cssTextSection;
|
||||
if (!hackCss) {
|
||||
childTextNode.textContent = cssTextSplits[i];
|
||||
} else if (i < cssTextSplits.length - 1) {
|
||||
let endIndex = startIndex;
|
||||
let endSearch = cssTextSplits[i + 1].length;
|
||||
|
||||
// don't do hundreds of searches, in case a mismatch
|
||||
// is caused close to start of string
|
||||
endSearch = Math.min(endSearch, 30);
|
||||
|
||||
let found = false;
|
||||
for (; endSearch > 2; endSearch--) {
|
||||
const searchBit = cssTextSplits[i + 1].substring(0, endSearch);
|
||||
const searchIndex = adaptedCss.substring(startIndex).indexOf(searchBit);
|
||||
found = searchIndex !== -1;
|
||||
if (found) {
|
||||
endIndex += searchIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// something went wrong, put a similar sized chunk in the right place
|
||||
endIndex += cssTextSplits[i].length;
|
||||
}
|
||||
childTextNode.textContent = adaptedCss.substring(startIndex, endIndex);
|
||||
startIndex = endIndex;
|
||||
} else {
|
||||
childTextNode.textContent = adaptedCss.substring(startIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user