Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Sampo Kivistö committed May 27, 2022
1 parent a7d652d commit ae9f6bf
Show file tree
Hide file tree
Showing 8 changed files with 236 additions and 100 deletions.
2 changes: 1 addition & 1 deletion packages/inferno-test-utils/__tests__/testUtils.spec.jsx
Expand Up @@ -28,7 +28,7 @@ import {
scryVNodesWithType
} from 'inferno-test-utils';

const VNodeKeys = ['children', 'childFlags', 'className', 'dom', 'flags', 'isValidated', 'key', 'ref', 'props', 'type'].sort();
const VNodeKeys = ['children', 'childFlags', 'className', 'dom', 'flags', 'isValidated', 'key', 'ref', 'props', 'type', 'template'].sort();

const createDOMElement = (tagName) => document.createElement(tagName);

Expand Down
79 changes: 79 additions & 0 deletions packages/inferno/__tests__/patching.spec.jsx
Expand Up @@ -766,4 +766,83 @@ describe('patching routine', () => {
});
});
});

describe('static vNode $IsStatic', function () {
it('Should be able to swap between static nodes', function () {
function Swapper(props) {
if (props.swap) {
return <svg $IsStatic><path d="x" $IsStatic></path></svg>;
}

return <svg $IsStatic><circle $IsStatic></circle><path $IsStatic></path></svg>
}


// mount first
render(<Swapper swap={true} />, container);

expect(container.innerHTML).toEqual("<svg><path d=\"x\"></path></svg>");

// mount second
render(<Swapper swap={false} />, container);

expect(container.innerHTML).toEqual("<svg><circle></circle><path></path></svg>");

// patch second -> first
render(<Swapper swap={true} />, container);

expect(container.innerHTML).toEqual("<svg><path d=\"x\"></path></svg>");

// patch first -> second
render(<Swapper swap={false} />, container);

expect(container.innerHTML).toEqual("<svg><circle></circle><path></path></svg>");
});

it('Should be able to swap between static nodes when normalization is needed', function () {
function Swapper(props) {
if (props.swap) {
return <svg><path d="x" $IsStatic></path>{props.swap2 ? <g $IsStatic></g> : null}</svg>;
}

return (
<svg>
{props.swap2 ? <g $IsStatic></g> : null}
<circle $IsStatic></circle>
<path $IsStatic></path>
{props.swap2 ? <g $IsStatic></g> : null}
</svg>
);
}


// mount first
render(<Swapper swap={true} />, container);

expect(container.innerHTML).toEqual("<svg><path d=\"x\"></path></svg>");

// mount second
render(<Swapper swap={false} />, container);

expect(container.innerHTML).toEqual("<svg><circle></circle><path></path></svg>");

// patch second -> first
render(<Swapper swap={true} />, container);

expect(container.innerHTML).toEqual("<svg><path d=\"x\"></path></svg>");

// patch first -> second
render(<Swapper swap={false} />, container);

expect(container.innerHTML).toEqual("<svg><circle></circle><path></path></svg>");

render(<Swapper swap={true} swap2={true} />, container);

expect(container.innerHTML).toEqual("<svg><path d=\"x\"></path><g></g></svg>");

render(<Swapper swap={false} swap2={true} />, container);

expect(container.innerHTML).toEqual("<svg><g></g><circle></circle><path></path><g></g></svg>");
});
});
});
104 changes: 84 additions & 20 deletions packages/inferno/src/DOM/mounting.ts
Expand Up @@ -25,12 +25,15 @@ export function mount(
nextNode: Element | null,
lifecycle: Function[],
animations: AnimationQueues
): void {
): VNode {
const flags = (vNode.flags |= VNodeFlags.InUse);
const isStatic = (flags & VNodeFlags.IsStatic) > 0;

if ((flags & VNodeFlags.IsStatic) > 0 && vNode.template && vNode.template.dom) {
vNode.dom = documentCloneDom(vNode.template.dom)
} if (flags & VNodeFlags.Element) {
if (isStatic && vNode.staticDom) {
mountTemplate(vNode, parentDOM, nextNode);
return vNode;
}
if (flags & VNodeFlags.Element) {
mountElement(vNode, parentDOM, context, isSVG, nextNode, lifecycle, animations);
} else if (flags & VNodeFlags.ComponentClass) {
mountClassComponent(vNode, parentDOM, context, isSVG, nextNode, lifecycle, animations);
Expand All @@ -54,9 +57,66 @@ export function mount(
throwError(`mount() expects a valid VNode, instead it received an object with the type "${typeof vNode}".`);
}
}
if ((flags & VNodeFlags.IsStatic) > 0 && !vNode.template) {
vNode.template = vNode;
if (isStatic && !vNode.staticDom) {
vNode.staticDom = vNode.dom;
}

return vNode;
}

export function mountSingle(
vNode: VNode,
parentDOM: Element | null,
parentVNode: VNode,
context: Object,
isSVG: boolean,
nextNode: Element | null,
lifecycle: Function[],
animations: AnimationQueues
): VNode {
if (vNode.flags & VNodeFlags.InUse) {
vNode = parentVNode.children = directClone(vNode);
}

return mount(
vNode,
parentDOM,
context,
isSVG,
nextNode,
lifecycle,
animations
)
}

export function mountArrayRef(
vNode: VNode,
parentDOM: Element | null,
context: Object,
isSVG: boolean,
nextNode: Element | null,
lifecycle: Function[],
animations: AnimationQueues,
nextArrayRef: VNode[],
nextArrayIndex: number
): VNode {
const isInUse = (vNode.flags & VNodeFlags.InUse) > 0;

const newNextNode = mount(
vNode,
parentDOM,
context,
isSVG,
nextNode,
lifecycle,
animations
);

if (isInUse) {
nextArrayRef[nextArrayIndex] = newNextNode;
}

return newNextNode;
}

function mountPortal(vNode, context, parentDOM: Element | null, nextNode: Element | null, lifecycle: Function[], animations: AnimationQueues) {
Expand Down Expand Up @@ -95,6 +155,18 @@ export function mountText(vNode: VNode, parentDOM: Element | null, nextNode: Ele
}
}

function mountTemplate(
vNode: VNode,
parentDOM: Element | null,
nextNode: Element | null
) {
const dom = (vNode.dom = documentCloneDom(vNode.staticDom as Element));

if (!isNull(parentDOM)) {
insertOrAppend(parentDOM, dom, nextNode);
}
}

export function mountElement(
vNode: VNode,
parentDOM: Element | null,
Expand All @@ -109,7 +181,7 @@ export function mountElement(
const className = vNode.className;
const childFlags = vNode.childFlags;
const dom = (vNode.dom = documentCreateElement(vNode.type, (isSVG = isSVG || (flags & VNodeFlags.SvgElement) > 0)));
let children = vNode.children;
const children = vNode.children;

if (!isNullOrUndef(className) && className !== '') {
if (isSVG) {
Expand All @@ -129,10 +201,7 @@ export function mountElement(
const childrenIsSVG = isSVG && vNode.type !== 'foreignObject';

if (childFlags === ChildFlags.HasVNodeChildren) {
if ((children as VNode).flags & VNodeFlags.InUse) {
vNode.children = children = directClone(children as VNode);
}
mount(children as VNode, dom, context, childrenIsSVG, null, lifecycle, animations);
mountSingle(children as VNode, dom, vNode, context, childrenIsSVG, null, lifecycle, animations);
} else if (childFlags === ChildFlags.HasKeyedChildren || childFlags === ChildFlags.HasNonKeyedChildren) {
mountArrayChildren(children, dom, context, childrenIsSVG, null, lifecycle, animations);
}
Expand Down Expand Up @@ -162,14 +231,9 @@ export function mountArrayChildren(
nextNode: Element | null,
lifecycle: Function[],
animations: AnimationQueues
): void {
) {
for (let i = 0; i < children.length; ++i) {
let child = children[i];

if (child.flags & VNodeFlags.InUse) {
children[i] = child = directClone(child);
}
mount(child, dom, context, isSVG, nextNode, lifecycle, animations);
mountArrayRef(children[i], dom, context, isSVG, nextNode, lifecycle, animations, children, i);
}
}

Expand All @@ -189,7 +253,7 @@ export function mountClassComponent(
if (isFunction(instance.componentDidAppear)) {
childAnimations = new AnimationQueues();
}
mount(instance.$LI, parentDOM, instance.$CX, isSVG, nextNode, lifecycle, childAnimations);
instance.$LI = mount(instance.$LI, parentDOM, instance.$CX, isSVG, nextNode, lifecycle, childAnimations);
mountClassComponentCallbacks(vNode.ref, instance, lifecycle, animations);
}

Expand All @@ -209,7 +273,7 @@ export function mountFunctionalComponent(
childAnimations = new AnimationQueues();
}

mount((vNode.children = normalizeRoot(renderFunctionalComponent(vNode, context))), parentDOM, context, isSVG, nextNode, lifecycle, childAnimations);
vNode.children = mount(normalizeRoot(renderFunctionalComponent(vNode, context)), parentDOM, context, isSVG, nextNode, lifecycle, childAnimations);
mountFunctionalComponentCallbacks(vNode, lifecycle, animations);
}

Expand Down

0 comments on commit ae9f6bf

Please sign in to comment.