UNPKG

3.81 kBJavaScriptView Raw
1/**
2 * Copyright (c) 2014, Facebook, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * https://raw.github.com/facebook/regenerator/master/LICENSE file. An
7 * additional grant of patent rights can be found in the PATENTS file in
8 * the same directory.
9 */
10
11import assert from "assert";
12import * as t from "babel-types";
13import { inherits } from "util";
14
15function Entry() {
16 assert.ok(this instanceof Entry);
17}
18
19function FunctionEntry(returnLoc) {
20 Entry.call(this);
21 t.assertLiteral(returnLoc);
22 this.returnLoc = returnLoc;
23}
24
25inherits(FunctionEntry, Entry);
26exports.FunctionEntry = FunctionEntry;
27
28function LoopEntry(breakLoc, continueLoc, label) {
29 Entry.call(this);
30
31 t.assertLiteral(breakLoc);
32 t.assertLiteral(continueLoc);
33
34 if (label) {
35 t.assertIdentifier(label);
36 } else {
37 label = null;
38 }
39
40 this.breakLoc = breakLoc;
41 this.continueLoc = continueLoc;
42 this.label = label;
43}
44
45inherits(LoopEntry, Entry);
46exports.LoopEntry = LoopEntry;
47
48function SwitchEntry(breakLoc) {
49 Entry.call(this);
50 t.assertLiteral(breakLoc);
51 this.breakLoc = breakLoc;
52}
53
54inherits(SwitchEntry, Entry);
55exports.SwitchEntry = SwitchEntry;
56
57function TryEntry(firstLoc, catchEntry, finallyEntry) {
58 Entry.call(this);
59
60 t.assertLiteral(firstLoc);
61
62 if (catchEntry) {
63 assert.ok(catchEntry instanceof CatchEntry);
64 } else {
65 catchEntry = null;
66 }
67
68 if (finallyEntry) {
69 assert.ok(finallyEntry instanceof FinallyEntry);
70 } else {
71 finallyEntry = null;
72 }
73
74 // Have to have one or the other (or both).
75 assert.ok(catchEntry || finallyEntry);
76
77 this.firstLoc = firstLoc;
78 this.catchEntry = catchEntry;
79 this.finallyEntry = finallyEntry;
80}
81
82inherits(TryEntry, Entry);
83exports.TryEntry = TryEntry;
84
85function CatchEntry(firstLoc, paramId) {
86 Entry.call(this);
87
88 t.assertLiteral(firstLoc);
89 t.assertIdentifier(paramId);
90
91 this.firstLoc = firstLoc;
92 this.paramId = paramId;
93}
94
95inherits(CatchEntry, Entry);
96exports.CatchEntry = CatchEntry;
97
98function FinallyEntry(firstLoc, afterLoc) {
99 Entry.call(this);
100 t.assertLiteral(firstLoc);
101 t.assertLiteral(afterLoc);
102 this.firstLoc = firstLoc;
103 this.afterLoc = afterLoc;
104}
105
106inherits(FinallyEntry, Entry);
107exports.FinallyEntry = FinallyEntry;
108
109function LabeledEntry(breakLoc, label) {
110 Entry.call(this);
111
112 t.assertLiteral(breakLoc);
113 t.assertIdentifier(label);
114
115 this.breakLoc = breakLoc;
116 this.label = label;
117}
118
119inherits(LabeledEntry, Entry);
120exports.LabeledEntry = LabeledEntry;
121
122function LeapManager(emitter) {
123 assert.ok(this instanceof LeapManager);
124
125 let Emitter = require("./emit").Emitter;
126 assert.ok(emitter instanceof Emitter);
127
128 this.emitter = emitter;
129 this.entryStack = [new FunctionEntry(emitter.finalLoc)];
130}
131
132let LMp = LeapManager.prototype;
133exports.LeapManager = LeapManager;
134
135LMp.withEntry = function(entry, callback) {
136 assert.ok(entry instanceof Entry);
137 this.entryStack.push(entry);
138 try {
139 callback.call(this.emitter);
140 } finally {
141 let popped = this.entryStack.pop();
142 assert.strictEqual(popped, entry);
143 }
144};
145
146LMp._findLeapLocation = function(property, label) {
147 for (let i = this.entryStack.length - 1; i >= 0; --i) {
148 let entry = this.entryStack[i];
149 let loc = entry[property];
150 if (loc) {
151 if (label) {
152 if (entry.label &&
153 entry.label.name === label.name) {
154 return loc;
155 }
156 } else if (entry instanceof LabeledEntry) {
157 // Ignore LabeledEntry entries unless we are actually breaking to
158 // a label.
159 } else {
160 return loc;
161 }
162 }
163 }
164
165 return null;
166};
167
168LMp.getBreakLoc = function(label) {
169 return this._findLeapLocation("breakLoc", label);
170};
171
172LMp.getContinueLoc = function(label) {
173 return this._findLeapLocation("continueLoc", label);
174};