From cc97a4dd2a967e1c2273bd5f4c5f49a5bf2e2585 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 27 Mar 2019 21:01:33 +0100 Subject: remove node_modules --- node_modules/tslib/docs/generator.md | 486 ----------------------------------- 1 file changed, 486 deletions(-) delete mode 100644 node_modules/tslib/docs/generator.md (limited to 'node_modules/tslib/docs') diff --git a/node_modules/tslib/docs/generator.md b/node_modules/tslib/docs/generator.md deleted file mode 100644 index 88ffb08e2..000000000 --- a/node_modules/tslib/docs/generator.md +++ /dev/null @@ -1,486 +0,0 @@ -# The `__generator` helper - -The `__generator` helper is a function designed to support TypeScript's down-level emit for -async functions when targeting ES5 and earlier. But how, exactly, does it work? - -Here's the body of the `__generator` helper: - -```js -__generator = function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t; - return { next: verb(0), "throw": verb(1), "return": verb(2) }; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [0, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -``` - -And here's an example of it in use: - -```ts -// source -async function func(x) { - try { - await x; - } - catch (e) { - console.error(e); - } - finally { - console.log("finally"); - } -} - -// generated -function func(x) { - return __awaiter(this, void 0, void 0, function () { - var e_1; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - _a.trys.push([0, 1, 3, 4]); - return [4 /*yield*/, x]; - case 1: - _a.sent(); - return [3 /*break*/, 4]; - case 2: - e_1 = _a.sent(); - console.error(e_1); - return [3 /*break*/, 4]; - case 3: - console.log("finally"); - return [7 /*endfinally*/]; - case 4: return [2 /*return*/]; - } - }); - }); -} -``` - -There is a lot going on in this function, so the following will break down what each part of the -`__generator` helper does and how it works. - -# Opcodes - -The `__generator` helper uses opcodes which represent various operations that are interpreted by -the helper to affect its internal state. The following table lists the various opcodes, their -arguments, and their purpose: - -| Opcode | Arguments | Purpose | -|----------------|-----------|--------------------------------------------------------------------------------------------------------------------------------| -| 0 (next) | *value* | Starts the generator, or resumes the generator with *value* as the result of the `AwaitExpression` where execution was paused. | -| 1 (throw) | *value* | Resumes the generator, throwing *value* at `AwaitExpression` where execution was paused. | -| 2 (return) | *value* | Exits the generator, executing any `finally` blocks starting at the `AwaitExpression` where execution was paused. | -| 3 (break) | *label* | Performs an unconditional jump to the specified label, executing any `finally` between the current instruction and the label. | -| 4 (yield) | *value* | Suspends the generator, setting the resume point at the next label and yielding the value. | -| 5 (yieldstar) | *value* | Suspends the generator, setting the resume point at the next label and delegating operations to the supplied value. | -| 6 (catch) | *error* | An internal instruction used to indicate an exception that was thrown from the body of the generator. | -| 7 (endfinally) | | Exits a finally block, resuming any previous operation (such as a break, return, throw, etc.) | - -# State -The `_`, `f`, `y`, and `t` variables make up the persistent state of the `__generator` function. Each variable -has a specific purpose, as described in the following sections: - -## The `_` variable -The `__generator` helper must share state between its internal `step` orchestration function and -the `body` function passed to the helper. - -```ts -var _ = { - label: 0, - sent: function() { - if (t[0] & 1) // NOTE: true for `throw`, but not `next` or `catch` - throw t[1]; - return sent[1]; - }, - trys: [], - ops: [] -}; -``` - -The following table describes the members of the `_` state object and their purpose: - -| Name | Description | -|---------|---------------------------------------------------------------------------------------------------------------------------| -| `label` | Specifies the next switch case to execute in the `body` function. | -| `sent` | Handles the completion result passed to the generator. | -| `trys` | A stack of **Protected Regions**, which are 4-tuples that describe the labels that make up a `try..catch..finally` block. | -| `ops` | A stack of pending operations used for `try..finally` blocks. | - -The `__generator` helper passes this state object to the `body` function for use with switching -between switch cases in the body, handling completions from `AwaitExpression`, etc. - -## The `f` variable -The `f` variable indicates whether the generator is currently executing, to prevent re-entry of -the same generator during its execution. - -## The `y` variable -The `y` variable stores the iterator passed to a `yieldstar` instruction to which operations should be delegated. - -## The `t` variable -The `t` variable is a temporary variable that stores one of the following values: - -- The completion value when resuming from a `yield` or `yield*`. -- The error value for a catch block. -- The current **Protected Region**. -- The verb (`next`, `throw`, or `return` method) to delegate to the expression of a `yield*`. -- The result of evaluating the verb delegated to the expression of a `yield*`. - -> NOTE: None of the above cases overlap. - -# Protected Regions -A **Protected Region** is a region within the `body` function that indicates a -`try..catch..finally` statement. It consists of a 4-tuple that contains 4 labels: - -| Offset | Description | -|--------|-----------------------------------------------------------------------------------------| -| 0 | *Required* The label that indicates the beginning of a `try..catch..finally` statement. | -| 1 | *Optional* The label that indicates the beginning of a `catch` clause. | -| 2 | *Optional* The label that indicates the beginning of a `finally` clause. | -| 3 | *Required* The label that indicates the end of the `try..catch..finally` statement. | - -# The generator object -The final step of the `__generator` helper is the allocation of an object that implements the -`Generator` protocol, to be used by the `__awaiter` helper: - -```ts -return { next: verb(0), "throw": verb(1), "return": verb(2) }; -function verb(n) { return function (v) { return step([n, v]); }; } -``` - -This object translates calls to `next`, `throw`, and `return` to the appropriate Opcodes and -invokes the `step` orchestration function to continue execution. The `throw` and `return` method -names are quoted to better support ES3. - -# Orchestration -The `step` function is the main orechestration mechanism for the `__generator` helper. It -interprets opcodes, handles **protected regions**, and communicates results back to the caller. - -Here's a closer look at the `step` function: - -```ts -function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [0, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; -} -``` - -The main body of `step` exists in a `while` loop. This allows us to continually interpret -operations until we have reached some completion value, be it a `return`, `await`, or `throw`. - -## Preventing re-entry -The first part of the `step` function is used as a check to prevent re-entry into a currently -executing generator: - -```ts -if (f) throw new TypeError("Generator is already executing."); -``` - -## Running the generator -The main body of the `step` function consists of a `while` loop which continues to evaluate -instructions until the generator exits or is suspended: - -```ts -while (_) try ... -``` - -When the generator has run to completion, the `_` state variable will be cleared, forcing the loop -to exit. - -## Evaluating the generator body. -```ts -try { - ... - op = body.call(thisArg, _); -} -catch (e) { - op = [6, e]; - y = 0; -} -finally { - f = t = 0; -} -``` - -Depending on the current operation, we re-enter the generator body to start or continue execution. -Here we invoke `body` with `thisArg` as the `this` binding and the `_` state object as the only -argument. The result is a tuple that contains the next Opcode and argument. - -If evaluation of the body resulted in an exception, we convert this into an Opcode 6 ("catch") -operation to be handled in the next spin of the `while` loop. We also clear the `y` variable in -case it is set to ensure we are no longer delegating operations as the exception occurred in -user code *outside* of, or at the function boundary of, the delegated iterator (otherwise the -iterator would have handled the exception itself). - -After executing user code, we clear the `f` flag that indicates we are executing the generator, -as well as the `t` temporary value so that we don't hold onto values sent to the generator for -longer than necessary. - -Inside of the `try..finally` statement are a series of statements that are used to evaluate the -operations of the transformed generator body. - -The first thing we do is mark the generator as executing: - -```ts -if (f = 1, ...) -``` - -Despite the fact this expression is part of the head of an `if` statement, the comma operator -causes it to be evaluated and the result thrown out. This is a minification added purely to -reduce the overall footprint of the helper. - -## Delegating `yield*` - -The first two statements of the `try..finally` statement handle delegation for `yield*`: - -```ts -if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; -if (y = 0, t) op = [0, t.value]; -``` - -If the `y` variable is set, and `y` has a `next`, `throw`, or `return` method (depending on the -current operation), we invoke this method and store the return value (an IteratorResult) in `t`. - -If `t` indicates it is a yielded value (e.g. `t.done === false`), we return `t` to the caller. -If `t` indicates it is a returned value (e.g. `t.done === true`), we mark the operation with the -`next` Opcode, and the returned value. -If `y` did not have the appropriate method, or `t` was a returned value, we reset `y` to a falsey -value and continue processing the operation. - -## Handling operations - -The various Opcodes are handled in the following switch statement: - -```ts -switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; -} -``` - -The following sections describe the various Opcodes: - -### Opcode 0 ("next") and Opcode 1 ("throw") -```ts -case 0: // next -case 1: // throw - t = op; - break; -``` - -Both Opcode 0 ("next") and Opcode 1 ("throw") have the same behavior. The current operation is -stored in the `t` variable and the `body` function is invoked. The `body` function should call -`_.sent()` which will evaluate the appropriate completion result. - -### Opcode 4 ("yield") -```ts -case 4: // yield - _.label++; - return { value: op[1], done: false }; -``` - -When we encounter Opcode 4 ("yield"), we increment the label by one to indicate the point at which -the generator will resume execution. We then return an `IteratorResult` whose `value` is the -yielded value, and `done` is `false`. - -### Opcode 5 ("yieldstar") -```ts -case 5: // yieldstar - _.label++; - y = op[1]; - op = [0]; - continue; -``` - -When we receive Opcode 5 ("yieldstar"), we increment the label by one to indicate the point at which -the generator will resume execution. We then store the iterator in `op[1]` in the `y` variable, and -set the operation to delegate to Opcode 0 ("next") with no value. Finally, we continue execution at -the top of the loop to start delegation. - -### Opcode 7 ("endfinally") -```ts -case 7: - op = _.ops.pop(); - _.trys.pop(); - continue; -``` - -Opcode 7 ("endfinally") indicates that we have hit the end of a `finally` clause, and that the last -operation recorded before entering the `finally` block should be evaluated. - -### Opcode 2 ("return"), Opcode 3 ("break"), and Opcode 6 ("catch") -```ts -default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { - _ = 0; - continue; - } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { - _.label = op[1]; - break; - } - if (op[0] === 6 && _.label < t[1]) { - _.label = t[1]; - t = op; - break; - } - if (t && _.label < t[2]) { - _.label = t[2]; - _.ops.push(op); - break; - } - if (t[2]) - _.ops.pop(); - _.trys.pop(); - continue; -} -``` - -The handling for Opcode 2 ("return"), Opcode 3 ("break") and Opcode 6 ("catch") is more -complicated, as we must obey the specified runtime semantics of generators. The first line in this -clause gets the current **Protected Region** if found and stores it in the `t` temp variable: - -```ts -if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && ...) ... -``` - -The remainder of this statement, as well as the following by several `if` statements test for more -complex conditions. The first of these is the following: - -```ts -if (!(t = ...) && (op[0] === 6 || op[0] === 2)) { - _ = 0; - continue; -} -``` - -If we encounter an Opcode 6 ("catch") or Opcode 2 ("return"), and we are not in a protected region, -then this operation completes the generator by setting the `_` variable to a falsey value. The -`continue` statement resumes execution at the top of the `while` statement, which will exit the loop -so that we continue execution at the statement following the loop. - -```ts -if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { - _.label = op[1]; - break; -} -``` - -The `if` statement above handles Opcode 3 ("break") when we are either not in a **protected region**, or -are performing an unconditional jump to a label inside of the current **protected region**. In this case -we can unconditionally jump to the specified label. - -```ts -if (op[0] === 6 && _.label < t[1]) { - _.label = t[1]; - t = op; - break; -} -``` - -The `if` statement above handles Opcode 6 ("catch") when inside the `try` block of a **protected -region**. In this case we jump to the `catch` block, if present. We replace the value of `t` with -the operation so that the exception can be read as the first statement of the transformed `catch` -clause of the transformed generator body. - -```ts -if (t && _.label < t[2]) { - _.label = t[2]; - _.ops.push(op); - break; -} -``` - -This `if` statement handles all Opcodes when in a **protected region** with a `finally` clause. -As long as we are not already inside the `finally` clause, we jump to the `finally` clause and -push the pending operation onto the `_.ops` stack. This allows us to resume execution of the -pending operation once we have completed execution of the `finally` clause, as long as it does not -supersede this operation with its own completion value. - -```ts -if (t[2]) - _.ops.pop(); -``` - -Any other completion value inside of a `finally` clause will supersede the pending completion value -from the `try` or `catch` clauses. The above `if` statement pops the pending completion from the -stack. - -```ts -_.trys.pop(); -continue; -``` - -The remaining statements handle the point at which we exit a **protected region**. Here we pop the -current **protected region** from the stack and spin the `while` statement to evaluate the current -operation again in the next **protected region** or at the function boundary. - -## Handling a completed generator -Once the generator has completed, the `_` state variable will be falsey. As a result, the `while` -loop will terminate and hand control off to the final statement of the orchestration function, -which deals with how a completed generator is evaluated: - -```ts -if (op[0] & 5) - throw op[1]; -return { value: op[0] ? op[1] : void 0, done: true }; -``` - -If the caller calls `throw` on the generator it will send Opcode 1 ("throw"). If an exception -is uncaught within the body of the generator, it will send Opcode 6 ("catch"). As the generator has -completed, it throws the exception. Both of these cases are caught by the bitmask `5`, which does -not collide with the only two other valid completion Opcodes. - -If the caller calls `next` on the generator, it will send Opcode 0 ("next"). As the generator has -completed, it returns an `IteratorResult` where `value` is `undefined` and `done` is true. - -If the caller calls `return` on the generator, it will send Opcode 2 ("return"). As the generator -has completed, it returns an `IteratorResult` where `value` is the value provided to `return`, and -`done` is true. \ No newline at end of file -- cgit v1.2.3