"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = function (ast, strictCode, env, realm) { var blockRes = env.evaluateCompletionDeref(ast.block, strictCode); var handlerRes = blockRes; var handler = ast.handler; if (handler) { // The start of the catch handler is a join point where all throw completions come together blockRes = _singletons.Functions.incorporateSavedCompletion(realm, blockRes); if (blockRes instanceof _completions.ThrowCompletion) { handlerRes = env.evaluateCompletionDeref(handler, strictCode, blockRes); // Note: The handler may have introduced new forks } else if (blockRes instanceof _completions.JoinedAbruptCompletions || blockRes instanceof _completions.PossiblyNormalCompletion) { if (blockRes instanceof _completions.PossiblyNormalCompletion) { // Nothing has been joined and we are going to keep it that way. // The current state may have advanced since the time control forked into the various paths recorded in blockRes. // Update the normal path and restore the global state to what it was at the time of the fork. var subsequentEffects = realm.getCapturedEffects(blockRes, blockRes.value); (0, _invariant2.default)(subsequentEffects !== undefined); realm.stopEffectCaptureAndUndoEffects(blockRes); _singletons.Join.updatePossiblyNormalCompletionWithSubsequentEffects(realm, blockRes, subsequentEffects); } // All of the forked threads of control are now joined together and the global state reflects their joint effects var handlerEffects = composeNestedThrowEffectsWithHandler(blockRes); handlerRes = handlerEffects[0]; if (handlerRes instanceof _index2.Value) { // This can happen if all of the abrupt completions in blockRes were throw completions // and if the handler does not introduce any abrupt completions of its own. realm.applyEffects(handlerEffects); // The global state is now all joined up } else { // more than thread of control leaves the handler // The effects of each thread is tracked in handlerRes } } else { // The handler is not invoked, so just carry on. } } var finalizerRes = handlerRes; if (ast.finalizer) { // The start of the finalizer is a join point where all threads of control come together. // However, we choose to keep the threads unjoined and to apply the finalizer separately to each thread. if (blockRes instanceof _completions.PossiblyNormalCompletion || blockRes instanceof _completions.JoinedAbruptCompletions) { // The current global state is a the point of the fork that led to blockRes // All subsequent effects are kept inside the branches of blockRes. var finalizerEffects = composeNestedEffectsWithFinalizer(blockRes); finalizerRes = finalizerEffects[0]; // The result may become abrupt because of the finalizer, but it cannot become normal. (0, _invariant2.default)(!(finalizerRes instanceof _index2.Value)); } else { // A single thread of control has produced a normal blockRes and the global state is up to date. finalizerRes = env.evaluateCompletion(ast.finalizer, strictCode); } } if (finalizerRes instanceof _completions.AbruptCompletion) throw finalizerRes; if (finalizerRes instanceof _completions.PossiblyNormalCompletion) realm.composeWithSavedCompletion(finalizerRes); if (handlerRes instanceof _completions.PossiblyNormalCompletion) handlerRes = handlerRes.value; if (handlerRes instanceof _index2.Value) return (0, _index.UpdateEmpty)(realm, handlerRes, realm.intrinsics.undefined); throw handlerRes; // The handler is a potential join point for all throw completions, but is easier to not do the join here because // it is tricky to join the joined and composed result of the throw completions with the non exceptional completions. // Unfortunately, things are still complicated because the handler may turn abrupt completions into normal // completions and the other way around. When this happens the container has to change its type. // We do this by call joinEffects to create a new container at every level of the recursion. function composeNestedThrowEffectsWithHandler(c) { var priorEffects = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; var consequent = c.consequent; var consequentEffects = c.consequentEffects; priorEffects.push(consequentEffects); if (consequent instanceof _completions.JoinedAbruptCompletions || consequent instanceof _completions.PossiblyNormalCompletion) { consequentEffects = composeNestedThrowEffectsWithHandler(consequent, priorEffects); } else if (consequent instanceof _completions.ThrowCompletion) { consequentEffects = realm.evaluateForEffects(function () { var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = priorEffects[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var priorEffect = _step.value; realm.applyEffects(priorEffect); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } (0, _invariant2.default)(ast.handler); return env.evaluateCompletionDeref(ast.handler, strictCode, consequent); }); } priorEffects.pop(); var alternate = c.alternate; var alternateEffects = c.alternateEffects; priorEffects.push(alternateEffects); if (alternate instanceof _completions.PossiblyNormalCompletion || alternate instanceof _completions.JoinedAbruptCompletions) { alternateEffects = composeNestedThrowEffectsWithHandler(alternate, priorEffects); } else if (alternate instanceof _completions.ThrowCompletion) { alternateEffects = realm.evaluateForEffects(function () { var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = priorEffects[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var priorEffect = _step2.value; realm.applyEffects(priorEffect); } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } (0, _invariant2.default)(ast.handler); return env.evaluateCompletionDeref(ast.handler, strictCode, alternate); }); } priorEffects.pop(); return _singletons.Join.joinEffects(realm, c.joinCondition, consequentEffects, alternateEffects); } // The finalizer is not a join point, so update each path in the completion separately. // Things are complicated because the finalizer may turn normal completions into abrupt completions. // When this happens the container has to change its type. // We do this by call joinEffects to create a new container at every level of the recursion. function composeNestedEffectsWithFinalizer(c) { var priorEffects = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; var consequent = c.consequent; var consequentEffects = c.consequentEffects; priorEffects.push(consequentEffects); if (consequent instanceof _completions.JoinedAbruptCompletions || consequent instanceof _completions.PossiblyNormalCompletion) { consequentEffects = composeNestedThrowEffectsWithHandler(consequent, priorEffects); } else { consequentEffects = realm.evaluateForEffects(function () { var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = priorEffects[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var priorEffect = _step3.value; realm.applyEffects(priorEffect); } } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } (0, _invariant2.default)(ast.finalizer); return env.evaluateCompletionDeref(ast.finalizer, strictCode); }); if (!(consequentEffects[0] instanceof _completions.AbruptCompletion)) consequentEffects[0] = consequent; } priorEffects.pop(); var alternate = c.alternate; var alternateEffects = c.alternateEffects; priorEffects.push(alternateEffects); if (alternate instanceof _completions.PossiblyNormalCompletion || alternate instanceof _completions.JoinedAbruptCompletions) { alternateEffects = composeNestedThrowEffectsWithHandler(alternate, priorEffects); } else { alternateEffects = realm.evaluateForEffects(function () { var _iteratorNormalCompletion4 = true; var _didIteratorError4 = false; var _iteratorError4 = undefined; try { for (var _iterator4 = priorEffects[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { var priorEffect = _step4.value; realm.applyEffects(priorEffect); } } catch (err) { _didIteratorError4 = true; _iteratorError4 = err; } finally { try { if (!_iteratorNormalCompletion4 && _iterator4.return) { _iterator4.return(); } } finally { if (_didIteratorError4) { throw _iteratorError4; } } } (0, _invariant2.default)(ast.finalizer); return env.evaluateCompletionDeref(ast.finalizer, strictCode); }); if (!(alternateEffects[0] instanceof _completions.AbruptCompletion)) alternateEffects[0] = alternate; } priorEffects.pop(); return _singletons.Join.joinEffects(realm, c.joinCondition, consequentEffects, alternateEffects); } }; require("../environment.js"); var _completions = require("../completions.js"); var _index = require("../methods/index.js"); var _singletons = require("../singletons.js"); var _index2 = require("../values/index.js"); var _invariant = require("../invariant.js"); var _invariant2 = _interopRequireDefault(_invariant); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } //# sourceMappingURL=TryStatement.js.map