From 128621d6a056d4f73e8fc642c5571da4311742b6 Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 12 Nov 2020 16:11:14 -0500 Subject: [PATCH] wip: further optimize bindings --- packages/compiler-core/src/options.ts | 10 +- .../src/transforms/hoistStatic.ts | 10 +- .../src/transforms/transformElement.ts | 14 +-- .../src/transforms/transformExpression.ts | 17 ++- packages/compiler-core/src/transforms/vOn.ts | 13 ++- packages/compiler-sfc/src/compileScript.ts | 102 ++++++++++++------ packages/compiler-sfc/src/genCssVars.ts | 2 +- 7 files changed, 110 insertions(+), 58 deletions(-) diff --git a/packages/compiler-core/src/options.ts b/packages/compiler-core/src/options.ts index 05c3d2cd0..2a6b79c16 100644 --- a/packages/compiler-core/src/options.ts +++ b/packages/compiler-core/src/options.ts @@ -61,8 +61,16 @@ export type HoistTransform = ( parent: ParentNode ) => void +export const enum BindingTypes { + DATA = 'data', + PROPS = 'props', + SETUP = 'setup', + CONST = 'const', + OPTIONS = 'options' +} + export interface BindingMetadata { - [key: string]: 'data' | 'props' | 'setup' | 'options' | 'setup-raw' + [key: string]: BindingTypes } interface SharedTransformCodegenOptions { diff --git a/packages/compiler-core/src/transforms/hoistStatic.ts b/packages/compiler-core/src/transforms/hoistStatic.ts index 240f9bacf..a4131c6d6 100644 --- a/packages/compiler-core/src/transforms/hoistStatic.ts +++ b/packages/compiler-core/src/transforms/hoistStatic.ts @@ -207,11 +207,11 @@ export function getStaticType( case NodeTypes.TEXT_CALL: return getStaticType(node.content, resultCache) case NodeTypes.SIMPLE_EXPRESSION: - return node.isConstant - ? node.isRuntimeConstant - ? StaticType.HAS_RUNTIME_CONSTANT - : StaticType.FULL_STATIC - : StaticType.NOT_STATIC + return node.isRuntimeConstant + ? StaticType.HAS_RUNTIME_CONSTANT + : node.isConstant + ? StaticType.FULL_STATIC + : StaticType.NOT_STATIC case NodeTypes.COMPOUND_EXPRESSION: let returnType = StaticType.FULL_STATIC for (let i = 0; i < node.children.length; i++) { diff --git a/packages/compiler-core/src/transforms/transformElement.ts b/packages/compiler-core/src/transforms/transformElement.ts index 937e3a71d..f1e0fd2b1 100644 --- a/packages/compiler-core/src/transforms/transformElement.ts +++ b/packages/compiler-core/src/transforms/transformElement.ts @@ -54,7 +54,7 @@ import { } from '../utils' import { buildSlots } from './vSlot' import { getStaticType } from './hoistStatic' -import { BindingMetadata } from '../options' +import { BindingTypes } from '../options' // some directive transforms (e.g. v-model) may return a symbol for runtime // import, which should be used instead of a resolveDirective call. @@ -253,7 +253,7 @@ export function resolveComponentType( // 3. user component (from setup bindings) const bindings = context.bindingMetadata if (bindings !== EMPTY_OBJ) { - const checkType = (type: BindingMetadata[string]) => { + const checkType = (type: BindingTypes) => { let resolvedTag = tag if ( bindings[resolvedTag] === type || @@ -263,17 +263,17 @@ export function resolveComponentType( return resolvedTag } } - const tagFromSetup = checkType('setup') + const tagFromSetup = checkType(BindingTypes.SETUP) if (tagFromSetup) { return context.inline ? // setup scope bindings may be refs so they need to be unrefed `${context.helperString(UNREF)}(${tagFromSetup})` : `$setup[${JSON.stringify(tagFromSetup)}]` } - const tagFromImport = checkType('setup-raw') - if (tagFromImport) { - // raw setup bindings (e.g. imports) can be used as-is - return tagFromImport + const tagFromConst = checkType(BindingTypes.CONST) + if (tagFromConst) { + // constant setup bindings (e.g. imports) can be used as-is + return tagFromConst } } diff --git a/packages/compiler-core/src/transforms/transformExpression.ts b/packages/compiler-core/src/transforms/transformExpression.ts index 87c6c65b8..57039c05a 100644 --- a/packages/compiler-core/src/transforms/transformExpression.ts +++ b/packages/compiler-core/src/transforms/transformExpression.ts @@ -29,6 +29,7 @@ import { validateBrowserExpression } from '../validateExpression' import { parse } from '@babel/parser' import { walk } from 'estree-walker' import { UNREF } from '../runtimeHelpers' +import { BindingTypes } from '../options' const isLiteralWhitelisted = /*#__PURE__*/ makeMap('true,false,null,this') @@ -99,18 +100,26 @@ export function processExpression( } const { inline, bindingMetadata } = context + + // const bindings exposed from setup - we know they never change + if (inline && bindingMetadata[node.content] === BindingTypes.CONST) { + node.isRuntimeConstant = true + return node + } + const prefix = (raw: string) => { const type = hasOwn(bindingMetadata, raw) && bindingMetadata[raw] + if (type === BindingTypes.CONST) { + return raw + } if (inline) { // setup inline mode - if (type === 'setup') { + if (type === BindingTypes.SETUP) { return `${context.helperString(UNREF)}(${raw})` - } else if (type === 'props') { + } else if (type === BindingTypes.PROPS) { // use __props which is generated by compileScript so in ts mode // it gets correct type return `__props.${raw}` - } else if (type === 'setup-raw') { - return raw } } // fallback to normal diff --git a/packages/compiler-core/src/transforms/vOn.ts b/packages/compiler-core/src/transforms/vOn.ts index 441e6fd16..546f669e2 100644 --- a/packages/compiler-core/src/transforms/vOn.ts +++ b/packages/compiler-core/src/transforms/vOn.ts @@ -70,7 +70,7 @@ export const transformOn: DirectiveTransform = ( if (exp && !exp.content.trim()) { exp = undefined } - let isCacheable: boolean = context.cacheHandlers && !exp + let shouldCache: boolean = context.cacheHandlers && !exp if (exp) { const isMemberExp = isMemberExpression(exp.content) const isInlineStatement = !(isMemberExp || fnExpRE.test(exp.content)) @@ -83,8 +83,11 @@ export const transformOn: DirectiveTransform = ( isInlineStatement && context.removeIdentifiers(`$event`) // with scope analysis, the function is hoistable if it has no reference // to scope variables. - isCacheable = + shouldCache = context.cacheHandlers && + // runtime constants don't need to be cached + // (this is analyzed by compileScript in SFC