Skip to content

Commit

Permalink
fix(transformer): 当循环类型为数组、基本类型时可能会改变源数据的数据结构
Browse files Browse the repository at this point in the history
  • Loading branch information
yuche committed Sep 11, 2018
1 parent ecff4a6 commit fd59a09
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 12 deletions.
7 changes: 5 additions & 2 deletions packages/taro-transformer-wx/__tests__/loop.spec.ts
Expand Up @@ -996,14 +996,14 @@ describe('loop', () => {
...baseOptions,
isRoot: true,
code: buildComponent(`
const array = [{ list: [{}] }]
const array = [{ list: [] }]
const b1 = true
const b2 = true
const b3 = true
const b4 = true
return (
<View>{array.map(arr => {
return <CoverView>
return <CoverView key={String(arr)}>
{arr.list.map(item => {
return b1 ? <ScrollView className={\`test\`} >
{b2 ? <Map /> : null}
Expand All @@ -1019,6 +1019,9 @@ describe('loop', () => {
`, `handleClick = () => ({})`)
})

console.log(code)
console.log(template)

const instance = evalClass(ast)
removeShadowData(instance.state)
expect(Object.keys(instance.state).length).toBe(5)
Expand Down
2 changes: 2 additions & 0 deletions packages/taro-transformer-wx/src/constant.ts
Expand Up @@ -88,6 +88,8 @@ export const INTERNAL_INLINE_STYLE = 'internal_inline_style'

export const LOOP_STATE = '$loopState'

export const LOOP_ORIGINAL = '$$original'

export const LOOP_CALLEE = '$anonymousCallee_'

export const SPECIAL_COMPONENT_PROPS = new Map<string, Set<string>>()
Expand Down
48 changes: 39 additions & 9 deletions packages/taro-transformer-wx/src/render.ts
Expand Up @@ -19,13 +19,13 @@ import {
findMethodName,
isVarName
} from './utils'
import { difference } from 'lodash'
import { difference, set as setObject, cloneDeep } from 'lodash'
import {
setJSXAttr,
buildBlockElement,
parseJSXElement
} from './jsx'
import { DEFAULT_Component_SET, MAP_CALL_ITERATOR, LOOP_STATE, LOOP_CALLEE, THIRD_PARTY_COMPONENTS } from './constant'
import { DEFAULT_Component_SET, MAP_CALL_ITERATOR, LOOP_STATE, LOOP_CALLEE, THIRD_PARTY_COMPONENTS, LOOP_ORIGINAL } from './constant'
import generate from 'babel-generator'
const template = require('babel-template')

Expand Down Expand Up @@ -95,6 +95,7 @@ export class RenderParser {
private topLevelIfStatement = new Set<NodePath<t.IfStatement>>()
private usedEvents = new Set<string>()
private customComponentNames: Set<string>
private originalCallee = new Map<t.Expression, t.JSXElement>()

private renderPath: NodePath<t.ClassMethod>
private methods: ClassMethodsMap
Expand Down Expand Up @@ -316,6 +317,8 @@ export class RenderParser {
}
}
setJSXAttr(jsxElementPath.node, 'wx:for', t.jSXExpressionContainer(ary))
this.originalCallee.set(ary, jsxElementPath.node)

const [func] = callExpr.node.arguments
if (
t.isFunctionExpression(func) ||
Expand Down Expand Up @@ -865,26 +868,55 @@ export class RenderParser {
}
stateToBeAssign.forEach(s => this.loopRefIdentifiers.set(s, callee))
const properties = Array.from(stateToBeAssign).map(state => t.objectProperty(t.identifier(state), t.identifier(state)))
const self = this
component.traverse({
Identifier (path) {
const name = path.node.name
const parent = path.parent
if (stateToBeAssign.has(name) && path.isReferencedIdentifier()) {
path.replaceWith(
t.memberExpression(
t.identifier(item.name),
path.node
)
)
hasOriginalRef = true
}

if (
path.parentPath.isJSXExpressionContainer() &&
path.isReferencedIdentifier() &&
name === item.name
name === item.name &&
!(t.isMemberExpression(parent) && t.isIdentifier(parent.property, { name: LOOP_ORIGINAL })) &&
!(t.isMemberExpression(parent) && t.isIdentifier(parent.property) && (parent.property.name.startsWith(LOOP_STATE) || parent.property.name.startsWith(LOOP_CALLEE)))
) {
const parentCallExpr = path.findParent(c => isArrayMapCallExpression(c))
if (isArrayMapCallExpression(parentCallExpr)) {
const { object } = parentCallExpr.node.callee as t.MemberExpression
const isCallee = path.findParent(c => c.node === object)
if (isCallee) {
if (self.originalCallee.has(object)) {
const jsx = self.originalCallee.get(object)!
if (t.isMemberExpression(object)) {
const arr: string[] = ['object']
let obj = object.object as any
while (true) {
if (t.identifier(obj) && !t.isMemberExpression(obj)) {
break
}
obj = obj.object
arr.push('object')
}
const objectCopy = cloneDeep(object)
setObject(objectCopy, arr, t.memberExpression(t.identifier(item.name), t.identifier(LOOP_ORIGINAL)))
setJSXAttr(jsx, 'wx:for', t.jSXExpressionContainer(objectCopy))
}
}
return
}
}
path.replaceWith(t.memberExpression(
t.identifier(item.name),
t.identifier('$$original')
t.identifier(LOOP_ORIGINAL)
))
hasOriginalRef = true
}
Expand All @@ -898,13 +930,11 @@ export class RenderParser {
})
if (hasOriginalRef) {
properties.push(t.objectProperty(
t.identifier('$$original'),
t.identifier(LOOP_ORIGINAL),
t.identifier(item.name)
))
}
const returnStatement = t.returnStatement(t.objectExpression(
[t.spreadProperty(t.identifier(item.name)), ...properties]
))
const returnStatement = t.returnStatement(properties.length ? t.objectExpression(properties) : item)
const parentCallee = callee.findParent(c => isArrayMapCallExpression(c))
if (isArrayMapCallExpression(parentCallee)) {
const [ func ] = parentCallee.node.arguments
Expand Down
5 changes: 4 additions & 1 deletion packages/taro-transformer-wx/src/utils.ts
Expand Up @@ -353,12 +353,15 @@ export function hasComplexExpression (path: NodePath<t.Node>) {
return matched
}

export function findFirstIdentifierFromMemberExpression (node: t.MemberExpression): t.Identifier {
export function findFirstIdentifierFromMemberExpression (node: t.MemberExpression, member?): t.Identifier {
let id
let object = node.object as any
while (true) {
if (t.identifier(object) && !t.isMemberExpression(object)) {
id = object
if (member) {
object = member
}
break
}
object = object.object
Expand Down

0 comments on commit fd59a09

Please sign in to comment.