提交 f0cfbbc4 编写于 作者: fxy060608's avatar fxy060608

wip(mp): add extend helper

上级 a29f277d
......@@ -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
}
......@@ -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
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册