All files / src/compiler/phases/3-transform/server/visitors AssignmentExpression.js

97.18% Statements 69/71
92.85% Branches 13/14
100% Functions 3/3
97.05% Lines 66/68

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 62 63 64 65 66 67 68 692x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 1117x 1117x 2x 2x 2x 2x 2x 2x 2x 2x 2x 1169x 1169x 1169x 1169x 343x 343x 343x 1169x 1169x 1119x 1119x 50x 50x 50x 1138x     50x 1138x 40x 40x 40x 40x 40x 40x 10x 10x 10x 10x 10x 10x 10x 10x 10x 10x 10x 10x 10x 2x 2x 2x 2x 1113x 1113x 1113x  
/** @import { AssignmentExpression, AssignmentOperator, Expression, Pattern } from 'estree' */
/** @import { SvelteNode } from '#compiler' */
/** @import { Context, ServerTransformState } from '../types.js' */
import * as b from '../../../../utils/builders.js';
import { build_assignment_value } from '../../../../utils/ast.js';
import { visit_assignment_expression } from '../../shared/assignments.js';
 
/**
 * @param {AssignmentExpression} node
 * @param {Context} context
 */
export function AssignmentExpression(node, context) {
	return visit_assignment_expression(node, context, build_assignment) ?? context.next();
}
 
/**
 * Only returns an expression if this is not a `$store` assignment, as others can be kept as-is
 * @param {AssignmentOperator} operator
 * @param {Pattern} left
 * @param {Expression} right
 * @param {import('zimmerframe').Context<SvelteNode, ServerTransformState>} context
 * @returns {Expression | null}
 */
function build_assignment(operator, left, right, context) {
	let object = left;
 
	while (object.type === 'MemberExpression') {
		// @ts-expect-error
		object = object.object;
	}
 
	if (object.type !== 'Identifier' || !is_store_name(object.name)) {
		return null;
	}
 
	const name = object.name.slice(1);
 
	if (!context.state.scope.get(name)) {
		return null;
	}
 
	if (object === left) {
		let value = /** @type {Expression} */ (
			context.visit(build_assignment_value(operator, left, right))
		);
 
		return b.call('$.store_set', b.id(name), value);
	}
 
	return b.call(
		'$.store_mutate',
		b.assignment('??=', b.id('$$store_subs'), b.object([])),
		b.literal(object.name),
		b.id(name),
		b.assignment(
			operator,
			/** @type {Pattern} */ (context.visit(left)),
			/** @type {Expression} */ (context.visit(right))
		)
	);
}
 
/**
 * @param {string} name
 */
function is_store_name(name) {
	return name[0] === '$' && /[A-Za-z_]/.test(name[1]);
}