UNPKG

12.3 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.PossiblyNormalCompletion = exports.ForkedAbruptCompletion = exports.ReturnCompletion = exports.BreakCompletion = exports.ContinueCompletion = exports.ThrowCompletion = exports.AbruptCompletion = exports.SimpleNormalCompletion = exports.NormalCompletion = exports.Completion = void 0;
7
8var _invariant = _interopRequireDefault(require("./invariant.js"));
9
10var _realm = require("./realm.js");
11
12var _index = require("./values/index.js");
13
14function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
16/**
17 * Copyright (c) 2017-present, Facebook, Inc.
18 * All rights reserved.
19 *
20 * This source code is licensed under the BSD-style license found in the
21 * LICENSE file in the root directory of this source tree. An additional grant
22 * of patent rights can be found in the PATENTS file in the same directory.
23 */
24class Completion {
25 constructor(value, precedingEffects, location, target) {
26 let e = precedingEffects;
27
28 if (e !== undefined) {
29 if (e.result === undefined) e.result = this;else e = e.shallowCloneWithResult(this);
30 }
31
32 this.value = value;
33 this.effects = e;
34 this.target = target;
35 this.location = location;
36 (0, _invariant.default)(this.constructor !== Completion, "Completion is an abstract base class");
37 }
38
39 shallowCloneWithoutEffects() {
40 (0, _invariant.default)(false, "Completion.shallowCloneWithoutEffects is an abstract base method and should not be called");
41 }
42
43 toDisplayString() {
44 return "[" + this.constructor.name + " value " + (this.value ? this.value.toDisplayString() : "undefined") + "]";
45 }
46
47} // Normal completions are returned just like spec completions
48
49
50exports.Completion = Completion;
51
52class NormalCompletion extends Completion {
53 constructor(value, precedingEffects, location, target) {
54 super(value, precedingEffects, location, target);
55 (0, _invariant.default)(this.constructor !== NormalCompletion, "NormalCompletion is an abstract base class");
56 }
57
58 shallowCloneWithoutEffects() {
59 (0, _invariant.default)(false, "NormalCompletion.shallowCloneWithoutEffects is an abstract base method and should not be called");
60 }
61
62} // SimpleNormalCompletions are returned just like spec completions. This class exists as the parallel for
63// PossiblyNormalCompletion to make comparisons easier.
64
65
66exports.NormalCompletion = NormalCompletion;
67
68class SimpleNormalCompletion extends NormalCompletion {
69 shallowCloneWithoutEffects() {
70 return new SimpleNormalCompletion(this.value, undefined, this.location, this.target);
71 }
72
73} // Abrupt completions are thrown as exeptions, to make it a easier
74// to quickly get to the matching high level construct.
75
76
77exports.SimpleNormalCompletion = SimpleNormalCompletion;
78
79class AbruptCompletion extends Completion {
80 constructor(value, precedingEffects, location, target) {
81 super(value, precedingEffects, location, target);
82 (0, _invariant.default)(this.constructor !== AbruptCompletion, "AbruptCompletion is an abstract base class");
83 }
84
85 shallowCloneWithoutEffects() {
86 (0, _invariant.default)(false, "AbruptCompletion.shallowCloneWithoutEffects is an abstract base method and should not be called");
87 }
88
89}
90
91exports.AbruptCompletion = AbruptCompletion;
92
93class ThrowCompletion extends AbruptCompletion {
94 constructor(value, precedingEffects, location, nativeStack) {
95 super(value, precedingEffects, location);
96 this.nativeStack = nativeStack || new Error().stack;
97 let realm = value.$Realm;
98
99 if (realm.isInPureScope()) {
100 for (let callback of realm.reportSideEffectCallbacks) {
101 callback("EXCEPTION_THROWN", undefined, location);
102 }
103 }
104 }
105
106 shallowCloneWithoutEffects() {
107 return new ThrowCompletion(this.value, undefined, this.location, this.nativeStack);
108 }
109
110}
111
112exports.ThrowCompletion = ThrowCompletion;
113
114class ContinueCompletion extends AbruptCompletion {
115 constructor(value, precedingEffects, location, target) {
116 super(value, precedingEffects, location, target || null);
117 }
118
119 shallowCloneWithoutEffects() {
120 return new ContinueCompletion(this.value, undefined, this.location, this.target);
121 }
122
123}
124
125exports.ContinueCompletion = ContinueCompletion;
126
127class BreakCompletion extends AbruptCompletion {
128 constructor(value, precedingEffects, location, target) {
129 super(value, precedingEffects, location, target || null);
130 }
131
132 shallowCloneWithoutEffects() {
133 return new BreakCompletion(this.value, undefined, this.location, this.target);
134 }
135
136}
137
138exports.BreakCompletion = BreakCompletion;
139
140class ReturnCompletion extends AbruptCompletion {
141 constructor(value, precedingEffects, location) {
142 super(value, precedingEffects, location);
143
144 if (value instanceof _index.EmptyValue) {
145 this.value = value.$Realm.intrinsics.undefined;
146 }
147 }
148
149 shallowCloneWithoutEffects() {
150 return new ReturnCompletion(this.value, undefined, this.location);
151 }
152
153}
154
155exports.ReturnCompletion = ReturnCompletion;
156
157class ForkedAbruptCompletion extends AbruptCompletion {
158 constructor(realm, joinCondition, consequent, alternate) {
159 super(realm.intrinsics.empty, undefined, consequent.location);
160 this.joinCondition = joinCondition;
161 this.consequent = consequent;
162 this.alternate = alternate;
163 }
164
165 shallowCloneWithoutEffects() {
166 return new ForkedAbruptCompletion(this.value.$Realm, this.joinCondition, this.consequent, this.alternate);
167 } // For convenience, this.consequent.effects should always be defined, but accessing it directly requires
168 // verifying that with an invariant.
169
170
171 get consequentEffects() {
172 (0, _invariant.default)(this.consequent.effects);
173 return this.consequent.effects;
174 }
175
176 get alternateEffects() {
177 (0, _invariant.default)(this.alternate.effects);
178 return this.alternate.effects;
179 }
180
181 updateConsequentKeepingCurrentEffects(newConsequent) {
182 let e = this.consequent.effects;
183 (0, _invariant.default)(e);
184 newConsequent.effects = e.shallowCloneWithResult(newConsequent);
185 this.consequent = newConsequent;
186 return this;
187 }
188
189 updateAlternateKeepingCurrentEffects(newAlternate) {
190 let e = this.alternate.effects;
191 (0, _invariant.default)(e);
192 newAlternate.effects = e.shallowCloneWithResult(newAlternate);
193 this.alternate = newAlternate;
194 return this;
195 }
196
197 toDisplayString() {
198 let superString = super.toDisplayString().slice(0, -1);
199 return superString + " c: [" + this.consequent.toDisplayString() + "] a: [" + this.alternate.toDisplayString() + "]]";
200 }
201
202 containsCompletion(CompletionType) {
203 if (this.consequent instanceof CompletionType) return true;
204 if (this.alternate instanceof CompletionType) return true;
205
206 if (this.consequent instanceof ForkedAbruptCompletion) {
207 if (this.consequent.containsCompletion(CompletionType)) return true;
208 }
209
210 if (this.alternate instanceof ForkedAbruptCompletion) {
211 if (this.alternate.containsCompletion(CompletionType)) return true;
212 }
213
214 return false;
215 }
216
217 containsBreakOrContinue() {
218 if (this.consequent instanceof BreakCompletion || this.consequent instanceof ContinueCompletion) return true;
219 if (this.alternate instanceof BreakCompletion || this.alternate instanceof ContinueCompletion) return true;
220
221 if (this.consequent instanceof ForkedAbruptCompletion) {
222 if (this.consequent.containsBreakOrContinue()) return true;
223 }
224
225 if (this.alternate instanceof ForkedAbruptCompletion) {
226 if (this.alternate.containsBreakOrContinue()) return true;
227 }
228
229 return false;
230 }
231
232 transferChildrenToPossiblyNormalCompletion() {
233 (0, _invariant.default)(this.consequent.value instanceof _index.EmptyValue || this.alternate.value instanceof _index.EmptyValue);
234 return new PossiblyNormalCompletion(this.value.$Realm.intrinsics.empty, this.joinCondition, this.consequent, this.alternate, []);
235 }
236
237} // Possibly normal completions have to be treated like normal completions
238// and are thus never thrown. At the end of a try block or loop body, however,
239// action must be taken to deal with the possibly abrupt case of the completion.
240
241
242exports.ForkedAbruptCompletion = ForkedAbruptCompletion;
243
244class PossiblyNormalCompletion extends NormalCompletion {
245 constructor(value, joinCondition, consequent, alternate, savedPathConditions, savedEffects = undefined) {
246 (0, _invariant.default)(consequent instanceof NormalCompletion || alternate instanceof NormalCompletion);
247 super(value, undefined, consequent.location);
248 this.joinCondition = joinCondition;
249 this.consequent = consequent;
250 this.alternate = alternate;
251 this.savedEffects = savedEffects;
252 this.savedPathConditions = savedPathConditions;
253 }
254
255 shallowCloneWithoutEffects() {
256 let consequentEffects = this.consequentEffects;
257 let alternateEffects = this.alternateEffects;
258 (0, _invariant.default)(this.consequent === consequentEffects.result);
259 (0, _invariant.default)(this.alternate === alternateEffects.result);
260 return new PossiblyNormalCompletion(this.value, this.joinCondition, this.consequent, this.alternate, this.savedPathConditions, this.savedEffects);
261 } // For convenience, this.consequent.effects should always be defined, but accessing it directly requires
262 // verifying that with an invariant.
263
264
265 get consequentEffects() {
266 (0, _invariant.default)(this.consequent.effects);
267 return this.consequent.effects;
268 }
269
270 get alternateEffects() {
271 (0, _invariant.default)(this.alternate.effects);
272 return this.alternate.effects;
273 }
274
275 updateConsequentKeepingCurrentEffects(newConsequent) {
276 if (newConsequent instanceof NormalCompletion) this.value = newConsequent.value;
277 let e = this.consequentEffects;
278 let effects = e.shallowCloneWithResult(newConsequent);
279 this.consequent = effects.result;
280 return this;
281 }
282
283 updateAlternateKeepingCurrentEffects(newAlternate) {
284 if (newAlternate instanceof NormalCompletion) this.value = newAlternate.value;
285 let e = this.alternateEffects;
286 let effects = e.shallowCloneWithResult(newAlternate);
287 this.alternate = effects.result;
288 return this;
289 }
290
291 toDisplayString() {
292 let superString = super.toDisplayString().slice(0, -1);
293 return superString + " c: [" + this.consequent.toDisplayString() + "] a: [" + this.alternate.toDisplayString() + "]]";
294 }
295
296 getNormalCompletion() {
297 let result;
298
299 if (this.alternate instanceof SimpleNormalCompletion) {
300 result = this.alternate;
301 } else if (this.consequent instanceof SimpleNormalCompletion) {
302 result = this.consequent;
303 } else {
304 if (this.alternate instanceof PossiblyNormalCompletion) {
305 result = this.alternate.getNormalCompletion();
306 } else {
307 (0, _invariant.default)(this.consequent instanceof PossiblyNormalCompletion);
308 result = this.consequent.getNormalCompletion();
309 }
310 }
311
312 (0, _invariant.default)(result.value === this.value);
313 return result;
314 }
315
316 containsCompletion(CompletionType) {
317 if (this.consequent instanceof CompletionType) return true;
318 if (this.alternate instanceof CompletionType) return true;
319
320 if (this.consequent instanceof ForkedAbruptCompletion || this.consequent instanceof PossiblyNormalCompletion) {
321 if (this.consequent.containsCompletion(CompletionType)) return true;
322 }
323
324 if (this.alternate instanceof ForkedAbruptCompletion || this.alternate instanceof PossiblyNormalCompletion) {
325 if (this.alternate.containsCompletion(CompletionType)) return true;
326 }
327
328 return false;
329 }
330
331 containsBreakOrContinue() {
332 if (this.consequent instanceof BreakCompletion || this.consequent instanceof ContinueCompletion) return true;
333 if (this.alternate instanceof BreakCompletion || this.alternate instanceof ContinueCompletion) return true;
334
335 if (this.consequent instanceof ForkedAbruptCompletion || this.consequent instanceof PossiblyNormalCompletion) {
336 if (this.consequent.containsBreakOrContinue()) return true;
337 }
338
339 if (this.alternate instanceof ForkedAbruptCompletion || this.alternate instanceof PossiblyNormalCompletion) {
340 if (this.alternate.containsBreakOrContinue()) return true;
341 }
342
343 return false;
344 }
345
346}
347
348exports.PossiblyNormalCompletion = PossiblyNormalCompletion;
349//# sourceMappingURL=completions.js.map
\No newline at end of file