mirror of https://github.com/vuejs/core.git
wip: cache fileToScope + improve vue file offset
This commit is contained in:
parent
c93c11710e
commit
8451b92a7a
|
@ -3,6 +3,7 @@ import { parse } from '../../src'
|
||||||
import { ScriptCompileContext } from '../../src/script/context'
|
import { ScriptCompileContext } from '../../src/script/context'
|
||||||
import {
|
import {
|
||||||
inferRuntimeType,
|
inferRuntimeType,
|
||||||
|
invalidateTypeCache,
|
||||||
recordImports,
|
recordImports,
|
||||||
resolveTypeElements
|
resolveTypeElements
|
||||||
} from '../../src/script/resolveType'
|
} 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
|
// ctx.userImports is collected when calling compileScript(), but we are
|
||||||
// skipping that here, so need to manually register imports
|
// skipping that here, so need to manually register imports
|
||||||
ctx.userImports = recordImports(ctx.scriptSetupAst!.body) as any
|
ctx.userImports = recordImports(ctx.scriptSetupAst!.body) as any
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import LRU from 'lru-cache'
|
import LRU from 'lru-cache'
|
||||||
|
|
||||||
export function createCache<T>(size = 500) {
|
export function createCache<T>(size = 500) {
|
||||||
return __GLOBAL__ || __ESM_BROWSER__
|
if (__GLOBAL__ || __ESM_BROWSER__) {
|
||||||
? new Map<string, T>()
|
return new Map<string, T>()
|
||||||
: (new LRU(size) as any as 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>
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ export { compileTemplate } from './compileTemplate'
|
||||||
export { compileStyle, compileStyleAsync } from './compileStyle'
|
export { compileStyle, compileStyleAsync } from './compileStyle'
|
||||||
export { compileScript } from './compileScript'
|
export { compileScript } from './compileScript'
|
||||||
export { rewriteDefault, rewriteDefaultAST } from './rewriteDefault'
|
export { rewriteDefault, rewriteDefaultAST } from './rewriteDefault'
|
||||||
|
export { invalidateTypeCache } from './script/resolveType'
|
||||||
export {
|
export {
|
||||||
shouldTransform as shouldTransformRef,
|
shouldTransform as shouldTransformRef,
|
||||||
transform as transformRef,
|
transform as transformRef,
|
||||||
|
|
|
@ -126,7 +126,7 @@ export class ScriptCompileContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
error(msg: string, node: Node & WithScope, scope?: TypeScope): never {
|
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(
|
throw new Error(
|
||||||
`[@vue/compiler-sfc] ${msg}\n\n${
|
`[@vue/compiler-sfc] ${msg}\n\n${
|
||||||
(scope || this.descriptor).filename
|
(scope || this.descriptor).filename
|
||||||
|
|
|
@ -27,6 +27,7 @@ import { capitalize, hasOwn } from '@vue/shared'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { parse as babelParse } from '@babel/parser'
|
import { parse as babelParse } from '@babel/parser'
|
||||||
import { parse } from '../parse'
|
import { parse } from '../parse'
|
||||||
|
import { createCache } from '../cache'
|
||||||
|
|
||||||
type Import = Pick<ImportBinding, 'source' | 'imported'>
|
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(
|
function fileToScope(
|
||||||
ctx: ScriptCompileContext,
|
ctx: ScriptCompileContext,
|
||||||
filename: string,
|
filename: string,
|
||||||
fs: NonNullable<SFCScriptCompileOptions['fs']>
|
fs: NonNullable<SFCScriptCompileOptions['fs']>
|
||||||
): TypeScope {
|
): TypeScope {
|
||||||
// TODO cache
|
const cached = fileToScopeCache.get(filename)
|
||||||
|
if (cached) {
|
||||||
|
return cached
|
||||||
|
}
|
||||||
|
|
||||||
const source = fs.readFile(filename)
|
const source = fs.readFile(filename)
|
||||||
const [body, offset] = parseFile(ctx, filename, source)
|
const body = parseFile(ctx, filename, source)
|
||||||
const scope: TypeScope = {
|
const scope: TypeScope = {
|
||||||
filename,
|
filename,
|
||||||
source,
|
source,
|
||||||
offset,
|
offset: 0,
|
||||||
types: Object.create(null),
|
types: Object.create(null),
|
||||||
exportedTypes: Object.create(null),
|
exportedTypes: Object.create(null),
|
||||||
imports: recordImports(body)
|
imports: recordImports(body)
|
||||||
}
|
}
|
||||||
recordTypes(body, scope)
|
recordTypes(body, scope)
|
||||||
|
|
||||||
|
fileToScopeCache.set(filename, scope)
|
||||||
return scope
|
return scope
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -563,12 +576,10 @@ function parseFile(
|
||||||
ctx: ScriptCompileContext,
|
ctx: ScriptCompileContext,
|
||||||
filename: string,
|
filename: string,
|
||||||
content: string
|
content: string
|
||||||
): [Statement[], number] {
|
): Statement[] {
|
||||||
let body: Statement[] = []
|
|
||||||
let offset = 0
|
|
||||||
const ext = path.extname(filename)
|
const ext = path.extname(filename)
|
||||||
if (ext === '.ts' || ext === '.tsx') {
|
if (ext === '.ts' || ext === '.tsx') {
|
||||||
body = babelParse(content, {
|
return babelParse(content, {
|
||||||
plugins: resolveParserPlugins(
|
plugins: resolveParserPlugins(
|
||||||
ext.slice(1),
|
ext.slice(1),
|
||||||
ctx.options.babelParserPlugins
|
ctx.options.babelParserPlugins
|
||||||
|
@ -579,15 +590,33 @@ function parseFile(
|
||||||
const {
|
const {
|
||||||
descriptor: { script, scriptSetup }
|
descriptor: { script, scriptSetup }
|
||||||
} = parse(content)
|
} = 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
|
const lang = script?.lang || scriptSetup?.lang
|
||||||
body = babelParse(scriptContent, {
|
return babelParse(scriptContent, {
|
||||||
plugins: resolveParserPlugins(lang!, ctx.options.babelParserPlugins),
|
plugins: resolveParserPlugins(lang!, ctx.options.babelParserPlugins),
|
||||||
sourceType: 'module'
|
sourceType: 'module'
|
||||||
}).program.body
|
}).program.body
|
||||||
offset = scriptSetup ? scriptSetup.loc.start.offset : 0
|
|
||||||
}
|
}
|
||||||
return [body, offset]
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
function ctxToScope(ctx: ScriptCompileContext): TypeScope {
|
function ctxToScope(ctx: ScriptCompileContext): TypeScope {
|
||||||
|
|
Loading…
Reference in New Issue