feat: push codegen

This commit is contained in:
三咲智子 Kevin Deng 2023-12-01 22:12:19 +08:00
parent fe1780d9ff
commit 9843175c2c
No known key found for this signature in database
GPG Key ID: 69992F2250DFD93E
11 changed files with 352 additions and 130 deletions

View File

@ -69,7 +69,7 @@ export interface CodegenResult {
map?: RawSourceMap
}
enum NewlineType {
export enum NewlineType {
Start = 0,
End = -1,
None = -2,

View File

@ -21,7 +21,12 @@ export {
type StructuralDirectiveTransform,
type DirectiveTransform
} from './transform'
export { generate, type CodegenContext, type CodegenResult } from './codegen'
export {
generate,
NewlineType,
type CodegenContext,
type CodegenResult
} from './codegen'
export {
ErrorCodes,
errorMessages,

View File

@ -1,9 +1,8 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`compile > bindings 1`] = `
"import { template as _template, children as _children, createTextNode as _createTextNode, insert as _insert, effect as _effect, setText as _setText } from 'vue/vapor';
const t0 = _template('<div>count is <!>.</div>');
export function render(_ctx) {
"export function render(_ctx) {
const t0 = _template('<div>count is <!>.</div>');
const n0 = t0();
const {
0: [
@ -20,13 +19,13 @@ export function render(_ctx) {
});
return n0;
}
import { template as _template, children as _children, createTextNode as _createTextNode, insert as _insert, effect as _effect, setText as _setText } from 'vue/vapor';
"
`;
exports[`compile > directives > v-bind > simple expression 1`] = `
"import { template as _template, children as _children, effect as _effect, setAttr as _setAttr } from 'vue/vapor';
const t0 = _template('<div></div>');
export function render(_ctx) {
"export function render(_ctx) {
const t0 = _template('<div></div>');
const n0 = t0();
const {
0: [n1],
@ -36,13 +35,13 @@ export function render(_ctx) {
});
return n0;
}
import { template as _template, children as _children, effect as _effect, setAttr as _setAttr } from 'vue/vapor';
"
`;
exports[`compile > directives > v-html > no expression 1`] = `
"import { template as _template, children as _children, effect as _effect, setHtml as _setHtml } from 'vue/vapor';
const t0 = _template('<div></div>');
export function render(_ctx) {
"export function render(_ctx) {
const t0 = _template('<div></div>');
const n0 = t0();
const {
0: [n1],
@ -52,13 +51,13 @@ export function render(_ctx) {
});
return n0;
}
import { template as _template, children as _children, effect as _effect, setHtml as _setHtml } from 'vue/vapor';
"
`;
exports[`compile > directives > v-html > simple expression 1`] = `
"import { template as _template, children as _children, effect as _effect, setHtml as _setHtml } from 'vue/vapor';
const t0 = _template('<div></div>');
export function render(_ctx) {
"export function render(_ctx) {
const t0 = _template('<div></div>');
const n0 = t0();
const {
0: [n1],
@ -68,13 +67,13 @@ export function render(_ctx) {
});
return n0;
}
import { template as _template, children as _children, effect as _effect, setHtml as _setHtml } from 'vue/vapor';
"
`;
exports[`compile > directives > v-on > event modifier 1`] = `
"import { template as _template, children as _children, effect as _effect, withModifiers as _withModifiers, on as _on } from 'vue/vapor';
const t0 = _template('<div></div>');
export function render(_ctx) {
"export function render(_ctx) {
const t0 = _template('<div></div>');
const n0 = t0();
const {
0: [n1],
@ -84,13 +83,13 @@ export function render(_ctx) {
});
return n0;
}
import { template as _template, children as _children, effect as _effect, withModifiers as _withModifiers, on as _on } from 'vue/vapor';
"
`;
exports[`compile > directives > v-on > simple expression 1`] = `
"import { template as _template, children as _children, effect as _effect, on as _on } from 'vue/vapor';
const t0 = _template('<div></div>');
export function render(_ctx) {
"export function render(_ctx) {
const t0 = _template('<div></div>');
const n0 = t0();
const {
0: [n1],
@ -100,13 +99,13 @@ export function render(_ctx) {
});
return n0;
}
import { template as _template, children as _children, effect as _effect, on as _on } from 'vue/vapor';
"
`;
exports[`compile > directives > v-once > as root node 1`] = `
"import { template as _template, children as _children, setAttr as _setAttr } from 'vue/vapor';
const t0 = _template('<div></div>');
export function render(_ctx) {
"export function render(_ctx) {
const t0 = _template('<div></div>');
const n0 = t0();
const {
0: [n1],
@ -114,13 +113,13 @@ export function render(_ctx) {
_setAttr(n1, 'id', undefined, foo);
return n0;
}
import { template as _template, children as _children, setAttr as _setAttr } from 'vue/vapor';
"
`;
exports[`compile > directives > v-once > basic 1`] = `
"import { template as _template, children as _children, createTextNode as _createTextNode, setText as _setText, setAttr as _setAttr, prepend as _prepend } from 'vue/vapor';
const t0 = _template('<div> <span></span></div>');
export function render(_ctx) {
"export function render(_ctx) {
const t0 = _template('<div> <span></span></div>');
const n0 = t0();
const {
0: [
@ -136,23 +135,23 @@ export function render(_ctx) {
_prepend(n3, n1);
return n0;
}
import { template as _template, children as _children, createTextNode as _createTextNode, setText as _setText, setAttr as _setAttr, prepend as _prepend } from 'vue/vapor';
"
`;
exports[`compile > directives > v-pre > basic 1`] = `
"import { template as _template } from 'vue/vapor';
const t0 = _template('<div :id=\\"foo\\"><Comp></Comp>{{ bar }}</div>');
export function render(_ctx) {
"export function render(_ctx) {
const t0 = _template('<div :id=\\"foo\\"><Comp></Comp>{{ bar }}</div>');
const n0 = t0();
return n0;
}
import { template as _template } from 'vue/vapor';
"
`;
exports[`compile > directives > v-pre > self-closing v-pre 1`] = `
"import { template as _template, children as _children, createTextNode as _createTextNode, append as _append, effect as _effect, setAttr as _setAttr, setText as _setText } from 'vue/vapor';
const t0 = _template('<div></div><div><Comp></Comp></div>');
export function render(_ctx) {
"export function render(_ctx) {
const t0 = _template('<div></div><div><Comp></Comp></div>');
const n0 = t0();
const {
1: [n1],
@ -167,13 +166,13 @@ export function render(_ctx) {
});
return n0;
}
import { template as _template, children as _children, createTextNode as _createTextNode, append as _append, effect as _effect, setAttr as _setAttr, setText as _setText } from 'vue/vapor';
"
`;
exports[`compile > directives > v-pre > should not affect siblings after it 1`] = `
"import { template as _template, children as _children, createTextNode as _createTextNode, append as _append, effect as _effect, setAttr as _setAttr, setText as _setText } from 'vue/vapor';
const t0 = _template('<div :id=\\"foo\\"><Comp></Comp>{{ bar }}</div><div><Comp></Comp></div>');
export function render(_ctx) {
"export function render(_ctx) {
const t0 = _template('<div :id=\\"foo\\"><Comp></Comp>{{ bar }}</div><div><Comp></Comp></div>');
const n0 = t0();
const {
1: [n1],
@ -188,13 +187,13 @@ export function render(_ctx) {
});
return n0;
}
import { template as _template, children as _children, createTextNode as _createTextNode, append as _append, effect as _effect, setAttr as _setAttr, setText as _setText } from 'vue/vapor';
"
`;
exports[`compile > directives > v-text > no expression 1`] = `
"import { template as _template, children as _children, effect as _effect, setText as _setText } from 'vue/vapor';
const t0 = _template('<div></div>');
export function render(_ctx) {
"export function render(_ctx) {
const t0 = _template('<div></div>');
const n0 = t0();
const {
0: [n1],
@ -204,13 +203,13 @@ export function render(_ctx) {
});
return n0;
}
import { template as _template, children as _children, effect as _effect, setText as _setText } from 'vue/vapor';
"
`;
exports[`compile > directives > v-text > simple expression 1`] = `
"import { template as _template, children as _children, effect as _effect, setText as _setText } from 'vue/vapor';
const t0 = _template('<div></div>');
export function render(_ctx) {
"export function render(_ctx) {
const t0 = _template('<div></div>');
const n0 = t0();
const {
0: [n1],
@ -220,12 +219,12 @@ export function render(_ctx) {
});
return n0;
}
import { template as _template, children as _children, effect as _effect, setText as _setText } from 'vue/vapor';
"
`;
exports[`compile > dynamic root 1`] = `
"import { fragment as _fragment, createTextNode as _createTextNode, append as _append, effect as _effect, setText as _setText } from 'vue/vapor';
export function render(_ctx) {
"export function render(_ctx) {
const t0 = _fragment();
const n0 = t0();
const n1 = _createTextNode(1);
@ -239,13 +238,13 @@ export function render(_ctx) {
});
return n0;
}
import { fragment as _fragment, createTextNode as _createTextNode, append as _append, effect as _effect, setText as _setText } from 'vue/vapor';
"
`;
exports[`compile > dynamic root nodes and interpolation 1`] = `
"import { template as _template, children as _children, createTextNode as _createTextNode, prepend as _prepend, insert as _insert, append as _append, effect as _effect, on as _on, setAttr as _setAttr, setText as _setText } from 'vue/vapor';
const t0 = _template('<button>foo<!>foo</button>');
export function render(_ctx) {
"export function render(_ctx) {
const t0 = _template('<button>foo<!>foo</button>');
const n0 = t0();
const {
0: [
@ -272,23 +271,23 @@ export function render(_ctx) {
});
return n0;
}
import { template as _template, children as _children, createTextNode as _createTextNode, prepend as _prepend, insert as _insert, append as _append, effect as _effect, on as _on, setAttr as _setAttr, setText as _setText } from 'vue/vapor';
"
`;
exports[`compile > fragment 1`] = `
"import { template as _template } from 'vue/vapor';
const t0 = _template('<p></p><span></span><div></div>');
export function render(_ctx) {
"export function render(_ctx) {
const t0 = _template('<p></p><span></span><div></div>');
const n0 = t0();
return n0;
}
import { template as _template } from 'vue/vapor';
"
`;
exports[`compile > static + dynamic root 1`] = `
"import { template as _template, children as _children, createTextNode as _createTextNode, prepend as _prepend, insert as _insert, append as _append, effect as _effect, setText as _setText } from 'vue/vapor';
const t0 = _template('3<!>6<!>9');
export function render(_ctx) {
"export function render(_ctx) {
const t0 = _template('3<!>6<!>9');
const n0 = t0();
const {
1: [n9],
@ -332,15 +331,16 @@ export function render(_ctx) {
});
return n0;
}
import { template as _template, children as _children, createTextNode as _createTextNode, prepend as _prepend, insert as _insert, append as _append, effect as _effect, setText as _setText } from 'vue/vapor';
"
`;
exports[`compile > static template 1`] = `
"import { template as _template } from 'vue/vapor';
const t0 = _template('<div><p>hello</p><input><span></span></div>');
export function render(_ctx) {
"export function render(_ctx) {
const t0 = _template('<div><p>hello</p><input><span></span></div>');
const n0 = t0();
return n0;
}
import { template as _template } from 'vue/vapor';
"
`;

View File

@ -2,8 +2,6 @@
exports[`fixtures 1`] = `
"import { defineComponent as _defineComponent } from 'vue'
import { template as _template, children as _children, createTextNode as _createTextNode, append as _append, setText as _setText, effect as _effect, on as _on, setHtml as _setHtml } from 'vue/vapor'
const t0 = _template(\\"<h1 id=\\\\\\"title\\\\\\">Counter</h1><p>Count: </p><p>Double: </p><button>Increment</button><div></div><input type=\\\\\\"text\\\\\\"><p>once: </p><p>{{ count }}</p>\\")
import { ref, computed } from 'vue'
const html = '<b>HTML</b>'
@ -18,6 +16,7 @@ const increment = () => count.value++
return (() => {
const t0 = _template(\\"<h1 id=\\\\\\"title\\\\\\">Counter</h1><p>Count: </p><p>Double: </p><button>Increment</button><div></div><input type=\\\\\\"text\\\\\\"><p>once: </p><p>{{ count }}</p>\\")
const n0 = t0()
const { 1: [n2], 2: [n4], 3: [n5], 4: [n6], 6: [n8],} = _children(n0)
const n1 = _createTextNode(count.value)
@ -40,8 +39,9 @@ _effect(() => {
_setHtml(n6, undefined, html)
})
return n0
})()
import { template as _template, children as _children, createTextNode as _createTextNode, append as _append, setText as _setText, effect as _effect, on as _on, setHtml as _setHtml } from 'vue/vapor'
})();
}
})"

View File

@ -37,7 +37,8 @@
},
"homepage": "https://github.com/vuejs/core-vapor/tree/main/packages/compiler-vapor#readme",
"dependencies": {
"@vue/compiler-dom": "3.3.8",
"@vue/shared": "3.3.8",
"@vue/compiler-dom": "3.3.8"
"source-map-js": "^1.0.2"
}
}

View File

@ -1,27 +1,85 @@
import type { CodegenOptions, CodegenResult } from '@vue/compiler-dom'
import {
type CodegenOptions,
type CodegenResult,
type Position,
NewlineType,
advancePositionWithMutation,
locStub,
} from '@vue/compiler-dom'
import {
type DynamicChildren,
type RootIRNode,
IRNodeTypes,
OperationNode,
VaporHelper,
IRNode,
} from './ir'
import { SourceMapGenerator } from 'source-map-js'
// remove when stable
function checkNever(x: never): void {}
// @ts-expect-error
function checkNever(x: never): never {}
export interface CodegenContext
extends Omit<Required<CodegenOptions>, 'bindingMetadata' | 'inline'> {
source: string
code: string
line: number
column: number
offset: number
indentLevel: number
map?: SourceMapGenerator
push(code: string, newlineIndex?: NewlineType, node?: IRNode): void
indent(): void
deindent(withoutNewLine?: boolean): void
newline(): void
export interface CodegenContext {
options: CodegenOptions
helpers: Set<string>
vaporHelpers: Set<string>
helper(name: string): string
vaporHelper(name: string): string
}
function createCodegenContext(ir: RootIRNode, options: CodegenOptions) {
function createCodegenContext(
ir: RootIRNode,
{
mode = 'function',
prefixIdentifiers = mode === 'module',
sourceMap = false,
filename = `template.vue.html`,
scopeId = null,
optimizeImports = false,
runtimeGlobalName = `Vue`,
runtimeModuleName = `vue`,
ssrRuntimeModuleName = 'vue/server-renderer',
ssr = false,
isTS = false,
inSSR = false,
}: CodegenOptions,
) {
const { helpers, vaporHelpers } = ir
return {
options,
const context: CodegenContext = {
mode,
prefixIdentifiers,
sourceMap,
filename,
scopeId,
optimizeImports,
runtimeGlobalName,
runtimeModuleName,
ssrRuntimeModuleName,
ssr,
isTS,
inSSR,
source: ir.source,
code: ``,
column: 1,
line: 1,
offset: 0,
indentLevel: 0,
helpers,
vaporHelpers,
helper(name: string) {
@ -32,7 +90,104 @@ function createCodegenContext(ir: RootIRNode, options: CodegenOptions) {
vaporHelpers.add(name)
return `_${name}`
},
push(code, newlineIndex: NewlineType = NewlineType.None, node) {
context.code += code
if (!__BROWSER__ && context.map) {
if (node) {
// TODO
let name
// if (node.type === NodeTypes.SIMPLE_EXPRESSION && !node.isStatic) {
// const content = node.content.replace(/^_ctx\./, '')
// if (content !== node.content && isSimpleIdentifier(content)) {
// name = content
// }
// }
addMapping(node.loc.start, name)
}
if (newlineIndex === NewlineType.Unknown) {
// multiple newlines, full iteration
advancePositionWithMutation(context, code)
} else {
// fast paths
context.offset += code.length
if (newlineIndex === NewlineType.None) {
// no newlines; fast path to avoid newline detection
if (__TEST__ && code.includes('\n')) {
throw new Error(
`CodegenContext.push() called newlineIndex: none, but contains` +
`newlines: ${code.replace(/\n/g, '\\n')}`,
)
}
context.column += code.length
} else {
// single newline at known index
if (newlineIndex === NewlineType.End) {
newlineIndex = code.length - 1
}
if (
__TEST__ &&
(code.charAt(newlineIndex) !== '\n' ||
code.slice(0, newlineIndex).includes('\n') ||
code.slice(newlineIndex + 1).includes('\n'))
) {
throw new Error(
`CodegenContext.push() called with newlineIndex: ${newlineIndex} ` +
`but does not conform: ${code.replace(/\n/g, '\\n')}`,
)
}
context.line++
context.column = code.length - newlineIndex
}
}
if (node && node.loc !== locStub) {
addMapping(node.loc.end)
}
}
},
indent() {
newline(++context.indentLevel)
},
deindent(withoutNewLine = false) {
if (withoutNewLine) {
--context.indentLevel
} else {
newline(--context.indentLevel)
}
},
newline() {
newline(context.indentLevel)
},
}
function newline(n: number) {
context.push(`\n${` `.repeat(n)}`, NewlineType.Start)
}
function addMapping(loc: Position, name: string | null = null) {
// we use the private property to directly add the mapping
// because the addMapping() implementation in source-map-js has a bunch of
// unnecessary arg and validation checks that are pure overhead in our case.
const { _names, _mappings } = context.map!
if (name !== null && !_names.has(name)) _names.add(name)
_mappings.add({
originalLine: loc.line,
originalColumn: loc.column - 1, // source-map column is 0 based
generatedLine: context.line,
generatedColumn: context.column - 1,
source: filename,
// @ts-ignore it is possible to be null
name,
})
}
if (!__BROWSER__ && sourceMap) {
// lazy require source-map implementation, only in non-browser builds
context.map = new SourceMapGenerator()
context.map.setSourceContent(filename, context.source)
context.map._sources.add(filename)
}
return context
}
// IR -> JS codegen
@ -43,86 +198,112 @@ export function generate(
const ctx = createCodegenContext(ir, options)
const { vaporHelper, helpers, vaporHelpers } = ctx
let code = ''
let preamble = ''
const functionName = 'render'
const isSetupInlined = !!options.inline
if (isSetupInlined) {
ctx.push(`(() => {\n`, NewlineType.End)
} else {
ctx.push(`export function ${functionName}(_ctx) {\n`, NewlineType.End)
}
ir.template.forEach((template, i) => {
if (template.type === IRNodeTypes.TEMPLATE_FACTORY) {
preamble += `const t${i} = ${vaporHelper('template')}(${JSON.stringify(
template.template,
)})\n`
// TODO source map?
ctx.push(
`const t${i} = ${vaporHelper('template')}(${JSON.stringify(
template.template,
)})\n`,
NewlineType.End,
)
} else {
// fragment
code += `const t0 = ${vaporHelper('fragment')}()\n`
ctx.push(`const t0 = ${vaporHelper('fragment')}()\n`, NewlineType.End)
}
})
{
code += `const n${ir.dynamic.id} = t0()\n`
ctx.push(`const n${ir.dynamic.id} = t0()\n`, NewlineType.End, ir)
const children = genChildren(ir.dynamic.children)
if (children) {
code += `const ${children} = ${vaporHelper('children')}(n${
ir.dynamic.id
})\n`
ctx.push(
`const ${children} = ${vaporHelper('children')}(n${ir.dynamic.id})\n`,
NewlineType.End,
)
}
for (const operation of ir.operation) {
code += genOperation(operation, ctx)
genOperation(operation, ctx).forEach((args) => ctx.push(...args))
}
for (const [_expr, operations] of Object.entries(ir.effect)) {
let scope = `${vaporHelper('effect')}(() => {\n`
ctx.push(`${vaporHelper('effect')}(() => {\n`, NewlineType.End)
for (const operation of operations) {
scope += genOperation(operation, ctx)
genOperation(operation, ctx).forEach((args) => ctx.push(...args))
}
scope += '})\n'
code += scope
ctx.push('})\n', NewlineType.End)
}
// TODO multiple-template
// TODO return statement in IR
code += `return n${ir.dynamic.id}\n`
ctx.push(`return n${ir.dynamic.id}\n`, NewlineType.End)
}
if (isSetupInlined) {
ctx.push('})()')
} else {
ctx.push('}')
}
ctx.newline()
if (vaporHelpers.size)
// TODO: extract
preamble =
ctx.push(
`import { ${[...vaporHelpers]
.map((h) => `${h} as _${h}`)
.join(', ')} } from 'vue/vapor'\n` + preamble
.join(', ')} } from 'vue/vapor'\n`,
NewlineType.End,
)
if (helpers.size)
preamble =
ctx.push(
`import { ${[...helpers]
.map((h) => `${h} as _${h}`)
.join(', ')} } from 'vue'\n` + preamble
const functionName = 'render'
const isSetupInlined = !!options.inline
if (isSetupInlined) {
code = `(() => {\n${code}\n})();`
} else {
code = `${preamble}export function ${functionName}(_ctx) {\n${code}\n}`
}
.join(', ')} } from 'vue'\n`,
NewlineType.End,
)
return {
code,
code: ctx.code,
ast: ir as any,
preamble,
preamble: '',
map: ctx.map ? ctx.map.toJSON() : undefined,
}
}
function genOperation(oper: OperationNode, { vaporHelper }: CodegenContext) {
function genOperation(
oper: OperationNode,
{ vaporHelper }: CodegenContext,
): Parameters<CodegenContext['push']>[] {
// TODO: cache old value
switch (oper.type) {
case IRNodeTypes.SET_PROP: {
return `${vaporHelper('setAttr')}(n${oper.element}, ${JSON.stringify(
oper.name,
)}, undefined, ${oper.value})\n`
return [
[
`${vaporHelper('setAttr')}(n${oper.element}, ${JSON.stringify(
oper.name,
)}, undefined, ${oper.value})\n`,
NewlineType.End,
],
]
}
case IRNodeTypes.SET_TEXT: {
return `${vaporHelper('setText')}(n${oper.element}, undefined, ${
oper.value
})\n`
return [
[
`${vaporHelper('setText')}(n${oper.element}, undefined, ${
oper.value
})\n`,
NewlineType.End,
],
]
}
case IRNodeTypes.SET_EVENT: {
@ -132,43 +313,73 @@ function genOperation(oper: OperationNode, { vaporHelper }: CodegenContext) {
oper.modifiers,
)})`
}
return `${vaporHelper('on')}(n${oper.element}, ${JSON.stringify(
oper.name,
)}, ${value})\n`
return [
[
`${vaporHelper('on')}(n${oper.element}, ${JSON.stringify(
oper.name,
)}, ${value})\n`,
NewlineType.End,
],
]
}
case IRNodeTypes.SET_HTML: {
return `${vaporHelper('setHtml')}(n${oper.element}, undefined, ${
oper.value
})\n`
return [
[
`${vaporHelper('setHtml')}(n${oper.element}, undefined, ${
oper.value
})\n`,
NewlineType.End,
],
]
}
case IRNodeTypes.CREATE_TEXT_NODE: {
return `const n${oper.id} = ${vaporHelper('createTextNode')}(${
oper.value
})\n`
return [
[
`const n${oper.id} = ${vaporHelper('createTextNode')}(${
oper.value
})\n`,
NewlineType.End,
],
]
}
case IRNodeTypes.INSERT_NODE: {
const elements = ([] as number[]).concat(oper.element)
let element = elements.map((el) => `n${el}`).join(', ')
if (elements.length > 1) element = `[${element}]`
return `${vaporHelper('insert')}(${element}, n${
oper.parent
}${`, n${oper.anchor}`})\n`
return [
[
`${vaporHelper('insert')}(${element}, n${
oper.parent
}${`, n${oper.anchor}`})\n`,
NewlineType.End,
],
]
}
case IRNodeTypes.PREPEND_NODE: {
return `${vaporHelper('prepend')}(n${oper.parent}, ${oper.elements
.map((el) => `n${el}`)
.join(', ')})\n`
return [
[
`${vaporHelper('prepend')}(n${oper.parent}, ${oper.elements
.map((el) => `n${el}`)
.join(', ')})\n`,
NewlineType.End,
],
]
}
case IRNodeTypes.APPEND_NODE: {
return `${vaporHelper('append')}(n${oper.parent}, ${oper.elements
.map((el) => `n${el}`)
.join(', ')})\n`
return [
[
`${vaporHelper('append')}(n${oper.parent}, ${oper.elements
.map((el) => `n${el}`)
.join(', ')})\n`,
NewlineType.End,
],
]
}
default:
checkNever(oper)
return checkNever(oper)
}
}

View File

@ -26,6 +26,7 @@ export type VaporHelper = keyof typeof import('../../runtime-vapor/src')
export interface RootIRNode extends IRNode {
type: IRNodeTypes.ROOT
source: string
template: Array<TemplateFactoryIRNode | FragmentFactoryIRNode>
dynamic: DynamicInfo
// TODO multi-expression effect

View File

@ -175,6 +175,7 @@ export function transform(
const ir: RootIRNode = {
type: IRNodeTypes.ROOT,
source: root.source,
loc: root.loc,
template: [],
dynamic: {

View File

@ -1,7 +1,7 @@
import * as m from 'monaco-editor'
import { CompilerError, CompilerOptions } from '@vue/compiler-dom'
import { compile } from '@vue/compiler-vapor'
import { compile as ssrCompile } from '@vue/compiler-ssr'
import { CompilerError } from '@vue/compiler-dom'
import { compile, CompilerOptions } from '@vue/compiler-vapor'
// import { compile as ssrCompile } from '@vue/compiler-ssr'
import {
defaultOptions,
compilerOptions,
@ -74,7 +74,7 @@ window.init = () => {
console.clear()
try {
const errors: CompilerError[] = []
const compileFn = ssrMode.value ? ssrCompile : compile
const compileFn = /* ssrMode.value ? ssrCompile : */ compile
const start = performance.now()
const { code, ast, map } = compileFn(source, {
...compilerOptions,
@ -93,8 +93,8 @@ window.init = () => {
console.log(`AST: `, ast)
console.log(`Options: `, toRaw(compilerOptions))
lastSuccessfulCode = code + `\n\n// Check the console for the AST`
// lastSuccessfulMap = new SourceMapConsumer(map!)
// lastSuccessfulMap!.computeColumnSpans()
lastSuccessfulMap = new SourceMapConsumer(map!)
lastSuccessfulMap!.computeColumnSpans()
} catch (e: any) {
lastSuccessfulCode = `/* ERROR: ${e.message} (see console for more info) */`
console.error(e)

View File

@ -1,5 +1,5 @@
import { h, reactive, createApp, ref } from 'vue'
import { CompilerOptions } from '@vue/compiler-dom'
import { CompilerOptions } from '@vue/compiler-vapor'
import { BindingTypes } from '@vue/compiler-core'
export const ssrMode = ref(false)

View File

@ -274,6 +274,9 @@ importers:
'@vue/shared':
specifier: 3.3.8
version: 3.3.8
source-map-js:
specifier: ^1.0.2
version: 1.0.2
packages/dts-built-test:
dependencies: