Repository: vuejs/vue
Pull request: fix(#9577): support deep object as dynamic arguments

<!--
Please make sure to read the Pull Request Guidelines:
https://github.com/vuejs/vue/blob/dev/.github/CONTRIBUTING.md#pull-request-guidelines
-->

<!-- PULL REQUEST TEMPLATE -->
<!-- (Update "[ ]" to "[x]" to check a box) -->

**What kind of change does this PR introduce?** (check at least one)

- [x] Bugfix
- [ ] Feature
- [ ] Code style update
- [ ] Refactor
- [ ] Build-related changes
- [ ] Other, please describe:

**Does this PR introduce a breaking change?** (check one)

- [ ] Yes
- [x] No

If yes, please describe the impact and migration path for existing applications:

**The PR fulfills these requirements:**

- [x] It's submitted to the `dev` branch for v2.x (or to a previous version branch), _not_ the `master` branch
- [x] When resolving a specific issue, it's referenced in the PR's title (e.g. `fix #xxx[,#xxx]`, where "xxx" is the issue number)
- [x] All tests are passing: https://github.com/vuejs/vue/blob/dev/.github/CONTRIBUTING.md#development-setup
- [x] New/updated tests are included

If adding a **new feature**, the PR's description includes:
- [ ] A convincing reason for adding this feature (to avoid wasting your time, it's best to open a suggestion issue first and wait for approval before working on it)

**Other information:**
Fixed issue #9577.

The old modifier matching pattern is `/\.[^.]+/g`, It does not take into account that dynamic arguments may contain `.`，so I updated it and hope it is correct.

code example:

``` {javascript}
const before = /\.[^.]+/g;
const after = /\.[^.\]]+(?=\.|$)/g;

let s = 'name:[a.b].c.d';

console.log(s.match(before)); // [".b]", ".c", ".d"]
console.log(s.match(after));    // [".c", ".d"]
```

Changed files:
filename: src/compiler/parser/index.js
patch: @@ -33,7 +33,7 @@ const dynamicArgRE = /^\[.*\]$/
 const argRE = /:(.*)$/
 export const bindRE = /^:|^\.|^v-bind:/
 const propBindRE = /^\./
-const modifierRE = /\.[^.]+/g
+const modifierRE = /\.[^.\]]+(?=[^\]]*$)/g
 
 const slotRE = /^v-slot(:|$)|^#/
 

filename: test/unit/features/options/directives.spec.js
patch: @@ -287,4 +287,82 @@ describe('Options directives', () => {
     }).$mount()
     vm.key = 'bar'
   })
+
+  it('deep object like `deep.a` as dynamic arguments', done => {
+    const vm = new Vue({
+      template: `<div v-my:[deep.a]="1"/>`,
+      data: {
+        deep: {
+          a: 'foo'
+        }
+      },
+      directives: {
+        my: {
+          bind(el, binding) {
+            expect(binding.arg).toBe('foo')
+          },
+          update(el, binding) {
+            expect(binding.arg).toBe('bar')
+            expect(binding.oldArg).toBe('foo')
+            done()
+          }
+        }
+      }
+    }).$mount()
+    vm.deep.a = 'bar'
+  })
+
+  it('deep object like `deep.a.b` as dynamic arguments', done => {
+    const vm = new Vue({
+      template: `<div v-my:[deep.a.b]="1"/>`,
+      data: {
+        deep: {
+          a: {
+            b: 'foo'
+          }
+        }
+      },
+      directives: {
+        my: {
+          bind(el, binding) {
+            expect(binding.arg).toBe('foo')
+          },
+          update(el, binding) {
+            expect(binding.arg).toBe('bar')
+            expect(binding.oldArg).toBe('foo')
+            done()
+          }
+        }
+      }
+    }).$mount()
+    vm.deep.a.b = 'bar'
+  })
+
+  it('deep object as dynamic arguments with modifiers', done => {
+    const vm = new Vue({
+      template: `<div v-my:[deep.a.b].x.y="1"/>`,
+      data: {
+        deep: {
+          a: {
+            b: 'foo'
+          }
+        }
+      },
+      directives: {
+        my: {
+          bind(el, binding) {
+            expect(binding.arg).toBe('foo')
+            expect(binding.modifiers.x).toBe(true)
+            expect(binding.modifiers.y).toBe(true)
+          },
+          update(el, binding) {
+            expect(binding.arg).toBe('bar')
+            expect(binding.oldArg).toBe('foo')
+            done()
+          }
+        }
+      }
+    }).$mount()
+    vm.deep.a.b = 'bar'
+  })
 })