interpreter.js 22 KB

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