mirror of https://github.com/vuejs/core.git
feat(compiler-vapor): resolve directive
This commit is contained in:
parent
30f98942db
commit
e2b51d6e7a
|
@ -16,30 +16,34 @@ exports[`compile > custom directive > basic 1`] = `
|
|||
const t0 = _template("<div></div>")
|
||||
|
||||
export function render(_ctx) {
|
||||
const _directive_test = _resolveDirective("test")
|
||||
const _directive_hello = _resolveDirective("hello")
|
||||
const n0 = t0()
|
||||
_withDirectives(n0, [[_resolveDirective("vTest")], [_resolveDirective("vHello"), void 0, void 0, { world: true }]])
|
||||
_withDirectives(n0, [[_directive_test], [_directive_hello, void 0, void 0, { world: true }]])
|
||||
return n0
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compile > custom directive > component 1`] = `
|
||||
"import { resolveComponent as _resolveComponent, createComponent as _createComponent, resolveDirective as _resolveDirective, withDirectives as _withDirectives, insert as _insert, createIf as _createIf, template as _template } from 'vue/vapor';
|
||||
"import { resolveComponent as _resolveComponent, resolveDirective as _resolveDirective, createComponent as _createComponent, withDirectives as _withDirectives, insert as _insert, createIf as _createIf, template as _template } from 'vue/vapor';
|
||||
const t0 = _template("<div></div>")
|
||||
|
||||
export function render(_ctx) {
|
||||
const _component_Bar = _resolveComponent("Bar")
|
||||
const _component_Comp = _resolveComponent("Comp")
|
||||
const _directive_hello = _resolveDirective("hello")
|
||||
const _directive_test = _resolveDirective("test")
|
||||
const n4 = _createComponent(_component_Comp, null, { default: () => {
|
||||
const n0 = _createIf(() => (true), () => {
|
||||
const n3 = t0()
|
||||
const n2 = _createComponent(_component_Bar)
|
||||
_withDirectives(n2, [[_resolveDirective("vHello"), void 0, void 0, { world: true }]])
|
||||
_withDirectives(n2, [[_directive_hello, void 0, void 0, { world: true }]])
|
||||
_insert(n2, n3)
|
||||
return n3
|
||||
})
|
||||
return n0
|
||||
} }, null, true)
|
||||
_withDirectives(n4, [[_resolveDirective("vTest")]])
|
||||
_withDirectives(n4, [[_directive_test]])
|
||||
return n4
|
||||
}"
|
||||
`;
|
||||
|
|
|
@ -71,9 +71,10 @@ export function render(_ctx) {
|
|||
`;
|
||||
|
||||
exports[`compiler: transform <slot> outlets > error on unexpected custom directive on <slot> 1`] = `
|
||||
"import { createSlot as _createSlot } from 'vue/vapor';
|
||||
"import { resolveDirective as _resolveDirective, createSlot as _createSlot } from 'vue/vapor';
|
||||
|
||||
export function render(_ctx) {
|
||||
const _directive_foo = _resolveDirective("foo")
|
||||
const n0 = _createSlot("default", null)
|
||||
return n0
|
||||
}"
|
||||
|
|
|
@ -36,7 +36,7 @@ describe('compiler: element transform', () => {
|
|||
type: IRNodeTypes.CREATE_COMPONENT_NODE,
|
||||
id: 0,
|
||||
tag: 'Foo',
|
||||
resolve: true,
|
||||
asset: true,
|
||||
root: true,
|
||||
props: [[]],
|
||||
},
|
||||
|
@ -66,7 +66,7 @@ describe('compiler: element transform', () => {
|
|||
{
|
||||
type: IRNodeTypes.CREATE_COMPONENT_NODE,
|
||||
tag: 'Example',
|
||||
resolve: false,
|
||||
asset: false,
|
||||
},
|
||||
])
|
||||
})
|
||||
|
@ -172,7 +172,7 @@ describe('compiler: element transform', () => {
|
|||
type: IRNodeTypes.CREATE_COMPONENT_NODE,
|
||||
id: 0,
|
||||
tag: 'Example',
|
||||
resolve: true,
|
||||
asset: true,
|
||||
},
|
||||
])
|
||||
})
|
||||
|
@ -212,7 +212,7 @@ describe('compiler: element transform', () => {
|
|||
{
|
||||
type: IRNodeTypes.CREATE_COMPONENT_NODE,
|
||||
tag: 'Foo',
|
||||
resolve: true,
|
||||
asset: true,
|
||||
root: true,
|
||||
props: [
|
||||
[
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import type { BlockIRNode } from '../ir'
|
||||
import type { BlockIRNode, VaporHelper } from '../ir'
|
||||
import {
|
||||
type CodeFragment,
|
||||
DELIMITERS_ARRAY,
|
||||
|
@ -12,6 +12,7 @@ import {
|
|||
import type { CodegenContext } from '../generate'
|
||||
import { genEffects, genOperations } from './operation'
|
||||
import { genChildren } from './template'
|
||||
import { toValidAssetId } from '@vue/compiler-dom'
|
||||
|
||||
export function genBlock(
|
||||
oper: BlockIRNode,
|
||||
|
@ -43,16 +44,8 @@ export function genBlockContent(
|
|||
const resetBlock = context.enterBlock(block)
|
||||
|
||||
if (root) {
|
||||
for (const name of context.ir.component) {
|
||||
push(
|
||||
NEWLINE,
|
||||
`const _component_${name} = `,
|
||||
...genCall(
|
||||
context.vaporHelper('resolveComponent'),
|
||||
JSON.stringify(name),
|
||||
),
|
||||
)
|
||||
}
|
||||
genResolveAssets('component', 'resolveComponent')
|
||||
genResolveAssets('directive', 'resolveDirective')
|
||||
}
|
||||
|
||||
for (const child of dynamic.children) {
|
||||
|
@ -77,4 +70,17 @@ export function genBlockContent(
|
|||
|
||||
resetBlock()
|
||||
return frag
|
||||
|
||||
function genResolveAssets(
|
||||
kind: 'component' | 'directive',
|
||||
helper: VaporHelper,
|
||||
) {
|
||||
for (const name of context.ir[kind]) {
|
||||
push(
|
||||
NEWLINE,
|
||||
`const ${toValidAssetId(name, kind)} = `,
|
||||
...genCall(context.vaporHelper(helper), JSON.stringify(name)),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ import {
|
|||
} from './utils'
|
||||
import { genExpression } from './expression'
|
||||
import { genPropKey } from './prop'
|
||||
import { createSimpleExpression } from '@vue/compiler-dom'
|
||||
import { createSimpleExpression, toValidAssetId } from '@vue/compiler-dom'
|
||||
import { genEventHandler } from './event'
|
||||
import { genDirectiveModifiers, genDirectivesForElement } from './directive'
|
||||
import { genModelHandler } from './modelValue'
|
||||
|
@ -52,8 +52,8 @@ export function genCreateComponent(
|
|||
]
|
||||
|
||||
function genTag() {
|
||||
if (oper.resolve) {
|
||||
return [`_component_${oper.tag}`]
|
||||
if (oper.asset) {
|
||||
return toValidAssetId(oper.tag, 'component')
|
||||
} else {
|
||||
return genExpression(
|
||||
extend(createSimpleExpression(oper.tag, false), { ast: null }),
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
import { createSimpleExpression, isSimpleIdentifier } from '@vue/compiler-dom'
|
||||
import { camelize } from '@vue/shared'
|
||||
import {
|
||||
createSimpleExpression,
|
||||
isSimpleIdentifier,
|
||||
toValidAssetId,
|
||||
} from '@vue/compiler-dom'
|
||||
import { extend } from '@vue/shared'
|
||||
import { genExpression } from './expression'
|
||||
import type { CodegenContext } from '../generate'
|
||||
import {
|
||||
|
@ -36,7 +40,12 @@ export function genWithDirective(
|
|||
...genCall(vaporHelper('withDirectives'), element, directives),
|
||||
]
|
||||
|
||||
function genDirective({ dir, builtin }: WithDirectiveIRNode): CodeFragment[] {
|
||||
function genDirective({
|
||||
dir,
|
||||
name,
|
||||
builtin,
|
||||
asset,
|
||||
}: WithDirectiveIRNode): CodeFragment[] {
|
||||
const directive = genDirective()
|
||||
const value = dir.exp && ['() => ', ...genExpression(dir.exp, context)]
|
||||
const argument = dir.arg && genExpression(dir.arg, context)
|
||||
|
@ -55,24 +64,15 @@ export function genWithDirective(
|
|||
)
|
||||
|
||||
function genDirective() {
|
||||
const {
|
||||
vaporHelper,
|
||||
options: { bindingMetadata },
|
||||
} = context
|
||||
if (dir.name === 'show') {
|
||||
return [vaporHelper('vShow')]
|
||||
} else if (builtin) {
|
||||
return [vaporHelper(builtin)]
|
||||
if (builtin) {
|
||||
return vaporHelper(name as any)
|
||||
} else if (asset) {
|
||||
return toValidAssetId(name, 'directive')
|
||||
} else {
|
||||
const directiveReference = camelize(`v-${dir.name}`)
|
||||
// TODO resolve directive
|
||||
if (bindingMetadata[directiveReference]) {
|
||||
const directiveExpression = createSimpleExpression(directiveReference)
|
||||
directiveExpression.ast = null
|
||||
return genExpression(directiveExpression, context)
|
||||
} else {
|
||||
return `${vaporHelper('resolveDirective')}("${directiveReference}")`
|
||||
}
|
||||
return genExpression(
|
||||
extend(createSimpleExpression(name, false), { ast: null }),
|
||||
context,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ export interface RootIRNode {
|
|||
source: string
|
||||
template: string[]
|
||||
component: Set<string>
|
||||
directive: Set<string>
|
||||
block: BlockIRNode
|
||||
}
|
||||
|
||||
|
@ -197,7 +198,9 @@ export interface WithDirectiveIRNode extends BaseIRNode {
|
|||
type: IRNodeTypes.WITH_DIRECTIVE
|
||||
element: number
|
||||
dir: VaporDirectiveNode
|
||||
builtin?: VaporHelper
|
||||
name: string
|
||||
builtin?: boolean
|
||||
asset?: boolean
|
||||
}
|
||||
|
||||
export interface ComponentSlotBlockIRNode extends BlockIRNode {
|
||||
|
@ -219,7 +222,7 @@ export interface CreateComponentIRNode extends BaseIRNode {
|
|||
slots?: ComponentSlots
|
||||
dynamicSlots?: ComponentDynamicSlot[]
|
||||
|
||||
resolve: boolean
|
||||
asset: boolean
|
||||
root: boolean
|
||||
}
|
||||
|
||||
|
|
|
@ -79,6 +79,8 @@ export class TransformContext<T extends AllNode = AllNode> {
|
|||
|
||||
comment: CommentNode[] = []
|
||||
component: Set<string> = this.ir.component
|
||||
directive: Set<string> = this.ir.directive
|
||||
|
||||
slots?: ComponentSlots
|
||||
dynamicSlots?: ComponentDynamicSlot[]
|
||||
|
||||
|
@ -220,6 +222,7 @@ export function transform(
|
|||
source: node.source,
|
||||
template: [],
|
||||
component: new Set(),
|
||||
directive: new Set(),
|
||||
block: newBlock(node),
|
||||
}
|
||||
|
||||
|
|
|
@ -72,24 +72,24 @@ function transformComponentElement(
|
|||
propsResult: PropsResult,
|
||||
context: TransformContext,
|
||||
) {
|
||||
let resolve = true
|
||||
let asset = true
|
||||
|
||||
if (!__BROWSER__) {
|
||||
const fromSetup = resolveSetupReference(tag, context)
|
||||
if (fromSetup) {
|
||||
tag = fromSetup
|
||||
resolve = false
|
||||
asset = false
|
||||
}
|
||||
const dotIndex = tag.indexOf('.')
|
||||
if (dotIndex > 0) {
|
||||
const ns = resolveSetupReference(tag.slice(0, dotIndex), context)
|
||||
if (ns) {
|
||||
tag = ns + tag.slice(dotIndex)
|
||||
resolve = false
|
||||
asset = false
|
||||
}
|
||||
}
|
||||
}
|
||||
if (resolve) {
|
||||
if (asset) {
|
||||
context.component.add(tag)
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ function transformComponentElement(
|
|||
id: context.reference(),
|
||||
tag,
|
||||
props: propsResult[0] ? propsResult[1] : [propsResult[1]],
|
||||
resolve,
|
||||
asset,
|
||||
root,
|
||||
slots: context.slots,
|
||||
dynamicSlots: context.dynamicSlots,
|
||||
|
@ -287,7 +287,7 @@ function transformProp(
|
|||
node: ElementNode,
|
||||
context: TransformContext<ElementNode>,
|
||||
): DirectiveTransformResult | void {
|
||||
const { name } = prop
|
||||
let { name } = prop
|
||||
|
||||
if (prop.type === NodeTypes.ATTRIBUTE) {
|
||||
if (isReservedProp(name)) return
|
||||
|
@ -305,10 +305,20 @@ function transformProp(
|
|||
}
|
||||
|
||||
if (!isBuiltInDirective(name)) {
|
||||
const fromSetup =
|
||||
!__BROWSER__ && resolveSetupReference(`v-${name}`, context)
|
||||
if (fromSetup) {
|
||||
name = fromSetup
|
||||
} else {
|
||||
context.directive.add(name)
|
||||
}
|
||||
|
||||
context.registerOperation({
|
||||
type: IRNodeTypes.WITH_DIRECTIVE,
|
||||
element: context.reference(),
|
||||
dir: prop,
|
||||
name,
|
||||
asset: !fromSetup,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,8 +62,6 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
|
|||
}
|
||||
|
||||
const isComponent = node.tagType === ElementTypes.COMPONENT
|
||||
let runtimeDirective: VaporHelper | undefined
|
||||
|
||||
if (isComponent) {
|
||||
return {
|
||||
key: arg ? arg : createSimpleExpression('modelValue', true),
|
||||
|
@ -71,7 +69,8 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
|
|||
model: true,
|
||||
modelModifiers: dir.modifiers,
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
if (dir.arg)
|
||||
context.options.onError(
|
||||
createDOMCompilerError(
|
||||
|
@ -81,7 +80,7 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
|
|||
)
|
||||
const { tag } = node
|
||||
const isCustomElement = context.options.isCustomElement(tag)
|
||||
runtimeDirective = 'vModelText'
|
||||
let runtimeDirective: VaporHelper | undefined = 'vModelText'
|
||||
if (
|
||||
tag === 'input' ||
|
||||
tag === 'textarea' ||
|
||||
|
@ -139,7 +138,6 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
|
|||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
context.registerOperation({
|
||||
type: IRNodeTypes.SET_MODEL_VALUE,
|
||||
|
@ -154,7 +152,8 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
|
|||
type: IRNodeTypes.WITH_DIRECTIVE,
|
||||
element: context.reference(),
|
||||
dir,
|
||||
builtin: runtimeDirective,
|
||||
name: runtimeDirective,
|
||||
builtin: true,
|
||||
})
|
||||
|
||||
function checkDuplicatedValue() {
|
||||
|
|
|
@ -14,5 +14,7 @@ export const transformVShow: DirectiveTransform = (dir, node, context) => {
|
|||
type: IRNodeTypes.WITH_DIRECTIVE,
|
||||
element: context.reference(),
|
||||
dir,
|
||||
name: 'vShow',
|
||||
builtin: true,
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue