Browse Source

Commit js

Jonathan Kelley 1 year ago
parent
commit
f447f01403

+ 0 - 1
packages/interpreter/a.txt

@@ -1 +0,0 @@
-pub const SLEDGEHAMMER_JS: &str = "let m,p,ls,d,t,op,i,e,z,metaflags;\n            const namespace = [];\n                    let namespace_cache_hit, namespace_cache_idx;\n                    function get_namespace() {\n                        namespace_cache_idx = u8buf[u8bufp++];\n                        if(namespace_cache_idx & 128){\n                            namespace_cache_hit=s.substring(sp,sp+=u8buf[u8bufp++]);\n                            namespace[namespace_cache_idx&4294967167]=namespace_cache_hit;\n                            return namespace_cache_hit;\n                        }\n                        else{\n                            return namespace[namespace_cache_idx&4294967167];\n                        }\n                    }let u8buf,u8bufp;const attr = [];\n                    let attr_cache_hit, attr_cache_idx;\n                    function get_attr() {\n                        attr_cache_idx = u8buf[u8bufp++];\n                        if(attr_cache_idx & 128){\n                            attr_cache_hit=s.substring(sp,sp+=u8buf[u8bufp++]);\n                            attr[attr_cache_idx&4294967167]=attr_cache_hit;\n                            return attr_cache_hit;\n                        }\n                        else{\n                            return attr[attr_cache_idx&4294967167];\n                        }\n                    }const evt = [];\n                    let evt_cache_hit, evt_cache_idx;\n                    function get_evt() {\n                        evt_cache_idx = u8buf[u8bufp++];\n                        if(evt_cache_idx & 128){\n                            evt_cache_hit=s.substring(sp,sp+=u8buf[u8bufp++]);\n                            evt[evt_cache_idx&4294967167]=evt_cache_hit;\n                            return evt_cache_hit;\n                        }\n                        else{\n                            return evt[evt_cache_idx&4294967167];\n                        }\n                    }const el = [];\n                    let el_cache_hit, el_cache_idx;\n                    function get_el() {\n                        el_cache_idx = u8buf[u8bufp++];\n                        if(el_cache_idx & 128){\n                            el_cache_hit=s.substring(sp,sp+=u8buf[u8bufp++]);\n                            el[el_cache_idx&4294967167]=el_cache_hit;\n                            return el_cache_hit;\n                        }\n                        else{\n                            return el[el_cache_idx&4294967167];\n                        }\n                    }let u32buf,u32bufp;let s = \"\";let lsp,sp,sl; let c = new TextDecoder();let u16buf,u16bufp;const ns_cache = [];\n                    let ns_cache_cache_hit, ns_cache_cache_idx;\n                    function get_ns_cache() {\n                        ns_cache_cache_idx = u8buf[u8bufp++];\n                        if(ns_cache_cache_idx & 128){\n                            ns_cache_cache_hit=s.substring(sp,sp+=u8buf[u8bufp++]);\n                            ns_cache[ns_cache_cache_idx&4294967167]=ns_cache_cache_hit;\n                            return ns_cache_cache_hit;\n                        }\n                        else{\n                            return ns_cache[ns_cache_cache_idx&4294967167];\n                        }\n                    }\n            let field,ptr,array,ns,id,value,len,event,many,bubbles,event_name;\n            export  function create(r){\n                d=r;\n            }\n            export  function update_memory(b){\n                m=new DataView(b.buffer)\n            }\n            export  function run(){\n                metaflags=m.getUint32(d,true);\n                if((metaflags>>>6)&1){\n                    ls=m.getUint32(d+6*4,true);\n                }\n                p=ls;\n                if ((metaflags>>>5)&1){\n                t = m.getUint32(d+5*4,true);\n                u8buf=new Uint8Array(m.buffer,t,((m.buffer.byteLength-t)-(m.buffer.byteLength-t)%1)/1);\n            }\n            u8bufp=0;if ((metaflags>>>3)&1){\n                t = m.getUint32(d+3*4,true);\n                u32buf=new Uint32Array(m.buffer,t,((m.buffer.byteLength-t)-(m.buffer.byteLength-t)%4)/4);\n            }\n            u32bufp=0;if (metaflags&1){\n                lsp = m.getUint32(d+1*4,true);\n            }\n            if ((metaflags>>>2)&1) {\n                sl = m.getUint32(d+2*4,true);\n                if ((metaflags>>>1)&1) {\n                    sp = lsp;\n                    s = \"\";\n                    e = sp + ((sl / 4) | 0) * 4;\n                    while (sp < e) {\n                        t = m.getUint32(sp, true);\n                        s += String.fromCharCode(\n                            t & 255,\n                            (t & 65280) >> 8,\n                            (t & 16711680) >> 16,\n                            t >> 24\n                        );\n                        sp += 4;\n                    }\n                    while (sp < lsp + sl) {\n                        s += String.fromCharCode(m.getUint8(sp++));\n                    }\n                } else {\n                    s = c.decode(new DataView(m.buffer, lsp, sl));\n                }\n            }\n            sp=0;if ((metaflags>>>4)&1){\n                t = m.getUint32(d+4*4,true);\n                u16buf=new Uint16Array(m.buffer,t,((m.buffer.byteLength-t)-(m.buffer.byteLength-t)%2)/2);\n            }\n            u16bufp=0;\n                for(;;){\n                    op=m.getUint32(p,true);\n                    p+=4;\n                    z=0;\n                    while(z++<4){\n                        switch(op&255){\n                            case 0:{AppendChildren(root, stack.length-1);}break;case 1:{stack.push(nodes[u32buf[u32bufp++]]);}break;case 2:{AppendChildren(u32buf[u32bufp++], u16buf[u16bufp++]);}break;case 3:{stack.pop();}break;case 4:{root = nodes[u32buf[u32bufp++]]; els = stack.splice(stack.length-u16buf[u16bufp++]); if (root.listening) { listeners.removeAllNonBubbling(root); } root.replaceWith(...els);}break;case 5:{nodes[u32buf[u32bufp++]].after(...stack.splice(stack.length-u16buf[u16bufp++]));}break;case 6:{nodes[u32buf[u32bufp++]].before(...stack.splice(stack.length-u16buf[u16bufp++]));}break;case 7:{node = nodes[u32buf[u32bufp++]]; if (node !== undefined) { if (node.listening) { listeners.removeAllNonBubbling(node); } node.remove(); }}break;case 8:{stack.push(document.createTextNode(s.substring(sp,sp+=u32buf[u32bufp++])));}break;case 9:{node = document.createTextNode(s.substring(sp,sp+=u32buf[u32bufp++])); nodes[u32buf[u32bufp++]] = node; stack.push(node);}break;case 10:{node = document.createElement('pre'); node.hidden = true; stack.push(node); nodes[u32buf[u32bufp++]] = node;}break;case 11:event_name=get_evt();id=u32buf[u32bufp++];bubbles=u8buf[u8bufp++];node = nodes[id]; if(node.listening){node.listening += 1;}else{node.listening = 1;} node.setAttribute('data-dioxus-id', `${id}`); listeners.create(event_name, node, bubbles);break;case 12:{node = nodes[u32buf[u32bufp++]]; node.listening -= 1; node.removeAttribute('data-dioxus-id'); listeners.remove(node, get_evt(), u8buf[u8bufp++]);}break;case 13:{nodes[u32buf[u32bufp++]].textContent = s.substring(sp,sp+=u32buf[u32bufp++]);}break;case 14:{node = nodes[u32buf[u32bufp++]]; setAttributeInner(node, get_attr(), s.substring(sp,sp+=u32buf[u32bufp++]), get_ns_cache());}break;case 15:id=u32buf[u32bufp++];field=get_attr();ns=get_ns_cache();{\n                node = nodes[id];\n                if (!ns) {\n                    switch (field) {\n                        case \"value\":\n                            node.value = \"\";\n                            break;\n                        case \"checked\":\n                            node.checked = false;\n                            break;\n                        case \"selected\":\n                            node.selected = false;\n                            break;\n                        case \"dangerous_inner_html\":\n                            node.innerHTML = \"\";\n                            break;\n                        default:\n                            node.removeAttribute(field);\n                            break;\n                    }\n                } else if (ns == \"style\") {\n                    node.style.removeProperty(name);\n                } else {\n                    node.removeAttributeNS(ns, field);\n                }\n            }break;case 16:{nodes[u32buf[u32bufp++]] = LoadChild(u32buf[u32bufp++], u8buf[u8bufp++]);}break;case 17:ptr=u32buf[u32bufp++];len=u8buf[u8bufp++];value=s.substring(sp,sp+=u32buf[u32bufp++]);id=u32buf[u32bufp++];{\n                node = LoadChild(ptr, len);\n                if (node.nodeType == Node.TEXT_NODE) {\n                    node.textContent = value;\n                } else {\n                    let text = document.createTextNode(value);\n                    node.replaceWith(text);\n                    node = text;\n                }\n                nodes[id] = node;\n            }break;case 18:{els = stack.splice(stack.length - u16buf[u16bufp++]); node = LoadChild(u32buf[u32bufp++], u8buf[u8bufp++]); node.replaceWith(...els);}break;case 19:{node = templates[u16buf[u16bufp++]][u16buf[u16bufp++]].cloneNode(true); nodes[u32buf[u32bufp++]] = node; stack.push(node);}break;case 20:many=u16buf[u16bufp++];{\n            root = stack[stack.length-many-1];\n            els = stack.splice(stack.length-many);\n            for (k = 0; k < many; k++) {\n                root.appendChild(els[k]);\n            }\n        }break;case 21:{setAttributeInner(stack[stack.length-1], get_attr(), s.substring(sp,sp+=u32buf[u32bufp++]), get_ns_cache());}break;case 22:{node = document.createElement('pre'); node.hidden = true; stack.push(node);}break;case 23:{stack.push(document.createElementNS(get_namespace(), get_el()))}break;case 24:{stack.push(document.createElement(get_el()))}break;case 25:{templates[u16buf[u16bufp++]] = stack.splice(stack.length-u16buf[u16bufp++]);}break;case 26:event=get_evt();id=u32buf[u32bufp++];bubbles=u8buf[u8bufp++];\n        bubbles = bubbles == 1;\n        node = nodes[id];\n        if(node.listening){\n            node.listening += 1;\n        } else {\n            node.listening = 1;\n        }\n        node.setAttribute('data-dioxus-id', `${id}`);\n        const event_name = event;\n\n        // if this is a mounted listener, we send the event immediately\n        if (event_name === \"mounted\") {\n            window.ipc.postMessage(\n                window.interpreter.serializeIpcMessage(\"user_event\", {\n                    name: event_name,\n                    element: id,\n                    data: null,\n                    bubbles,\n                })\n            );\n        } else {\n            listeners.create(event_name, node, bubbles, (event) => {\n                handler(event, event_name, bubbles, config);\n            });\n        }break;case 27:{nodes[u32buf[u32bufp++]] = LoadChild((()=>{e=u8bufp+u32buf[u32bufp++];const final_array = u8buf.slice(u8bufp,e);u8bufp=e;return final_array;})());}break;case 28:array=(()=>{e=u8bufp+u32buf[u32bufp++];const final_array = u8buf.slice(u8bufp,e);u8bufp=e;return final_array;})();value=s.substring(sp,sp+=u32buf[u32bufp++]);id=u32buf[u32bufp++];{\n            node = LoadChild(array);\n            if (node.nodeType == Node.TEXT_NODE) {\n                node.textContent = value;\n            } else {\n                let text = document.createTextNode(value);\n                node.replaceWith(text);\n                node = text;\n            }\n            nodes[id] = node;\n        }break;case 29:{els = stack.splice(stack.length - u16buf[u16bufp++]); node = LoadChild((()=>{e=u8bufp+u32buf[u32bufp++];const final_array = u8buf.slice(u8bufp,e);u8bufp=e;return final_array;})()); node.replaceWith(...els);}break;case 30:return true;\n                        }\n                        op>>>=8;\n                    }\n                }\n            }\n            export  function run_from_bytes(bytes){\n                d = 0;\n                update_memory(new Uint8Array(bytes))\n                run()\n            }"

+ 36 - 34
packages/interpreter/build.rs

@@ -6,11 +6,41 @@ use std::{
 
 fn main() {
     // If any TS changes, re-run the build script
-    println!("cargo:rerun-if-changed=src/*.ts");
+    println!("cargo:rerun-if-changed=src/ts/*.ts");
 
-    // for entry in ["common", "form", "interpreter"].iter() {
-    //     gen_bindings(entry);
-    // }
+    // Compute the hash of the ts files
+    let hash = hash_dir("src/ts");
+
+    // If the hash matches the one on disk, we're good and don't need to update bindings
+    if let Ok(contents) = read_to_string("src/js/hash.txt") {
+        if contents.trim() == hash.to_string() {
+            return;
+        }
+    }
+
+    // Otherwise, generate the bindings and write the new hash to disk
+    // Generate the bindings for both native and web
+    gen_bindings("native");
+    gen_bindings("web");
+
+    std::fs::write("src/js/hash.txt", hash.to_string()).unwrap();
+}
+
+/// Hashes the contents of a directory
+fn hash_dir(dir: &str) -> u64 {
+    let mut hasher = DefaultHasher::new();
+
+    for entry in std::fs::read_dir(dir).unwrap() {
+        let entry = entry.unwrap();
+        let path = entry.path();
+        let metadata = std::fs::metadata(&path).unwrap();
+        if metadata.is_file() {
+            let contents = std::fs::read(&path).unwrap();
+            contents.hash(&mut hasher);
+        }
+    }
+
+    hasher.finish()
 }
 
 // okay...... so tsc might fail if the user doesn't have it installed
@@ -21,27 +51,10 @@ fn main() {
 // if the hashes don't match, we need to fail the build
 // that way we also don't need
 fn gen_bindings(name: &str) {
-    let contents = read_to_string(&format!("src/{name}.ts")).unwrap();
-    let generated = read_to_string(&format!("src/gen/{name}.js")).unwrap_or_default();
-    let hashed = hash_it(&contents);
-
-    // If the file is generated, and the hash is the same, we're good, don't do anything
-    if generated
-        .lines()
-        .next()
-        .unwrap_or_default()
-        .starts_with(&format!("// DO NOT EDIT THIS FILE. HASH: {}", hashed))
-    {
-        return;
-    }
-
     // If the file is generated, and the hash is different, we need to generate it
     let status = Command::new("tsc")
-        .arg(format!("src/{name}.ts"))
-        .arg("--outDir")
-        .arg("gen")
-        .arg("--target")
-        .arg("es6")
+        .arg("--p")
+        .arg(format!("tsconfig.{name}.json"))
         .status()
         .unwrap();
 
@@ -51,15 +64,4 @@ fn gen_bindings(name: &str) {
             name
         );
     }
-
-    // The file should exist, and now we need write the TS hash to the file
-    let generated = read_to_string(&format!("gen/{name}.js")).unwrap();
-    let generated = format!("// DO NOT EDIT THIS FILE. HASH: {}\n{}", hashed, generated);
-    std::fs::write(&format!("src/gen/{name}.js"), generated).unwrap();
-}
-
-fn hash_it(obj: impl Hash) -> u64 {
-    let mut hasher = DefaultHasher::new();
-    obj.hash(&mut hasher);
-    hasher.finish()
 }

+ 0 - 3
packages/interpreter/gen/README.md

@@ -1,3 +0,0 @@
-temporary generated code directory since tsc doesn't have a crossplatform way of generating typescript to stdout
-
-https://github.com/microsoft/TypeScript/issues/1226#issuecomment-523544134

+ 1 - 0
packages/interpreter/src/js/hash.txt

@@ -0,0 +1 @@
+16803007677292896021

+ 681 - 0
packages/interpreter/src/js/native.js

@@ -0,0 +1,681 @@
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    };
+    return function (d, b) {
+        if (typeof b !== "function" && b !== null)
+            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+    return new (P || (P = Promise))(function (resolve, reject) {
+        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+        step((generator = generator.apply(thisArg, _arguments || [])).next());
+    });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+    function verb(n) { return function (v) { return step([n, v]); }; }
+    function step(op) {
+        if (f) throw new TypeError("Generator is already executing.");
+        while (g && (g = 0, op[0] && (_ = 0)), _) try {
+            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+            if (y = 0, t) op = [op[0] & 2, t.value];
+            switch (op[0]) {
+                case 0: case 1: t = op; break;
+                case 4: _.label++; return { value: op[1], done: false };
+                case 5: _.label++; y = op[1]; op = [0]; continue;
+                case 7: op = _.ops.pop(); _.trys.pop(); continue;
+                default:
+                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+                    if (t[2]) _.ops.pop();
+                    _.trys.pop(); continue;
+            }
+            op = body.call(thisArg, _);
+        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+    }
+};
+System.register("form", [], function (exports_1, context_1) {
+    "use strict";
+    var __moduleName = context_1 && context_1.id;
+    function retriveValues(event, target) {
+        var contents = {};
+        if (target instanceof HTMLFormElement && (event.type === "submit" || event.type === "input")) {
+            retrieveFormValues(target, contents);
+        }
+        if (target instanceof HTMLSelectElement && (event.type === "input" || event.type === "change")) {
+            retriveInputsValues(target, contents);
+        }
+        return contents;
+    }
+    exports_1("retriveValues", retriveValues);
+    function retrieveFormValues(form, contents) {
+        var formData = new FormData(form);
+        for (var name_1 in formData.keys()) {
+            var element = form.elements.namedItem(name_1);
+            if (!(element instanceof HTMLInputElement)) {
+                continue;
+            }
+            switch (element.type) {
+                case "select-multiple":
+                    contents[name_1] = formData.getAll(name_1);
+                    break;
+                default:
+                    contents[name_1] = [formData.get(name_1)];
+                    break;
+            }
+        }
+    }
+    exports_1("retrieveFormValues", retrieveFormValues);
+    function retriveInputsValues(target, contents) {
+        var selectData = target.options;
+        contents["options"] = [];
+        for (var i = 0; i < selectData.length; i++) {
+            var option = selectData[i];
+            if (option.selected) {
+                contents["options"].push(option.value.toString());
+            }
+        }
+    }
+    exports_1("retriveInputsValues", retriveInputsValues);
+    return {
+        setters: [],
+        execute: function () {
+        }
+    };
+});
+System.register("interpreter_core", [], function (exports_2, context_2) {
+    "use strict";
+    var Interpreter;
+    var __moduleName = context_2 && context_2.id;
+    return {
+        setters: [],
+        execute: function () {
+            Interpreter = (function () {
+                function Interpreter(root, handler) {
+                    this.root = root;
+                    this.nodes = [root];
+                    this.stack = [root];
+                    this.global = {};
+                    this.local = {};
+                    this.handler = handler;
+                }
+                Interpreter.prototype.createListener = function (event_name, element, bubbles) {
+                    if (bubbles) {
+                        if (this.global[event_name] === undefined) {
+                            this.global[event_name] = { active: 1, callback: this.handler };
+                            this.root.addEventListener(event_name, this.handler);
+                        }
+                        else {
+                            this.global[event_name].active++;
+                        }
+                    }
+                    else {
+                        var id = element.getAttribute("data-dioxus-id");
+                        if (!this.local[id]) {
+                            this.local[id] = {};
+                        }
+                        element.addEventListener(event_name, this.handler);
+                    }
+                };
+                Interpreter.prototype.removeListener = function (element, event_name, bubbles) {
+                    if (bubbles) {
+                        this.removeBubblingListener(event_name);
+                    }
+                    else {
+                        this.removeNonBubblingListener(element, event_name);
+                    }
+                };
+                Interpreter.prototype.removeBubblingListener = function (event_name) {
+                    this.global[event_name].active--;
+                    if (this.global[event_name].active === 0) {
+                        this.root.removeEventListener(event_name, this.global[event_name].callback);
+                        delete this.global[event_name];
+                    }
+                };
+                Interpreter.prototype.removeNonBubblingListener = function (element, event_name) {
+                    var id = element.getAttribute("data-dioxus-id");
+                    delete this.local[id][event_name];
+                    if (Object.keys(this.local[id]).length === 0) {
+                        delete this.local[id];
+                    }
+                    element.removeEventListener(event_name, this.handler);
+                };
+                Interpreter.prototype.removeAllNonBubblingListeners = function (element) {
+                    var id = element.getAttribute("data-dioxus-id");
+                    delete this.local[id];
+                };
+                return Interpreter;
+            }());
+            exports_2("Interpreter", Interpreter);
+        }
+    };
+});
+System.register("serialize", [], function (exports_3, context_3) {
+    "use strict";
+    var __moduleName = context_3 && context_3.id;
+    function serializeEvent(event) {
+        if (event instanceof KeyboardEvent) {
+            return {
+                char_code: event.charCode,
+                is_composing: event.isComposing,
+                key: event.key,
+                alt_key: event.altKey,
+                ctrl_key: event.ctrlKey,
+                meta_key: event.metaKey,
+                key_code: event.keyCode,
+                shift_key: event.shiftKey,
+                location: event.location,
+                repeat: event.repeat,
+                which: event.which,
+                code: event.code,
+            };
+        }
+        if (event instanceof PointerEvent) {
+            return {
+                alt_key: event.altKey,
+                button: event.button,
+                buttons: event.buttons,
+                client_x: event.clientX,
+                client_y: event.clientY,
+                ctrl_key: event.ctrlKey,
+                meta_key: event.metaKey,
+                page_x: event.pageX,
+                page_y: event.pageY,
+                screen_x: event.screenX,
+                screen_y: event.screenY,
+                shift_key: event.shiftKey,
+                pointer_id: event.pointerId,
+                width: event.width,
+                height: event.height,
+                pressure: event.pressure,
+                tangential_pressure: event.tangentialPressure,
+                tilt_x: event.tiltX,
+                tilt_y: event.tiltY,
+                twist: event.twist,
+                pointer_type: event.pointerType,
+                is_primary: event.isPrimary,
+            };
+        }
+        if (event instanceof MouseEvent) {
+            return {
+                alt_key: event.altKey,
+                button: event.button,
+                buttons: event.buttons,
+                client_x: event.clientX,
+                client_y: event.clientY,
+                ctrl_key: event.ctrlKey,
+                meta_key: event.metaKey,
+                offset_x: event.offsetX,
+                offset_y: event.offsetY,
+                page_x: event.pageX,
+                page_y: event.pageY,
+                screen_x: event.screenX,
+                screen_y: event.screenY,
+                shift_key: event.shiftKey,
+            };
+        }
+        if (event instanceof TouchEvent) {
+            return {
+                alt_key: event.altKey,
+                ctrl_key: event.ctrlKey,
+                meta_key: event.metaKey,
+                shift_key: event.shiftKey,
+                changed_touches: event.changedTouches,
+                target_touches: event.targetTouches,
+                touches: event.touches,
+            };
+        }
+        if (event instanceof WheelEvent) {
+            return {
+                delta_x: event.deltaX,
+                delta_y: event.deltaY,
+                delta_z: event.deltaZ,
+                delta_mode: event.deltaMode,
+            };
+        }
+        if (event instanceof AnimationEvent) {
+            return {
+                animation_name: event.animationName,
+                elapsed_time: event.elapsedTime,
+                pseudo_element: event.pseudoElement,
+            };
+        }
+        if (event instanceof TransitionEvent) {
+            return {
+                property_name: event.propertyName,
+                elapsed_time: event.elapsedTime,
+                pseudo_element: event.pseudoElement,
+            };
+        }
+        if (event instanceof ClipboardEvent) {
+            return {};
+        }
+        if (event instanceof CompositionEvent) {
+            return {
+                data: event.data,
+            };
+        }
+        if (event instanceof DragEvent) {
+            return {
+                mouse: {
+                    alt_key: event.altKey,
+                    ctrl_key: event.ctrlKey,
+                    meta_key: event.metaKey,
+                    shift_key: event.shiftKey,
+                },
+                files: [],
+            };
+        }
+        if (event instanceof FocusEvent) {
+            return {};
+        }
+        return {};
+    }
+    exports_3("serializeEvent", serializeEvent);
+    function isElementNode(node) {
+        return node.nodeType == 1;
+    }
+    function eventBubbles(eventName) {
+        switch (eventName) {
+            case "copy":
+                return true;
+            case "cut":
+                return true;
+            case "paste":
+                return true;
+            case "compositionend":
+                return true;
+            case "compositionstart":
+                return true;
+            case "compositionupdate":
+                return true;
+            case "keydown":
+                return true;
+            case "keypress":
+                return true;
+            case "keyup":
+                return true;
+            case "focus":
+                return false;
+            case "focusout":
+                return true;
+            case "focusin":
+                return true;
+            case "blur":
+                return false;
+            case "change":
+                return true;
+            case "input":
+                return true;
+            case "invalid":
+                return true;
+            case "reset":
+                return true;
+            case "submit":
+                return true;
+            case "click":
+                return true;
+            case "contextmenu":
+                return true;
+            case "doubleclick":
+                return true;
+            case "dblclick":
+                return true;
+            case "drag":
+                return true;
+            case "dragend":
+                return true;
+            case "dragenter":
+                return false;
+            case "dragexit":
+                return false;
+            case "dragleave":
+                return true;
+            case "dragover":
+                return true;
+            case "dragstart":
+                return true;
+            case "drop":
+                return true;
+            case "mousedown":
+                return true;
+            case "mouseenter":
+                return false;
+            case "mouseleave":
+                return false;
+            case "mousemove":
+                return true;
+            case "mouseout":
+                return true;
+            case "scroll":
+                return false;
+            case "mouseover":
+                return true;
+            case "mouseup":
+                return true;
+            case "pointerdown":
+                return true;
+            case "pointermove":
+                return true;
+            case "pointerup":
+                return true;
+            case "pointercancel":
+                return true;
+            case "gotpointercapture":
+                return true;
+            case "lostpointercapture":
+                return true;
+            case "pointerenter":
+                return false;
+            case "pointerleave":
+                return false;
+            case "pointerover":
+                return true;
+            case "pointerout":
+                return true;
+            case "select":
+                return true;
+            case "touchcancel":
+                return true;
+            case "touchend":
+                return true;
+            case "touchmove":
+                return true;
+            case "touchstart":
+                return true;
+            case "wheel":
+                return true;
+            case "abort":
+                return false;
+            case "canplay":
+                return false;
+            case "canplaythrough":
+                return false;
+            case "durationchange":
+                return false;
+            case "emptied":
+                return false;
+            case "encrypted":
+                return true;
+            case "ended":
+                return false;
+            case "error":
+                return false;
+            case "loadeddata":
+            case "loadedmetadata":
+            case "loadstart":
+            case "load":
+                return false;
+            case "pause":
+                return false;
+            case "play":
+                return false;
+            case "playing":
+                return false;
+            case "progress":
+                return false;
+            case "ratechange":
+                return false;
+            case "seeked":
+                return false;
+            case "seeking":
+                return false;
+            case "stalled":
+                return false;
+            case "suspend":
+                return false;
+            case "timeupdate":
+                return false;
+            case "volumechange":
+                return false;
+            case "waiting":
+                return false;
+            case "animationstart":
+                return true;
+            case "animationend":
+                return true;
+            case "animationiteration":
+                return true;
+            case "transitionend":
+                return true;
+            case "toggle":
+                return true;
+            case "mounted":
+                return false;
+        }
+        return true;
+    }
+    return {
+        setters: [],
+        execute: function () {
+        }
+    };
+});
+System.register("interpreter_native", ["form", "interpreter_core", "serialize"], function (exports_4, context_4) {
+    "use strict";
+    var form_1, interpreter_core_1, serialize_1, NativeInterpreter;
+    var __moduleName = context_4 && context_4.id;
+    function handleVirtualdomEventSync(contents) {
+        var xhr = new XMLHttpRequest();
+        xhr.timeout = 1000;
+        xhr.open("GET", "/handle/event.please", false);
+        xhr.setRequestHeader("Content-Type", "application/json");
+        xhr.send(contents);
+        return JSON.parse(xhr.responseText);
+    }
+    function targetId(target) {
+        if (!(target instanceof Node)) {
+            return null;
+        }
+        var ourTarget = target;
+        var realId = null;
+        while (realId == null) {
+            if (ourTarget === null) {
+                return null;
+            }
+            if (ourTarget instanceof Element) {
+                realId = ourTarget.getAttribute("data-dioxus-id");
+            }
+            ourTarget = ourTarget.parentNode;
+        }
+        return parseInt(realId);
+    }
+    return {
+        setters: [
+            function (form_1_1) {
+                form_1 = form_1_1;
+            },
+            function (interpreter_core_1_1) {
+                interpreter_core_1 = interpreter_core_1_1;
+            },
+            function (serialize_1_1) {
+                serialize_1 = serialize_1_1;
+            }
+        ],
+        execute: function () {
+            NativeInterpreter = (function (_super) {
+                __extends(NativeInterpreter, _super);
+                function NativeInterpreter(root) {
+                    var _this = _super.call(this, root, function (event) { return _this.handleEvent(event, event.type, true); }) || this;
+                    _this.intercept_link_redirects = true;
+                    _this.liveview = false;
+                    _this.ipc = window.ipc;
+                    return _this;
+                }
+                NativeInterpreter.prototype.serializeIpcMessage = function (method, params) {
+                    if (params === void 0) { params = {}; }
+                    return JSON.stringify({ method: method, params: params });
+                };
+                NativeInterpreter.prototype.scrollTo = function (id, behavior) {
+                    var node = this.nodes[id];
+                    if (node instanceof HTMLElement) {
+                        node.scrollIntoView({ behavior: behavior });
+                    }
+                };
+                NativeInterpreter.prototype.getClientRect = function (id) {
+                    var node = this.nodes[id];
+                    if (node instanceof HTMLElement) {
+                        var rect = node.getBoundingClientRect();
+                        return {
+                            type: "GetClientRect",
+                            origin: [rect.x, rect.y],
+                            size: [rect.width, rect.height],
+                        };
+                    }
+                };
+                NativeInterpreter.prototype.setFocus = function (id, focus) {
+                    var node = this.nodes[id];
+                    if (node instanceof HTMLElement) {
+                        if (focus) {
+                            node.focus();
+                        }
+                        else {
+                            node.blur();
+                        }
+                    }
+                };
+                NativeInterpreter.prototype.LoadChild = function (array) {
+                    var node = this.stack[this.stack.length - 1];
+                    for (var i = 0; i < array.length; i++) {
+                        var end = array[i];
+                        for (node = node.firstChild; end > 0; end--) {
+                            node = node.nextSibling;
+                        }
+                    }
+                    return node;
+                };
+                NativeInterpreter.prototype.AppendChildren = function (id, many) {
+                    var root = this.nodes[id];
+                    var els = this.stack.splice(this.stack.length - many);
+                    for (var k = 0; k < many; k++) {
+                        root.appendChild(els[k]);
+                    }
+                };
+                NativeInterpreter.prototype.handleEvent = function (event, name, bubbles) {
+                    var target = event.target;
+                    var realId = targetId(target);
+                    var contents = serialize_1.serializeEvent(event);
+                    if (target instanceof HTMLElement) {
+                        contents.values = form_1.retriveValues(event, target);
+                    }
+                    var body = {
+                        name: name,
+                        data: contents,
+                        element: realId,
+                        bubbles: bubbles,
+                    };
+                    this.preventDefaults(event, target);
+                    if (this.liveview) {
+                        if (target instanceof HTMLInputElement && (event.type === "change" || event.type === "input")) {
+                            if (target.getAttribute("type") === "file") {
+                                this.readFiles(target, contents, bubbles, realId, name);
+                            }
+                        }
+                    }
+                    else {
+                        var res = handleVirtualdomEventSync(JSON.stringify(body));
+                        if (res.preventDefault) {
+                            event.preventDefault();
+                        }
+                        if (res.stopPropagation) {
+                            event.stopPropagation();
+                        }
+                    }
+                };
+                NativeInterpreter.prototype.readFiles = function (target, contents, bubbles, realId, name) {
+                    return __awaiter(this, void 0, void 0, function () {
+                        var files, file_contents, i, file, _a, _b, _c, _d, _e, message;
+                        return __generator(this, function (_f) {
+                            switch (_f.label) {
+                                case 0:
+                                    files = target.files;
+                                    file_contents = {};
+                                    i = 0;
+                                    _f.label = 1;
+                                case 1:
+                                    if (!(i < files.length)) return [3, 4];
+                                    file = files[i];
+                                    _a = file_contents;
+                                    _b = file.name;
+                                    _d = (_c = Array).from;
+                                    _e = Uint8Array.bind;
+                                    return [4, file.arrayBuffer()];
+                                case 2:
+                                    _a[_b] = _d.apply(_c, [new (_e.apply(Uint8Array, [void 0, _f.sent()]))()]);
+                                    _f.label = 3;
+                                case 3:
+                                    i++;
+                                    return [3, 1];
+                                case 4:
+                                    contents.files = { files: file_contents };
+                                    message = this.serializeIpcMessage("user_event", {
+                                        name: name,
+                                        element: realId,
+                                        data: contents,
+                                        bubbles: bubbles,
+                                    });
+                                    this.ipc.postMessage(message);
+                                    return [2];
+                            }
+                        });
+                    });
+                };
+                NativeInterpreter.prototype.preventDefaults = function (event, target) {
+                    var preventDefaultRequests = null;
+                    if (target instanceof Element) {
+                        preventDefaultRequests = target.getAttribute("dioxus-prevent-default");
+                    }
+                    if (preventDefaultRequests && preventDefaultRequests.includes("on".concat(event.type))) {
+                        event.preventDefault();
+                    }
+                    if (event.type === "submit") {
+                        event.preventDefault();
+                    }
+                    if (target instanceof Element && event.type === "click") {
+                        this.handleClickNavigate(event, target, preventDefaultRequests);
+                    }
+                };
+                NativeInterpreter.prototype.handleClickNavigate = function (event, target, preventDefaultRequests) {
+                    if (!this.intercept_link_redirects) {
+                        return;
+                    }
+                    if (target.tagName === "BUTTON" && event.type == "submit") {
+                        event.preventDefault();
+                    }
+                    var a_element = target.closest("a");
+                    if (a_element == null) {
+                        return;
+                    }
+                    event.preventDefault();
+                    var elementShouldPreventDefault = preventDefaultRequests && preventDefaultRequests.includes("onclick");
+                    var aElementShouldPreventDefault = a_element.getAttribute("dioxus-prevent-default");
+                    var linkShouldPreventDefault = aElementShouldPreventDefault &&
+                        aElementShouldPreventDefault.includes("onclick");
+                    if (!elementShouldPreventDefault && !linkShouldPreventDefault) {
+                        var href = a_element.getAttribute("href");
+                        if (href !== "" && href !== null && href !== undefined) {
+                            this.ipc.postMessage(this.serializeIpcMessage("browser_open", { href: href }));
+                        }
+                    }
+                };
+                return NativeInterpreter;
+            }(interpreter_core_1.Interpreter));
+            exports_4("NativeInterpreter", NativeInterpreter);
+        }
+    };
+});

+ 159 - 0
packages/interpreter/src/js/web.js

@@ -0,0 +1,159 @@
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    };
+    return function (d, b) {
+        if (typeof b !== "function" && b !== null)
+            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+System.register("interpreter_core", [], function (exports_1, context_1) {
+    "use strict";
+    var Interpreter;
+    var __moduleName = context_1 && context_1.id;
+    return {
+        setters: [],
+        execute: function () {
+            Interpreter = (function () {
+                function Interpreter(root, handler) {
+                    this.root = root;
+                    this.nodes = [root];
+                    this.stack = [root];
+                    this.global = {};
+                    this.local = {};
+                    this.handler = handler;
+                }
+                Interpreter.prototype.createListener = function (event_name, element, bubbles) {
+                    if (bubbles) {
+                        if (this.global[event_name] === undefined) {
+                            this.global[event_name] = { active: 1, callback: this.handler };
+                            this.root.addEventListener(event_name, this.handler);
+                        }
+                        else {
+                            this.global[event_name].active++;
+                        }
+                    }
+                    else {
+                        var id = element.getAttribute("data-dioxus-id");
+                        if (!this.local[id]) {
+                            this.local[id] = {};
+                        }
+                        element.addEventListener(event_name, this.handler);
+                    }
+                };
+                Interpreter.prototype.removeListener = function (element, event_name, bubbles) {
+                    if (bubbles) {
+                        this.removeBubblingListener(event_name);
+                    }
+                    else {
+                        this.removeNonBubblingListener(element, event_name);
+                    }
+                };
+                Interpreter.prototype.removeBubblingListener = function (event_name) {
+                    this.global[event_name].active--;
+                    if (this.global[event_name].active === 0) {
+                        this.root.removeEventListener(event_name, this.global[event_name].callback);
+                        delete this.global[event_name];
+                    }
+                };
+                Interpreter.prototype.removeNonBubblingListener = function (element, event_name) {
+                    var id = element.getAttribute("data-dioxus-id");
+                    delete this.local[id][event_name];
+                    if (Object.keys(this.local[id]).length === 0) {
+                        delete this.local[id];
+                    }
+                    element.removeEventListener(event_name, this.handler);
+                };
+                Interpreter.prototype.removeAllNonBubblingListeners = function (element) {
+                    var id = element.getAttribute("data-dioxus-id");
+                    delete this.local[id];
+                };
+                return Interpreter;
+            }());
+            exports_1("Interpreter", Interpreter);
+        }
+    };
+});
+System.register("interpreter_web", ["interpreter_core"], function (exports_2, context_2) {
+    "use strict";
+    var interpreter_core_1, WebInterpreter;
+    var __moduleName = context_2 && context_2.id;
+    return {
+        setters: [
+            function (interpreter_core_1_1) {
+                interpreter_core_1 = interpreter_core_1_1;
+            }
+        ],
+        execute: function () {
+            WebInterpreter = (function (_super) {
+                __extends(WebInterpreter, _super);
+                function WebInterpreter(root, handler) {
+                    return _super.call(this, root, handler) || this;
+                }
+                WebInterpreter.prototype.LoadChild = function (ptr, len) {
+                    var node = this.stack[this.stack.length - 1];
+                    var ptr_end = ptr + len;
+                    for (; ptr < ptr_end; ptr++) {
+                        var end = this.m.getUint8(ptr);
+                        for (node = node.firstChild; end > 0; end--) {
+                            node = node.nextSibling;
+                        }
+                    }
+                    return node;
+                };
+                WebInterpreter.prototype.saveTemplate = function (nodes, tmpl_id) {
+                    this.templates[tmpl_id] = nodes;
+                };
+                WebInterpreter.prototype.hydrateRoot = function (ids) {
+                    var hydrateNodes = document.querySelectorAll('[data-node-hydration]');
+                    for (var i = 0; i < hydrateNodes.length; i++) {
+                        var hydrateNode = hydrateNodes[i];
+                        var hydration = hydrateNode.getAttribute('data-node-hydration');
+                        var split = hydration.split(',');
+                        var id = ids[parseInt(split[0])];
+                        this.nodes[id] = hydrateNode;
+                        if (split.length > 1) {
+                            hydrateNode.listening = split.length - 1;
+                            hydrateNode.setAttribute('data-dioxus-id', id.toString());
+                            for (var j = 1; j < split.length; j++) {
+                                var listener = split[j];
+                                var split2 = listener.split(':');
+                                var event_name = split2[0];
+                                var bubbles = split2[1] === '1';
+                                this.createListener(event_name, hydrateNode, bubbles);
+                            }
+                        }
+                    }
+                    var treeWalker = document.createTreeWalker(document.body, NodeFilter.SHOW_COMMENT);
+                    var currentNode = treeWalker.nextNode();
+                    while (currentNode) {
+                        var id = currentNode.textContent;
+                        var split = id.split('node-id');
+                        if (split.length > 1) {
+                            this.nodes[ids[parseInt(split[1])]] = currentNode.nextSibling;
+                        }
+                        currentNode = treeWalker.nextNode();
+                    }
+                };
+                WebInterpreter.prototype.getNode = function (id) {
+                    return this.nodes[id];
+                };
+                WebInterpreter.prototype.appendChildren = function (id, many) {
+                    var root = this.nodes[id];
+                    var els = this.stack.splice(this.stack.length - many);
+                    for (var k = 0; k < many; k++) {
+                        root.appendChild(els[k]);
+                    }
+                };
+                return WebInterpreter;
+            }(interpreter_core_1.Interpreter));
+            exports_2("WebInterpreter", WebInterpreter);
+        }
+    };
+});

+ 2 - 2
packages/interpreter/src/lib.rs

@@ -2,8 +2,8 @@
 #![doc(html_logo_url = "https://avatars.githubusercontent.com/u/79236386")]
 #![doc(html_favicon_url = "https://avatars.githubusercontent.com/u/79236386")]
 
-pub static INTERPRETER_JS: &str = include_str!("./gen/interpreter.js");
-pub static COMMON_JS: &str = include_str!("./gen/common.js");
+pub static INTERPRETER_JS: &str = include_str!("./js/native.js");
+pub static COMMON_JS: &str = include_str!("./js/web.js");
 
 #[cfg(all(feature = "binary-protocol", feature = "sledgehammer"))]
 mod write_native_mutations;

+ 3 - 0
packages/interpreter/src/ts/.gitignore

@@ -0,0 +1,3 @@
+# please dont accidentally run tsc and commit your js in this dir.
+*.js
+

+ 1 - 0
packages/interpreter/src/ts/interpreter_core.ts

@@ -12,6 +12,7 @@ export class Interpreter {
       [key: string]: EventListener
     }
   };
+
   root: HTMLElement;
   handler: EventListener;
   nodes: Node[];

+ 0 - 5
packages/interpreter/tsconfig.json

@@ -11,12 +11,7 @@
         "noImplicitAny": true,
         "removeComments": true,
         "preserveConstEnums": true,
-        "outFile": "gen/main.js",
-        "sourceMap": true
     },
-    "include": [
-        "src/ts/*.ts"
-    ],
     "exclude": [
         "**/*.spec.ts"
     ]

+ 10 - 0
packages/interpreter/tsconfig.native.json

@@ -0,0 +1,10 @@
+{
+    // extends the base
+    "extends": "./tsconfig.json",
+    "compilerOptions": {
+        "outFile": "src/js/native.js"
+    },
+    "files": [
+        "src/ts/interpreter_native.ts"
+    ],
+}

+ 10 - 0
packages/interpreter/tsconfig.web.json

@@ -0,0 +1,10 @@
+{
+    // extends the base
+    "extends": "./tsconfig.json",
+    "compilerOptions": {
+        "outFile": "src/js/web.js"
+    },
+    "files": [
+        "src/ts/interpreter_web.ts"
+    ],
+}