diff --git a/packages/compiler-core/src/codegen.ts b/packages/compiler-core/src/codegen.ts index 31fe534ca78..0ab78993d41 100644 --- a/packages/compiler-core/src/codegen.ts +++ b/packages/compiler-core/src/codegen.ts @@ -60,12 +60,16 @@ type CodegenNode = TemplateChildNode | JSChildNode | SSRCodegenNode export interface CodegenResult { code: string + preamble: string ast: RootNode map?: RawSourceMap } export interface CodegenContext - extends Omit, 'bindingMetadata'> { + extends Omit< + Required, + 'bindingMetadata' | 'inline' | 'inlinePropsIdentifier' + > { source: string code: string line: number @@ -199,12 +203,18 @@ export function generate( const hasHelpers = ast.helpers.length > 0 const useWithBlock = !prefixIdentifiers && mode !== 'module' const genScopeId = !__BROWSER__ && scopeId != null && mode === 'module' + const isSetupInlined = !!options.inline // preambles + // in setup() inline mode, the preamble is generated in a sub context + // and returned separately. + const preambleContext = isSetupInlined + ? createCodegenContext(ast, options) + : context if (!__BROWSER__ && mode === 'module') { - genModulePreamble(ast, context, genScopeId) + genModulePreamble(ast, preambleContext, genScopeId, isSetupInlined) } else { - genFunctionPreamble(ast, context) + genFunctionPreamble(ast, preambleContext) } // binding optimizations @@ -213,10 +223,17 @@ export function generate( : `` // enter render function if (!ssr) { - if (genScopeId) { - push(`const render = ${PURE_ANNOTATION}_withId(`) + if (isSetupInlined) { + if (genScopeId) { + push(`${PURE_ANNOTATION}_withId(`) + } + push(`() => {`) + } else { + if (genScopeId) { + push(`const render = ${PURE_ANNOTATION}_withId(`) + } + push(`function render(_ctx, _cache${optimizeSources}) {`) } - push(`function render(_ctx, _cache${optimizeSources}) {`) } else { if (genScopeId) { push(`const ssrRender = ${PURE_ANNOTATION}_withId(`) @@ -290,6 +307,7 @@ export function generate( return { ast, code: context.code, + preamble: isSetupInlined ? preambleContext.code : ``, // SourceMapGenerator does have toJSON() method but it's not in the types map: context.map ? (context.map as any).toJSON() : undefined } @@ -356,7 +374,8 @@ function genFunctionPreamble(ast: RootNode, context: CodegenContext) { function genModulePreamble( ast: RootNode, context: CodegenContext, - genScopeId: boolean + genScopeId: boolean, + inline?: boolean ) { const { push, @@ -423,7 +442,10 @@ function genModulePreamble( genHoists(ast.hoists, context) newline() - push(`export `) + + if (!inline) { + push(`export `) + } } function genAssets( diff --git a/packages/compiler-core/src/options.ts b/packages/compiler-core/src/options.ts index 22d8a086b2f..b0af0cefabe 100644 --- a/packages/compiler-core/src/options.ts +++ b/packages/compiler-core/src/options.ts @@ -65,7 +65,39 @@ export interface BindingMetadata { [key: string]: 'data' | 'props' | 'setup' | 'options' } -export interface TransformOptions { +interface SharedTransformCodegenOptions { + /** + * Transform expressions like {{ foo }} to `_ctx.foo`. + * If this option is false, the generated code will be wrapped in a + * `with (this) { ... }` block. + * - This is force-enabled in module mode, since modules are by default strict + * and cannot use `with` + * @default mode === 'module' + */ + prefixIdentifiers?: boolean + /** + * Generate SSR-optimized render functions instead. + * The resulting function must be attached to the component via the + * `ssrRender` option instead of `render`. + */ + ssr?: boolean + /** + * Optional binding metadata analyzed from script - used to optimize + * binding access when `prefixIdentifiers` is enabled. + */ + bindingMetadata?: BindingMetadata + /** + * Compile the function for inlining inside setup(). + * This allows the function to directly access setup() local bindings. + */ + inline?: boolean + /** + * Identifier for props in setup() inline mode. + */ + inlinePropsIdentifier?: string +} + +export interface TransformOptions extends SharedTransformCodegenOptions { /** * An array of node transforms to be applied to every AST node. */ @@ -128,26 +160,15 @@ export interface TransformOptions { * SFC scoped styles ID */ scopeId?: string | null - /** - * Generate SSR-optimized render functions instead. - * The resulting function must be attached to the component via the - * `ssrRender` option instead of `render`. - */ - ssr?: boolean /** * SFC `