|  |  | @ -1,4 +1,4 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | /** @import { Expression, Identifier, ImportDeclaration, MemberExpression, Program, Statement } from 'estree' */ |  |  |  | /** @import { ClassDeclaration, Expression, FunctionDeclaration, Identifier, ImportDeclaration, MemberExpression, Program, Statement, VariableDeclarator } from 'estree' */ | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | /** @import { ComponentContext } from '../types' */ |  |  |  | /** @import { ComponentContext } from '../types' */ | 
			
		
	
		
		
			
				
					
					|  |  |  | import { build_getter, is_prop_source } from '../utils.js'; |  |  |  | import { build_getter, is_prop_source } from '../utils.js'; | 
			
		
	
		
		
			
				
					
					|  |  |  | import * as b from '#compiler/builders'; |  |  |  | import * as b from '#compiler/builders'; | 
			
		
	
	
		
		
			
				
					|  |  | @ -160,52 +160,10 @@ function transform_body(program, context) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	/** @type {Identifier | null} */ |  |  |  | 	/** @type {Identifier | null} */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 	let last = null; |  |  |  | 	let last = null; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	for (let node of program.body) { |  |  |  | 	/** | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		if (node.type === 'ImportDeclaration') { |  |  |  | 	 * @param {Statement | VariableDeclarator | FunctionDeclaration | ClassDeclaration} node | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			// TODO we can get rid of the visitor
 |  |  |  | 	 */ | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			context.state.hoisted.push(node); |  |  |  | 	const push = (node) => { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			continue; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if (node.type === 'ExportDefaultDeclaration' || node.type === 'ExportAllDeclaration') { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			// this can't happen, but it's useful for TypeScript to understand that
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			continue; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if (node.type === 'ExportNamedDeclaration') { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			if (node.declaration) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				// TODO ditto — no visitor needed
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				node = node.declaration; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} else { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				continue; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if (node.type === 'VariableDeclaration') { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			for (const declarator of node.declarations) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				const awaited = awaited_statements.get(declarator); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				if (awaited) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 					// TODO dependencies
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 					out.push( |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 						b.var( |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 							awaited.id, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 							b.call( |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 								'$.run', |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 								b.array([]), |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 								b.arrow([], declarator.init ?? b.block([]), awaited.has_await) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 							) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 						) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 					); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 					last = awaited.id; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				} else { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 					out.push(b.var(declarator.id, declarator.init)); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} else if (node.type === 'ClassDeclaration' || node.type === 'FunctionDeclaration') { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			// TODO
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} else { |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 		const awaited = awaited_statements.get(node); |  |  |  | 		const awaited = awaited_statements.get(node); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if (awaited) { |  |  |  | 		if (awaited) { | 
			
		
	
	
		
		
			
				
					|  |  | @ -214,7 +172,7 @@ function transform_body(program, context) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 			for (const binding of awaited.metadata.dependencies) { |  |  |  | 			for (const binding of awaited.metadata.dependencies) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 				const dep = awaited_declarations.get(binding.node.name); |  |  |  | 				const dep = awaited_declarations.get(binding.node.name); | 
			
		
	
		
		
			
				
					
					|  |  |  | 					if (dep && !ids.has(dep.id)) { |  |  |  | 				if (dep && dep.id !== awaited.id && !ids.has(dep.id)) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 					ids.add(dep.id); |  |  |  | 					ids.add(dep.id); | 
			
		
	
		
		
			
				
					
					|  |  |  | 					patterns.add(dep.pattern); |  |  |  | 					patterns.add(dep.pattern); | 
			
		
	
		
		
			
				
					
					|  |  |  | 				} |  |  |  | 				} | 
			
		
	
	
		
		
			
				
					|  |  | @ -224,26 +182,58 @@ function transform_body(program, context) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 				ids.add(last); |  |  |  | 				ids.add(last); | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  | 			} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 				// TODO dependencies
 |  |  |  | 			const rhs = | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				node.type === 'VariableDeclarator' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 					? node.init ?? b.block([]) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 					: node.type === 'ExpressionStatement' | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 						? node.expression | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 						: b.block([node]); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 			out.push( |  |  |  | 			out.push( | 
			
		
	
		
		
			
				
					
					|  |  |  | 				b.var( |  |  |  | 				b.var( | 
			
		
	
		
		
			
				
					
					|  |  |  | 					awaited.id, |  |  |  | 					awaited.id, | 
			
		
	
		
		
			
				
					
					|  |  |  | 						b.call( |  |  |  | 					b.call('$.run', b.array([...ids]), b.arrow([...patterns], rhs, awaited.has_await)) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 							'$.run', |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 							b.array([...ids]), |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 							b.arrow( |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 								[...patterns], |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 								node.type === 'ExpressionStatement' ? node.expression : b.block([node]), |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 								awaited.has_await |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 							) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 						) |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 				) |  |  |  | 				) | 
			
		
	
		
		
			
				
					
					|  |  |  | 			); |  |  |  | 			); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 			last = awaited.id; |  |  |  | 			last = awaited.id; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} else if (node.type === 'VariableDeclarator') { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			out.push(b.var(node.id, node.init)); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} else { |  |  |  | 		} else { | 
			
		
	
		
		
			
				
					
					|  |  |  | 			out.push(node); |  |  |  | 			out.push(node); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	}; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	for (let node of program.body) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if (node.type === 'ImportDeclaration') { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			// TODO we can get rid of the visitor
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			context.state.hoisted.push(node); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			continue; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if (node.type === 'ExportDefaultDeclaration' || node.type === 'ExportAllDeclaration') { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			// this can't happen, but it's useful for TypeScript to understand that
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			continue; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if (node.type === 'ExportNamedDeclaration') { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			if (node.declaration) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				// TODO ditto — no visitor needed
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				node = node.declaration; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			} else { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				continue; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if (node.type === 'VariableDeclaration') { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			for (const declarator of node.declarations) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				push(declarator); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} else if (node.type === 'ClassDeclaration' || node.type === 'FunctionDeclaration') { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			// TODO
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			push(node); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} else { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			push(node); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | 
 |