compiler-sfc: HTML comment nodes are missing from element children when the element is a Vue transition
Vue version
3.3.4
Link to minimal reproduction
https://github.com/Sidnioulz/vue-sfcmod/blob/feat/template/src/template/__tests__/stringify.spec.ts
Steps to reproduce
- Use
compileTemplate
to compile with the following pattern:<Transition><!-- Comment --><input /></Transition>
- Explore the AST
- Notice the absence of a children node for the comment
What is expected?
There should be a node in the children with type 3 / COMMENT, which contains the comment.
What is actually happening?
It seems that when the element node is a Vue transition, specifically, comment nodes are missing. TransitionGroup works fine, though.
System Info
No response
Any additional comments?
I'm writing a codemod engine for Vue templates and this issue prevents me from preserving comments in templates.
For repro, I have a unit test suite with a test named 'Comment inside transition'. It may have been merged to main by the time you read this, though.
Relevant code in core: https://github.com/vuejs/core/blob/main/packages/compiler-dom/__tests__/transforms/Transition.spec.ts#L150. This is intentional, though I don't understand what the harm is in preserving comments.
set compilerOptions.comments
to true
see https://vuejs.org/api/options-rendering.html#compileroptions
Upon checking with the option on, I still think there's a bug with transition
.
Attached are two ASTs, one for <Transition><!-- Comment --><input /></Transition>
and one for <form><!-- Comment --><input /></form>
.
On the Transition AST, you can see that there is no child node of NodeType.COMMENT
, whereas on the form AST, it's rendered.
Transition AST
{
"type": 0,
"children": [
{
"type": 1,
"ns": 0,
"tag": "Transition",
"tagType": 1,
"props": [],
"isSelfClosing": false,
"children": [
{
"type": 1,
"ns": 0,
"tag": "input",
"tagType": 0,
"props": [],
"isSelfClosing": true,
"children": [],
"loc": {
"start": {
"column": 29,
"line": 1,
"offset": 28
},
"end": {
"column": 38,
"line": 1,
"offset": 37
},
"source": "<input />"
},
"codegenNode": {
"type": 4,
"loc": {
"start": {
"column": 29,
"line": 1,
"offset": 28
},
"end": {
"column": 38,
"line": 1,
"offset": 37
},
"source": "<input />"
},
"content": "_hoisted_1",
"isStatic": false,
"constType": 2,
"hoisted": {
"type": 13,
"tag": "\"input\"",
"patchFlag": "-1 /* HOISTED */",
"isBlock": false,
"disableTracking": false,
"isComponent": false,
"loc": {
"start": {
"column": 29,
"line": 1,
"offset": 28
},
"end": {
"column": 38,
"line": 1,
"offset": 37
},
"source": "<input />"
}
}
}
}
],
"loc": {
"start": {
"column": 1,
"line": 1,
"offset": 0
},
"end": {
"column": 51,
"line": 1,
"offset": 50
},
"source": "<Transition><!-- Comment --><input /></Transition>"
},
"codegenNode": {
"type": 13,
"children": {
"type": 15,
"loc": {
"start": {
"column": 1,
"line": 1,
"offset": 0
},
"end": {
"column": 51,
"line": 1,
"offset": 50
},
"source": "<Transition><!-- Comment --><input /></Transition>"
},
"properties": [
{
"type": 16,
"loc": {
"source": "",
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 1,
"column": 1,
"offset": 0
}
},
"key": {
"type": 4,
"loc": {
"source": "",
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 1,
"column": 1,
"offset": 0
}
},
"content": "default",
"isStatic": true,
"constType": 3
},
"value": {
"type": 18,
"returns": [
{
"type": 1,
"ns": 0,
"tag": "input",
"tagType": 0,
"props": [],
"isSelfClosing": true,
"children": [],
"loc": {
"start": {
"column": 29,
"line": 1,
"offset": 28
},
"end": {
"column": 38,
"line": 1,
"offset": 37
},
"source": "<input />"
},
"codegenNode": {
"type": 4,
"loc": {
"start": {
"column": 29,
"line": 1,
"offset": 28
},
"end": {
"column": 38,
"line": 1,
"offset": 37
},
"source": "<input />"
},
"content": "_hoisted_1",
"isStatic": false,
"constType": 2,
"hoisted": {
"type": 13,
"tag": "\"input\"",
"patchFlag": "-1 /* HOISTED */",
"isBlock": false,
"disableTracking": false,
"isComponent": false,
"loc": {
"start": {
"column": 29,
"line": 1,
"offset": 28
},
"end": {
"column": 38,
"line": 1,
"offset": 37
},
"source": "<input />"
}
}
}
}
],
"newline": false,
"isSlot": true,
"loc": {
"start": {
"column": 29,
"line": 1,
"offset": 28
},
"end": {
"column": 38,
"line": 1,
"offset": 37
},
"source": "<input />"
}
}
},
{
"type": 16,
"loc": {
"source": "",
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 1,
"column": 1,
"offset": 0
}
},
"key": {
"type": 4,
"loc": {
"source": "",
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 1,
"column": 1,
"offset": 0
}
},
"content": "_",
"isStatic": true,
"constType": 3
},
"value": {
"type": 4,
"loc": {
"source": "",
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 1,
"column": 1,
"offset": 0
}
},
"content": "1 /* STABLE */",
"isStatic": false,
"constType": 0
}
}
]
},
"isBlock": true,
"disableTracking": false,
"isComponent": true,
"loc": {
"start": {
"column": 1,
"line": 1,
"offset": 0
},
"end": {
"column": 51,
"line": 1,
"offset": 50
},
"source": "<Transition><!-- Comment --><input /></Transition>"
}
}
}
],
"helpers": {},
"components": [],
"directives": [],
"hoists": [
{
"type": 13,
"tag": "\"input\"",
"patchFlag": "-1 /* HOISTED */",
"isBlock": false,
"disableTracking": false,
"isComponent": false,
"loc": {
"start": {
"column": 29,
"line": 1,
"offset": 28
},
"end": {
"column": 38,
"line": 1,
"offset": 37
},
"source": "<input />"
}
}
],
"imports": [],
"cached": 0,
"temps": 0,
"codegenNode": {
"type": 13,
"children": {
"type": 15,
"loc": {
"start": {
"column": 1,
"line": 1,
"offset": 0
},
"end": {
"column": 51,
"line": 1,
"offset": 50
},
"source": "<Transition><!-- Comment --><input /></Transition>"
},
"properties": [
{
"type": 16,
"loc": {
"source": "",
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 1,
"column": 1,
"offset": 0
}
},
"key": {
"type": 4,
"loc": {
"source": "",
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 1,
"column": 1,
"offset": 0
}
},
"content": "default",
"isStatic": true,
"constType": 3
},
"value": {
"type": 18,
"returns": [
{
"type": 1,
"ns": 0,
"tag": "input",
"tagType": 0,
"props": [],
"isSelfClosing": true,
"children": [],
"loc": {
"start": {
"column": 29,
"line": 1,
"offset": 28
},
"end": {
"column": 38,
"line": 1,
"offset": 37
},
"source": "<input />"
},
"codegenNode": {
"type": 4,
"loc": {
"start": {
"column": 29,
"line": 1,
"offset": 28
},
"end": {
"column": 38,
"line": 1,
"offset": 37
},
"source": "<input />"
},
"content": "_hoisted_1",
"isStatic": false,
"constType": 2,
"hoisted": {
"type": 13,
"tag": "\"input\"",
"patchFlag": "-1 /* HOISTED */",
"isBlock": false,
"disableTracking": false,
"isComponent": false,
"loc": {
"start": {
"column": 29,
"line": 1,
"offset": 28
},
"end": {
"column": 38,
"line": 1,
"offset": 37
},
"source": "<input />"
}
}
}
}
],
"newline": false,
"isSlot": true,
"loc": {
"start": {
"column": 29,
"line": 1,
"offset": 28
},
"end": {
"column": 38,
"line": 1,
"offset": 37
},
"source": "<input />"
}
}
},
{
"type": 16,
"loc": {
"source": "",
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 1,
"column": 1,
"offset": 0
}
},
"key": {
"type": 4,
"loc": {
"source": "",
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 1,
"column": 1,
"offset": 0
}
},
"content": "_",
"isStatic": true,
"constType": 3
},
"value": {
"type": 4,
"loc": {
"source": "",
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 1,
"column": 1,
"offset": 0
}
},
"content": "1 /* STABLE */",
"isStatic": false,
"constType": 0
}
}
]
},
"isBlock": true,
"disableTracking": false,
"isComponent": true,
"loc": {
"start": {
"column": 1,
"line": 1,
"offset": 0
},
"end": {
"column": 51,
"line": 1,
"offset": 50
},
"source": "<Transition><!-- Comment --><input /></Transition>"
}
},
"loc": {
"start": {
"column": 1,
"line": 1,
"offset": 0
},
"end": {
"column": 51,
"line": 1,
"offset": 50
},
"source": "<Transition><!-- Comment --><input /></Transition>"
},
"filters": []
}
Form AST
{
"type": 0,
"children": [
{
"type": 1,
"ns": 0,
"tag": "form",
"tagType": 0,
"props": [],
"isSelfClosing": false,
"children": [
{
"type": 3,
"content": " Comment ",
"loc": {
"start": {
"column": 7,
"line": 1,
"offset": 6
},
"end": {
"column": 23,
"line": 1,
"offset": 22
},
"source": "<!-- Comment -->"
}
},
{
"type": 1,
"ns": 0,
"tag": "input",
"tagType": 0,
"props": [],
"isSelfClosing": true,
"children": [],
"loc": {
"start": {
"column": 23,
"line": 1,
"offset": 22
},
"end": {
"column": 32,
"line": 1,
"offset": 31
},
"source": "<input />"
},
"codegenNode": {
"type": 4,
"loc": {
"start": {
"column": 23,
"line": 1,
"offset": 22
},
"end": {
"column": 32,
"line": 1,
"offset": 31
},
"source": "<input />"
},
"content": "_hoisted_1",
"isStatic": false,
"constType": 2,
"hoisted": {
"type": 13,
"tag": "\"input\"",
"patchFlag": "-1 /* HOISTED */",
"isBlock": false,
"disableTracking": false,
"isComponent": false,
"loc": {
"start": {
"column": 23,
"line": 1,
"offset": 22
},
"end": {
"column": 32,
"line": 1,
"offset": 31
},
"source": "<input />"
}
}
}
}
],
"loc": {
"start": {
"column": 1,
"line": 1,
"offset": 0
},
"end": {
"column": 39,
"line": 1,
"offset": 38
},
"source": "<form><!-- Comment --><input /></form>"
},
"codegenNode": {
"type": 13,
"tag": "\"form\"",
"children": [
{
"type": 3,
"content": " Comment ",
"loc": {
"start": {
"column": 7,
"line": 1,
"offset": 6
},
"end": {
"column": 23,
"line": 1,
"offset": 22
},
"source": "<!-- Comment -->"
}
},
{
"type": 1,
"ns": 0,
"tag": "input",
"tagType": 0,
"props": [],
"isSelfClosing": true,
"children": [],
"loc": {
"start": {
"column": 23,
"line": 1,
"offset": 22
},
"end": {
"column": 32,
"line": 1,
"offset": 31
},
"source": "<input />"
},
"codegenNode": {
"type": 4,
"loc": {
"start": {
"column": 23,
"line": 1,
"offset": 22
},
"end": {
"column": 32,
"line": 1,
"offset": 31
},
"source": "<input />"
},
"content": "_hoisted_1",
"isStatic": false,
"constType": 2,
"hoisted": {
"type": 13,
"tag": "\"input\"",
"patchFlag": "-1 /* HOISTED */",
"isBlock": false,
"disableTracking": false,
"isComponent": false,
"loc": {
"start": {
"column": 23,
"line": 1,
"offset": 22
},
"end": {
"column": 32,
"line": 1,
"offset": 31
},
"source": "<input />"
}
}
}
}
],
"isBlock": true,
"disableTracking": false,
"isComponent": false,
"loc": {
"start": {
"column": 1,
"line": 1,
"offset": 0
},
"end": {
"column": 39,
"line": 1,
"offset": 38
},
"source": "<form><!-- Comment --><input /></form>"
}
}
}
],
"helpers": {},
"components": [],
"directives": [],
"hoists": [
{
"type": 13,
"tag": "\"input\"",
"patchFlag": "-1 /* HOISTED */",
"isBlock": false,
"disableTracking": false,
"isComponent": false,
"loc": {
"start": {
"column": 23,
"line": 1,
"offset": 22
},
"end": {
"column": 32,
"line": 1,
"offset": 31
},
"source": "<input />"
}
}
],
"imports": [],
"cached": 0,
"temps": 0,
"codegenNode": {
"type": 13,
"tag": "\"form\"",
"children": [
{
"type": 3,
"content": " Comment ",
"loc": {
"start": {
"column": 7,
"line": 1,
"offset": 6
},
"end": {
"column": 23,
"line": 1,
"offset": 22
},
"source": "<!-- Comment -->"
}
},
{
"type": 1,
"ns": 0,
"tag": "input",
"tagType": 0,
"props": [],
"isSelfClosing": true,
"children": [],
"loc": {
"start": {
"column": 23,
"line": 1,
"offset": 22
},
"end": {
"column": 32,
"line": 1,
"offset": 31
},
"source": "<input />"
},
"codegenNode": {
"type": 4,
"loc": {
"start": {
"column": 23,
"line": 1,
"offset": 22
},
"end": {
"column": 32,
"line": 1,
"offset": 31
},
"source": "<input />"
},
"content": "_hoisted_1",
"isStatic": false,
"constType": 2,
"hoisted": {
"type": 13,
"tag": "\"input\"",
"patchFlag": "-1 /* HOISTED */",
"isBlock": false,
"disableTracking": false,
"isComponent": false,
"loc": {
"start": {
"column": 23,
"line": 1,
"offset": 22
},
"end": {
"column": 32,
"line": 1,
"offset": 31
},
"source": "<input />"
}
}
}
}
],
"isBlock": true,
"disableTracking": false,
"isComponent": false,
"loc": {
"start": {
"column": 1,
"line": 1,
"offset": 0
},
"end": {
"column": 39,
"line": 1,
"offset": 38
},
"source": "<form><!-- Comment --><input /></form>"
}
},
"loc": {
"start": {
"column": 1,
"line": 1,
"offset": 0
},
"end": {
"column": 39,
"line": 1,
"offset": 38
},
"source": "<form><!-- Comment --><input /></form>"
},
"filters": []
}