From: 三咲智子 Kevin Deng Date: Fri, 1 Dec 2023 14:12:19 +0000 (+0800) Subject: feat: push codegen X-Git-Tag: v3.6.0-alpha.1~16^2~772 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9843175c2c5a1b2b1b7be2bc613970dfa47590c4;p=thirdparty%2Fvuejs%2Fcore.git feat: push codegen --- diff --git a/packages/compiler-core/src/codegen.ts b/packages/compiler-core/src/codegen.ts index 890ef9bfda..6ab8a99870 100644 --- a/packages/compiler-core/src/codegen.ts +++ b/packages/compiler-core/src/codegen.ts @@ -69,7 +69,7 @@ export interface CodegenResult { map?: RawSourceMap } -enum NewlineType { +export enum NewlineType { Start = 0, End = -1, None = -2, diff --git a/packages/compiler-core/src/index.ts b/packages/compiler-core/src/index.ts index 25a446e7f4..d4f2f3d12b 100644 --- a/packages/compiler-core/src/index.ts +++ b/packages/compiler-core/src/index.ts @@ -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, diff --git a/packages/compiler-vapor/__tests__/__snapshots__/compile.test.ts.snap b/packages/compiler-vapor/__tests__/__snapshots__/compile.test.ts.snap index 74932f20d8..22883caa72 100644 --- a/packages/compiler-vapor/__tests__/__snapshots__/compile.test.ts.snap +++ b/packages/compiler-vapor/__tests__/__snapshots__/compile.test.ts.snap @@ -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('
count is .
'); -export function render(_ctx) { +"export function render(_ctx) { + const t0 = _template('
count is .
'); 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('
'); -export function render(_ctx) { +"export function render(_ctx) { + const t0 = _template('
'); 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('
'); -export function render(_ctx) { +"export function render(_ctx) { + const t0 = _template('
'); 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('
'); -export function render(_ctx) { +"export function render(_ctx) { + const t0 = _template('
'); 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('
'); -export function render(_ctx) { +"export function render(_ctx) { + const t0 = _template('
'); 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('
'); -export function render(_ctx) { +"export function render(_ctx) { + const t0 = _template('
'); 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('
'); -export function render(_ctx) { +"export function render(_ctx) { + const t0 = _template('
'); 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('
'); -export function render(_ctx) { +"export function render(_ctx) { + const t0 = _template('
'); 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('
{{ bar }}
'); -export function render(_ctx) { +"export function render(_ctx) { + const t0 = _template('
{{ bar }}
'); 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('
'); -export function render(_ctx) { +"export function render(_ctx) { + const t0 = _template('
'); 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('
{{ bar }}
'); -export function render(_ctx) { +"export function render(_ctx) { + const t0 = _template('
{{ bar }}
'); 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('
'); -export function render(_ctx) { +"export function render(_ctx) { + const t0 = _template('
'); 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('
'); -export function render(_ctx) { +"export function render(_ctx) { + const t0 = _template('
'); 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(''); -export function render(_ctx) { +"export function render(_ctx) { + const t0 = _template(''); 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('

'); -export function render(_ctx) { +"export function render(_ctx) { + const t0 = _template('

'); 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('369'); -export function render(_ctx) { +"export function render(_ctx) { + const t0 = _template('369'); 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('

hello

'); -export function render(_ctx) { +"export function render(_ctx) { + const t0 = _template('

hello

'); const n0 = t0(); return n0; } +import { template as _template } from 'vue/vapor'; " `; diff --git a/packages/compiler-vapor/__tests__/__snapshots__/fixtures.test.ts.snap b/packages/compiler-vapor/__tests__/__snapshots__/fixtures.test.ts.snap index a4585b155d..99a1391458 100644 --- a/packages/compiler-vapor/__tests__/__snapshots__/fixtures.test.ts.snap +++ b/packages/compiler-vapor/__tests__/__snapshots__/fixtures.test.ts.snap @@ -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(\\"

Counter

Count:

Double:

once:

{{ count }}

\\") import { ref, computed } from 'vue' const html = 'HTML' @@ -18,6 +16,7 @@ const increment = () => count.value++ return (() => { +const t0 = _template(\\"

Counter

Count:

Double:

once:

{{ count }}

\\") 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' -})(); } })" diff --git a/packages/compiler-vapor/package.json b/packages/compiler-vapor/package.json index 1b63871509..2f57f3777f 100644 --- a/packages/compiler-vapor/package.json +++ b/packages/compiler-vapor/package.json @@ -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" } } diff --git a/packages/compiler-vapor/src/generate.ts b/packages/compiler-vapor/src/generate.ts index 9c90002045..5eff9a9404 100644 --- a/packages/compiler-vapor/src/generate.ts +++ b/packages/compiler-vapor/src/generate.ts @@ -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, '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 vaporHelpers: Set 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[] { // 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) } } diff --git a/packages/compiler-vapor/src/ir.ts b/packages/compiler-vapor/src/ir.ts index 8bfbf38636..de518c10c3 100644 --- a/packages/compiler-vapor/src/ir.ts +++ b/packages/compiler-vapor/src/ir.ts @@ -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 dynamic: DynamicInfo // TODO multi-expression effect diff --git a/packages/compiler-vapor/src/transform.ts b/packages/compiler-vapor/src/transform.ts index dcc781c2a7..df7e73d6d9 100644 --- a/packages/compiler-vapor/src/transform.ts +++ b/packages/compiler-vapor/src/transform.ts @@ -175,6 +175,7 @@ export function transform( const ir: RootIRNode = { type: IRNodeTypes.ROOT, + source: root.source, loc: root.loc, template: [], dynamic: { diff --git a/packages/template-explorer/src/index.ts b/packages/template-explorer/src/index.ts index 08258514ea..ca89addfb4 100644 --- a/packages/template-explorer/src/index.ts +++ b/packages/template-explorer/src/index.ts @@ -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) diff --git a/packages/template-explorer/src/options.ts b/packages/template-explorer/src/options.ts index 73e0a959f7..46c0d9263d 100644 --- a/packages/template-explorer/src/options.ts +++ b/packages/template-explorer/src/options.ts @@ -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) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4a1779f4e4..82ca550ff8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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: