Repository: vuejs/vue
Pull request: fix #9042, #7138: handle empty placeholder case in IE

<!--
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:**
Before this fix, the workaround for #9042 was to provide null or false value instead of empty string: `:placeholder="placeholder || null"`. 
The fix from #7138 was incomplete as it did not account for the case when placeholder attribute exists but is empty and the bug is **not** triggered in IE.
A new test case ensures the first triggered event does not get blocked.

Changed files:
filename: src/platforms/web/runtime/modules/attrs.js
patch: @@ -98,8 +98,8 @@ function baseSetAttr (el, key, value) {
     /* istanbul ignore if */
     if (
       isIE && !isIE9 &&
-      (el.tagName === 'TEXTAREA' || el.tagName === 'INPUT') &&
-      key === 'placeholder' && !el.__ieph
+      el.tagName === 'TEXTAREA' &&
+      key === 'placeholder' && value !== '' && !el.__ieph
     ) {
       const blocker = e => {
         e.stopImmediatePropagation()

filename: test/unit/features/directives/model-text.spec.js
patch: @@ -437,8 +437,8 @@ describe('Directive v-model text', () => {
     })
   }
 
-  // #7138
   if (isIE && !isIE9) {
+    // #7138
     it('should not fire input on initial render of textarea with placeholder in IE10/11', done => {
       const el = document.createElement('div')
       document.body.appendChild(el)
@@ -452,5 +452,21 @@ describe('Directive v-model text', () => {
         done()
       }, 17)
     })
+
+    // #9042
+    it('should not block the first input event when placeholder is empty', done => {
+      const el = document.createElement('div')
+      document.body.appendChild(el)
+      const vm = new Vue({
+        el,
+        data: { evtCount: 0 },
+        template: `<textarea placeholder="" @input="evtCount++"></textarea>`,
+      })
+      triggerEvent(vm.$el, 'input')
+      setTimeout(() => {
+        expect(vm.evtCount).toBe(1)
+        done()
+      }, 17)
+    })
   }
 })