You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					143 lines
				
				4.0 KiB
			
		
		
			
		
	
	
					143 lines
				
				4.0 KiB
			| 
											3 years ago
										 | "use strict"; | ||
|  | 
 | ||
|  | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); | ||
|  | var _assert = _interopRequireDefault(require("assert")); | ||
|  | var _emit = require("./emit"); | ||
|  | var _util = require("util"); | ||
|  | var _util2 = require("./util"); | ||
|  | /** | ||
|  |  * Copyright (c) 2014-present, Facebook, Inc. | ||
|  |  * | ||
|  |  * This source code is licensed under the MIT license found in the | ||
|  |  * LICENSE file in the root directory of this source tree. | ||
|  |  */ | ||
|  | 
 | ||
|  | function Entry() { | ||
|  |   _assert["default"].ok(this instanceof Entry); | ||
|  | } | ||
|  | function FunctionEntry(returnLoc) { | ||
|  |   Entry.call(this); | ||
|  |   (0, _util2.getTypes)().assertLiteral(returnLoc); | ||
|  |   this.returnLoc = returnLoc; | ||
|  | } | ||
|  | (0, _util.inherits)(FunctionEntry, Entry); | ||
|  | exports.FunctionEntry = FunctionEntry; | ||
|  | function LoopEntry(breakLoc, continueLoc, label) { | ||
|  |   Entry.call(this); | ||
|  |   var t = (0, _util2.getTypes)(); | ||
|  |   t.assertLiteral(breakLoc); | ||
|  |   t.assertLiteral(continueLoc); | ||
|  |   if (label) { | ||
|  |     t.assertIdentifier(label); | ||
|  |   } else { | ||
|  |     label = null; | ||
|  |   } | ||
|  |   this.breakLoc = breakLoc; | ||
|  |   this.continueLoc = continueLoc; | ||
|  |   this.label = label; | ||
|  | } | ||
|  | (0, _util.inherits)(LoopEntry, Entry); | ||
|  | exports.LoopEntry = LoopEntry; | ||
|  | function SwitchEntry(breakLoc) { | ||
|  |   Entry.call(this); | ||
|  |   (0, _util2.getTypes)().assertLiteral(breakLoc); | ||
|  |   this.breakLoc = breakLoc; | ||
|  | } | ||
|  | (0, _util.inherits)(SwitchEntry, Entry); | ||
|  | exports.SwitchEntry = SwitchEntry; | ||
|  | function TryEntry(firstLoc, catchEntry, finallyEntry) { | ||
|  |   Entry.call(this); | ||
|  |   var t = (0, _util2.getTypes)(); | ||
|  |   t.assertLiteral(firstLoc); | ||
|  |   if (catchEntry) { | ||
|  |     _assert["default"].ok(catchEntry instanceof CatchEntry); | ||
|  |   } else { | ||
|  |     catchEntry = null; | ||
|  |   } | ||
|  |   if (finallyEntry) { | ||
|  |     _assert["default"].ok(finallyEntry instanceof FinallyEntry); | ||
|  |   } else { | ||
|  |     finallyEntry = null; | ||
|  |   } | ||
|  | 
 | ||
|  |   // Have to have one or the other (or both).
 | ||
|  |   _assert["default"].ok(catchEntry || finallyEntry); | ||
|  |   this.firstLoc = firstLoc; | ||
|  |   this.catchEntry = catchEntry; | ||
|  |   this.finallyEntry = finallyEntry; | ||
|  | } | ||
|  | (0, _util.inherits)(TryEntry, Entry); | ||
|  | exports.TryEntry = TryEntry; | ||
|  | function CatchEntry(firstLoc, paramId) { | ||
|  |   Entry.call(this); | ||
|  |   var t = (0, _util2.getTypes)(); | ||
|  |   t.assertLiteral(firstLoc); | ||
|  |   t.assertIdentifier(paramId); | ||
|  |   this.firstLoc = firstLoc; | ||
|  |   this.paramId = paramId; | ||
|  | } | ||
|  | (0, _util.inherits)(CatchEntry, Entry); | ||
|  | exports.CatchEntry = CatchEntry; | ||
|  | function FinallyEntry(firstLoc, afterLoc) { | ||
|  |   Entry.call(this); | ||
|  |   var t = (0, _util2.getTypes)(); | ||
|  |   t.assertLiteral(firstLoc); | ||
|  |   t.assertLiteral(afterLoc); | ||
|  |   this.firstLoc = firstLoc; | ||
|  |   this.afterLoc = afterLoc; | ||
|  | } | ||
|  | (0, _util.inherits)(FinallyEntry, Entry); | ||
|  | exports.FinallyEntry = FinallyEntry; | ||
|  | function LabeledEntry(breakLoc, label) { | ||
|  |   Entry.call(this); | ||
|  |   var t = (0, _util2.getTypes)(); | ||
|  |   t.assertLiteral(breakLoc); | ||
|  |   t.assertIdentifier(label); | ||
|  |   this.breakLoc = breakLoc; | ||
|  |   this.label = label; | ||
|  | } | ||
|  | (0, _util.inherits)(LabeledEntry, Entry); | ||
|  | exports.LabeledEntry = LabeledEntry; | ||
|  | function LeapManager(emitter) { | ||
|  |   _assert["default"].ok(this instanceof LeapManager); | ||
|  |   _assert["default"].ok(emitter instanceof _emit.Emitter); | ||
|  |   this.emitter = emitter; | ||
|  |   this.entryStack = [new FunctionEntry(emitter.finalLoc)]; | ||
|  | } | ||
|  | var LMp = LeapManager.prototype; | ||
|  | exports.LeapManager = LeapManager; | ||
|  | LMp.withEntry = function (entry, callback) { | ||
|  |   _assert["default"].ok(entry instanceof Entry); | ||
|  |   this.entryStack.push(entry); | ||
|  |   try { | ||
|  |     callback.call(this.emitter); | ||
|  |   } finally { | ||
|  |     var popped = this.entryStack.pop(); | ||
|  |     _assert["default"].strictEqual(popped, entry); | ||
|  |   } | ||
|  | }; | ||
|  | LMp._findLeapLocation = function (property, label) { | ||
|  |   for (var i = this.entryStack.length - 1; i >= 0; --i) { | ||
|  |     var entry = this.entryStack[i]; | ||
|  |     var loc = entry[property]; | ||
|  |     if (loc) { | ||
|  |       if (label) { | ||
|  |         if (entry.label && entry.label.name === label.name) { | ||
|  |           return loc; | ||
|  |         } | ||
|  |       } else if (entry instanceof LabeledEntry) { | ||
|  |         // Ignore LabeledEntry entries unless we are actually breaking to
 | ||
|  |         // a label.
 | ||
|  |       } else { | ||
|  |         return loc; | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  |   return null; | ||
|  | }; | ||
|  | LMp.getBreakLoc = function (label) { | ||
|  |   return this._findLeapLocation("breakLoc", label); | ||
|  | }; | ||
|  | LMp.getContinueLoc = function (label) { | ||
|  |   return this._findLeapLocation("continueLoc", label); | ||
|  | }; |