Skip to content

Commit 0455378

Browse files
authored
fix(runtime-core): do not throw on unknown directives (#6671)
fix #6340 This commit improves the case when a directive is not found in a template. As `resolveDirective` returns `undefined`, some code was failing with the following error: ``` TypeError: Cannot read properties of undefined (reading 'deep') ```
1 parent b72a4af commit 0455378

File tree

2 files changed

+43
-21
lines changed

2 files changed

+43
-21
lines changed

packages/runtime-core/__tests__/directives.spec.ts

+21-1
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ describe('directives', () => {
242242
expect(root.children[0]).toBe(el)
243243

244244
// node should not have been updated yet
245-
// expect(el.children[0].text).toBe(`${count.value - 1}`)
245+
expect(el.children[0].text).toBe(`${count.value - 1}`)
246246

247247
assertBindings(binding)
248248

@@ -421,4 +421,24 @@ describe('directives', () => {
421421
render(h(App), root)
422422
expect(res!).toBe('Test')
423423
})
424+
425+
test('should not throw with unknown directive', async () => {
426+
const d1 = {
427+
mounted: jest.fn()
428+
}
429+
const App = {
430+
name: 'App',
431+
render() {
432+
// simulates the code generated on an unknown directive
433+
return withDirectives(h('div'), [
434+
[undefined],
435+
[d1]
436+
])
437+
}
438+
}
439+
440+
const root = nodeOps.createElement('div')
441+
render(h(App), root)
442+
expect(d1.mounted).toHaveBeenCalled()
443+
})
424444
})

packages/runtime-core/src/directives.ts

+22-20
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,10 @@ export function validateDirectiveName(name: string) {
7171

7272
// Directive, value, argument, modifiers
7373
export type DirectiveArguments = Array<
74-
| [Directive]
75-
| [Directive, any]
76-
| [Directive, any, string]
77-
| [Directive, any, string, DirectiveModifiers]
74+
| [Directive | undefined]
75+
| [Directive | undefined, any]
76+
| [Directive | undefined, any, string]
77+
| [Directive | undefined, any, string, DirectiveModifiers]
7878
>
7979

8080
/**
@@ -95,23 +95,25 @@ export function withDirectives<T extends VNode>(
9595
const bindings: DirectiveBinding[] = vnode.dirs || (vnode.dirs = [])
9696
for (let i = 0; i < directives.length; i++) {
9797
let [dir, value, arg, modifiers = EMPTY_OBJ] = directives[i]
98-
if (isFunction(dir)) {
99-
dir = {
100-
mounted: dir,
101-
updated: dir
102-
} as ObjectDirective
98+
if (dir) {
99+
if (isFunction(dir)) {
100+
dir = {
101+
mounted: dir,
102+
updated: dir
103+
} as ObjectDirective
104+
}
105+
if (dir.deep) {
106+
traverse(value)
107+
}
108+
bindings.push({
109+
dir,
110+
instance,
111+
value,
112+
oldValue: void 0,
113+
arg,
114+
modifiers
115+
})
103116
}
104-
if (dir.deep) {
105-
traverse(value)
106-
}
107-
bindings.push({
108-
dir,
109-
instance,
110-
value,
111-
oldValue: void 0,
112-
arg,
113-
modifiers
114-
})
115117
}
116118
return vnode
117119
}

0 commit comments

Comments
 (0)