public async start()

in packages/libs/extension/src/main.ts [413:498]


  public async start(extension: Extension, enableDebugger = false): Promise<ChildProcess> {
    const PathVar = getPathVariableName();

    await this.validateExtensionSystemRequirements(extension);
    if (!extension.definition.scripts) {
      throw new MissingStartCommandException(extension);
    }

    const script =
      enableDebugger && extension.definition.scripts.debug
        ? extension.definition.scripts.debug
        : extension.definition.scripts.start;

    // look at the extension for the
    if (!script) {
      throw new MissingStartCommandException(extension);
    }
    const command = cmdlineToArray(script);

    if (command.length === 0) {
      throw new MissingStartCommandException(extension);
    }
    // add each engine into the front of the path.
    const env = { ...process.env };

    // add potential .bin folders (depends on platform and npm version)
    env[PathVar] = `${join(extension.modulePath, "node_modules", ".bin")}${delimiter}${env[PathVar]}`;
    env[PathVar] = `${join(extension.location, "node_modules", ".bin")}${delimiter}${env[PathVar]}`;

    // find appropriate path for interpreter
    switch (command[0].toLowerCase()) {
      case "node":
      case "node.exe":
        command[0] = nodePath;
        break;

      case "python":
      case "python.exe":
      case "python3":
      case "python3.exe":
        await patchPythonPath(command as PythonCommandLine, { version: ">=3.6" });
        break;
    }

    // ensure parameters requiring quotes have them.
    for (let i = 0; i < command.length; i++) {
      command[i] = quoteIfNecessary(command[i]);
    }
    // spawn the command via the shell (since that how npm would have done it anyway.)
    const fullCommandPath = await getFullPath(command[0], env[getPathVariableName()]);
    if (!fullCommandPath) {
      throw new Exception(
        `Unable to resolve full path for executable '${command[0]}' -- (cmdline '${command.join(" ")}')`,
      );
    }

    // == special case ==
    // on Windows, if this command has a space in the name, and it's not an .EXE
    // then we're going to have to add the folder to the PATH
    // and execute it by just the filename
    // and set the path back when we're done.
    if (process.platform === "win32" && fullCommandPath.indexOf(" ") > -1 && !/.exe$/gi.exec(fullCommandPath)) {
      // preserve the current path
      const originalPath = process.env[PathVar];
      try {
        // insert the dir into the path
        process.env[PathVar] = `${dirname(fullCommandPath)}${delimiter}${env[PathVar]}`;

        // call spawn and return
        return spawn(basename(fullCommandPath), command.slice(1), {
          env,
          cwd: extension.modulePath,
          stdio: ["pipe", "pipe", "pipe"],
        });
      } finally {
        // regardless, restore the original path on the way out!
        process.env[PathVar] = originalPath;
      }
    }

    return spawn(fullCommandPath, command.slice(1), {
      env,
      cwd: extension.modulePath,
      stdio: ["pipe", "pipe", "pipe"],
    });
  }