Skip to content

Commit

Permalink
catch more runes mode cases, tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
dummdidumm committed Apr 24, 2024
1 parent 81d08fe commit 8a3060f
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 12 deletions.
4 changes: 2 additions & 2 deletions packages/svelte2tsx/src/svelte2tsx/addComponentExport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class __sveltets_Render${genericsDef} {
* Remove this once Svelte typings no longer do that (Svelte 6 or 7)
*/
let customConstructor = '';
if (exportedNames.usesRunes()) {
if (exportedNames.hasPropsRune()) {
customConstructor = `\n constructor(options: import('svelte').ComponentConstructorOptions<__sveltets_2_PropsWithChildren<${returnType('props')}, ${returnType('slots')}>>) { super(options); }`;
}

Expand Down Expand Up @@ -145,7 +145,7 @@ function addSimpleComponentExport({
* Remove this once Svelte typings no longer do that (Svelte 6 or 7)
*/
let customConstructor = '';
if (exportedNames.usesRunes()) {
if (exportedNames.hasPropsRune()) {
customConstructor = `\n constructor(options = __sveltets_2_runes_constructor(${propDef})) { super(options); }`;
}

Expand Down
4 changes: 4 additions & 0 deletions packages/svelte2tsx/src/svelte2tsx/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,10 @@ export function svelte2tsx(
({ exportedNames, events, generics, uses$$SlotsInterface } = res);
}

if (svelte5Plus) {
exportedNames.checkGlobalsForRunes(implicitStoreValues.getGlobals());
}

//wrap the script tag and template content in a function returning the slot and exports
createRenderFunction({
str,
Expand Down
34 changes: 29 additions & 5 deletions packages/svelte2tsx/src/svelte2tsx/nodes/ExportedNames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ export class ExportedNames {
* Uses the `$$Props` type
*/
public uses$$Props = false;
/**
* Component contains globals that have a rune name
*/
private hasRunesGlobals = false;
/**
* The `$props()` rune's type info as a string, if it exists.
* If using TS, this returns the generic string, if using JS, returns the `@type {..}` string.
Expand All @@ -33,6 +37,7 @@ export class ExportedNames {
type: '',
bindings: [] as string[]
};
/** Map of all props and exports. Exposing it publicly is no longer necessary for runes mode */
private exports = new Map<string, ExportedName>();
private possibleExports = new Map<
string,
Expand Down Expand Up @@ -646,6 +651,13 @@ export class ExportedNames {
return result;
}

if (this.usesRunes()) {
// Necessary, because {} roughly equals to any
return this.isTsFile
? '{} as Record<string, never>'
: '/** @type {Record<string, never>} */ ({})';
}

if (this.uses$$Props) {
const lets = names.filter(([, { isLet }]) => isLet);
const others = names.filter(([, { isLet }]) => !isLet);
Expand Down Expand Up @@ -741,17 +753,29 @@ export class ExportedNames {
}

createOptionalPropsArray(): string[] {
return Array.from(this.exports.entries())
.filter(([_, entry]) => !entry.required)
.map(([name, entry]) => `'${entry.identifierText || name}'`);
if (this.usesRunes()) {
return [];
} else {
return Array.from(this.exports.entries())
.filter(([_, entry]) => !entry.required)
.map(([name, entry]) => `'${entry.identifierText || name}'`);
}
}

getExportsMap() {
return this.exports;
}

usesRunes() {
// TODO runes mode can also be given if there's no $props() (but $state() etc)
hasPropsRune() {
return this.$props.type || this.$props.comment;
}

checkGlobalsForRunes(globals: string[]) {
const runes = ['$state', '$derived', '$effect']; // no need to check for props, already handled through other means in here
this.hasRunesGlobals = globals.some((global) => runes.includes(global));
}

private usesRunes() {
return this.hasRunesGlobals || this.hasPropsRune();
}
}
14 changes: 13 additions & 1 deletion packages/svelte2tsx/src/svelte2tsx/nodes/ImplicitStoreValues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { extractIdentifiers, getNamesFromLabeledStatement } from '../utils/tsAst
/**
* Tracks all store-usages as well as all variable declarations and imports in the component.
*
* In the modification-step at the end, all variable declartaions and imports which
* In the modification-step at the end, all variable declarations and imports which
* were used as stores are appended with `let $xx = __sveltets_2_store_get(xx)` to create the store variables.
*/
export class ImplicitStoreValues {
Expand Down Expand Up @@ -49,6 +49,18 @@ export class ImplicitStoreValues {
return [...this.accessedStores.keys()];
}

public getGlobals(): string[] {
const globals = new Set<string>(this.accessedStores);
this.variableDeclarations.forEach((node) =>
extractIdentifiers(node.name).forEach((id) => globals.delete(id.text))
);
this.reactiveDeclarations.forEach((node) =>
getNamesFromLabeledStatement(node).forEach((name) => globals.delete(name))
);
this.importStatements.forEach(({ name }) => name && globals.delete(name.getText()));
return [...globals].map((name) => `$${name}`);
}

private attachStoreValueDeclarationToDecl(
node: ts.VariableDeclaration,
astOffset: number,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
///<reference types="svelte" />
;function render() {

let x = $state();
function foo() { return true; }
;
async () => {

x;};
return { props: /** @type {Record<string, never>} */ ({}), exports: /** @type {foo: typeof foo} */ ({}), slots: {}, events: {} }}

export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(__sveltets_2_with_any_event(render()))) {
get foo() { return render().exports.foo }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<script lang="ts">
let x = $state();
export function foo() { return true; }
</script>

{x}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
async () => {};
return { props: /** @type {$$ComponentProps} */({}), exports: /** @type {snapshot: typeof snapshot} */ ({}), slots: {}, events: {} }}

export default class Page__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['snapshot'], __sveltets_2_with_any_event(render()))) {
constructor(options = __sveltets_2_runes_constructor(__sveltets_2_partial(['snapshot'], __sveltets_2_with_any_event(render())))) { super(options); }
export default class Page__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(__sveltets_2_with_any_event(render()))) {
constructor(options = __sveltets_2_runes_constructor(__sveltets_2_partial(__sveltets_2_with_any_event(render())))) { super(options); }
get snapshot() { return render().exports.snapshot }
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
async () => {};
return { props: /** @type {$$ComponentProps} */({}), exports: /** @type {snapshot: typeof snapshot} */ ({}), slots: {}, events: {} }}

export default class Page__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['snapshot'], __sveltets_2_with_any_event(render()))) {
constructor(options = __sveltets_2_runes_constructor(__sveltets_2_partial(['snapshot'], __sveltets_2_with_any_event(render())))) { super(options); }
export default class Page__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(__sveltets_2_with_any_event(render()))) {
constructor(options = __sveltets_2_runes_constructor(__sveltets_2_partial(__sveltets_2_with_any_event(render())))) { super(options); }
get snapshot() { return render().exports.snapshot }
}

0 comments on commit 8a3060f

Please sign in to comment.