diff --git a/packages/uni-mp-compiler/src/compile.ts b/packages/uni-mp-compiler/src/compile.ts index 07203eb7e8e05cd3053d3dec7eee878c49a5d5dc..e145ee775b99abcdc83f4c3e27e4a4e7bce761da 100644 --- a/packages/uni-mp-compiler/src/compile.ts +++ b/packages/uni-mp-compiler/src/compile.ts @@ -3,13 +3,8 @@ import { baseParse } from '@vue/compiler-core' import { isString, extend } from '@vue/shared' import { hash, parseFilterNames } from '@dcloudio/uni-cli-shared' import { generate } from './codegen' -import { CompilerOptions } from './options' -import { - DirectiveTransform, - NodeTransform, - transform, - TransformContext, -} from './transform' +import { CodegenRootNode, CompilerOptions } from './options' +import { DirectiveTransform, NodeTransform, transform } from './transform' import { transformExpression } from './transforms/transformExpression' import { transformIdentifier } from './transforms/transformIdentifier' import { transformIf } from './transforms/vIf' @@ -19,27 +14,6 @@ import { transformOn } from './transforms/vOn' import { transformElement } from './transforms/transformElement' import { transformBind } from './transforms/vBind' import { transformComponent } from './transforms/transformComponent' -import { - ArrowFunctionExpression, - BlockStatement, - CallExpression, - callExpression, - ConditionalExpression, - identifier, - isCallExpression, - isConditionalExpression, - isIdentifier, - isObjectExpression, - isObjectProperty, - isSpreadElement, - objectExpression, - ObjectExpression, - ObjectProperty, - ReturnStatement, - SpreadElement, -} from '@babel/types' -import { createObjectExpression } from './ast' -import { EXTEND } from './runtimeHelpers' export type TransformPreset = [ NodeTransform[], @@ -68,7 +42,9 @@ export function getBaseTransformPreset({ export function baseCompile(template: string, options: CompilerOptions = {}) { const prefixIdentifiers = options.prefixIdentifiers === true || options.mode === 'module' - const ast = isString(template) ? baseParse(template, options) : template + const ast = ( + isString(template) ? baseParse(template, options) : template + ) as CodegenRootNode const [nodeTransforms, directiveTransforms] = getBaseTransformPreset({ prefixIdentifiers, skipTransformIdentifier: options.skipTransformIdentifier === true, @@ -100,7 +76,6 @@ export function baseCompile(template: string, options: CompilerOptions = {}) { const result = extend( generate( extend(ast, { - renderData: createRenderDataExpr(context.scope.properties, context), bindingComponents: context.bindingComponents, }), options @@ -140,114 +115,3 @@ function parseFilters(lang: string, filename: string) { } return [] } - -function createRenderDataExpr( - properties: (ObjectProperty | SpreadElement)[], - context: TransformContext -) { - const objExpr = createObjectExpression(properties) - if (context.renderDataSpread || !hasSpreadElement(objExpr)) { - return objExpr - } - return transformObjectSpreadExpr(objExpr, context) -} - -function hasSpreadElement(expr: ObjectExpression): boolean { - return expr.properties.some((prop) => { - if (isSpreadElement(prop)) { - return true - } else { - const objExpr = parseReturnObjExpr(prop as ObjectProperty) - if (objExpr) { - return hasSpreadElement(objExpr) - } - } - }) -} - -function parseReturnObjExpr(prop: ObjectProperty) { - if ( - isObjectProperty(prop) && - isCallExpression(prop.value) && - isIdentifier(prop.value.callee) && - prop.value.callee.name === '_vFor' - ) { - // 目前硬编码 - return ( - ( - (prop.value.arguments[1] as ArrowFunctionExpression) - .body as BlockStatement - ).body[0] as ReturnStatement - ).argument as ObjectExpression - } -} - -function transformObjectPropertyExpr( - prop: ObjectProperty, - context: TransformContext -) { - // vFor - const objExpr = parseReturnObjExpr(prop) - if (objExpr) { - if (hasSpreadElement(objExpr)) { - ;( - ( - ( - (prop.value as CallExpression) - .arguments[1] as ArrowFunctionExpression - ).body as BlockStatement - ).body[0] as ReturnStatement - ).argument = transformObjectSpreadExpr(objExpr, context) - } - } - return prop -} - -function transformObjectSpreadExpr( - objExpr: ObjectExpression, - context: TransformContext -) { - const properties = objExpr.properties as (ObjectProperty | SpreadElement)[] - const args: (ObjectExpression | ConditionalExpression)[] = [] - let objExprProperties: ObjectProperty[] = [] - properties.forEach((prop) => { - if (isObjectProperty(prop)) { - objExprProperties.push(transformObjectPropertyExpr(prop, context)) - } else { - if (objExprProperties.length) { - args.push(objectExpression(objExprProperties)) - } - args.push( - transformConditionalExpression( - prop.argument as ConditionalExpression, - context - ) - ) - objExprProperties = [] - } - }) - if (objExprProperties.length) { - args.push(objectExpression(objExprProperties)) - } - if (args.length === 1) { - return args[0] as ObjectExpression - } - return callExpression(identifier(context.helperString(EXTEND)), args) -} -function transformConditionalExpression( - expr: ConditionalExpression, - context: TransformContext -) { - const { consequent, alternate } = expr - if (isObjectExpression(consequent) && hasSpreadElement(consequent)) { - expr.consequent = transformObjectSpreadExpr(consequent, context) - } - if (isObjectExpression(alternate)) { - if (hasSpreadElement(alternate)) { - expr.alternate = transformObjectSpreadExpr(alternate, context) - } - } else if (isConditionalExpression(alternate)) { - transformConditionalExpression(alternate, context) - } - return expr -} diff --git a/packages/uni-mp-compiler/src/transform.ts b/packages/uni-mp-compiler/src/transform.ts index 75eea49aa3f15d4673b86e450bdb7f641b0cc2e5..f5dea9e8c9c397ef0e2f839308731643c8a41315 100644 --- a/packages/uni-mp-compiler/src/transform.ts +++ b/packages/uni-mp-compiler/src/transform.ts @@ -8,6 +8,25 @@ import { camelize, } from '@vue/shared' +import { + ConditionalExpression, + isObjectExpression, + isConditionalExpression, + identifier, + callExpression, + ObjectExpression, + objectExpression, + ObjectProperty, + SpreadElement, + isObjectProperty, + BlockStatement, + ArrowFunctionExpression, + ReturnStatement, + isCallExpression, + isIdentifier, + isSpreadElement, + CallExpression, +} from '@babel/types' import { DirectiveNode, ElementNode, @@ -28,6 +47,7 @@ import { } from '@vue/compiler-core' import IdentifierGenerator from './identifier' import { + CodegenRootNode, CodegenRootScope, CodegenScope, CodegenVForScope, @@ -36,6 +56,8 @@ import { CodegenVIfScopeInit, TransformOptions, } from './options' +import { EXTEND } from './runtimeHelpers' +import { createObjectExpression } from './ast' export interface ImportItem { exp: string | ExpressionNode @@ -119,9 +141,10 @@ export function isVForScope(scope: CodegenScope): scope is CodegenVForScope { return !!(scope as CodegenVForScope).source } -export function transform(root: RootNode, options: TransformOptions) { +export function transform(root: CodegenRootNode, options: TransformOptions) { const context = createTransformContext(root, options) traverseNode(root, context) + root.renderData = createRenderDataExpr(context.scope.properties, context) // finalize meta information root.helpers = [...context.helpers.keys()] root.components = [...context.components] @@ -475,3 +498,114 @@ export function createStructuralDirectiveTransform( } } } + +function createRenderDataExpr( + properties: (ObjectProperty | SpreadElement)[], + context: TransformContext +) { + const objExpr = createObjectExpression(properties) + if (context.renderDataSpread || !hasSpreadElement(objExpr)) { + return objExpr + } + return transformObjectSpreadExpr(objExpr, context) +} + +function hasSpreadElement(expr: ObjectExpression): boolean { + return expr.properties.some((prop) => { + if (isSpreadElement(prop)) { + return true + } else { + const objExpr = parseReturnObjExpr(prop as ObjectProperty) + if (objExpr) { + return hasSpreadElement(objExpr) + } + } + }) +} + +function parseReturnObjExpr(prop: ObjectProperty) { + if ( + isObjectProperty(prop) && + isCallExpression(prop.value) && + isIdentifier(prop.value.callee) && + prop.value.callee.name === '_vFor' + ) { + // 目前硬编码 + return ( + ( + (prop.value.arguments[1] as ArrowFunctionExpression) + .body as BlockStatement + ).body[0] as ReturnStatement + ).argument as ObjectExpression + } +} + +function transformObjectPropertyExpr( + prop: ObjectProperty, + context: TransformContext +) { + // vFor + const objExpr = parseReturnObjExpr(prop) + if (objExpr) { + if (hasSpreadElement(objExpr)) { + ;( + ( + ( + (prop.value as CallExpression) + .arguments[1] as ArrowFunctionExpression + ).body as BlockStatement + ).body[0] as ReturnStatement + ).argument = transformObjectSpreadExpr(objExpr, context) + } + } + return prop +} + +function transformObjectSpreadExpr( + objExpr: ObjectExpression, + context: TransformContext +) { + const properties = objExpr.properties as (ObjectProperty | SpreadElement)[] + const args: (ObjectExpression | ConditionalExpression)[] = [] + let objExprProperties: ObjectProperty[] = [] + properties.forEach((prop) => { + if (isObjectProperty(prop)) { + objExprProperties.push(transformObjectPropertyExpr(prop, context)) + } else { + if (objExprProperties.length) { + args.push(objectExpression(objExprProperties)) + } + args.push( + transformConditionalExpression( + prop.argument as ConditionalExpression, + context + ) + ) + objExprProperties = [] + } + }) + if (objExprProperties.length) { + args.push(objectExpression(objExprProperties)) + } + if (args.length === 1) { + return args[0] as ObjectExpression + } + return callExpression(identifier(context.helperString(EXTEND)), args) +} +function transformConditionalExpression( + expr: ConditionalExpression, + context: TransformContext +) { + const { consequent, alternate } = expr + if (isObjectExpression(consequent) && hasSpreadElement(consequent)) { + expr.consequent = transformObjectSpreadExpr(consequent, context) + } + if (isObjectExpression(alternate)) { + if (hasSpreadElement(alternate)) { + expr.alternate = transformObjectSpreadExpr(alternate, context) + } + } else if (isConditionalExpression(alternate)) { + transformConditionalExpression(alternate, context) + } + return expr +}