Skip to content

Commit

Permalink
fix: simplify and fix minimal repro
Browse files Browse the repository at this point in the history
  • Loading branch information
nolanlawson committed Nov 27, 2024
1 parent 7161ea4 commit a474f3b
Show file tree
Hide file tree
Showing 5 changed files with 14 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
// We should slowly drive down these test failures or at least document where we expect the failures
// TODO [#4815]: enable all SSR v2 tests
export const expectedFailures = new Set([
'adjacent-text-nodes/preserve-comments-off/deep/index.js',
'attribute-aria/dynamic/index.js',
'attribute-class/with-scoped-styles-only-in-child/dynamic/index.js',
'attribute-class/with-scoped-styles/dynamic/index.js',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
import { esTemplate, esTemplateWithYield } from '../estemplate';
import type { BlockStatement as EsBlockStatement, Statement as EsStatement } from 'estree';
import { esTemplateWithYield } from '../estemplate';
import type { BlockStatement as EsBlockStatement } from 'estree';
import type { TransformerContext } from './types';
import type { Node as IrNode } from '@lwc/template-compiler';

Expand All @@ -25,15 +25,6 @@ const isConcatenatedNode = (node: IrNode, cxt: TransformerContext) => {
}
};

export const isFirstConcatenatedNode = (cxt: TransformerContext) => {
const { prevSibling } = cxt;
if (!prevSibling) {
// we are the first sibling
return true;
}
return !isConcatenatedNode(prevSibling, cxt);
};

export const isLastConcatenatedNode = (cxt: TransformerContext) => {
const { nextSibling } = cxt;
if (!nextSibling) {
Expand All @@ -43,18 +34,15 @@ export const isLastConcatenatedNode = (cxt: TransformerContext) => {
return !isConcatenatedNode(nextSibling, cxt);
};

export const bDeclareTextContentBuffer = esTemplate`
// Deliberately using var so we can re-declare as many times as we want in the same scope
var textContentBuffer = '';
var didBufferTextContent = false;
`<EsStatement[]>;

export const bYieldTextContent = esTemplateWithYield`
if (didBufferTextContent) {
// We are at the end of a series of text nodes - flush to a concatenated string
// We only render the ZWJ if there were actually any dynamic text nodes rendered
// The ZWJ is just so hydration can compare the SSR'd dynamic text content against
// the CSR'd text content.
yield textContentBuffer === '' ? '\u200D' : htmlEscape(textContentBuffer);
// Reset
textContentBuffer = '';
didBufferTextContent = false;
}
`<EsBlockStatement>;
5 changes: 5 additions & 0 deletions packages/@lwc/ssr-compiler/src/compile-template/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ const bExportTemplate = esTemplate`
Cmp,
instance
) {
// Deliberately using let so we can mutate as many times as we want in the same scope.
// These should be scoped to the "tmpl" function however, to avoid conflicts with other templates.
let textContentBuffer = '';
let didBufferTextContent = false;
const isLightDom = Cmp.renderMode === 'light';
if (!isLightDom) {
yield \`<template shadowrootmode="open"\${Cmp.delegatesFocus ? ' shadowrootdelegatesfocus' : ''}>\`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,7 @@

import { builders as b } from 'estree-toolkit';

import {
bDeclareTextContentBuffer,
bYieldTextContent,
isFirstConcatenatedNode,
isLastConcatenatedNode,
} from '../adjacent-text-nodes';
import { bYieldTextContent, isLastConcatenatedNode } from '../adjacent-text-nodes';
import type { Comment as IrComment } from '@lwc/template-compiler';
import type { Transformer } from '../types';

Expand All @@ -22,15 +17,11 @@ export const Comment: Transformer<IrComment> = function Comment(node, cxt) {
} else {
cxt.import('htmlEscape');

const isFirstInSeries = isFirstConcatenatedNode(cxt);
const isLastInSeries = isLastConcatenatedNode(cxt);

// If preserve comments is off, we check if we should flush text content
// for adjacent text nodes. (If preserve comments is on, then the previous
// text node already flushed.)
return [
...(isFirstInSeries ? bDeclareTextContentBuffer() : []),
...(isLastInSeries ? [bYieldTextContent()] : []),
];
return [...(isLastInSeries ? [bYieldTextContent()] : [])];
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,7 @@ import { builders as b, is } from 'estree-toolkit';
import { esTemplateWithYield } from '../../estemplate';
import { expressionIrToEs } from '../expression';

import {
bDeclareTextContentBuffer,
bYieldTextContent,
isFirstConcatenatedNode,
isLastConcatenatedNode,
} from '../adjacent-text-nodes';
import { bYieldTextContent, isLastConcatenatedNode } from '../adjacent-text-nodes';
import type { Statement as EsStatement } from 'estree';
import type {
ComplexExpression as IrComplexExpression,
Expand All @@ -41,16 +36,11 @@ function isLiteral(node: IrLiteral | IrExpression | IrComplexExpression): node i
export const Text: Transformer<IrText> = function Text(node, cxt): EsStatement[] {
cxt.import('htmlEscape');

const isFirstInSeries = isFirstConcatenatedNode(cxt);
const isLastInSeries = isLastConcatenatedNode(cxt);

const valueToYield = isLiteral(node.value)
? b.literal(node.value.value)
: expressionIrToEs(node.value, cxt);

return [
...(isFirstInSeries ? bDeclareTextContentBuffer() : []),
...bBufferTextContent(valueToYield),
...(isLastInSeries ? [bYieldTextContent()] : []),
];
return [...bBufferTextContent(valueToYield), ...(isLastInSeries ? [bYieldTextContent()] : [])];
};

0 comments on commit a474f3b

Please sign in to comment.