* Evaluate the code snippet. * * Append it to virtual .ts file, compile, handle compiler errors, compute a diff of the JS, and eval any code that * appears as "added" in the diff.
(options: {
service: Service;
state: EvalState;
input: string;
wrappedErr?: unknown;
/** Enable top-level await but only if the TSNode service allows it. */
enableTopLevelAwait?: boolean;
context: Context | undefined;
/**
* Added so that `evalCode` can be guaranteed *not* to trigger the `isCompletion`
* codepath. However, the `isCompletion` logic is ancient and maybe should be removed entirely.
* Nobody's looked at it in a long time.
*/
overrideIsCompletion?: boolean;
})
| 506 | * appears as "added" in the diff. |
| 507 | */ |
| 508 | function appendCompileAndEvalInput(options: { |
| 509 | service: Service; |
| 510 | state: EvalState; |
| 511 | input: string; |
| 512 | wrappedErr?: unknown; |
| 513 | /** Enable top-level await but only if the TSNode service allows it. */ |
| 514 | enableTopLevelAwait?: boolean; |
| 515 | context: Context | undefined; |
| 516 | /** |
| 517 | * Added so that `evalCode` can be guaranteed *not* to trigger the `isCompletion` |
| 518 | * codepath. However, the `isCompletion` logic is ancient and maybe should be removed entirely. |
| 519 | * Nobody's looked at it in a long time. |
| 520 | */ |
| 521 | overrideIsCompletion?: boolean; |
| 522 | }): AppendCompileAndEvalInputResult { |
| 523 | const { |
| 524 | service, |
| 525 | state, |
| 526 | wrappedErr, |
| 527 | enableTopLevelAwait = false, |
| 528 | context, |
| 529 | overrideIsCompletion, |
| 530 | } = options; |
| 531 | let { input } = options; |
| 532 | |
| 533 | // It's confusing for `{ a: 1 }` to be interpreted as a block statement |
| 534 | // rather than an object literal. So, we first try to wrap it in |
| 535 | // parentheses, so that it will be interpreted as an expression. |
| 536 | // Based on https://github.com/nodejs/node/blob/c2e6822153bad023ab7ebd30a6117dcc049e475c/lib/repl.js#L413-L422 |
| 537 | let wrappedCmd = false; |
| 538 | if (!wrappedErr && /^\s*{/.test(input) && !/;\s*$/.test(input)) { |
| 539 | input = `(${input.trim()})\n`; |
| 540 | wrappedCmd = true; |
| 541 | } |
| 542 | |
| 543 | const lines = state.lines; |
| 544 | const isCompletion = overrideIsCompletion ?? !/\n$/.test(input); |
| 545 | const undo = appendToEvalState(state, input); |
| 546 | let output: string; |
| 547 | |
| 548 | // Based on https://github.com/nodejs/node/blob/92573721c7cff104ccb82b6ed3e8aa69c4b27510/lib/repl.js#L457-L461 |
| 549 | function adjustUseStrict(code: string) { |
| 550 | // "void 0" keeps the repl from returning "use strict" as the result |
| 551 | // value for statements and declarations that don't return a value. |
| 552 | return code.replace(/^"use strict";/, '"use strict"; void 0;'); |
| 553 | } |
| 554 | |
| 555 | try { |
| 556 | output = service.compile(state.input, state.path, -lines); |
| 557 | } catch (err) { |
| 558 | undo(); |
| 559 | |
| 560 | if (wrappedCmd) { |
| 561 | if (err instanceof TSError && err.diagnosticCodes[0] === 2339) { |
| 562 | // Ensure consistent and more sane behavior between { a: 1 }['b'] and ({ a: 1 }['b']) |
| 563 | throw err; |
| 564 | } |
| 565 | // Unwrap and try again |
no test coverage detected
searching dependent graphs…