refactor: tidy up compile/nodes

pull/8034/head
Simon He 4 years ago
parent b05b684b95
commit a5afc9d55b

@ -101,12 +101,11 @@ export default class Binding extends Node {
validate_binding_rest_properties(scope: TemplateScope) {
this.expression.references.forEach(name => {
const each_block = scope.get_owner(name);
if (each_block && each_block.type === 'EachBlock') {
if (!each_block || each_block.type !== 'EachBlock') return;
const rest_node = each_block.context_rest_properties.get(name);
if (rest_node) {
this.component.warn(rest_node as any, compiler_warnings.invalid_rest_eachblock_binding(name));
}
}
});
}
}

@ -66,7 +66,7 @@ export default class ConstTag extends Node {
this.expression = new Expression(this.component, this, this.scope, this.node.expression.right);
this.contexts.forEach(context => {
const owner = this.scope.get_owner(context.key.name);
if (owner && owner.type === 'ConstTag' && owner.parent === this.parent) {
if (owner?.type === 'ConstTag' && owner?.parent === this.parent) {
this.component.error(this.node, compiler_errors.invalid_const_declaration(context.key.name));
}
this.scope.add(context.key.name, this.expression.dependencies, this);

@ -13,8 +13,6 @@ export default class DebugTag extends Node {
constructor(component: Component, parent: INode, scope: TemplateScope, info: TemplateNode) {
super(component, parent, scope, info);
this.expressions = info.identifiers.map((node: EsTreeNode) => {
return new Expression(component, parent, scope, node);
});
this.expressions = info.identifiers.map((node: EsTreeNode) => new Expression(component, parent, scope, node));
}
}

@ -261,8 +261,7 @@ export default class Element extends Node {
}
}
if (this.name === 'textarea') {
if (info.children.length > 0) {
if (this.name === 'textarea' && info.children.length) {
const value_attribute = info.attributes.find(node => node.name === 'value');
if (value_attribute) {
component.error(value_attribute, compiler_errors.textarea_duplicate_value);
@ -279,7 +278,6 @@ export default class Element extends Node {
info.children = [];
}
}
if (this.name === 'option') {
// Special case — treat these the same way:
@ -688,20 +686,10 @@ export default class Element extends Node {
if (this.name === 'label') {
const has_input_child = (children: INode[]) => {
if (children.some(child => (child instanceof Element && (a11y_labelable.has(child.name) || child.name === 'slot')))) {
return true;
}
for (const child of children) {
if (!('children' in child) || child.children.length === 0) {
continue;
}
if (has_input_child(child.children)) {
return true;
}
}
return false;
return children.some(child => (child instanceof Element && (a11y_labelable.has(child.name) || child.name === 'slot'))) ||
children.some(child =>
('children' in child) && child.children.length && has_input_child(child.children)
);
};
if (!attribute_map.has('for') && !has_input_child(this.children)) {
@ -714,11 +702,9 @@ export default class Element extends Node {
return;
}
let has_caption;
const track = this.children.find((i: Element) => i.name === 'track');
if (track) {
has_caption = track.attributes.find(a => a.name === 'kind' && a.get_static_value() === 'captions');
}
const has_caption = this.children
.find((i: Element) => i.name === 'track')
?.attributes.find(a => a.name === 'kind' && a.get_static_value() === 'captions');
if (!has_caption) {
component.warn(this, compiler_warnings.a11y_media_has_caption);
@ -1011,7 +997,7 @@ export default class Element extends Node {
const attribute = this.attributes.find(a => a.name === attribute_name);
if (attribute && !attribute.is_true) {
attribute.chunks.forEach((chunk, index) => {
if (chunk.type === 'Text') {
if (chunk.type !== 'Text') return;
let data = chunk.data.replace(regex_any_repeated_whitespaces, ' ');
if (index === 0) {
data = data.trimLeft();
@ -1019,7 +1005,6 @@ export default class Element extends Node {
data = data.trimRight();
}
chunk.data = data;
}
});
}
});

@ -52,12 +52,8 @@ export default class EventHandler extends Node {
}
get reassigned(): boolean {
if (!this.expression) {
return false;
}
const node = this.expression.node;
if (regex_contains_term_function_expression.test(node.type)) {
if (!this.expression ||
regex_contains_term_function_expression.test(this.expression.node.type)) {
return false;
}

@ -24,7 +24,7 @@ export default class Head extends Node {
return (child.type !== 'Text' || regex_non_whitespace_character.test(child.data));
}));
if (this.children.length > 0) {
if (this.children.length) {
this.id = `svelte-${hash(this.component.source.slice(this.start, this.end))}`;
}
}

@ -172,9 +172,7 @@ function not_whitespace_text(node) {
function get_namespace(parent: Node, explicit_namespace: string) {
const parent_element = parent.find_nearest(/^Element/);
if (!parent_element) {
return explicit_namespace;
}
return parent_element.namespace;
return !parent_element
? explicit_namespace
: parent_element.namespace;
}

@ -42,7 +42,10 @@ export default class SlotTemplate extends Node {
break;
}
case 'Attribute': {
if (node.name === 'slot') {
if (node.name !== 'slot') {
throw new Error(`Invalid attribute '${node.name}' in <svelte:fragment>`);
}
this.slot_attribute = new Attribute(component, this, scope, node);
if (!this.slot_attribute.is_static) {
return component.error(node, compiler_errors.invalid_slot_attribute);
@ -54,8 +57,6 @@ export default class SlotTemplate extends Node {
this.slot_template_name = value as string;
break;
}
throw new Error(`Invalid attribute '${node.name}' in <svelte:fragment>`);
}
default:
throw new Error(`Not implemented: ${node.type}`);
}

@ -40,16 +40,15 @@ export default class Text extends Node {
if (parent_element.type === 'InlineComponent') return parent_element.children.length === 1 && this === parent_element.children[0];
// svg namespace exclusions
if (regex_ends_with_svg.test(parent_element.namespace)) {
if (this.prev && this.prev.type === 'Element' && this.prev.name === 'tspan') return false;
if (regex_ends_with_svg.test(parent_element.namespace) && this.prev?.type === 'Element' && this.prev?.name === 'tspan') {
return false;
}
return parent_element.namespace || elements_without_text.has(parent_element.name);
}
keep_space(): boolean {
if (this.component.component_options.preserveWhitespace) return true;
return this.within_pre();
return this.component.component_options.preserveWhitespace || this.within_pre();
}
within_pre(): boolean {

@ -14,7 +14,7 @@ export default class Title extends Node {
super(component, parent, scope, info);
this.children = map_children(component, parent, scope, info.children);
if (info.attributes.length > 0) {
if (info.attributes.length) {
component.error(info.attributes[0], compiler_errors.illegal_attribute_title);
return;
}

@ -47,11 +47,10 @@ export default class Window extends Node {
fuzzymatch(node.name, valid_bindings)
);
if (match) {
return component.error(node, compiler_errors.invalid_binding_on(node.name, '<svelte:window>', ` (did you mean '${match}'?)`));
} else {
return component.error(node, compiler_errors.invalid_binding_on(node.name, '<svelte:window>', ` — valid bindings are ${list(valid_bindings)}`));
}
return component.error(node, compiler_errors.invalid_binding_on(node.name, '<svelte:window>',
match
? ` (did you mean '${match}'?)`
: ` — valid bindings are ${list(valid_bindings)}`));
}
this.bindings.push(new Binding(component, this, scope, node));

@ -19,7 +19,7 @@ export default class AbstractBlock extends Node {
const child = this.children[0];
if (!child || (child.type === 'Text' && !regex_non_whitespace_characters.test(child.data))) {
if (child?.type === 'Text' && !regex_non_whitespace_characters.test(child.data)) {
this.component.warn(this, compiler_warnings.empty_block);
}
}

@ -48,7 +48,7 @@ export function unpack_destructuring({
context_rest_properties.set((node.argument as Identifier).name, node);
} else if (node.type === 'ArrayPattern') {
node.elements.forEach((element, i) => {
if (element && element.type === 'RestElement') {
if (element?.type === 'RestElement') {
unpack_destructuring({
contexts,
node: element,
@ -59,7 +59,7 @@ export function unpack_destructuring({
context_rest_properties
});
context_rest_properties.set((element.argument as Identifier).name, element);
} else if (element && element.type === 'AssignmentPattern') {
} else if (element?.type === 'AssignmentPattern') {
const n = contexts.length;
mark_referenced(element.right, scope, component);
@ -195,12 +195,11 @@ function mark_referenced(
) {
walk(node, {
enter(node: any, parent: any) {
if (is_reference(node, parent)) {
if (!is_reference(node, parent)) return;
const { name } = flatten_reference(node);
if (!scope.is_let(name) && !scope.names.has(name)) {
component.add_reference(node, name);
}
}
}
});
}

@ -133,8 +133,7 @@ export default class Expression {
}
}
if (names) {
names.forEach(name => {
names?.forEach(name => {
if (template_scope.names.has(name)) {
if (template_scope.is_const(name)) {
component.error(node, compiler_errors.invalid_const_update(name));
@ -172,7 +171,6 @@ export default class Expression {
}
}
});
}
},
leave(node: Node) {
@ -189,8 +187,8 @@ export default class Expression {
dynamic_dependencies() {
return Array.from(this.dependencies).filter(name => {
if (this.template_scope.is_let(name)) return true;
if (is_reserved_keyword(name)) return true;
if (this.template_scope.is_let(name) ||
is_reserved_keyword(name)) return true;
const variable = this.component.var_lookup.get(name);
return is_dynamic(variable);
@ -428,11 +426,9 @@ export default class Expression {
}
});
if (declarations.length > 0) {
if (declarations.length) {
block.maintain_context = true;
declarations.forEach(declaration => {
block.chunks.init.push(declaration);
});
block.chunks.init.push(...declarations);
}
return (this.manipulated = node as Node);

@ -36,11 +36,10 @@ export default class Node {
}
cannot_use_innerhtml() {
if (this.can_use_innerhtml !== false) {
if (this.can_use_innerhtml === false) return;
this.can_use_innerhtml = false;
if (this.parent) this.parent.cannot_use_innerhtml();
}
}
find_nearest(selector: RegExp) {
if (selector.test(this.type)) return this;

@ -28,8 +28,7 @@ export default class TemplateScope {
}
child() {
const child = new TemplateScope(this);
return child;
return new TemplateScope(this);
}
is_top_level(name: string) {

@ -65,7 +65,7 @@ function sort_consts_nodes(consts_nodes: ConstTag[], component: Component) {
return acc;
}, []));
if (cycle && cycle.length) {
if (cycle?.length) {
const nodeList = lookup.get(cycle[0]);
const node = nodeList[0];
component.error(node.node, compiler_errors.cyclical_const_tags(cycle));

@ -3,10 +3,11 @@ import TemplateScope from './TemplateScope';
import { is_reserved_keyword } from '../../utils/reserved_keywords';
export default function is_contextual(component: Component, scope: TemplateScope, name: string) {
if (is_reserved_keyword(name)) return true;
if (is_reserved_keyword(name) ||
// if it's a name below root scope, it's contextual
if (!scope.is_top_level(name)) return true;
!scope.is_top_level(name)
) return true;
const variable = component.var_lookup.get(name);

Loading…
Cancel
Save