|
|
@ -16,28 +16,30 @@ import { build_template_chunk, get_expression_id } from './utils.js';
|
|
|
|
* @param {ComponentContext} context
|
|
|
|
* @param {ComponentContext} context
|
|
|
|
* @param {AST.RegularElement | AST.SvelteElement} element
|
|
|
|
* @param {AST.RegularElement | AST.SvelteElement} element
|
|
|
|
* @param {Identifier} element_id
|
|
|
|
* @param {Identifier} element_id
|
|
|
|
* @param {Identifier} attributes_id
|
|
|
|
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
export function build_set_attributes(
|
|
|
|
export function build_attribute_effect(
|
|
|
|
attributes,
|
|
|
|
attributes,
|
|
|
|
class_directives,
|
|
|
|
class_directives,
|
|
|
|
style_directives,
|
|
|
|
style_directives,
|
|
|
|
context,
|
|
|
|
context,
|
|
|
|
element,
|
|
|
|
element,
|
|
|
|
element_id,
|
|
|
|
element_id
|
|
|
|
attributes_id
|
|
|
|
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
let is_dynamic = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @type {ObjectExpression['properties']} */
|
|
|
|
/** @type {ObjectExpression['properties']} */
|
|
|
|
const values = [];
|
|
|
|
const values = [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @type {Expression[]} */
|
|
|
|
|
|
|
|
const expressions = [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @param {Expression} value */
|
|
|
|
|
|
|
|
function memoize(value) {
|
|
|
|
|
|
|
|
return b.id(`$${expressions.push(value) - 1}`);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (const attribute of attributes) {
|
|
|
|
for (const attribute of attributes) {
|
|
|
|
if (attribute.type === 'Attribute') {
|
|
|
|
if (attribute.type === 'Attribute') {
|
|
|
|
const { value, has_state } = build_attribute_value(
|
|
|
|
const { value } = build_attribute_value(attribute.value, context, (value, metadata) =>
|
|
|
|
attribute.value,
|
|
|
|
metadata.has_call ? memoize(value) : value
|
|
|
|
context,
|
|
|
|
|
|
|
|
(value, metadata) => (metadata.has_call ? get_expression_id(context.state, value) : value)
|
|
|
|
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
if (
|
|
|
@ -51,16 +53,11 @@ export function build_set_attributes(
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
values.push(b.init(attribute.name, value));
|
|
|
|
values.push(b.init(attribute.name, value));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
is_dynamic ||= has_state;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
// objects could contain reactive getters -> play it safe and always assume spread attributes are reactive
|
|
|
|
|
|
|
|
is_dynamic = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let value = /** @type {Expression} */ (context.visit(attribute));
|
|
|
|
let value = /** @type {Expression} */ (context.visit(attribute));
|
|
|
|
|
|
|
|
|
|
|
|
if (attribute.metadata.expression.has_call) {
|
|
|
|
if (attribute.metadata.expression.has_call) {
|
|
|
|
value = get_expression_id(context.state, value);
|
|
|
|
value = memoize(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
values.push(b.spread(value));
|
|
|
|
values.push(b.spread(value));
|
|
|
@ -72,12 +69,9 @@ export function build_set_attributes(
|
|
|
|
b.prop(
|
|
|
|
b.prop(
|
|
|
|
'init',
|
|
|
|
'init',
|
|
|
|
b.array([b.id('$.CLASS')]),
|
|
|
|
b.array([b.id('$.CLASS')]),
|
|
|
|
build_class_directives_object(class_directives, context)
|
|
|
|
build_class_directives_object(class_directives, expressions, context)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
is_dynamic ||=
|
|
|
|
|
|
|
|
class_directives.find((directive) => directive.metadata.expression.has_state) !== null;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (style_directives.length) {
|
|
|
|
if (style_directives.length) {
|
|
|
@ -85,31 +79,28 @@ export function build_set_attributes(
|
|
|
|
b.prop(
|
|
|
|
b.prop(
|
|
|
|
'init',
|
|
|
|
'init',
|
|
|
|
b.array([b.id('$.STYLE')]),
|
|
|
|
b.array([b.id('$.STYLE')]),
|
|
|
|
build_style_directives_object(style_directives, context)
|
|
|
|
build_style_directives_object(style_directives, expressions, context)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
is_dynamic ||= style_directives.some((directive) => directive.metadata.expression.has_state);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const call = b.call(
|
|
|
|
context.state.init.push(
|
|
|
|
'$.set_attributes',
|
|
|
|
b.stmt(
|
|
|
|
element_id,
|
|
|
|
b.call(
|
|
|
|
is_dynamic ? attributes_id : b.null,
|
|
|
|
'$.attribute_effect',
|
|
|
|
b.object(values),
|
|
|
|
element_id,
|
|
|
|
element.metadata.scoped &&
|
|
|
|
b.arrow(
|
|
|
|
context.state.analysis.css.hash !== '' &&
|
|
|
|
expressions.map((_, i) => b.id(`$${i}`)),
|
|
|
|
b.literal(context.state.analysis.css.hash),
|
|
|
|
b.object(values)
|
|
|
|
is_ignored(element, 'hydration_attribute_changed') && b.true
|
|
|
|
),
|
|
|
|
|
|
|
|
expressions.length > 0 && b.array(expressions.map((expression) => b.thunk(expression))),
|
|
|
|
|
|
|
|
element.metadata.scoped &&
|
|
|
|
|
|
|
|
context.state.analysis.css.hash !== '' &&
|
|
|
|
|
|
|
|
b.literal(context.state.analysis.css.hash),
|
|
|
|
|
|
|
|
is_ignored(element, 'hydration_attribute_changed') && b.true
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
)
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (is_dynamic) {
|
|
|
|
|
|
|
|
context.state.init.push(b.let(attributes_id));
|
|
|
|
|
|
|
|
const update = b.stmt(b.assignment('=', attributes_id, call));
|
|
|
|
|
|
|
|
context.state.update.push(update);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
context.state.init.push(b.stmt(call));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -167,7 +158,7 @@ export function build_set_class(element, node_id, attribute, class_directives, c
|
|
|
|
value = b.call('$.clsx', value);
|
|
|
|
value = b.call('$.clsx', value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return metadata.has_call ? get_expression_id(context.state, value) : value;
|
|
|
|
return metadata.has_call ? get_expression_id(context.state.expressions, value) : value;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
/** @type {Identifier | undefined} */
|
|
|
|
/** @type {Identifier | undefined} */
|
|
|
@ -180,7 +171,7 @@ export function build_set_class(element, node_id, attribute, class_directives, c
|
|
|
|
let next;
|
|
|
|
let next;
|
|
|
|
|
|
|
|
|
|
|
|
if (class_directives.length) {
|
|
|
|
if (class_directives.length) {
|
|
|
|
next = build_class_directives_object(class_directives, context);
|
|
|
|
next = build_class_directives_object(class_directives, context.state.expressions, context);
|
|
|
|
has_state ||= class_directives.some((d) => d.metadata.expression.has_state);
|
|
|
|
has_state ||= class_directives.some((d) => d.metadata.expression.has_state);
|
|
|
|
|
|
|
|
|
|
|
|
if (has_state) {
|
|
|
|
if (has_state) {
|
|
|
@ -235,7 +226,7 @@ export function build_set_class(element, node_id, attribute, class_directives, c
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
export function build_set_style(node_id, attribute, style_directives, context) {
|
|
|
|
export function build_set_style(node_id, attribute, style_directives, context) {
|
|
|
|
let { value, has_state } = build_attribute_value(attribute.value, context, (value, metadata) =>
|
|
|
|
let { value, has_state } = build_attribute_value(attribute.value, context, (value, metadata) =>
|
|
|
|
metadata.has_call ? get_expression_id(context.state, value) : value
|
|
|
|
metadata.has_call ? get_expression_id(context.state.expressions, value) : value
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
/** @type {Identifier | undefined} */
|
|
|
|
/** @type {Identifier | undefined} */
|
|
|
@ -248,7 +239,7 @@ export function build_set_style(node_id, attribute, style_directives, context) {
|
|
|
|
let next;
|
|
|
|
let next;
|
|
|
|
|
|
|
|
|
|
|
|
if (style_directives.length) {
|
|
|
|
if (style_directives.length) {
|
|
|
|
next = build_style_directives_object(style_directives, context);
|
|
|
|
next = build_style_directives_object(style_directives, context.state.expressions, context);
|
|
|
|
has_state ||= style_directives.some((d) => d.metadata.expression.has_state);
|
|
|
|
has_state ||= style_directives.some((d) => d.metadata.expression.has_state);
|
|
|
|
|
|
|
|
|
|
|
|
if (has_state) {
|
|
|
|
if (has_state) {
|
|
|
|