]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): do not throw on unknown directives (#6671)
authorCédric Exbrayat <cexbrayat@users.noreply.github.com>
Tue, 8 Nov 2022 02:49:49 +0000 (03:49 +0100)
committerGitHub <noreply@github.com>
Tue, 8 Nov 2022 02:49:49 +0000 (21:49 -0500)
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')
```

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

index c2a183b12ef4a9e0ad02a4e2fbbe6cbc6bb4f891..47ea58f7307fe1024d27e53dc59f29c720b36b59 100644 (file)
@@ -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()
+  })
 })
index 6f0eb4c2c0abdb463949a1f329694c977d2cdd3a..18c3352b002a72a59f7123719bfe9e9994b2c3ad 100644 (file)
@@ -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<T extends VNode>(
   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
 }