Repository: vuejs/vue
Pull request: feat(core): support KeyboardEvent.key for built in keyboard event modifiers, fix #6900

<!--
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)

- [ ] Bugfix
- [x] 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:**
#6900 

Changed files:
filename: src/core/instance/render-helpers/check-keycodes.js
patch: @@ -3,6 +3,26 @@
 import config from 'core/config'
 import { hyphenate } from 'shared/util'
 
+const keyNames: { [key: string]: string | Array<string> } = {
+  esc: 'Escape',
+  tab: 'Tab',
+  enter: 'Enter',
+  space: ' ',
+  up: 'ArrowUp',
+  left: 'ArrowLeft',
+  right: 'ArrowRight',
+  down: 'ArrowDown',
+  'delete': ['Backspace', 'Delete']
+}
+
+function isKeyNotMatch<T> (expect: T | Array<T>, actual: T): boolean {
+  if (Array.isArray(expect)) {
+    return expect.indexOf(actual) === -1
+  } else {
+    return expect !== actual
+  }
+}
+
 /**
  * Runtime helper for checking keyCodes from config.
  * exposed as Vue.prototype._k
@@ -15,12 +35,11 @@ export function checkKeyCodes (
   eventKeyName?: string
 ): ?boolean {
   const keyCodes = config.keyCodes[key] || builtInAlias
-  if (keyCodes) {
-    if (Array.isArray(keyCodes)) {
-      return keyCodes.indexOf(eventKeyCode) === -1
-    } else {
-      return keyCodes !== eventKeyCode
-    }
+  const builtInName: string | Array<string> = keyNames[key]
+  if (builtInName && keyCodes === builtInAlias && eventKeyName) {
+    return isKeyNotMatch(builtInName, eventKeyName)
+  } else if (keyCodes) {
+    return isKeyNotMatch(keyCodes, eventKeyCode)
   } else if (eventKeyName) {
     return hyphenate(eventKeyName) !== key
   }

filename: test/unit/features/directives/on.spec.js
patch: @@ -362,6 +362,35 @@ describe('Directive v-on', () => {
     expect(spyMiddle).toHaveBeenCalled()
   })
 
+  it('should support KeyboardEvent.key for built in aliases', () => {
+    vm = new Vue({
+      el,
+      template: `
+        <div>
+          <input ref="enter" @keyup.enter="foo">
+          <input ref="space" @keyup.space="foo">
+          <input ref="esc" @keyup.esc="foo">
+          <input ref="left" @keyup.left="foo">
+          <input ref="delete" @keyup.delete="foo">
+        </div>
+      `,
+      methods: { foo: spy }
+    })
+
+    triggerEvent(vm.$refs.enter, 'keyup', e => { e.key = 'Enter' })
+    expect(spy.calls.count()).toBe(1)
+    triggerEvent(vm.$refs.space, 'keyup', e => { e.key = ' ' })
+    expect(spy.calls.count()).toBe(2)
+    triggerEvent(vm.$refs.esc, 'keyup', e => { e.key = 'Escape' })
+    expect(spy.calls.count()).toBe(3)
+    triggerEvent(vm.$refs.left, 'keyup', e => { e.key = 'ArrowLeft' })
+    expect(spy.calls.count()).toBe(4)
+    triggerEvent(vm.$refs.delete, 'keyup', e => { e.key = 'Backspace' })
+    expect(spy.calls.count()).toBe(5)
+    triggerEvent(vm.$refs.delete, 'keyup', e => { e.key = 'Delete' })
+    expect(spy.calls.count()).toBe(6)
+  })
+
   it('should support custom keyCode', () => {
     Vue.config.keyCodes.test = 1
     vm = new Vue({