|
|
@ -22,13 +22,7 @@ import {
|
|
|
|
build_set_style
|
|
|
|
build_set_style
|
|
|
|
} from './shared/element.js';
|
|
|
|
} from './shared/element.js';
|
|
|
|
import { process_children } from './shared/fragment.js';
|
|
|
|
import { process_children } from './shared/fragment.js';
|
|
|
|
import {
|
|
|
|
import { build_render_statement, build_template_chunk, get_expression_id } from './shared/utils.js';
|
|
|
|
build_render_statement,
|
|
|
|
|
|
|
|
build_template_chunk,
|
|
|
|
|
|
|
|
build_update_assignment,
|
|
|
|
|
|
|
|
get_expression_id,
|
|
|
|
|
|
|
|
memoize_expression
|
|
|
|
|
|
|
|
} from './shared/utils.js';
|
|
|
|
|
|
|
|
import { visit_event_attribute } from './shared/events.js';
|
|
|
|
import { visit_event_attribute } from './shared/events.js';
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -200,16 +194,16 @@ export function RegularElement(node, context) {
|
|
|
|
|
|
|
|
|
|
|
|
const node_id = context.state.node;
|
|
|
|
const node_id = context.state.node;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** If true, needs `__value` for inputs */
|
|
|
|
|
|
|
|
const needs_special_value_handling =
|
|
|
|
|
|
|
|
node.name === 'option' ||
|
|
|
|
|
|
|
|
node.name === 'select' ||
|
|
|
|
|
|
|
|
bindings.has('group') ||
|
|
|
|
|
|
|
|
bindings.has('checked');
|
|
|
|
|
|
|
|
|
|
|
|
if (has_spread) {
|
|
|
|
if (has_spread) {
|
|
|
|
build_attribute_effect(attributes, class_directives, style_directives, context, node, node_id);
|
|
|
|
build_attribute_effect(attributes, class_directives, style_directives, context, node, node_id);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
/** If true, needs `__value` for inputs */
|
|
|
|
|
|
|
|
const needs_special_value_handling =
|
|
|
|
|
|
|
|
node.name === 'option' ||
|
|
|
|
|
|
|
|
node.name === 'select' ||
|
|
|
|
|
|
|
|
bindings.has('group') ||
|
|
|
|
|
|
|
|
bindings.has('checked');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (const attribute of /** @type {AST.Attribute[]} */ (attributes)) {
|
|
|
|
for (const attribute of /** @type {AST.Attribute[]} */ (attributes)) {
|
|
|
|
if (is_event_attribute(attribute)) {
|
|
|
|
if (is_event_attribute(attribute)) {
|
|
|
|
visit_event_attribute(attribute, context);
|
|
|
|
visit_event_attribute(attribute, context);
|
|
|
@ -217,7 +211,6 @@ export function RegularElement(node, context) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (needs_special_value_handling && attribute.name === 'value') {
|
|
|
|
if (needs_special_value_handling && attribute.name === 'value') {
|
|
|
|
build_element_special_value_attribute(node.name, node_id, attribute, context);
|
|
|
|
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -401,6 +394,15 @@ export function RegularElement(node, context) {
|
|
|
|
context.state.update.push(b.stmt(b.assignment('=', dir, dir)));
|
|
|
|
context.state.update.push(b.stmt(b.assignment('=', dir, dir)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!has_spread && needs_special_value_handling) {
|
|
|
|
|
|
|
|
for (const attribute of /** @type {AST.Attribute[]} */ (attributes)) {
|
|
|
|
|
|
|
|
if (attribute.name === 'value') {
|
|
|
|
|
|
|
|
build_element_special_value_attribute(node.name, node_id, attribute, context);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
context.state.template.pop_element();
|
|
|
|
context.state.template.pop_element();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -650,10 +652,7 @@ function build_element_special_value_attribute(element, node_id, attribute, cont
|
|
|
|
|
|
|
|
|
|
|
|
const { value, has_state } = build_attribute_value(attribute.value, context, (value, metadata) =>
|
|
|
|
const { value, has_state } = build_attribute_value(attribute.value, context, (value, metadata) =>
|
|
|
|
metadata.has_call || metadata.has_await
|
|
|
|
metadata.has_call || metadata.has_await
|
|
|
|
? // if is a select with value we will also invoke `init_select` which need a reference before the template effect so we memoize separately
|
|
|
|
? get_expression_id(metadata.has_await ? state.async_expressions : state.expressions, value)
|
|
|
|
is_select_with_value
|
|
|
|
|
|
|
|
? memoize_expression(context.state, value)
|
|
|
|
|
|
|
|
: get_expression_id(metadata.has_await ? state.async_expressions : state.expressions, value)
|
|
|
|
|
|
|
|
: value
|
|
|
|
: value
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
@ -679,23 +678,21 @@ function build_element_special_value_attribute(element, node_id, attribute, cont
|
|
|
|
: inner_assignment
|
|
|
|
: inner_assignment
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (is_select_with_value) {
|
|
|
|
|
|
|
|
state.init.push(b.stmt(b.call('$.init_select', node_id, b.thunk(value))));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (has_state) {
|
|
|
|
if (has_state) {
|
|
|
|
const id = state.scope.generate(`${node_id.name}_value`);
|
|
|
|
const id = b.id(state.scope.generate(`${node_id.name}_value`));
|
|
|
|
build_update_assignment(
|
|
|
|
|
|
|
|
state,
|
|
|
|
// `<option>` is a special case: The value property reflects to the DOM. If the value is set to undefined,
|
|
|
|
id,
|
|
|
|
// that means the value should be set to the empty string. To be able to do that when the value is
|
|
|
|
// `<option>` is a special case: The value property reflects to the DOM. If the value is set to undefined,
|
|
|
|
// initially undefined, we need to set a value that is guaranteed to be different.
|
|
|
|
// that means the value should be set to the empty string. To be able to do that when the value is
|
|
|
|
const init = element === 'option' ? b.object([]) : undefined;
|
|
|
|
// initially undefined, we need to set a value that is guaranteed to be different.
|
|
|
|
|
|
|
|
element === 'option' ? b.object([]) : undefined,
|
|
|
|
state.init.push(b.var(id, init));
|
|
|
|
value,
|
|
|
|
state.update.push(b.if(b.binary('!==', id, b.assignment('=', id, value)), b.block([update])));
|
|
|
|
update
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
state.init.push(update);
|
|
|
|
state.init.push(update);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (is_select_with_value) {
|
|
|
|
|
|
|
|
state.init.push(b.stmt(b.call('$.init_select', node_id)));
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|