Skip to content

Commit 2aae90e

Browse files
authored
(fix) handle missing semicolon in reactive assignment + store situation (#1105)
#1097
1 parent b140473 commit 2aae90e

File tree

5 files changed

+83
-4
lines changed

5 files changed

+83
-4
lines changed

packages/svelte2tsx/src/svelte2tsx/nodes/ImplicitStoreValues.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import MagicString from 'magic-string';
22
import ts from 'typescript';
33
import { surroundWithIgnoreComments } from '../../utils/ignore';
4+
import { preprendStr } from '../../utils/magic-string';
45
import { extractIdentifiers, getNamesFromLabeledStatement } from '../utils/tsAst';
56

67
/**
@@ -84,7 +85,14 @@ export class ImplicitStoreValues {
8485
);
8586
const endPos = node.getEnd() + astOffset;
8687

87-
str.appendRight(endPos, storeDeclarations);
88+
// Hack for quick-fixing https://github.com/sveltejs/language-tools/issues/1097
89+
// TODO think about a SourceMap-wrapper that does these things for us,
90+
// or investigate altering the inner workings of SourceMap
91+
if (str.original.charAt(endPos - 1) !== ';') {
92+
preprendStr(str, endPos, storeDeclarations);
93+
} else {
94+
str.appendRight(endPos, storeDeclarations);
95+
}
8896
}
8997

9098
private attachStoreValueDeclarationOfImportsToRenderFn(str: MagicString) {

packages/svelte2tsx/src/svelte2tsx/nodes/ImplicitTopLevelNames.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
isParenthesizedObjectOrArrayLiteralExpression,
55
getNamesFromLabeledStatement
66
} from '../utils/tsAst';
7-
import { preprendStr } from '../../utils/magic-string';
7+
import { overwriteStr, preprendStr } from '../../utils/magic-string';
88

99
export class ImplicitTopLevelNames {
1010
private map = new Set<ts.LabeledStatement>();
@@ -91,7 +91,7 @@ export class ImplicitTopLevelNames {
9191
const end = node.statement.expression.getEnd() + this.astOffset - 1;
9292
// We need to keep the `)` of the "wrap with invalidate" expression above.
9393
// We overwrite the same range so it's needed.
94-
this.str.overwrite(end, end + 1, ')', { contentOnly: true });
94+
overwriteStr(this.str, end, ')', true);
9595
}
9696
}
9797
}

packages/svelte2tsx/src/utils/magic-string.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,43 @@ import MagicString from 'magic-string';
44
* Prepends a string at the given index in a way that the source map maps the appended string
55
* to the given character, not the previous character (as MagicString's other methods would).
66
*/
7-
export function preprendStr(str: MagicString, index: number, toAppend: string): MagicString {
7+
export function preprendStr(
8+
str: MagicString,
9+
index: number,
10+
toAppend: string,
11+
removeExisting?: boolean
12+
): MagicString {
13+
const prepends = updatePrepends(str, index, toAppend, removeExisting);
14+
toAppend = prepends.join('');
815
str.overwrite(index, index + 1, toAppend + str.original.charAt(index), { contentOnly: true });
916
return str;
1017
}
18+
19+
/**
20+
* Overwrites a string at the given index but also keeps the other preprends from `prependStr`
21+
* if not explicitely told otherwise.
22+
*/
23+
export function overwriteStr(
24+
str: MagicString,
25+
index: number,
26+
toOverwrite: string,
27+
removeExisting?: boolean
28+
): MagicString {
29+
const prepends = updatePrepends(str, index, toOverwrite, removeExisting);
30+
toOverwrite = prepends.join('');
31+
str.overwrite(index, index + 1, toOverwrite, { contentOnly: true });
32+
return str;
33+
}
34+
35+
function updatePrepends(
36+
str: MagicString,
37+
index: number,
38+
toAppend: string,
39+
removeExisting?: boolean
40+
) {
41+
(str as any).__prepends__ = (str as any).__prepends__ || new Map<string, string[]>();
42+
const prepends = removeExisting ? [] : (str as any).__prepends__.get(index) || [];
43+
prepends.push(toAppend);
44+
(str as any).__prepends__.set(index, prepends);
45+
return prepends;
46+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
///<reference types="svelte" />
2+
<></>;function render() {
3+
4+
const uid = readable('')/*Ωignore_startΩ*/;let $uid = __sveltets_1_store_get(uid);/*Ωignore_endΩ*/
5+
let foo1 = __sveltets_1_invalidate(() => getFoo1((__sveltets_1_store_get(uid), $uid)));/*Ωignore_startΩ*/;let $foo1 = __sveltets_1_store_get(foo1);/*Ωignore_endΩ*/
6+
;() => {$: console.log({ foo1: (__sveltets_1_store_get(foo1), $foo1) });}
7+
8+
let foo2 = __sveltets_1_invalidate(() => getFoo2((__sveltets_1_store_get(uid), $uid)))/*Ωignore_startΩ*/;let $foo2 = __sveltets_1_store_get(foo2);/*Ωignore_endΩ*/
9+
;() => {$: console.log({ foo2: (__sveltets_1_store_get(foo2), $foo2) })}
10+
11+
let {foo3} = __sveltets_1_invalidate(() => getFoo3((__sveltets_1_store_get(uid), $uid)));/*Ωignore_startΩ*/;let $foo3 = __sveltets_1_store_get(foo3);/*Ωignore_endΩ*/
12+
;() => {$: console.log({ foo3: (__sveltets_1_store_get(foo3), $foo3) });}
13+
14+
let {foo4} = __sveltets_1_invalidate(() => getFoo4((__sveltets_1_store_get(uid), $uid)))/*Ωignore_startΩ*/;let $foo4 = __sveltets_1_store_get(foo4);/*Ωignore_endΩ*/
15+
;() => {$: console.log({ foo4: (__sveltets_1_store_get(foo4), $foo4) })}
16+
;
17+
() => (<></>);
18+
return { props: {}, slots: {}, getters: {}, events: {} }}
19+
20+
export default class Input__SvelteComponent_ extends __sveltets_1_createSvelte2TsxComponent(__sveltets_1_partial(__sveltets_1_with_any_event(render()))) {
21+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script lang="ts">
2+
const uid = readable('')
3+
$: foo1 = getFoo1($uid);
4+
$: console.log({ foo1: $foo1 });
5+
6+
$: foo2 = getFoo2($uid)
7+
$: console.log({ foo2: $foo2 })
8+
9+
$: ({foo3} = getFoo3($uid));
10+
$: console.log({ foo3: $foo3 });
11+
12+
$: ({foo4} = getFoo4($uid))
13+
$: console.log({ foo4: $foo4 })
14+
</script>

0 commit comments

Comments
 (0)