152 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			152 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | "use strict"; | ||
|  | 
 | ||
|  | Object.defineProperty(exports, "__esModule", { | ||
|  |   value: true | ||
|  | }); | ||
|  | exports.default = void 0; | ||
|  | 
 | ||
|  | var _path = _interopRequireDefault(require("./path")); | ||
|  | 
 | ||
|  | function t() { | ||
|  |   const data = _interopRequireWildcard(require("@babel/types")); | ||
|  | 
 | ||
|  |   t = function () { | ||
|  |     return data; | ||
|  |   }; | ||
|  | 
 | ||
|  |   return data; | ||
|  | } | ||
|  | 
 | ||
|  | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } | ||
|  | 
 | ||
|  | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
|  | 
 | ||
|  | const testing = process.env.NODE_ENV === "test"; | ||
|  | 
 | ||
|  | class TraversalContext { | ||
|  |   constructor(scope, opts, state, parentPath) { | ||
|  |     this.queue = null; | ||
|  |     this.parentPath = parentPath; | ||
|  |     this.scope = scope; | ||
|  |     this.state = state; | ||
|  |     this.opts = opts; | ||
|  |   } | ||
|  | 
 | ||
|  |   shouldVisit(node) { | ||
|  |     const opts = this.opts; | ||
|  |     if (opts.enter || opts.exit) return true; | ||
|  |     if (opts[node.type]) return true; | ||
|  |     const keys = t().VISITOR_KEYS[node.type]; | ||
|  |     if (!keys || !keys.length) return false; | ||
|  | 
 | ||
|  |     for (const key of keys) { | ||
|  |       if (node[key]) return true; | ||
|  |     } | ||
|  | 
 | ||
|  |     return false; | ||
|  |   } | ||
|  | 
 | ||
|  |   create(node, obj, key, listKey) { | ||
|  |     return _path.default.get({ | ||
|  |       parentPath: this.parentPath, | ||
|  |       parent: node, | ||
|  |       container: obj, | ||
|  |       key: key, | ||
|  |       listKey | ||
|  |     }); | ||
|  |   } | ||
|  | 
 | ||
|  |   maybeQueue(path, notPriority) { | ||
|  |     if (this.trap) { | ||
|  |       throw new Error("Infinite cycle detected"); | ||
|  |     } | ||
|  | 
 | ||
|  |     if (this.queue) { | ||
|  |       if (notPriority) { | ||
|  |         this.queue.push(path); | ||
|  |       } else { | ||
|  |         this.priorityQueue.push(path); | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   visitMultiple(container, parent, listKey) { | ||
|  |     if (container.length === 0) return false; | ||
|  |     const queue = []; | ||
|  | 
 | ||
|  |     for (let key = 0; key < container.length; key++) { | ||
|  |       const node = container[key]; | ||
|  | 
 | ||
|  |       if (node && this.shouldVisit(node)) { | ||
|  |         queue.push(this.create(parent, container, key, listKey)); | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     return this.visitQueue(queue); | ||
|  |   } | ||
|  | 
 | ||
|  |   visitSingle(node, key) { | ||
|  |     if (this.shouldVisit(node[key])) { | ||
|  |       return this.visitQueue([this.create(node, node, key)]); | ||
|  |     } else { | ||
|  |       return false; | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   visitQueue(queue) { | ||
|  |     this.queue = queue; | ||
|  |     this.priorityQueue = []; | ||
|  |     const visited = []; | ||
|  |     let stop = false; | ||
|  | 
 | ||
|  |     for (const path of queue) { | ||
|  |       path.resync(); | ||
|  | 
 | ||
|  |       if (path.contexts.length === 0 || path.contexts[path.contexts.length - 1] !== this) { | ||
|  |         path.pushContext(this); | ||
|  |       } | ||
|  | 
 | ||
|  |       if (path.key === null) continue; | ||
|  | 
 | ||
|  |       if (testing && queue.length >= 10000) { | ||
|  |         this.trap = true; | ||
|  |       } | ||
|  | 
 | ||
|  |       if (visited.indexOf(path.node) >= 0) continue; | ||
|  |       visited.push(path.node); | ||
|  | 
 | ||
|  |       if (path.visit()) { | ||
|  |         stop = true; | ||
|  |         break; | ||
|  |       } | ||
|  | 
 | ||
|  |       if (this.priorityQueue.length) { | ||
|  |         stop = this.visitQueue(this.priorityQueue); | ||
|  |         this.priorityQueue = []; | ||
|  |         this.queue = queue; | ||
|  |         if (stop) break; | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     for (const path of queue) { | ||
|  |       path.popContext(); | ||
|  |     } | ||
|  | 
 | ||
|  |     this.queue = null; | ||
|  |     return stop; | ||
|  |   } | ||
|  | 
 | ||
|  |   visit(node, key) { | ||
|  |     const nodes = node[key]; | ||
|  |     if (!nodes) return false; | ||
|  | 
 | ||
|  |     if (Array.isArray(nodes)) { | ||
|  |       return this.visitMultiple(nodes, node, key); | ||
|  |     } else { | ||
|  |       return this.visitSingle(node, key); | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | exports.default = TraversalContext; |