diff --git a/src/harness/fakes.ts b/src/harness/fakes.ts index 79d3503cb8079..4fdd30c940e26 100644 --- a/src/harness/fakes.ts +++ b/src/harness/fakes.ts @@ -150,7 +150,7 @@ namespace fakes { private _getStats(path: string) { try { - return this.vfs.statSync(path); + return this.vfs.existsSync(path) ? this.vfs.statSync(path) : undefined; } catch { return undefined; @@ -332,7 +332,7 @@ namespace fakes { let fs = this.vfs; while (fs.shadowRoot) { try { - const shadowRootStats = fs.shadowRoot.statSync(canonicalFileName); + const shadowRootStats = fs.shadowRoot.existsSync(canonicalFileName) && fs.shadowRoot.statSync(canonicalFileName); if (shadowRootStats.dev !== stats.dev || shadowRootStats.ino !== stats.ino || shadowRootStats.mtimeMs !== stats.mtimeMs) { diff --git a/src/harness/vfs.ts b/src/harness/vfs.ts index 4972dd08925e1..34a48f5909104 100644 --- a/src/harness/vfs.ts +++ b/src/harness/vfs.ts @@ -384,6 +384,14 @@ namespace vfs { // POSIX API (aligns with NodeJS "fs" module API) + /** + * Determines whether a path exists. + */ + public existsSync(path: string) { + const result = this._walk(this._resolve(path), /*noFollow*/ true, () => "stop"); + return result !== undefined && result.node !== undefined; + } + /** * Get file status. If `path` is a symbolic link, it is dereferenced. * @@ -861,8 +869,8 @@ namespace vfs { */ private _resolve(path: string) { return this._cwd - ? vpath.resolve(this._cwd, vpath.validate(path, vpath.ValidationFlags.RelativeOrAbsolute)) - : vpath.validate(path, vpath.ValidationFlags.Absolute); + ? vpath.resolve(this._cwd, vpath.validate(path, vpath.ValidationFlags.RelativeOrAbsolute | vpath.ValidationFlags.AllowWildcard)) + : vpath.validate(path, vpath.ValidationFlags.Absolute | vpath.ValidationFlags.AllowWildcard); } private _applyFiles(files: FileSet, dirname: string) { diff --git a/src/harness/vpath.ts b/src/harness/vpath.ts index e2024f890c4c2..6211fc9278a63 100644 --- a/src/harness/vpath.ts +++ b/src/harness/vpath.ts @@ -26,7 +26,9 @@ namespace vpath { const invalidRootComponentRegExp = /^(?!(\/|\/\/\w+\/|[a-zA-Z]:\/?|)$)/; const invalidNavigableComponentRegExp = /[:*?"<>|]/; + const invalidNavigableComponentWithWildcardsRegExp = /[:"<>|]/; const invalidNonNavigableComponentRegExp = /^\.{1,2}$|[:*?"<>|]/; + const invalidNonNavigableComponentWithWildcardsRegExp = /^\.{1,2}$|[:"<>|]/; const extRegExp = /\.\w+$/; export const enum ValidationFlags { @@ -44,6 +46,7 @@ namespace vpath { AllowExtname = 1 << 8, AllowTrailingSeparator = 1 << 9, AllowNavigation = 1 << 10, + AllowWildcard = 1 << 11, /** Path must be a valid directory root */ Root = RequireRoot | AllowRoot | AllowTrailingSeparator, @@ -63,7 +66,9 @@ namespace vpath { const hasDirname = components.length > 2; const hasBasename = components.length > 1; const hasExtname = hasBasename && extRegExp.test(components[components.length - 1]); - const invalidComponentRegExp = flags & ValidationFlags.AllowNavigation ? invalidNavigableComponentRegExp : invalidNonNavigableComponentRegExp; + const invalidComponentRegExp = flags & ValidationFlags.AllowNavigation + ? flags & ValidationFlags.AllowWildcard ? invalidNavigableComponentWithWildcardsRegExp : invalidNavigableComponentRegExp + : flags & ValidationFlags.AllowWildcard ? invalidNonNavigableComponentWithWildcardsRegExp : invalidNonNavigableComponentRegExp; // Validate required components if (flags & ValidationFlags.RequireRoot && !hasRoot) return false;