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

fix: rewrite SSR client-side hydration #6067

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/declarations/stencil-private.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1435,6 +1435,12 @@ export interface RenderNode extends HostElement {
*/
['s-nr']?: RenderNode;

/**
* Original Order:
* During SSR; a number representing the order of a slotted node
*/
['s-oo']?: number;

/**
* Scope Id
*/
Expand Down
31 changes: 24 additions & 7 deletions src/mock-doc/serialize-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export function serializeNodeToHtml(elm: Node | MockNode, serializationOptions:
? Array.from((elm as MockDocument).body.childNodes)
: opts.outerHtml
? [elm]
: Array.from(elm.childNodes as NodeList);
: Array.from(getChildNodes(elm));

for (let i = 0, ii = children.length; i < ii; i++) {
const child = children[i];
Expand Down Expand Up @@ -130,7 +130,10 @@ function* streamToHtml(
* ToDo(https://github.com/ionic-team/stencil/issues/4111): the shadow root class is `#document-fragment`
* and has no mode attribute. We should consider adding a mode attribute.
*/
if (tag === 'template') {
if (
tag === 'template' &&
(!(node as Element).getAttribute || !(node as Element).getAttribute('shadowrootmode'))
) {
const mode = ` shadowrootmode="open"`;
yield mode;
output.currentLineWidth += mode.length;
Expand Down Expand Up @@ -242,12 +245,13 @@ function* streamToHtml(
yield* streamToHtml(shadowRoot, opts, output);
output.indent = output.indent - (opts.indentSpaces ?? 0);

const childNodes = getChildNodes(node);
if (
opts.newLines &&
(node.childNodes.length === 0 ||
(node.childNodes.length === 1 &&
node.childNodes[0].nodeType === NODE_TYPES.TEXT_NODE &&
node.childNodes[0].nodeValue?.trim() === ''))
(childNodes.length === 0 ||
(childNodes.length === 1 &&
childNodes[0].nodeType === NODE_TYPES.TEXT_NODE &&
childNodes[0].nodeValue?.trim() === ''))
) {
yield '\n';
output.currentLineWidth = 0;
Expand All @@ -262,7 +266,9 @@ function* streamToHtml(
if (opts.excludeTagContent == null || opts.excludeTagContent.includes(tagName) === false) {
const tag = tagName === shadowRootTag ? 'template' : tagName;
const childNodes =
tagName === 'template' ? ((node as any as HTMLTemplateElement).content.childNodes as any) : node.childNodes;
tagName === 'template'
? ((node as any as HTMLTemplateElement).content.childNodes as any)
: getChildNodes(node);
const childNodeLength = childNodes.length;

if (childNodeLength > 0) {
Expand Down Expand Up @@ -525,6 +531,17 @@ function isWithinWhitespaceSensitive(node: Node | MockNode) {
return false;
}

/**
* Normalizes the `childNodes` of a node due to if `experimentalSlotFixes` is enabled, `
* childNodes` will only return 'slotted' / lightDOM nodes
*
* @param node to return `childNodes` from
* @returns a node list of child nodes
*/
function getChildNodes(node: Node | MockNode) {
return ((node as any).__childNodes || node.childNodes) as NodeList;
}

// TODO(STENCIL-1299): Audit this list, remove unsupported/deprecated elements
/*@__PURE__*/ export const NON_ESCAPABLE_CONTENT = new Set([
'STYLE',
Expand Down
Loading
Loading