merge DynamicElement to Element

pull/6898/head
Yuichiro Yamashita 5 years ago
parent 89dd933c8b
commit f8cc52a0c3

@ -1,109 +0,0 @@
import Wrapper from '../shared/Wrapper';
import Renderer from '../../Renderer';
import Block from '../../Block';
import { b, x } from 'code-red';
import { Identifier } from 'estree';
import ElementWrapper from './index';
import create_debugging_comment from '../shared/create_debugging_comment';
import Element from '../../../nodes/Element';
export default class DynamicElementWrapper extends Wrapper {
node: Element;
elementWrapper: ElementWrapper;
dynamic_element_block: Block;
var: Identifier = { type: 'Identifier', name: 'dynamic_element' };
constructor(
renderer: Renderer,
block: Block,
parent: Wrapper,
node: Element,
strip_whitespace: boolean,
next_sibling: Wrapper
) {
super(renderer, block, parent, node);
this.not_static_content();
this.dynamic_element_block = block.child({
comment: create_debugging_comment(node, renderer.component),
name: renderer.component.get_unique_name('create_dynamic_element'),
type: 'dynamic_element'
});
renderer.blocks.push(this.dynamic_element_block);
this.elementWrapper = new ElementWrapper(
renderer,
this.dynamic_element_block,
parent,
node,
strip_whitespace,
next_sibling
);
}
render(block: Block, parent_node: Identifier, parent_nodes: Identifier) {
this.elementWrapper.render(
this.dynamic_element_block,
null,
(x`#nodes` as unknown) as Identifier
);
const previous_tag = block.get_unique_name('previous_tag');
const snippet = this.node.dynamic_tag_expr.manipulate(block);
block.add_variable(previous_tag, snippet);
block.chunks.init.push(b`
let ${this.var} = ${this.dynamic_element_block.name}(#ctx);
`);
block.chunks.create.push(b`${this.var}.c();`);
if (this.renderer.options.hydratable) {
block.chunks.claim.push(b`${this.var}.l(${parent_nodes});`);
}
block.chunks.mount.push(
b`${this.var}.m(${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'
});`
);
const has_transitions = !!(
this.dynamic_element_block.has_intro_method || this.dynamic_element_block.has_outro_method
);
const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
const body = b`
${has_transitions
? b`
@group_outros();
@transition_out(${this.var}, 1, 1, @noop);
@check_outros();
`
: b`${this.var}.d(1);`
}
${this.var} = ${this.dynamic_element_block.name}(#ctx);
${this.var}.c();
${has_transitions && b`@transition_in(${this.var})`}
${this.var}.m(${this.get_update_mount_node(anchor)}, ${anchor});
`;
const not_equal = this.renderer.component.component_options.immutable ? x`@not_equal` : x`@safe_not_equal`;
const condition = x`${not_equal}(${previous_tag}, ${previous_tag} = ${snippet})`;
block.chunks.update.push(b`
if (${condition}) {
${body}
} else {
${this.var}.p(#ctx, #dirty);
}
`);
if (has_transitions) {
block.chunks.intro.push(b`@transition_in(${this.var})`);
block.chunks.outro.push(b`@transition_out(${this.var})`);
}
block.chunks.destroy.push(b`${this.var}.d(detaching)`);
}
}

@ -19,6 +19,7 @@ import { add_event_handler } from '../shared/add_event_handlers';
import { add_action } from '../shared/add_actions'; import { add_action } from '../shared/add_actions';
import bind_this from '../shared/bind_this'; import bind_this from '../shared/bind_this';
import { is_head } from '../shared/is_head'; import { is_head } from '../shared/is_head';
import create_debugging_comment from '../shared/create_debugging_comment';
import { Identifier, ExpressionStatement, CallExpression } from 'estree'; import { Identifier, ExpressionStatement, CallExpression } from 'estree';
import EventHandler from './EventHandler'; import EventHandler from './EventHandler';
import { extract_names } from 'periscopic'; import { extract_names } from 'periscopic';
@ -146,6 +147,9 @@ export default class ElementWrapper extends Wrapper {
var: any; var: any;
void: boolean; void: boolean;
child_dynamic_element_block?: Block = null;
child_dynamic_element?: ElementWrapper = null;
constructor( constructor(
renderer: Renderer, renderer: Renderer,
block: Block, block: Block,
@ -155,11 +159,34 @@ export default class ElementWrapper extends Wrapper {
next_sibling: Wrapper next_sibling: Wrapper
) { ) {
super(renderer, block, parent, node); super(renderer, block, parent, node);
this.var = { this.var = {
type: 'Identifier', type: 'Identifier',
name: node.name.replace(/[^a-zA-Z0-9_$]/g, '_') name: node.name.replace(/[^a-zA-Z0-9_$]/g, '_')
}; };
if (node.dynamic_tag_expr) {
if (block.type !== 'child_dynamic_element') {
this.not_static_content();
this.child_dynamic_element_block = block.child({
comment: create_debugging_comment(node, renderer.component),
name: renderer.component.get_unique_name('create_dynamic_element'),
type: 'child_dynamic_element'
});
renderer.blocks.push(this.child_dynamic_element_block);
this.child_dynamic_element = new ElementWrapper(
renderer,
this.child_dynamic_element_block,
parent,
node,
strip_whitespace,
next_sibling
);
} else {
this.var = { type: 'Identifier', name: 'dynamic_element' };
}
}
this.void = is_void(node.name); this.void = is_void(node.name);
this.class_dependencies = []; this.class_dependencies = [];
@ -234,6 +261,14 @@ export default class ElementWrapper extends Wrapper {
} }
render(block: Block, parent_node: Identifier, parent_nodes: Identifier) { render(block: Block, parent_node: Identifier, parent_nodes: Identifier) {
if (this.child_dynamic_element) {
this.render_dynamic_element(block, parent_node, parent_nodes);
} else {
this.render_element(block, parent_node, parent_nodes);
}
}
render_element(block: Block, parent_node: Identifier, parent_nodes: Identifier) {
const { renderer } = this; const { renderer } = this;
if (this.node.name === 'noscript') return; if (this.node.name === 'noscript') return;
@ -385,6 +420,71 @@ export default class ElementWrapper extends Wrapper {
} }
} }
render_dynamic_element(block: Block, parent_node: Identifier, parent_nodes: Identifier) {
this.child_dynamic_element.render(
this.child_dynamic_element_block,
null,
(x`#nodes` as unknown) as Identifier
);
const previous_tag = block.get_unique_name('previous_tag');
const snippet = this.node.dynamic_tag_expr.manipulate(block);
block.add_variable(previous_tag, snippet);
block.chunks.init.push(b`
let ${this.var} = ${this.child_dynamic_element_block.name}(#ctx);
`);
block.chunks.create.push(b`${this.var}.c();`);
if (this.renderer.options.hydratable) {
block.chunks.claim.push(b`${this.var}.l(${parent_nodes});`);
}
block.chunks.mount.push(
b`${this.var}.m(${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'
});`
);
const has_transitions = !!(
this.child_dynamic_element_block.has_intro_method || this.child_dynamic_element_block.has_outro_method
);
const anchor = this.get_or_create_anchor(block, parent_node, parent_nodes);
const body = b`
${has_transitions
? b`
@group_outros();
@transition_out(${this.var}, 1, 1, @noop);
@check_outros();
`
: b`${this.var}.d(1);`
}
${this.var} = ${this.child_dynamic_element_block.name}(#ctx);
${this.var}.c();
${has_transitions && b`@transition_in(${this.var})`}
${this.var}.m(${this.get_update_mount_node(anchor)}, ${anchor});
`;
const not_equal = this.renderer.component.component_options.immutable ? x`@not_equal` : x`@safe_not_equal`;
const condition = x`${not_equal}(${previous_tag}, ${previous_tag} = ${snippet})`;
block.chunks.update.push(b`
if (${condition}) {
${body}
} else {
${this.var}.p(#ctx, #dirty);
}
`);
if (has_transitions) {
block.chunks.intro.push(b`@transition_in(${this.var})`);
block.chunks.outro.push(b`@transition_out(${this.var})`);
}
block.chunks.destroy.push(b`${this.var}.d(detaching)`);
}
can_use_textcontent() { can_use_textcontent() {
return this.is_static_content && this.fragment.nodes.every(node => node.node.type === 'Text' || node.node.type === 'MustacheTag'); return this.is_static_content && this.fragment.nodes.every(node => node.node.type === 'Text' || node.node.type === 'MustacheTag');
} }

@ -2,7 +2,6 @@ import Wrapper from './shared/Wrapper';
import AwaitBlock from './AwaitBlock'; import AwaitBlock from './AwaitBlock';
import Body from './Body'; import Body from './Body';
import DebugTag from './DebugTag'; import DebugTag from './DebugTag';
import DynamicElement from './Element/DynamicElement';
import EachBlock from './EachBlock'; import EachBlock from './EachBlock';
import Element from './Element/index'; import Element from './Element/index';
import Head from './Head'; import Head from './Head';
@ -28,7 +27,6 @@ const wrappers = {
Body, Body,
Comment: null, Comment: null,
DebugTag, DebugTag,
DynamicElement,
EachBlock, EachBlock,
Element, Element,
Head, Head,
@ -116,13 +114,7 @@ export default class FragmentWrapper {
link(last_child, last_child = wrapper); link(last_child, last_child = wrapper);
} else { } else {
const Wrapper = (function () { const Wrapper = wrappers[child.type];
if (child.type === 'Element' && child.dynamic_tag_expr) {
return wrappers['DynamicElement'];
} else {
return wrappers[child.type];
}
}());
if (!Wrapper) continue; if (!Wrapper) continue;
const wrapper = new Wrapper(renderer, block, parent, child, strip_whitespace, last_child || next_sibling); const wrapper = new Wrapper(renderer, block, parent, child, strip_whitespace, last_child || next_sibling);

Loading…
Cancel
Save