create.rs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. use crate::any_props::AnyProps;
  2. use crate::innerlude::{VComponent, VPlaceholder, VText};
  3. use crate::mutations::Mutation;
  4. use crate::mutations::Mutation::*;
  5. use crate::nodes::VNode;
  6. use crate::nodes::{DynamicNode, TemplateNode};
  7. use crate::virtual_dom::VirtualDom;
  8. use crate::{AttributeValue, ElementId, RenderReturn, ScopeId, SuspenseContext, Template};
  9. use std::cell::Cell;
  10. use std::iter::Peekable;
  11. use std::rc::Rc;
  12. use TemplateNode::*;
  13. fn sort_bfs(paths: &[&'static [u8]]) -> Vec<(usize, &'static [u8])> {
  14. let mut with_indecies = paths.iter().copied().enumerate().collect::<Vec<_>>();
  15. with_indecies.sort_unstable_by(|(_, a), (_, b)| {
  16. let mut a = a.iter();
  17. let mut b = b.iter();
  18. loop {
  19. match (a.next(), b.next()) {
  20. (Some(a), Some(b)) => {
  21. if a != b {
  22. return a.cmp(b);
  23. }
  24. }
  25. // The shorter path goes first
  26. (Some(_), None) => return std::cmp::Ordering::Less,
  27. (None, Some(_)) => return std::cmp::Ordering::Greater,
  28. (None, None) => return std::cmp::Ordering::Equal,
  29. }
  30. }
  31. });
  32. with_indecies
  33. }
  34. #[test]
  35. fn sorting() {
  36. let r: [(usize, &[u8]); 5] = [
  37. (0, &[0, 1]),
  38. (1, &[0, 2]),
  39. (2, &[1, 0]),
  40. (4, &[1, 1]),
  41. (3, &[1, 2]),
  42. ];
  43. assert_eq!(
  44. sort_bfs(&[&[0, 1,], &[0, 2,], &[1, 0,], &[1, 2,], &[1, 1,],]),
  45. r
  46. );
  47. assert!(matches!(&[0], &[_, ..]))
  48. }
  49. impl<'b> VirtualDom {
  50. /// Create a new template [`VNode`] and write it to the [`Mutations`] buffer.
  51. ///
  52. /// This method pushes the ScopeID to the internal scopestack and returns the number of nodes created.
  53. pub(crate) fn create_scope(&mut self, scope: ScopeId, template: &'b VNode<'b>) -> usize {
  54. self.scope_stack.push(scope);
  55. let out = self.create(template);
  56. self.scope_stack.pop();
  57. out
  58. }
  59. /// Create this template and write its mutations
  60. pub(crate) fn create(&mut self, node: &'b VNode<'b>) -> usize {
  61. // check for a overriden template
  62. #[cfg(debug_assertions)]
  63. {
  64. let (path, byte_index) = node.template.get().name.rsplit_once(':').unwrap();
  65. if let Some(template) = self
  66. .templates
  67. .get(path)
  68. .and_then(|map| map.get(&byte_index.parse().unwrap()))
  69. {
  70. node.template.set(*template);
  71. }
  72. }
  73. // Intialize the root nodes slice
  74. node.root_ids
  75. .intialize(vec![ElementId(0); node.template.get().roots.len()].into_boxed_slice());
  76. // The best renderers will have templates prehydrated and registered
  77. // Just in case, let's create the template using instructions anyways
  78. if !self.templates.contains_key(&node.template.get().name) {
  79. self.register_template(node.template.get());
  80. }
  81. // we know that this will generate at least one mutation per node
  82. self.mutations
  83. .edits
  84. .reserve(node.template.get().roots.len());
  85. // Walk the roots, creating nodes and assigning IDs
  86. // nodes in an iterator of ((dynamic_node_index, sorted_index), path)
  87. // todo: adjust dynamic nodes to be in the order of roots and then leaves (ie BFS)
  88. #[cfg(not(debug_assertions))]
  89. let (mut attrs, mut nodes) = (
  90. node.template
  91. .get()
  92. .attr_paths
  93. .iter()
  94. .copied()
  95. .enumerate()
  96. .peekable(),
  97. node.template
  98. .get()
  99. .node_paths
  100. .iter()
  101. .copied()
  102. .enumerate()
  103. .map(|(i, path)| ((i, i), path))
  104. .peekable(),
  105. );
  106. // If this is a debug build, we need to check that the paths are in the correct order because hot reloading can cause scrambled states
  107. #[cfg(debug_assertions)]
  108. let (attrs_sorted, nodes_sorted) = {
  109. (
  110. sort_bfs(node.template.get().attr_paths),
  111. sort_bfs(node.template.get().node_paths),
  112. )
  113. };
  114. #[cfg(debug_assertions)]
  115. let (mut attrs, mut nodes) = {
  116. (
  117. attrs_sorted.into_iter().peekable(),
  118. nodes_sorted
  119. .iter()
  120. .copied()
  121. .enumerate()
  122. .map(|(i, (id, path))| ((id, i), path))
  123. .peekable(),
  124. )
  125. };
  126. node.template
  127. .get()
  128. .roots
  129. .iter()
  130. .enumerate()
  131. .map(|(idx, root)| match root {
  132. DynamicText { id } | Dynamic { id } => {
  133. nodes.next().unwrap();
  134. self.write_dynamic_root(node, *id)
  135. }
  136. Element { .. } => {
  137. #[cfg(not(debug_assertions))]
  138. let id = self.write_element_root(node, idx, &mut attrs, &mut nodes, &[]);
  139. #[cfg(debug_assertions)]
  140. let id =
  141. self.write_element_root(node, idx, &mut attrs, &mut nodes, &nodes_sorted);
  142. id
  143. }
  144. Text { .. } => self.write_static_text_root(node, idx),
  145. })
  146. .sum()
  147. }
  148. fn write_static_text_root(&mut self, node: &VNode, idx: usize) -> usize {
  149. // Simply just load the template root, no modifications needed
  150. self.load_template_root(node, idx);
  151. // Text producs just one node on the stack
  152. 1
  153. }
  154. fn write_dynamic_root(&mut self, template: &'b VNode<'b>, idx: usize) -> usize {
  155. use DynamicNode::*;
  156. match &template.dynamic_nodes[idx] {
  157. node @ Component { .. } | node @ Fragment(_) => {
  158. self.create_dynamic_node(template, node, idx)
  159. }
  160. Placeholder(VPlaceholder { id }) => {
  161. let id = self.set_slot(template, id, idx);
  162. self.mutations.push(CreatePlaceholder { id });
  163. 1
  164. }
  165. Text(VText { id, value }) => {
  166. let id = self.set_slot(template, id, idx);
  167. self.create_static_text(value, id);
  168. 1
  169. }
  170. }
  171. }
  172. fn create_static_text(&mut self, value: &str, id: ElementId) {
  173. // Safety: we promise not to re-alias this text later on after committing it to the mutation
  174. let unbounded_text: &str = unsafe { std::mem::transmute(value) };
  175. self.mutations.push(CreateTextNode {
  176. value: unbounded_text,
  177. id,
  178. });
  179. }
  180. /// We write all the descndent data for this element
  181. ///
  182. /// Elements can contain other nodes - and those nodes can be dynamic or static
  183. ///
  184. /// We want to make sure we write these nodes while on top of the root
  185. fn write_element_root(
  186. &mut self,
  187. template: &'b VNode<'b>,
  188. root_idx: usize,
  189. dynamic_attrs: &mut Peekable<impl Iterator<Item = (usize, &'static [u8])>>,
  190. dynamic_nodes_iter: &mut Peekable<impl Iterator<Item = ((usize, usize), &'static [u8])>>,
  191. dynamic_nodes: &[(usize, &'static [u8])],
  192. ) -> usize {
  193. // Load the template root and get the ID for the node on the stack
  194. let root_on_stack = self.load_template_root(template, root_idx);
  195. // Write all the attributes below this root
  196. self.write_attrs_on_root(dynamic_attrs, root_idx as u8, root_on_stack, template);
  197. // Load in all of the placeholder or dynamic content under this root too
  198. self.load_placeholders(dynamic_nodes_iter, dynamic_nodes, root_idx as u8, template);
  199. 1
  200. }
  201. /// Load all of the placeholder nodes for descendents of this root node
  202. ///
  203. /// ```rust, ignore
  204. /// rsx! {
  205. /// div {
  206. /// // This is a placeholder
  207. /// some_value,
  208. ///
  209. /// // Load this too
  210. /// "{some_text}"
  211. /// }
  212. /// }
  213. /// ```
  214. #[allow(unused)]
  215. fn load_placeholders(
  216. &mut self,
  217. dynamic_nodes_iter: &mut Peekable<impl Iterator<Item = ((usize, usize), &'static [u8])>>,
  218. dynamic_nodes: &[(usize, &'static [u8])],
  219. root_idx: u8,
  220. template: &'b VNode<'b>,
  221. ) {
  222. let (start, end) = match collect_dyn_node_range(dynamic_nodes_iter, root_idx) {
  223. Some((a, b)) => (a, b),
  224. None => return,
  225. };
  226. // If hot reloading is enabled, we need to map the sorted index to the original index of the dynamic node. If it is disabled, we can just use the sorted index
  227. #[cfg(not(debug_assertions))]
  228. let reversed_iter = (start..=end).rev();
  229. #[cfg(debug_assertions)]
  230. let reversed_iter = (start..=end)
  231. .rev()
  232. .map(|sorted_index| dynamic_nodes[sorted_index].0);
  233. for idx in reversed_iter {
  234. let m = self.create_dynamic_node(template, &template.dynamic_nodes[idx], idx);
  235. if m > 0 {
  236. // The path is one shorter because the top node is the root
  237. let path = &template.template.get().node_paths[idx][1..];
  238. self.mutations.push(ReplacePlaceholder { m, path });
  239. }
  240. }
  241. }
  242. fn write_attrs_on_root(
  243. &mut self,
  244. attrs: &mut Peekable<impl Iterator<Item = (usize, &'static [u8])>>,
  245. root_idx: u8,
  246. root: ElementId,
  247. node: &VNode,
  248. ) {
  249. while let Some((mut attr_id, path)) =
  250. attrs.next_if(|(_, p)| p.first().copied() == Some(root_idx))
  251. {
  252. let id = self.assign_static_node_as_dynamic(path, root, node, attr_id);
  253. loop {
  254. self.write_attribute(&node.dynamic_attrs[attr_id], id);
  255. // Only push the dynamic attributes forward if they match the current path (same element)
  256. match attrs.next_if(|(_, p)| *p == path) {
  257. Some((next_attr_id, _)) => attr_id = next_attr_id,
  258. None => break,
  259. }
  260. }
  261. }
  262. }
  263. fn write_attribute(&mut self, attribute: &crate::Attribute, id: ElementId) {
  264. // Make sure we set the attribute's associated id
  265. attribute.mounted_element.set(id);
  266. // Safety: we promise not to re-alias this text later on after committing it to the mutation
  267. let unbounded_name: &str = unsafe { std::mem::transmute(attribute.name) };
  268. // match &attribute.value {
  269. // AttributeValue::Text(value) => {
  270. // // Safety: we promise not to re-alias this text later on after committing it to the mutation
  271. // let unbounded_value: &str = unsafe { std::mem::transmute(*value) };
  272. // self.mutations.push(SetAttribute {
  273. // name: unbounded_name,
  274. // value: unbounded_value,
  275. // ns: attribute.namespace,
  276. // id,
  277. // })
  278. // }
  279. // AttributeValue::Bool(value) => self.mutations.push(SetBoolAttribute {
  280. // name: unbounded_name,
  281. // value: *value,
  282. // id,
  283. // }),
  284. // AttributeValue::Listener(_) => {
  285. // self.mutations.push(NewEventListener {
  286. // // all listeners start with "on"
  287. // name: &unbounded_name[2..],
  288. // id,
  289. // })
  290. // }
  291. // _ => {
  292. // }
  293. // AttributeValue::Float(_) => todo!(),
  294. // AttributeValue::Int(_) => todo!(),
  295. // AttributeValue::Any() => todo!(),
  296. // AttributeValue::None => todo!(),
  297. // }
  298. // Safety: we promise not to re-alias this text later on after committing it to the mutation
  299. match &attribute.value {
  300. AttributeValue::Listener(_) => {
  301. self.mutations.push(NewEventListener {
  302. // all listeners start with "on"
  303. name: &unbounded_name[2..],
  304. id,
  305. })
  306. }
  307. _ => {
  308. // Safety: we promise not to re-alias this text later on after committing it to the mutation
  309. let unbounded_value = unsafe { std::mem::transmute(attribute.value.clone()) };
  310. self.mutations.push(SetAttribute {
  311. name: unbounded_name,
  312. value: unbounded_value,
  313. ns: attribute.namespace,
  314. id,
  315. })
  316. }
  317. }
  318. }
  319. fn load_template_root(&mut self, template: &VNode, root_idx: usize) -> ElementId {
  320. // Get an ID for this root since it's a real root
  321. let this_id = self.next_root(template, root_idx);
  322. template.root_ids.set(root_idx, this_id);
  323. self.mutations.push(LoadTemplate {
  324. name: template.template.get().name,
  325. index: root_idx,
  326. id: this_id,
  327. });
  328. this_id
  329. }
  330. /// We have some dynamic attributes attached to a some node
  331. ///
  332. /// That node needs to be loaded at runtime, so we need to give it an ID
  333. ///
  334. /// If the node in question is on the stack, we just return that ID
  335. ///
  336. /// If the node is not on the stack, we create a new ID for it and assign it
  337. fn assign_static_node_as_dynamic(
  338. &mut self,
  339. path: &'static [u8],
  340. this_id: ElementId,
  341. template: &VNode,
  342. attr_id: usize,
  343. ) -> ElementId {
  344. if path.len() == 1 {
  345. return this_id;
  346. }
  347. // if attribute is on a root node, then we've already created the element
  348. // Else, it's deep in the template and we should create a new id for it
  349. let id = self.next_element(template, template.template.get().attr_paths[attr_id]);
  350. self.mutations.push(Mutation::AssignId {
  351. path: &path[1..],
  352. id,
  353. });
  354. id
  355. }
  356. /// Insert a new template into the VirtualDom's template registry
  357. pub(crate) fn register_template_first_byte_index(&mut self, mut template: Template<'static>) {
  358. // First, make sure we mark the template as seen, regardless if we process it
  359. let (path, _) = template.name.rsplit_once(':').unwrap();
  360. if let Some((_, old_template)) = self
  361. .templates
  362. .entry(path)
  363. .or_default()
  364. .iter_mut()
  365. .min_by_key(|(byte_index, _)| **byte_index)
  366. {
  367. // the byte index of the hot reloaded template could be different
  368. template.name = old_template.name;
  369. *old_template = template;
  370. } else {
  371. // This is a template without any current instances
  372. self.templates
  373. .entry(path)
  374. .or_default()
  375. .insert(usize::MAX, template);
  376. }
  377. // If it's all dynamic nodes, then we don't need to register it
  378. if !template.is_completely_dynamic() {
  379. self.mutations.templates.push(template);
  380. }
  381. }
  382. /// Insert a new template into the VirtualDom's template registry
  383. pub(crate) fn register_template(&mut self, mut template: Template<'static>) {
  384. // First, make sure we mark the template as seen, regardless if we process it
  385. let (path, byte_index) = template.name.rsplit_once(':').unwrap();
  386. let byte_index = byte_index.parse::<usize>().unwrap();
  387. // if hot reloading is enabled, then we need to check for a template that has overriten this one
  388. #[cfg(debug_assertions)]
  389. if let Some(mut new_template) = self
  390. .templates
  391. .get_mut(path)
  392. .and_then(|map| map.remove(&usize::MAX))
  393. {
  394. // the byte index of the hot reloaded template could be different
  395. new_template.name = template.name;
  396. template = new_template;
  397. }
  398. self.templates
  399. .entry(path)
  400. .or_default()
  401. .insert(byte_index, template);
  402. // If it's all dynamic nodes, then we don't need to register it
  403. if !template.is_completely_dynamic() {
  404. self.mutations.templates.push(template);
  405. }
  406. }
  407. pub(crate) fn create_dynamic_node(
  408. &mut self,
  409. template: &'b VNode<'b>,
  410. node: &'b DynamicNode<'b>,
  411. idx: usize,
  412. ) -> usize {
  413. use DynamicNode::*;
  414. match node {
  415. Text(text) => self.create_dynamic_text(template, text, idx),
  416. Placeholder(place) => self.create_placeholder(place, template, idx),
  417. Component(component) => self.create_component_node(template, component, idx),
  418. Fragment(frag) => frag.iter().map(|child| self.create(child)).sum(),
  419. }
  420. }
  421. fn create_dynamic_text(
  422. &mut self,
  423. template: &'b VNode<'b>,
  424. text: &'b VText<'b>,
  425. idx: usize,
  426. ) -> usize {
  427. // Allocate a dynamic element reference for this text node
  428. let new_id = self.next_element(template, template.template.get().node_paths[idx]);
  429. // Make sure the text node is assigned to the correct element
  430. text.id.set(Some(new_id));
  431. // Safety: we promise not to re-alias this text later on after committing it to the mutation
  432. let value = unsafe { std::mem::transmute(text.value) };
  433. // Add the mutation to the list
  434. self.mutations.push(HydrateText {
  435. id: new_id,
  436. path: &template.template.get().node_paths[idx][1..],
  437. value,
  438. });
  439. // Since we're hydrating an existing node, we don't create any new nodes
  440. 0
  441. }
  442. pub(crate) fn create_placeholder(
  443. &mut self,
  444. placeholder: &VPlaceholder,
  445. template: &'b VNode<'b>,
  446. idx: usize,
  447. ) -> usize {
  448. // Allocate a dynamic element reference for this text node
  449. let id = self.next_element(template, template.template.get().node_paths[idx]);
  450. // Make sure the text node is assigned to the correct element
  451. placeholder.id.set(Some(id));
  452. // Assign the ID to the existing node in the template
  453. self.mutations.push(AssignId {
  454. path: &template.template.get().node_paths[idx][1..],
  455. id,
  456. });
  457. // Since the placeholder is already in the DOM, we don't create any new nodes
  458. 0
  459. }
  460. pub(super) fn create_component_node(
  461. &mut self,
  462. template: &'b VNode<'b>,
  463. component: &'b VComponent<'b>,
  464. idx: usize,
  465. ) -> usize {
  466. use RenderReturn::*;
  467. // Load up a ScopeId for this vcomponent
  468. let scope = self.load_scope_from_vcomponent(component);
  469. component.scope.set(Some(scope));
  470. match unsafe { self.run_scope(scope).extend_lifetime_ref() } {
  471. Ready(t) => self.mount_component(scope, template, t, idx),
  472. Aborted(t) => self.mount_aborted(template, t),
  473. Pending(_) => self.mount_async(template, idx, scope),
  474. }
  475. }
  476. /// Load a scope from a vcomponent. If the props don't exist, that means the component is currently "live"
  477. fn load_scope_from_vcomponent(&mut self, component: &VComponent) -> ScopeId {
  478. component
  479. .props
  480. .take()
  481. .map(|props| {
  482. let unbounded_props: Box<dyn AnyProps> = unsafe { std::mem::transmute(props) };
  483. self.new_scope(unbounded_props, component.name).id
  484. })
  485. .unwrap_or_else(|| component.scope.get().unwrap())
  486. }
  487. fn mount_component(
  488. &mut self,
  489. scope: ScopeId,
  490. parent: &'b VNode<'b>,
  491. new: &'b VNode<'b>,
  492. idx: usize,
  493. ) -> usize {
  494. // Keep track of how many mutations are in the buffer in case we need to split them out if a suspense boundary
  495. // is encountered
  496. let mutations_to_this_point = self.mutations.edits.len();
  497. // Create the component's root element
  498. let created = self.create_scope(scope, new);
  499. // If there are no suspense leaves below us, then just don't bother checking anything suspense related
  500. if self.collected_leaves.is_empty() {
  501. return created;
  502. }
  503. // If running the scope has collected some leaves and *this* component is a boundary, then handle the suspense
  504. let boundary = match self.scopes[scope.0].has_context::<Rc<SuspenseContext>>() {
  505. Some(boundary) => boundary,
  506. _ => return created,
  507. };
  508. // Since this is a boundary, use its placeholder within the template as the placeholder for the suspense tree
  509. let new_id = self.next_element(new, parent.template.get().node_paths[idx]);
  510. // Now connect everything to the boundary
  511. self.scopes[scope.0].placeholder.set(Some(new_id));
  512. // This involves breaking off the mutations to this point, and then creating a new placeholder for the boundary
  513. // Note that we break off dynamic mutations only - since static mutations aren't rendered immediately
  514. let split_off = unsafe {
  515. std::mem::transmute::<Vec<Mutation>, Vec<Mutation>>(
  516. self.mutations.edits.split_off(mutations_to_this_point),
  517. )
  518. };
  519. boundary.mutations.borrow_mut().edits.extend(split_off);
  520. boundary.created_on_stack.set(created);
  521. boundary
  522. .waiting_on
  523. .borrow_mut()
  524. .extend(self.collected_leaves.drain(..));
  525. // Now assign the placeholder in the DOM
  526. self.mutations.push(AssignId {
  527. id: new_id,
  528. path: &parent.template.get().node_paths[idx][1..],
  529. });
  530. 0
  531. }
  532. fn mount_aborted(&mut self, parent: &'b VNode<'b>, placeholder: &VPlaceholder) -> usize {
  533. let id = self.next_element(parent, &[]);
  534. self.mutations.push(Mutation::CreatePlaceholder { id });
  535. placeholder.id.set(Some(id));
  536. 1
  537. }
  538. /// Take the rendered nodes from a component and handle them if they were async
  539. ///
  540. /// IE simply assign an ID to the placeholder
  541. fn mount_async(&mut self, template: &VNode, idx: usize, scope: ScopeId) -> usize {
  542. let new_id = self.next_element(template, template.template.get().node_paths[idx]);
  543. // Set the placeholder of the scope
  544. self.scopes[scope.0].placeholder.set(Some(new_id));
  545. // Since the placeholder is already in the DOM, we don't create any new nodes
  546. self.mutations.push(AssignId {
  547. id: new_id,
  548. path: &template.template.get().node_paths[idx][1..],
  549. });
  550. 0
  551. }
  552. fn set_slot(
  553. &mut self,
  554. template: &'b VNode<'b>,
  555. slot: &'b Cell<Option<ElementId>>,
  556. id: usize,
  557. ) -> ElementId {
  558. let id = self.next_element(template, template.template.get().node_paths[id]);
  559. slot.set(Some(id));
  560. id
  561. }
  562. }
  563. fn collect_dyn_node_range(
  564. dynamic_nodes: &mut Peekable<impl Iterator<Item = ((usize, usize), &'static [u8])>>,
  565. root_idx: u8,
  566. ) -> Option<(usize, usize)> {
  567. let start = match dynamic_nodes.peek() {
  568. Some(((_, idx), [first, ..])) if *first == root_idx => *idx,
  569. _ => return None,
  570. };
  571. let mut end = start;
  572. while let Some(((_, idx), p)) =
  573. dynamic_nodes.next_if(|(_, p)| matches!(p, [idx, ..] if *idx == root_idx))
  574. {
  575. if p.len() == 1 {
  576. continue;
  577. }
  578. end = idx;
  579. }
  580. Some((start, end))
  581. }