From 7ce9ee0db6120cdc9bcae8c877b92bf788d79820 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Thu, 8 Jul 2021 14:15:08 -0700 Subject: [PATCH] fix: check path is string in pathToFsPath There's a chance this function can be called with a path that is not a string. To catch that, we check if path is of a different type and throw an error if it is. This also adds a couple tests for this function. --- src/node/util.ts | 12 +++++++++-- test/unit/node/util.test.ts | 41 +++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/node/util.ts b/src/node/util.ts index 40ae9cef..2a010f0e 100644 --- a/src/node/util.ts +++ b/src/node/util.ts @@ -10,6 +10,7 @@ import * as path from "path" import safeCompare from "safe-compare" import * as util from "util" import xdgBasedir from "xdg-basedir" +import { getFirstString } from "../common/util" export interface Paths { data: string @@ -457,10 +458,17 @@ enum CharCode { * Taken from vs/base/common/uri.ts. It's not imported to avoid also importing * everything that file imports. */ -export function pathToFsPath(path: string, keepDriveLetterCasing = false): string { +export function pathToFsPath(path: string | string[], keepDriveLetterCasing = false): string { const isWindows = process.platform === "win32" - const uri = { authority: undefined, path, scheme: "file" } + const uri = { authority: undefined, path: getFirstString(path), scheme: "file" } let value: string + + if (typeof uri.path !== "string") { + throw new Error( + `Could not compute fsPath from given uri. Expected path to be of type string, but was of type ${typeof uri.path}.`, + ) + } + if (uri.authority && uri.path.length > 1 && uri.scheme === "file") { // unc path: file://shares/c$/far/boo value = `//${uri.authority}${uri.path}` diff --git a/test/unit/node/util.test.ts b/test/unit/node/util.test.ts index d93cbd37..398d48bf 100644 --- a/test/unit/node/util.test.ts +++ b/test/unit/node/util.test.ts @@ -453,3 +453,44 @@ describe("escapeHtml", () => { ) }) }) + +describe("pathToFsPath", () => { + it("should convert a path to a file system path", () => { + expect(util.pathToFsPath("/foo/bar/baz")).toBe("/foo/bar/baz") + }) + it("should lowercase drive letter casing by default", () => { + expect(util.pathToFsPath("/C:/far/boo")).toBe("c:/far/boo") + }) + it("should keep drive letter casing when set to true", () => { + expect(util.pathToFsPath("/C:/far/bo", true)).toBe("C:/far/bo") + }) + it("should throw an error if a non-string is passed in for path", () => { + expect(() => + util + // @ts-expect-error We need to check other types + .pathToFsPath({}), + ).toThrow( + `Could not compute fsPath from given uri. Expected path to be of type string, but was of type undefined.`, + ) + }) + it("should not throw an error for a string array", () => { + // @ts-expect-error We need to check other types + expect(() => util.pathToFsPath(["/hello/foo", "/hello/bar"]).not.toThrow()) + }) + it("should use the first string in a string array", () => { + expect(util.pathToFsPath(["/hello/foo", "/hello/bar"])).toBe("/hello/foo") + }) + it("should replace / with \\ on Windows", () => { + let ORIGINAL_PLATFORM = process.platform + + Object.defineProperty(process, "platform", { + value: "win32", + }) + + expect(util.pathToFsPath("/C:/far/boo")).toBe("c:\\far\\boo") + + Object.defineProperty(process, "platform", { + value: ORIGINAL_PLATFORM, + }) + }) +})