module Hyalite::Mount
Constants
- CHECKSUM_ATTR_NAME
- ID_ATTR_NAME
Public Class Methods
container_for_id(id)
click to toggle source
cf. ReactMount#findReactContainerForID
# File lib/hyalite/mount.rb, line 202 def container_for_id(id) root_id = InstanceHandles.root_id_from_node_id(id) @containers_by_root_id[root_id] end
contains_node(outer_node, inner_node)
click to toggle source
# File lib/hyalite/mount.rb, line 268 def contains_node(outer_node, inner_node) case when outer_node.nil? || inner_node.nil? false when outer_node == inner_node true when outer_node.text? false else contains_node(outer_node, inner_node.parent) end end
find_component_root(ancestor_node, target_id)
click to toggle source
# File lib/hyalite/mount.rb, line 227 def find_component_root(ancestor_node, target_id) deepest_ancestor = find_deepest_cached_ancestor(target_id) || ancestor_node first_children = [ deepest_ancestor.children.first ] while first_children.length > 0 child = first_children.shift while child child_id = node_id(child) if child_id if target_id == child_id return child elsif InstanceHandles.is_ancestor_id_of(child_id, target_id) first_children = [ child.children.first ] end else first_children.push(child.children.first) end child = child.next_sibling end end raise "can't find component_root ancestor_node: #{ancestor_node}, target_id: #{target_id}" end
find_deepest_cached_ancestor(target_id)
click to toggle source
# File lib/hyalite/mount.rb, line 254 def find_deepest_cached_ancestor(target_id) deepest_node_so_far = nil InstanceHandles.traverse_ancestors(target_id) do |ancestor_id| ancestor = node_cache[ancestor_id] if ancestor && is_valid(ancestor, ancestor_id) deepest_node_so_far = ancestor; else false end end deepest_node_so_far end
find_first_hyalite_dom(node)
click to toggle source
# File lib/hyalite/mount.rb, line 281 def find_first_hyalite_dom(node) while node && node.parent unless node.element? && node_id = internal_id(node) node = node.parent next end root_id = InstanceHandles.root_id_from_node_id(node_id) current = node loop do last_id = internal_id(current) return nil unless current = current.parent break if last_id == root_id end return node if current == @containers_by_root_id[root_id] node = node.parent end nil end
has_non_root_child(node)
click to toggle source
# File lib/hyalite/mount.rb, line 98 def has_non_root_child(node) root_id = root_id(container) root_id ? root_id != InstanceHandles.root_id_from_node_id(root_id) : false end
instances_by_root_id(root_id)
click to toggle source
# File lib/hyalite/mount.rb, line 21 def instances_by_root_id(root_id) @instances_by_root_id[root_id] end
internal_id(node)
click to toggle source
# File lib/hyalite/mount.rb, line 195 def internal_id(node) if node.element? node.attributes[ID_ATTR_NAME] end end
is_rendered(node)
click to toggle source
# File lib/hyalite/mount.rb, line 59 def is_rendered(node) return false unless node.element? id = node_id(node) id ? id[0] == Hyalite::Reconciler::SEPARATOR : false end
is_valid(node, id)
click to toggle source
# File lib/hyalite/mount.rb, line 216 def is_valid(node, id) if node container = @containers_by_root_id[id] if container && contains_node(container, node) return true end end false end
mount_component_into_node(component_instance, root_id, container, should_reuse_markup)
click to toggle source
# File lib/hyalite/mount.rb, line 133 def mount_component_into_node(component_instance, root_id, container, should_reuse_markup) Hyalite.updates.reconcile_transaction.perform do |transaction| markup = Reconciler.mount_component(component_instance, root_id, transaction.mount_ready, {}) component_instance.rendered_component.top_level_wrapper = component_instance mount_image_into_node(markup, container, should_reuse_markup) end end
mount_image_into_node(markup, container, should_reuse_markup)
click to toggle source
# File lib/hyalite/mount.rb, line 141 def mount_image_into_node(markup, container, should_reuse_markup) if should_reuse_markup root_element = root_element_in_container(container) checksum = Adler32.checksum markup checksum_attr = root_element.attributes[CHECKSUM_ATTR_NAME] if checksum == checksum_attr return end root_element.attributes.remove(CHECKSUM_ATTR_NAME) root_element.attributes[CHECKSUM_ATTR_NAME] = checksum end container.inner_dom = markup end
node(id)
click to toggle source
# File lib/hyalite/mount.rb, line 207 def node(id) node = node_cache[id] unless node && is_valid(node, id) root_id = InstanceHandles.root_id_from_node_id(id) node = node_cache[id] = find_component_root(@containers_by_root_id[root_id], id) end node end
node_cache()
click to toggle source
# File lib/hyalite/mount.rb, line 170 def node_cache @node_cache ||= {} end
node_id(node)
click to toggle source
# File lib/hyalite/mount.rb, line 178 def node_id(node) id = internal_id(node) if id if node_cache.has_key?(id) cached = node_cache[id] if cached != node #raise "Mount: Two valid but unequal nodes with the same `#{ID_ATTR_NAME}`: #{id}" node_cache[id] = node end else node_cache[id] = node end end id end
purge_id(id)
click to toggle source
# File lib/hyalite/mount.rb, line 174 def purge_id(id) @node_cache.delete(id) end
register_component(next_component, container)
click to toggle source
# File lib/hyalite/mount.rb, line 111 def register_component(next_component, container) #ReactBrowserEventEmitter.ensureScrollValueMonitoring(); root_id = register_container(container) @instances_by_root_id[root_id] = next_component; root_id end
register_container(container)
click to toggle source
# File lib/hyalite/mount.rb, line 119 def register_container(container) root_id = root_id(container) if root_id root_id = InstanceHandles.root_id_from_node_id(root_id) end unless root_id root_id = InstanceHandles.create_root_id end @containers_by_root_id[root_id] = container root_id end
render_new_root_component(next_element, container, should_reuse_markup)
click to toggle source
# File lib/hyalite/mount.rb, line 66 def render_new_root_component(next_element, container, should_reuse_markup) component_instance = Hyalite.instantiate_component(next_element) root_id = register_component(component_instance, container) Hyalite.updates.batched_updates do mount_component_into_node(component_instance, root_id, container, should_reuse_markup) end component_instance end
render_subtree_into_container(next_element, container) { |component| ... }
click to toggle source
# File lib/hyalite/mount.rb, line 25 def render_subtree_into_container(next_element, container, &block) next_wrapped_element = ElementObject.new(TopLevelWrapper, nil, nil, nil, next_element) prev_component = @instances_by_root_id[root_id(container)] if prev_component prev_wrapped_element = prev_component.current_element prev_element = prev_wrapped_element.props; if Reconciler.should_update_component(prev_element, next_element) return update_root_component( prev_component, next_wrapped_element, &block ).rendered_component.public_instance else unmount_component_at_node(container) end end root_element = root_element_in_container(container) container_has_markup = root_element && is_rendered(root_element) should_reuse_markup = container_has_markup && prev_component.nil? component = render_new_root_component( next_wrapped_element, container, should_reuse_markup ).rendered_component.public_instance if block_given? yield component end component end
root_element_in_container(container)
click to toggle source
# File lib/hyalite/mount.rb, line 157 def root_element_in_container(container) if container.document? container else container.children.first end end
root_id(container)
click to toggle source
# File lib/hyalite/mount.rb, line 165 def root_id(container) root_element = root_element_in_container(container) root_element && node_id(root_element) end
unmount_component_at_node(container)
click to toggle source
# File lib/hyalite/mount.rb, line 77 def unmount_component_at_node(container) root_id = root_id(container) component = @instances_by_root_id[root_id] unless component container_has_non_root_child = has_non_root_child(container) container_id = internal_id(container) container_id && container_id == InstanceHandles.root_id_from_node_id(container_id) return false end Hyalite.updates.batched_updates do unmount_component_from_node(component, container) end @instances_by_root_id.delete(root_id) @containers_by_root_id.delete(root_id) true end
unmount_component_from_node(instance, container)
click to toggle source
# File lib/hyalite/mount.rb, line 103 def unmount_component_from_node(instance, container) Reconciler.unmount_component(instance) while container.children.length > 0 container.children.last.remove end end
update_root_component(prev_component, next_element, &callback)
click to toggle source
# File lib/hyalite/mount.rb, line 305 def update_root_component(prev_component, next_element, &callback) UpdateQueue.enqueue_element_internal(prev_component, next_element) if block_given? UpdateQueue.enqueue_callback_internal(prev_component, &callback) end prev_component end