1
0

interpreter.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916
  1. class ListenerMap {
  2. constructor(root) {
  3. // bubbling events can listen at the root element
  4. this.global = {};
  5. // non bubbling events listen at the element the listener was created at
  6. this.local = {};
  7. this.root = root;
  8. }
  9. create(event_name, element, handler, bubbles) {
  10. if (bubbles) {
  11. if (this.global[event_name] === undefined) {
  12. this.global[event_name] = {};
  13. this.global[event_name].active = 1;
  14. this.global[event_name].callback = handler;
  15. this.root.addEventListener(event_name, handler);
  16. } else {
  17. this.global[event_name].active++;
  18. }
  19. } else {
  20. const id = element.getAttribute("data-dioxus-id");
  21. if (!this.local[id]) {
  22. this.local[id] = {};
  23. }
  24. this.local[id][event_name] = handler;
  25. element.addEventListener(event_name, handler);
  26. }
  27. }
  28. remove(element, event_name, bubbles) {
  29. if (bubbles) {
  30. this.global[event_name].active--;
  31. if (this.global[event_name].active === 0) {
  32. this.root.removeEventListener(
  33. event_name,
  34. this.global[event_name].callback
  35. );
  36. delete this.global[event_name];
  37. }
  38. } else {
  39. const id = element.getAttribute("data-dioxus-id");
  40. delete this.local[id][event_name];
  41. if (this.local[id].length === 0) {
  42. delete this.local[id];
  43. }
  44. element.removeEventListener(event_name, handler);
  45. }
  46. }
  47. removeAllNonBubbling(element) {
  48. const id = element.getAttribute("data-dioxus-id");
  49. delete this.local[id];
  50. }
  51. }
  52. class Interpreter {
  53. constructor(root) {
  54. this.root = root;
  55. this.listeners = new ListenerMap(root);
  56. this.nodes = [root];
  57. this.stack = [root];
  58. this.handlers = {};
  59. this.templates = {};
  60. this.lastNodeWasText = false;
  61. }
  62. top() {
  63. return this.stack[this.stack.length - 1];
  64. }
  65. pop() {
  66. return this.stack.pop();
  67. }
  68. MountToRoot() {
  69. this.AppendChildren(this.stack.length - 1);
  70. }
  71. SetNode(id, node) {
  72. this.nodes[id] = node;
  73. }
  74. PushRoot(root) {
  75. const node = this.nodes[root];
  76. this.stack.push(node);
  77. }
  78. PopRoot() {
  79. this.stack.pop();
  80. }
  81. AppendChildren(many) {
  82. // let root = this.nodes[id];
  83. let root = this.stack[this.stack.length - 1 - many];
  84. let to_add = this.stack.splice(this.stack.length - many);
  85. for (let i = 0; i < many; i++) {
  86. root.appendChild(to_add[i]);
  87. }
  88. }
  89. ReplaceWith(root_id, m) {
  90. let root = this.nodes[root_id];
  91. let els = this.stack.splice(this.stack.length - m);
  92. if (is_element_node(root.nodeType)) {
  93. this.listeners.removeAllNonBubbling(root);
  94. }
  95. root.replaceWith(...els);
  96. }
  97. InsertAfter(root, n) {
  98. let old = this.nodes[root];
  99. let new_nodes = this.stack.splice(this.stack.length - n);
  100. old.after(...new_nodes);
  101. }
  102. InsertBefore(root, n) {
  103. let old = this.nodes[root];
  104. let new_nodes = this.stack.splice(this.stack.length - n);
  105. old.before(...new_nodes);
  106. }
  107. Remove(root) {
  108. let node = this.nodes[root];
  109. if (node !== undefined) {
  110. if (is_element_node(node)) {
  111. this.listeners.removeAllNonBubbling(node);
  112. }
  113. node.remove();
  114. }
  115. }
  116. CreateTextNode(text, root) {
  117. const node = document.createTextNode(text);
  118. this.nodes[root] = node;
  119. this.stack.push(node);
  120. }
  121. CreatePlaceholder(root) {
  122. let el = document.createElement("pre");
  123. el.hidden = true;
  124. this.stack.push(el);
  125. this.nodes[root] = el;
  126. }
  127. NewEventListener(event_name, root, bubbles, handler) {
  128. const element = this.nodes[root];
  129. element.setAttribute("data-dioxus-id", `${root}`);
  130. this.listeners.create(event_name, element, handler, bubbles);
  131. }
  132. RemoveEventListener(root, event_name, bubbles) {
  133. const element = this.nodes[root];
  134. element.removeAttribute(`data-dioxus-id`);
  135. this.listeners.remove(element, event_name, bubbles);
  136. }
  137. SetText(root, text) {
  138. this.nodes[root].textContent = text;
  139. }
  140. SetAttribute(id, field, value, ns) {
  141. if (value === null) {
  142. this.RemoveAttribute(id, field, ns);
  143. } else {
  144. const node = this.nodes[id];
  145. this.SetAttributeInner(node, field, value, ns);
  146. }
  147. }
  148. SetAttributeInner(node, field, value, ns) {
  149. const name = field;
  150. if (ns === "style") {
  151. // ????? why do we need to do this
  152. if (node.style === undefined) {
  153. node.style = {};
  154. }
  155. node.style[name] = value;
  156. } else if (ns != null && ns != undefined) {
  157. node.setAttributeNS(ns, name, value);
  158. } else {
  159. switch (name) {
  160. case "value":
  161. if (value !== node.value) {
  162. node.value = value;
  163. }
  164. break;
  165. case "checked":
  166. node.checked = value === "true";
  167. break;
  168. case "selected":
  169. node.selected = value === "true";
  170. break;
  171. case "dangerous_inner_html":
  172. node.innerHTML = value;
  173. break;
  174. default:
  175. // https://github.com/facebook/react/blob/8b88ac2592c5f555f315f9440cbb665dd1e7457a/packages/react-dom/src/shared/DOMProperty.js#L352-L364
  176. if (value === "false" && bool_attrs.hasOwnProperty(name)) {
  177. node.removeAttribute(name);
  178. } else {
  179. node.setAttribute(name, value);
  180. }
  181. }
  182. }
  183. }
  184. RemoveAttribute(root, field, ns) {
  185. const name = field;
  186. const node = this.nodes[root];
  187. if (ns == "style") {
  188. node.style.removeProperty(name);
  189. } else if (ns !== null || ns !== undefined) {
  190. node.removeAttributeNS(ns, name);
  191. } else if (name === "value") {
  192. node.value = "";
  193. } else if (name === "checked") {
  194. node.checked = false;
  195. } else if (name === "selected") {
  196. node.selected = false;
  197. } else if (name === "dangerous_inner_html") {
  198. node.innerHTML = "";
  199. } else {
  200. node.removeAttribute(name);
  201. }
  202. }
  203. handleEdits(edits) {
  204. for (let template of edits.templates) {
  205. this.SaveTemplate(template);
  206. }
  207. for (let edit of edits.edits) {
  208. this.handleEdit(edit);
  209. }
  210. }
  211. SaveTemplate(template) {
  212. let roots = [];
  213. for (let root of template.roots) {
  214. roots.push(this.MakeTemplateNode(root));
  215. }
  216. this.templates[template.name] = roots;
  217. }
  218. MakeTemplateNode(node) {
  219. switch (node.type) {
  220. case "Text":
  221. return document.createTextNode(node.text);
  222. case "Dynamic":
  223. let dyn = document.createElement("pre");
  224. dyn.hidden = true;
  225. return dyn;
  226. case "DynamicText":
  227. return document.createTextNode("placeholder");
  228. case "Element":
  229. let el;
  230. if (node.namespace != null) {
  231. el = document.createElementNS(node.namespace, node.tag);
  232. } else {
  233. el = document.createElement(node.tag);
  234. }
  235. for (let attr of node.attrs) {
  236. if (attr.type == "Static") {
  237. this.SetAttributeInner(el, attr.name, attr.value, attr.namespace);
  238. }
  239. }
  240. for (let child of node.children) {
  241. el.appendChild(this.MakeTemplateNode(child));
  242. }
  243. return el;
  244. }
  245. }
  246. AssignId(path, id) {
  247. this.nodes[id] = this.LoadChild(path);
  248. }
  249. LoadChild(path) {
  250. // iterate through each number and get that child
  251. let node = this.stack[this.stack.length - 1];
  252. for (let i = 0; i < path.length; i++) {
  253. node = node.childNodes[path[i]];
  254. }
  255. return node;
  256. }
  257. HydrateText(path, value, id) {
  258. let node = this.LoadChild(path);
  259. if (node.nodeType == Node.TEXT_NODE) {
  260. node.textContent = value;
  261. } else {
  262. // replace with a textnode
  263. let text = document.createTextNode(value);
  264. node.replaceWith(text);
  265. node = text;
  266. }
  267. this.nodes[id] = node;
  268. }
  269. ReplacePlaceholder(path, m) {
  270. let els = this.stack.splice(this.stack.length - m);
  271. let node = this.LoadChild(path);
  272. node.replaceWith(...els);
  273. }
  274. LoadTemplate(name, index, id) {
  275. let node = this.templates[name][index].cloneNode(true);
  276. this.nodes[id] = node;
  277. this.stack.push(node);
  278. }
  279. handleEdit(edit) {
  280. switch (edit.type) {
  281. case "AppendChildren":
  282. this.AppendChildren(edit.m);
  283. break;
  284. case "AssignId":
  285. this.AssignId(edit.path, edit.id);
  286. break;
  287. case "CreatePlaceholder":
  288. this.CreatePlaceholder(edit.id);
  289. break;
  290. case "CreateTextNode":
  291. this.CreateTextNode(edit.value, edit.id);
  292. break;
  293. case "HydrateText":
  294. this.HydrateText(edit.path, edit.value, edit.id);
  295. break;
  296. case "LoadTemplate":
  297. this.LoadTemplate(edit.name, edit.index, edit.id);
  298. break;
  299. case "PushRoot":
  300. this.PushRoot(edit.id);
  301. break;
  302. case "ReplaceWith":
  303. this.ReplaceWith(edit.id, edit.m);
  304. break;
  305. case "ReplacePlaceholder":
  306. this.ReplacePlaceholder(edit.path, edit.m);
  307. break;
  308. case "InsertAfter":
  309. this.InsertAfter(edit.id, edit.m);
  310. break;
  311. case "InsertBefore":
  312. this.InsertBefore(edit.id, edit.m);
  313. break;
  314. case "Remove":
  315. this.Remove(edit.id);
  316. break;
  317. case "SetText":
  318. this.SetText(edit.id, edit.value);
  319. break;
  320. case "SetAttribute":
  321. this.SetAttribute(edit.id, edit.name, edit.value, edit.ns);
  322. break;
  323. case "RemoveAttribute":
  324. this.RemoveAttribute(edit.id, edit.name, edit.ns);
  325. break;
  326. case "RemoveEventListener":
  327. this.RemoveEventListener(edit.id, edit.name);
  328. break;
  329. case "NewEventListener":
  330. let bubbles = event_bubbles(edit.name);
  331. // this handler is only provided on desktop implementations since this
  332. // method is not used by the web implementation
  333. let handler = (event) => {
  334. let target = event.target;
  335. if (target != null) {
  336. let realId = target.getAttribute(`data-dioxus-id`);
  337. let shouldPreventDefault = target.getAttribute(
  338. `dioxus-prevent-default`
  339. );
  340. if (event.type === "click") {
  341. // todo call prevent default if it's the right type of event
  342. let a_element = target.closest("a");
  343. if (a_element != null) {
  344. event.preventDefault();
  345. if (
  346. shouldPreventDefault !== `onclick` &&
  347. a_element.getAttribute(`dioxus-prevent-default`) !== `onclick`
  348. ) {
  349. const href = a_element.getAttribute("href");
  350. if (href !== "" && href !== null && href !== undefined) {
  351. window.ipc.postMessage(
  352. serializeIpcMessage("browser_open", { href })
  353. );
  354. }
  355. }
  356. }
  357. // also prevent buttons from submitting
  358. if (target.tagName === "BUTTON" && event.type == "submit") {
  359. event.preventDefault();
  360. }
  361. }
  362. // walk the tree to find the real element
  363. while (realId == null) {
  364. // we've reached the root we don't want to send an event
  365. if (target.parentElement === null) {
  366. return;
  367. }
  368. target = target.parentElement;
  369. realId = target.getAttribute(`data-dioxus-id`);
  370. }
  371. shouldPreventDefault = target.getAttribute(
  372. `dioxus-prevent-default`
  373. );
  374. let contents = serialize_event(event);
  375. if (shouldPreventDefault === `on${event.type}`) {
  376. event.preventDefault();
  377. }
  378. if (event.type === "submit") {
  379. event.preventDefault();
  380. }
  381. if (
  382. target.tagName === "FORM" &&
  383. (event.type === "submit" || event.type === "input")
  384. ) {
  385. const formData = new FormData(target);
  386. for (let name of formData.keys()) {
  387. contents.values[name] = formData.getAll(name);
  388. }
  389. }
  390. if (realId === null) {
  391. return;
  392. }
  393. window.ipc.postMessage(
  394. serializeIpcMessage("user_event", {
  395. name: edit.name,
  396. element: parseInt(realId),
  397. data: contents,
  398. bubbles,
  399. })
  400. );
  401. }
  402. };
  403. this.NewEventListener(edit.name, edit.id, bubbles, handler);
  404. break;
  405. }
  406. }
  407. }
  408. function get_mouse_data(event) {
  409. const {
  410. altKey,
  411. button,
  412. buttons,
  413. clientX,
  414. clientY,
  415. ctrlKey,
  416. metaKey,
  417. offsetX,
  418. offsetY,
  419. pageX,
  420. pageY,
  421. screenX,
  422. screenY,
  423. shiftKey,
  424. } = event;
  425. return {
  426. alt_key: altKey,
  427. button: button,
  428. buttons: buttons,
  429. client_x: clientX,
  430. client_y: clientY,
  431. ctrl_key: ctrlKey,
  432. meta_key: metaKey,
  433. offset_x: offsetX,
  434. offset_y: offsetY,
  435. page_x: pageX,
  436. page_y: pageY,
  437. screen_x: screenX,
  438. screen_y: screenY,
  439. shift_key: shiftKey,
  440. };
  441. }
  442. function serialize_event(event) {
  443. switch (event.type) {
  444. case "copy":
  445. case "cut":
  446. case "past": {
  447. return {};
  448. }
  449. case "compositionend":
  450. case "compositionstart":
  451. case "compositionupdate": {
  452. let { data } = event;
  453. return {
  454. data,
  455. };
  456. }
  457. case "keydown":
  458. case "keypress":
  459. case "keyup": {
  460. let {
  461. charCode,
  462. key,
  463. altKey,
  464. ctrlKey,
  465. metaKey,
  466. keyCode,
  467. shiftKey,
  468. location,
  469. repeat,
  470. which,
  471. code,
  472. } = event;
  473. return {
  474. char_code: charCode,
  475. key: key,
  476. alt_key: altKey,
  477. ctrl_key: ctrlKey,
  478. meta_key: metaKey,
  479. key_code: keyCode,
  480. shift_key: shiftKey,
  481. location: location,
  482. repeat: repeat,
  483. which: which,
  484. code,
  485. };
  486. }
  487. case "focus":
  488. case "blur": {
  489. return {};
  490. }
  491. case "change": {
  492. let target = event.target;
  493. let value;
  494. if (target.type === "checkbox" || target.type === "radio") {
  495. value = target.checked ? "true" : "false";
  496. } else {
  497. value = target.value ?? target.textContent;
  498. }
  499. return {
  500. value: value,
  501. values: {},
  502. };
  503. }
  504. case "input":
  505. case "invalid":
  506. case "reset":
  507. case "submit": {
  508. let target = event.target;
  509. let value = target.value ?? target.textContent;
  510. if (target.type === "checkbox") {
  511. value = target.checked ? "true" : "false";
  512. }
  513. return {
  514. value: value,
  515. values: {},
  516. };
  517. }
  518. case "drag":
  519. case "dragend":
  520. case "dragenter":
  521. case "dragexit":
  522. case "dragleave":
  523. case "dragover":
  524. case "dragstart":
  525. case "drop": {
  526. return { mouse: get_mouse_data(event) };
  527. }
  528. case "click":
  529. case "contextmenu":
  530. case "doubleclick":
  531. case "dblclick":
  532. case "mousedown":
  533. case "mouseenter":
  534. case "mouseleave":
  535. case "mousemove":
  536. case "mouseout":
  537. case "mouseover":
  538. case "mouseup": {
  539. return get_mouse_data(event);
  540. }
  541. case "pointerdown":
  542. case "pointermove":
  543. case "pointerup":
  544. case "pointercancel":
  545. case "gotpointercapture":
  546. case "lostpointercapture":
  547. case "pointerenter":
  548. case "pointerleave":
  549. case "pointerover":
  550. case "pointerout": {
  551. const {
  552. altKey,
  553. button,
  554. buttons,
  555. clientX,
  556. clientY,
  557. ctrlKey,
  558. metaKey,
  559. pageX,
  560. pageY,
  561. screenX,
  562. screenY,
  563. shiftKey,
  564. pointerId,
  565. width,
  566. height,
  567. pressure,
  568. tangentialPressure,
  569. tiltX,
  570. tiltY,
  571. twist,
  572. pointerType,
  573. isPrimary,
  574. } = event;
  575. return {
  576. alt_key: altKey,
  577. button: button,
  578. buttons: buttons,
  579. client_x: clientX,
  580. client_y: clientY,
  581. ctrl_key: ctrlKey,
  582. meta_key: metaKey,
  583. page_x: pageX,
  584. page_y: pageY,
  585. screen_x: screenX,
  586. screen_y: screenY,
  587. shift_key: shiftKey,
  588. pointer_id: pointerId,
  589. width: width,
  590. height: height,
  591. pressure: pressure,
  592. tangential_pressure: tangentialPressure,
  593. tilt_x: tiltX,
  594. tilt_y: tiltY,
  595. twist: twist,
  596. pointer_type: pointerType,
  597. is_primary: isPrimary,
  598. };
  599. }
  600. case "select": {
  601. return {};
  602. }
  603. case "touchcancel":
  604. case "touchend":
  605. case "touchmove":
  606. case "touchstart": {
  607. const { altKey, ctrlKey, metaKey, shiftKey } = event;
  608. return {
  609. // changed_touches: event.changedTouches,
  610. // target_touches: event.targetTouches,
  611. // touches: event.touches,
  612. alt_key: altKey,
  613. ctrl_key: ctrlKey,
  614. meta_key: metaKey,
  615. shift_key: shiftKey,
  616. };
  617. }
  618. case "scroll": {
  619. return {};
  620. }
  621. case "wheel": {
  622. const { deltaX, deltaY, deltaZ, deltaMode } = event;
  623. return {
  624. delta_x: deltaX,
  625. delta_y: deltaY,
  626. delta_z: deltaZ,
  627. delta_mode: deltaMode,
  628. };
  629. }
  630. case "animationstart":
  631. case "animationend":
  632. case "animationiteration": {
  633. const { animationName, elapsedTime, pseudoElement } = event;
  634. return {
  635. animation_name: animationName,
  636. elapsed_time: elapsedTime,
  637. pseudo_element: pseudoElement,
  638. };
  639. }
  640. case "transitionend": {
  641. const { propertyName, elapsedTime, pseudoElement } = event;
  642. return {
  643. property_name: propertyName,
  644. elapsed_time: elapsedTime,
  645. pseudo_element: pseudoElement,
  646. };
  647. }
  648. case "abort":
  649. case "canplay":
  650. case "canplaythrough":
  651. case "durationchange":
  652. case "emptied":
  653. case "encrypted":
  654. case "ended":
  655. case "error":
  656. case "loadeddata":
  657. case "loadedmetadata":
  658. case "loadstart":
  659. case "pause":
  660. case "play":
  661. case "playing":
  662. case "progress":
  663. case "ratechange":
  664. case "seeked":
  665. case "seeking":
  666. case "stalled":
  667. case "suspend":
  668. case "timeupdate":
  669. case "volumechange":
  670. case "waiting": {
  671. return {};
  672. }
  673. case "toggle": {
  674. return {};
  675. }
  676. default: {
  677. return {};
  678. }
  679. }
  680. }
  681. function serializeIpcMessage(method, params = {}) {
  682. return JSON.stringify({ method, params });
  683. }
  684. const bool_attrs = {
  685. allowfullscreen: true,
  686. allowpaymentrequest: true,
  687. async: true,
  688. autofocus: true,
  689. autoplay: true,
  690. checked: true,
  691. controls: true,
  692. default: true,
  693. defer: true,
  694. disabled: true,
  695. formnovalidate: true,
  696. hidden: true,
  697. ismap: true,
  698. itemscope: true,
  699. loop: true,
  700. multiple: true,
  701. muted: true,
  702. nomodule: true,
  703. novalidate: true,
  704. open: true,
  705. playsinline: true,
  706. readonly: true,
  707. required: true,
  708. reversed: true,
  709. selected: true,
  710. truespeed: true,
  711. };
  712. function is_element_node(node) {
  713. return node.nodeType == 1;
  714. }
  715. function event_bubbles(event) {
  716. switch (event) {
  717. case "copy":
  718. return true;
  719. case "cut":
  720. return true;
  721. case "paste":
  722. return true;
  723. case "compositionend":
  724. return true;
  725. case "compositionstart":
  726. return true;
  727. case "compositionupdate":
  728. return true;
  729. case "keydown":
  730. return true;
  731. case "keypress":
  732. return true;
  733. case "keyup":
  734. return true;
  735. case "focus":
  736. return false;
  737. case "focusout":
  738. return true;
  739. case "focusin":
  740. return true;
  741. case "blur":
  742. return false;
  743. case "change":
  744. return true;
  745. case "input":
  746. return true;
  747. case "invalid":
  748. return true;
  749. case "reset":
  750. return true;
  751. case "submit":
  752. return true;
  753. case "click":
  754. return true;
  755. case "contextmenu":
  756. return true;
  757. case "doubleclick":
  758. return true;
  759. case "dblclick":
  760. return true;
  761. case "drag":
  762. return true;
  763. case "dragend":
  764. return true;
  765. case "dragenter":
  766. return false;
  767. case "dragexit":
  768. return false;
  769. case "dragleave":
  770. return true;
  771. case "dragover":
  772. return true;
  773. case "dragstart":
  774. return true;
  775. case "drop":
  776. return true;
  777. case "mousedown":
  778. return true;
  779. case "mouseenter":
  780. return false;
  781. case "mouseleave":
  782. return false;
  783. case "mousemove":
  784. return true;
  785. case "mouseout":
  786. return true;
  787. case "scroll":
  788. return false;
  789. case "mouseover":
  790. return true;
  791. case "mouseup":
  792. return true;
  793. case "pointerdown":
  794. return true;
  795. case "pointermove":
  796. return true;
  797. case "pointerup":
  798. return true;
  799. case "pointercancel":
  800. return true;
  801. case "gotpointercapture":
  802. return true;
  803. case "lostpointercapture":
  804. return true;
  805. case "pointerenter":
  806. return false;
  807. case "pointerleave":
  808. return false;
  809. case "pointerover":
  810. return true;
  811. case "pointerout":
  812. return true;
  813. case "select":
  814. return true;
  815. case "touchcancel":
  816. return true;
  817. case "touchend":
  818. return true;
  819. case "touchmove":
  820. return true;
  821. case "touchstart":
  822. return true;
  823. case "wheel":
  824. return true;
  825. case "abort":
  826. return false;
  827. case "canplay":
  828. return false;
  829. case "canplaythrough":
  830. return false;
  831. case "durationchange":
  832. return false;
  833. case "emptied":
  834. return false;
  835. case "encrypted":
  836. return true;
  837. case "ended":
  838. return false;
  839. case "error":
  840. return false;
  841. case "loadeddata":
  842. return false;
  843. case "loadedmetadata":
  844. return false;
  845. case "loadstart":
  846. return false;
  847. case "pause":
  848. return false;
  849. case "play":
  850. return false;
  851. case "playing":
  852. return false;
  853. case "progress":
  854. return false;
  855. case "ratechange":
  856. return false;
  857. case "seeked":
  858. return false;
  859. case "seeking":
  860. return false;
  861. case "stalled":
  862. return false;
  863. case "suspend":
  864. return false;
  865. case "timeupdate":
  866. return false;
  867. case "volumechange":
  868. return false;
  869. case "waiting":
  870. return false;
  871. case "animationstart":
  872. return true;
  873. case "animationend":
  874. return true;
  875. case "animationiteration":
  876. return true;
  877. case "transitionend":
  878. return true;
  879. case "toggle":
  880. return true;
  881. }
  882. return true;
  883. }