fix: static + dynamic root nodes
This commit is contained in:
parent
ac686033aa
commit
45858c085d
|
@ -5,7 +5,7 @@ exports[`comile > bindings 1`] = `
|
|||
import { template, children, insert, setText } from 'vue/vapor';
|
||||
const t0 = template(\`<div>count is <!>.</div>\`);
|
||||
export function render() {
|
||||
const root = t0();
|
||||
const n0 = t0();
|
||||
const {
|
||||
0: [
|
||||
n1,
|
||||
|
@ -19,7 +19,7 @@ export function render() {
|
|||
watchEffect(() => {
|
||||
setText(n2, undefined, count.value);
|
||||
});
|
||||
return root;
|
||||
return n0;
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
@ -29,14 +29,14 @@ exports[`comile > directives > v-bind > simple expression 1`] = `
|
|||
import { template, children, setAttr } from 'vue/vapor';
|
||||
const t0 = template(\`<div></div>\`);
|
||||
export function render() {
|
||||
const root = t0();
|
||||
const n0 = t0();
|
||||
const {
|
||||
0: [n1],
|
||||
} = children(root);
|
||||
watchEffect(() => {
|
||||
setAttr(n1, 'id', undefined, id.value);
|
||||
});
|
||||
return root;
|
||||
return n0;
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
@ -46,14 +46,14 @@ exports[`comile > directives > v-html > no expression 1`] = `
|
|||
import { template, children, setHtml } from 'vue/vapor';
|
||||
const t0 = template(\`<div></div>\`);
|
||||
export function render() {
|
||||
const root = t0();
|
||||
const n0 = t0();
|
||||
const {
|
||||
0: [n1],
|
||||
} = children(root);
|
||||
watchEffect(() => {
|
||||
setHtml(n1, undefined, '');
|
||||
});
|
||||
return root;
|
||||
return n0;
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
@ -63,14 +63,14 @@ exports[`comile > directives > v-html > simple expression 1`] = `
|
|||
import { template, children, setHtml } from 'vue/vapor';
|
||||
const t0 = template(\`<div></div>\`);
|
||||
export function render() {
|
||||
const root = t0();
|
||||
const n0 = t0();
|
||||
const {
|
||||
0: [n1],
|
||||
} = children(root);
|
||||
watchEffect(() => {
|
||||
setHtml(n1, undefined, code.value);
|
||||
});
|
||||
return root;
|
||||
return n0;
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
@ -80,14 +80,14 @@ exports[`comile > directives > v-on > simple expression 1`] = `
|
|||
import { template, children, on } from 'vue/vapor';
|
||||
const t0 = template(\`<div></div>\`);
|
||||
export function render() {
|
||||
const root = t0();
|
||||
const n0 = t0();
|
||||
const {
|
||||
0: [n1],
|
||||
} = children(root);
|
||||
watchEffect(() => {
|
||||
on(n1, 'click', handleClick);
|
||||
});
|
||||
return root;
|
||||
return n0;
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
@ -97,14 +97,14 @@ exports[`comile > directives > v-once > as root node 1`] = `
|
|||
import { template, children, setAttr } from 'vue/vapor';
|
||||
const t0 = template(\`<div></div>\`);
|
||||
export function render() {
|
||||
const root = t0();
|
||||
const n0 = t0();
|
||||
const {
|
||||
0: [n1],
|
||||
} = children(root);
|
||||
watchEffect(() => {
|
||||
setAttr(n1, 'id', undefined, foo);
|
||||
});
|
||||
return root;
|
||||
return n0;
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
@ -113,7 +113,7 @@ exports[`comile > directives > v-once > basic 1`] = `
|
|||
"import { template, children, insert, setText, setAttr } from 'vue/vapor';
|
||||
const t0 = template(\`<div> <span></span></div>\`);
|
||||
export function render() {
|
||||
const root = t0();
|
||||
const n0 = t0();
|
||||
const {
|
||||
0: [
|
||||
n1,
|
||||
|
@ -126,7 +126,7 @@ export function render() {
|
|||
insert(n2, n1, 0 /* InsertPosition.FIRST */);
|
||||
setText(n2, undefined, msg.value);
|
||||
setAttr(n3, 'class', undefined, clz.value);
|
||||
return root;
|
||||
return n0;
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
@ -136,14 +136,14 @@ exports[`comile > directives > v-text > no expression 1`] = `
|
|||
import { template, children, setText } from 'vue/vapor';
|
||||
const t0 = template(\`<div></div>\`);
|
||||
export function render() {
|
||||
const root = t0();
|
||||
const n0 = t0();
|
||||
const {
|
||||
0: [n1],
|
||||
} = children(root);
|
||||
watchEffect(() => {
|
||||
setText(n1, undefined, '');
|
||||
});
|
||||
return root;
|
||||
return n0;
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
@ -153,42 +153,55 @@ exports[`comile > directives > v-text > simple expression 1`] = `
|
|||
import { template, children, setText } from 'vue/vapor';
|
||||
const t0 = template(\`<div></div>\`);
|
||||
export function render() {
|
||||
const root = t0();
|
||||
const n0 = t0();
|
||||
const {
|
||||
0: [n1],
|
||||
} = children(root);
|
||||
watchEffect(() => {
|
||||
setText(n1, undefined, str.value);
|
||||
});
|
||||
return root;
|
||||
return n0;
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`comile > fragment 1`] = `
|
||||
"import { template, children } from 'vue/vapor';
|
||||
"import { template } from 'vue/vapor';
|
||||
const t0 = template(\`<p></p><span></span><div></div>\`);
|
||||
export function render() {
|
||||
const root = t0();
|
||||
const {
|
||||
0: [n1],
|
||||
1: [n2],
|
||||
2: [n3],
|
||||
} = children(root);
|
||||
return root;
|
||||
const n0 = t0();
|
||||
return n0;
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`comile > static + dynamic root 1`] = `
|
||||
"import { watchEffect } from 'vue';
|
||||
import { template, insert, setText } from 'vue/vapor';
|
||||
const t0 = template(\`2\`);
|
||||
export function render() {
|
||||
const n0 = t0();
|
||||
const n1 = document.createTextNode(1);
|
||||
insert(n1, n0, 0 /* InsertPosition.FIRST */);
|
||||
const n2 = document.createTextNode(3);
|
||||
insert(n2, n0);
|
||||
watchEffect(() => {
|
||||
setText(n1, undefined, 1);
|
||||
});
|
||||
watchEffect(() => {
|
||||
setText(n2, undefined, 3);
|
||||
});
|
||||
return n0;
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`comile > static template 1`] = `
|
||||
"import { template, children } from 'vue/vapor';
|
||||
"import { template } from 'vue/vapor';
|
||||
const t0 = template(\`<div><p>hello</p><input><span></span></div>\`);
|
||||
export function render() {
|
||||
const root = t0();
|
||||
const {
|
||||
0: [n1],
|
||||
} = children(root);
|
||||
return root;
|
||||
const n0 = t0();
|
||||
return n0;
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
|
|
@ -19,28 +19,28 @@ const increment = () => count.value++
|
|||
|
||||
|
||||
return (() => {
|
||||
const root = t0()
|
||||
const { 0: [n1], 1: [n2], 2: [n4], 3: [n6], 4: [n7], 5: [n8], 6: [n9], 7: [n11],} = children(root)
|
||||
const n3 = document.createTextNode(count.value)
|
||||
insert(n3, n2)
|
||||
const n5 = document.createTextNode(double.value)
|
||||
insert(n5, n4)
|
||||
const n10 = document.createTextNode(count.value)
|
||||
insert(n10, n9)
|
||||
setText(n10, undefined, count.value)
|
||||
const n0 = t0()
|
||||
const { 1: [n1], 2: [n3], 3: [n5], 4: [n6], 6: [n7],} = children(root)
|
||||
const n2 = document.createTextNode(count.value)
|
||||
insert(n2, n1)
|
||||
const n4 = document.createTextNode(double.value)
|
||||
insert(n4, n3)
|
||||
const n8 = document.createTextNode(count.value)
|
||||
insert(n8, n7)
|
||||
setText(n8, undefined, count.value)
|
||||
watchEffect(() => {
|
||||
setText(n3, undefined, count.value)
|
||||
setText(n2, undefined, count.value)
|
||||
})
|
||||
watchEffect(() => {
|
||||
setText(n5, undefined, double.value)
|
||||
setText(n4, undefined, double.value)
|
||||
})
|
||||
watchEffect(() => {
|
||||
on(n6, \\"click\\", increment)
|
||||
on(n5, \\"click\\", increment)
|
||||
})
|
||||
watchEffect(() => {
|
||||
setHtml(n7, undefined, html)
|
||||
setHtml(n6, undefined, html)
|
||||
})
|
||||
return root
|
||||
return n0
|
||||
|
||||
})();
|
||||
}
|
||||
|
|
|
@ -28,6 +28,11 @@ describe('comile', () => {
|
|||
expect(code).matchSnapshot()
|
||||
})
|
||||
|
||||
test('static + dynamic root', async () => {
|
||||
const code = await compile(`{{ 1 }}2{{ 3 }}`)
|
||||
expect(code).matchSnapshot()
|
||||
})
|
||||
|
||||
test('fragment', async () => {
|
||||
const code = await compile(`<p/><span/><div/>`)
|
||||
expect(code).matchSnapshot()
|
||||
|
|
|
@ -28,9 +28,11 @@ export function generate(
|
|||
}
|
||||
|
||||
{
|
||||
code += `const root = t0()\n`
|
||||
code += `const {${genChildren(ir.children.children)}} = children(root)\n`
|
||||
vaporHelpers.add('children')
|
||||
code += `const n${ir.children.id} = t0()\n`
|
||||
if (Object.keys(ir.children.children).length) {
|
||||
code += `const {${genChildren(ir.children.children)}} = children(root)\n`
|
||||
vaporHelpers.add('children')
|
||||
}
|
||||
|
||||
for (const operation of ir.operation) {
|
||||
code += genOperation(operation)
|
||||
|
@ -46,7 +48,7 @@ export function generate(
|
|||
code += scope
|
||||
}
|
||||
// TODO multiple-template
|
||||
code += `return root\n`
|
||||
code += `return n${ir.children.id}\n`
|
||||
}
|
||||
|
||||
if (vaporHelpers.size)
|
||||
|
|
|
@ -83,6 +83,7 @@ export type OperationNode =
|
|||
export interface DynamicChild {
|
||||
id: number | null
|
||||
store: boolean
|
||||
ghost: boolean
|
||||
children: DynamicChildren
|
||||
}
|
||||
export type DynamicChildren = Record<number, DynamicChild>
|
||||
|
|
|
@ -29,8 +29,10 @@ export interface TransformContext<T extends Node = Node> {
|
|||
store: boolean
|
||||
ghost: boolean
|
||||
once: boolean
|
||||
id: number | null
|
||||
|
||||
getElementId(): number
|
||||
getId(): number
|
||||
incraseId(): number
|
||||
registerTemplate(): number
|
||||
registerEffect(expr: string, operation: OperationNode): void
|
||||
registerOpration(...oprations: OperationNode[]): void
|
||||
|
@ -42,7 +44,7 @@ function createRootContext(
|
|||
node: RootNode,
|
||||
options: TransformOptions,
|
||||
): TransformContext<RootNode> {
|
||||
let i = 0
|
||||
let globalId = 0
|
||||
const { effect, operation: operation, helpers, vaporHelpers } = ir
|
||||
|
||||
const ctx: TransformContext<RootNode> = {
|
||||
|
@ -56,7 +58,12 @@ function createRootContext(
|
|||
ghost: false,
|
||||
once: false,
|
||||
|
||||
getElementId: () => i++,
|
||||
id: null,
|
||||
incraseId: () => globalId++,
|
||||
getId() {
|
||||
if (this.id !== null) return this.id
|
||||
return (this.id = this.incraseId())
|
||||
},
|
||||
registerEffect(expr, operation) {
|
||||
if (!effect[expr]) effect[expr] = []
|
||||
effect[expr].push(operation)
|
||||
|
@ -94,15 +101,11 @@ function createContext<T extends TemplateChildNode>(
|
|||
parent: TransformContext,
|
||||
index: number,
|
||||
): TransformContext<T> {
|
||||
let id: number | undefined
|
||||
const getElementId = () => {
|
||||
if (id !== undefined) return id
|
||||
return (id = parent.root.getElementId())
|
||||
}
|
||||
const children = {}
|
||||
|
||||
const ctx: TransformContext<T> = {
|
||||
...parent,
|
||||
id: null,
|
||||
node,
|
||||
parent,
|
||||
index,
|
||||
|
@ -112,8 +115,6 @@ function createContext<T extends TemplateChildNode>(
|
|||
set template(t) {
|
||||
parent.template = t
|
||||
},
|
||||
getElementId,
|
||||
|
||||
children,
|
||||
store: false,
|
||||
registerEffect(expr, operation) {
|
||||
|
@ -142,13 +143,14 @@ export function transform(
|
|||
vaporHelpers: new Set([]),
|
||||
}
|
||||
const ctx = createRootContext(ir, root, options)
|
||||
const rootId = ctx.getElementId()
|
||||
const rootId = ctx.getId()
|
||||
|
||||
// TODO: transform presets, see packages/compiler-core/src/transforms
|
||||
transformChildren(ctx, true)
|
||||
ir.children = {
|
||||
store: true,
|
||||
id: rootId,
|
||||
store: true,
|
||||
ghost: false,
|
||||
children: ctx.children,
|
||||
}
|
||||
|
||||
|
@ -172,13 +174,6 @@ function transformChildren(
|
|||
const isFirst = i === 0
|
||||
const isLast = i === children.length - 1
|
||||
|
||||
// TODO: multiple root elements
|
||||
if (root) {
|
||||
child.store = true
|
||||
// generate id for root element early
|
||||
child.getElementId()
|
||||
}
|
||||
|
||||
switch (node.type) {
|
||||
case 1 satisfies NodeTypes.ELEMENT: {
|
||||
transformElement(child as TransformContext<ElementNode>)
|
||||
|
@ -215,9 +210,10 @@ function transformChildren(
|
|||
|
||||
if (Object.keys(child.children).length > 0 || child.store)
|
||||
ctx.children[index] = {
|
||||
id: child.store ? child.getElementId() : null,
|
||||
id: child.store ? child.getId() : null,
|
||||
store: child.store,
|
||||
children: child.children,
|
||||
ghost: child.ghost,
|
||||
}
|
||||
|
||||
if (!child.ghost) index++
|
||||
|
@ -252,7 +248,7 @@ function transformInterpolation(
|
|||
const expr = processExpression(ctx, node.content)!
|
||||
|
||||
const parent = ctx.parent!
|
||||
const parentId = parent.getElementId()
|
||||
const parentId = parent.getId()
|
||||
parent.store = true
|
||||
|
||||
if (isFirst && isLast) {
|
||||
|
@ -267,12 +263,12 @@ function transformInterpolation(
|
|||
let anchor: number | 'first' | 'last'
|
||||
|
||||
if (!isFirst && !isLast) {
|
||||
id = ctx.root.getElementId()
|
||||
anchor = ctx.getElementId()
|
||||
id = ctx.incraseId()
|
||||
anchor = ctx.getId()
|
||||
ctx.template += '<!>'
|
||||
ctx.store = true
|
||||
} else {
|
||||
id = ctx.getElementId()
|
||||
id = ctx.getId()
|
||||
ctx.ghost = true
|
||||
anchor = isFirst ? 'first' : 'last'
|
||||
}
|
||||
|
@ -342,7 +338,7 @@ function transformProp(
|
|||
ctx.registerEffect(expr, {
|
||||
type: IRNodeTypes.SET_PROP,
|
||||
loc: node.loc,
|
||||
element: ctx.getElementId(),
|
||||
element: ctx.getId(),
|
||||
name: node.arg.content,
|
||||
value: expr,
|
||||
})
|
||||
|
@ -366,7 +362,7 @@ function transformProp(
|
|||
ctx.registerEffect(expr, {
|
||||
type: IRNodeTypes.SET_EVENT,
|
||||
loc: node.loc,
|
||||
element: ctx.getElementId(),
|
||||
element: ctx.getId(),
|
||||
name: node.arg.content,
|
||||
value: expr,
|
||||
})
|
||||
|
@ -377,7 +373,7 @@ function transformProp(
|
|||
ctx.registerEffect(value, {
|
||||
type: IRNodeTypes.SET_HTML,
|
||||
loc: node.loc,
|
||||
element: ctx.getElementId(),
|
||||
element: ctx.getId(),
|
||||
value,
|
||||
})
|
||||
break
|
||||
|
@ -387,7 +383,7 @@ function transformProp(
|
|||
ctx.registerEffect(value, {
|
||||
type: IRNodeTypes.SET_TEXT,
|
||||
loc: node.loc,
|
||||
element: ctx.getElementId(),
|
||||
element: ctx.getId(),
|
||||
value,
|
||||
})
|
||||
break
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<template>{{ '1' }}2{{ '3' }}</template>
|
Loading…
Reference in New Issue