cloneNode.js
  1  "use strict";
  2  
  3  Object.defineProperty(exports, "__esModule", {
  4    value: true
  5  });
  6  exports.default = cloneNode;
  7  
  8  var _definitions = require("../definitions");
  9  
 10  var _generated = require("../validators/generated");
 11  
 12  const has = Function.call.bind(Object.prototype.hasOwnProperty);
 13  
 14  function cloneIfNode(obj, deep, withoutLoc) {
 15    if (obj && typeof obj.type === "string") {
 16      return cloneNode(obj, deep, withoutLoc);
 17    }
 18  
 19    return obj;
 20  }
 21  
 22  function cloneIfNodeOrArray(obj, deep, withoutLoc) {
 23    if (Array.isArray(obj)) {
 24      return obj.map(node => cloneIfNode(node, deep, withoutLoc));
 25    }
 26  
 27    return cloneIfNode(obj, deep, withoutLoc);
 28  }
 29  
 30  function cloneNode(node, deep = true, withoutLoc = false) {
 31    if (!node) return node;
 32    const {
 33      type
 34    } = node;
 35    const newNode = {
 36      type: node.type
 37    };
 38  
 39    if ((0, _generated.isIdentifier)(node)) {
 40      newNode.name = node.name;
 41  
 42      if (has(node, "optional") && typeof node.optional === "boolean") {
 43        newNode.optional = node.optional;
 44      }
 45  
 46      if (has(node, "typeAnnotation")) {
 47        newNode.typeAnnotation = deep ? cloneIfNodeOrArray(node.typeAnnotation, true, withoutLoc) : node.typeAnnotation;
 48      }
 49    } else if (!has(_definitions.NODE_FIELDS, type)) {
 50      throw new Error(`Unknown node type: "${type}"`);
 51    } else {
 52      for (const field of Object.keys(_definitions.NODE_FIELDS[type])) {
 53        if (has(node, field)) {
 54          if (deep) {
 55            newNode[field] = (0, _generated.isFile)(node) && field === "comments" ? maybeCloneComments(node.comments, deep, withoutLoc) : cloneIfNodeOrArray(node[field], true, withoutLoc);
 56          } else {
 57            newNode[field] = node[field];
 58          }
 59        }
 60      }
 61    }
 62  
 63    if (has(node, "loc")) {
 64      if (withoutLoc) {
 65        newNode.loc = null;
 66      } else {
 67        newNode.loc = node.loc;
 68      }
 69    }
 70  
 71    if (has(node, "leadingComments")) {
 72      newNode.leadingComments = maybeCloneComments(node.leadingComments, deep, withoutLoc);
 73    }
 74  
 75    if (has(node, "innerComments")) {
 76      newNode.innerComments = maybeCloneComments(node.innerComments, deep, withoutLoc);
 77    }
 78  
 79    if (has(node, "trailingComments")) {
 80      newNode.trailingComments = maybeCloneComments(node.trailingComments, deep, withoutLoc);
 81    }
 82  
 83    if (has(node, "extra")) {
 84      newNode.extra = Object.assign({}, node.extra);
 85    }
 86  
 87    return newNode;
 88  }
 89  
 90  function maybeCloneComments(comments, deep, withoutLoc) {
 91    if (!comments || !deep) {
 92      return comments;
 93    }
 94  
 95    return comments.map(({
 96      type,
 97      value,
 98      loc
 99    }) => {
100      if (withoutLoc) {
101        return {
102          type,
103          value,
104          loc: null
105        };
106      }
107  
108      return {
109        type,
110        value,
111        loc
112      };
113    });
114  }