interpreter.js 23 KB

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