diff options
Diffstat (limited to 'js/repl.ts')
-rw-r--r-- | js/repl.ts | 197 |
1 files changed, 0 insertions, 197 deletions
diff --git a/js/repl.ts b/js/repl.ts deleted file mode 100644 index 966e809e8..000000000 --- a/js/repl.ts +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. -import { close } from "./files.ts"; -import { exit } from "./os.ts"; -import { window } from "./window.ts"; -import { core } from "./core.ts"; -import { formatError } from "./format_error.ts"; -import { stringifyArgs } from "./console.ts"; -import * as dispatch from "./dispatch.ts"; -import { sendSync, sendAsync } from "./dispatch_json.ts"; - -const { console } = window; - -/** - * REPL logging. - * In favor of console.log to avoid unwanted indentation - */ -function replLog(...args: unknown[]): void { - core.print(stringifyArgs(args) + "\n"); -} - -/** - * REPL logging for errors. - * In favor of console.error to avoid unwanted indentation - */ -function replError(...args: unknown[]): void { - core.print(stringifyArgs(args) + "\n", true); -} - -const helpMsg = [ - "_ Get last evaluation result", - "_error Get last thrown error", - "exit Exit the REPL", - "help Print this help message" -].join("\n"); - -const replCommands = { - exit: { - get(): void { - exit(0); - } - }, - help: { - get(): string { - return helpMsg; - } - } -}; - -function startRepl(historyFile: string): number { - return sendSync(dispatch.OP_REPL_START, { historyFile }); -} - -// @internal -export async function readline(rid: number, prompt: string): Promise<string> { - return sendAsync(dispatch.OP_REPL_READLINE, { rid, prompt }); -} - -// Error messages that allow users to continue input -// instead of throwing an error to REPL -// ref: https://github.com/v8/v8/blob/master/src/message-template.h -// TODO(kevinkassimo): this list might not be comprehensive -const recoverableErrorMessages = [ - "Unexpected end of input", // { or [ or ( - "Missing initializer in const declaration", // const a - "Missing catch or finally after try", // try {} - "missing ) after argument list", // console.log(1 - "Unterminated template literal" // `template - // TODO(kevinkassimo): need a parser to handling errors such as: - // "Missing } in template expression" // `${ or `${ a 123 }` -]; - -function isRecoverableError(e: Error): boolean { - return recoverableErrorMessages.includes(e.message); -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type Value = any; - -let lastEvalResult: Value = undefined; -let lastThrownError: Value = undefined; - -// Evaluate code. -// Returns true if code is consumed (no error/irrecoverable error). -// Returns false if error is recoverable -function evaluate(code: string): boolean { - const [result, errInfo] = core.evalContext(code); - if (!errInfo) { - lastEvalResult = result; - replLog(result); - } else if (errInfo.isCompileError && isRecoverableError(errInfo.thrown)) { - // Recoverable compiler error - return false; // don't consume code. - } else { - lastThrownError = errInfo.thrown; - if (errInfo.isNativeError) { - const formattedError = formatError( - core.errorToJSON(errInfo.thrown as Error) - ); - replError(formattedError); - } else { - replError("Thrown:", errInfo.thrown); - } - } - return true; -} - -// @internal -export async function replLoop(): Promise<void> { - Object.defineProperties(window, replCommands); - - const historyFile = "deno_history.txt"; - const rid = startRepl(historyFile); - - const quitRepl = (exitCode: number): void => { - // Special handling in case user calls deno.close(3). - try { - close(rid); // close signals Drop on REPL and saves history. - } catch {} - exit(exitCode); - }; - - // Configure window._ to give the last evaluation result. - Object.defineProperty(window, "_", { - configurable: true, - get: (): Value => lastEvalResult, - set: (value: Value): Value => { - Object.defineProperty(window, "_", { - value: value, - writable: true, - enumerable: true, - configurable: true - }); - console.log("Last evaluation result is no longer saved to _."); - } - }); - - // Configure window._error to give the last thrown error. - Object.defineProperty(window, "_error", { - configurable: true, - get: (): Value => lastThrownError, - set: (value: Value): Value => { - Object.defineProperty(window, "_error", { - value: value, - writable: true, - enumerable: true, - configurable: true - }); - console.log("Last thrown error is no longer saved to _error."); - } - }); - - while (true) { - let code = ""; - // Top level read - try { - code = await readline(rid, "> "); - if (code.trim() === "") { - continue; - } - } catch (err) { - if (err.message === "EOF") { - quitRepl(0); - } else { - // If interrupted, don't print error. - if (err.message !== "Interrupted") { - // e.g. this happens when we have deno.close(3). - // We want to display the problem. - const formattedError = formatError(core.errorToJSON(err)); - replError(formattedError); - } - // Quit REPL anyways. - quitRepl(1); - } - } - // Start continued read - while (!evaluate(code)) { - code += "\n"; - try { - code += await readline(rid, " "); - } catch (err) { - // If interrupted on continued read, - // abort this read instead of quitting. - if (err.message === "Interrupted") { - break; - } else if (err.message === "EOF") { - quitRepl(0); - } else { - // e.g. this happens when we have deno.close(3). - // We want to display the problem. - const formattedError = formatError(core.errorToJSON(err)); - replError(formattedError); - quitRepl(1); - } - } - } - } -} |