fix: relative root (by default) yields LookupError, fixes #419, #424, also related to #395

This commit is contained in:
Harttle
2021-10-27 23:55:39 +08:00
committed by Harttle
parent 564972ba74
commit aebeae9e1b
7 changed files with 67 additions and 50 deletions
+13 -15
View File
@@ -16,14 +16,21 @@ export enum LookupType {
Root = 'root'
}
export class Loader {
public shouldLoadRelative: (referencedFile: string) => boolean
private options: LoaderOptions
private sep: string
private rRelativePath: RegExp
private contains: (root: string, file: string) => boolean
constructor (options: LoaderOptions) {
this.options = options
this.sep = this.options.fs.sep || '/'
this.rRelativePath = new RegExp(['.' + this.sep, '..' + this.sep].map(prefix => escapeRegex(prefix)).join('|'))
if (options.relativeReference) {
const sep = options.fs.sep
assert(sep, '`fs.sep` is required for relative reference')
const rRelativePath = new RegExp(['.' + sep, '..' + sep].map(prefix => escapeRegex(prefix)).join('|'))
this.shouldLoadRelative = (referencedFile: string) => rRelativePath.test(referencedFile)
} else {
this.shouldLoadRelative = (referencedFile: string) => false
}
this.contains = this.options.fs.contains || (() => true)
}
public * lookup (file: string, type: LookupType, sync?: boolean, currentFile?: string) {
@@ -35,16 +42,12 @@ export class Loader {
throw this.lookupError(file, dirs)
}
public shouldLoadRelative (referencedFile: string) {
return this.options.relativeReference && this.rRelativePath.test(referencedFile)
}
public * candidates (file: string, dirs: string[], currentFile?: string, enforceRoot?: boolean) {
const { fs, extname } = this.options
if (this.shouldLoadRelative(file) && currentFile) {
const referenced = fs.resolve(this.dirname(currentFile), file, extname)
for (const dir of dirs) {
if (!enforceRoot || this.withinDir(referenced, dir)) {
if (!enforceRoot || this.contains(dir, referenced)) {
// the relatively referenced file is within one of root dirs
yield referenced
break
@@ -53,7 +56,7 @@ export class Loader {
}
for (const dir of dirs) {
const referenced = fs.resolve(dir, file, extname)
if (!enforceRoot || this.withinDir(referenced, dir)) {
if (!enforceRoot || this.contains(dir, referenced)) {
yield referenced
}
}
@@ -63,11 +66,6 @@ export class Loader {
}
}
private withinDir (file: string, dir: string) {
dir = dir.endsWith(this.sep) ? dir : dir + this.sep
return file.startsWith(dir)
}
private dirname (path: string) {
const fs = this.options.fs
assert(fs.dirname, '`fs.dirname` is required for relative reference')