From e48f45f76ee1c26c655ebc30c25622e0208f99d2 Mon Sep 17 00:00:00 2001 From: Michael Rose Date: Fri, 21 May 2021 11:47:49 +0200 Subject: [PATCH] fix(cli-repl): do not throw internal errors for invalid user code MONGOSH-777 --- .../src/js-multiline-to-singleline.ts | 22 +++++++++++++------ packages/cli-repl/src/mongosh-repl.spec.ts | 22 +++++++++++++++++++ 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/packages/cli-repl/src/js-multiline-to-singleline.ts b/packages/cli-repl/src/js-multiline-to-singleline.ts index 7f53b8d5e9..69b5ac44a2 100644 --- a/packages/cli-repl/src/js-multiline-to-singleline.ts +++ b/packages/cli-repl/src/js-multiline-to-singleline.ts @@ -1,7 +1,7 @@ import { transformSync } from '@babel/core'; export function makeMultilineJSIntoSingleLine(src: string): string { - // We use babel without any actual transofmration steps, and only for ASI + // We use babel without any actual transformation steps, and only for ASI // effects here, e.g. turning `return\n42` into `return;\n42;` // since without the added semicolons semantics would be different. // This unfortunately modifies the code in some other ways as well, e.g. @@ -9,12 +9,20 @@ export function makeMultilineJSIntoSingleLine(src: string): string { // important here than keeping aesthetics intact. // It would be nice to have a dedicated package at some point that does // ASI and *only* ASI and leaves the source intact otherwise. - const postASI = transformSync(src, { - retainLines: true, - compact: false, - code: true, - comments: false - })?.code ?? src; + let postASI: string; + try { + postASI = transformSync(src, { + retainLines: true, + compact: false, + code: true, + comments: false + })?.code ?? src; + } catch { + // The src might still be invalid, e.g. because a recoverable error was not fixed + // and is now an unrecoverable error. Best we can do is just keep the lines now. + postASI = src; + } + const asSingleLine = postASI.split(/[\r\n]+/g) .map(line => line.trim()) .join(' ') diff --git a/packages/cli-repl/src/mongosh-repl.spec.ts b/packages/cli-repl/src/mongosh-repl.spec.ts index aacfad15ac..fcbdbdb77f 100644 --- a/packages/cli-repl/src/mongosh-repl.spec.ts +++ b/packages/cli-repl/src/mongosh-repl.spec.ts @@ -308,6 +308,28 @@ describe('MongoshNodeRepl', () => { expect(output).not.to.include('Error'); }); + it('allows to enter and fix recoverable errors', async() => { + input.write('24 %\n'); + await waitEval(bus); + expect(output).to.not.include('Error'); + + input.write('6\n'); + await waitEval(bus); + expect(output).to.include(0); + expect(output).to.not.include('Error'); + }); + + it('behaves correctly on non-recoverable multi-line errors', async() => { + input.write('24 %\n'); + await waitEval(bus); + expect(output).to.not.include('Error'); + + input.write(';\n'); + await waitEval(bus); + expect(output).to.not.include('MongoshInternalError'); + expect(output).to.include('SyntaxError'); + }); + it('pressing Ctrl+C twice exits the shell', async() => { input.write('\u0003'); await tick();