Repository: sveltejs/svelte (JavaScript)
Date: 2021-07-19 15:50:47+00:00
Task type: Bug Fix

Issue:
Parser wrong positions in attribute values that include mustache tags
https://astexplorer.net/#/gist/7493c123a3c10eade136578aa9ebf4c8/6dc1f7f10625232aa5d214091bf3d6769b2e0558
```svelte
<input foo=a{1} />
```
```json
{
  "start": 11,
  "end": 13,
  "type": "Text",
  "raw": "a",
  "data": "a"
}      
```
Expected `"end": 12`


Issue discussion:
Correction this happens on every attribute value that has mustache tags, so even `style="color:{color};"` has wrong end position for the first Text node

https://astexplorer.net/#/gist/09380864606687886956085fb0442755/e48a32b2ea9a2a3d3fb5116495c30d7c025d87ff

Solution patch:
diff --git a/src/compiler/parse/state/tag.ts b/src/compiler/parse/state/tag.ts
--- a/src/compiler/parse/state/tag.ts
+++ b/src/compiler/parse/state/tag.ts
@@ -487,10 +487,10 @@ function read_sequence(parser: Parser, done: () => boolean): TemplateNode[] {
 		data: null
 	};
 
-	function flush() {
+	function flush(end: number) {
 		if (current_chunk.raw) {
 			current_chunk.data = decode_character_references(current_chunk.raw);
-			current_chunk.end = parser.index;
+			current_chunk.end = end;
 			chunks.push(current_chunk);
 		}
 	}
@@ -501,10 +501,10 @@ function read_sequence(parser: Parser, done: () => boolean): TemplateNode[] {
 		const index = parser.index;
 
 		if (done()) {
-			flush();
+			flush(parser.index);
 			return chunks;
 		} else if (parser.eat('{')) {
-			flush();
+			flush(parser.index - 1);
 
 			parser.allow_whitespace();
 			const expression = read_expression(parser);


Test patch:
diff --git a/test/parser/samples/attribute-curly-bracket/input.svelte b/test/parser/samples/attribute-curly-bracket/input.svelte
new file mode 100644
--- /dev/null
+++ b/test/parser/samples/attribute-curly-bracket/input.svelte
@@ -0,0 +1 @@
+<input foo=a{1} />
diff --git a/test/parser/samples/attribute-curly-bracket/output.json b/test/parser/samples/attribute-curly-bracket/output.json
new file mode 100644
--- /dev/null
+++ b/test/parser/samples/attribute-curly-bracket/output.json
@@ -0,0 +1,55 @@
+{
+  "html": {
+    "start": 0,
+    "end": 18,
+    "type": "Fragment",
+    "children": [
+      {
+        "start": 0,
+        "end": 18,
+        "type": "Element",
+        "name": "input",
+        "attributes": [
+          {
+            "start": 7,
+            "end": 15,
+            "type": "Attribute",
+            "name": "foo",
+            "value": [
+              {
+                "start": 11,
+                "end": 12,
+                "type": "Text",
+                "raw": "a",
+                "data": "a"
+              },
+              {
+                "start": 12,
+                "end": 15,
+                "type": "MustacheTag",
+                "expression": {
+                  "type": "Literal",
+                  "start": 13,
+                  "end": 14,
+                  "loc": {
+                    "start": {
+                      "line": 1,
+                      "column": 13
+                    },
+                    "end": {
+                      "line": 1,
+                      "column": 14
+                    }
+                  },
+                  "value": 1,
+                  "raw": "1"
+                }
+              }
+            ]
+          }
+        ],
+        "children": []
+      }
+    ]
+  }
+}
diff --git a/test/parser/samples/attribute-dynamic/output.json b/test/parser/samples/attribute-dynamic/output.json
--- a/test/parser/samples/attribute-dynamic/output.json
+++ b/test/parser/samples/attribute-dynamic/output.json
@@ -18,7 +18,7 @@
 						"value": [
 							{
 								"start": 12,
-								"end": 20,
+								"end": 19,
 								"type": "Text",
 								"raw": "color: ",
 								"data": "color: "
@@ -80,4 +80,4 @@
 			}
 		]
 	}
-}
\ No newline at end of file
+}
diff --git a/test/parser/samples/textarea-children/output.json b/test/parser/samples/textarea-children/output.json
--- a/test/parser/samples/textarea-children/output.json
+++ b/test/parser/samples/textarea-children/output.json
@@ -13,7 +13,7 @@
 				"children": [
 					{
 						"start": 10,
-						"end": 41,
+						"end": 40,
 						"type": "Text",
 						"raw": "\n\t<p>not actually an element. ",
 						"data": "\n\t<p>not actually an element. "
diff --git a/test/parser/samples/textarea-end-tag/output.json b/test/parser/samples/textarea-end-tag/output.json
--- a/test/parser/samples/textarea-end-tag/output.json
+++ b/test/parser/samples/textarea-end-tag/output.json
@@ -13,7 +13,7 @@
 				"children": [
 					{
 						"start": 10,
-						"end": 51,
+						"end": 50,
 						"type": "Text",
 						"raw": "\n\t<p>not actu </textar ally an element. ",
 						"data": "\n\t<p>not actu </textar ally an element. "
@@ -50,4 +50,4 @@
 			}
 		]
 	}
-}
\ No newline at end of file
+}