From 94af464767fd57a0fb4017adee9861a62b77b707 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Thu, 21 Nov 2024 11:22:38 +0100 Subject: [PATCH 1/2] chore: consolidate template walking logic right now some of the logic of walking the template is within the svelte2tsx part, some in the htmlxtojsx part. This makes it hard to decide where to put new stuff and represents an arbitrary barrier for features that may need to work across both. This PR therefore moves all the logic from the svelte2tsx part into the htmlxtojsx part. --- .../svelte2tsx/src/htmlxtojsx_v2/index.ts | 287 +++++++++++++++-- packages/svelte2tsx/src/svelte2tsx/index.ts | 298 +----------------- 2 files changed, 269 insertions(+), 316 deletions(-) diff --git a/packages/svelte2tsx/src/htmlxtojsx_v2/index.ts b/packages/svelte2tsx/src/htmlxtojsx_v2/index.ts index 913cc54bc..bf719b261 100644 --- a/packages/svelte2tsx/src/htmlxtojsx_v2/index.ts +++ b/packages/svelte2tsx/src/htmlxtojsx_v2/index.ts @@ -28,8 +28,40 @@ import { handleText } from './nodes/Text'; import { handleTransitionDirective } from './nodes/Transition'; import { handleImplicitChildren, handleSnippet, hoistSnippetBlock } from './nodes/SnippetBlock'; import { handleRenderTag } from './nodes/RenderTag'; +import { ComponentDocumentation } from '../svelte2tsx/nodes/ComponentDocumentation'; +import { ScopeStack } from '../svelte2tsx/utils/Scope'; +import { Stores } from '../svelte2tsx/nodes/Stores'; +import { Scripts } from '../svelte2tsx/nodes/Scripts'; +import { Node } from 'estree'; +import { SlotHandler } from '../svelte2tsx/nodes/slot'; +import TemplateScope from '../svelte2tsx/nodes/TemplateScope'; +import { + handleScopeAndResolveForSlot, + handleScopeAndResolveLetVarForSlot +} from '../svelte2tsx/nodes/handleScopeAndResolveForSlot'; +import { EventHandler } from '../svelte2tsx/nodes/event-handler'; +import { ComponentEvents } from '../svelte2tsx/nodes/ComponentEvents'; -type Walker = (node: TemplateNode, parent: BaseNode, prop: string, index: number) => void; +export interface TemplateProcessResult { + /** + * The HTML part of the Svelte AST. + */ + htmlAst: TemplateNode; + uses$$props: boolean; + uses$$restProps: boolean; + uses$$slots: boolean; + slots: Map>; + scriptTag: BaseNode; + moduleScriptTag: BaseNode; + /** Start/end positions of snippets that should be moved to the instance script or possibly even module script */ + rootSnippets: Array<[number, number]>; + /** To be added later as a comment on the default class export */ + componentDocumentation: ComponentDocumentation; + events: ComponentEvents; + resolvedStores: string[]; + usesAccessors: boolean; + isRunes: boolean; +} function stripDoctype(str: MagicString): void { const regex = /(\n)?/i; @@ -46,18 +78,19 @@ function stripDoctype(str: MagicString): void { export function convertHtmlxToJsx( str: MagicString, ast: TemplateNode, - onWalk: Walker = null, - onLeave: Walker = null, + tags: BaseNode[], options: { - svelte5Plus: boolean; - preserveAttributeCase?: boolean; + emitOnTemplateError?: boolean; + namespace?: string; + accessors?: boolean; + mode?: 'ts' | 'dts'; typingsNamespace?: string; + svelte5Plus: boolean; } = { svelte5Plus: false } -) { - const htmlx = str.original; - options = { preserveAttributeCase: false, ...options }; +): TemplateProcessResult { options.typingsNamespace = options.typingsNamespace || 'svelteHTML'; - htmlx; + const preserveAttributeCase = options.namespace === 'foreign'; + stripDoctype(str); const rootSnippets: Array<[number, number]> = []; @@ -65,17 +98,131 @@ export function convertHtmlxToJsx( const pendingSnippetHoistCheck = new Set(); + let uses$$props = false; + let uses$$restProps = false; + let uses$$slots = false; + let usesAccessors = !!options.accessors; + let isRunes = false; + + const componentDocumentation = new ComponentDocumentation(); + + //track if we are in a declaration scope + const isDeclaration = { value: false }; + + //track $store variables since we are only supposed to give top level scopes special treatment, and users can declare $blah variables at higher scopes + //which prevents us just changing all instances of Identity that start with $ + + const scopeStack = new ScopeStack(); + const stores = new Stores(scopeStack, isDeclaration); + const scripts = new Scripts(ast); + + const handleSvelteOptions = (node: Node) => { + for (let i = 0; i < node.attributes.length; i++) { + const optionName = node.attributes[i].name; + const optionValue = node.attributes[i].value; + + switch (optionName) { + case 'accessors': + if (Array.isArray(optionValue)) { + if (optionValue[0].type === 'MustacheTag') { + usesAccessors = optionValue[0].expression.value; + } + } else { + usesAccessors = true; + } + break; + case 'runes': + isRunes = true; + break; + } + } + }; + + const handleIdentifier = (node: Node) => { + if (node.name === '$$props') { + uses$$props = true; + return; + } + if (node.name === '$$restProps') { + uses$$restProps = true; + return; + } + + if (node.name === '$$slots') { + uses$$slots = true; + return; + } + }; + + const handleStyleTag = (node: Node) => { + str.remove(node.start, node.end); + }; + + const slotHandler = new SlotHandler(str.original); + let templateScope = new TemplateScope(); + + const handleComponentLet = (component: Node) => { + templateScope = templateScope.child(); + const lets = slotHandler.getSlotConsumerOfComponent(component); + + for (const { letNode, slotName } of lets) { + handleScopeAndResolveLetVarForSlot({ + letNode, + slotName, + slotHandler, + templateScope, + component + }); + } + }; + + const handleScopeAndResolveForSlotInner = ( + identifierDef: Node, + initExpression: Node, + owner: Node + ) => { + handleScopeAndResolveForSlot({ + identifierDef, + initExpression, + slotHandler, + templateScope, + owner + }); + }; + + const eventHandler = new EventHandler(); + walk(ast as any, { - enter: (estreeTypedNode, estreeTypedParent, prop: string, index: number) => { + enter: (estreeTypedNode, estreeTypedParent, prop: string) => { const node = estreeTypedNode as TemplateNode; const parent = estreeTypedParent as BaseNode; + if ( + prop == 'params' && + (parent.type == 'FunctionDeclaration' || parent.type == 'ArrowFunctionExpression') + ) { + isDeclaration.value = true; + } + if (prop == 'id' && parent.type == 'VariableDeclarator') { + isDeclaration.value = true; + } + try { switch (node.type) { + case 'Identifier': + handleIdentifier(node); + stores.handleIdentifier(node, parent, prop); + eventHandler.handleIdentifier(node, parent, prop); + break; case 'IfBlock': handleIf(str, node); break; case 'EachBlock': + templateScope = templateScope.child(); + + if (node.context) { + handleScopeAndResolveForSlotInner(node.context, node.expression, node); + } handleEach(str, node); break; case 'ElseBlock': @@ -84,7 +231,13 @@ export function convertHtmlxToJsx( case 'KeyBlock': handleKey(str, node); break; + case 'BlockStatement': + case 'FunctionDeclaration': + case 'ArrowFunctionExpression': + scopeStack.push(); + break; case 'SnippetBlock': + scopeStack.push(); handleSnippet( str, node, @@ -96,7 +249,7 @@ export function convertHtmlxToJsx( : undefined ); if (parent === ast) { - // root snippet -> move to instance script + // root snippet -> move to instance script or possibly even module script rootSnippets.push([node.start, node.end]); } else { pendingSnippetHoistCheck.add(parent); @@ -106,6 +259,7 @@ export function convertHtmlxToJsx( handleMustacheTag(str, node, parent); break; case 'RawMustacheTag': + scripts.checkIfContainsScriptTag(node); handleRawHtml(str, node); break; case 'DebugTag': @@ -127,6 +281,7 @@ export function convertHtmlxToJsx( if (options.svelte5Plus) { handleImplicitChildren(node, element as InlineComponent); } + handleComponentLet(node); break; case 'Element': case 'Options': @@ -139,6 +294,14 @@ export function convertHtmlxToJsx( case 'SvelteBoundary': case 'Slot': case 'SlotTemplate': + if (node.type === 'Element') { + scripts.checkIfElementIsScriptTag(node, parent); + } else if (node.type === 'Options') { + handleSvelteOptions(node); + } else if (node.type === 'Slot') { + slotHandler.handleSlot(node, templateScope); + } + if (node.name !== '!DOCTYPE') { if (element) { element.child = new Element( @@ -154,6 +317,7 @@ export function convertHtmlxToJsx( } break; case 'Comment': + componentDocumentation.handleComment(node); handleComment(str, node); break; case 'Binding': @@ -173,12 +337,15 @@ export function convertHtmlxToJsx( handleStyleDirective(str, node as StyleDirective, element as Element); break; case 'Action': + stores.handleDirective(node, str); handleActionDirective(node as BaseDirective, element as Element); break; case 'Transition': + stores.handleDirective(node, str); handleTransitionDirective(str, node as BaseDirective, element as Element); break; case 'Animation': + stores.handleDirective(node, str); handleAnimateDirective(str, node as BaseDirective, element as Element); break; case 'Attribute': @@ -186,7 +353,7 @@ export function convertHtmlxToJsx( str, node as Attribute, parent, - options.preserveAttributeCase, + preserveAttributeCase, options.svelte5Plus, element ); @@ -195,6 +362,7 @@ export function convertHtmlxToJsx( handleSpread(node, element); break; case 'EventHandler': + eventHandler.handleEventHandler(node, parent); handleEventHandler(str, node as BaseDirective, element); break; case 'Let': @@ -202,7 +370,7 @@ export function convertHtmlxToJsx( str, node, parent, - options.preserveAttributeCase, + preserveAttributeCase, options.svelte5Plus, element ); @@ -210,9 +378,29 @@ export function convertHtmlxToJsx( case 'Text': handleText(str, node as Text, parent); break; - } - if (onWalk) { - onWalk(node, parent, prop, index); + case 'Style': + handleStyleTag(node); + break; + case 'VariableDeclarator': + isDeclaration.value = true; + break; + case 'AwaitBlock': + templateScope = templateScope.child(); + if (node.value) { + handleScopeAndResolveForSlotInner( + node.value, + node.expression, + node.then + ); + } + if (node.error) { + handleScopeAndResolveForSlotInner( + node.error, + node.expression, + node.catch + ); + } + break; } } catch (e) { console.error('Error walking node ', node, e); @@ -220,17 +408,37 @@ export function convertHtmlxToJsx( } }, - leave: (estreeTypedNode, estreeTypedParent, prop: string, index: number) => { + leave: (estreeTypedNode, estreeTypedParent, prop: string) => { const node = estreeTypedNode as TemplateNode; const parent = estreeTypedParent as BaseNode; + if ( + prop == 'params' && + (parent.type == 'FunctionDeclaration' || parent.type == 'ArrowFunctionExpression') + ) { + isDeclaration.value = false; + } + + if (prop == 'id' && parent.type == 'VariableDeclarator') { + isDeclaration.value = false; + } + const onTemplateScopeLeave = () => { + templateScope = templateScope.parent; + }; + try { switch (node.type) { - case 'IfBlock': + case 'BlockStatement': + case 'FunctionDeclaration': + case 'ArrowFunctionExpression': + case 'SnippetBlock': + scopeStack.pop(); break; case 'EachBlock': + onTemplateScopeLeave(); break; case 'AwaitBlock': + onTemplateScopeLeave(); handleAwait(str, node); break; case 'InlineComponent': @@ -245,15 +453,15 @@ export function convertHtmlxToJsx( case 'Document': case 'Slot': case 'SlotTemplate': + if (node.type === 'InlineComponent') { + onTemplateScopeLeave(); + } if (node.name !== '!DOCTYPE') { element.performTransformation(); element = element.parent; } break; } - if (onLeave) { - onLeave(node, parent, prop, index); - } } catch (e) { console.error('Error leaving node ', node); throw e; @@ -261,11 +469,39 @@ export function convertHtmlxToJsx( } }); + // hoist inner snippets to top of containing element for (const node of pendingSnippetHoistCheck) { hoistSnippetBlock(str, node); } - return rootSnippets; + // resolve scripts + const { scriptTag, moduleScriptTag } = scripts.getTopLevelScriptTags(); + if (options.mode !== 'ts') { + scripts.blankOtherScriptTags(str); + } + + //resolve stores + const resolvedStores = stores.getStoreNames(); + + return { + htmlAst: ast, + moduleScriptTag, + scriptTag, + rootSnippets, + slots: slotHandler.getSlotDef(), + events: new ComponentEvents( + eventHandler, + tags.some((tag) => tag.attributes?.some((a) => a.name === 'strictEvents')), + str + ), + uses$$props, + uses$$restProps, + uses$$slots, + componentDocumentation, + resolvedStores, + usesAccessors, + isRunes + }; } /** @@ -281,10 +517,13 @@ export function htmlx2jsx( svelte5Plus: boolean; } ) { - const ast = parseHtmlx(htmlx, parse, { ...options }).htmlxAst; + const { htmlxAst, tags } = parseHtmlx(htmlx, parse, { ...options }); const str = new MagicString(htmlx); - convertHtmlxToJsx(str, ast, null, null, options); + convertHtmlxToJsx(str, htmlxAst, tags, { + ...options, + namespace: options?.preserveAttributeCase ? 'foreign' : undefined + }); return { map: str.generateMap({ hires: true }), diff --git a/packages/svelte2tsx/src/svelte2tsx/index.ts b/packages/svelte2tsx/src/svelte2tsx/index.ts index 2daf71419..06f343ac4 100644 --- a/packages/svelte2tsx/src/svelte2tsx/index.ts +++ b/packages/svelte2tsx/src/svelte2tsx/index.ts @@ -1,51 +1,15 @@ -import { Node } from 'estree-walker'; import MagicString from 'magic-string'; -import { convertHtmlxToJsx } from '../htmlxtojsx_v2'; +import { convertHtmlxToJsx, TemplateProcessResult } from '../htmlxtojsx_v2'; import { parseHtmlx } from '../utils/htmlxparser'; -import { ComponentDocumentation } from './nodes/ComponentDocumentation'; -import { ComponentEvents } from './nodes/ComponentEvents'; -import { EventHandler } from './nodes/event-handler'; +import { addComponentExport } from './addComponentExport'; +import { createRenderFunction } from './createRenderFunction'; import { ExportedNames } from './nodes/ExportedNames'; -import { - handleScopeAndResolveForSlot, - handleScopeAndResolveLetVarForSlot -} from './nodes/handleScopeAndResolveForSlot'; +import { Generics } from './nodes/Generics'; import { ImplicitStoreValues } from './nodes/ImplicitStoreValues'; -import { Scripts } from './nodes/Scripts'; -import { SlotHandler } from './nodes/slot'; -import { Stores } from './nodes/Stores'; -import TemplateScope from './nodes/TemplateScope'; import { processInstanceScriptContent } from './processInstanceScriptContent'; import { createModuleAst, ModuleAst, processModuleScriptTag } from './processModuleScriptTag'; -import { ScopeStack } from './utils/Scope'; -import { Generics } from './nodes/Generics'; -import { addComponentExport } from './addComponentExport'; -import { createRenderFunction } from './createRenderFunction'; -// @ts-ignore -import { TemplateNode } from 'svelte/types/compiler/interfaces'; import path from 'path'; -import { VERSION, parse } from 'svelte/compiler'; - -type TemplateProcessResult = { - /** - * The HTML part of the Svelte AST. - */ - htmlAst: TemplateNode; - uses$$props: boolean; - uses$$restProps: boolean; - uses$$slots: boolean; - slots: Map>; - scriptTag: Node; - moduleScriptTag: Node; - /** Start/end positions of snippets that should be moved to the instance script */ - rootSnippets: Array<[number, number]>; - /** To be added later as a comment on the default class export */ - componentDocumentation: ComponentDocumentation; - events: ComponentEvents; - resolvedStores: string[]; - usesAccessors: boolean; - isRunes: boolean; -}; +import { parse, VERSION } from 'svelte/compiler'; function processSvelteTemplate( str: MagicString, @@ -60,257 +24,7 @@ function processSvelteTemplate( } ): TemplateProcessResult { const { htmlxAst, tags } = parseHtmlx(str.original, parse, options); - - let uses$$props = false; - let uses$$restProps = false; - let uses$$slots = false; - let usesAccessors = !!options.accessors; - let isRunes = false; - - const componentDocumentation = new ComponentDocumentation(); - - //track if we are in a declaration scope - const isDeclaration = { value: false }; - - //track $store variables since we are only supposed to give top level scopes special treatment, and users can declare $blah variables at higher scopes - //which prevents us just changing all instances of Identity that start with $ - - const scopeStack = new ScopeStack(); - const stores = new Stores(scopeStack, isDeclaration); - const scripts = new Scripts(htmlxAst); - - const handleSvelteOptions = (node: Node) => { - for (let i = 0; i < node.attributes.length; i++) { - const optionName = node.attributes[i].name; - const optionValue = node.attributes[i].value; - - switch (optionName) { - case 'accessors': - if (Array.isArray(optionValue)) { - if (optionValue[0].type === 'MustacheTag') { - usesAccessors = optionValue[0].expression.value; - } - } else { - usesAccessors = true; - } - break; - case 'runes': - isRunes = true; - break; - } - } - }; - - const handleIdentifier = (node: Node) => { - if (node.name === '$$props') { - uses$$props = true; - return; - } - if (node.name === '$$restProps') { - uses$$restProps = true; - return; - } - - if (node.name === '$$slots') { - uses$$slots = true; - return; - } - }; - - const handleStyleTag = (node: Node) => { - str.remove(node.start, node.end); - }; - - const slotHandler = new SlotHandler(str.original); - let templateScope = new TemplateScope(); - - const handleEach = (node: Node) => { - templateScope = templateScope.child(); - - if (node.context) { - handleScopeAndResolveForSlotInner(node.context, node.expression, node); - } - }; - - const handleAwait = (node: Node) => { - templateScope = templateScope.child(); - if (node.value) { - handleScopeAndResolveForSlotInner(node.value, node.expression, node.then); - } - if (node.error) { - handleScopeAndResolveForSlotInner(node.error, node.expression, node.catch); - } - }; - - const handleComponentLet = (component: Node) => { - templateScope = templateScope.child(); - const lets = slotHandler.getSlotConsumerOfComponent(component); - - for (const { letNode, slotName } of lets) { - handleScopeAndResolveLetVarForSlot({ - letNode, - slotName, - slotHandler, - templateScope, - component - }); - } - }; - - const handleScopeAndResolveForSlotInner = ( - identifierDef: Node, - initExpression: Node, - owner: Node - ) => { - handleScopeAndResolveForSlot({ - identifierDef, - initExpression, - slotHandler, - templateScope, - owner - }); - }; - - const eventHandler = new EventHandler(); - - const onHtmlxWalk = (node: Node, parent: Node, prop: string) => { - if ( - prop == 'params' && - (parent.type == 'FunctionDeclaration' || parent.type == 'ArrowFunctionExpression') - ) { - isDeclaration.value = true; - } - if (prop == 'id' && parent.type == 'VariableDeclarator') { - isDeclaration.value = true; - } - - switch (node.type) { - case 'Comment': - componentDocumentation.handleComment(node); - break; - case 'Options': - handleSvelteOptions(node); - break; - case 'Identifier': - handleIdentifier(node); - stores.handleIdentifier(node, parent, prop); - eventHandler.handleIdentifier(node, parent, prop); - break; - case 'Transition': - case 'Action': - case 'Animation': - stores.handleDirective(node, str); - break; - case 'Slot': - slotHandler.handleSlot(node, templateScope); - break; - case 'Style': - handleStyleTag(node); - break; - case 'Element': - scripts.checkIfElementIsScriptTag(node, parent); - break; - case 'RawMustacheTag': - scripts.checkIfContainsScriptTag(node); - break; - case 'BlockStatement': - scopeStack.push(); - break; - case 'FunctionDeclaration': - scopeStack.push(); - break; - case 'ArrowFunctionExpression': - scopeStack.push(); - break; - case 'EventHandler': - eventHandler.handleEventHandler(node, parent); - break; - case 'VariableDeclarator': - isDeclaration.value = true; - break; - case 'EachBlock': - handleEach(node); - break; - case 'AwaitBlock': - handleAwait(node); - break; - case 'InlineComponent': - handleComponentLet(node); - break; - } - }; - - const onHtmlxLeave = (node: Node, parent: Node, prop: string, _index: number) => { - if ( - prop == 'params' && - (parent.type == 'FunctionDeclaration' || parent.type == 'ArrowFunctionExpression') - ) { - isDeclaration.value = false; - } - - if (prop == 'id' && parent.type == 'VariableDeclarator') { - isDeclaration.value = false; - } - const onTemplateScopeLeave = () => { - templateScope = templateScope.parent; - }; - - switch (node.type) { - case 'BlockStatement': - scopeStack.pop(); - break; - case 'FunctionDeclaration': - scopeStack.pop(); - break; - case 'ArrowFunctionExpression': - scopeStack.pop(); - break; - case 'EachBlock': - onTemplateScopeLeave(); - break; - case 'AwaitBlock': - onTemplateScopeLeave(); - break; - case 'InlineComponent': - onTemplateScopeLeave(); - break; - } - }; - - const rootSnippets = convertHtmlxToJsx(str, htmlxAst, onHtmlxWalk, onHtmlxLeave, { - preserveAttributeCase: options?.namespace == 'foreign', - typingsNamespace: options.typingsNamespace, - svelte5Plus: options.svelte5Plus - }); - - // resolve scripts - const { scriptTag, moduleScriptTag } = scripts.getTopLevelScriptTags(); - if (options.mode !== 'ts') { - scripts.blankOtherScriptTags(str); - } - - //resolve stores - const resolvedStores = stores.getStoreNames(); - - return { - htmlAst: htmlxAst, - moduleScriptTag, - scriptTag, - rootSnippets, - slots: slotHandler.getSlotDef(), - events: new ComponentEvents( - eventHandler, - tags.some((tag) => tag.attributes?.some((a) => a.name === 'strictEvents')), - str - ), - uses$$props, - uses$$restProps, - uses$$slots, - componentDocumentation, - resolvedStores, - usesAccessors, - isRunes - }; + return convertHtmlxToJsx(str, htmlxAst, tags, options); } export function svelte2tsx( From fb8e9228025ab8ddeee2f8521a0a538f94828b41 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Thu, 21 Nov 2024 11:25:35 +0100 Subject: [PATCH 2/2] fix --- packages/svelte2tsx/src/htmlxtojsx_v2/index.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/svelte2tsx/src/htmlxtojsx_v2/index.ts b/packages/svelte2tsx/src/htmlxtojsx_v2/index.ts index bf719b261..acc2f9c82 100644 --- a/packages/svelte2tsx/src/htmlxtojsx_v2/index.ts +++ b/packages/svelte2tsx/src/htmlxtojsx_v2/index.ts @@ -32,7 +32,6 @@ import { ComponentDocumentation } from '../svelte2tsx/nodes/ComponentDocumentati import { ScopeStack } from '../svelte2tsx/utils/Scope'; import { Stores } from '../svelte2tsx/nodes/Stores'; import { Scripts } from '../svelte2tsx/nodes/Scripts'; -import { Node } from 'estree'; import { SlotHandler } from '../svelte2tsx/nodes/slot'; import TemplateScope from '../svelte2tsx/nodes/TemplateScope'; import { @@ -116,7 +115,7 @@ export function convertHtmlxToJsx( const stores = new Stores(scopeStack, isDeclaration); const scripts = new Scripts(ast); - const handleSvelteOptions = (node: Node) => { + const handleSvelteOptions = (node: BaseNode) => { for (let i = 0; i < node.attributes.length; i++) { const optionName = node.attributes[i].name; const optionValue = node.attributes[i].value; @@ -138,7 +137,7 @@ export function convertHtmlxToJsx( } }; - const handleIdentifier = (node: Node) => { + const handleIdentifier = (node: BaseNode) => { if (node.name === '$$props') { uses$$props = true; return; @@ -154,14 +153,14 @@ export function convertHtmlxToJsx( } }; - const handleStyleTag = (node: Node) => { + const handleStyleTag = (node: BaseNode) => { str.remove(node.start, node.end); }; const slotHandler = new SlotHandler(str.original); let templateScope = new TemplateScope(); - const handleComponentLet = (component: Node) => { + const handleComponentLet = (component: BaseNode) => { templateScope = templateScope.child(); const lets = slotHandler.getSlotConsumerOfComponent(component); @@ -177,9 +176,9 @@ export function convertHtmlxToJsx( }; const handleScopeAndResolveForSlotInner = ( - identifierDef: Node, - initExpression: Node, - owner: Node + identifierDef: BaseNode, + initExpression: BaseNode, + owner: BaseNode ) => { handleScopeAndResolveForSlot({ identifierDef,