251 lines
11 KiB
JavaScript
251 lines
11 KiB
JavaScript
"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
|