All files / src/compiler/phases/2-analyze/visitors ExportNamedDeclaration.js

100% Statements 63/63
95.83% Branches 23/24
100% Functions 1/1
100% Lines 61/61

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 622x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 3867x 3867x 3867x 3867x 3638x 3638x 3638x 3638x 9x 3638x 1x 1x 3637x 3637x 4133x 4197x 4197x 4197x 4197x 1x 1x 4196x 4197x 3x 3x 4197x 4129x 3633x 3862x 3862x 75x 20x 20x 10x 20x 12x 12x 12x 12x 20x 8x 8x 8x 8x 8x 8x 20x 75x 3867x  
/** @import { ExportNamedDeclaration, Identifier, Node } from 'estree' */
/** @import { Binding } from '#compiler' */
/** @import { Context } from '../types' */
/** @import { Scope } from '../../scope' */
import * as e from '../../../errors.js';
import { extract_identifiers } from '../../../utils/ast.js';
 
/**
 * @param {ExportNamedDeclaration} node
 * @param {Context} context
 */
export function ExportNamedDeclaration(node, context) {
	// visit children, so bindings are correctly initialised
	context.next();
 
	if (node.declaration?.type === 'VariableDeclaration') {
		// in runes mode, forbid `export let`
		if (
			context.state.analysis.runes &&
			context.state.ast_type === 'instance' &&
			node.declaration.kind === 'let'
		) {
			e.legacy_export_invalid(node);
		}
 
		for (const declarator of node.declaration.declarations) {
			for (const id of extract_identifiers(declarator.id)) {
				const binding = context.state.scope.get(id.name);
				if (!binding) continue;
 
				if (binding.kind === 'derived') {
					e.derived_invalid_export(node);
				}
 
				if ((binding.kind === 'state' || binding.kind === 'raw_state') && binding.reassigned) {
					e.state_invalid_export(node);
				}
			}
		}
	}
 
	if (context.state.analysis.runes) {
		if (node.declaration && context.state.ast_type === 'instance') {
			if (
				node.declaration.type === 'FunctionDeclaration' ||
				node.declaration.type === 'ClassDeclaration'
			) {
				context.state.analysis.exports.push({
					name: /** @type {Identifier} */ (node.declaration.id).name,
					alias: null
				});
			} else if (node.declaration.kind === 'const') {
				for (const declarator of node.declaration.declarations) {
					for (const node of extract_identifiers(declarator.id)) {
						context.state.analysis.exports.push({ name: node.name, alias: null });
					}
				}
			}
		}
	}
}