diff --git a/packages/runtime-core/__tests__/directives.spec.ts b/packages/runtime-core/__tests__/directives.spec.ts index c2a183b12ef..47ea58f7307 100644 --- a/packages/runtime-core/__tests__/directives.spec.ts +++ b/packages/runtime-core/__tests__/directives.spec.ts @@ -242,7 +242,7 @@ describe('directives', () => { expect(root.children[0]).toBe(el) // node should not have been updated yet - // expect(el.children[0].text).toBe(`${count.value - 1}`) + expect(el.children[0].text).toBe(`${count.value - 1}`) assertBindings(binding) @@ -421,4 +421,24 @@ describe('directives', () => { render(h(App), root) expect(res!).toBe('Test') }) + + test('should not throw with unknown directive', async () => { + const d1 = { + mounted: jest.fn() + } + const App = { + name: 'App', + render() { + // simulates the code generated on an unknown directive + return withDirectives(h('div'), [ + [undefined], + [d1] + ]) + } + } + + const root = nodeOps.createElement('div') + render(h(App), root) + expect(d1.mounted).toHaveBeenCalled() + }) }) diff --git a/packages/runtime-core/src/directives.ts b/packages/runtime-core/src/directives.ts index 6f0eb4c2c0a..18c3352b002 100644 --- a/packages/runtime-core/src/directives.ts +++ b/packages/runtime-core/src/directives.ts @@ -71,10 +71,10 @@ export function validateDirectiveName(name: string) { // Directive, value, argument, modifiers export type DirectiveArguments = Array< - | [Directive] - | [Directive, any] - | [Directive, any, string] - | [Directive, any, string, DirectiveModifiers] + | [Directive | undefined] + | [Directive | undefined, any] + | [Directive | undefined, any, string] + | [Directive | undefined, any, string, DirectiveModifiers] > /** @@ -95,23 +95,25 @@ export function withDirectives( const bindings: DirectiveBinding[] = vnode.dirs || (vnode.dirs = []) for (let i = 0; i < directives.length; i++) { let [dir, value, arg, modifiers = EMPTY_OBJ] = directives[i] - if (isFunction(dir)) { - dir = { - mounted: dir, - updated: dir - } as ObjectDirective + if (dir) { + if (isFunction(dir)) { + dir = { + mounted: dir, + updated: dir + } as ObjectDirective + } + if (dir.deep) { + traverse(value) + } + bindings.push({ + dir, + instance, + value, + oldValue: void 0, + arg, + modifiers + }) } - if (dir.deep) { - traverse(value) - } - bindings.push({ - dir, - instance, - value, - oldValue: void 0, - arg, - modifiers - }) } return vnode }