member-expr.js 2.5 KB
Newer Older
fxy060608's avatar
fxy060608 已提交
1
const t = require('@babel/types')
2 3 4 5 6
const traverse = require('@babel/traverse').default

const {
  VAR_ROOT
} = require('../../constants')
fxy060608's avatar
fxy060608 已提交
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

function isMatch (name, forItem, forIndex) {
  return name === forItem || name === forIndex
}

function findScoped (path, state) {
  if (!path) {
    return state
  }
  const scoped = state.scoped.find(scoped => {
    const {
      forItem,
      forIndex
    } = scoped
    let match = false
22 23 24 25 26 27 28
    path.traverse({
      noScope: true,
      Identifier (path) {
        if (!match && path.key !== 'key' && (path.key !== 'property' || path.parent.computed)) {
          match = isMatch(path.node.name, forItem, forIndex)
          if (match) {
            path.stop()
fxy060608's avatar
fxy060608 已提交
29 30
          }
        }
31 32
      }
    })
fxy060608's avatar
fxy060608 已提交
33 34 35 36 37 38 39 40
    return match
  })
  if (!scoped && state.scoped.length > 1) {
    return state.scoped[1] // 取父
  }
  return scoped || state
}

41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
function findTest (path, state) {
  let tests
  while (path.parentPath && path.key !== 'body') {
    if (path.key === 'consequent' || path.key === 'alternate') {
      let test = t.arrayExpression([t.clone(path.container.test)])
      traverse(test, {
        noScope: true,
        MemberExpression (path) {
          const names = state.scoped.map(scoped => scoped.forItem)
          const node = path.node
          const objectName = node.object.name
          if (objectName === VAR_ROOT || names.includes(objectName)) {
            path.replaceWith(node.property)
          }
        }
      })
      test = test.elements[0]
      if (path.key === 'alternate') {
        test = t.unaryExpression('!', test)
      }
      tests = tests ? t.logicalExpression('&&', test, tests) : test
    }
    path = path.parentPath
  }
  return tests
}

fxy060608's avatar
fxy060608 已提交
68 69
module.exports = function getMemberExpr (path, name, init, state, variableDeclaration = true) {
  const scoped = findScoped(path, state)
70
  const test = findTest(path, state)
fxy060608's avatar
fxy060608 已提交
71 72 73 74 75 76 77 78 79 80

  if (!variableDeclaration) {
    scoped.declarationArray.push(t.expressionStatement(init))
    return
  }

  const identifier = t.identifier(name)

  scoped.propertyArray.push(t.objectProperty(identifier, identifier))
  scoped.declarationArray.push(
81
    t.variableDeclaration('var', [t.variableDeclarator(identifier, test ? t.conditionalExpression(test, init, t.nullLiteral()) : init)])
fxy060608's avatar
fxy060608 已提交
82 83 84 85 86 87 88
  )

  state.identifierArray.push(identifier)

  const contextIdentifier = t.identifier(scoped.context)
  contextIdentifier.$mpProcessed = true
  return t.memberExpression(contextIdentifier, identifier)
89
}