diff --git a/packages/compiler-cli/ngcc/src/utils.ts b/packages/compiler-cli/ngcc/src/utils.ts index f729abe386..acd7ea69fa 100644 --- a/packages/compiler-cli/ngcc/src/utils.ts +++ b/packages/compiler-cli/ngcc/src/utils.ts @@ -7,7 +7,7 @@ */ import * as ts from 'typescript'; -import {absoluteFrom, AbsoluteFsPath, FileSystem} from '../../src/ngtsc/file_system'; +import {absoluteFrom, AbsoluteFsPath, FileSystem, isRooted} from '../../src/ngtsc/file_system'; import {KnownDeclaration} from '../../src/ngtsc/reflection'; /** @@ -85,10 +85,11 @@ export type PathMappings = { /** * Test whether a path is "relative". * - * Relative paths start with `/`, `./` or `../`; or are simply `.` or `..`. + * Relative paths start with `/`, `./` or `../` (or the Windows equivalents); or are simply `.` or + * `..`. */ export function isRelativePath(path: string): boolean { - return /^\/|^\.\.?($|\/)/.test(path); + return isRooted(path) || /^\.\.?(\/|\\|$)/.test(path); } /** diff --git a/packages/compiler-cli/ngcc/test/dependencies/module_resolver_spec.ts b/packages/compiler-cli/ngcc/test/dependencies/module_resolver_spec.ts index 2ef140ca71..503c157161 100644 --- a/packages/compiler-cli/ngcc/test/dependencies/module_resolver_spec.ts +++ b/packages/compiler-cli/ngcc/test/dependencies/module_resolver_spec.ts @@ -67,16 +67,29 @@ runInEachFileSystem(() => { ]); }); - describe('resolveModule()', () => { + describe('resolveModuleImport()', () => { describe('with relative paths', () => { it('should resolve sibling, child and aunt modules', () => { const resolver = new ModuleResolver(getFileSystem()); + + // With relative file paths. expect(resolver.resolveModuleImport('./x', _('/libs/local-package/index.js'))) .toEqual(new ResolvedRelativeModule(_('/libs/local-package/x.js'))); expect(resolver.resolveModuleImport('./sub-folder', _('/libs/local-package/index.js'))) .toEqual(new ResolvedRelativeModule(_('/libs/local-package/sub-folder/index.js'))); expect(resolver.resolveModuleImport('../x', _('/libs/local-package/sub-folder/index.js'))) .toEqual(new ResolvedRelativeModule(_('/libs/local-package/x.js'))); + + // With absolute file paths. + expect(resolver.resolveModuleImport( + _('/libs/local-package/x'), _('/libs/local-package/index.js'))) + .toEqual(new ResolvedRelativeModule(_('/libs/local-package/x.js'))); + expect(resolver.resolveModuleImport( + _('/libs/local-package/sub-folder'), _('/libs/local-package/index.js'))) + .toEqual(new ResolvedRelativeModule(_('/libs/local-package/sub-folder/index.js'))); + expect(resolver.resolveModuleImport( + _('/libs/local-package/x'), _('/libs/local-package/sub-folder/index.js'))) + .toEqual(new ResolvedRelativeModule(_('/libs/local-package/x.js'))); }); it('should return `null` if the resolved module relative module does not exist', () => { diff --git a/packages/compiler-cli/ngcc/test/utils_spec.ts b/packages/compiler-cli/ngcc/test/utils_spec.ts index f373e5313a..d01b1e3e9a 100644 --- a/packages/compiler-cli/ngcc/test/utils_spec.ts +++ b/packages/compiler-cli/ngcc/test/utils_spec.ts @@ -7,6 +7,8 @@ */ import * as ts from 'typescript'; +import {absoluteFrom as _abs} from '../../src/ngtsc/file_system'; +import {runInEachFileSystem} from '../../src/ngtsc/file_system/testing'; import {KnownDeclaration} from '../../src/ngtsc/reflection'; import {FactoryMap, getTsHelperFnFromDeclaration, getTsHelperFnFromIdentifier, isRelativePath, stripExtension} from '../src/utils'; @@ -167,30 +169,36 @@ describe('getTsHelperFnFromIdentifier()', () => { }); }); -describe('isRelativePath()', () => { - it('should return true for relative paths', () => { - expect(isRelativePath('.')).toBe(true); - expect(isRelativePath('..')).toBe(true); - expect(isRelativePath('./')).toBe(true); - expect(isRelativePath('../')).toBe(true); - expect(isRelativePath('./abc/xyz')).toBe(true); - expect(isRelativePath('../abc/xyz')).toBe(true); - }); +runInEachFileSystem(() => { + describe('isRelativePath()', () => { + it('should return true for relative paths', () => { + expect(isRelativePath('.')).toBe(true); + expect(isRelativePath('..')).toBe(true); + expect(isRelativePath('./')).toBe(true); + expect(isRelativePath('.\\')).toBe(true); + expect(isRelativePath('../')).toBe(true); + expect(isRelativePath('..\\')).toBe(true); + expect(isRelativePath('./abc/xyz')).toBe(true); + expect(isRelativePath('.\\abc\\xyz')).toBe(true); + expect(isRelativePath('../abc/xyz')).toBe(true); + expect(isRelativePath('..\\abc\\xyz')).toBe(true); + }); - it('should return true for absolute paths', () => { - expect(isRelativePath('/')).toBe(true); - expect(isRelativePath('/abc/xyz')).toBe(true); - }); + it('should return true for absolute paths', () => { + expect(isRelativePath(_abs('/'))).toBe(true); + expect(isRelativePath(_abs('/abc/xyz'))).toBe(true); + }); - it('should return false for other paths', () => { - expect(isRelativePath('abc')).toBe(false); - expect(isRelativePath('abc/xyz')).toBe(false); - expect(isRelativePath('.abc')).toBe(false); - expect(isRelativePath('..abc')).toBe(false); - expect(isRelativePath('@abc')).toBe(false); - expect(isRelativePath('.abc/xyz')).toBe(false); - expect(isRelativePath('..abc/xyz')).toBe(false); - expect(isRelativePath('@abc/xyz')).toBe(false); + it('should return false for other paths', () => { + expect(isRelativePath('abc')).toBe(false); + expect(isRelativePath('abc/xyz')).toBe(false); + expect(isRelativePath('.abc')).toBe(false); + expect(isRelativePath('..abc')).toBe(false); + expect(isRelativePath('@abc')).toBe(false); + expect(isRelativePath('.abc/xyz')).toBe(false); + expect(isRelativePath('..abc/xyz')).toBe(false); + expect(isRelativePath('@abc/xyz')).toBe(false); + }); }); }); diff --git a/packages/compiler-cli/src/ngtsc/file_system/index.ts b/packages/compiler-cli/src/ngtsc/file_system/index.ts index 594af21923..2bf3079757 100644 --- a/packages/compiler-cli/src/ngtsc/file_system/index.ts +++ b/packages/compiler-cli/src/ngtsc/file_system/index.ts @@ -7,7 +7,7 @@ */ export {CachedFileSystem} from './src/cached_file_system'; export {NgtscCompilerHost} from './src/compiler_host'; -export {absoluteFrom, absoluteFromSourceFile, basename, dirname, getFileSystem, isRoot, join, relative, relativeFrom, resolve, setFileSystem} from './src/helpers'; +export {absoluteFrom, absoluteFromSourceFile, basename, dirname, getFileSystem, isRoot, isRooted, join, relative, relativeFrom, resolve, setFileSystem} from './src/helpers'; export {LogicalFileSystem, LogicalProjectPath} from './src/logical'; export {NodeJSFileSystem} from './src/node_js_file_system'; export {AbsoluteFsPath, FileStats, FileSystem, PathSegment, PathString} from './src/types'; diff --git a/packages/compiler-cli/src/ngtsc/file_system/src/helpers.ts b/packages/compiler-cli/src/ngtsc/file_system/src/helpers.ts index 9cf87fedb6..61d676e058 100644 --- a/packages/compiler-cli/src/ngtsc/file_system/src/helpers.ts +++ b/packages/compiler-cli/src/ngtsc/file_system/src/helpers.ts @@ -37,8 +37,8 @@ export function absoluteFromSourceFile(sf: ts.SourceFile): AbsoluteFsPath { } /** -* Convert the path `path` to a `PathSegment`, throwing an error if it's not a relative path. -*/ + * Convert the path `path` to a `PathSegment`, throwing an error if it's not a relative path. + */ export function relativeFrom(path: string): PathSegment { const normalized = normalizeSeparators(path); if (fs.isRooted(normalized)) { @@ -73,6 +73,13 @@ export function isRoot(path: AbsoluteFsPath): boolean { return fs.isRoot(path); } +/** + * Static access to `isRooted`. + */ +export function isRooted(path: string): boolean { + return fs.isRooted(path); +} + /** * Static access to `relative`. */