123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- "use strict";
- const CodePathState = require("./code-path-state");
- const IdGenerator = require("./id-generator");
- class CodePath {
-
-
- constructor(id, upper, onLooped) {
-
- this.id = id;
-
- this.upper = upper;
-
- this.childCodePaths = [];
-
- Object.defineProperty(
- this,
- "internal",
- { value: new CodePathState(new IdGenerator(`${id}_`), onLooped) }
- );
-
- if (upper) {
- upper.childCodePaths.push(this);
- }
- }
-
- static getState(codePath) {
- return codePath.internal;
- }
-
- get initialSegment() {
- return this.internal.initialSegment;
- }
-
- get finalSegments() {
- return this.internal.finalSegments;
- }
-
- get returnedSegments() {
- return this.internal.returnedForkContext;
- }
-
- get thrownSegments() {
- return this.internal.thrownForkContext;
- }
-
- get currentSegments() {
- return this.internal.currentSegments;
- }
-
- traverseSegments(options, callback) {
- let resolvedOptions;
- let resolvedCallback;
- if (typeof options === "function") {
- resolvedCallback = options;
- resolvedOptions = {};
- } else {
- resolvedOptions = options || {};
- resolvedCallback = callback;
- }
- const startSegment = resolvedOptions.first || this.internal.initialSegment;
- const lastSegment = resolvedOptions.last;
- let item = null;
- let index = 0;
- let end = 0;
- let segment = null;
- const visited = Object.create(null);
- const stack = [[startSegment, 0]];
- let skippedSegment = null;
- let broken = false;
- const controller = {
- skip() {
- if (stack.length <= 1) {
- broken = true;
- } else {
- skippedSegment = stack[stack.length - 2][0];
- }
- },
- break() {
- broken = true;
- }
- };
-
- function isVisited(prevSegment) {
- return (
- visited[prevSegment.id] ||
- segment.isLoopedPrevSegment(prevSegment)
- );
- }
- while (stack.length > 0) {
- item = stack[stack.length - 1];
- segment = item[0];
- index = item[1];
- if (index === 0) {
-
- if (visited[segment.id]) {
- stack.pop();
- continue;
- }
-
- if (segment !== startSegment &&
- segment.prevSegments.length > 0 &&
- !segment.prevSegments.every(isVisited)
- ) {
- stack.pop();
- continue;
- }
-
- if (skippedSegment && segment.prevSegments.indexOf(skippedSegment) !== -1) {
- skippedSegment = null;
- }
- visited[segment.id] = true;
-
- if (!skippedSegment) {
- resolvedCallback.call(this, segment, controller);
- if (segment === lastSegment) {
- controller.skip();
- }
- if (broken) {
- break;
- }
- }
- }
-
- end = segment.nextSegments.length - 1;
- if (index < end) {
- item[1] += 1;
- stack.push([segment.nextSegments[index], 0]);
- } else if (index === end) {
- item[0] = segment.nextSegments[index];
- item[1] = 0;
- } else {
- stack.pop();
- }
- }
- }
- }
- module.exports = CodePath;
|