From 364ac7dbc2a5859d5b819aaed344ea230f8fa3c1 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Fri, 24 Nov 2023 16:46:41 +0100 Subject: [PATCH] feat: Svelte 5 fixes and improvements (#2217) - pass children to zero types Svelte 5: +layout.svelte children not included in zero-effort type safety #2212 - add possibility to pass in version to svelte2tsx to differentiate transpiler targets - add implicit children prop in Svelte 5 mode Svelte 5: Implicit children not detected correctly #2211 - add best-effort fallback typings to $props() rune - hide deprecation warnings in generated code Svelte 5: Typescript generics in components are marked as deprecated svelte#9586 --- .../src/plugins/svelte/SveltePlugin.ts | 1 + .../plugins/typescript/DocumentSnapshot.ts | 2 + .../features/DiagnosticsProvider.ts | 13 +- .../src/plugins/typescript/service.ts | 1 + .../component-invalid/components.d.ts | 6 +- packages/svelte2tsx/index.d.ts | 5 + packages/svelte2tsx/repl/debug.ts | 5 +- .../svelte2tsx/src/htmlxtojsx_v2/index.ts | 12 +- .../src/htmlxtojsx_v2/nodes/SnippetBlock.ts | 51 +++++++- .../src/svelte2tsx/createRenderFunction.ts | 35 +++-- packages/svelte2tsx/src/svelte2tsx/index.ts | 15 ++- .../src/svelte2tsx/nodes/ExportedNames.ts | 121 ++++++++++++++++-- packages/svelte2tsx/svelte-shims-v4.d.ts | 2 + packages/svelte2tsx/svelte-shims.d.ts | 3 - packages/svelte2tsx/test/helpers.ts | 45 +++++-- packages/svelte2tsx/test/htmlx2jsx/index.ts | 5 +- .../expected-svelte5.js | 3 + .../expected-svelte5.js | 3 + .../expected-svelte5.js | 3 + .../component-multi-slot/expected-svelte5.js | 11 ++ .../component-named-slot/expected-svelte5.js | 8 ++ .../expected-svelte5.js | 8 ++ .../expected-svelte5.js | 7 + .../expected-svelte5.js | 98 ++++++++++++++ .../if-nested-slot-let/expected-svelte5.js | 22 ++++ .../expected-svelte5.js} | 16 ++- .../{snippet.skip => snippet.v5}/input.svelte | 12 +- .../svelte-fragment/expected-svelte5.js | 19 +++ .../expected-svelte5.js} | 0 .../input.svelte | 0 packages/svelte2tsx/test/sourcemaps/index.ts | 4 +- .../expected-svelte5.ts | 15 +++ .../expected-svelte5.ts | 19 +++ .../expected-svelte5.ts | 25 ++++ .../expected-svelte5.ts | 25 ++++ .../expected-svelte5.ts | 15 +++ .../expected-svelte5.ts | 11 ++ .../expected-svelte5.ts | 11 ++ .../expected-svelte5.ts | 16 +++ .../expected-svelte5.ts | 14 ++ .../expected-svelte5.ts | 13 ++ .../expected-svelte5.ts | 11 ++ .../expected-svelte5.ts | 19 +++ .../expected-svelte5.ts | 14 ++ .../expected-svelte5.ts | 11 ++ .../expected-svelte5.ts | 11 ++ .../const-tag-component/expected-svelte5.ts | 69 ++++++++++ .../samples/creates-dts/expected-svelte5.ts | 34 +++++ .../creates-no-script-dts/expected-svelte5.ts | 15 +++ .../runes-best-effort-types/expectedv2.ts | 10 ++ .../runes-best-effort-types/input.svelte | 3 + .../runes-looking-like-stores/expectedv2.ts | 4 +- .../expected-svelte5.ts | 15 +++ .../expected-svelte5.ts} | 2 +- .../input.svelte | 0 .../svelte-element/expected-svelte5.ts | 17 +++ .../ts-$$generics-dts/expected-svelte5.ts | 45 +++++++ .../samples/ts-$$generics/expected-svelte5.ts | 44 +++++++ .../ts-creates-dts/expected-svelte5.ts | 33 +++++ .../expected-svelte5.ts | 40 ++++++ .../ts-runes-best-effort-types/expectedv2.ts | 10 ++ .../ts-runes-best-effort-types/input.svelte | 3 + .../uses-$$slots-script/expected-svelte5.ts | 17 +++ .../samples/uses-$$slots/expected-svelte5.ts | 13 ++ .../expected-svelte5.ts | 16 +++ .../expected-svelte5.ts | 20 +++ 66 files changed, 1118 insertions(+), 58 deletions(-) create mode 100644 packages/svelte2tsx/test/htmlx2jsx/samples/component-default-slot-let-destructure/expected-svelte5.js create mode 100644 packages/svelte2tsx/test/htmlx2jsx/samples/component-default-slot-let/expected-svelte5.js create mode 100644 packages/svelte2tsx/test/htmlx2jsx/samples/component-default-slot/expected-svelte5.js create mode 100644 packages/svelte2tsx/test/htmlx2jsx/samples/component-multi-slot/expected-svelte5.js create mode 100644 packages/svelte2tsx/test/htmlx2jsx/samples/component-named-slot/expected-svelte5.js create mode 100644 packages/svelte2tsx/test/htmlx2jsx/samples/component-slot-infer-props/expected-svelte5.js create mode 100644 packages/svelte2tsx/test/htmlx2jsx/samples/component-slot-shadowed-prop/expected-svelte5.js create mode 100644 packages/svelte2tsx/test/htmlx2jsx/samples/if-nested-slot-let-shadowed/expected-svelte5.js create mode 100644 packages/svelte2tsx/test/htmlx2jsx/samples/if-nested-slot-let/expected-svelte5.js rename packages/svelte2tsx/test/htmlx2jsx/samples/{snippet.skip/expectedv2.js => snippet.v5/expected-svelte5.js} (52%) rename packages/svelte2tsx/test/htmlx2jsx/samples/{snippet.skip => snippet.v5}/input.svelte (66%) create mode 100644 packages/svelte2tsx/test/htmlx2jsx/samples/svelte-fragment/expected-svelte5.js rename packages/svelte2tsx/test/htmlx2jsx/samples/{ts-in-template.skip/expectedv2.js => ts-in-template.v5/expected-svelte5.js} (100%) rename packages/svelte2tsx/test/htmlx2jsx/samples/{ts-in-template.skip => ts-in-template.v5}/input.svelte (100%) create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/component-default-slot/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/component-multiple-slots/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/component-slot-$$slot-interface/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/component-slot-$$slot-type/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/component-slot-crazy-attributes/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/component-slot-fallback/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/component-slot-forward-with-props/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/component-slot-inside-await/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/component-slot-inside-each/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/component-slot-let-forward-named-slot/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/component-slot-let-forward/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/component-slot-nest-scope/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/component-slot-no-space/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/component-slot-object-key/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/component-slot-var-shadowing/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/const-tag-component/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/creates-dts/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/creates-no-script-dts/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/runes-best-effort-types/expectedv2.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/runes-best-effort-types/input.svelte create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/script-style-like-component/expected-svelte5.ts rename packages/svelte2tsx/test/svelte2tsx/samples/{snippet-instance-script.skip/expectedv2.ts => snippet-instance-script.v5/expected-svelte5.ts} (79%) rename packages/svelte2tsx/test/svelte2tsx/samples/{snippet-instance-script.skip => snippet-instance-script.v5}/input.svelte (100%) create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/ts-$$generics-dts/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/ts-$$generics/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/ts-creates-dts/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/ts-generics-attribute1/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-best-effort-types/expectedv2.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-best-effort-types/input.svelte create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots-script/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/uses-svelte-components-let-forward/expected-svelte5.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/uses-svelte-components/expected-svelte5.ts diff --git a/packages/language-server/src/plugins/svelte/SveltePlugin.ts b/packages/language-server/src/plugins/svelte/SveltePlugin.ts index 379ad07d8..3aeb39cf5 100644 --- a/packages/language-server/src/plugins/svelte/SveltePlugin.ts +++ b/packages/language-server/src/plugins/svelte/SveltePlugin.ts @@ -68,6 +68,7 @@ export class SveltePlugin async getCompiledResult(document: Document): Promise { try { const svelteDoc = await this.getSvelteDoc(document); + // @ts-ignore is 'client' in Svelte 5 return svelteDoc.getCompiledWith({ generate: 'dom' }); } catch (error) { return null; diff --git a/packages/language-server/src/plugins/typescript/DocumentSnapshot.ts b/packages/language-server/src/plugins/typescript/DocumentSnapshot.ts index 84d55bf14..da5c09351 100644 --- a/packages/language-server/src/plugins/typescript/DocumentSnapshot.ts +++ b/packages/language-server/src/plugins/typescript/DocumentSnapshot.ts @@ -68,6 +68,7 @@ export interface DocumentSnapshot extends ts.IScriptSnapshot, DocumentMapper { */ export interface SvelteSnapshotOptions { parse: typeof import('svelte/compiler').parse | undefined; + version: string | undefined; transformOnTemplateError: boolean; typingsNamespace: string; } @@ -199,6 +200,7 @@ function preprocessSvelteFile(document: Document, options: SvelteSnapshotOptions try { const tsx = svelte2tsx(text, { parse: options.parse, + version: options.version, filename: document.getFilePath() ?? undefined, isTsFile: scriptKind === ts.ScriptKind.TS, mode: 'ts', diff --git a/packages/language-server/src/plugins/typescript/features/DiagnosticsProvider.ts b/packages/language-server/src/plugins/typescript/features/DiagnosticsProvider.ts index dc6b61f81..c5f9c6aa4 100644 --- a/packages/language-server/src/plugins/typescript/features/DiagnosticsProvider.ts +++ b/packages/language-server/src/plugins/typescript/features/DiagnosticsProvider.ts @@ -42,7 +42,8 @@ export enum DiagnosticCode { MISSING_PROP = 2741, // "Property '..' is missing in type '..' but required in type '..'." NO_OVERLOAD_MATCHES_CALL = 2769, // "No overload matches this call" CANNOT_FIND_NAME = 2304, // "Cannot find name 'xxx'" - EXPECTED_N_ARGUMENTS = 2554 // Expected {0} arguments, but got {1}. + EXPECTED_N_ARGUMENTS = 2554, // Expected {0} arguments, but got {1}. + DEPRECATED_SIGNATURE = 6387 // The signature '..' of '..' is deprecated } export class DiagnosticsProviderImpl implements DiagnosticsProvider { @@ -222,6 +223,8 @@ function hasNoNegativeLines(diagnostic: Diagnostic): boolean { return diagnostic.range.start.line >= 0 && diagnostic.range.end.line >= 0; } +const generatedVarRegex = /'\$\$_\w+(\.\$on)?'/; + function isNoFalsePositive(document: Document, tsDoc: SvelteDocumentSnapshot) { const text = document.getText(); const usesPug = document.getLanguageAttribute('template') === 'pug'; @@ -238,6 +241,14 @@ function isNoFalsePositive(document: Document, tsDoc: SvelteDocumentSnapshot) { } } + if ( + diagnostic.code === DiagnosticCode.DEPRECATED_SIGNATURE && + generatedVarRegex.test(diagnostic.message) + ) { + // Svelte 5: $on and constructor is deprecated, but we don't want to show this warning for generated code + return false; + } + return ( isNoUsedBeforeAssigned(diagnostic, text, tsDoc) && (!usesPug || isNoPugFalsePositive(diagnostic, document)) diff --git a/packages/language-server/src/plugins/typescript/service.ts b/packages/language-server/src/plugins/typescript/service.ts index b918cccf5..d839fda21 100644 --- a/packages/language-server/src/plugins/typescript/service.ts +++ b/packages/language-server/src/plugins/typescript/service.ts @@ -298,6 +298,7 @@ async function createLanguageService( let languageService = ts.createLanguageService(host); const transformationConfig: SvelteSnapshotOptions = { parse: svelteCompiler?.parse, + version: svelteCompiler?.VERSION, transformOnTemplateError: docContext.transformOnTemplateError, typingsNamespace: raw?.svelteOptions?.namespace || 'svelteHTML' }; diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/component-invalid/components.d.ts b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/component-invalid/components.d.ts index bb67f7824..174a16d6b 100644 --- a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/component-invalid/components.d.ts +++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/component-invalid/components.d.ts @@ -10,5 +10,9 @@ export class Works2 extends SvelteComponentTyped< }; } > {} -export class Works3 extends SvelteComponentTyped }, never> {} +export class Works3 extends SvelteComponentTyped< + any, + { [evt: string]: CustomEvent }, + Record +> {} export class DoesntWork {} diff --git a/packages/svelte2tsx/index.d.ts b/packages/svelte2tsx/index.d.ts index d65765175..08b18f563 100644 --- a/packages/svelte2tsx/index.d.ts +++ b/packages/svelte2tsx/index.d.ts @@ -79,6 +79,11 @@ export function svelte2tsx( * The Svelte parser to use. Defaults to the one bundled with `svelte2tsx`. */ parse?: typeof import('svelte/compiler').parse; + /** + * The VERSION from 'svelte/compiler'. Defaults to the one bundled with `svelte2tsx`. + * Transpiled output may vary between versions. + */ + version?: string; } ): SvelteCompiledToTsx diff --git a/packages/svelte2tsx/repl/debug.ts b/packages/svelte2tsx/repl/debug.ts index 4ba8c171d..cc3b646a2 100644 --- a/packages/svelte2tsx/repl/debug.ts +++ b/packages/svelte2tsx/repl/debug.ts @@ -1,7 +1,10 @@ import fs from 'fs'; import { svelte2tsx } from '../src/svelte2tsx/index'; +import { VERSION } from 'svelte/compiler'; + const content = fs.readFileSync(`${__dirname}/index.svelte`, 'utf-8'); -console.log(svelte2tsx(content).code); + +console.log(svelte2tsx(content, {version: VERSION}).code); /** * To enable the REPL, simply run the "dev" package script. * diff --git a/packages/svelte2tsx/src/htmlxtojsx_v2/index.ts b/packages/svelte2tsx/src/htmlxtojsx_v2/index.ts index 6228520a8..8d297520c 100644 --- a/packages/svelte2tsx/src/htmlxtojsx_v2/index.ts +++ b/packages/svelte2tsx/src/htmlxtojsx_v2/index.ts @@ -26,7 +26,7 @@ import { handleSpread } from './nodes/Spread'; import { handleStyleDirective } from './nodes/StyleDirective'; import { handleText } from './nodes/Text'; import { handleTransitionDirective } from './nodes/Transition'; -import { handleSnippet } from './nodes/SnippetBlock'; +import { handleImplicitChildren, handleSnippet } from './nodes/SnippetBlock'; import { handleRenderTag } from './nodes/RenderTag'; type Walker = (node: TemplateNode, parent: BaseNode, prop: string, index: number) => void; @@ -48,7 +48,11 @@ export function convertHtmlxToJsx( ast: TemplateNode, onWalk: Walker = null, onLeave: Walker = null, - options: { preserveAttributeCase?: boolean; typingsNamespace?: string } = {} + options: { + svelte5Plus: boolean; + preserveAttributeCase?: boolean; + typingsNamespace?: string; + } = { svelte5Plus: false } ) { const htmlx = str.original; options = { preserveAttributeCase: false, ...options }; @@ -114,6 +118,9 @@ export function convertHtmlxToJsx( } else { element = new InlineComponent(str, node); } + if (options.svelte5Plus) { + handleImplicitChildren(node, element as InlineComponent); + } break; case 'Element': case 'Options': @@ -248,6 +255,7 @@ export function htmlx2jsx( emitOnTemplateError?: boolean; preserveAttributeCase: boolean; typingsNamespace: string; + svelte5Plus: boolean; } ) { const ast = parseHtmlx(htmlx, parse, { ...options }).htmlxAst; diff --git a/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/SnippetBlock.ts b/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/SnippetBlock.ts index e29ac3e62..fdd8826b3 100644 --- a/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/SnippetBlock.ts +++ b/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/SnippetBlock.ts @@ -28,7 +28,7 @@ import { surroundWithIgnoreComments } from '../../utils/ignore'; export function handleSnippet( str: MagicString, snippetBlock: BaseNode, - element?: InlineComponent + component?: InlineComponent ): void { const endSnippet = str.original.lastIndexOf('{', snippetBlock.end - 1); // Return something to silence the "snippet type not assignable to return type void" error @@ -39,7 +39,7 @@ export function handleSnippet( const startEnd = str.original.indexOf('}', snippetBlock.context?.end || snippetBlock.expression.end) + 1; - if (element !== undefined) { + if (component !== undefined) { str.overwrite(snippetBlock.start, snippetBlock.expression.start, '', { contentOnly: true }); const transforms: TransformationArray = ['(']; if (snippetBlock.context) { @@ -53,7 +53,10 @@ export function handleSnippet( } transforms.push(') => {'); transforms.push([startEnd, snippetBlock.end]); - element.addProp([[snippetBlock.expression.start, snippetBlock.expression.end]], transforms); + component.addProp( + [[snippetBlock.expression.start, snippetBlock.expression.end]], + transforms + ); } else { const generic = snippetBlock.context ? snippetBlock.context.typeAnnotation @@ -79,3 +82,45 @@ export function handleSnippet( transform(str, snippetBlock.start, startEnd, startEnd, transforms); } } + +export function handleImplicitChildren(componentNode: BaseNode, component: InlineComponent): void { + if (componentNode.children?.length === 0) { + return; + } + + let hasSlot = false; + + for (const child of componentNode.children) { + if ( + child.type === 'SvelteSelf' || + child.type === 'InlineComponent' || + child.type === 'Element' || + child.type === 'SlotTemplate' + ) { + if ( + child.attributes.some( + (a) => + a.type === 'Attribute' && + a.name === 'slot' && + a.value[0]?.data !== 'default' + ) + ) { + continue; + } + } + if (child.type === 'Text' && child.data.trim() === '') { + continue; + } + if (child.type !== 'SnippetBlock') { + hasSlot = true; + break; + } + } + + if (!hasSlot) { + return; + } + + // it's enough to fake a children prop, we don't need to actually move the content inside (which would also reset control flow) + component.addProp(['children'], ['() => { return __sveltets_2_any(0); }']); +} diff --git a/packages/svelte2tsx/src/svelte2tsx/createRenderFunction.ts b/packages/svelte2tsx/src/svelte2tsx/createRenderFunction.ts index 300775f66..9e80abe9b 100644 --- a/packages/svelte2tsx/src/svelte2tsx/createRenderFunction.ts +++ b/packages/svelte2tsx/src/svelte2tsx/createRenderFunction.ts @@ -12,6 +12,7 @@ export interface CreateRenderFunctionPara extends InstanceScriptProcessResult { slots: Map>; events: ComponentEvents; uses$$SlotsInterface: boolean; + svelte5Plus: boolean; mode?: 'ts' | 'dts'; } @@ -28,6 +29,7 @@ export function createRenderFunction({ uses$$slots, uses$$SlotsInterface, generics, + svelte5Plus, mode }: CreateRenderFunctionPara) { const htmlx = str.original; @@ -105,19 +107,28 @@ export function createRenderFunction({ : '{' + Array.from(slots.entries()) .map(([name, attrs]) => { - const attrsAsString = Array.from(attrs.entries()) - .map(([exportName, expr]) => - exportName.startsWith('__spread__') - ? `...${expr}` - : `${exportName}:${expr}` - ) - .join(', '); - return `'${name}': {${attrsAsString}}`; + return `'${name}': {${slotAttributesToString(attrs)}}`; }) .join(', ') + '}'; + const needsImplicitChildrenProp = + svelte5Plus && + !exportedNames.uses$propsRune() && + slots.has('default') && + !exportedNames.getExportsMap().has('default'); + if (needsImplicitChildrenProp) { + exportedNames.addImplicitChildrenExport(slots.get('default')!.size > 0); + } + const returnString = + `${ + needsImplicitChildrenProp && slots.get('default')!.size > 0 + ? `\nlet $$implicit_children = __sveltets_2_snippet({${slotAttributesToString( + slots.get('default')! + )}});` + : '' + }` + `\nreturn { props: ${exportedNames.createPropsStr(uses$$props || uses$$restProps)}` + `, slots: ${slotsAsDef}` + `, events: ${events.toDefString()} }}`; @@ -127,3 +138,11 @@ export function createRenderFunction({ str.append(returnString); } + +function slotAttributesToString(attrs: Map) { + return Array.from(attrs.entries()) + .map(([exportName, expr]) => + exportName.startsWith('__spread__') ? `...${expr}` : `${exportName}:${expr}` + ) + .join(', '); +} diff --git a/packages/svelte2tsx/src/svelte2tsx/index.ts b/packages/svelte2tsx/src/svelte2tsx/index.ts index a6f3b4d73..ea6d5405b 100644 --- a/packages/svelte2tsx/src/svelte2tsx/index.ts +++ b/packages/svelte2tsx/src/svelte2tsx/index.ts @@ -24,7 +24,7 @@ import { createRenderFunction } from './createRenderFunction'; // @ts-ignore import { TemplateNode } from 'svelte/types/compiler/interfaces'; import path from 'path'; -import { parse } from 'svelte/compiler'; +import { VERSION, parse } from 'svelte/compiler'; type TemplateProcessResult = { /** @@ -55,6 +55,7 @@ function processSvelteTemplate( accessors?: boolean; mode?: 'ts' | 'dts'; typingsNamespace?: string; + svelte5Plus: boolean; } ): TemplateProcessResult { const { htmlxAst, tags } = parseHtmlx(str.original, parse, options); @@ -273,7 +274,8 @@ function processSvelteTemplate( const rootSnippets = convertHtmlxToJsx(str, htmlxAst, onHtmlxWalk, onHtmlxLeave, { preserveAttributeCase: options?.namespace == 'foreign', - typingsNamespace: options.typingsNamespace + typingsNamespace: options.typingsNamespace, + svelte5Plus: options.svelte5Plus }); // resolve scripts @@ -309,6 +311,7 @@ export function svelte2tsx( svelte: string, options: { parse?: typeof import('svelte/compiler').parse; + version?: string; filename?: string; isTsFile?: boolean; emitOnTemplateError?: boolean; @@ -320,9 +323,11 @@ export function svelte2tsx( } = { parse } ) { options.mode = options.mode || 'ts'; + options.version = options.version || VERSION; const str = new MagicString(svelte); const basename = path.basename(options.filename || ''); + const svelte5Plus = Number(options.version![0]) > 4; // process the htmlx as a svelte template let { htmlAst, @@ -337,7 +342,10 @@ export function svelte2tsx( componentDocumentation, resolvedStores, usesAccessors - } = processSvelteTemplate(str, options.parse || parse, options); + } = processSvelteTemplate(str, options.parse || parse, { + ...options, + svelte5Plus + }); /* Rearrange the script tags so that module is first, and instance second followed finally by the template * This is a bit convoluted due to some trouble I had with magic string. A simple str.move(start,end,0) for each script wasn't enough @@ -400,6 +408,7 @@ export function svelte2tsx( uses$$slots, uses$$SlotsInterface, generics, + svelte5Plus, mode: options.mode }); diff --git a/packages/svelte2tsx/src/svelte2tsx/nodes/ExportedNames.ts b/packages/svelte2tsx/src/svelte2tsx/nodes/ExportedNames.ts index 96785d8ab..078a0090e 100644 --- a/packages/svelte2tsx/src/svelte2tsx/nodes/ExportedNames.ts +++ b/packages/svelte2tsx/src/svelte2tsx/nodes/ExportedNames.ts @@ -17,6 +17,7 @@ interface ExportedName { identifierText?: string; required?: boolean; doc?: string; + implicitChildren?: 'empty' | 'attributes'; } export class ExportedNames { @@ -137,25 +138,31 @@ export class ExportedNames { if (node.initializer.typeArguments?.length > 0) { this.$props.generic = node.initializer.typeArguments[0].getText(); } else { - const text = node.getSourceFile().getFullText(); - let comments = ts - .getLeadingCommentRanges(text, node.pos) - ?.map((c) => text.substring(c.pos, c.end)) - .find((c) => c.includes('@type')); - if (!comments) { - comments = ts - .getLeadingCommentRanges(text, node.parent.pos) + if (!this.isTsFile) { + const text = node.getSourceFile().getFullText(); + let comments = ts + .getLeadingCommentRanges(text, node.pos) ?.map((c) => text.substring(c.pos, c.end)) .find((c) => c.includes('@type')); + if (!comments) { + comments = ts + .getLeadingCommentRanges(text, node.parent.pos) + ?.map((c) => text.substring(c.pos, c.end)) + .find((c) => c.includes('@type')); + } + + // We don't bother extracting the type, we just use the comment as-is + this.$props.comment = comments || ''; } - // We don't bother extracting the type, we just use the comment as-is - this.$props.comment = comments || ''; + if (this.$props.comment) { + return; + } - if (!comments && internalHelpers.isKitRouteFile(this.basename)) { - const kitType = `{ data: import('./$types.js').${ - this.basename.includes('layout') ? 'LayoutData' : 'PageData' - }, form: import('./$types.js').ActionData }`; + if (internalHelpers.isKitRouteFile(this.basename)) { + const kitType = this.basename.includes('layout') + ? `{ data: import('./$types.js').LayoutData, form: import('./$types.js').ActionData, children: import('svelte').Snippet }` + : `{ data: import('./$types.js').PageData, form: import('./$types.js').ActionData }`; if (this.isTsFile) { this.$props.generic = kitType; @@ -168,6 +175,63 @@ export class ExportedNames { this.$props.comment = `/** @type {${kitType}} */`; preprendStr(this.str, node.pos + this.astOffset, this.$props.comment); } + } else { + // Do a best-effort to extract the props from the object literal + let propsStr = ''; + let withUnknown = false; + let props = []; + + if (ts.isObjectBindingPattern(node.name)) { + for (const element of node.name.elements) { + if (!ts.isIdentifier(element.name) || !!element.dotDotDotToken) { + withUnknown = true; + } else { + if (element.initializer) { + const type = ts.isAsExpression(element.initializer) + ? element.initializer.type.getText() + : ts.isStringLiteral(element.initializer) + ? 'string' + : ts.isNumericLiteral(element.initializer) + ? 'number' + : element.initializer.kind === ts.SyntaxKind.TrueKeyword || + element.initializer.kind === ts.SyntaxKind.FalseKeyword + ? 'boolean' + : ts.isIdentifier(element.initializer) + ? `typeof ${element.initializer.text}` + : 'unknown'; + props.push(`${element.name.text}?: ${type}`); + } else { + props.push(`${element.name.text}: unknown`); + } + } + } + } + + if (props.length > 0) { + propsStr = + `{ ${props.join(', ')} }` + + (withUnknown ? ' & Record' : ''); + } else if (withUnknown) { + propsStr = 'Record'; + } else { + propsStr = 'Record'; + } + + if (this.isTsFile) { + this.$props.generic = propsStr; + if (props.length > 0 || withUnknown) { + preprendStr( + this.str, + node.initializer.expression.end + this.astOffset, + surroundWithIgnoreComments(`<${propsStr}>`) + ); + } + } else { + this.$props.comment = `/** @type {${propsStr}} */`; + if (props.length > 0 || withUnknown) { + preprendStr(this.str, node.pos + this.astOffset, this.$props.comment); + } + } } } } @@ -372,6 +436,16 @@ export class ExportedNames { }); } } + + addImplicitChildrenExport(hasAttributes: boolean): void { + if (this.exports.has('children')) return; + + this.exports.set('children', { + isLet: true, + implicitChildren: hasAttributes ? 'attributes' : 'empty' + }); + } + /** * Adds export to map */ @@ -517,6 +591,13 @@ export class ExportedNames { dontAddTypeDef: boolean ): string[] { return names.map(([key, value]) => { + if (value.implicitChildren) { + return `children?: ${ + value.implicitChildren === 'empty' + ? '__sveltets_2_snippet()' + : '$$implicit_children' + }`; + } // Important to not use shorthand props for rename functionality return `${dontAddTypeDef && value.doc ? `\n${value.doc}` : ''}${ value.identifierText || key @@ -526,6 +607,14 @@ export class ExportedNames { private createReturnElementsType(names: Array<[string, ExportedName]>) { return names.map(([key, value]) => { + if (value.implicitChildren) { + return `children?: ${ + value.implicitChildren === 'empty' + ? `import('svelte').Snippet` + : 'typeof $$implicit_children' + }`; + } + const identifier = `${value.doc ? `\n${value.doc}` : ''}${value.identifierText || key}${ value.required ? '' : '?' }`; @@ -546,4 +635,8 @@ export class ExportedNames { getExportsMap() { return this.exports; } + + uses$propsRune() { + return !!this.$props.generic || !!this.$props.comment; + } } diff --git a/packages/svelte2tsx/svelte-shims-v4.d.ts b/packages/svelte2tsx/svelte-shims-v4.d.ts index f5807b3f5..19d2f7c2f 100644 --- a/packages/svelte2tsx/svelte-shims-v4.d.ts +++ b/packages/svelte2tsx/svelte-shims-v4.d.ts @@ -147,6 +147,8 @@ declare function __sveltets_2_cssProp(prop: Record): {}; // @ts-ignore Svelte v3/v4 don't have this declare function __sveltets_2_ensureSnippet(val: ReturnType): any; +// @ts-ignore Svelte v3/v4 don't have this +declare function __sveltets_2_snippet(t: T): import('svelte').Snippet; /** @internal PRIVATE API, DO NOT USE */ type __sveltets_2_SvelteAnimationReturnType = { diff --git a/packages/svelte2tsx/svelte-shims.d.ts b/packages/svelte2tsx/svelte-shims.d.ts index 8bc3720fc..a8066b0a7 100644 --- a/packages/svelte2tsx/svelte-shims.d.ts +++ b/packages/svelte2tsx/svelte-shims.d.ts @@ -224,9 +224,6 @@ declare function __sveltets_2_nonNullable(type: T): NonNullable; declare function __sveltets_2_cssProp(prop: Record): {}; -// @ts-ignore Svelte v3/v4 don't have this -declare function __sveltets_2_ensureSnippet(val: ReturnType): any; - /** @internal PRIVATE API, DO NOT USE */ type __sveltets_2_SvelteAnimationReturnType = { delay?: number, diff --git a/packages/svelte2tsx/test/helpers.ts b/packages/svelte2tsx/test/helpers.ts index 358e88062..26e8ebb68 100644 --- a/packages/svelte2tsx/test/helpers.ts +++ b/packages/svelte2tsx/test/helpers.ts @@ -3,6 +3,7 @@ import assert, { AssertionError } from 'assert'; import { TestFunction } from 'mocha'; import { htmlx2jsx, svelte2tsx } from './build'; import path from 'path'; +import { VERSION } from 'svelte/compiler'; let update_count = 0; let all_tests_skipped = false; @@ -222,11 +223,14 @@ const enum TestError { WrongExpected = 'Expected a different output' } +const isSvelte5Plus = Number(VERSION[0]) >= 5; + export function test_samples(dir: string, transform: TransformSampleFn, js: 'js' | 'ts') { for (const sample of each_sample(dir)) { - if (sample.name.endsWith('.skip')) continue; + if (sample.name.endsWith('.v5') && !isSvelte5Plus) continue; const svelteFile = sample.find_file('*.svelte'); + const expectedFile = isSvelte5Plus ? `expected-svelte5.${js}` : `expectedv2.${js}`; const config = { filename: svelteFile, sampleName: sample.name, @@ -237,12 +241,17 @@ export function test_samples(dir: string, transform: TransformSampleFn, js: 'js' if (process.env.CI) { sample.checkDirectory({ required: ['*.svelte', `expectedv2.${js}`], - allowed: ['expected.js', 'expected.error.json'] + allowed: ['expected.js', `expected-svelte5.${js}`, 'expected.error.json'] }); } else { sample.checkDirectory({ required: ['*.svelte'], - allowed: ['expected.js', `expectedv2.${js}`, 'expected.error.json'] + allowed: [ + 'expected.js', + `expectedv2.${js}`, + `expected-svelte5.${js}`, + 'expected.error.json' + ] }); if (sample.hasOnly(svelteFile) || sample.hasOnly(svelteFile, 'expected.js')) { @@ -254,7 +263,7 @@ export function test_samples(dir: string, transform: TransformSampleFn, js: 'js' generate('expected.error.json', print_error(error)); config.emitOnTemplateError = true; } - generate(`expectedv2.${js}`, transform(input, config).code); + generate(expectedFile, transform(input, config).code); }); } @@ -263,7 +272,7 @@ export function test_samples(dir: string, transform: TransformSampleFn, js: 'js' const { message, actual } = err; switch (message) { case TestError.WrongExpected: { - generate(`expectedv2.${js}`, actual); + generate(expectedFile, actual); break; } case TestError.WrongError: { @@ -283,11 +292,14 @@ export function test_samples(dir: string, transform: TransformSampleFn, js: 'js' transform(input, config); } catch (error) { hadError = true; - assert.deepEqual( - JSON.parse(JSON.stringify(error)), - JSON.parse(sample.get('expected.error.json')), - TestError.WrongError - ); + let actual = JSON.parse(JSON.stringify(error)); + let expected = JSON.parse(sample.get('expected.error.json')); + if (isSvelte5Plus && actual && expected) { + // Error output looks a bit different but we only care about the start and end really + actual = { start: actual.start, end: actual.end }; + expected = { start: expected.start, end: expected.end }; + } + assert.deepEqual(actual, expected, TestError.WrongError); config.emitOnTemplateError = true; } assert(hadError, TestError.MissingError); @@ -301,7 +313,15 @@ export function test_samples(dir: string, transform: TransformSampleFn, js: 'js' assert.strictEqual( normalize(transform(input, config).code), - sample.get(`expectedv2.${js}`), + sample.get( + // Check the expectedv2 file first even in Svelte 5 mode because many are identical between versions. + // This way we don't need to duplicate a bunch of expected files. + isSvelte5Plus + ? sample.has(expectedFile) + ? expectedFile + : `expectedv2.${js}` + : expectedFile + ), TestError.WrongExpected ); }); @@ -322,7 +342,8 @@ export function get_svelte2tsx_config(base: BaseConfig, sampleName: string): Sve namespace: sampleName.endsWith('-foreign-ns') ? 'foreign' : null, typingsNamespace: 'svelteHTML', mode: sampleName.endsWith('-dts') ? 'dts' : 'ts', - accessors: sampleName.startsWith('accessors-config') + accessors: sampleName.startsWith('accessors-config'), + version: VERSION }; } diff --git a/packages/svelte2tsx/test/htmlx2jsx/index.ts b/packages/svelte2tsx/test/htmlx2jsx/index.ts index ff7fe41f5..f8439d2ea 100644 --- a/packages/svelte2tsx/test/htmlx2jsx/index.ts +++ b/packages/svelte2tsx/test/htmlx2jsx/index.ts @@ -1,4 +1,4 @@ -import { parse } from 'svelte/compiler'; +import { VERSION, parse } from 'svelte/compiler'; import { htmlx2jsx } from '../build'; import { test_samples } from '../helpers'; @@ -9,7 +9,8 @@ describe('htmlx2jsx', () => { return htmlx2jsx(input, parse, { emitOnTemplateError, preserveAttributeCase, - typingsNamespace: 'svelteHTML' + typingsNamespace: 'svelteHTML', + svelte5Plus: Number(VERSION[0]) >= 5 }); }, 'js' diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/component-default-slot-let-destructure/expected-svelte5.js b/packages/svelte2tsx/test/htmlx2jsx/samples/component-default-slot-let-destructure/expected-svelte5.js new file mode 100644 index 000000000..b83f6d131 --- /dev/null +++ b/packages/svelte2tsx/test/htmlx2jsx/samples/component-default-slot-let-destructure/expected-svelte5.js @@ -0,0 +1,3 @@ + { const $$_tnenopmoC0C = __sveltets_2_ensureComponent(Component); const $$_tnenopmoC0 = new $$_tnenopmoC0C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,thing:{ a },} = $$_tnenopmoC0.$$slot_def.default;$$_$$; + { svelteHTML.createElement("h1", {}); a ; } + }Component} \ No newline at end of file diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/component-default-slot-let/expected-svelte5.js b/packages/svelte2tsx/test/htmlx2jsx/samples/component-default-slot-let/expected-svelte5.js new file mode 100644 index 000000000..b623bfe7a --- /dev/null +++ b/packages/svelte2tsx/test/htmlx2jsx/samples/component-default-slot-let/expected-svelte5.js @@ -0,0 +1,3 @@ + { const $$_tnenopmoC0C = __sveltets_2_ensureComponent(Component); const $$_tnenopmoC0 = new $$_tnenopmoC0C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,name:n,thing,} = $$_tnenopmoC0.$$slot_def.default;$$_$$; + { svelteHTML.createElement("h1", {}); thing; n; } + }Component} \ No newline at end of file diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/component-default-slot/expected-svelte5.js b/packages/svelte2tsx/test/htmlx2jsx/samples/component-default-slot/expected-svelte5.js new file mode 100644 index 000000000..41f63084e --- /dev/null +++ b/packages/svelte2tsx/test/htmlx2jsx/samples/component-default-slot/expected-svelte5.js @@ -0,0 +1,3 @@ + { const $$_tnenopmoC0C = __sveltets_2_ensureComponent(Component); new $$_tnenopmoC0C({ target: __sveltets_2_any(), props: {children:() => { return __sveltets_2_any(0); },}}); + { svelteHTML.createElement("h1", {}); } + Component} \ No newline at end of file diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/component-multi-slot/expected-svelte5.js b/packages/svelte2tsx/test/htmlx2jsx/samples/component-multi-slot/expected-svelte5.js new file mode 100644 index 000000000..51bc77a40 --- /dev/null +++ b/packages/svelte2tsx/test/htmlx2jsx/samples/component-multi-slot/expected-svelte5.js @@ -0,0 +1,11 @@ + { const $$_tnenopmoC0C = __sveltets_2_ensureComponent(Component); const $$_tnenopmoC0 = new $$_tnenopmoC0C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,var:new_var,} = $$_tnenopmoC0.$$slot_def.default;$$_$$; + { svelteHTML.createElement("h1", {}); new_var; } + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,slotvar:newvar,} = $$_tnenopmoC0.$$slot_def["someslot"];$$_$$;{ svelteHTML.createElement("div", { });newvar; + { svelteHTML.createElement("h2", {}); newvar; } + }} + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,newvar2,} = $$_tnenopmoC0.$$slot_def["slotwithoutchildren"];$$_$$;{ svelteHTML.createElement("div", { });newvar2; }} + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,hi1,hi2,hi3:hi3alias,} = $$_tnenopmoC0.$$slot_def["slotwithmultiplelets"];$$_$$;{ svelteHTML.createElement("div", { }); }} + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,} = $$_tnenopmoC0.$$slot_def["desc"];$$_$$;{ svelteHTML.createElement("p", { }); + + }} + }Component} \ No newline at end of file diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/component-named-slot/expected-svelte5.js b/packages/svelte2tsx/test/htmlx2jsx/samples/component-named-slot/expected-svelte5.js new file mode 100644 index 000000000..4f7bbb8c9 --- /dev/null +++ b/packages/svelte2tsx/test/htmlx2jsx/samples/component-named-slot/expected-svelte5.js @@ -0,0 +1,8 @@ + { const $$_tneraP0C = __sveltets_2_ensureComponent(Parent); const $$_tneraP0 = new $$_tneraP0C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,foo,bar:baz,} = $$_tneraP0.$$slot_def.default;$$_$$; + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,bla,} = $$_tneraP0.$$slot_def["named"];$$_$$;{ const $$_tnenopmoC1C = __sveltets_2_ensureComponent(Component); new $$_tnenopmoC1C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },}}); + foo; baz; bla; + }Component} + { const $$_tnenopmoC1C = __sveltets_2_ensureComponent(Component); const $$_tnenopmoC1 = new $$_tnenopmoC1C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,blubb,} = $$_tnenopmoC1.$$slot_def.default;$$_$$; + blubb; + }Component} + }Parent} \ No newline at end of file diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/component-slot-infer-props/expected-svelte5.js b/packages/svelte2tsx/test/htmlx2jsx/samples/component-slot-infer-props/expected-svelte5.js new file mode 100644 index 000000000..5dcdcf334 --- /dev/null +++ b/packages/svelte2tsx/test/htmlx2jsx/samples/component-slot-infer-props/expected-svelte5.js @@ -0,0 +1,8 @@ + { const $$_tneraP0C = __sveltets_2_ensureComponent(Parent); const $$_tneraP0 = new $$_tneraP0C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },"bare":true,shorthand,"text1":`val1`,"text2":`val2`,"text3":`a${a}b${b}`,"textEmpty":"","literal":true,"strLiteral":'foo',"complex":{a},"a-dashed-complex":{a},...__sveltets_2_cssProp({"--custom-cssprop":`foo`}),}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,foo,} = $$_tneraP0.$$slot_def.default;$$_$$; + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,bar,} = $$_tneraP0.$$slot_def["named"];$$_$$;{ const $$_tnenopmoC1C = __sveltets_2_ensureComponent(Component); new $$_tnenopmoC1C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },}}); + foo; bar; + }Component} + { svelteHTML.createElement("div", {}); + foo; + } + }Parent} \ No newline at end of file diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/component-slot-shadowed-prop/expected-svelte5.js b/packages/svelte2tsx/test/htmlx2jsx/samples/component-slot-shadowed-prop/expected-svelte5.js new file mode 100644 index 000000000..2a770fffe --- /dev/null +++ b/packages/svelte2tsx/test/htmlx2jsx/samples/component-slot-shadowed-prop/expected-svelte5.js @@ -0,0 +1,7 @@ + { const $$_tnenopmoC0C = __sveltets_2_ensureComponent(Component); const $$_tnenopmoC0 = new $$_tnenopmoC0C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },unshadowed1,"foo":unshadowed2,subthing,shadowed1,"shadowed-2":shadowed2,"templateString":` ${complex} `,"complex":{complex},}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,name:n,shadowed1,shadowed2,subthing,} = $$_tnenopmoC0.$$slot_def.default;$$_$$; + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,subthing,} = $$_tnenopmoC0.$$slot_def["sub1"];$$_$$;{ svelteHTML.createElement("p", { });thing;subthing; }} + + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,subthing,othersubthing,} = $$_tnenopmoC0.$$slot_def["sub2"];$$_$$;{ const $$_buS1C = __sveltets_2_ensureComponent(Sub); new $$_buS1C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },subthing,}});thing;subthing; }Sub} + + { const $$_buS1C = __sveltets_2_ensureComponent(Sub); const $$_buS1 = new $$_buS1C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },subthing,}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,subthing,othersubthing,} = $$_buS1.$$slot_def.default;$$_$$;thing;subthing; }Sub} + }Component} \ No newline at end of file diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/if-nested-slot-let-shadowed/expected-svelte5.js b/packages/svelte2tsx/test/htmlx2jsx/samples/if-nested-slot-let-shadowed/expected-svelte5.js new file mode 100644 index 000000000..5357ce84d --- /dev/null +++ b/packages/svelte2tsx/test/htmlx2jsx/samples/if-nested-slot-let-shadowed/expected-svelte5.js @@ -0,0 +1,98 @@ +if(hello && hello1){ + { const $$_pmoC0C = __sveltets_2_ensureComponent(Comp); const $$_pmoC0 = new $$_pmoC0C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,hello,} = $$_pmoC0.$$slot_def.default;$$_$$; + hello; + { const $$_pmoC1C = __sveltets_2_ensureComponent(Comp); const $$_pmoC1 = new $$_pmoC1C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,hello,} = $$_pmoC1.$$slot_def.default;$$_$$; + if(hello){ + hello; + } + }Comp} + { const $$_pmoC1C = __sveltets_2_ensureComponent(Comp); const $$_pmoC1 = new $$_pmoC1C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },hello,}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,hello,} = $$_pmoC1.$$slot_def.default;$$_$$; + if(hello){ + hello; + } + }Comp} + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,hello,} = $$_pmoC0.$$slot_def["named1"];$$_$$;{ svelteHTML.createElement("svelte:fragment", { }); + if(hello){ + hello; + } + }} + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,hello,} = $$_pmoC0.$$slot_def["named2"];$$_$$;{ svelteHTML.createElement("p", { }); + if(hello){ + hello; + } + }} + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,hello,} = $$_pmoC0.$$slot_def["named3"];$$_$$;{ const $$_pmoC1C = __sveltets_2_ensureComponent(Comp); new $$_pmoC1C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },}}); + if(hello){ + hello; + } + }Comp} + if(hello){ + { const $$_pmoC1C = __sveltets_2_ensureComponent(Comp); const $$_pmoC1 = new $$_pmoC1C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,hello,} = $$_pmoC1.$$slot_def.default;$$_$$; + if(hello){ + hello; + } + }Comp} + { const $$_pmoC1C = __sveltets_2_ensureComponent(Comp); const $$_pmoC1 = new $$_pmoC1C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,foo,} = $$_pmoC1.$$slot_def.default;$$_$$; + const hello = foo; + if(hello){ + hello; + } + }Comp} + } + }Comp} + if(hi && bye){ + { const $$_pmoC0C = __sveltets_2_ensureComponent(Comp); const $$_pmoC0 = new $$_pmoC0C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,foo:bye,} = $$_pmoC0.$$slot_def.default;$$_$$; + bye; + }Comp} + } else if (cool){ + { const $$_pmoC0C = __sveltets_2_ensureComponent(Comp); const $$_pmoC0 = new $$_pmoC0C({ target: __sveltets_2_any(), props: {}}); + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,cool,hello,} = $$_pmoC0.$$slot_def["named"];$$_$$;{ svelteHTML.createElement("div", { }); + hello; + }} + Comp} + }else{ + { const $$_pmoC0C = __sveltets_2_ensureComponent(Comp); const $$_pmoC0 = new $$_pmoC0C({ target: __sveltets_2_any(), props: {}}); + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,foo:hello,hello1:other,} = $$_pmoC0.$$slot_def["named"];$$_$$;{ svelteHTML.createElement("div", { }); + hello; + }} + Comp} + } +} + + { const $$_pmoC0C = __sveltets_2_ensureComponent(Comp); const $$_pmoC0 = new $$_pmoC0C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,hello,} = $$_pmoC0.$$slot_def.default;$$_$$; + if(hello && bye){ + hello; bye; + } else if (hello && bye){ + hello; bye; + }else{ + hello; bye; + } + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,hello,} = $$_pmoC0.$$slot_def["named1"];$$_$$;{ svelteHTML.createElement("svelte:fragment", { }); + if(hello && bye){ + hello; bye; + } else if (hello && bye){ + hello; bye; + }else{ + hello; bye; + } + }} + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,hello,} = $$_pmoC0.$$slot_def["named2"];$$_$$;{ svelteHTML.createElement("p", { }); + if(hello && bye){ + hello; bye; + } else if (hello && bye){ + hello; bye; + }else{ + hello; bye; + } + }} + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,foo,} = $$_pmoC0.$$slot_def["named3"];$$_$$;{ svelteHTML.createElement("p", { }); + const hello = foo; + if(hello && bye){ + hello; bye; + } else if (hello && bye){ + hello; bye; + }else{ + hello; bye; + } + }} + }Comp} \ No newline at end of file diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/if-nested-slot-let/expected-svelte5.js b/packages/svelte2tsx/test/htmlx2jsx/samples/if-nested-slot-let/expected-svelte5.js new file mode 100644 index 000000000..dd954cdfc --- /dev/null +++ b/packages/svelte2tsx/test/htmlx2jsx/samples/if-nested-slot-let/expected-svelte5.js @@ -0,0 +1,22 @@ +if(hello){ + { const $$_pmoC0C = __sveltets_2_ensureComponent(Comp); const $$_pmoC0 = new $$_pmoC0C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,foo,} = $$_pmoC0.$$slot_def.default;$$_$$; + foo; + }Comp} + if(hi && bye){ + { const $$_pmoC0C = __sveltets_2_ensureComponent(Comp); const $$_pmoC0 = new $$_pmoC0C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,foo:bar,} = $$_pmoC0.$$slot_def.default;$$_$$; + bar; + }Comp} + } else if (cool){ + { const $$_pmoC0C = __sveltets_2_ensureComponent(Comp); const $$_pmoC0 = new $$_pmoC0C({ target: __sveltets_2_any(), props: {}}); + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,foo,foo1,} = $$_pmoC0.$$slot_def["named"];$$_$$;{ svelteHTML.createElement("div", { }); + foo; + }} + Comp} + }else{ + { const $$_pmoC0C = __sveltets_2_ensureComponent(Comp); const $$_pmoC0 = new $$_pmoC0C({ target: __sveltets_2_any(), props: {}}); + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,foo:bar,} = $$_pmoC0.$$slot_def["named"];$$_$$;{ svelteHTML.createElement("div", { }); + bar; + }} + Comp} + } +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/snippet.skip/expectedv2.js b/packages/svelte2tsx/test/htmlx2jsx/samples/snippet.v5/expected-svelte5.js similarity index 52% rename from packages/svelte2tsx/test/htmlx2jsx/samples/snippet.skip/expectedv2.js rename to packages/svelte2tsx/test/htmlx2jsx/samples/snippet.v5/expected-svelte5.js index 163de3102..a924a26a5 100644 --- a/packages/svelte2tsx/test/htmlx2jsx/samples/snippet.skip/expectedv2.js +++ b/packages/svelte2tsx/test/htmlx2jsx/samples/snippet.v5/expected-svelte5.js @@ -2,10 +2,14 @@ { svelteHTML.createElement("div", {}); x; } return __sveltets_2_any(0)} + var bar/*Ωignore_startΩ*/: import('svelte').Snippet/*Ωignore_endΩ*/ = () => { + { svelteHTML.createElement("div", {}); } +return __sveltets_2_any(0)} + ;__sveltets_2_ensureSnippet(foo(1)); -;__sveltets_2_ensureSnippet(foo()); +;__sveltets_2_ensureSnippet(bar()); - { const $$_tnenopmoC0C = __sveltets_2_ensureComponent(Component); new $$_tnenopmoC0C({ target: __sveltets_2_any(), props: {bar:(x) => { + { const $$_tnenopmoC0C = __sveltets_2_ensureComponent(Component); new $$_tnenopmoC0C({ target: __sveltets_2_any(), props: {children:() => { return __sveltets_2_any(0); },bar:(x) => { { svelteHTML.createElement("div", {}); x; } return __sveltets_2_any(0)},}}); { svelteHTML.createElement("div", {});asd; } @@ -16,4 +20,10 @@ return __sveltets_2_any(0)} item; return __sveltets_2_any(0)},}}); - List} \ No newline at end of file + List} + + { const $$_tsiL0C = __sveltets_2_ensureComponent(List); new $$_tsiL0C({ target: __sveltets_2_any(), props: {children:() => { return __sveltets_2_any(0); },}}); + + List} + +;__sveltets_2_ensureSnippet(children()); \ No newline at end of file diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/snippet.skip/input.svelte b/packages/svelte2tsx/test/htmlx2jsx/samples/snippet.v5/input.svelte similarity index 66% rename from packages/svelte2tsx/test/htmlx2jsx/samples/snippet.skip/input.svelte rename to packages/svelte2tsx/test/htmlx2jsx/samples/snippet.v5/input.svelte index c8c6a8716..6f3603fca 100644 --- a/packages/svelte2tsx/test/htmlx2jsx/samples/snippet.skip/input.svelte +++ b/packages/svelte2tsx/test/htmlx2jsx/samples/snippet.v5/input.svelte @@ -2,8 +2,12 @@
asd{x}
{/snippet} +{#snippet bar()} +
asd
+{/snippet} + {@render foo(1)} -{@render foo()} +{@render bar()}
{asd}
@@ -17,3 +21,9 @@ {item} {/snippet} + + + implicit children + + +{@render children()} diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/svelte-fragment/expected-svelte5.js b/packages/svelte2tsx/test/htmlx2jsx/samples/svelte-fragment/expected-svelte5.js new file mode 100644 index 000000000..d890df015 --- /dev/null +++ b/packages/svelte2tsx/test/htmlx2jsx/samples/svelte-fragment/expected-svelte5.js @@ -0,0 +1,19 @@ + { const $$_tnenopmoC0C = __sveltets_2_ensureComponent(Component); const $$_tnenopmoC0 = new $$_tnenopmoC0C({ target: __sveltets_2_any(), props: {children:() => { return __sveltets_2_any(0); },}}); + { svelteHTML.createElement("svelte:fragment", {}); + { svelteHTML.createElement("p", {}); } + } + + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,} = $$_tnenopmoC0.$$slot_def["named"];$$_$$;{ svelteHTML.createElement("svelte:fragment", { }); + { svelteHTML.createElement("p", {}); } + }} + Component} + + { const $$_tnenopmoC0C = __sveltets_2_ensureComponent(Component); const $$_tnenopmoC0 = new $$_tnenopmoC0C({ target: __sveltets_2_any(), props: {children:() => { return __sveltets_2_any(0); },}}); + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,foo,bar:baz,} = $$_tnenopmoC0.$$slot_def.default;$$_$$;{ svelteHTML.createElement("svelte:fragment", { }); + { svelteHTML.createElement("p", {});foo; baz; } + }} + + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,foo,bar:baz,} = $$_tnenopmoC0.$$slot_def["named"];$$_$$;{ svelteHTML.createElement("svelte:fragment", { }); + { svelteHTML.createElement("p", {});foo; baz; } + }} + Component} \ No newline at end of file diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/ts-in-template.skip/expectedv2.js b/packages/svelte2tsx/test/htmlx2jsx/samples/ts-in-template.v5/expected-svelte5.js similarity index 100% rename from packages/svelte2tsx/test/htmlx2jsx/samples/ts-in-template.skip/expectedv2.js rename to packages/svelte2tsx/test/htmlx2jsx/samples/ts-in-template.v5/expected-svelte5.js diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/ts-in-template.skip/input.svelte b/packages/svelte2tsx/test/htmlx2jsx/samples/ts-in-template.v5/input.svelte similarity index 100% rename from packages/svelte2tsx/test/htmlx2jsx/samples/ts-in-template.skip/input.svelte rename to packages/svelte2tsx/test/htmlx2jsx/samples/ts-in-template.v5/input.svelte diff --git a/packages/svelte2tsx/test/sourcemaps/index.ts b/packages/svelte2tsx/test/sourcemaps/index.ts index 81e821a5a..08b2f62c4 100644 --- a/packages/svelte2tsx/test/sourcemaps/index.ts +++ b/packages/svelte2tsx/test/sourcemaps/index.ts @@ -13,9 +13,11 @@ import { validate_edit_file, validate_test_file } from './process'; +import { VERSION } from 'svelte/compiler'; // TODO figure out what to do with those now that we have the new transformation -describe('sourcemaps', function () { +const isSvelte5Plus = Number(VERSION[0]) >= 5; +(isSvelte5Plus ? describe.skip : describe)('sourcemaps', function () { for (const sample of each_sample(__dirname)) { if (process.env.CI) { sample.checkDirectory({ required: ['*.svelte', 'mappings.jsx', 'test.jsx'] }); diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/component-default-slot/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/component-default-slot/expected-svelte5.ts new file mode 100644 index 000000000..3c53e5578 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/component-default-slot/expected-svelte5.ts @@ -0,0 +1,15 @@ +/// +;function render() { + + let b = 7; + +/*Ωignore_startΩ*/;const __sveltets_createSlot = __sveltets_2_createCreateSlot();/*Ωignore_endΩ*/; +async () => { + { svelteHTML.createElement("div", {}); + { __sveltets_createSlot("default", { "a":b,}); } + }}; +let $$implicit_children = {a:b}; +return { props: {children: $$implicit_children}, slots: {'default': {a:b}}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['children'], __sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/component-multiple-slots/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/component-multiple-slots/expected-svelte5.ts new file mode 100644 index 000000000..bcfe2f952 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/component-multiple-slots/expected-svelte5.ts @@ -0,0 +1,19 @@ +/// +;function render() { + + let b = 7; + let d = 5; + let e = 5; + +/*Ωignore_startΩ*/;const __sveltets_createSlot = __sveltets_2_createCreateSlot();/*Ωignore_endΩ*/; +async () => { + { svelteHTML.createElement("div", {}); + { __sveltets_createSlot("default", { "a":b,}); } + { __sveltets_createSlot("test", { "c":d,e,}); } + { __sveltets_createSlot("abc-cde.113", { }); } + }}; +let $$implicit_children = {a:b}; +return { props: {children: $$implicit_children}, slots: {'default': {a:b}, 'test': {c:d, e:e}, 'abc-cde.113': {}}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['children'], __sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-$$slot-interface/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-$$slot-interface/expected-svelte5.ts new file mode 100644 index 000000000..fd7f3a9c5 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-$$slot-interface/expected-svelte5.ts @@ -0,0 +1,25 @@ +/// +;function render() { + + interface $$Slots { + default: { + a: number; + }, + foo: { + b: number + } + } + let b = 7; + +/*Ωignore_startΩ*/;const __sveltets_createSlot = __sveltets_2_createCreateSlot<$$Slots>();/*Ωignore_endΩ*/; +async () => { + + { svelteHTML.createElement("div", {}); + { __sveltets_createSlot("default", { "a":b,});} + { __sveltets_createSlot("foo", { b,});} + }}; +let $$implicit_children = {a:b}; +return { props: {children: $$implicit_children}, slots: {} as unknown as $$Slots, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['children'], __sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-$$slot-type/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-$$slot-type/expected-svelte5.ts new file mode 100644 index 000000000..0439e6636 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-$$slot-type/expected-svelte5.ts @@ -0,0 +1,25 @@ +/// +;function render() { + + type $$Slots = { + default: { + a: number; + }, + foo: { + b: number + } + } + let b = 7; + +/*Ωignore_startΩ*/;const __sveltets_createSlot = __sveltets_2_createCreateSlot<$$Slots>();/*Ωignore_endΩ*/; +async () => { + + { svelteHTML.createElement("div", {}); + { __sveltets_createSlot("default", { "a":b,});} + { __sveltets_createSlot("foo", { b,});} + }}; +let $$implicit_children = {a:b}; +return { props: {children: $$implicit_children}, slots: {} as unknown as $$Slots, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['children'], __sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-crazy-attributes/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-crazy-attributes/expected-svelte5.ts new file mode 100644 index 000000000..9a1589581 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-crazy-attributes/expected-svelte5.ts @@ -0,0 +1,15 @@ +/// +;function render() { + + let b = 7; + +/*Ωignore_startΩ*/;const __sveltets_createSlot = __sveltets_2_createCreateSlot();/*Ωignore_endΩ*/; +async () => { + { svelteHTML.createElement("div", {}); + { __sveltets_createSlot("default", { "a":b,b,"c":`b`,"d":`a${b}`,"e":b,}); } + }}; +let $$implicit_children = {a:b, b:b, c:"b", d:"__svelte_ts_string", e:b}; +return { props: {children: $$implicit_children}, slots: {'default': {a:b, b:b, c:"b", d:"__svelte_ts_string", e:b}}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['children'], __sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-fallback/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-fallback/expected-svelte5.ts new file mode 100644 index 000000000..21803bd49 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-fallback/expected-svelte5.ts @@ -0,0 +1,11 @@ +/// +;function render() { +/*Ωignore_startΩ*/;const __sveltets_createSlot = __sveltets_2_createCreateSlot();/*Ωignore_endΩ*/ +async () => { { __sveltets_createSlot("default", {}); { svelteHTML.createElement("div", {}); } } + { __sveltets_createSlot("foo", { bar,"baz":`boo`,}); + { svelteHTML.createElement("p", {}); } + }}; +return { props: {children: __sveltets_2_snippet}, slots: {'default': {}, 'foo': {bar:bar, baz:"boo"}}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['children'], __sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-forward-with-props/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-forward-with-props/expected-svelte5.ts new file mode 100644 index 000000000..ae12d9e6b --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-forward-with-props/expected-svelte5.ts @@ -0,0 +1,11 @@ +/// +;function render() { +/*Ωignore_startΩ*/;const __sveltets_createSlot = __sveltets_2_createCreateSlot();/*Ωignore_endΩ*/ +async () => { { const $$_tneraP0C = __sveltets_2_ensureComponent(Parent); const $$_tneraP0 = new $$_tneraP0C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },"propA":true,propB,"propC":`val1`,"propD":`val2`,"propE":`a${a}b${b}`,}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,foo,} = $$_tneraP0.$$slot_def.default;$$_$$; + { __sveltets_createSlot("default", { foo,});} + }Parent}}; +let $$implicit_children = {foo:__sveltets_2_instanceOf(Parent).$$slot_def['default'].foo}; +return { props: {children: $$implicit_children}, slots: {'default': {foo:__sveltets_2_instanceOf(Parent).$$slot_def['default'].foo}}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['children'], __sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-inside-await/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-inside-await/expected-svelte5.ts new file mode 100644 index 000000000..a75de6541 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-inside-await/expected-svelte5.ts @@ -0,0 +1,16 @@ +/// +;function render() { +/*Ωignore_startΩ*/;const __sveltets_createSlot = __sveltets_2_createCreateSlot();/*Ωignore_endΩ*/ +async () => { { try { const $$_value = await (promise);{ const value = $$_value; + { __sveltets_createSlot("default", { "a":value,}); } +}} catch($$_e) { const err = __sveltets_2_any(); + { __sveltets_createSlot("err", { "err":err,}); } +}} + { const $$_value = await (promise2);{ const { b } = $$_value; + { __sveltets_createSlot("second", { "a":b,}); } +}}}; +let $$implicit_children = {a:__sveltets_2_unwrapPromiseLike(promise)}; +return { props: {children: $$implicit_children}, slots: {'default': {a:__sveltets_2_unwrapPromiseLike(promise)}, 'err': {err:__sveltets_2_any({})}, 'second': {a:(({ b }) => b)(__sveltets_2_unwrapPromiseLike(promise2))}}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['children'], __sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-inside-each/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-inside-each/expected-svelte5.ts new file mode 100644 index 000000000..60c5308c9 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-inside-each/expected-svelte5.ts @@ -0,0 +1,14 @@ +/// +;function render() { +/*Ωignore_startΩ*/;const __sveltets_createSlot = __sveltets_2_createCreateSlot();/*Ωignore_endΩ*/ +async () => { for(let item of __sveltets_2_ensureArray(items)){ + { __sveltets_createSlot("default", { "a":item,}); } +} + for(let { a } of __sveltets_2_ensureArray(items2)){ + { __sveltets_createSlot("second", { a,}); } +}}; +let $$implicit_children = {a:__sveltets_2_unwrapArr(items)}; +return { props: {children: $$implicit_children}, slots: {'default': {a:__sveltets_2_unwrapArr(items)}, 'second': {a:(({ a }) => a)(__sveltets_2_unwrapArr(items2))}}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['children'], __sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-let-forward-named-slot/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-let-forward-named-slot/expected-svelte5.ts new file mode 100644 index 000000000..5383619e2 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-let-forward-named-slot/expected-svelte5.ts @@ -0,0 +1,13 @@ +/// +;function render() { +/*Ωignore_startΩ*/;const __sveltets_createSlot = __sveltets_2_createCreateSlot();/*Ωignore_endΩ*/ +async () => { { const $$_tnenopmoC0C = __sveltets_2_ensureComponent(Component); const $$_tnenopmoC0 = new $$_tnenopmoC0C({ target: __sveltets_2_any(), props: {}}); + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,a,} = $$_tnenopmoC0.$$slot_def["b"];$$_$$;{ svelteHTML.createElement("div", { }); + { __sveltets_createSlot("default", {a,}); } + }} + Component}}; +let $$implicit_children = {a:__sveltets_2_instanceOf(Component).$$slot_def['b'].a}; +return { props: {children: $$implicit_children}, slots: {'default': {a:__sveltets_2_instanceOf(Component).$$slot_def['b'].a}}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['children'], __sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-let-forward/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-let-forward/expected-svelte5.ts new file mode 100644 index 000000000..3d9ee3e89 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-let-forward/expected-svelte5.ts @@ -0,0 +1,11 @@ +/// +;function render() { +/*Ωignore_startΩ*/;const __sveltets_createSlot = __sveltets_2_createCreateSlot();/*Ωignore_endΩ*/ +async () => { { const $$_tnenopmoC0C = __sveltets_2_ensureComponent(Component); const $$_tnenopmoC0 = new $$_tnenopmoC0C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,name:n,thing,whatever:{ bla },} = $$_tnenopmoC0.$$slot_def.default;$$_$$; + { __sveltets_createSlot("default", { n,thing,bla,});} + }Component}}; +let $$implicit_children = {n:__sveltets_2_instanceOf(Component).$$slot_def['default'].name, thing:__sveltets_2_instanceOf(Component).$$slot_def['default'].thing, bla:(({ bla }) => bla)(__sveltets_2_instanceOf(Component).$$slot_def['default'].whatever)}; +return { props: {children: $$implicit_children}, slots: {'default': {n:__sveltets_2_instanceOf(Component).$$slot_def['default'].name, thing:__sveltets_2_instanceOf(Component).$$slot_def['default'].thing, bla:(({ bla }) => bla)(__sveltets_2_instanceOf(Component).$$slot_def['default'].whatever)}}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['children'], __sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-nest-scope/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-nest-scope/expected-svelte5.ts new file mode 100644 index 000000000..18a004c38 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-nest-scope/expected-svelte5.ts @@ -0,0 +1,19 @@ +/// +;function render() { +/*Ωignore_startΩ*/;const __sveltets_createSlot = __sveltets_2_createCreateSlot();/*Ωignore_endΩ*/ +async () => { for(let item of __sveltets_2_ensureArray(items)){ + for(let { a } of __sveltets_2_ensureArray(item)){ + { __sveltets_createSlot("default", {a,}); } + } + { __sveltets_createSlot("second", { a,}); } +} + { const $$_tnenopmoC0C = __sveltets_2_ensureComponent(Component); const $$_tnenopmoC0 = new $$_tnenopmoC0C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,c,} = $$_tnenopmoC0.$$slot_def.default;$$_$$; c ; }Component} + { const $$_value = await (promise);{ const d = $$_value; + d; +}} + { __sveltets_createSlot("third", { d,c,}); }}; +let $$implicit_children = {a:(({ a }) => a)(__sveltets_2_unwrapArr(__sveltets_2_unwrapArr(items)))}; +return { props: {children: $$implicit_children}, slots: {'default': {a:(({ a }) => a)(__sveltets_2_unwrapArr(__sveltets_2_unwrapArr(items)))}, 'second': {a:a}, 'third': {d:d, c:c}}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['children'], __sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-no-space/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-no-space/expected-svelte5.ts new file mode 100644 index 000000000..e105b7c9b --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-no-space/expected-svelte5.ts @@ -0,0 +1,14 @@ +/// +; +import Test from './Test.svelte'; +function render() { + + +; +async () => { + + { svelteHTML.createElement("div", {}); { const $$_tseT1C = __sveltets_2_ensureComponent(Test); const $$_tseT1 = new $$_tseT1C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,t,} = $$_tseT1.$$slot_def.default;$$_$$; }Test} }}; +return { props: /** @type {Record} */ ({}), slots: {}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(__sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-object-key/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-object-key/expected-svelte5.ts new file mode 100644 index 000000000..1b3bbf8c8 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-object-key/expected-svelte5.ts @@ -0,0 +1,11 @@ +/// +;function render() { +/*Ωignore_startΩ*/;const __sveltets_createSlot = __sveltets_2_createCreateSlot();/*Ωignore_endΩ*/ +async () => { for(let item of __sveltets_2_ensureArray(items)){ + { __sveltets_createSlot("default", { "a":item,"b":{ item },"c":{ item: 'abc' }.item,"d":{ item: item },"e":$item,"f":$item,...g,...item,}); } +}}; +let $$implicit_children = {a:__sveltets_2_unwrapArr(items), b:{ item:__sveltets_2_unwrapArr(items) }, c:{ item: 'abc' }.item, d:{ item: __sveltets_2_unwrapArr(items) }, e:$item, f:$item, ...g, ...__sveltets_2_unwrapArr(items)}; +return { props: {children: $$implicit_children}, slots: {'default': {a:__sveltets_2_unwrapArr(items), b:{ item:__sveltets_2_unwrapArr(items) }, c:{ item: 'abc' }.item, d:{ item: __sveltets_2_unwrapArr(items) }, e:$item, f:$item, ...g, ...__sveltets_2_unwrapArr(items)}}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['children'], __sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-var-shadowing/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-var-shadowing/expected-svelte5.ts new file mode 100644 index 000000000..35492b2e1 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-var-shadowing/expected-svelte5.ts @@ -0,0 +1,11 @@ +/// +;function render() { +/*Ωignore_startΩ*/;const __sveltets_createSlot = __sveltets_2_createCreateSlot();/*Ωignore_endΩ*/ +async () => { { const $$_each = __sveltets_2_ensureArray(items); for(let items of $$_each){ + { __sveltets_createSlot("default", { "a":items,}); } +}}}; +let $$implicit_children = {a:__sveltets_2_unwrapArr(items)}; +return { props: {children: $$implicit_children}, slots: {'default': {a:__sveltets_2_unwrapArr(items)}}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['children'], __sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/const-tag-component/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/const-tag-component/expected-svelte5.ts new file mode 100644 index 000000000..ebfc034c1 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/const-tag-component/expected-svelte5.ts @@ -0,0 +1,69 @@ +/// +; +import Component from './Component.svelte'; +function render() { + + + let box = {width: 3, height: 4}; + let constant = 10; + + function calculate(width, height, constant) { + return { area: width * height, volume: width * height * constant }; + } +; +async () => { + + { const $$_tnenopmoC0C = __sveltets_2_ensureComponent(Component); const $$_tnenopmoC0 = new $$_tnenopmoC0C({ target: __sveltets_2_any(), props: {children:() => { return __sveltets_2_any(0); },box,}}); + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,box,} = $$_tnenopmoC0.$$slot_def["box1"];$$_$$;{ svelteHTML.createElement("svelte:fragment", { }); + const {area, volume} = calculate(box.width, box.height, constant); + const perimeter = (box.width + box.height) * constant; + const [width, height, sum] = [box.width * constant, box.height, box.width * constant + box.height]; + { svelteHTML.createElement("div", {});area; volume; perimeter; width; height; sum; } + }} + + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,width,height,} = $$_tnenopmoC0.$$slot_def["box2"];$$_$$;{ svelteHTML.createElement("svelte:fragment", { }); + const {area, volume} = calculate(width, height, constant); + const perimeter = (width + height) * constant; + const [_width, _height, sum] = [width * constant, height, width * constant + height]; + { svelteHTML.createElement("div", {});area; volume; perimeter; _width; _height; sum; } + }} + + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,box:{width, height},} = $$_tnenopmoC0.$$slot_def.default;$$_$$;{ svelteHTML.createElement("svelte:fragment", { }); + const {area, volume} = calculate(width, height, constant); + const perimeter = (width + height) * constant; + const [_width, _height, sum] = [width * constant, height, width * constant + height]; + { svelteHTML.createElement("div", {});area; volume; perimeter; _width; _height; sum; } + }} + Component} + + { const $$_tnenopmoC0C = __sveltets_2_ensureComponent(Component); const $$_tnenopmoC0 = new $$_tnenopmoC0C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },box,}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,box,} = $$_tnenopmoC0.$$slot_def.default;$$_$$; + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,box,} = $$_tnenopmoC0.$$slot_def["box1"];$$_$$;{ svelteHTML.createElement("div", { }); + const {area, volume} = calculate(box.width, box.height, constant); + const perimeter = (box.width + box.height) * constant; + const [width, height, sum] = [box.width * constant, box.height, box.width * constant + box.height]; + { svelteHTML.createElement("div", {});area; volume; perimeter; width; height; sum; } + }} + + {const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,width,height,} = $$_tnenopmoC0.$$slot_def["box2"];$$_$$;{ svelteHTML.createElement("div", { }); + const {area, volume} = calculate(width, height, constant); + const perimeter = (width + height) * constant; + const [_width, _height, sum] = [width * constant, height, width * constant + height]; + { svelteHTML.createElement("div", {});area; volume; perimeter; _width; _height; sum; } + }} + + const {area, volume} = calculate(box.width, box.height, constant); + const perimeter = (box.width + box.height) * constant; + const [width, height, sum] = [box.width * constant, box.height, box.width * constant + box.height]; + { svelteHTML.createElement("div", {});area; volume; perimeter; width; height; sum; } + }Component} + + { const $$_tnenopmoC0C = __sveltets_2_ensureComponent(Component); const $$_tnenopmoC0 = new $$_tnenopmoC0C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },box,}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,box:{width, height},} = $$_tnenopmoC0.$$slot_def.default;$$_$$; + const {area, volume} = calculate(width, height, constant); + const perimeter = (width + height) * constant; + const [_width, _height, sum] = [width * constant, height, width * constant + height]; + { svelteHTML.createElement("div", {});area; volume; perimeter; _width; _height; sum; } + }Component}}; +return { props: {box: box , constant: constant}, slots: {}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['box','constant'], __sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/creates-dts/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/creates-dts/expected-svelte5.ts new file mode 100644 index 000000000..7534c78f3 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/creates-dts/expected-svelte5.ts @@ -0,0 +1,34 @@ +import { SvelteComponentTyped } from "svelte" + +; + export const foo = 'foo'; +;; + +import { createEventDispatcher } from 'svelte'; +function render() { + + + + /** @type {boolean} */ + let bar/*Ωignore_startΩ*/;bar = __sveltets_2_any(bar);/*Ωignore_endΩ*/; + let foobar = ''; + + const dispatch = createEventDispatcher(); + dispatch('hi'); +; +async () => { + + + + { svelteHTML.createElement("button", { "on:click":undefined,}); } + { __sveltets_createSlot("default", {bar,}); }}; +let $$implicit_children = {bar:bar}; +return { props: { +/** @type {boolean} */bar: bar , foobar: foobar , children: $$implicit_children}, slots: {'default': {bar:bar}}, events: {'click':__sveltets_2_mapElementEvent('click'), 'hi': __sveltets_2_customEvent} }} +const __propDef = __sveltets_2_partial(['foobar','children'], __sveltets_2_with_any_event(render())); +/** @typedef {typeof __propDef.props} InputProps */ +/** @typedef {typeof __propDef.events} InputEvents */ +/** @typedef {typeof __propDef.slots} InputSlots */ + +export default class Input extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['foobar','children'], __sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/creates-no-script-dts/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/creates-no-script-dts/expected-svelte5.ts new file mode 100644 index 000000000..96155ecfd --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/creates-no-script-dts/expected-svelte5.ts @@ -0,0 +1,15 @@ +import { SvelteComponentTyped } from "svelte" + +;function render() { +async () => { { svelteHTML.createElement("button", { "on:click":undefined,}); { __sveltets_createSlot("default", {});} } + { const $$_value = await (Promise.resolve(0));{ const n = $$_value; + n; +}}}; +return { props: {children: __sveltets_2_snippet}, slots: {'default': {}}, events: {'click':__sveltets_2_mapElementEvent('click')} }} +const __propDef = __sveltets_2_partial(['children'], __sveltets_2_with_any_event(render())); +/** @typedef {typeof __propDef.props} InputProps */ +/** @typedef {typeof __propDef.events} InputEvents */ +/** @typedef {typeof __propDef.slots} InputSlots */ + +export default class Input extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['children'], __sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/runes-best-effort-types/expectedv2.ts b/packages/svelte2tsx/test/svelte2tsx/samples/runes-best-effort-types/expectedv2.ts new file mode 100644 index 000000000..0d9f1015a --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/runes-best-effort-types/expectedv2.ts @@ -0,0 +1,10 @@ +/// +;function render() { + + let/** @type {{ a: unknown, b?: boolean, c?: number, d?: string, e?: unknown, f?: unknown, g?: typeof foo }} */ { a, b = true, c = 1, d = '', e = null, f = {}, g = foo } = $props(); +; +async () => {}; +return { props: /** @type {{ a: unknown, b?: boolean, c?: number, d?: string, e?: unknown, f?: unknown, g?: typeof foo }} */({}), slots: {}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(__sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/runes-best-effort-types/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/runes-best-effort-types/input.svelte new file mode 100644 index 000000000..a4a6fefa1 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/runes-best-effort-types/input.svelte @@ -0,0 +1,3 @@ + diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/runes-looking-like-stores/expectedv2.ts b/packages/svelte2tsx/test/svelte2tsx/samples/runes-looking-like-stores/expectedv2.ts index 2b5181184..99bcaff29 100644 --- a/packages/svelte2tsx/test/svelte2tsx/samples/runes-looking-like-stores/expectedv2.ts +++ b/packages/svelte2tsx/test/svelte2tsx/samples/runes-looking-like-stores/expectedv2.ts @@ -1,14 +1,14 @@ /// ;function render() { - let { props } = $props(); + let/** @type {{ props: unknown }} */ { props } = $props(); let state = $state(0); let derived = $derived(state * 2); ; async () => { state; derived;}; -return { props: /** @type {Record} */ ({}), slots: {}, events: {} }} +return { props: /** @type {{ props: unknown }} */({}), slots: {}, events: {} }} export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(__sveltets_2_with_any_event(render()))) { } \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/script-style-like-component/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/script-style-like-component/expected-svelte5.ts new file mode 100644 index 000000000..25c7a5e18 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/script-style-like-component/expected-svelte5.ts @@ -0,0 +1,15 @@ +/// +;function render() { + + let Script, Style; +; +async () => { + + { const $$_tpircS0C = __sveltets_2_ensureComponent(Script); new $$_tpircS0C({ target: __sveltets_2_any(), props: {children:() => { return __sveltets_2_any(0); },}}); + { svelteHTML.createElement("p", {}); } + Script} + { const $$_elytS0C = __sveltets_2_ensureComponent(Style); new $$_elytS0C({ target: __sveltets_2_any(), props: {}});}}; +return { props: /** @type {Record} */ ({}), slots: {}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(__sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/snippet-instance-script.skip/expectedv2.ts b/packages/svelte2tsx/test/svelte2tsx/samples/snippet-instance-script.v5/expected-svelte5.ts similarity index 79% rename from packages/svelte2tsx/test/svelte2tsx/samples/snippet-instance-script.skip/expectedv2.ts rename to packages/svelte2tsx/test/svelte2tsx/samples/snippet-instance-script.v5/expected-svelte5.ts index 1f04f5e52..435861e05 100644 --- a/packages/svelte2tsx/test/svelte2tsx/samples/snippet-instance-script.skip/expectedv2.ts +++ b/packages/svelte2tsx/test/svelte2tsx/samples/snippet-instance-script.v5/expected-svelte5.ts @@ -3,7 +3,7 @@ let foo = true; bar; - var bar/*Ωignore_startΩ*/: import('svelte').Snippet/*Ωignore_endΩ*/ = () => { foo; + var bar/*Ωignore_startΩ*/: import('svelte').Snippet/*Ωignore_endΩ*/ = () => { foo; return __sveltets_2_any(0)}; async () => { diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/snippet-instance-script.skip/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/snippet-instance-script.v5/input.svelte similarity index 100% rename from packages/svelte2tsx/test/svelte2tsx/samples/snippet-instance-script.skip/input.svelte rename to packages/svelte2tsx/test/svelte2tsx/samples/snippet-instance-script.v5/input.svelte diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/expected-svelte5.ts new file mode 100644 index 000000000..6adeb2aef --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/expected-svelte5.ts @@ -0,0 +1,17 @@ +/// +;function render() { + + let tag = 'div'; +; +async () => { + + { svelteHTML.createElement(tag, { });} + { svelteHTML.createElement("tag", { });} + { svelteHTML.createElement(tag ? 'a' : 'b', { });} + { svelteHTML.createElement(tag, { });tag; } + { svelteHTML.createElement(tag, { "on:click":() => tag,});} + { svelteHTML.createElement("a", { "data-sveltekit-preload-data":true,"href":`https://kit.svelte.dev`,});}}; +return { props: /** @type {Record} */ ({}), slots: {}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(__sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/ts-$$generics-dts/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/ts-$$generics-dts/expected-svelte5.ts new file mode 100644 index 000000000..75c895585 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/ts-$$generics-dts/expected-svelte5.ts @@ -0,0 +1,45 @@ +import { SvelteComponentTyped } from "svelte" + +; +import { createEventDispatcher } from 'svelte'; +function render/*Ωignore_startΩ*//*Ωignore_endΩ*/() { + + + + + + + + let a: A/*Ωignore_startΩ*/;a = __sveltets_2_any(a);/*Ωignore_endΩ*/; + let b: B/*Ωignore_startΩ*/;b = __sveltets_2_any(b);/*Ωignore_endΩ*/; + let c: C/*Ωignore_startΩ*/;c = __sveltets_2_any(c);/*Ωignore_endΩ*/; + + const dispatch = createEventDispatcher<{a: A}>(); + + function getA() { + return a; + } +; +async () => { + + { __sveltets_createSlot("default", { c,});}}; +let $$implicit_children = {c:c}; +return { props: {a: a , b: b , c: c , getA: getA , children: $$implicit_children} as {a: A, b: B, c: C, getA?: typeof getA, children: typeof $$implicit_children}, slots: {'default': {c:c}}, events: {...__sveltets_2_toEventTypings<{a: A}>()} }} +class __sveltets_Render { + props() { + return render().props; + } + events() { + return __sveltets_2_with_any_event(render()).events; + } + slots() { + return render().slots; + } +} +export type InputProps = ReturnType<__sveltets_Render['props']>; +export type InputEvents = ReturnType<__sveltets_Render['events']>; +export type InputSlots = ReturnType<__sveltets_Render['slots']>; + +export default class Input extends SvelteComponentTyped, InputEvents, InputSlots> { + get getA() { return __sveltets_2_nonNullable(this.$$prop_def.getA) } +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/ts-$$generics/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/ts-$$generics/expected-svelte5.ts new file mode 100644 index 000000000..3b6e38bf6 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/ts-$$generics/expected-svelte5.ts @@ -0,0 +1,44 @@ +/// +; +import { createEventDispatcher } from 'svelte'; +function render/*Ωignore_startΩ*//*Ωignore_endΩ*/() { + + + + + + + + let a: A/*Ωignore_startΩ*/;a = __sveltets_2_any(a);/*Ωignore_endΩ*/; + let b: B/*Ωignore_startΩ*/;b = __sveltets_2_any(b);/*Ωignore_endΩ*/; + let c: C/*Ωignore_startΩ*/;c = __sveltets_2_any(c);/*Ωignore_endΩ*/; + + const dispatch = createEventDispatcher<{a: A}>(); + + function getA() { + return a; + } + +/*Ωignore_startΩ*/;const __sveltets_createSlot = __sveltets_2_createCreateSlot();/*Ωignore_endΩ*/; +async () => { + + { __sveltets_createSlot("default", { c,});}}; +let $$implicit_children = {c:c}; +return { props: {a: a , b: b , c: c , getA: getA , children: $$implicit_children} as {a: A, b: B, c: C, getA?: typeof getA, children: typeof $$implicit_children}, slots: {'default': {c:c}}, events: {...__sveltets_2_toEventTypings<{a: A}>()} }} +class __sveltets_Render { + props() { + return render().props; + } + events() { + return __sveltets_2_with_any_event(render()).events; + } + slots() { + return render().slots; + } +} + + +import { SvelteComponentTyped as __SvelteComponentTyped__ } from "svelte" +export default class Input__SvelteComponent_ extends __SvelteComponentTyped__['props']>, ReturnType<__sveltets_Render['events']>, ReturnType<__sveltets_Render['slots']>> { + get getA() { return __sveltets_2_nonNullable(this.$$prop_def.getA) } +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/ts-creates-dts/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/ts-creates-dts/expected-svelte5.ts new file mode 100644 index 000000000..9fc79a0c7 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/ts-creates-dts/expected-svelte5.ts @@ -0,0 +1,33 @@ +import { SvelteComponentTyped } from "svelte" + +; + export const foo = 'foo'; +;; + +import Bar from './bar'; +import { createEventDispatcher } from 'svelte'; +function render() { + + + + + let bar: Bar/*Ωignore_startΩ*/;bar = __sveltets_2_any(bar);/*Ωignore_endΩ*/; + let foobar = ''; + + const dispatch = createEventDispatcher<{swipe: string}>(); +; +async () => { + + + + { svelteHTML.createElement("button", { "on:click":undefined,}); } + { __sveltets_createSlot("default", {bar,}); }}; +let $$implicit_children = {bar:bar}; +return { props: {bar: bar , foobar: foobar , children: $$implicit_children} as {bar: Bar, foobar?: typeof foobar, children: typeof $$implicit_children}, slots: {'default': {bar:bar}}, events: {...__sveltets_2_toEventTypings<{swipe: string}>(), 'click':__sveltets_2_mapElementEvent('click')} }} +const __propDef = __sveltets_2_with_any_event(render()); +export type InputProps = typeof __propDef.props; +export type InputEvents = typeof __propDef.events; +export type InputSlots = typeof __propDef.slots; + +export default class Input extends SvelteComponentTyped { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/ts-generics-attribute1/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/ts-generics-attribute1/expected-svelte5.ts new file mode 100644 index 000000000..a090364c4 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/ts-generics-attribute1/expected-svelte5.ts @@ -0,0 +1,40 @@ +/// +; +import { createEventDispatcher } from 'svelte'; +function render() { + + + + let a: A/*Ωignore_startΩ*/;a = __sveltets_2_any(a);/*Ωignore_endΩ*/; + let b: B/*Ωignore_startΩ*/;b = __sveltets_2_any(b);/*Ωignore_endΩ*/; + let c: C/*Ωignore_startΩ*/;c = __sveltets_2_any(c);/*Ωignore_endΩ*/; + + const dispatch = createEventDispatcher<{a: A}>(); + + function getA() { + return a; + } + +/*Ωignore_startΩ*/;const __sveltets_createSlot = __sveltets_2_createCreateSlot();/*Ωignore_endΩ*/; +async () => { + + { __sveltets_createSlot("default", { c,});}}; +let $$implicit_children = {c:c}; +return { props: {a: a , b: b , c: c , getA: getA , children: $$implicit_children} as {a: A, b: B, c: C, getA?: typeof getA, children: typeof $$implicit_children}, slots: {'default': {c:c}}, events: {...__sveltets_2_toEventTypings<{a: A}>()} }} +class __sveltets_Render { + props() { + return render().props; + } + events() { + return __sveltets_2_with_any_event(render()).events; + } + slots() { + return render().slots; + } +} + + +import { SvelteComponentTyped as __SvelteComponentTyped__ } from "svelte" +export default class Input__SvelteComponent_ extends __SvelteComponentTyped__['props']>, ReturnType<__sveltets_Render['events']>, ReturnType<__sveltets_Render['slots']>> { + get getA() { return __sveltets_2_nonNullable(this.$$prop_def.getA) } +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-best-effort-types/expectedv2.ts b/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-best-effort-types/expectedv2.ts new file mode 100644 index 000000000..d1cc6a0a7 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-best-effort-types/expectedv2.ts @@ -0,0 +1,10 @@ +/// +;function render() { + + let { a, b = true, c = 1, d = '', e = null, f = {}, g = foo, h = null as Bar, i = null as any as Baz } = $props/*Ωignore_startΩ*/<{ a: unknown, b?: boolean, c?: number, d?: string, e?: unknown, f?: unknown, g?: typeof foo, h?: Bar, i?: Baz }>/*Ωignore_endΩ*/(); +; +async () => {}; +return { props: {} as any as { a: unknown, b?: boolean, c?: number, d?: string, e?: unknown, f?: unknown, g?: typeof foo, h?: Bar, i?: Baz }, slots: {}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_with_any_event(render())) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-best-effort-types/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-best-effort-types/input.svelte new file mode 100644 index 000000000..8e27e77f4 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-best-effort-types/input.svelte @@ -0,0 +1,3 @@ + diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots-script/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots-script/expected-svelte5.ts new file mode 100644 index 000000000..8e9bb4470 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots-script/expected-svelte5.ts @@ -0,0 +1,17 @@ +/// +;function render() { let $$slots = __sveltets_2_slotsType({'foo': '', 'dashed-name': '', 'default': ''}); + + let name = $$slots.foo; + let dashedName = $$slots['dashed-name']; + +/*Ωignore_startΩ*/;const __sveltets_createSlot = __sveltets_2_createCreateSlot();/*Ωignore_endΩ*/; +async () => { + + { svelteHTML.createElement("h1", {});name; } + { __sveltets_createSlot("foo", { });} + { __sveltets_createSlot("dashed-name", { });} + { __sveltets_createSlot("default", {});}}; +return { props: {children: __sveltets_2_snippet}, slots: {'foo': {}, 'dashed-name': {}, 'default': {}}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['children'], __sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots/expected-svelte5.ts new file mode 100644 index 000000000..78a21b343 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/uses-$$slots/expected-svelte5.ts @@ -0,0 +1,13 @@ +/// +;function render() { let $$slots = __sveltets_2_slotsType({'foo': '', 'dashed-name': '', 'default': ''}); +/*Ωignore_startΩ*/;const __sveltets_createSlot = __sveltets_2_createCreateSlot();/*Ωignore_endΩ*/ +async () => { { svelteHTML.createElement("h1", {});$$slots.foo; } + { svelteHTML.createElement("h1", {});$$slots['dashed-name']; } + + { __sveltets_createSlot("foo", { });} + { __sveltets_createSlot("dashed-name", { });} + { __sveltets_createSlot("default", {});}}; +return { props: {children: __sveltets_2_snippet}, slots: {'foo': {}, 'dashed-name': {}, 'default': {}}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['children'], __sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/uses-svelte-components-let-forward/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/uses-svelte-components-let-forward/expected-svelte5.ts new file mode 100644 index 000000000..5a5b93510 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/uses-svelte-components-let-forward/expected-svelte5.ts @@ -0,0 +1,16 @@ +/// +;function render() { +/*Ωignore_startΩ*/;const __sveltets_createSlot = __sveltets_2_createCreateSlot();/*Ωignore_endΩ*/ +async () => {if(true){ + { const $$_svelteself0 = __sveltets_2_createComponentAny({ children:() => { return __sveltets_2_any(0); },});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,prop,} = $$_svelteself0.$$slot_def.default;$$_$$; + { __sveltets_createSlot("default", { prop,});} + }} +} + { const $$_tnenopmoc_etlevs0C = __sveltets_2_ensureComponent(testComponent); const $$_tnenopmoc_etlevs0 = new $$_tnenopmoc_etlevs0C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },}});{const {/*Ωignore_startΩ*/$$_$$/*Ωignore_endΩ*/,prop,} = $$_tnenopmoc_etlevs0.$$slot_def.default;$$_$$; + { __sveltets_createSlot("default", { prop,});} + }}}; +let $$implicit_children = {prop:__sveltets_2_instanceOf(__sveltets_1_componentType()).$$slot_def['default'].prop}; +return { props: {children: $$implicit_children}, slots: {'default': {prop:__sveltets_2_instanceOf(__sveltets_1_componentType()).$$slot_def['default'].prop}}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(['children'], __sveltets_2_with_any_event(render()))) { +} \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/uses-svelte-components/expected-svelte5.ts b/packages/svelte2tsx/test/svelte2tsx/samples/uses-svelte-components/expected-svelte5.ts new file mode 100644 index 000000000..b5aa1f8cb --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/uses-svelte-components/expected-svelte5.ts @@ -0,0 +1,20 @@ +/// +;function render() { +async () => {if(true){ + { __sveltets_2_createComponentAny({ "prop1":1,});} +} + { const $$_tnenopmoc_etlevs0C = __sveltets_2_ensureComponent(testComponent); new $$_tnenopmoc_etlevs0C({ target: __sveltets_2_any(), props: { children:() => { return __sveltets_2_any(0); },"propa":5,}}); + { svelteHTML.createElement("h1", {}); } + } + { svelteHTML.createElement("svelte:window", { "on:click":e => {},});} + { svelteHTML.createElement("svelte:body", { "on:click":e => {},});} + { svelteHTML.createElement("svelte:head", {}); + { svelteHTML.createElement("h1", {}); } + } + { svelteHTML.createElement("svelte:options", {});} + { svelteHTML.createElement("svelte:fragment", {});} + { svelteHTML.createElement("svelte:document", { "foo":`bar`,"on:click":e => {},});}}; +return { props: /** @type {Record} */ ({}), slots: {}, events: {} }} + +export default class Input__SvelteComponent_ extends __sveltets_2_createSvelte2TsxComponent(__sveltets_2_partial(__sveltets_2_with_any_event(render()))) { +} \ No newline at end of file