From f8cc52a0c37b9883dd412ce64ad89e272f09c8d0 Mon Sep 17 00:00:00 2001 From: Yuichiro Yamashita Date: Wed, 3 Nov 2021 21:52:47 +0900 Subject: [PATCH] merge DynamicElement to Element --- .../wrappers/Element/DynamicElement.ts | 109 ------------------ .../render_dom/wrappers/Element/index.ts | 100 ++++++++++++++++ .../compile/render_dom/wrappers/Fragment.ts | 10 +- 3 files changed, 101 insertions(+), 118 deletions(-) delete mode 100644 src/compiler/compile/render_dom/wrappers/Element/DynamicElement.ts diff --git a/src/compiler/compile/render_dom/wrappers/Element/DynamicElement.ts b/src/compiler/compile/render_dom/wrappers/Element/DynamicElement.ts deleted file mode 100644 index c81e4f01a3..0000000000 --- a/src/compiler/compile/render_dom/wrappers/Element/DynamicElement.ts +++ /dev/null @@ -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)`); - } -} diff --git a/src/compiler/compile/render_dom/wrappers/Element/index.ts b/src/compiler/compile/render_dom/wrappers/Element/index.ts index 9b76078b5b..12422ae163 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/index.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/index.ts @@ -19,6 +19,7 @@ import { add_event_handler } from '../shared/add_event_handlers'; import { add_action } from '../shared/add_actions'; import bind_this from '../shared/bind_this'; import { is_head } from '../shared/is_head'; +import create_debugging_comment from '../shared/create_debugging_comment'; import { Identifier, ExpressionStatement, CallExpression } from 'estree'; import EventHandler from './EventHandler'; import { extract_names } from 'periscopic'; @@ -146,6 +147,9 @@ export default class ElementWrapper extends Wrapper { var: any; void: boolean; + child_dynamic_element_block?: Block = null; + child_dynamic_element?: ElementWrapper = null; + constructor( renderer: Renderer, block: Block, @@ -155,11 +159,34 @@ export default class ElementWrapper extends Wrapper { next_sibling: Wrapper ) { super(renderer, block, parent, node); + this.var = { type: 'Identifier', 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.class_dependencies = []; @@ -234,6 +261,14 @@ export default class ElementWrapper extends Wrapper { } 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; 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() { return this.is_static_content && this.fragment.nodes.every(node => node.node.type === 'Text' || node.node.type === 'MustacheTag'); } diff --git a/src/compiler/compile/render_dom/wrappers/Fragment.ts b/src/compiler/compile/render_dom/wrappers/Fragment.ts index d233610395..98805b9639 100644 --- a/src/compiler/compile/render_dom/wrappers/Fragment.ts +++ b/src/compiler/compile/render_dom/wrappers/Fragment.ts @@ -2,7 +2,6 @@ import Wrapper from './shared/Wrapper'; import AwaitBlock from './AwaitBlock'; import Body from './Body'; import DebugTag from './DebugTag'; -import DynamicElement from './Element/DynamicElement'; import EachBlock from './EachBlock'; import Element from './Element/index'; import Head from './Head'; @@ -28,7 +27,6 @@ const wrappers = { Body, Comment: null, DebugTag, - DynamicElement, EachBlock, Element, Head, @@ -116,13 +114,7 @@ export default class FragmentWrapper { link(last_child, last_child = wrapper); } else { - const Wrapper = (function () { - if (child.type === 'Element' && child.dynamic_tag_expr) { - return wrappers['DynamicElement']; - } else { - return wrappers[child.type]; - } - }()); + const Wrapper = wrappers[child.type]; if (!Wrapper) continue; const wrapper = new Wrapper(renderer, block, parent, child, strip_whitespace, last_child || next_sibling);