You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							453 lines
						
					
					
						
							12 KiB
						
					
					
				
			
		
		
	
	
							453 lines
						
					
					
						
							12 KiB
						
					
					
				'use strict'; | 
						|
 | 
						|
Object.defineProperty(exports, '__esModule', { value: true }); | 
						|
 | 
						|
var _t = require('@babel/types'); | 
						|
 | 
						|
function _interopNamespace(e) { | 
						|
  if (e && e.__esModule) return e; | 
						|
  var n = Object.create(null); | 
						|
  if (e) { | 
						|
    Object.keys(e).forEach(function (k) { | 
						|
      if (k !== 'default') { | 
						|
        var d = Object.getOwnPropertyDescriptor(e, k); | 
						|
        Object.defineProperty(n, k, d.get ? d : { | 
						|
          enumerable: true, | 
						|
          get: function () { | 
						|
            return e[k]; | 
						|
          } | 
						|
        }); | 
						|
      } | 
						|
    }); | 
						|
  } | 
						|
  n['default'] = e; | 
						|
  return Object.freeze(n); | 
						|
} | 
						|
 | 
						|
var _t__namespace = /*#__PURE__*/_interopNamespace(_t); | 
						|
 | 
						|
function willPathCastToBoolean(path) { | 
						|
  const maybeWrapped = path; | 
						|
  const { | 
						|
    node, | 
						|
    parentPath | 
						|
  } = maybeWrapped; | 
						|
 | 
						|
  if (parentPath.isLogicalExpression()) { | 
						|
    const { | 
						|
      operator, | 
						|
      right | 
						|
    } = parentPath.node; | 
						|
 | 
						|
    if (operator === "&&" || operator === "||" || operator === "??" && node === right) { | 
						|
      return willPathCastToBoolean(parentPath); | 
						|
    } | 
						|
  } | 
						|
 | 
						|
  if (parentPath.isSequenceExpression()) { | 
						|
    const { | 
						|
      expressions | 
						|
    } = parentPath.node; | 
						|
 | 
						|
    if (expressions[expressions.length - 1] === node) { | 
						|
      return willPathCastToBoolean(parentPath); | 
						|
    } else { | 
						|
      return true; | 
						|
    } | 
						|
  } | 
						|
 | 
						|
  return parentPath.isConditional({ | 
						|
    test: node | 
						|
  }) || parentPath.isUnaryExpression({ | 
						|
    operator: "!" | 
						|
  }) || parentPath.isLoop({ | 
						|
    test: node | 
						|
  }); | 
						|
} | 
						|
 | 
						|
const { | 
						|
  LOGICAL_OPERATORS, | 
						|
  arrowFunctionExpression, | 
						|
  assignmentExpression, | 
						|
  binaryExpression, | 
						|
  booleanLiteral, | 
						|
  callExpression, | 
						|
  cloneNode, | 
						|
  conditionalExpression, | 
						|
  identifier, | 
						|
  isMemberExpression, | 
						|
  isOptionalCallExpression, | 
						|
  isOptionalMemberExpression, | 
						|
  isUpdateExpression, | 
						|
  logicalExpression, | 
						|
  memberExpression, | 
						|
  nullLiteral, | 
						|
  numericLiteral, | 
						|
  optionalCallExpression, | 
						|
  optionalMemberExpression, | 
						|
  sequenceExpression, | 
						|
  unaryExpression | 
						|
} = _t__namespace; | 
						|
 | 
						|
class AssignmentMemoiser { | 
						|
  constructor() { | 
						|
    this._map = void 0; | 
						|
    this._map = new WeakMap(); | 
						|
  } | 
						|
 | 
						|
  has(key) { | 
						|
    return this._map.has(key); | 
						|
  } | 
						|
 | 
						|
  get(key) { | 
						|
    if (!this.has(key)) return; | 
						|
 | 
						|
    const record = this._map.get(key); | 
						|
 | 
						|
    const { | 
						|
      value | 
						|
    } = record; | 
						|
    record.count--; | 
						|
 | 
						|
    if (record.count === 0) { | 
						|
      return assignmentExpression("=", value, key); | 
						|
    } | 
						|
 | 
						|
    return value; | 
						|
  } | 
						|
 | 
						|
  set(key, value, count) { | 
						|
    return this._map.set(key, { | 
						|
      count, | 
						|
      value | 
						|
    }); | 
						|
  } | 
						|
 | 
						|
} | 
						|
 | 
						|
function toNonOptional(path, base) { | 
						|
  const { | 
						|
    node | 
						|
  } = path; | 
						|
 | 
						|
  if (isOptionalMemberExpression(node)) { | 
						|
    return memberExpression(base, node.property, node.computed); | 
						|
  } | 
						|
 | 
						|
  if (path.isOptionalCallExpression()) { | 
						|
    const callee = path.get("callee"); | 
						|
 | 
						|
    if (path.node.optional && callee.isOptionalMemberExpression()) { | 
						|
      const { | 
						|
        object | 
						|
      } = callee.node; | 
						|
      const context = path.scope.maybeGenerateMemoised(object) || object; | 
						|
      callee.get("object").replaceWith(assignmentExpression("=", context, object)); | 
						|
      return callExpression(memberExpression(base, identifier("call")), [context, ...path.node.arguments]); | 
						|
    } | 
						|
 | 
						|
    return callExpression(base, path.node.arguments); | 
						|
  } | 
						|
 | 
						|
  return path.node; | 
						|
} | 
						|
 | 
						|
function isInDetachedTree(path) { | 
						|
  while (path) { | 
						|
    if (path.isProgram()) break; | 
						|
    const { | 
						|
      parentPath, | 
						|
      container, | 
						|
      listKey | 
						|
    } = path; | 
						|
    const parentNode = parentPath.node; | 
						|
 | 
						|
    if (listKey) { | 
						|
      if (container !== parentNode[listKey]) return true; | 
						|
    } else { | 
						|
      if (container !== parentNode) return true; | 
						|
    } | 
						|
 | 
						|
    path = parentPath; | 
						|
  } | 
						|
 | 
						|
  return false; | 
						|
} | 
						|
 | 
						|
const handle = { | 
						|
  memoise() {}, | 
						|
 | 
						|
  handle(member, noDocumentAll) { | 
						|
    const { | 
						|
      node, | 
						|
      parent, | 
						|
      parentPath, | 
						|
      scope | 
						|
    } = member; | 
						|
 | 
						|
    if (member.isOptionalMemberExpression()) { | 
						|
      if (isInDetachedTree(member)) return; | 
						|
      const endPath = member.find(({ | 
						|
        node, | 
						|
        parent | 
						|
      }) => { | 
						|
        if (isOptionalMemberExpression(parent)) { | 
						|
          return parent.optional || parent.object !== node; | 
						|
        } | 
						|
 | 
						|
        if (isOptionalCallExpression(parent)) { | 
						|
          return node !== member.node && parent.optional || parent.callee !== node; | 
						|
        } | 
						|
 | 
						|
        return true; | 
						|
      }); | 
						|
 | 
						|
      if (scope.path.isPattern()) { | 
						|
        endPath.replaceWith(callExpression(arrowFunctionExpression([], endPath.node), [])); | 
						|
        return; | 
						|
      } | 
						|
 | 
						|
      const willEndPathCastToBoolean = willPathCastToBoolean(endPath); | 
						|
      const rootParentPath = endPath.parentPath; | 
						|
 | 
						|
      if (rootParentPath.isUpdateExpression({ | 
						|
        argument: node | 
						|
      }) || rootParentPath.isAssignmentExpression({ | 
						|
        left: node | 
						|
      })) { | 
						|
        throw member.buildCodeFrameError(`can't handle assignment`); | 
						|
      } | 
						|
 | 
						|
      const isDeleteOperation = rootParentPath.isUnaryExpression({ | 
						|
        operator: "delete" | 
						|
      }); | 
						|
 | 
						|
      if (isDeleteOperation && endPath.isOptionalMemberExpression() && endPath.get("property").isPrivateName()) { | 
						|
        throw member.buildCodeFrameError(`can't delete a private class element`); | 
						|
      } | 
						|
 | 
						|
      let startingOptional = member; | 
						|
 | 
						|
      for (;;) { | 
						|
        if (startingOptional.isOptionalMemberExpression()) { | 
						|
          if (startingOptional.node.optional) break; | 
						|
          startingOptional = startingOptional.get("object"); | 
						|
          continue; | 
						|
        } else if (startingOptional.isOptionalCallExpression()) { | 
						|
          if (startingOptional.node.optional) break; | 
						|
          startingOptional = startingOptional.get("callee"); | 
						|
          continue; | 
						|
        } | 
						|
 | 
						|
        throw new Error(`Internal error: unexpected ${startingOptional.node.type}`); | 
						|
      } | 
						|
 | 
						|
      const startingProp = startingOptional.isOptionalMemberExpression() ? "object" : "callee"; | 
						|
      const startingNode = startingOptional.node[startingProp]; | 
						|
      const baseNeedsMemoised = scope.maybeGenerateMemoised(startingNode); | 
						|
      const baseRef = baseNeedsMemoised != null ? baseNeedsMemoised : startingNode; | 
						|
      const parentIsOptionalCall = parentPath.isOptionalCallExpression({ | 
						|
        callee: node | 
						|
      }); | 
						|
 | 
						|
      const isOptionalCall = parent => parentIsOptionalCall; | 
						|
 | 
						|
      const parentIsCall = parentPath.isCallExpression({ | 
						|
        callee: node | 
						|
      }); | 
						|
      startingOptional.replaceWith(toNonOptional(startingOptional, baseRef)); | 
						|
 | 
						|
      if (isOptionalCall()) { | 
						|
        if (parent.optional) { | 
						|
          parentPath.replaceWith(this.optionalCall(member, parent.arguments)); | 
						|
        } else { | 
						|
          parentPath.replaceWith(this.call(member, parent.arguments)); | 
						|
        } | 
						|
      } else if (parentIsCall) { | 
						|
        member.replaceWith(this.boundGet(member)); | 
						|
      } else { | 
						|
        member.replaceWith(this.get(member)); | 
						|
      } | 
						|
 | 
						|
      let regular = member.node; | 
						|
 | 
						|
      for (let current = member; current !== endPath;) { | 
						|
        const parentPath = current.parentPath; | 
						|
 | 
						|
        if (parentPath === endPath && isOptionalCall() && parent.optional) { | 
						|
          regular = parentPath.node; | 
						|
          break; | 
						|
        } | 
						|
 | 
						|
        regular = toNonOptional(parentPath, regular); | 
						|
        current = parentPath; | 
						|
      } | 
						|
 | 
						|
      let context; | 
						|
      const endParentPath = endPath.parentPath; | 
						|
 | 
						|
      if (isMemberExpression(regular) && endParentPath.isOptionalCallExpression({ | 
						|
        callee: endPath.node, | 
						|
        optional: true | 
						|
      })) { | 
						|
        const { | 
						|
          object | 
						|
        } = regular; | 
						|
        context = member.scope.maybeGenerateMemoised(object); | 
						|
 | 
						|
        if (context) { | 
						|
          regular.object = assignmentExpression("=", context, object); | 
						|
        } | 
						|
      } | 
						|
 | 
						|
      let replacementPath = endPath; | 
						|
 | 
						|
      if (isDeleteOperation) { | 
						|
        replacementPath = endParentPath; | 
						|
        regular = endParentPath.node; | 
						|
      } | 
						|
 | 
						|
      const baseMemoised = baseNeedsMemoised ? assignmentExpression("=", cloneNode(baseRef), cloneNode(startingNode)) : cloneNode(baseRef); | 
						|
 | 
						|
      if (willEndPathCastToBoolean) { | 
						|
        let nonNullishCheck; | 
						|
 | 
						|
        if (noDocumentAll) { | 
						|
          nonNullishCheck = binaryExpression("!=", baseMemoised, nullLiteral()); | 
						|
        } else { | 
						|
          nonNullishCheck = logicalExpression("&&", binaryExpression("!==", baseMemoised, nullLiteral()), binaryExpression("!==", cloneNode(baseRef), scope.buildUndefinedNode())); | 
						|
        } | 
						|
 | 
						|
        replacementPath.replaceWith(logicalExpression("&&", nonNullishCheck, regular)); | 
						|
      } else { | 
						|
        let nullishCheck; | 
						|
 | 
						|
        if (noDocumentAll) { | 
						|
          nullishCheck = binaryExpression("==", baseMemoised, nullLiteral()); | 
						|
        } else { | 
						|
          nullishCheck = logicalExpression("||", binaryExpression("===", baseMemoised, nullLiteral()), binaryExpression("===", cloneNode(baseRef), scope.buildUndefinedNode())); | 
						|
        } | 
						|
 | 
						|
        replacementPath.replaceWith(conditionalExpression(nullishCheck, isDeleteOperation ? booleanLiteral(true) : scope.buildUndefinedNode(), regular)); | 
						|
      } | 
						|
 | 
						|
      if (context) { | 
						|
        const endParent = endParentPath.node; | 
						|
        endParentPath.replaceWith(optionalCallExpression(optionalMemberExpression(endParent.callee, identifier("call"), false, true), [cloneNode(context), ...endParent.arguments], false)); | 
						|
      } | 
						|
 | 
						|
      return; | 
						|
    } | 
						|
 | 
						|
    if (isUpdateExpression(parent, { | 
						|
      argument: node | 
						|
    })) { | 
						|
      if (this.simpleSet) { | 
						|
        member.replaceWith(this.simpleSet(member)); | 
						|
        return; | 
						|
      } | 
						|
 | 
						|
      const { | 
						|
        operator, | 
						|
        prefix | 
						|
      } = parent; | 
						|
      this.memoise(member, 2); | 
						|
      const value = binaryExpression(operator[0], unaryExpression("+", this.get(member)), numericLiteral(1)); | 
						|
 | 
						|
      if (prefix) { | 
						|
        parentPath.replaceWith(this.set(member, value)); | 
						|
      } else { | 
						|
        const { | 
						|
          scope | 
						|
        } = member; | 
						|
        const ref = scope.generateUidIdentifierBasedOnNode(node); | 
						|
        scope.push({ | 
						|
          id: ref | 
						|
        }); | 
						|
        value.left = assignmentExpression("=", cloneNode(ref), value.left); | 
						|
        parentPath.replaceWith(sequenceExpression([this.set(member, value), cloneNode(ref)])); | 
						|
      } | 
						|
 | 
						|
      return; | 
						|
    } | 
						|
 | 
						|
    if (parentPath.isAssignmentExpression({ | 
						|
      left: node | 
						|
    })) { | 
						|
      if (this.simpleSet) { | 
						|
        member.replaceWith(this.simpleSet(member)); | 
						|
        return; | 
						|
      } | 
						|
 | 
						|
      const { | 
						|
        operator, | 
						|
        right: value | 
						|
      } = parentPath.node; | 
						|
 | 
						|
      if (operator === "=") { | 
						|
        parentPath.replaceWith(this.set(member, value)); | 
						|
      } else { | 
						|
        const operatorTrunc = operator.slice(0, -1); | 
						|
 | 
						|
        if (LOGICAL_OPERATORS.includes(operatorTrunc)) { | 
						|
          this.memoise(member, 1); | 
						|
          parentPath.replaceWith(logicalExpression(operatorTrunc, this.get(member), this.set(member, value))); | 
						|
        } else { | 
						|
          this.memoise(member, 2); | 
						|
          parentPath.replaceWith(this.set(member, binaryExpression(operatorTrunc, this.get(member), value))); | 
						|
        } | 
						|
      } | 
						|
 | 
						|
      return; | 
						|
    } | 
						|
 | 
						|
    if (parentPath.isCallExpression({ | 
						|
      callee: node | 
						|
    })) { | 
						|
      parentPath.replaceWith(this.call(member, parentPath.node.arguments)); | 
						|
      return; | 
						|
    } | 
						|
 | 
						|
    if (parentPath.isOptionalCallExpression({ | 
						|
      callee: node | 
						|
    })) { | 
						|
      if (scope.path.isPattern()) { | 
						|
        parentPath.replaceWith(callExpression(arrowFunctionExpression([], parentPath.node), [])); | 
						|
        return; | 
						|
      } | 
						|
 | 
						|
      parentPath.replaceWith(this.optionalCall(member, parentPath.node.arguments)); | 
						|
      return; | 
						|
    } | 
						|
 | 
						|
    if (parentPath.isForXStatement({ | 
						|
      left: node | 
						|
    }) || parentPath.isObjectProperty({ | 
						|
      value: node | 
						|
    }) && parentPath.parentPath.isObjectPattern() || parentPath.isAssignmentPattern({ | 
						|
      left: node | 
						|
    }) && parentPath.parentPath.isObjectProperty({ | 
						|
      value: parent | 
						|
    }) && parentPath.parentPath.parentPath.isObjectPattern() || parentPath.isArrayPattern() || parentPath.isAssignmentPattern({ | 
						|
      left: node | 
						|
    }) && parentPath.parentPath.isArrayPattern() || parentPath.isRestElement()) { | 
						|
      member.replaceWith(this.destructureSet(member)); | 
						|
      return; | 
						|
    } | 
						|
 | 
						|
    if (parentPath.isTaggedTemplateExpression()) { | 
						|
      member.replaceWith(this.boundGet(member)); | 
						|
    } else { | 
						|
      member.replaceWith(this.get(member)); | 
						|
    } | 
						|
  } | 
						|
 | 
						|
}; | 
						|
function memberExpressionToFunctions(path, visitor, state) { | 
						|
  path.traverse(visitor, Object.assign({}, handle, state, { | 
						|
    memoiser: new AssignmentMemoiser() | 
						|
  })); | 
						|
} | 
						|
 | 
						|
exports.default = memberExpressionToFunctions; | 
						|
//# sourceMappingURL=index.js.map
 | 
						|
 |