Repository: sveltejs/svelte
File: packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js (JavaScript)

Code before:

	const loc = locator(/** @type {number} */ (left.start));

	return b.call(
		'$$ownership_validator.mutation',
		b.literal(binding.prop_alias),
		b.array(path),
		expression,
		loc && b.literal(loc.line),
		loc && b.literal(loc.column)
	);
}

/**
 *
 * @param {ComponentContext} context
 * @param {Expression} expression
 * @param {ExpressionMetadata} metadata
 */
export function build_expression(context, expression, metadata, state = context.state) {
	const value = /** @type {Expression} */ (context.visit(expression, state));

	if (context.state.analysis.runes || context.state.analysis.maybe_runes) {
		return value;
	}

	if (!metadata.has_call && !metadata.has_member_expression && !metadata.has_assignment) {
		return value;
	}

	// Legacy reactivity is coarse-grained, looking at the statically visible dependencies. Replicate that here
	const sequence = b.sequence([]);

	for (const binding of metadata.references) {
		if (binding.kind === 'normal' && binding.declaration_kind !== 'import') {
			continue;
		}

		var getter = build_getter({ ...binding.node }, state);

		if (
			binding.kind === 'bindable_prop' ||
			binding.kind === 'template' ||
			binding.declaration_kind === 'import' ||
			binding.node.name === '$$props' ||
			binding.node.name === '$$restProps'
		) {
			getter = b.call('$.deep_read_state', getter);
		}

		sequence.expressions.push(getter);

Review comment (suggestion):
```suggestion
	// Components not explicitly in legacy mode might be expected to be in runes mode (especially since we didn't
	// adjust this behavior until recently, which broke people's existing components), so we also bail in this case.
	// Kind of an in-between-mode.
	if (context.state.analysis.runes || context.state.analysis.maybe_runes) {
```

Code after:

	const loc = locator(/** @type {number} */ (left.start));

	return b.call(
		'$$ownership_validator.mutation',
		b.literal(binding.prop_alias),
		b.array(path),
		expression,
		loc && b.literal(loc.line),
		loc && b.literal(loc.column)
	);
}

/**
 *
 * @param {ComponentContext} context
 * @param {Expression} expression
 * @param {ExpressionMetadata} metadata
 */
export function build_expression(context, expression, metadata, state = context.state) {
	const value = /** @type {Expression} */ (context.visit(expression, state));

	// Components not explicitly in legacy mode might be expected to be in runes mode (especially since we didn't
	// adjust this behavior until recently, which broke people's existing components), so we also bail in this case.
	// Kind of an in-between-mode.
	if (context.state.analysis.runes || context.state.analysis.maybe_runes) {
		return value;
	}

	if (!metadata.has_call && !metadata.has_member_expression && !metadata.has_assignment) {
		return value;
	}

	// Legacy reactivity is coarse-grained, looking at the statically visible dependencies. Replicate that here
	const sequence = b.sequence([]);

	for (const binding of metadata.references) {
		if (binding.kind === 'normal' && binding.declaration_kind !== 'import') {
			continue;
		}

		var getter = build_getter({ ...binding.node }, state);

		if (
			binding.kind === 'bindable_prop' ||
			binding.kind === 'template' ||
			binding.declaration_kind === 'import' ||
			binding.node.name === '$$props' ||
			binding.node.name === '$$restProps'
		) {
			getter = b.call('$.deep_read_state', getter);