Lint and format src/compiler/compile/render_dom/wrappers/Element/Binding.js

pull/8569/head
Simon Holthausen 3 years ago
parent 00a3597fb4
commit 5c7b9594dd

@ -8,7 +8,6 @@ import handle_select_value_binding from './handle_select_value_binding';
import { regex_box_size } from '../../../../utils/patterns'; import { regex_box_size } from '../../../../utils/patterns';
/** */ /** */
export default class BindingWrapper { export default class BindingWrapper {
/** @type {import('../../../nodes/Binding.js').default} */ /** @type {import('../../../nodes/Binding.js').default} */
node = undefined; node = undefined;
@ -59,7 +58,13 @@ export default class BindingWrapper {
this.binding_group = get_binding_group(parent.renderer, this, block); this.binding_group = get_binding_group(parent.renderer, this, block);
} }
// view to model // view to model
this.handler = get_event_handler(this, parent.renderer, block, this.object, this.node.raw_expression); this.handler = get_event_handler(
this,
parent.renderer,
block,
this.object,
this.node.raw_expression
);
this.snippet = this.node.expression.manipulate(block); this.snippet = this.node.expression.manipulate(block);
this.is_readonly = this.node.is_readonly; this.is_readonly = this.node.is_readonly;
this.needs_lock = this.node.name === 'currentTime'; // TODO others? this.needs_lock = this.node.name === 'currentTime'; // TODO others?
@ -86,13 +91,13 @@ export default class BindingWrapper {
this.node.expression.template_scope.dependencies_for_name this.node.expression.template_scope.dependencies_for_name
.get(object) .get(object)
.forEach((name) => dependencies.add(name)); .forEach((name) => dependencies.add(name));
} } else {
else {
dependencies.add(object); dependencies.add(object);
} }
const result = new Set(dependencies); const result = new Set(dependencies);
dependencies.forEach((dependency) => { dependencies.forEach((dependency) => {
const indirect_dependencies = this.parent.renderer.component.indirect_dependencies.get(dependency); const indirect_dependencies =
this.parent.renderer.component.indirect_dependencies.get(dependency);
if (indirect_dependencies) { if (indirect_dependencies) {
indirect_dependencies.forEach((indirect_dependency) => { indirect_dependencies.forEach((indirect_dependency) => {
result.add(indirect_dependency); result.add(indirect_dependency);
@ -110,12 +115,11 @@ export default class BindingWrapper {
* @param {import('estree').Identifier} lock * @param {import('estree').Identifier} lock
*/ */
render(block, lock) { render(block, lock) {
if (this.is_readonly) if (this.is_readonly) return;
return;
const { parent } = this; const { parent } = this;
/** @type {any[]} */ /** @type {any[]} */
const update_conditions = this.needs_lock ? [x `!${lock}`] : []; const update_conditions = this.needs_lock ? [x`!${lock}`] : [];
/** @type {any[]} */ /** @type {any[]} */
const mount_conditions = []; const mount_conditions = [];
@ -128,17 +132,18 @@ export default class BindingWrapper {
} }
if (parent.node.name === 'input') { if (parent.node.name === 'input') {
const type = parent.node.get_static_attribute_value('type'); const type = parent.node.get_static_attribute_value('type');
if (type === null || if (
type === null ||
type === '' || type === '' ||
type === 'text' || type === 'text' ||
type === 'email' || type === 'email' ||
type === 'password' || type === 'password' ||
type === 'search' || type === 'search' ||
type === 'url') { type === 'url'
update_conditions.push(x `${parent.var}.${this.node.name} !== ${this.snippet}`); ) {
} update_conditions.push(x`${parent.var}.${this.node.name} !== ${this.snippet}`);
else if (type === 'number') { } else if (type === 'number') {
update_conditions.push(x `@to_number(${parent.var}.${this.node.name}) !== ${this.snippet}`); update_conditions.push(x`@to_number(${parent.var}.${this.node.name}) !== ${this.snippet}`);
} }
} }
// model to view // model to view
@ -149,38 +154,39 @@ export default class BindingWrapper {
case 'group': { case 'group': {
block.renderer.add_to_context('$$binding_groups'); block.renderer.add_to_context('$$binding_groups');
this.binding_group.add_element(block, this.parent.var); this.binding_group.add_element(block, this.parent.var);
if (( /** @type {import('../Element.js').default} */(this.parent)).has_dynamic_value) { if (/** @type {import('../Element.js').default} */ (this.parent).has_dynamic_value) {
update_or_condition = ( /** @type {import('../Element.js').default} */(this.parent)).dynamic_value_condition; update_or_condition = /** @type {import('../Element.js').default} */ (this.parent)
.dynamic_value_condition;
} }
break; break;
} }
case 'textContent': case 'textContent':
update_conditions.push(x `${this.snippet} !== ${parent.var}.textContent`); update_conditions.push(x`${this.snippet} !== ${parent.var}.textContent`);
mount_conditions.push(x `${this.snippet} !== void 0`); mount_conditions.push(x`${this.snippet} !== void 0`);
break; break;
case 'innerText': case 'innerText':
update_conditions.push(x `${this.snippet} !== ${parent.var}.innerText`); update_conditions.push(x`${this.snippet} !== ${parent.var}.innerText`);
mount_conditions.push(x `${this.snippet} !== void 0`); mount_conditions.push(x`${this.snippet} !== void 0`);
break; break;
case 'innerHTML': case 'innerHTML':
update_conditions.push(x `${this.snippet} !== ${parent.var}.innerHTML`); update_conditions.push(x`${this.snippet} !== ${parent.var}.innerHTML`);
mount_conditions.push(x `${this.snippet} !== void 0`); mount_conditions.push(x`${this.snippet} !== void 0`);
break; break;
case 'currentTime': case 'currentTime':
update_conditions.push(x `!@_isNaN(${this.snippet})`); update_conditions.push(x`!@_isNaN(${this.snippet})`);
mount_dom = null; mount_dom = null;
break; break;
case 'playbackRate': case 'playbackRate':
case 'volume': case 'volume':
update_conditions.push(x `!@_isNaN(${this.snippet})`); update_conditions.push(x`!@_isNaN(${this.snippet})`);
mount_conditions.push(x `!@_isNaN(${this.snippet})`); mount_conditions.push(x`!@_isNaN(${this.snippet})`);
break; break;
case 'paused': { case 'paused': {
// this is necessary to prevent audio restarting by itself // this is necessary to prevent audio restarting by itself
const last = block.get_unique_name(`${parent.var.name}_is_paused`); const last = block.get_unique_name(`${parent.var.name}_is_paused`);
block.add_variable(last, x `true`); block.add_variable(last, x`true`);
update_conditions.push(x `${last} !== (${last} = ${this.snippet})`); update_conditions.push(x`${last} !== (${last} = ${this.snippet})`);
update_dom = b `${parent.var}[${last} ? "pause" : "play"]();`; update_dom = b`${parent.var}[${last} ? "pause" : "play"]();`;
mount_dom = null; mount_dom = null;
break; break;
} }
@ -192,29 +198,26 @@ export default class BindingWrapper {
} }
if (update_dom) { if (update_dom) {
if (update_conditions.length > 0) { if (update_conditions.length > 0) {
let condition = update_conditions.reduce((lhs, rhs) => x `${lhs} && ${rhs}`); let condition = update_conditions.reduce((lhs, rhs) => x`${lhs} && ${rhs}`);
if (update_or_condition) if (update_or_condition) condition = x`${update_or_condition} || (${condition})`;
condition = x `${update_or_condition} || (${condition})`; block.chunks.update.push(b`
block.chunks.update.push(b `
if (${condition}) { if (${condition}) {
${update_dom} ${update_dom}
} }
`); `);
} } else {
else {
block.chunks.update.push(update_dom); block.chunks.update.push(update_dom);
} }
} }
if (mount_dom) { if (mount_dom) {
if (mount_conditions.length > 0) { if (mount_conditions.length > 0) {
const condition = mount_conditions.reduce((lhs, rhs) => x `${lhs} && ${rhs}`); const condition = mount_conditions.reduce((lhs, rhs) => x`${lhs} && ${rhs}`);
block.chunks.mount.push(b ` block.chunks.mount.push(b`
if (${condition}) { if (${condition}) {
${mount_dom} ${mount_dom}
} }
`); `);
} } else {
else {
block.chunks.mount.push(mount_dom); block.chunks.mount.push(mount_dom);
} }
} }
@ -236,22 +239,23 @@ function get_dom_updater(element, binding, mounting) {
} }
if (node.name === 'select') { if (node.name === 'select') {
return node.get_static_attribute_value('multiple') === true return node.get_static_attribute_value('multiple') === true
? b `@select_options(${element.var}, ${binding.snippet})` ? b`@select_options(${element.var}, ${binding.snippet})`
: mounting : mounting
? b `@select_option(${element.var}, ${binding.snippet}, true)` ? b`@select_option(${element.var}, ${binding.snippet}, true)`
: b `@select_option(${element.var}, ${binding.snippet})`; : b`@select_option(${element.var}, ${binding.snippet})`;
} }
if (binding.node.name === 'group') { if (binding.node.name === 'group') {
const type = node.get_static_attribute_value('type'); const type = node.get_static_attribute_value('type');
const condition = type === 'checkbox' const condition =
? x `~(${binding.snippet} || []).indexOf(${element.var}.__value)` type === 'checkbox'
: x `${element.var}.__value === ${binding.snippet}`; ? x`~(${binding.snippet} || []).indexOf(${element.var}.__value)`
return b `${element.var}.checked = ${condition};`; : x`${element.var}.__value === ${binding.snippet}`;
return b`${element.var}.checked = ${condition};`;
} }
if (binding.node.name === 'value') { if (binding.node.name === 'value') {
return b `@set_input_value(${element.var}, ${binding.snippet});`; return b`@set_input_value(${element.var}, ${binding.snippet});`;
} }
return b `${element.var}.${binding.node.name} = ${binding.snippet};`; return b`${element.var}.${binding.node.name} = ${binding.snippet};`;
} }
/** /**
@ -287,8 +291,7 @@ function get_binding_group(renderer, binding, block) {
if (context) { if (context) {
key = context.object.name; key = context.object.name;
name = context.property.name; name = context.property.name;
} } else {
else {
key = dep; key = dep;
name = dep; name = dep;
} }
@ -320,10 +323,10 @@ function get_binding_group(renderer, binding, block) {
}); });
renderer.binding_groups.set(keypath, { renderer.binding_groups.set(keypath, {
binding_group: () => { binding_group: () => {
let obj = x `$$binding_groups[${index}]`; let obj = x`$$binding_groups[${index}]`;
if (contexts.length > 0) { if (contexts.length > 0) {
contexts.forEach((secondary_index) => { contexts.forEach((secondary_index) => {
obj = x `${obj}[${secondary_index}]`; obj = x`${obj}[${secondary_index}]`;
}); });
} }
return obj; return obj;
@ -346,14 +349,21 @@ function get_binding_group(renderer, binding, block) {
type: 'ArrayExpression', type: 'ArrayExpression',
elements: contexts.map((name) => block.renderer.reference(name)) elements: contexts.map((name) => block.renderer.reference(name))
}; };
block.chunks.init.push(b `${local_name} = @init_binding_group_dynamic(${binding_group}[${index}], ${indexes})`); block.chunks.init.push(
block.chunks.update.push(b `if (${block.renderer.dirty(Array.from(list_dependencies))}) ${local_name}.u(${indexes})`); b`${local_name} = @init_binding_group_dynamic(${binding_group}[${index}], ${indexes})`
} );
else { block.chunks.update.push(
block.chunks.init.push(b `${local_name} = @init_binding_group(${binding_group}[${index}])`); b`if (${block.renderer.dirty(
} Array.from(list_dependencies)
block.chunks.hydrate.push(b `${local_name}.p(${elements.get(block)})`); )}) ${local_name}.u(${indexes})`
block.chunks.destroy.push(b `${local_name}.r()`); );
} else {
block.chunks.init.push(
b`${local_name} = @init_binding_group(${binding_group}[${index}])`
);
}
block.chunks.hydrate.push(b`${local_name}.p(${elements.get(block)})`);
block.chunks.destroy.push(b`${local_name}.r()`);
} }
}); });
} }
@ -384,18 +394,17 @@ function get_event_handler(binding, renderer, block, name, lhs) {
contextual_dependencies.add(property.name); contextual_dependencies.add(property.name);
contextual_dependencies.delete(name); contextual_dependencies.delete(name);
if (store) { if (store) {
set_store = b `${store}.set(${`$${store}`});`; set_store = b`${store}.set(${`$${store}`});`;
}
} }
else { } else {
const object = get_object(lhs); const object = get_object(lhs);
if (object.name[0] === '$') { if (object.name[0] === '$') {
const store = object.name.slice(1); const store = object.name.slice(1);
set_store = b `${store}.set(${object.name});`; set_store = b`${store}.set(${object.name});`;
} }
} }
const value = get_value_from_dom(renderer, binding.parent, binding, contextual_dependencies); const value = get_value_from_dom(renderer, binding.parent, binding, contextual_dependencies);
const mutation = b ` const mutation = b`
${lhs} = ${value}; ${lhs} = ${value};
${set_store} ${set_store}
`; `;
@ -417,17 +426,17 @@ function get_value_from_dom(_renderer, element, binding, contextual_dependencies
const { node } = element; const { node } = element;
const { name } = binding.node; const { name } = binding.node;
if (name === 'this') { if (name === 'this') {
return x `$$value`; return x`$$value`;
} }
// <div bind:contentRect|contentBoxSize|borderBoxSize|devicePixelContentBoxSize> // <div bind:contentRect|contentBoxSize|borderBoxSize|devicePixelContentBoxSize>
if (regex_box_size.test(name)) { if (regex_box_size.test(name)) {
return x `@ResizeObserverSingleton.entries.get(this)?.${name}`; return x`@ResizeObserverSingleton.entries.get(this)?.${name}`;
} }
// <select bind:value='selected> // <select bind:value='selected>
if (node.name === 'select') { if (node.name === 'select') {
return node.get_static_attribute_value('multiple') === true return node.get_static_attribute_value('multiple') === true
? x `@select_multiple_value(this)` ? x`@select_multiple_value(this)`
: x `@select_value(this)`; : x`@select_value(this)`;
} }
const type = node.get_static_attribute_value('type'); const type = node.get_static_attribute_value('type');
// <input type='checkbox' bind:group='foo'> // <input type='checkbox' bind:group='foo'>
@ -435,21 +444,17 @@ function get_value_from_dom(_renderer, element, binding, contextual_dependencies
if (type === 'checkbox') { if (type === 'checkbox') {
const { binding_group, contexts } = binding.binding_group; const { binding_group, contexts } = binding.binding_group;
add_to_set(contextual_dependencies, contexts); add_to_set(contextual_dependencies, contexts);
return x `@get_binding_group_value(${binding_group()}, this.__value, this.checked)`; return x`@get_binding_group_value(${binding_group()}, this.__value, this.checked)`;
} }
return x `this.__value`; return x`this.__value`;
} }
// <input type='range|number' bind:value> // <input type='range|number' bind:value>
if (type === 'range' || type === 'number') { if (type === 'range' || type === 'number') {
return x `@to_number(this.${name})`; return x`@to_number(this.${name})`;
} }
if (name === 'buffered' || name === 'seekable' || name === 'played') { if (name === 'buffered' || name === 'seekable' || name === 'played') {
return x `@time_ranges_to_array(this.${name})`; return x`@time_ranges_to_array(this.${name})`;
} }
// everything else // everything else
return x `this.${name}`; return x`this.${name}`;
} }

Loading…
Cancel
Save