Repository: sveltejs/svelte (JavaScript) — Feature

Issue:
await...then shorthand
Follow-up to #952. This...

```html
{{#await promise then foo}}
  <p>{{foo}}</p>
{{/await}}
```

...would be a nice shorthand for this:

```html
{{#await promise}}
  <!-- no need to show a pending state -->
{{then foo}}
  <p>{{foo}}</p>
{{catch error}}
  <!-- promise is guaranteed to fulfil -->
{{/await}}
```


Discussion:
I'd recommend an implicit variable as an option, since seeing `await` and `then` together seems strange.

Coming from a groovy background we always have `it`:

Explicit:
```groovy
def myVariable = 'foo'
myVariable.with { myVariable ->
  myVariable == 'foo'
}
```

Implicit:
```groovy
def myVariable = 'foo'
myVariable.with {
  it == 'foo'
}
```

So this would mean you could either have the implicit:

```javascript
{{#await foo}}
  {{it}} equals foo
{{/await}}
```

Or the explicit:
```javascript
{{#await foo then quux}}
  {{quux}} equals foo
{{/await}}
```

Sorry about the atrocious code examples, it's been a long day!

Resolving patch:
diff --git a/src/parse/state/mustache.ts b/src/parse/state/mustache.ts
--- a/src/parse/state/mustache.ts
+++ b/src/parse/state/mustache.ts
@@ -283,14 +283,22 @@ export default function mustache(parser: Parser) {
 			}
 		}
 
+		let awaitBlockShorthand = type === 'AwaitBlock' && parser.eat('then');
+		if (awaitBlockShorthand) {
+			parser.requireWhitespace();
+			block.value = parser.readIdentifier();
+			parser.allowWhitespace();
+		}
+
 		parser.eat('}}', true);
 
 		parser.current().children.push(block);
 		parser.stack.push(block);
 
 		if (type === 'AwaitBlock') {
-			block.pending.start = parser.index;
-			parser.stack.push(block.pending);
+			const childBlock = awaitBlockShorthand ? block.then : block.pending;
+			childBlock.start = parser.index;
+			parser.stack.push(childBlock);
 		}
 	} else if (parser.eat('yield')) {
 		// {{yield}}


Test patch:
diff --git a/test/runtime/samples/await-then-shorthand/_config.js b/test/runtime/samples/await-then-shorthand/_config.js
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/await-then-shorthand/_config.js
@@ -0,0 +1,45 @@
+let fulfil;
+
+let thePromise = new Promise(f => {
+	fulfil = f;
+});
+
+export default {
+	data: {
+		thePromise
+	},
+
+	html: ``,
+
+	test(assert, component, target) {
+		fulfil(42);
+
+		return thePromise
+			.then(() => {
+				assert.htmlEqual(target.innerHTML, `
+					<p>the value is 42</p>
+				`);
+
+				let reject;
+
+				thePromise = new Promise((f, r) => {
+					reject = r;
+				});
+
+				component.set({
+					thePromise
+				});
+
+				assert.htmlEqual(target.innerHTML, ``);
+
+				reject(new Error('something broke'));
+
+				return thePromise.catch(() => {});
+			})
+			.then(() => {
+				assert.htmlEqual(target.innerHTML, `
+					<p>oh no! something broke</p>
+				`);
+			});
+	}
+};
\ No newline at end of file
diff --git a/test/runtime/samples/await-then-shorthand/main.html b/test/runtime/samples/await-then-shorthand/main.html
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/await-then-shorthand/main.html
@@ -0,0 +1,5 @@
+{{#await thePromise then theValue}}
+	<p>the value is {{theValue}}</p>
+{{catch theError}}
+	<p>oh no! {{theError.message}}</p>
+{{/await}}
\ No newline at end of file