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

Code before:
			attributes.push(attribute);
		} else if (attribute.type === 'ClassDirective') {
			class_directives.push(attribute);
		} else if (attribute.type === 'StyleDirective') {
			style_directives.push(attribute);
		} else if (attribute.type === 'LetDirective') {
			lets.push(/** @type {ExpressionStatement} */ (context.visit(attribute)));
		} else if (attribute.type === 'OnDirective') {
			const handler = /** @type {Expression} */ (context.visit(attribute, inner_context.state));
			inner_context.state.after_update.push(b.stmt(handler));
		} else {
			context.visit(attribute, inner_context.state);
		}
	}

	// Let bindings first, they can be used on attributes
	context.state.init.push(...lets); // create computeds in the outer context; the dynamic element is the single child of this slot

	// Then do attributes
	let is_attributes_reactive = false;

	if (
		attributes.length === 1 &&
		attributes[0].type === 'Attribute' &&
		attributes[0].name.toLowerCase() === 'class' &&
		attributes[0].value !== true &&
		!Array.isArray(attributes[0].value) &&
		attributes[0].value.metadata.expression.has_call === false
	) {
		// special case when there only a class attribute, without call expression
		let { value, has_state } = build_attribute_value(
			attributes[0].value,
			context,
			(value, metadata) => (metadata.has_call ? get_expression_id(context.state, value) : value)
		);

		is_attributes_reactive = build_set_class(
			node,
			element_id,
			attributes[0],
			value,
			has_state,
			class_directives,
			inner_context,
			false
		);
	} else if (attributes.length) {
		const attributes_id = b.id(context.state.scope.generate('attributes'));

		// Always use spread because we don't know whether the element is a custom element or not,
		// therefore we need to do the "how to set an attribute" logic at runtime.

Review comment (bug):
I might be wrong but there should be a `is_text_attrobute` utility somewhere...can you check if that's the case and use that?

Code after:
			attributes.push(attribute);
		} else if (attribute.type === 'ClassDirective') {
			class_directives.push(attribute);
		} else if (attribute.type === 'StyleDirective') {
			style_directives.push(attribute);
		} else if (attribute.type === 'LetDirective') {
			lets.push(/** @type {ExpressionStatement} */ (context.visit(attribute)));
		} else if (attribute.type === 'OnDirective') {
			const handler = /** @type {Expression} */ (context.visit(attribute, inner_context.state));
			inner_context.state.after_update.push(b.stmt(handler));
		} else {
			context.visit(attribute, inner_context.state);
		}
	}

	// Let bindings first, they can be used on attributes
	context.state.init.push(...lets); // create computeds in the outer context; the dynamic element is the single child of this slot

	// Then do attributes
	let is_attributes_reactive = false;

	if (
		attributes.length === 1 &&
		attributes[0].type === 'Attribute' &&
		attributes[0].name.toLowerCase() === 'class' &&
		is_text_attribute(attributes[0])
	) {
		// special case when there only a class attribute, without call expression
		let { value, has_state } = build_attribute_value(
			attributes[0].value,
			context,
			(value, metadata) => (metadata.has_call ? get_expression_id(context.state, value) : value)
		);

		is_attributes_reactive = build_set_class(
			node,
			element_id,
			attributes[0],
			value,
			has_state,
			class_directives,
			inner_context,
			false
		);
	} else if (attributes.length) {
		const attributes_id = b.id(context.state.scope.generate('attributes'));

		// Always use spread because we don't know whether the element is a custom element or not,
		// therefore we need to do the "how to set an attribute" logic at runtime.
		is_attributes_reactive = build_set_attributes(
			attributes,