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

Code before:
		}
		return false;
	}
}

/**
 * @param {(AST.Text | AST.ExpressionTag)[]} nodes
 * @param {import('../types.js').ComponentClientTransformState} state
 */
function can_inline_all_nodes(nodes, state) {
	let can_inline = true;
	let has_expression_tag = false;
	for (let value of nodes) {
		if (value.type === 'ExpressionTag') {
			if (value.expression.type === 'Identifier') {
				const binding = state.scope
					.owner(value.expression.name)
					?.declarations.get(value.expression.name);
				can_inline &&= can_inline_variable(binding);
			} else {
				can_inline = false;
			}
			has_expression_tag = true;
		}
	}
	return { can_inline, has_expression_tag };
}

/**
 * Like `build_element_attribute_update_assignment` but without any special attribute treatment.
 * @param {Identifier}	node_id
 * @param {AST.Attribute} attribute
 * @param {ComponentContext} context
 * @returns {boolean}
 */
function build_custom_element_attribute_update_assignment(node_id, attribute, context) {
	const state = context.state;
	const name = attribute.name; // don't lowercase, as we set the element's property, which might be case sensitive
	let { has_call, value } = build_attribute_value(attribute.value, context);

	const update = b.stmt(b.call('$.set_custom_element_data', node_id, b.literal(name), value));

	if (attribute.metadata.expression.has_state) {
		if (has_call) {
			state.init.push(build_update(update));
		} else {
			state.update.push(update);
		}
		return true;
	} else {
		state.init.push(update);

Review comment (refactor):
This returns two values, but at the usage site they're used together - can we simplify this? Also, does it make sense to put this function into the `utils.js` file?

Code after:
 * @param {(AST.Text | AST.ExpressionTag)[]} nodes
 * @param {import('../types.js').ComponentClientTransformState} state
 */
function is_inlinable_expression(nodes, state) {
	let has_expression_tag = false;
	for (let value of nodes) {
		if (value.type === 'ExpressionTag') {
			if (value.expression.type === 'Identifier') {
				const binding = state.scope
					.owner(value.expression.name)
					?.declarations.get(value.expression.name);
				if (!can_inline_variable(binding)) {
					return false;
				}
			} else {
				return false;
			}
			has_expression_tag = true;
		}
	}
	return has_expression_tag;
}

/**
 * Like `build_element_attribute_update_assignment` but without any special attribute treatment.
 * @param {Identifier}	node_id
 * @param {AST.Attribute} attribute
 * @param {ComponentContext} context
 * @returns {boolean}
 */
function build_custom_element_attribute_update_assignment(node_id, attribute, context) {
	const state = context.state;
	const name = attribute.name; // don't lowercase, as we set the element's property, which might be case sensitive
	let { has_call, value } = build_attribute_value(attribute.value, context);

	const update = b.stmt(b.call('$.set_custom_element_data', node_id, b.literal(name), value));

	if (attribute.metadata.expression.has_state) {
		if (has_call) {
			state.init.push(build_update(update));
		} else {
			state.update.push(update);
		}
		return true;
	} else {
		state.init.push(update);
		return false;
	}
}

/**