/
descriptorCache.ts
94 lines (83 loc) · 2.39 KB
/
descriptorCache.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import fs from 'node:fs'
import path from 'node:path'
import { createHash } from 'node:crypto'
import slash from 'slash'
import type { CompilerError, SFCDescriptor } from 'vue/compiler-sfc'
import type { ResolvedOptions, VueQuery } from '..'
// compiler-sfc should be exported so it can be re-used
export interface SFCParseResult {
descriptor: SFCDescriptor
errors: Array<CompilerError | SyntaxError>
}
const cache = new Map<string, SFCDescriptor>()
const prevCache = new Map<string, SFCDescriptor | undefined>()
export function createDescriptor(
filename: string,
source: string,
{ root, isProduction, sourceMap, compiler }: ResolvedOptions
): SFCParseResult {
const { descriptor, errors } = compiler.parse(source, {
filename,
sourceMap
})
// ensure the path is normalized in a way that is consistent inside
// project (relative to root) and on different systems.
const normalizedPath = slash(path.normalize(path.relative(root, filename)))
descriptor.id = getHash(normalizedPath + (isProduction ? source : ''))
cache.set(filename, descriptor)
return { descriptor, errors }
}
export function getPrevDescriptor(filename: string): SFCDescriptor | undefined {
return prevCache.get(filename)
}
export function setPrevDescriptor(
filename: string,
entry: SFCDescriptor
): void {
prevCache.set(filename, entry)
}
export function getDescriptor(
filename: string,
options: ResolvedOptions,
createIfNotFound = true
): SFCDescriptor | undefined {
if (cache.has(filename)) {
return cache.get(filename)!
}
if (createIfNotFound) {
const { descriptor, errors } = createDescriptor(
filename,
fs.readFileSync(filename, 'utf-8'),
options
)
if (errors.length) {
throw errors[0]
}
return descriptor
}
}
export function getSrcDescriptor(
filename: string,
query: VueQuery
): SFCDescriptor {
if (query.scoped) {
return cache.get(`${filename}?src=${query.src}`)!
}
return cache.get(filename)!
}
export function setSrcDescriptor(
filename: string,
entry: SFCDescriptor,
scoped?: boolean
): void {
if (scoped) {
// if multiple Vue files use the same src file, they will be overwritten
// should use other key
cache.set(`${filename}?src=${entry.id}`, entry)
return
}
cache.set(filename, entry)
}
function getHash(text: string): string {
return createHash('sha256').update(text).digest('hex').substring(0, 8)
}