Repository: vuejs/vue
Pull request: fix(vue-template-compiler): allow comments on the root node in templates (fix #9407)

in SFC templates, we are alloed to have comments on the root node. We are not alloed to do so if we
try to extract these comments. This commits ignores the root components instead of breaking.

#9407

<!--
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:**


Changed files:
filename: src/compiler/parser/index.js
patch: @@ -377,16 +377,20 @@ export function parse (
       }
     },
     comment (text: string, start, end) {
-      const child: ASTText = {
-        type: 3,
-        text,
-        isComment: true
-      }
-      if (process.env.NODE_ENV !== 'production' && options.outputSourceRange) {
-        child.start = start
-        child.end = end
+      // adding anyting as a sibling to the root node is forbidden
+      // comments should still be allowed, but ignored
+      if (currentParent) {
+        const child: ASTText = {
+          type: 3,
+          text,
+          isComment: true
+        }
+        if (process.env.NODE_ENV !== 'production' && options.outputSourceRange) {
+          child.start = start
+          child.end = end
+        }
+        currentParent.children.push(child)
       }
-      currentParent.children.push(child)
     }
   })
   return root

filename: test/unit/modules/compiler/parser.spec.js
patch: @@ -786,6 +786,16 @@ describe('parser', () => {
     expect(ast.children[1].text).toBe('comment here')
   })
 
+  // #9407
+  it('should parse templates with comments anywhere', () => {
+    const options = extend({
+      comments: true
+    }, baseOptions)
+    const ast = parse(`<!--comment here--><div>123</div>`, options)
+    expect(ast.tag).toBe('div')
+    expect(ast.children.length).toBe(1)
+  })
+
   // #8103
   it('should allow CRLFs in string interpolations', () => {
     const ast = parse(`<p>{{\r\nmsg\r\n}}</p>`, baseOptions)
@@ -797,7 +807,7 @@ describe('parser', () => {
       preserveWhitespace: false
     }, baseOptions)
 
-     const ast = parse('<p>\n  Welcome to <b>Vue.js</b>    <i>world</i>  \n  <span>.\n  Have fun!\n</span></p>', options)
+    const ast = parse('<p>\n  Welcome to <b>Vue.js</b>    <i>world</i>  \n  <span>.\n  Have fun!\n</span></p>', options)
     expect(ast.tag).toBe('p')
     expect(ast.children.length).toBe(4)
     expect(ast.children[0].type).toBe(3)