From 3b56501535c0cd2f39114c91295524caf5b30beb Mon Sep 17 00:00:00 2001 From: Sam Date: Wed, 22 Jan 2020 11:08:58 -0800 Subject: [PATCH] Add shell debugging and fix timeout issue --- CHANGELOG.md | 2 ++ src/commands/functions-shell.js | 4 +++- src/emulator/commandUtils.ts | 17 +++++++++++++++++ src/emulator/controller.ts | 16 ++-------------- src/emulator/functionsEmulator.ts | 7 +++++++ src/functionsShellCommandAction.js | 8 ++++++++ 6 files changed, 39 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e69de29bb2d..ef8dd190cab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -0,0 +1,2 @@ +* Adds breakpoint debugging to `functions:shell` (#1872) +* Removes function timeouts when breakpoint debugging is enabled (#1931) \ No newline at end of file diff --git a/src/commands/functions-shell.js b/src/commands/functions-shell.js index 932ec5daa8f..363562721bc 100644 --- a/src/commands/functions-shell.js +++ b/src/commands/functions-shell.js @@ -4,10 +4,12 @@ var { Command } = require("../command"); var { requirePermissions } = require("../requirePermissions"); var action = require("../functionsShellCommandAction"); var requireConfig = require("../requireConfig"); +var commandUtils = require("../emulator/commandUtils"); module.exports = new Command("functions:shell") .description("launch full Node shell with emulated functions") - .option("-p, --port ", "the port on which to emulate functions (default: 5000)", 5000) + .option("-p, --port ", "the port on which to emulate functions", 5000) + .option(commandUtils.FLAG_INSPECT_FUNCTIONS, commandUtils.DESC_INSPECT_FUNCTIONS) .before(requireConfig) .before(requirePermissions) .action(action); diff --git a/src/emulator/commandUtils.ts b/src/emulator/commandUtils.ts index 2461faf7226..8c83e1ba220 100644 --- a/src/emulator/commandUtils.ts +++ b/src/emulator/commandUtils.ts @@ -6,6 +6,7 @@ import * as logger from "../logger"; import requireAuth = require("../requireAuth"); import requireConfig = require("../requireConfig"); import { Emulators } from "../emulator/types"; +import { FirebaseError } from "../error"; export const FLAG_ONLY: string = "--only "; export const DESC_ONLY: string = @@ -55,3 +56,19 @@ export async function beforeEmulatorCommand(options: any): Promise { await requireConfig(options); } } + +export function parseInspectionPort(options: any): number { + let port = options.inspectFunctions; + if (port === true) { + port = "9229"; + } + + const parsed = Number(port); + if (isNaN(parsed) || parsed < 1024 || parsed > 65535) { + throw new FirebaseError( + `"${port}" is not a valid port for debugging, please pass an integer between 1024 and 65535.` + ); + } + + return parsed; +} diff --git a/src/emulator/controller.ts b/src/emulator/controller.ts index 51a90378b80..97366a29d12 100644 --- a/src/emulator/controller.ts +++ b/src/emulator/controller.ts @@ -16,6 +16,7 @@ import { HostingEmulator } from "../emulator/hostingEmulator"; import { FirebaseError } from "../error"; import * as getProjectId from "../getProjectId"; import { PubsubEmulator } from "./pubsubEmulator"; +import * as commandUtils from "./commandUtils"; export const VALID_EMULATOR_STRINGS: string[] = ALL_EMULATORS; @@ -133,21 +134,8 @@ export async function startAll(options: any): Promise { ); let inspectFunctions: number | undefined; - - // If the flag is provided without a value, use the Node.js default - if (options.inspectFunctions === true) { - options.inspectFunctions = "9229"; - } - if (options.inspectFunctions) { - inspectFunctions = Number(options.inspectFunctions); - if (isNaN(inspectFunctions) || inspectFunctions < 1024 || inspectFunctions > 65535) { - throw new FirebaseError( - `"${ - options.inspectFunctions - }" is not a valid value for the --inspect-functions flag, please pass an integer between 1024 and 65535.` - ); - } + inspectFunctions = commandUtils.parseInspectionPort(options); // TODO(samstern): Add a link to documentation utils.logLabeledWarning( diff --git a/src/emulator/functionsEmulator.ts b/src/emulator/functionsEmulator.ts index 247e43c1465..35c1bbc4181 100644 --- a/src/emulator/functionsEmulator.ts +++ b/src/emulator/functionsEmulator.ts @@ -115,6 +115,13 @@ export class FunctionsEmulator implements EmulatorInstance { // TODO: Would prefer not to have static state but here we are! EmulatorLogger.verbosity = this.args.quiet ? Verbosity.QUIET : Verbosity.DEBUG; + // When debugging is enabled, the "timeout" feature needs to be disabled so that + // functions don't timeout while a breakpoint is active. + if (this.args.debugPort) { + this.args.disabledRuntimeFeatures = this.args.disabledRuntimeFeatures || {}; + this.args.disabledRuntimeFeatures.timeout = true; + } + const mode = this.args.debugPort ? FunctionsExecutionMode.SEQUENTIAL : FunctionsExecutionMode.AUTO; diff --git a/src/functionsShellCommandAction.js b/src/functionsShellCommandAction.js index 62da640f7b2..ed0d0c8dd29 100644 --- a/src/functionsShellCommandAction.js +++ b/src/functionsShellCommandAction.js @@ -10,15 +10,23 @@ var serveFunctions = require("./serve/functions"); var LocalFunction = require("./localFunction"); var logger = require("./logger"); var shell = require("./emulator/functionsEmulatorShell"); +var commandUtitls = require("./emulator/commandUtils"); module.exports = function(options) { options.port = parseInt(options.port, 10); + + let debugPort = undefined; + if (options.inspectFunctions) { + debugPort = commandUtitls.parseInspectionPort(options); + } + return serveFunctions .start(options, { // TODO(samstern): Note that these are not acctually valid FunctionsEmulatorArgs // and when we eventually move to all TypeScript we'll have to start adding // projectId and functionsDir here. quiet: true, + debugPort, }) .then(function() { return serveFunctions.connect();