diff options
-rw-r--r-- | lib/js/urweb.js | 106 | ||||
-rw-r--r-- | tests/babySpawn.ur | 3 | ||||
-rw-r--r-- | tests/dynTable.ur | 8 |
3 files changed, 94 insertions, 23 deletions
diff --git a/lib/js/urweb.js b/lib/js/urweb.js index b8ebc1c6..a181bbf9 100644 --- a/lib/js/urweb.js +++ b/lib/js/urweb.js @@ -691,6 +691,8 @@ function lastParent() { return pos; } +var thisScript = null; + function parent() { return thisScript ? thisScript.parentNode : lastParent(); } @@ -703,10 +705,21 @@ function addNode(node) { lastParent().appendChild(node); } -var thisScript = null; - function runScripts(node) { - if (node.getElementsByTagName) { + if (node.tagName == "SCRIPT") { + var savedScript = thisScript; + thisScript = node; + + try { + eval(thisScript.text); + } catch (v) { + doExn(v); + } + if (thisScript.parentNode) + thisScript.parentNode.removeChild(thisScript); + + thisScript = savedScript; + } else if (node.getElementsByTagName) { var savedScript = thisScript; var scripts = node.getElementsByTagName("script"), scriptsCopy = []; @@ -747,7 +760,7 @@ function normalizeTable(table) { var script, next; - while (table.tagName != "TABLE") + while (table && table.tagName != "TABLE") table = table.parentNode; for (var tbody = table.firstChild; tbody; tbody = tbody.nextSibling) { @@ -776,7 +789,12 @@ function normalizeTable(table) { table.appendChild(tbody); } +var suspendScripts = false; + function dyn(pnode, s) { + if (suspendScripts) + return; + var x = document.createElement("script"); x.dead = false; x.signal = s; @@ -814,8 +832,14 @@ function dyn(pnode, s) { normalizeTable(x.parentNode); var dummy = document.createElement("body"); - dummy.innerHTML = "<table>" + html + "</table>"; - runScripts(dummy); + suspendScripts = true; + try { + dummy.innerHTML = "<table>" + html + "</table>"; + } catch (e) { + suspendScripts = false; + throw e; + } + var table = x.parentNode; if (table) { @@ -843,12 +867,23 @@ function dyn(pnode, s) { for (var node = tbody.firstChild; node; node = next) { next = node.nextSibling; table.insertBefore(node, x); + suspendScripts = false; + runScripts(node); + suspendScripts = true; } } + + suspendScripts = false; } else if (pnode == "tr") { var dummy = document.createElement("body"); - dummy.innerHTML = "<table><tr>" + html + "</tr></table>"; - runScripts(dummy); + suspendScripts = true; + try { + dummy.innerHTML = "<table><tr>" + html + "</tr></table>"; + } catch (e) { + suspendScripts = false; + throw e; + } + var table = x.parentNode; if (table) { @@ -866,14 +901,27 @@ function dyn(pnode, s) { for (var node = tr.firstChild; node; node = next) { next = node.nextSibling; table.insertBefore(node, x); + suspendScripts = false; + runScripts(node); + suspendScripts = true; } - } + }; + + suspendScripts = false; } else { firstChild = document.createElement("span"); - firstChild.innerHTML = html; + + suspendScripts = true; + try { + firstChild.innerHTML = html; + if (x.parentNode) + x.parentNode.insertBefore(firstChild, x); + } catch (e) { + suspendScripts = false; + throw e; + } + suspendScripts = false; runScripts(firstChild); - if (x.parentNode) - x.parentNode.insertBefore(firstChild, x); } }; @@ -909,13 +957,18 @@ function setInnerHTML(node, html) { var cls = {v : null}; var html = flatten(cls, html); x.closures = cls.v; + suspendScripts = true; node.innerHTML = html; + suspendScripts = false; runScripts(node); } var maySuspend = true; function active(s) { + if (suspendScripts) + return; + var span = document.createElement("span"); addNode(span); var ms = maySuspend; @@ -944,6 +997,9 @@ function input(x, s, recreate, type, name) { } function inp(s, name) { + if (suspendScripts) + return; + var x = input(document.createElement("input"), s, function(x) { return function(v) { if (x.value != v) x.value = v; }; }, null, name); x.value = s.data; @@ -969,6 +1025,9 @@ function setSelectValue(x, v) { } function sel(s, content) { + if (suspendScripts) + return; + var dummy = document.createElement("span"); dummy.innerHTML = "<select>" + content + "</select>"; var x = input(dummy.firstChild, s, function(x) { return function(v) { if (selectValue(x) != v) setSelectValue(x, v); }; }); @@ -989,6 +1048,9 @@ function sel(s, content) { } function chk(s) { + if (suspendScripts) + return; + var x = input(document.createElement("input"), s, function(x) { return function(v) { if (x.checked != v) x.checked = v; }; }, "checkbox"); x.defaultChecked = x.checked = s.data; @@ -998,6 +1060,9 @@ function chk(s) { } function tbx(s) { + if (suspendScripts) + return; + var x = input(document.createElement("textarea"), s, function(x) { return function(v) { if (x.value != v) x.value = v; }; }); x.innerHTML = s.data; @@ -1007,12 +1072,17 @@ function tbx(s) { } function dynClass(html, s_class, s_style) { + if (suspendScripts) + return; + var htmlCls = {v : null}; html = flatten(htmlCls, html); htmlCls = htmlCls.v; var dummy = document.createElement("body"); + suspendScripts = true; dummy.innerHTML = html; + suspendScripts = false; var html = dummy.firstChild; dummy.removeChild(html); addNode(html); @@ -1863,14 +1933,12 @@ function fresh() { } function giveFocus(id) { - window.setTimeout(function() { - var node = document.getElementById(id); + var node = document.getElementById(id); - if (node) - node.focus(); - else - er("Tried to give focus to ID not used in document: " + id); - }, 0); + if (node) + node.focus(); + else + er("Tried to give focus to ID not used in document: " + id); } diff --git a/tests/babySpawn.ur b/tests/babySpawn.ur new file mode 100644 index 00000000..d43e739f --- /dev/null +++ b/tests/babySpawn.ur @@ -0,0 +1,3 @@ +fun main () : transaction page = return <xml><body> + <button onclick={fn _ => spawn (alert "Hi")}/> +</body></xml> diff --git a/tests/dynTable.ur b/tests/dynTable.ur index 7fe295c6..d73dc52c 100644 --- a/tests/dynTable.ur +++ b/tests/dynTable.ur @@ -8,14 +8,14 @@ fun main () : transaction page = <tr> <td>Hi</td> </tr> </table> - <button onclick={v <- get n; - set n (v + 1); - set s <xml><tr> <td>Whoa!({[v]})</td> </tr></xml>}/> + <button onclick={fn _ => v <- get n; + set n (v + 1); + set s <xml><tr> <td>Whoa!({[v]})</td> </tr></xml>}/> <table> <tr> <dyn signal={signal s1}/> </tr> <tr> <td>Hi!</td> </tr> </table> - <button onclick={set s1 <xml><td>Whoa!</td></xml>}/> + <button onclick={fn _ => set s1 <xml><td>Whoa!</td></xml>}/> </body></xml> |