wip: cache fileToScope + improve vue file offset

This commit is contained in:
Evan You 2023-04-13 22:38:00 +08:00
parent c93c11710e
commit 8451b92a7a
5 changed files with 54 additions and 15 deletions

View File

@ -3,6 +3,7 @@ import { parse } from '../../src'
import { ScriptCompileContext } from '../../src/script/context'
import {
inferRuntimeType,
invalidateTypeCache,
recordImports,
resolveTypeElements
} from '../../src/script/resolveType'
@ -369,6 +370,10 @@ function resolve(code: string, files: Record<string, string> = {}) {
}
})
for (const file in files) {
invalidateTypeCache(file)
}
// ctx.userImports is collected when calling compileScript(), but we are
// skipping that here, so need to manually register imports
ctx.userImports = recordImports(ctx.scriptSetupAst!.body) as any

View File

@ -1,7 +1,11 @@
import LRU from 'lru-cache'
export function createCache<T>(size = 500) {
return __GLOBAL__ || __ESM_BROWSER__
? new Map<string, T>()
: (new LRU(size) as any as Map<string, T>)
if (__GLOBAL__ || __ESM_BROWSER__) {
return new Map<string, T>()
}
const cache = new LRU(size)
// @ts-expect-error
cache.delete = cache.del.bind(cache)
return cache as any as Map<string, T>
}

View File

@ -6,6 +6,7 @@ export { compileTemplate } from './compileTemplate'
export { compileStyle, compileStyleAsync } from './compileStyle'
export { compileScript } from './compileScript'
export { rewriteDefault, rewriteDefaultAST } from './rewriteDefault'
export { invalidateTypeCache } from './script/resolveType'
export {
shouldTransform as shouldTransformRef,
transform as transformRef,

View File

@ -126,7 +126,7 @@ export class ScriptCompileContext {
}
error(msg: string, node: Node & WithScope, scope?: TypeScope): never {
const offset = scope ? scope.offset || 0 : this.startOffset!
const offset = scope ? scope.offset : this.startOffset!
throw new Error(
`[@vue/compiler-sfc] ${msg}\n\n${
(scope || this.descriptor).filename

View File

@ -27,6 +27,7 @@ import { capitalize, hasOwn } from '@vue/shared'
import path from 'path'
import { parse as babelParse } from '@babel/parser'
import { parse } from '../parse'
import { createCache } from '../cache'
type Import = Pick<ImportBinding, 'source' | 'imported'>
@ -539,23 +540,35 @@ function resolveExt(
)
}
const fileToScopeCache = createCache<TypeScope>()
export function invalidateTypeCache(filename: string) {
fileToScopeCache.delete(filename)
}
function fileToScope(
ctx: ScriptCompileContext,
filename: string,
fs: NonNullable<SFCScriptCompileOptions['fs']>
): TypeScope {
// TODO cache
const cached = fileToScopeCache.get(filename)
if (cached) {
return cached
}
const source = fs.readFile(filename)
const [body, offset] = parseFile(ctx, filename, source)
const body = parseFile(ctx, filename, source)
const scope: TypeScope = {
filename,
source,
offset,
offset: 0,
types: Object.create(null),
exportedTypes: Object.create(null),
imports: recordImports(body)
}
recordTypes(body, scope)
fileToScopeCache.set(filename, scope)
return scope
}
@ -563,12 +576,10 @@ function parseFile(
ctx: ScriptCompileContext,
filename: string,
content: string
): [Statement[], number] {
let body: Statement[] = []
let offset = 0
): Statement[] {
const ext = path.extname(filename)
if (ext === '.ts' || ext === '.tsx') {
body = babelParse(content, {
return babelParse(content, {
plugins: resolveParserPlugins(
ext.slice(1),
ctx.options.babelParserPlugins
@ -579,15 +590,33 @@ function parseFile(
const {
descriptor: { script, scriptSetup }
} = parse(content)
const scriptContent = (script?.content || '') + (scriptSetup?.content || '')
if (!script && !scriptSetup) {
return []
}
// ensure the correct offset with original source
const scriptOffset = script ? script.loc.start.offset : Infinity
const scriptSetupOffset = scriptSetup
? scriptSetup.loc.start.offset
: Infinity
const firstBlock = scriptOffset < scriptSetupOffset ? script : scriptSetup
const secondBlock = scriptOffset < scriptSetupOffset ? scriptSetup : script
let scriptContent =
' '.repeat(Math.min(scriptOffset, scriptSetupOffset)) +
firstBlock!.content
if (secondBlock) {
scriptContent +=
' '.repeat(secondBlock.loc.start.offset - script!.loc.end.offset) +
secondBlock.content
}
const lang = script?.lang || scriptSetup?.lang
body = babelParse(scriptContent, {
return babelParse(scriptContent, {
plugins: resolveParserPlugins(lang!, ctx.options.babelParserPlugins),
sourceType: 'module'
}).program.body
offset = scriptSetup ? scriptSetup.loc.start.offset : 0
}
return [body, offset]
return []
}
function ctxToScope(ctx: ScriptCompileContext): TypeScope {