|
|
@ -59,7 +59,7 @@ function get_attribute_name(element, attribute, context) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Serializes each style directive into something like `$.style(element, style_property, value)`
|
|
|
|
* Serializes each style directive into something like `$.set_style(element, style_property, value)`
|
|
|
|
* and adds it either to init or update, depending on whether or not the value or the attributes are dynamic.
|
|
|
|
* and adds it either to init or update, depending on whether or not the value or the attributes are dynamic.
|
|
|
|
* @param {import('#compiler').StyleDirective[]} style_directives
|
|
|
|
* @param {import('#compiler').StyleDirective[]} style_directives
|
|
|
|
* @param {import('estree').Identifier} element_id
|
|
|
|
* @param {import('estree').Identifier} element_id
|
|
|
@ -74,9 +74,10 @@ function serialize_style_directives(style_directives, element_id, context, is_at
|
|
|
|
directive.value === true
|
|
|
|
directive.value === true
|
|
|
|
? serialize_get_binding({ name: directive.name, type: 'Identifier' }, context.state)
|
|
|
|
? serialize_get_binding({ name: directive.name, type: 'Identifier' }, context.state)
|
|
|
|
: serialize_attribute_value(directive.value, context)[1];
|
|
|
|
: serialize_attribute_value(directive.value, context)[1];
|
|
|
|
const grouped = b.stmt(
|
|
|
|
|
|
|
|
|
|
|
|
const update = b.stmt(
|
|
|
|
b.call(
|
|
|
|
b.call(
|
|
|
|
'$.style',
|
|
|
|
'$.set_style',
|
|
|
|
element_id,
|
|
|
|
element_id,
|
|
|
|
b.literal(directive.name),
|
|
|
|
b.literal(directive.name),
|
|
|
|
value,
|
|
|
|
value,
|
|
|
@ -85,17 +86,6 @@ function serialize_style_directives(style_directives, element_id, context, is_at
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
);
|
|
|
|
const singular = b.stmt(
|
|
|
|
|
|
|
|
b.call(
|
|
|
|
|
|
|
|
'$.style_effect',
|
|
|
|
|
|
|
|
element_id,
|
|
|
|
|
|
|
|
b.literal(directive.name),
|
|
|
|
|
|
|
|
b.arrow([], value),
|
|
|
|
|
|
|
|
/** @type {import('estree').Expression} */ (
|
|
|
|
|
|
|
|
directive.modifiers.includes('important') ? b.true : undefined
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const contains_call_expression =
|
|
|
|
const contains_call_expression =
|
|
|
|
Array.isArray(directive.value) &&
|
|
|
|
Array.isArray(directive.value) &&
|
|
|
@ -104,11 +94,11 @@ function serialize_style_directives(style_directives, element_id, context, is_at
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (!is_attributes_reactive && contains_call_expression) {
|
|
|
|
if (!is_attributes_reactive && contains_call_expression) {
|
|
|
|
state.init.push(singular);
|
|
|
|
state.init.push(serialize_update(update));
|
|
|
|
} else if (is_attributes_reactive || directive.metadata.dynamic || contains_call_expression) {
|
|
|
|
} else if (is_attributes_reactive || directive.metadata.dynamic || contains_call_expression) {
|
|
|
|
state.update.push({ grouped, singular });
|
|
|
|
state.update.push(update);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
state.init.push(grouped);
|
|
|
|
state.init.push(update);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -146,18 +136,15 @@ function serialize_class_directives(class_directives, element_id, context, is_at
|
|
|
|
const state = context.state;
|
|
|
|
const state = context.state;
|
|
|
|
for (const directive of class_directives) {
|
|
|
|
for (const directive of class_directives) {
|
|
|
|
const value = /** @type {import('estree').Expression} */ (context.visit(directive.expression));
|
|
|
|
const value = /** @type {import('estree').Expression} */ (context.visit(directive.expression));
|
|
|
|
const grouped = b.stmt(b.call('$.class_toggle', element_id, b.literal(directive.name), value));
|
|
|
|
const update = b.stmt(b.call('$.toggle_class', element_id, b.literal(directive.name), value));
|
|
|
|
const singular = b.stmt(
|
|
|
|
|
|
|
|
b.call('$.class_toggle_effect', element_id, b.literal(directive.name), b.arrow([], value))
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
const contains_call_expression = directive.expression.type === 'CallExpression';
|
|
|
|
const contains_call_expression = directive.expression.type === 'CallExpression';
|
|
|
|
|
|
|
|
|
|
|
|
if (!is_attributes_reactive && contains_call_expression) {
|
|
|
|
if (!is_attributes_reactive && contains_call_expression) {
|
|
|
|
state.init.push(singular);
|
|
|
|
state.init.push(serialize_update(update));
|
|
|
|
} else if (is_attributes_reactive || directive.metadata.dynamic || contains_call_expression) {
|
|
|
|
} else if (is_attributes_reactive || directive.metadata.dynamic || contains_call_expression) {
|
|
|
|
state.update.push({ grouped, singular });
|
|
|
|
state.update.push(update);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
state.init.push(grouped);
|
|
|
|
state.init.push(update);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -293,23 +280,14 @@ function serialize_element_spread_attributes(
|
|
|
|
|
|
|
|
|
|
|
|
const lowercase_attributes =
|
|
|
|
const lowercase_attributes =
|
|
|
|
element.metadata.svg || is_custom_element_node(element) ? b.false : b.true;
|
|
|
|
element.metadata.svg || is_custom_element_node(element) ? b.false : b.true;
|
|
|
|
const id = context.state.scope.generate('spread_attributes');
|
|
|
|
const id = context.state.scope.generate('attributes');
|
|
|
|
|
|
|
|
|
|
|
|
const standalone = b.stmt(
|
|
|
|
const update = b.stmt(
|
|
|
|
b.call(
|
|
|
|
|
|
|
|
'$.spread_attributes_effect',
|
|
|
|
|
|
|
|
element_id,
|
|
|
|
|
|
|
|
b.thunk(b.array(values)),
|
|
|
|
|
|
|
|
lowercase_attributes,
|
|
|
|
|
|
|
|
b.literal(context.state.analysis.css.hash)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
const inside_effect = b.stmt(
|
|
|
|
|
|
|
|
b.assignment(
|
|
|
|
b.assignment(
|
|
|
|
'=',
|
|
|
|
'=',
|
|
|
|
b.id(id),
|
|
|
|
b.id(id),
|
|
|
|
b.call(
|
|
|
|
b.call(
|
|
|
|
'$.spread_attributes',
|
|
|
|
'$.set_attributes',
|
|
|
|
element_id,
|
|
|
|
element_id,
|
|
|
|
b.id(id),
|
|
|
|
b.id(id),
|
|
|
|
b.array(values),
|
|
|
|
b.array(values),
|
|
|
@ -319,32 +297,21 @@ function serialize_element_spread_attributes(
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (!needs_isolation || needs_select_handling) {
|
|
|
|
|
|
|
|
context.state.init.push(b.let(id));
|
|
|
|
context.state.init.push(b.let(id));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// objects could contain reactive getters -> play it safe and always assume spread attributes are reactive
|
|
|
|
// objects could contain reactive getters -> play it safe and always assume spread attributes are reactive
|
|
|
|
if (needs_isolation) {
|
|
|
|
if (needs_isolation) {
|
|
|
|
if (needs_select_handling) {
|
|
|
|
context.state.init.push(serialize_update(update));
|
|
|
|
context.state.init.push(
|
|
|
|
|
|
|
|
b.stmt(b.call('$.render_effect', b.arrow([], b.block([inside_effect]))))
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
context.state.init.push(standalone);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
context.state.update.push({
|
|
|
|
context.state.update.push(update);
|
|
|
|
singular: needs_select_handling ? undefined : standalone,
|
|
|
|
|
|
|
|
grouped: inside_effect
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (needs_select_handling) {
|
|
|
|
if (needs_select_handling) {
|
|
|
|
context.state.init.push(
|
|
|
|
context.state.init.push(
|
|
|
|
b.stmt(b.call('$.init_select', element_id, b.thunk(b.member(b.id(id), b.id('value')))))
|
|
|
|
b.stmt(b.call('$.init_select', element_id, b.thunk(b.member(b.id(id), b.id('value')))))
|
|
|
|
);
|
|
|
|
);
|
|
|
|
context.state.update.push({
|
|
|
|
context.state.update.push(
|
|
|
|
grouped: b.if(
|
|
|
|
b.if(
|
|
|
|
b.binary('in', b.literal('value'), b.id(id)),
|
|
|
|
b.binary('in', b.literal('value'), b.id(id)),
|
|
|
|
b.block([
|
|
|
|
b.block([
|
|
|
|
// This ensures a one-way street to the DOM in case it's <select {value}>
|
|
|
|
// This ensures a one-way street to the DOM in case it's <select {value}>
|
|
|
@ -354,7 +321,7 @@ function serialize_element_spread_attributes(
|
|
|
|
b.stmt(b.call('$.select_option', element_id, b.member(b.id(id), b.id('value'))))
|
|
|
|
b.stmt(b.call('$.select_option', element_id, b.member(b.id(id), b.id('value'))))
|
|
|
|
])
|
|
|
|
])
|
|
|
|
)
|
|
|
|
)
|
|
|
|
});
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -370,12 +337,14 @@ function serialize_dynamic_element_attributes(attributes, context, element_id) {
|
|
|
|
if (attributes.length === 0) {
|
|
|
|
if (attributes.length === 0) {
|
|
|
|
if (context.state.analysis.css.hash) {
|
|
|
|
if (context.state.analysis.css.hash) {
|
|
|
|
context.state.init.push(
|
|
|
|
context.state.init.push(
|
|
|
|
b.stmt(b.call('$.class_name', element_id, b.literal(context.state.analysis.css.hash)))
|
|
|
|
b.stmt(b.call('$.set_class', element_id, b.literal(context.state.analysis.css.hash)))
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO why are we always treating this as a spread? needs docs, if that's not an error
|
|
|
|
|
|
|
|
|
|
|
|
let needs_isolation = false;
|
|
|
|
let needs_isolation = false;
|
|
|
|
let is_reactive = false;
|
|
|
|
let is_reactive = false;
|
|
|
|
|
|
|
|
|
|
|
@ -398,43 +367,37 @@ function serialize_dynamic_element_attributes(attributes, context, element_id) {
|
|
|
|
attribute.type === 'SpreadAttribute' && attribute.metadata.contains_call_expression;
|
|
|
|
attribute.type === 'SpreadAttribute' && attribute.metadata.contains_call_expression;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const isolated = b.stmt(
|
|
|
|
if (needs_isolation || is_reactive) {
|
|
|
|
b.call(
|
|
|
|
const id = context.state.scope.generate('attributes');
|
|
|
|
'$.spread_dynamic_element_attributes_effect',
|
|
|
|
|
|
|
|
element_id,
|
|
|
|
|
|
|
|
b.thunk(b.array(values)),
|
|
|
|
|
|
|
|
b.literal(context.state.analysis.css.hash)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (needs_isolation) {
|
|
|
|
|
|
|
|
context.state.init.push(isolated);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
} else if (is_reactive) {
|
|
|
|
|
|
|
|
const id = context.state.scope.generate('spread_attributes');
|
|
|
|
|
|
|
|
context.state.init.push(b.let(id));
|
|
|
|
context.state.init.push(b.let(id));
|
|
|
|
context.state.update.push({
|
|
|
|
|
|
|
|
singular: isolated,
|
|
|
|
const update = b.stmt(
|
|
|
|
grouped: b.stmt(
|
|
|
|
|
|
|
|
b.assignment(
|
|
|
|
b.assignment(
|
|
|
|
'=',
|
|
|
|
'=',
|
|
|
|
b.id(id),
|
|
|
|
b.id(id),
|
|
|
|
b.call(
|
|
|
|
b.call(
|
|
|
|
'$.spread_dynamic_element_attributes',
|
|
|
|
'$.set_dynamic_element_attributes',
|
|
|
|
element_id,
|
|
|
|
element_id,
|
|
|
|
b.id(id),
|
|
|
|
b.id(id),
|
|
|
|
b.array(values),
|
|
|
|
b.array(values),
|
|
|
|
b.literal(context.state.analysis.css.hash)
|
|
|
|
b.literal(context.state.analysis.css.hash)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (needs_isolation) {
|
|
|
|
|
|
|
|
context.state.init.push(serialize_update(update));
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
context.state.update.push(update);
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
context.state.init.push(
|
|
|
|
context.state.init.push(
|
|
|
|
b.stmt(
|
|
|
|
b.stmt(
|
|
|
|
b.call(
|
|
|
|
b.call(
|
|
|
|
'$.spread_dynamic_element_attributes',
|
|
|
|
'$.set_dynamic_element_attributes',
|
|
|
|
element_id,
|
|
|
|
element_id,
|
|
|
|
b.literal(null),
|
|
|
|
b.literal(null),
|
|
|
|
b.array(values),
|
|
|
|
b.array(values),
|
|
|
@ -443,7 +406,6 @@ function serialize_dynamic_element_attributes(attributes, context, element_id) {
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -453,7 +415,7 @@ function serialize_dynamic_element_attributes(attributes, context, element_id) {
|
|
|
|
* ```js
|
|
|
|
* ```js
|
|
|
|
* element.property = value;
|
|
|
|
* element.property = value;
|
|
|
|
* // or
|
|
|
|
* // or
|
|
|
|
* $.attr(element, property, value);
|
|
|
|
* $.set_attribute(element, property, value);
|
|
|
|
* });
|
|
|
|
* });
|
|
|
|
* ```
|
|
|
|
* ```
|
|
|
|
* Resulting code for dynamic looks something like this:
|
|
|
|
* Resulting code for dynamic looks something like this:
|
|
|
@ -463,7 +425,7 @@ function serialize_dynamic_element_attributes(attributes, context, element_id) {
|
|
|
|
* if (value !== (value = 'new value')) {
|
|
|
|
* if (value !== (value = 'new value')) {
|
|
|
|
* element.property = value;
|
|
|
|
* element.property = value;
|
|
|
|
* // or
|
|
|
|
* // or
|
|
|
|
* $.attr(element, property, value);
|
|
|
|
* $.set_attribute(element, property, value);
|
|
|
|
* }
|
|
|
|
* }
|
|
|
|
* });
|
|
|
|
* });
|
|
|
|
* ```
|
|
|
|
* ```
|
|
|
@ -482,7 +444,9 @@ function serialize_element_attribute_update_assignment(element, node_id, attribu
|
|
|
|
|
|
|
|
|
|
|
|
// The foreign namespace doesn't have any special handling, everything goes through the attr function
|
|
|
|
// The foreign namespace doesn't have any special handling, everything goes through the attr function
|
|
|
|
if (context.state.metadata.namespace === 'foreign') {
|
|
|
|
if (context.state.metadata.namespace === 'foreign') {
|
|
|
|
const statement = { grouped: b.stmt(b.call('$.attr', node_id, b.literal(name), value)) };
|
|
|
|
const statement = {
|
|
|
|
|
|
|
|
grouped: b.stmt(b.call('$.set_attribute', node_id, b.literal(name), value))
|
|
|
|
|
|
|
|
};
|
|
|
|
if (attribute.metadata.dynamic) {
|
|
|
|
if (attribute.metadata.dynamic) {
|
|
|
|
const id = state.scope.generate(`${node_id.name}_${name}`);
|
|
|
|
const id = state.scope.generate(`${node_id.name}_${name}`);
|
|
|
|
serialize_update_assignment(state, id, undefined, value, statement, contains_call_expression);
|
|
|
|
serialize_update_assignment(state, id, undefined, value, statement, contains_call_expression);
|
|
|
@ -493,84 +457,32 @@ function serialize_element_attribute_update_assignment(element, node_id, attribu
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let grouped_value = value;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (name === 'autofocus') {
|
|
|
|
if (name === 'autofocus') {
|
|
|
|
state.init.push(b.stmt(b.call('$.autofocus', node_id, value)));
|
|
|
|
state.init.push(b.stmt(b.call('$.autofocus', node_id, value)));
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (name === 'class') {
|
|
|
|
/** @type {import('estree').Statement} */
|
|
|
|
grouped_value = b.call('$.to_class', value);
|
|
|
|
let update;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @param {import('estree').Expression} grouped
|
|
|
|
|
|
|
|
* @param {import('estree').Expression} [singular]
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
const assign = (grouped, singular) => {
|
|
|
|
|
|
|
|
if (name === 'class') {
|
|
|
|
if (name === 'class') {
|
|
|
|
if (singular) {
|
|
|
|
update = b.stmt(b.call(is_svg ? '$.set_svg_class' : '$.set_class', node_id, value));
|
|
|
|
return {
|
|
|
|
} else if (DOMProperties.includes(name)) {
|
|
|
|
singular: b.stmt(
|
|
|
|
update = b.stmt(b.assignment('=', b.member(node_id, b.id(name)), value));
|
|
|
|
b.call(
|
|
|
|
|
|
|
|
is_svg ? '$.svg_class_name_effect' : '$.class_name_effect',
|
|
|
|
|
|
|
|
node_id,
|
|
|
|
|
|
|
|
b.thunk(singular)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
grouped: b.stmt(b.call(is_svg ? '$.svg_class_name' : '$.class_name', node_id, singular))
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
grouped: b.stmt(b.call(is_svg ? '$.svg_class_name' : '$.class_name', node_id, value))
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
} else if (!DOMProperties.includes(name)) {
|
|
|
|
|
|
|
|
if (singular) {
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
singular: b.stmt(
|
|
|
|
|
|
|
|
b.call(
|
|
|
|
|
|
|
|
name.startsWith('xlink') ? '$.xlink_attr_effect' : '$.attr_effect',
|
|
|
|
|
|
|
|
node_id,
|
|
|
|
|
|
|
|
b.literal(name),
|
|
|
|
|
|
|
|
b.thunk(singular)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
grouped: b.stmt(
|
|
|
|
|
|
|
|
b.call(
|
|
|
|
|
|
|
|
name.startsWith('xlink') ? '$.xlink_attr' : '$.attr',
|
|
|
|
|
|
|
|
node_id,
|
|
|
|
|
|
|
|
b.literal(name),
|
|
|
|
|
|
|
|
grouped
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
grouped: b.stmt(
|
|
|
|
|
|
|
|
b.call(
|
|
|
|
|
|
|
|
name.startsWith('xlink') ? '$.xlink_attr' : '$.attr',
|
|
|
|
|
|
|
|
node_id,
|
|
|
|
|
|
|
|
b.literal(name),
|
|
|
|
|
|
|
|
grouped
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
return { grouped: b.stmt(b.assignment('=', b.member(node_id, b.id(name)), grouped)) };
|
|
|
|
const callee = name.startsWith('xlink') ? '$.set_xlink_attribute' : '$.set_attribute';
|
|
|
|
|
|
|
|
update = b.stmt(b.call(callee, node_id, b.literal(name), value));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (attribute.metadata.dynamic) {
|
|
|
|
if (attribute.metadata.dynamic) {
|
|
|
|
const { grouped, singular } = assign(grouped_value, value);
|
|
|
|
if (contains_call_expression) {
|
|
|
|
if (contains_call_expression && singular) {
|
|
|
|
state.init.push(serialize_update(update));
|
|
|
|
state.init.push(singular);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
state.update.push({ singular, grouped });
|
|
|
|
state.update.push(update);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
state.init.push(assign(grouped_value).grouped);
|
|
|
|
state.init.push(update);
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -586,40 +498,18 @@ function serialize_custom_element_attribute_update_assignment(node_id, attribute
|
|
|
|
const state = context.state;
|
|
|
|
const state = context.state;
|
|
|
|
const name = attribute.name; // don't lowercase, as we set the element's property, which might be case sensitive
|
|
|
|
const name = attribute.name; // don't lowercase, as we set the element's property, which might be case sensitive
|
|
|
|
let [contains_call_expression, value] = serialize_attribute_value(attribute.value, context);
|
|
|
|
let [contains_call_expression, value] = serialize_attribute_value(attribute.value, context);
|
|
|
|
let grouped_value = value;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
const update = b.stmt(b.call('$.set_custom_element_data', node_id, b.literal(name), value));
|
|
|
|
* @param {import('estree').Expression} grouped
|
|
|
|
|
|
|
|
* @param {import('estree').Expression} [singular]
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
const assign = (grouped, singular) => {
|
|
|
|
|
|
|
|
if (singular) {
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
singular: b.stmt(
|
|
|
|
|
|
|
|
b.call('$.set_custom_element_data_effect', node_id, b.literal(name), b.thunk(singular))
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
grouped: b.stmt(b.call('$.set_custom_element_data', node_id, b.literal(name), grouped))
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
grouped: b.stmt(b.call('$.set_custom_element_data', node_id, b.literal(name), grouped))
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (attribute.metadata.dynamic) {
|
|
|
|
if (attribute.metadata.dynamic) {
|
|
|
|
const id = state.scope.generate(`${node_id.name}_${name}`);
|
|
|
|
if (contains_call_expression) {
|
|
|
|
// TODO should this use the if condition? what if someone mutates the value passed to the ce?
|
|
|
|
state.init.push(serialize_update(update));
|
|
|
|
serialize_update_assignment(
|
|
|
|
} else {
|
|
|
|
state,
|
|
|
|
state.update.push(update);
|
|
|
|
id,
|
|
|
|
}
|
|
|
|
undefined,
|
|
|
|
|
|
|
|
grouped_value,
|
|
|
|
|
|
|
|
assign(b.id(id), value),
|
|
|
|
|
|
|
|
contains_call_expression
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
state.init.push(assign(grouped_value).grouped);
|
|
|
|
state.init.push(update);
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -709,28 +599,18 @@ function serialize_update_assignment(state, id, init, value, assignment, contain
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
if (assignment.skip_condition) {
|
|
|
|
if (assignment.skip_condition) {
|
|
|
|
if (assignment.singular) {
|
|
|
|
if (assignment.singular) {
|
|
|
|
state.update.push({
|
|
|
|
state.update.push(assignment.grouped);
|
|
|
|
singular: assignment.singular,
|
|
|
|
|
|
|
|
grouped: assignment.grouped
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
state.init.push(b.var(id, init));
|
|
|
|
state.init.push(b.var(id, init));
|
|
|
|
state.update.push({
|
|
|
|
state.update.push(grouped);
|
|
|
|
grouped
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
if (assignment.singular) {
|
|
|
|
if (assignment.singular) {
|
|
|
|
state.init.push(b.var(id, init));
|
|
|
|
state.init.push(b.var(id, init));
|
|
|
|
state.update.push({
|
|
|
|
state.update.push(grouped);
|
|
|
|
singular: assignment.singular,
|
|
|
|
|
|
|
|
grouped
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
state.init.push(b.var(id, init));
|
|
|
|
state.init.push(b.var(id, init));
|
|
|
|
state.update.push({
|
|
|
|
state.update.push(grouped);
|
|
|
|
grouped
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1274,16 +1154,25 @@ function get_template_function(namespace, state) {
|
|
|
|
: '$.template';
|
|
|
|
: '$.template';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param {import('estree').Statement} statement
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
function serialize_update(statement) {
|
|
|
|
|
|
|
|
const body =
|
|
|
|
|
|
|
|
statement.type === 'ExpressionStatement' ? statement.expression : b.block([statement]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return b.stmt(b.call('$.render_effect', b.thunk(body)));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param {import('../types.js').ComponentClientTransformState} state
|
|
|
|
* @param {import('../types.js').ComponentClientTransformState} state
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function serialize_render_stmt(state) {
|
|
|
|
function serialize_render_stmt(state) {
|
|
|
|
if (state.update.length === 1 && state.update[0].singular) {
|
|
|
|
return state.update.length === 1
|
|
|
|
return state.update[0].singular;
|
|
|
|
? serialize_update(state.update[0])
|
|
|
|
}
|
|
|
|
: b.stmt(b.call('$.render_effect', b.thunk(b.block(state.update))));
|
|
|
|
|
|
|
|
|
|
|
|
return b.stmt(b.call('$.render_effect', b.thunk(b.block(state.update.map((n) => n.grouped)))));
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -1508,27 +1397,18 @@ function process_children(nodes, expression, is_element, { visit, state }) {
|
|
|
|
|
|
|
|
|
|
|
|
const text_id = get_node_id(b.call('$.space', expression(true)), state, 'text');
|
|
|
|
const text_id = get_node_id(b.call('$.space', expression(true)), state, 'text');
|
|
|
|
|
|
|
|
|
|
|
|
const singular = b.stmt(
|
|
|
|
const update = b.stmt(
|
|
|
|
b.call(
|
|
|
|
b.call(
|
|
|
|
'$.text_effect',
|
|
|
|
'$.set_text',
|
|
|
|
text_id,
|
|
|
|
text_id,
|
|
|
|
b.thunk(/** @type {import('estree').Expression} */ (visit(node.expression)))
|
|
|
|
/** @type {import('estree').Expression} */ (visit(node.expression))
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (node.metadata.contains_call_expression && !within_bound_contenteditable) {
|
|
|
|
if (node.metadata.contains_call_expression && !within_bound_contenteditable) {
|
|
|
|
state.init.push(singular);
|
|
|
|
state.init.push(serialize_update(update));
|
|
|
|
} else if (node.metadata.dynamic && !within_bound_contenteditable) {
|
|
|
|
} else if (node.metadata.dynamic && !within_bound_contenteditable) {
|
|
|
|
state.update.push({
|
|
|
|
state.update.push(update);
|
|
|
|
singular,
|
|
|
|
|
|
|
|
grouped: b.stmt(
|
|
|
|
|
|
|
|
b.call(
|
|
|
|
|
|
|
|
'$.text',
|
|
|
|
|
|
|
|
text_id,
|
|
|
|
|
|
|
|
/** @type {import('estree').Expression} */ (visit(node.expression))
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
state.init.push(
|
|
|
|
state.init.push(
|
|
|
|
b.stmt(
|
|
|
|
b.stmt(
|
|
|
@ -1551,25 +1431,19 @@ function process_children(nodes, expression, is_element, { visit, state }) {
|
|
|
|
|
|
|
|
|
|
|
|
state.template.push(' ');
|
|
|
|
state.template.push(' ');
|
|
|
|
|
|
|
|
|
|
|
|
const contains_call_expression = sequence.some(
|
|
|
|
const [contains_call_expression, value] = serialize_template_literal(sequence, visit);
|
|
|
|
(n) => n.type === 'ExpressionTag' && n.metadata.contains_call_expression
|
|
|
|
|
|
|
|
);
|
|
|
|
const update = b.stmt(b.call('$.set_text', text_id, value));
|
|
|
|
const assignment = serialize_template_literal(sequence, visit, state)[1];
|
|
|
|
|
|
|
|
const init = b.stmt(b.assignment('=', b.member(text_id, b.id('nodeValue')), assignment));
|
|
|
|
|
|
|
|
const singular = b.stmt(b.call('$.text_effect', text_id, b.thunk(assignment)));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (contains_call_expression && !within_bound_contenteditable) {
|
|
|
|
if (contains_call_expression && !within_bound_contenteditable) {
|
|
|
|
state.init.push(singular);
|
|
|
|
state.init.push(serialize_update(update));
|
|
|
|
} else if (
|
|
|
|
} else if (
|
|
|
|
sequence.some((node) => node.type === 'ExpressionTag' && node.metadata.dynamic) &&
|
|
|
|
sequence.some((node) => node.type === 'ExpressionTag' && node.metadata.dynamic) &&
|
|
|
|
!within_bound_contenteditable
|
|
|
|
!within_bound_contenteditable
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
state.update.push({
|
|
|
|
state.update.push(update);
|
|
|
|
singular,
|
|
|
|
|
|
|
|
grouped: b.stmt(b.call('$.text', text_id, assignment))
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
state.init.push(init);
|
|
|
|
state.init.push(b.stmt(b.assignment('=', b.member(text_id, b.id('nodeValue')), value)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
expression = (is_text) =>
|
|
|
|
expression = (is_text) =>
|
|
|
@ -1672,22 +1546,20 @@ function serialize_attribute_value(attribute_value, context) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return serialize_template_literal(attribute_value, context.visit, context.state);
|
|
|
|
return serialize_template_literal(attribute_value, context.visit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* @param {Array<import('#compiler').Text | import('#compiler').ExpressionTag>} values
|
|
|
|
* @param {Array<import('#compiler').Text | import('#compiler').ExpressionTag>} values
|
|
|
|
* @param {(node: import('#compiler').SvelteNode) => any} visit
|
|
|
|
* @param {(node: import('#compiler').SvelteNode) => any} visit
|
|
|
|
* @param {import('../types.js').ComponentClientTransformState} state
|
|
|
|
|
|
|
|
* @returns {[boolean, import('estree').TemplateLiteral]}
|
|
|
|
* @returns {[boolean, import('estree').TemplateLiteral]}
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function serialize_template_literal(values, visit, state) {
|
|
|
|
function serialize_template_literal(values, visit) {
|
|
|
|
/** @type {import('estree').TemplateElement[]} */
|
|
|
|
/** @type {import('estree').TemplateElement[]} */
|
|
|
|
const quasis = [];
|
|
|
|
const quasis = [];
|
|
|
|
|
|
|
|
|
|
|
|
/** @type {import('estree').Expression[]} */
|
|
|
|
/** @type {import('estree').Expression[]} */
|
|
|
|
const expressions = [];
|
|
|
|
const expressions = [];
|
|
|
|
const scope = state.scope;
|
|
|
|
|
|
|
|
let contains_call_expression = false;
|
|
|
|
let contains_call_expression = false;
|
|
|
|
quasis.push(b.quasi(''));
|
|
|
|
quasis.push(b.quasi(''));
|
|
|
|
|
|
|
|
|
|
|
@ -1711,6 +1583,7 @@ function serialize_template_literal(values, visit, state) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO instead of this tuple, return a `{ dynamic, complex, value }` object. will DRY stuff out
|
|
|
|
return [contains_call_expression, b.template(quasis, expressions)];
|
|
|
|
return [contains_call_expression, b.template(quasis, expressions)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -3128,15 +3001,15 @@ export const template_visitors = {
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
state.update.push({
|
|
|
|
state.update.push(
|
|
|
|
grouped: b.stmt(
|
|
|
|
b.stmt(
|
|
|
|
b.assignment(
|
|
|
|
b.assignment(
|
|
|
|
'=',
|
|
|
|
'=',
|
|
|
|
b.member(b.id('$.document'), b.id('title')),
|
|
|
|
b.member(b.id('$.document'), b.id('title')),
|
|
|
|
serialize_template_literal(/** @type {any} */ (node.fragment.nodes), visit, state)[1]
|
|
|
|
serialize_template_literal(/** @type {any} */ (node.fragment.nodes), visit)[1]
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
});
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
SvelteBody(node, context) {
|
|
|
|
SvelteBody(node, context) {
|
|
|
|