index.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. class Interpreter {
  2. constructor(root) {
  3. this.root = root;
  4. this.stack = [root];
  5. this.listeners = {
  6. "onclick": {}
  7. };
  8. this.lastNodeWasText = false;
  9. this.nodes = [root];
  10. }
  11. top() {
  12. return this.stack[this.stack.length - 1];
  13. }
  14. pop() {
  15. return this.stack.pop();
  16. }
  17. PushRoot(edit) {
  18. const id = edit.root;
  19. const node = this.nodes[id];
  20. this.stack.push(node);
  21. }
  22. PopRoot(_edit) {
  23. this.stack.pop();
  24. }
  25. AppendChildren(edit) {
  26. let root = this.stack[this.stack.length - (1 + edit.many)];
  27. let to_add = this.stack.splice(this.stack.length - edit.many);
  28. for (let i = 0; i < edit.many; i++) {
  29. root.appendChild(to_add[i]);
  30. }
  31. }
  32. ReplaceWith(edit) {
  33. // console.log(edit);
  34. let root = this.nodes[edit.root];
  35. let els = this.stack.splice(this.stack.length - edit.m);
  36. // console.log(root);
  37. // console.log(els);
  38. root.replaceWith(...els);
  39. }
  40. InsertAfter(edit) {
  41. let old = this.nodes[edit.root];
  42. let new_nodes = this.stack.splice(this.stack.length - edit.n);
  43. old.after(...new_nodes);
  44. }
  45. InsertBefore(edit) {
  46. let old = this.nodes[edit.root];
  47. let new_nodes = this.stack.splice(this.stack.length - edit.n);
  48. old.before(...new_nodes);
  49. }
  50. Remove(edit) {
  51. let node = this.nodes[edit.root];
  52. if (node !== undefined) {
  53. node.remove();
  54. }
  55. }
  56. CreateTextNode(edit) {
  57. const node = document.createTextNode(edit.text);
  58. this.nodes[edit.root] = node;
  59. this.stack.push(node);
  60. }
  61. CreateElement(edit) {
  62. const tagName = edit.tag;
  63. const el = document.createElement(tagName);
  64. this.nodes[edit.root] = el;
  65. this.stack.push(el);
  66. }
  67. CreateElementNs(edit) {
  68. let el = document.createElementNS(edit.ns, edit.tag);
  69. this.stack.push(el);
  70. this.nodes[edit.root] = el;
  71. }
  72. CreatePlaceholder(edit) {
  73. let el = document.createElement("pre");
  74. this.stack.push(el);
  75. this.nodes[edit.root] = el;
  76. }
  77. RemoveEventListener(edit) { }
  78. NewEventListener(edit) {
  79. const event_name = edit.event_name;
  80. const mounted_node_id = edit.root;
  81. const scope = edit.scope;
  82. const element = this.nodes[edit.root]
  83. element.setAttribute(`dioxus-event-${event_name}`, `${scope}.${mounted_node_id}`);
  84. if (this.listeners[event_name] === undefined) {
  85. this.listeners[event_name] = "bla";
  86. this.root.addEventListener(event_name, (event) => {
  87. // console.log("CLICKED");
  88. const target = event.target;
  89. const val = target.getAttribute(`dioxus-event-${event_name}`);
  90. if (val == null) {
  91. return;
  92. }
  93. const fields = val.split(".");
  94. const scope_id = parseInt(fields[0]);
  95. const real_id = parseInt(fields[1]);
  96. // // console.log(`parsed event with scope_id ${scope_id} and real_id ${real_id}`);
  97. // console.log("message fired");
  98. let contents = serialize_event(event);
  99. let evt = {
  100. event: event_name,
  101. scope: scope_id,
  102. mounted_dom_id: real_id,
  103. contents: contents,
  104. };
  105. // console.log(evt);
  106. rpc.call('user_event', evt).then((reply) => {
  107. // console.log("reply received", reply);
  108. this.stack.push(this.root);
  109. reply.map((reply) => {
  110. let edits = reply.edits;
  111. for (let x = 0; x < edits.length; x++) {
  112. let edit = edits[x];
  113. let f = this[edit.type];
  114. f.call(this, edit);
  115. }
  116. });
  117. })
  118. });
  119. }
  120. }
  121. SetText(edit) {
  122. this.nodes[edit.root].textContent = edit.text;
  123. }
  124. SetAttribute(edit) {
  125. // console.log("setting attr", edit);
  126. const name = edit.field;
  127. const value = edit.value;
  128. const ns = edit.ns;
  129. const node = this.nodes[edit.root]
  130. if (ns == "style") {
  131. node.style[name] = value;
  132. } else if ((ns != null) || (ns != undefined)) {
  133. node.setAttributeNS(ns, name, value);
  134. } else {
  135. switch (name) {
  136. case "value":
  137. node.value = value;
  138. break;
  139. case "checked":
  140. // console.log("setting checked");
  141. node.checked = (value === "true");
  142. break;
  143. case "selected":
  144. node.selected = (value === "true");
  145. break;
  146. case "dangerous_inner_html":
  147. node.innerHTML = value;
  148. break;
  149. default:
  150. // console.log("setting attr directly ", name, value);
  151. node.setAttribute(name, value);
  152. }
  153. }
  154. }
  155. RemoveAttribute(edit) {
  156. const name = edit.field;
  157. const node = this.nodes[edit.root];
  158. node.removeAttribute(name);
  159. if (name === "value") {
  160. node.value = null;
  161. }
  162. if (name === "checked") {
  163. node.checked = false;
  164. }
  165. if (name === "selected") {
  166. node.selected = false;
  167. }
  168. }
  169. }
  170. async function initialize() {
  171. let root = window.document.getElementById("_dioxusroot");
  172. const interpreter = new Interpreter(root);
  173. const reply = await rpc.call('initiate');
  174. let pre_rendered = reply.pre_rendered;
  175. if (pre_rendered !== undefined) {
  176. root.innerHTML = pre_rendered;
  177. }
  178. const edits = reply.edits;
  179. apply_edits(edits, interpreter);
  180. }
  181. function apply_edits(edits, interpreter) {
  182. // console.log(edits);
  183. for (let x = 0; x < edits.length; x++) {
  184. let edit = edits[x];
  185. let f = interpreter[edit.type];
  186. f.call(interpreter, edit);
  187. }
  188. // // console.log("stack completed: ", interpreter.stack);
  189. }
  190. function serialize_event(event) {
  191. let serializer = SerializeMap[event.type];
  192. if (serializer === undefined) {
  193. return {};
  194. } else {
  195. return serializer(event);
  196. }
  197. }
  198. const SerializeMap = {
  199. "copy": serialize_clipboard,
  200. "cut": serialize_clipboard,
  201. "paste": serialize_clipboard,
  202. "compositionend": serialize_composition,
  203. "compositionstart": serialize_composition,
  204. "compositionupdate": serialize_composition,
  205. "keydown": serialize_keyboard,
  206. "keypress": serialize_keyboard,
  207. "keyup": serialize_keyboard,
  208. "focus": serialize_focus,
  209. "blur": serialize_focus,
  210. // "change": serialize_form,
  211. "change": serialize_change,
  212. "input": serialize_form,
  213. "invalid": serialize_form,
  214. "reset": serialize_form,
  215. "submit": serialize_form,
  216. "click": serialize_mouse,
  217. "contextmenu": serialize_mouse,
  218. "doubleclick": serialize_mouse,
  219. "drag": serialize_mouse,
  220. "dragend": serialize_mouse,
  221. "dragenter": serialize_mouse,
  222. "dragexit": serialize_mouse,
  223. "dragleave": serialize_mouse,
  224. "dragover": serialize_mouse,
  225. "dragstart": serialize_mouse,
  226. "drop": serialize_mouse,
  227. "mousedown": serialize_mouse,
  228. "mouseenter": serialize_mouse,
  229. "mouseleave": serialize_mouse,
  230. "mousemove": serialize_mouse,
  231. "mouseout": serialize_mouse,
  232. "mouseover": serialize_mouse,
  233. "mouseup": serialize_mouse,
  234. "pointerdown": serialize_pointer,
  235. "pointermove": serialize_pointer,
  236. "pointerup": serialize_pointer,
  237. "pointercancel": serialize_pointer,
  238. "gotpointercapture": serialize_pointer,
  239. "lostpointercapture": serialize_pointer,
  240. "pointerenter": serialize_pointer,
  241. "pointerleave": serialize_pointer,
  242. "pointerover": serialize_pointer,
  243. "pointerout": serialize_pointer,
  244. "select": serialize_selection,
  245. "touchcancel": serialize_touch,
  246. "touchend": serialize_touch,
  247. "touchmove": serialize_touch,
  248. "touchstart": serialize_touch,
  249. "scroll": serialize_scroll,
  250. "wheel": serialize_wheel,
  251. "animationstart": serialize_animation,
  252. "animationend": serialize_animation,
  253. "animationiteration": serialize_animation,
  254. "transitionend": serialize_transition,
  255. "abort": serialize_media,
  256. "canplay": serialize_media,
  257. "canplaythrough": serialize_media,
  258. "durationchange": serialize_media,
  259. "emptied": serialize_media,
  260. "encrypted": serialize_media,
  261. "ended": serialize_media,
  262. "error": serialize_media,
  263. "loadeddata": serialize_media,
  264. "loadedmetadata": serialize_media,
  265. "loadstart": serialize_media,
  266. "pause": serialize_media,
  267. "play": serialize_media,
  268. "playing": serialize_media,
  269. "progress": serialize_media,
  270. "ratechange": serialize_media,
  271. "seeked": serialize_media,
  272. "seeking": serialize_media,
  273. "stalled": serialize_media,
  274. "suspend": serialize_media,
  275. "timeupdate": serialize_media,
  276. "volumechange": serialize_media,
  277. "waiting": serialize_media,
  278. "toggle": serialize_toggle
  279. }
  280. function serialize_clipboard(_event) {
  281. return {};
  282. }
  283. function serialize_composition(event) {
  284. return {
  285. data: event.data
  286. }
  287. }
  288. function serialize_keyboard(event) {
  289. return {
  290. char_code: event.charCode,
  291. key: event.key,
  292. alt_key: event.altKey,
  293. ctrl_key: event.ctrlKey,
  294. meta_key: event.metaKey,
  295. key_code: event.keyCode,
  296. shift_key: event.shiftKey,
  297. locale: "locale",
  298. // locale: event.locale,
  299. location: event.location,
  300. repeat: event.repeat,
  301. which: event.which,
  302. }
  303. }
  304. function serialize_focus(_event) {
  305. return {}
  306. }
  307. function serialize_change(event) {
  308. let target = event.target;
  309. let value;
  310. if (target.type === "checkbox" || target.type === "radio") {
  311. value = target.checked ? "true" : "false";
  312. } else {
  313. value = target.value ?? target.textContent;
  314. }
  315. return {
  316. value: value
  317. }
  318. }
  319. function serialize_form(event) {
  320. let target = event.target;
  321. let value = target.value ?? target.textContent;
  322. return {
  323. value: value
  324. }
  325. }
  326. function serialize_mouse(event) {
  327. return {
  328. alt_key: event.altKey,
  329. button: event.button,
  330. buttons: event.buttons,
  331. client_x: event.clientX,
  332. client_y: event.clientY,
  333. ctrl_key: event.ctrlKey,
  334. meta_key: event.metaKey,
  335. page_x: event.pageX,
  336. page_y: event.pageY,
  337. screen_x: event.screenX,
  338. screen_y: event.screenY,
  339. shift_key: event.shiftKey,
  340. }
  341. }
  342. function serialize_pointer(event) {
  343. return {
  344. alt_key: event.altKey,
  345. button: event.button,
  346. buttons: event.buttons,
  347. client_x: event.clientX,
  348. client_y: event.clientY,
  349. ctrl_key: event.ctrlKey,
  350. meta_key: event.metaKey,
  351. page_x: event.pageX,
  352. page_y: event.pageY,
  353. screen_x: event.screenX,
  354. screen_y: event.screenY,
  355. shift_key: event.shiftKey,
  356. pointer_id: event.pointerId,
  357. width: event.width,
  358. height: event.height,
  359. pressure: event.pressure,
  360. tangential_pressure: event.tangentialPressure,
  361. tilt_x: event.tiltX,
  362. tilt_y: event.tiltY,
  363. twist: event.twist,
  364. pointer_type: event.pointerType,
  365. is_primary: event.isPrimary,
  366. }
  367. }
  368. function serialize_selection(event) {
  369. return {}
  370. }
  371. function serialize_touch(event) {
  372. return {
  373. alt_key: event.altKey,
  374. ctrl_key: event.ctrlKey,
  375. meta_key: event.metaKey,
  376. shift_key: event.shiftKey,
  377. // changed_touches: event.changedTouches,
  378. // target_touches: event.targetTouches,
  379. // touches: event.touches,
  380. }
  381. }
  382. function serialize_scroll(event) {
  383. return {}
  384. }
  385. function serialize_wheel(event) {
  386. return {
  387. delta_x: event.deltaX,
  388. delta_y: event.deltaY,
  389. delta_z: event.deltaZ,
  390. delta_mode: event.deltaMode,
  391. }
  392. }
  393. function serialize_animation(event) {
  394. return {
  395. animation_name: event.animationName,
  396. elapsed_time: event.elapsedTime,
  397. pseudo_element: event.pseudoElement,
  398. }
  399. }
  400. function serialize_transition(event) {
  401. return {
  402. property_name: event.propertyName,
  403. elapsed_time: event.elapsedTime,
  404. pseudo_element: event.pseudoElement,
  405. }
  406. }
  407. function serialize_media(event) {
  408. return {}
  409. }
  410. function serialize_toggle(event) {
  411. return {}
  412. }
  413. initialize();