mirror of https://github.com/vuejs/core.git
feat(compiler-vapor): resolve implicitly self-referencing component (#13400)
This commit is contained in:
parent
08f9c1d9f6
commit
978c47f751
|
@ -17,6 +17,7 @@ export {
|
|||
createTransformContext,
|
||||
traverseNode,
|
||||
createStructuralDirectiveTransform,
|
||||
getSelfName,
|
||||
type NodeTransform,
|
||||
type StructuralDirectiveTransform,
|
||||
type DirectiveTransform,
|
||||
|
|
|
@ -123,6 +123,11 @@ export interface TransformContext
|
|||
filters?: Set<string>
|
||||
}
|
||||
|
||||
export function getSelfName(filename: string): string | null {
|
||||
const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/)
|
||||
return nameMatch ? capitalize(camelize(nameMatch[1])) : null
|
||||
}
|
||||
|
||||
export function createTransformContext(
|
||||
root: RootNode,
|
||||
{
|
||||
|
@ -150,11 +155,10 @@ export function createTransformContext(
|
|||
compatConfig,
|
||||
}: TransformOptions,
|
||||
): TransformContext {
|
||||
const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/)
|
||||
const context: TransformContext = {
|
||||
// options
|
||||
filename,
|
||||
selfName: nameMatch && capitalize(camelize(nameMatch[1])),
|
||||
selfName: getSelfName(filename),
|
||||
prefixIdentifiers,
|
||||
hoistStatic,
|
||||
hmr,
|
||||
|
|
|
@ -77,6 +77,16 @@ export function render(_ctx, $props, $emit, $attrs, $slots) {
|
|||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: element transform > component > resolve implicitly self-referencing component 1`] = `
|
||||
"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback } from 'vue';
|
||||
|
||||
export function render(_ctx) {
|
||||
const _component_Example__self = _resolveComponent("Example", true)
|
||||
const n0 = _createComponentWithFallback(_component_Example__self, null, null, true)
|
||||
return n0
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: element transform > component > resolve namespaced component from props bindings (inline) 1`] = `
|
||||
"
|
||||
const n0 = _createComponent(Foo.Example, null, null, true)
|
||||
|
|
|
@ -39,11 +39,12 @@ describe('compiler: element transform', () => {
|
|||
})
|
||||
})
|
||||
|
||||
test.todo('resolve implicitly self-referencing component', () => {
|
||||
test('resolve implicitly self-referencing component', () => {
|
||||
const { code, helpers } = compileWithElementTransform(`<Example/>`, {
|
||||
filename: `/foo/bar/Example.vue?vue&type=template`,
|
||||
})
|
||||
expect(code).toMatchSnapshot()
|
||||
expect(code).toContain('_resolveComponent("Example", true)')
|
||||
expect(helpers).toContain('resolveComponent')
|
||||
})
|
||||
|
||||
|
|
|
@ -44,7 +44,21 @@ export function genBlockContent(
|
|||
const resetBlock = context.enterBlock(block)
|
||||
|
||||
if (root) {
|
||||
genResolveAssets('component', 'resolveComponent')
|
||||
for (let name of context.ir.component) {
|
||||
const id = toValidAssetId(name, 'component')
|
||||
const maybeSelfReference = name.endsWith('__self')
|
||||
if (maybeSelfReference) name = name.slice(0, -6)
|
||||
push(
|
||||
NEWLINE,
|
||||
`const ${id} = `,
|
||||
...genCall(
|
||||
context.helper('resolveComponent'),
|
||||
JSON.stringify(name),
|
||||
// pass additional `maybeSelfReference` flag
|
||||
maybeSelfReference ? 'true' : undefined,
|
||||
),
|
||||
)
|
||||
}
|
||||
genResolveAssets('directive', 'resolveDirective')
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
type TemplateChildNode,
|
||||
defaultOnError,
|
||||
defaultOnWarn,
|
||||
getSelfName,
|
||||
isVSlot,
|
||||
} from '@vue/compiler-dom'
|
||||
import { EMPTY_OBJ, NOOP, extend, isArray, isString } from '@vue/shared'
|
||||
|
@ -61,6 +62,7 @@ export type StructuralDirectiveTransform = (
|
|||
export type TransformOptions = HackOptions<BaseTransformOptions>
|
||||
|
||||
export class TransformContext<T extends AllNode = AllNode> {
|
||||
selfName: string | null = null
|
||||
parent: TransformContext<RootNode | ElementNode> | null = null
|
||||
root: TransformContext<RootNode>
|
||||
index: number = 0
|
||||
|
@ -92,6 +94,7 @@ export class TransformContext<T extends AllNode = AllNode> {
|
|||
) {
|
||||
this.options = extend({}, defaultOptions, options)
|
||||
this.root = this as TransformContext<RootNode>
|
||||
if (options.filename) this.selfName = getSelfName(options.filename)
|
||||
}
|
||||
|
||||
enterBlock(ir: BlockIRNode, isVFor: boolean = false): () => void {
|
||||
|
|
|
@ -119,6 +119,13 @@ function transformComponentElement(
|
|||
}
|
||||
|
||||
if (asset) {
|
||||
// self referencing component (inferred from filename)
|
||||
if (context.selfName && capitalize(camelize(tag)) === context.selfName) {
|
||||
// generators/block.ts has special check for __self postfix when generating
|
||||
// component imports, which will pass additional `maybeSelfReference` flag
|
||||
// to `resolveComponent`.
|
||||
tag += `__self`
|
||||
}
|
||||
context.component.add(tag)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue