Skip to content

Commit 7a732e7

Browse files
authored
(fix) await without then (#432)
* (fix) await without then #427 * (refactor) move htmlxtojsx into own folder
1 parent a032ff2 commit 7a732e7

File tree

7 files changed

+151
-89
lines changed

7 files changed

+151
-89
lines changed

packages/svelte2tsx/rollup.config.test.js

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,36 +5,51 @@ import json from 'rollup-plugin-json';
55
import del from 'rollup-plugin-delete';
66
import builtins from 'builtin-modules';
77

8-
export default [{
9-
input: ['src/index.ts'],
10-
output: {
11-
sourcemap: true,
12-
format: 'commonjs',
13-
file: 'test/build/index.js'
14-
},
15-
plugins: [
16-
del({ targets: 'test/build/index.*' }),
17-
resolve({ browser: false, preferBuiltins: true }),
18-
commonjs(),
19-
json(),
20-
typescript()
21-
],
22-
external: [...builtins, 'typescript', 'svelte', 'svelte/compiler', 'parse5', 'magic-string']
23-
}, {
24-
input: ['src/htmlxtojsx.ts'],
25-
output: {
26-
sourcemap: true,
27-
format: 'commonjs',
28-
file: 'test/build/htmlxtojsx.js'
29-
},
30-
plugins: [
31-
del({ targets: 'test/build/htmlxtojsx.*' }),
32-
resolve({ browser: false, preferBuiltins: true }),
33-
commonjs(),
34-
json(),
35-
typescript()
36-
],
37-
external: [...builtins, 'typescript', 'svelte', 'svelte/compiler', 'parse5', 'magic-string']
38-
39-
}
8+
export default [
9+
{
10+
input: ['src/index.ts'],
11+
output: {
12+
sourcemap: true,
13+
format: 'commonjs',
14+
file: 'test/build/index.js',
15+
},
16+
plugins: [
17+
del({ targets: 'test/build/index.*' }),
18+
resolve({ browser: false, preferBuiltins: true }),
19+
commonjs(),
20+
json(),
21+
typescript(),
22+
],
23+
external: [
24+
...builtins,
25+
'typescript',
26+
'svelte',
27+
'svelte/compiler',
28+
'parse5',
29+
'magic-string',
30+
],
31+
},
32+
{
33+
input: ['src/htmlxtojsx/index.ts'],
34+
output: {
35+
sourcemap: true,
36+
format: 'commonjs',
37+
file: 'test/build/htmlxtojsx.js',
38+
},
39+
plugins: [
40+
del({ targets: 'test/build/htmlxtojsx.*' }),
41+
resolve({ browser: false, preferBuiltins: true }),
42+
commonjs(),
43+
json(),
44+
typescript(),
45+
],
46+
external: [
47+
...builtins,
48+
'typescript',
49+
'svelte',
50+
'svelte/compiler',
51+
'parse5',
52+
'magic-string',
53+
],
54+
},
4055
];

packages/svelte2tsx/src/htmlxtojsx.ts renamed to packages/svelte2tsx/src/htmlxtojsx/index.ts

Lines changed: 3 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import MagicString from 'magic-string';
22
import svelte from 'svelte/compiler';
33
import { Node } from 'estree-walker';
4-
import { parseHtmlx } from './htmlxparser';
4+
import { parseHtmlx } from '../htmlxparser';
55
import svgAttributes from './svgattributes';
66
import { getTypeForComponent } from './nodes/component-type';
7+
import { handleAwait } from './nodes/await-block';
78

89
type ElementType = string;
910
const oneWayBindingAttributes: Map<string, ElementType> = new Map(
@@ -544,61 +545,6 @@ export function convertHtmlxToJsx(
544545
}
545546
};
546547

547-
// {#await somePromise then value} ->
548-
// {() => {let _$$p = (somePromise);
549-
const handleAwait = (awaitBlock: Node) => {
550-
str.overwrite(awaitBlock.start, awaitBlock.expression.start, '{() => {let _$$p = (');
551-
// then value } | {:then value} ->
552-
// __sveltets_awaitThen(_$$p, (value) => {<>
553-
let thenStart: number;
554-
let thenEnd: number;
555-
if (!awaitBlock.pending.skip) {
556-
//thenBlock includes the {:then}
557-
thenStart = awaitBlock.then.start;
558-
if (awaitBlock.value) {
559-
thenEnd = htmlx.indexOf('}', awaitBlock.value.end) + 1;
560-
} else {
561-
thenEnd = htmlx.indexOf('}', awaitBlock.then.start) + 1;
562-
}
563-
str.prependLeft(thenStart, '</>; ');
564-
// add the start tag too
565-
const awaitEnd = htmlx.indexOf('}', awaitBlock.expression.end);
566-
567-
// somePromise} -> somePromise);
568-
str.overwrite(awaitBlock.expression.end, awaitEnd + 1, ');');
569-
str.appendRight(awaitEnd + 1, ' <>');
570-
} else {
571-
thenEnd = htmlx.lastIndexOf('}', awaitBlock.then.start) + 1;
572-
thenStart = htmlx.indexOf('then', awaitBlock.expression.end);
573-
574-
// somePromise then -> somePromise); then
575-
str.overwrite(awaitBlock.expression.end, thenStart, '); ');
576-
}
577-
if (awaitBlock.value) {
578-
str.overwrite(thenStart, awaitBlock.value.start, '__sveltets_awaitThen(_$$p, (');
579-
str.overwrite(awaitBlock.value.end, thenEnd, ') => {<>');
580-
} else {
581-
str.overwrite(thenStart, thenEnd, '__sveltets_awaitThen(_$$p, () => {<>');
582-
}
583-
//{:catch error} ->
584-
//</>}, (error) => {<>
585-
if (!awaitBlock.catch.skip) {
586-
//catch block includes the {:catch}
587-
const catchStart = awaitBlock.catch.start;
588-
const catchSymbolEnd = htmlx.indexOf(':catch', catchStart) + ':catch'.length;
589-
590-
const errorStart = awaitBlock.error ? awaitBlock.error.start : catchSymbolEnd;
591-
const errorEnd = awaitBlock.error ? awaitBlock.error.end : errorStart;
592-
const catchEnd = htmlx.indexOf('}', errorEnd) + 1;
593-
str.overwrite(catchStart, errorStart, '</>}, (');
594-
str.overwrite(errorEnd, catchEnd, ') => {<>');
595-
}
596-
// {/await} ->
597-
// <>})}
598-
const awaitEndStart = htmlx.lastIndexOf('{', awaitBlock.end);
599-
str.overwrite(awaitEndStart, awaitBlock.end, '</>})}}');
600-
};
601-
602548
const handleComment = (node: Node) => {
603549
str.remove(node.start, node.end);
604550
};
@@ -628,7 +574,7 @@ export function convertHtmlxToJsx(
628574
handleElse(node, parent);
629575
break;
630576
case 'AwaitBlock':
631-
handleAwait(node);
577+
handleAwait(htmlx, str, node);
632578
break;
633579
case 'RawMustacheTag':
634580
handleRaw(node);
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import MagicString from 'magic-string';
2+
import { Node } from 'estree-walker';
3+
4+
/**
5+
* Transform {#await ...} into something JSX understands
6+
*/
7+
export function handleAwait(htmlx: string, str: MagicString, awaitBlock: Node): void {
8+
// {#await somePromise then value} ->
9+
// {() => {let _$$p = (somePromise);
10+
str.overwrite(awaitBlock.start, awaitBlock.expression.start, '{() => {let _$$p = (');
11+
12+
// then value } | {:then value} | {await ..} .. {/await} ->
13+
// __sveltets_awaitThen(_$$p, (value) => {<>
14+
let thenStart: number;
15+
let thenEnd: number;
16+
if (!awaitBlock.then.skip) {
17+
// then value } | {:then value}
18+
if (!awaitBlock.pending.skip) {
19+
// {await ...} ... {:then ...}
20+
// thenBlock includes the {:then}
21+
thenStart = awaitBlock.then.start;
22+
if (awaitBlock.value) {
23+
thenEnd = htmlx.indexOf('}', awaitBlock.value.end) + 1;
24+
} else {
25+
thenEnd = htmlx.indexOf('}', awaitBlock.then.start) + 1;
26+
}
27+
str.prependLeft(thenStart, '</>; ');
28+
// add the start tag too
29+
const awaitEnd = htmlx.indexOf('}', awaitBlock.expression.end);
30+
31+
// somePromise} -> somePromise);
32+
str.overwrite(awaitBlock.expression.end, awaitEnd + 1, ');');
33+
str.appendRight(awaitEnd + 1, ' <>');
34+
} else {
35+
// {await ... then ...}
36+
thenStart = htmlx.indexOf('then', awaitBlock.expression.end);
37+
thenEnd = htmlx.lastIndexOf('}', awaitBlock.then.start) + 1;
38+
// somePromise then -> somePromise); then
39+
str.overwrite(awaitBlock.expression.end, thenStart, '); ');
40+
}
41+
} else {
42+
// {await ..} ... ({:catch ..}) {/await} -> no then block, no value, but always a pending block
43+
thenEnd = awaitBlock.catch.skip
44+
? htmlx.lastIndexOf('{', awaitBlock.end)
45+
: awaitBlock.catch.start;
46+
thenStart = Math.min(awaitBlock.pending.end + 1, thenEnd);
47+
48+
const awaitEnd = htmlx.indexOf('}', awaitBlock.expression.end);
49+
str.overwrite(awaitBlock.expression.end, awaitEnd + 1, ');');
50+
str.appendRight(awaitEnd + 1, ' <>');
51+
str.appendLeft(thenEnd, '</>; ');
52+
}
53+
54+
if (awaitBlock.value) {
55+
str.overwrite(thenStart, awaitBlock.value.start, '__sveltets_awaitThen(_$$p, (');
56+
str.overwrite(awaitBlock.value.end, thenEnd, ') => {<>');
57+
} else {
58+
const awaitThenFn = '__sveltets_awaitThen(_$$p, () => {<>';
59+
if (thenStart === thenEnd) {
60+
str.appendLeft(thenStart, awaitThenFn);
61+
} else {
62+
str.overwrite(thenStart, thenEnd, awaitThenFn);
63+
}
64+
}
65+
66+
//{:catch error} ->
67+
//</>}, (error) => {<>
68+
if (!awaitBlock.catch.skip) {
69+
//catch block includes the {:catch}
70+
const catchStart = awaitBlock.catch.start;
71+
const catchSymbolEnd = htmlx.indexOf(':catch', catchStart) + ':catch'.length;
72+
73+
const errorStart = awaitBlock.error ? awaitBlock.error.start : catchSymbolEnd;
74+
const errorEnd = awaitBlock.error ? awaitBlock.error.end : errorStart;
75+
const catchEnd = htmlx.indexOf('}', errorEnd) + 1;
76+
str.overwrite(catchStart, errorStart, '</>}, (');
77+
str.overwrite(errorEnd, catchEnd, ') => {<>');
78+
}
79+
// {/await} ->
80+
// <>})}
81+
const awaitEndStart = htmlx.lastIndexOf('{', awaitBlock.end);
82+
str.overwrite(awaitEndStart, awaitBlock.end, '</>})}}');
83+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<>{() => {let _$$p = (aPromise); <>
2+
<div>Spinner...</div>
3+
</>; __sveltets_awaitThen(_$$p, () => {<></>})}}
4+
5+
{() => {let _$$p = (aPromise); <>
6+
<div>Spinner...</div>
7+
</>; __sveltets_awaitThen(_$$p, () => {<></>}, (error) => {<>
8+
<div>Ups: {error}</div>
9+
</>})}}</>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{#await aPromise}
2+
<div>Spinner...</div>
3+
{/await}
4+
5+
{#await aPromise}
6+
<div>Spinner...</div>
7+
{:catch error}
8+
<div>Ups: {error}</div>
9+
{/await}

0 commit comments

Comments
 (0)