summaryrefslogtreecommitdiff
path: root/lib/js/urweb.js
diff options
context:
space:
mode:
authorBenjamin Barenblat <bbaren@mit.edu>2017-07-23 09:50:04 -0400
committerBenjamin Barenblat <bbaren@mit.edu>2017-07-23 09:50:04 -0400
commit0cccdb0ae595cd7e3e136e984ac7b95b99f71a53 (patch)
tree491d3b13813610943c60460d3e178d3a73916346 /lib/js/urweb.js
Import urweb_20170720+dfsg.orig.tar.gz
[dgit import orig urweb_20170720+dfsg.orig.tar.gz]
Diffstat (limited to 'lib/js/urweb.js')
-rw-r--r--lib/js/urweb.js2252
1 files changed, 2252 insertions, 0 deletions
diff --git a/lib/js/urweb.js b/lib/js/urweb.js
new file mode 100644
index 0000000..ebe192c
--- /dev/null
+++ b/lib/js/urweb.js
@@ -0,0 +1,2252 @@
+// Detect browser quirks that we should be aware of.
+
+function needsDynPrefix() {
+ var span = document.createElement("span");
+ span.innerHTML = "<script>alert('test');</script>";
+ var scripts = span.getElementsByTagName("script");
+ return scripts.length == 0;
+}
+
+var dynPrefix = needsDynPrefix() ? "<span style=\"display:none\">A</span>" : "";
+
+// Function versions of operators
+
+function not(x) { return !x; }
+function neg(x) { return -x; }
+
+function eq(x, y) { return x == y; }
+function plus(x, y) { return x + y; }
+function minus(x, y) { return x - y; }
+function times(x, y) { return x * y; }
+function div(x, y) { return x / y; }
+function divInt(x, y) { if (y == 0) er("Division by zero"); var n = x / y; return n < 0 ? Math.ceil(n) : Math.floor(n); }
+function mod(x, y) { return x % y; }
+function modInt(x, y) { if (y == 0) er("Division by zero"); var n = x % y; return n < 0 ? Math.ceil(n) : Math.floor(n); }
+function lt(x, y) { return x < y; }
+function le(x, y) { return x <= y; }
+
+// Characters
+
+function isLower(c) { return c >= 'a' && c <= 'z'; }
+function isUpper(c) { return c >= 'A' && c <= 'Z'; }
+function isAlpha(c) { return isLower(c) || isUpper(c); }
+function isDigit(c) { return c >= '0' && c <= '9'; }
+function isAlnum(c) { return isAlpha(c) || isDigit(c); }
+function isBlank(c) { return c == ' ' || c == '\t'; }
+function isSpace(c) { return isBlank(c) || c == '\r' || c == '\n'; }
+function isXdigit(c) { return isDigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); }
+function ord(c) { return c.charCodeAt(0); }
+function isPrint(c) { return ord(c) > 31 && ord(c) < 127; }
+function toLower(c) { return c.toLowerCase(); }
+function toUpper(c) { return c.toUpperCase(); }
+
+// Lists
+
+function cons(v, ls) {
+ return { next : ls, data : v };
+}
+function rev(ls) {
+ var acc = null;
+ for (; ls; ls = ls.next)
+ acc = cons(ls.data, acc);
+ return acc;
+}
+function concat(ls1, ls2) {
+ var acc = ls2;
+ ls1 = rev(ls1);
+ for (; ls1; ls1 = ls1.next)
+ acc = cons(ls1.data, acc);
+ return acc;
+}
+function member(x, ls) {
+ for (; ls; ls = ls.next)
+ if (ls.data == x)
+ return true;
+ return false;
+}
+function remove(x, ls) {
+ var acc = null;
+
+ for (; ls; ls = ls.next)
+ if (ls.data == x)
+ return concat(acc, ls.next);
+ else
+ acc = cons(ls.data, acc);
+
+ return ls;
+}
+function union(ls1, ls2) {
+ var acc = ls2;
+
+ for (; ls1; ls1 = ls1.next)
+ if (!member(ls1.data, ls2))
+ acc = cons(ls1.data, acc);
+
+ return acc;
+}
+function length(ls) {
+ var acc = 0;
+
+ for (; ls; ls = ls.next)
+ ++acc;
+
+ return acc;
+}
+
+
+// Floats
+
+function float(n) {
+ return n;
+}
+
+function trunc(n) {
+ return ~~n;
+}
+
+function ceil(n) {
+ return Math.ceil(n);
+}
+
+function round(n) {
+ return Math.round(n);
+}
+
+function pow(n, m) {
+ return Math.pow(n, m);
+}
+
+function sqrt(n){
+ return Math.sqrt(n);
+}
+
+function sin(n){
+ return Math.sin(n);
+}
+
+function cos(n){
+ return Math.cos(n);
+}
+
+function log(n){
+ return Math.log(n);
+}
+
+function exp(n){
+ return Math.exp(n);
+}
+
+function asin(n){
+ return Math.asin(n);
+}
+function acos(n){
+ return Math.acos(n);
+}
+
+function atan(n){
+ return Math.atan(n);
+}
+
+function atan2(n, m){
+ return Math.atan2(n, m);
+}
+
+function floor(n){
+ return Math.floor(n);
+}
+
+function abs(n){
+ return Math.abs(n);
+}
+
+// Time, represented as counts of microseconds since the epoch
+
+var time_format = "%c";
+
+function showTime(tm) {
+ return strftime(time_format, tm);
+}
+
+function showTimeHtml(tm) {
+ return eh(showTime(tm));
+}
+
+function now() {
+ return (new Date()).getTime() * 1000;
+}
+
+function diffInSeconds(tm1, tm2) {
+ return Math.round((tm2 - tm1) / 1000000);
+}
+
+function diffInMilliseconds(tm1, tm2) {
+ return Math.round((tm2 - tm1) / 1000);
+}
+
+function toSeconds(tm) {
+ return Math.round(tm / 1000000);
+}
+
+function toMilliseconds(tm) {
+ return Math.round(tm / 1000);
+}
+
+function fromMilliseconds(tm) {
+ return tm * 1000;
+}
+
+function addSeconds(tm, n) {
+ return tm + n * 1000000;
+}
+
+function stringToTime_error(string) {
+ var t = Date.parse(string);
+ if (isNaN(t))
+ er("Invalid date string: " + string);
+ else
+ return t * 1000;
+}
+
+function stringToTime(string) {
+ try {
+ var t = Date.parse(string);
+ if (isNaN(t))
+ return null;
+ else
+ return t * 1000;
+ } catch (e) {
+ return null;
+ }
+}
+
+/*
+strftime() implementation from:
+YUI 3.4.1 (build 4118)
+Copyright 2011 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+
+var xPad=function (x, pad, r)
+{
+ if(typeof r === "undefined")
+ {
+ r=10;
+ }
+ pad = pad.toString();
+ for( ; parseInt(x, 10)<r && r>1; r/=10) {
+ x = pad + x;
+ }
+ return x.toString();
+};
+
+var YDateEn = {
+ a: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+ A: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+ b: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+ B: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+ c: "%a %d %b %Y %T %Z",
+ p: ["AM", "PM"],
+ P: ["am", "pm"],
+ r: "%I:%M:%S %p",
+ x: "%d/%m/%y",
+ X: "%T"
+};
+
+var Dt = {
+ formats: {
+ a: function (d, l) { return l.a[d.getDay()]; },
+ A: function (d, l) { return l.A[d.getDay()]; },
+ b: function (d, l) { return l.b[d.getMonth()]; },
+ B: function (d, l) { return l.B[d.getMonth()]; },
+ C: function (d) { return xPad(parseInt(d.getFullYear()/100, 10), 0); },
+ d: ["getDate", "0"],
+ e: ["getDate", " "],
+ g: function (d) { return xPad(parseInt(Dt.formats.G(d)%100, 10), 0); },
+ G: function (d) {
+ var y = d.getFullYear();
+ var V = parseInt(Dt.formats.V(d), 10);
+ var W = parseInt(Dt.formats.W(d), 10);
+
+ if(W > V) {
+ y++;
+ } else if(W===0 && V>=52) {
+ y--;
+ }
+
+ return y;
+ },
+ H: ["getHours", "0"],
+ I: function (d) { var I=d.getHours()%12; return xPad(I===0?12:I, 0); },
+ j: function (d) {
+ var gmd_1 = new Date("" + d.getFullYear() + "/1/1 GMT");
+ var gmdate = new Date("" + d.getFullYear() + "/" + (d.getMonth()+1) + "/" + d.getDate() + " GMT");
+ var ms = gmdate - gmd_1;
+ var doy = parseInt(ms/60000/60/24, 10)+1;
+ return xPad(doy, 0, 100);
+ },
+ k: ["getHours", " "],
+ l: function (d) { var I=d.getHours()%12; return xPad(I===0?12:I, " "); },
+ m: function (d) { return xPad(d.getMonth()+1, 0); },
+ M: ["getMinutes", "0"],
+ p: function (d, l) { return l.p[d.getHours() >= 12 ? 1 : 0 ]; },
+ P: function (d, l) { return l.P[d.getHours() >= 12 ? 1 : 0 ]; },
+ s: function (d, l) { return parseInt(d.getTime()/1000, 10); },
+ S: ["getSeconds", "0"],
+ u: function (d) { var dow = d.getDay(); return dow===0?7:dow; },
+ U: function (d) {
+ var doy = parseInt(Dt.formats.j(d), 10);
+ var rdow = 6-d.getDay();
+ var woy = parseInt((doy+rdow)/7, 10);
+ return xPad(woy, 0);
+ },
+ V: function (d) {
+ var woy = parseInt(Dt.formats.W(d), 10);
+ var dow1_1 = (new Date("" + d.getFullYear() + "/1/1")).getDay();
+ var idow = woy + (dow1_1 > 4 || dow1_1 <= 1 ? 0 : 1);
+ if(idow === 53 && (new Date("" + d.getFullYear() + "/12/31")).getDay() < 4)
+ {
+ idow = 1;
+ }
+ else if(idow === 0)
+ {
+ idow = Dt.formats.V(new Date("" + (d.getFullYear()-1) + "/12/31"));
+ }
+
+ return xPad(idow, 0);
+ },
+ w: "getDay",
+ W: function (d) {
+ var doy = parseInt(Dt.formats.j(d), 10);
+ var rdow = 7-Dt.formats.u(d);
+ var woy = parseInt((doy+rdow)/7, 10);
+ return xPad(woy, 0, 10);
+ },
+ y: function (d) { return xPad(d.getFullYear()%100, 0); },
+ Y: "getFullYear",
+ z: function (d) {
+ var o = d.getTimezoneOffset();
+ var H = xPad(parseInt(Math.abs(o/60), 10), 0);
+ var M = xPad(Math.abs(o%60), 0);
+ return (o>0?"-":"+") + H + M;
+ },
+ Z: function (d) {
+ var tz = d.toString().replace(/^.*:\d\d( GMT[+-]\d+)? \(?([A-Za-z ]+)\)?\d*$/, "$2").replace(/[a-z ]/g, "");
+ if(tz.length > 4) {
+ tz = Dt.formats.z(d);
+ }
+ return tz;
+ },
+ "%": function (d) { return "%"; }
+ },
+
+ aggregates: {
+ c: "locale",
+ D: "%m/%d/%y",
+ F: "%Y-%m-%d",
+ h: "%b",
+ n: "\n",
+ r: "%I:%M:%S %p",
+ R: "%H:%M",
+ t: "\t",
+ T: "%H:%M:%S",
+ x: "locale",
+ X: "locale"
+ },
+
+ format : function (oDate, format) {
+ var replace_aggs = function (m0, m1) {
+ var f = Dt.aggregates[m1];
+ return (f === "locale" ? YDateEn[m1] : f);
+ };
+
+ var replace_formats = function (m0, m1) {
+ var f = Dt.formats[m1];
+ switch(typeof f) {
+ case "string":
+ return oDate[f]();
+ case "function":
+ return f.call(oDate, oDate, YDateEn);
+ case "array":
+ case "object":
+ if(typeof(f[0]) === "string")
+ return xPad(oDate[f[0]](), f[1]);
+ default:
+ return m1;
+ }
+ };
+
+ while(format.match(/%[cDFhnrRtTxX]/)) {
+ format = format.replace(/%([cDFhnrRtTxX])/g, replace_aggs);
+ }
+
+ var str = format.replace(/%([aAbBCdegGHIjklmMpPsSuUVwWyYzZ%])/g, replace_formats);
+
+ replace_aggs = replace_formats = undefined;
+
+ return str;
+ }
+};
+
+// End of YUI code
+
+function strftime(fmt, thisTime)
+{
+ var thisDate = new Date();
+ thisDate.setTime(Math.floor(thisTime / 1000));
+ return Dt.format(thisDate, fmt);
+};
+
+function fromDatetime(year, month, date, hour, minute, second) {
+ return (new Date(year, month, date, hour, minute, second)).getTime() * 1000;
+};
+
+function datetimeYear(t) {
+ return (new Date(t / 1000)).getYear() + 1900;
+};
+
+function datetimeMonth(t) {
+ return (new Date(t / 1000)).getMonth();
+};
+
+function datetimeDay(t) {
+ return (new Date(t / 1000)).getDate();
+};
+
+function datetimeHour(t) {
+ return (new Date(t / 1000)).getHours();
+};
+
+function datetimeMinute(t) {
+ return (new Date(t / 1000)).getMinutes();
+};
+
+function datetimeSecond(t) {
+ return (new Date(t / 1000)).getSeconds();
+};
+
+function datetimeDayOfWeek(t) {
+ return (new Date(t / 1000)).getDay();
+};
+
+
+// Error handling
+
+function uw_debug(msg) {
+ try {
+ console.debug(msg);
+ } catch (e) {
+ alert("DEBUG: " + msg);
+ }
+
+ return 0;
+}
+
+function whine(msg) {
+ alert(msg);
+ throw msg;
+}
+
+function pf(loc) {
+ throw ("Pattern match failure (" + loc + ")");
+}
+
+var lameDuck = false;
+
+function runHandlers(kind, ls, arg) {
+ if (!lameDuck) {
+ if (ls == null)
+ alert(kind + ": " + arg);
+ for (; ls; ls = ls.next)
+ try {
+ exec({c:"a", f:{c:"a", f:ls.data, x:{c:"c", v:arg}}, x:{c:"c", v:null}});
+ } catch (v) { }
+ }
+}
+
+var errorHandlers = null;
+
+function flift0(v) {
+ return {c:"c", v:v};
+}
+
+function onError(f) {
+ errorHandlers = cons(flift0(f), errorHandlers);
+}
+
+function er(s) {
+ runHandlers("Error", errorHandlers, s);
+ throw {uw_error: s};
+}
+
+var failHandlers = null;
+
+function onFail(f) {
+ failHandlers = cons(flift0(f), failHandlers);
+}
+
+function doExn(v) {
+ if (v == null || v.uw_error == null) {
+ var s = (v == null ? "null" : v.message ? v.message : v.toString());
+ if (v != null && v.fileName && v.lineNumber)
+ s += " (" + v.fileName + ":" + v.lineNumber + ")";
+ runHandlers("Fail", failHandlers, s);
+ }
+}
+
+var disconnectHandlers = null;
+
+function flift(f) {
+ return {c: "c", v:{env:cons(f,null), body:{c:"v", n:1}}};
+}
+
+function onDisconnect(f) {
+ disconnectHandlers = cons(flift(f), disconnectHandlers);
+}
+
+function discon() {
+ runHandlers("Disconnect", disconnectHandlers, null);
+}
+
+var connectHandlers = null;
+
+function onConnectFail(f) {
+ connectHandlers = cons(flift(f), connectHandlers);
+}
+
+function conn(msg) {
+ var rx = /(.*)<body>((.|\n|\r)*)<\/body>(.*)/g;
+ var arr = rx.exec(msg);
+ msg = (arr && arr.length >= 3) ? arr[2] : msg;
+ runHandlers("RPC failure", connectHandlers, msg);
+}
+
+var serverHandlers = null;
+
+function onServerError(f) {
+ serverHandlers = cons(flift0(f), serverHandlers);
+}
+
+function servErr(s) {
+ window.setTimeout(function () { runHandlers("Server", serverHandlers, s); }, 0);
+}
+
+// Key and mouse events
+
+var uw_event = null;
+
+function uw_getEvent() {
+ return window.event ? window.event : uw_event;
+}
+
+function firstGood(x, y) {
+ if (x == undefined || x == 0)
+ return y;
+ else
+ return x;
+}
+
+function uw_mouseEvent() {
+ var ev = uw_getEvent();
+
+ return {_ScreenX : firstGood(ev.screenX, 0),
+ _ScreenY : firstGood(ev.screenY, 0),
+ _ClientX : firstGood(ev.clientX, 0),
+ _ClientY : firstGood(ev.clientY, 0),
+ _CtrlKey : firstGood(ev.ctrlKey, false),
+ _ShiftKey : firstGood(ev.shiftKey, false),
+ _AltKey : firstGood(ev.altKey, false),
+ _MetaKey : firstGood(ev.metaKey, false),
+ _Button : ev.button == 2 ? "Right" : ev.button == 1 ? "Middle" : "Left"};
+}
+
+function uw_keyEvent() {
+ var ev = uw_getEvent();
+
+ return {_KeyCode : firstGood(ev.keyCode, ev.which),
+ _CtrlKey : firstGood(ev.ctrlKey, false),
+ _ShiftKey : firstGood(ev.shiftKey, false),
+ _AltKey : firstGood(ev.altKey, false),
+ _MetaKey : firstGood(ev.metaKey, false)};
+}
+
+
+
+// Document events
+
+function uw_handler(name, f) {
+ var old = document[name];
+ if (old == undefined)
+ document[name] = function(event) { uw_event = event; execF(execF(f, uw_mouseEvent())); };
+ else
+ document[name] = function(event) { uw_event = event; old(); execF(execF(f, uw_mouseEvent())); };
+}
+
+function uw_onClick(f) {
+ uw_handler("onclick", f);
+}
+
+function uw_onContextmenu(f) {
+ uw_handler("oncontextmenu", f);
+}
+
+function uw_onDblclick(f) {
+ uw_handler("ondblclick", f);
+}
+
+function uw_onMousedown(f) {
+ uw_handler("onmousedown", f);
+}
+
+function uw_onMouseenter(f) {
+ uw_handler("onmouseenter", f);
+}
+
+function uw_onMouseleave(f) {
+ uw_handler("onmouseleave", f);
+}
+
+function uw_onMousemove(f) {
+ uw_handler("onmousemove", f);
+}
+
+function uw_onMouseout(f) {
+ uw_handler("onmouseout", f);
+}
+
+function uw_onMouseover(f) {
+ uw_handler("onmouseover", f);
+}
+
+function uw_onMouseup(f) {
+ uw_handler("onmouseup", f);
+}
+
+function uw_keyHandler(name, f) {
+ var old = document[name];
+ if (old == undefined)
+ document[name] = function(event) { uw_event = event; execF(execF(f, uw_keyEvent())); };
+ else
+ document[name] = function(event) { uw_event = event; old(); execF(execF(f, uw_keyEvent())); };
+}
+
+function uw_onKeydown(f) {
+ uw_keyHandler("onkeydown", f);
+}
+
+function uw_onKeypress(f) {
+ uw_keyHandler("onkeypress", f);
+}
+
+function uw_onKeyup(f) {
+ uw_keyHandler("onkeyup", f);
+}
+
+// Cancelling of further event processing
+
+function uw_preventDefault() {
+ var e = window.event ? window.event : uw_event;
+ e.returnValue = false;
+ if (e.preventDefault) e.preventDefault();
+}
+
+function uw_stopPropagation() {
+ var e = window.event ? window.event : uw_event;
+ e.cancelBubble = true;
+ if (e.stopPropagation) e.stopPropagation();
+}
+
+// Embedding closures in XML strings
+
+function cs(f) {
+ return {closure: f};
+}
+
+function isWeird(v) {
+ return v.closure != null || v.cat1 != null;
+}
+
+function cat(s1, s2) {
+ if (isWeird(s1) || isWeird(s2))
+ return {cat1: s1, cat2: s2};
+ else
+ return s1 + s2;
+}
+
+var closures = [];
+var freeClosures = null;
+
+function newClosure(f) {
+ var n;
+ if (freeClosures == null) {
+ n = closures.length;
+ } else {
+ n = freeClosures.data;
+ freeClosures = freeClosures.next;
+ }
+ closures[n] = f;
+ return n;
+}
+
+function freeClosure(n) {
+ closures[n] = null;
+ freeClosures = cons(n, freeClosures);
+}
+
+function cr(n) {
+ return closures[n];
+}
+
+function flattenAcc(a, cls, trs) {
+ while (trs) {
+ var tr = trs.data;
+ trs = trs.next;
+
+ if (tr.cat1 != null) {
+ trs = cons(tr.cat1, cons(tr.cat2, trs));
+ } else if (tr.closure != null) {
+ var cl = newClosure(tr.closure);
+ cls.v = cons(cl, cls.v);
+ a.push("cr(", cl.toString(), ")");
+ } else
+ a.push(tr);
+ }
+}
+
+function flatten(cls, tr) {
+ var a = [];
+ flattenAcc(a, cls, cons(tr, null));
+ return a.join("");
+}
+
+function flattenLocal(s) {
+ var cls = {v : null};
+ var r = flatten(cls, s);
+ for (cl = cls.v; cl != null; cl = cl.next)
+ freeClosure(cl.data);
+ return r;
+}
+
+
+// Dynamic tree management
+
+function populate(node) {
+ if (node.dead) return;
+
+ var s = node.signal;
+ var oldSources = node.sources;
+ try {
+ var sr = execF(s, null);
+ var newSources = sr._sources;
+
+ for (var sp = oldSources; sp; sp = sp.next)
+ if (!member(sp.data, newSources))
+ sp.data.dyns = remove(node, sp.data.dyns);
+
+ for (var sp = newSources; sp; sp = sp.next)
+ if (!member(sp.data, oldSources))
+ sp.data.dyns = cons(node, sp.data.dyns);
+
+ node.sources = newSources;
+ node.recreate(sr._data);
+ } catch (v) {
+ doExn(v);
+ }
+}
+
+function sc(v) {
+ return {data : v, dyns : null};
+}
+function sv(s, v) {
+ if (s.data != v) {
+ s.data = v;
+
+ for (var ls = s.dyns; ls; ls = ls.next)
+ populate(ls.data);
+ }
+}
+function sg(s) {
+ return s.data;
+}
+
+function ss(s) {
+ return {env:cons(s, null), body:{c:"r", l:
+ cons({n:"sources", v:{c:"c", v:cons(s, null)}},
+ cons({n:"data", v:{c:"f", f:sg, a:cons({c:"v", n:1}, null)}}, null))}};
+}
+function sr(v) {
+ return {env:null, body:{c:"c", v:{_sources : null, _data : v}}};
+}
+function sb(x,y) {
+ return {env:cons(y,cons(x,null)),
+ body:{c:"=",
+ e1:{c:"a", f:{c:"v", n:2}, x:{c:"c", v:null}},
+ e2:{c:"=",
+ e1:{c:"a",
+ f:{c:"a", f:{c:"v", n:2}, x:{c:".", r:{c:"v", n:0}, f:"data"}},
+ x:{c:"c", v:null}},
+ e2:{c:"r", l:cons(
+ {n:"sources", v:{c:"f", f:union, a:cons({c:".", r:{c:"v", n:1}, f:"sources"},
+ cons({c:".", r:{c:"v", n:0}, f:"sources"}, null))}},
+ cons({n:"data", v:{c:".", r:{c:"v", n:0}, f:"data"}}, null))}}}};
+}
+function scur(s) {
+ return execF(s, null)._data;
+}
+
+function lastParent() {
+ var pos = document.body;
+
+ while (pos.lastChild && pos.lastChild.nodeType == 1)
+ pos = pos.lastChild;
+
+ pos = pos.parentNode;
+
+ return pos;
+}
+
+var thisScript = null;
+
+function addNode(node) {
+ if (thisScript) {
+ if (thisScript.parentNode)
+ thisScript.parentNode.replaceChild(node, thisScript);
+ } else
+ lastParent().appendChild(node);
+}
+
+function runScripts(node) {
+ 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 = [];
+ var len = scripts.length;
+ for (var i = 0; i < len; ++i)
+ scriptsCopy[i] = scripts[i];
+ for (var i = 0; i < len; ++i) {
+ thisScript = scriptsCopy[i];
+
+ try {
+ eval(thisScript.text);
+ } catch (v) {
+ doExn(v);
+ }
+ if (thisScript.parentNode)
+ thisScript.parentNode.removeChild(thisScript);
+ }
+
+ thisScript = savedScript;
+ }
+}
+
+
+// Dynamic tree entry points
+
+function killScript(scr) {
+ scr.dead = true;
+ for (var ls = scr.sources; ls; ls = ls.next)
+ ls.data.dyns = remove(scr, ls.data.dyns);
+ for (var ls = scr.closures; ls; ls = ls.next)
+ freeClosure(ls.data);
+}
+
+// Sometimes we wind up with tables that contain <script>s outside the single <tbody>.
+// To avoid dealing with that case, we normalize by moving <script>s into <tbody>.
+function normalizeTable(table) {
+ var orig = table;
+
+ var script, next;
+
+ while (table && table.tagName != "TABLE")
+ table = table.parentNode;
+
+ for (var tbody = table.firstChild; tbody; tbody = tbody.nextSibling) {
+ if (tbody.tagName == "TBODY") {
+ var firstChild = tbody.firstChild;
+
+ for (script = table.firstChild; script && script != tbody; script = next) {
+ next = script.nextSibling;
+
+ if (script.tagName === "SCRIPT") {
+ if (firstChild)
+ tbody.insertBefore(script, firstChild);
+ else
+ tbody.appendChild(script);
+ }
+ }
+
+ return;
+ }
+ }
+
+ var tbody = document.createElement("tbody");
+ for (script = table.firstChild; script; script = next) {
+ next = script.nextSibling;
+
+ tbody.appendChild(script);
+ }
+ table.appendChild(tbody);
+}
+
+var suspendScripts = false;
+
+function dyn(pnode, s) {
+ if (suspendScripts)
+ return;
+
+ var x = document.createElement("script");
+ x.dead = false;
+ x.signal = s;
+ x.sources = null;
+ x.closures = null;
+
+ var firstChild = null;
+
+ x.recreate = function(v) {
+ for (var ls = x.closures; ls; ls = ls.next)
+ freeClosure(ls.data);
+
+ var next;
+ for (var child = firstChild; child && child != x; child = next) {
+ next = child.nextSibling;
+
+ killScript(child);
+ if (child.getElementsByTagName) {
+ var arr = child.getElementsByTagName("script");
+ for (var i = 0; i < arr.length; ++i)
+ killScript(arr[i]);
+ }
+
+ if (child.parentNode)
+ child.parentNode.removeChild(child);
+ }
+
+ var cls = {v : null};
+ var html = flatten(cls, v);
+ if (pnode != "table" && pnode != "tr")
+ html = dynPrefix + html;
+ x.closures = cls.v;
+
+ if (pnode == "table") {
+ normalizeTable(x.parentNode);
+
+ var dummy = document.createElement("body");
+ suspendScripts = true;
+ try {
+ dummy.innerHTML = "<table>" + html + "</table>";
+ } catch (e) {
+ suspendScripts = false;
+ throw e;
+ }
+
+ var table = x.parentNode;
+
+ if (table) {
+ firstChild = null;
+ var tbody;
+
+ var arr = dummy.getElementsByTagName("tbody");
+
+ var tbody;
+ if (arr.length > 0 && arr[0].parentNode == dummy.firstChild) {
+ tbody = arr[0];
+ var next;
+ for (var node = dummy.firstChild.firstChild; node; node = next) {
+ next = node.nextSibling;
+
+ if (node.tagName != "TBODY")
+ tbody.appendChild(node);
+ }
+ } else
+ tbody = dummy.firstChild;
+
+ var next;
+ firstChild = document.createElement("script");
+ table.insertBefore(firstChild, x);
+ 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");
+ suspendScripts = true;
+ try {
+ dummy.innerHTML = "<table><tr>" + html + "</tr></table>";
+ } catch (e) {
+ suspendScripts = false;
+ throw e;
+ }
+
+ var table = x.parentNode;
+
+ if (table) {
+ var arr = dummy.getElementsByTagName("tr");
+ firstChild = null;
+ var tr;
+ if (arr.length > 0 && table != null)
+ tr = arr[0];
+ else
+ tr = dummy.firstChild;
+
+ var next;
+ firstChild = document.createElement("script");
+ table.insertBefore(firstChild, x);
+ 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");
+
+ suspendScripts = true;
+ try {
+ firstChild.innerHTML = html;
+ if (x.parentNode)
+ x.parentNode.insertBefore(firstChild, x);
+ } catch (e) {
+ suspendScripts = false;
+ throw e;
+ }
+ suspendScripts = false;
+ runScripts(firstChild);
+ }
+ };
+
+ addNode(x);
+ populate(x);
+}
+
+function setInnerHTML(node, html) {
+ var x;
+
+ if (node.previousSibling && node.previousSibling.closures != undefined) {
+ x = node.previousSibling;
+
+ for (var ls = x.closures; ls; ls = ls.next)
+ freeClosure(ls.data);
+
+ if (node.getElementsByTagName) {
+ var arr = node.getElementsByTagName("script");
+ for (var i = 0; i < arr.length; ++i)
+ killScript(arr[i]);
+ }
+ } else {
+ x = document.createElement("script");
+ x.dead = false;
+ x.sources = null;
+
+ if (node.parentNode)
+ node.parentNode.insertBefore(x, node);
+ else
+ whine("setInnerHTML: node is not already in the DOM tree");
+ }
+
+ 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 ms = maySuspend;
+ maySuspend = false;
+ try {
+ var html = execF(s);
+ } catch (e) {
+ maySuspend = ms;
+ throw e;
+ }
+ maySuspend = ms;
+ if (html != "") {
+ var span = document.createElement("span");
+ addNode(span);
+ setInnerHTML(span, html);
+ }
+}
+
+function input(x, s, recreate, type, name) {
+ if (name) x.name = name;
+ if (type) x.type = type;
+ addNode(x);
+
+ var sc = document.createElement("script");
+ sc.dead = false;
+ sc.signal = ss(s);
+ sc.sources = null;
+ sc.recreate = recreate(x);
+
+ if (x.parentNode)
+ x.parentNode.insertBefore(sc, x);
+
+ populate(sc);
+
+ return x;
+}
+
+function inpt(type, s, name) {
+ if (suspendScripts)
+ return;
+
+ var x = input(document.createElement("input"), s,
+ function(x) { return function(v) { if (x.value != v) x.value = v; }; }, type, name);
+ x.value = s.data;
+ x.onkeyup = x.oninput = x.onchange = x.onpropertychange = function() { sv(s, x.value) };
+
+ return x;
+}
+function inpt_float(type, s, name) {
+ if (suspendScripts)
+ return;
+
+ var filterFloat = function(value) {
+ if (/^(\-|\+)?([0-9]+(\.[0-9]+)?|Infinity)$/
+ .test(value))
+ return Number(value);
+ return null;
+ }
+ var x = input(document.createElement("input"), s, function(x) { return function(v) { if (x.value != v) x.value = v; }; }, type, name);
+ x.value = s.data;
+ x.onkeyup = x.oninput = x.onchange = x.onpropertychange = function() { sv(s, filterFloat(x.value)) };
+
+ return x;
+}
+
+
+function inp(s, name) {
+ return inpt("text", s, name);
+}
+
+function password(s, name) {
+ return inpt("password", s, name);
+}
+
+function email(s, name) {
+ return inpt("email", s, name);
+}
+
+function search(s, name) {
+ return inpt("search", s, name);
+}
+
+function url(s, name) {
+ return inpt("url", s, name);
+}
+
+function tel(s, name) {
+ return inpt("tel", s, name);
+}
+
+function color(s, name) {
+ return inpt("color", s, name);
+}
+
+function number(s, name) {
+ return inpt_float("number", s, name);
+}
+
+function range(s, name) {
+ return inpt_float("range", s, name);
+}
+
+function date(s, name) {
+ return inpt("date", s, name);
+}
+
+function datetime(s, name) {
+ return inpt("datetime", s, name);
+}
+
+function datetime_local(s, name) {
+ return inpt("datetime-local", s, name);
+}
+
+function month(s, name) {
+ return inpt("month", s, name);
+}
+
+function week(s, name) {
+ return inpt("week", s, name);
+}
+
+function time(s, name) {
+ return inpt("time", s, name);
+}
+
+
+function selectValue(x) {
+ if (x.options.length == 0)
+ return "";
+ else
+ return x.options[x.selectedIndex].value;
+}
+
+function setSelectValue(x, v) {
+ for (var i = 0; i < x.options.length; ++i) {
+ if(x.options[i].value == v) {
+ x.selectedIndex = i;
+ return;
+ }
+ }
+}
+
+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); }; });
+
+ for (var i = 0; i < x.options.length; ++i) {
+ if (x.options[i].value == "")
+ x.options[i].value = x.options[i].text;
+ else
+ x.options[i].value = x.options[i].value.substring(1);
+ }
+
+ setSelectValue(x, s.data);
+ if (selectValue(x) != s.data)
+ sv(s, selectValue(x));
+ x.onchange = function() { sv(s, selectValue(x)) };
+
+ return x;
+}
+
+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;
+ x.onclick = x.onkeyup = x.oninput = x.onchange = x.onpropertychange = function() { sv(s, x.checked) };
+
+ return x;
+}
+
+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;
+ x.onkeyup = x.oninput = x.onchange = x.onpropertychange = function() { sv(s, x.value) };
+
+ return x;
+}
+
+function dynClass(pnode, html, s_class, s_style) {
+ if (suspendScripts)
+ return;
+
+ var htmlCls = {v : null};
+ html = flatten(htmlCls, html);
+ htmlCls = htmlCls.v;
+
+ var dummy = document.createElement(pnode);
+ suspendScripts = true;
+ dummy.innerHTML = html;
+ suspendScripts = false;
+ var html = dummy.firstChild;
+ dummy.removeChild(html);
+ if (pnode == "table" && html.tagName == "TBODY") {
+ html = html.firstChild;
+ }
+ addNode(html);
+ runScripts(html);
+
+ if (s_class) {
+ var x = document.createElement("script");
+ x.dead = false;
+ x.signal = s_class;
+ x.sources = null;
+ x.closures = htmlCls;
+
+ x.recreate = function(v) {
+ for (var ls = x.closures; ls != htmlCls; ls = ls.next)
+ freeClosure(ls.data);
+
+ var cls = {v : null};
+ html.className = flatten(cls, v);
+ x.closures = concat(cls.v, htmlCls);
+ }
+
+ html.appendChild(x);
+ populate(x);
+ }
+
+ if (s_style) {
+ var htmlCls2 = s_class ? null : htmlCls;
+ var y = document.createElement("script");
+ y.dead = false;
+ y.signal = s_style;
+ y.sources = null;
+ y.closures = htmlCls2;
+
+ y.recreate = function(v) {
+ for (var ls = y.closures; ls != htmlCls2; ls = ls.next)
+ freeClosure(ls.data);
+
+ var cls = {v : null};
+ html.style.cssText = flatten(cls, v);
+ y.closures = concat(cls.v, htmlCls2);
+ }
+
+ html.appendChild(y);
+ populate(y);
+ }
+}
+
+function bodyDynClass(s_class, s_style) {
+ if (suspendScripts)
+ return;
+
+ var htmlCls = null;
+
+ if (s_class) {
+ var x = document.createElement("script");
+ x.dead = false;
+ x.signal = s_class;
+ x.sources = null;
+ x.closures = htmlCls;
+
+ x.recreate = function(v) {
+ for (var ls = x.closures; ls != htmlCls; ls = ls.next)
+ freeClosure(ls.data);
+
+ var cls = {v : null};
+ document.body.className = flatten(cls, v);
+ console.log("className to + " + document.body.className);
+ x.closures = concat(cls.v, htmlCls);
+ }
+
+ document.body.appendChild(x);
+ populate(x);
+ }
+
+ if (s_style) {
+ var htmlCls2 = s_class ? null : htmlCls;
+ var y = document.createElement("script");
+ y.dead = false;
+ y.signal = s_style;
+ y.sources = null;
+ y.closures = htmlCls2;
+
+ y.recreate = function(v) {
+ for (var ls = y.closures; ls != htmlCls2; ls = ls.next)
+ freeClosure(ls.data);
+
+ var cls = {v : null};
+ document.body.style.cssText = flatten(cls, v);
+ console.log("style to + " + document.body.style.cssText);
+ y.closures = concat(cls.v, htmlCls2);
+ }
+
+ document.body.appendChild(y);
+ populate(y);
+ }
+}
+
+function addOnChange(x, f) {
+ var old = x.onchange;
+ if (old == null)
+ x.onchange = f;
+ else
+ x.onchange = function() { old(); f(); };
+}
+
+function addOnKeyUp(x, f) {
+ var old = x.onkeyup;
+ if (old == null)
+ x.onkeyup = f;
+ else
+ x.onkeyup = function(x) { old(x); f(x); };
+}
+
+
+// Basic string operations
+
+function eh(x) {
+ if (x == null)
+ return "NULL";
+ else
+ return x.split("&").join("&amp;").split("<").join("&lt;").split(">").join("&gt;");
+}
+
+function ts(x) { return x.toString() }
+function bs(b) { return (b ? "True" : "False") }
+function s2b(s) { return s == "True" ? true : s == "False" ? false : null; }
+function s2be(s) { return s == "True" ? true : s == "False" ? false : er("Illegal Boolean " ^ s); }
+
+function id(x) { return x; }
+function sub(s, i) { return s.charAt(i); }
+function suf(s, i) { return s.substring(i); }
+function slen(s) { return s.length; }
+function sidx(s, ch) {
+ var r = s.indexOf(ch);
+ if (r == -1)
+ return null;
+ else
+ return r;
+}
+function ssidx(h, n) {
+ var r = h.indexOf(n);
+ if (r == -1)
+ return null;
+ else
+ return r;
+}
+function sspn(s, chs) {
+ for (var i = 0; i < s.length; ++i)
+ if (chs.indexOf(s.charAt(i)) != -1)
+ return i;
+
+ return s.length;
+}
+function schr(s, ch) {
+ var r = s.indexOf(ch);
+ if (r == -1)
+ return null;
+ else
+ return s.substring(r);
+}
+function ssub(s, start, len) {
+ return s.substring(start, start+len);
+}
+function strlenGe(s, len) {
+ return s.length >= len;
+}
+
+function trimZeroes(s) {
+ for (var i = 0; i < s.length; ++i)
+ if (s.charAt(i) != '0') {
+ if (i > 0)
+ return s.substring(i);
+ else
+ return s;
+ }
+
+ if (s.length == 0)
+ return s;
+ else
+ return "0";
+}
+
+function pi(s) {
+ var st = trimZeroes(s);
+ var r = parseInt(st);
+ if (r.toString() == st)
+ return r;
+ else
+ er("Can't parse int: " + s);
+}
+
+function pfl(s) {
+ var r = parseFloat(s);
+ if (r.toString() == s)
+ return r;
+ else
+ er("Can't parse float: " + s);
+}
+
+function pio(s) {
+ var st = trimZeroes(s);
+ var r = parseInt(st);
+ if (r.toString() == st)
+ return r;
+ else
+ return null;
+}
+
+function pflo(s) {
+ var r = parseFloat(s);
+ if (r.toString() == s)
+ return r;
+ else
+ return null;
+}
+
+function parseSource(s1, s2) {
+ return eval("s" + s1 + "_" + s2);
+}
+
+function uf(s) {
+ if (s.length == 0)
+ return "_";
+ s = s.replace(/\./g, ".2E");
+ return (s.charAt(0) == '_' ? "_" : "") + encodeURIComponent(s).replace(/%/g, ".");
+}
+
+function uu(s) {
+ if (s.length > 0 && s.charAt(0) == '_') {
+ s = s.substring(1);
+ } else if (s.length >= 3 && (s.charAt(0) == '%' || s.charAt(0) == '.')
+ && s.charAt(1) == '5' && (s.charAt(2) == 'f' || s.charAt(2) == 'F'))
+ s = s.substring(3);
+ s = s.replace(/\+/g, " ");
+ s = s.replace(/\./g, "%");
+ return decodeURIComponent(s);
+}
+
+function atr(s) {
+ return s.replace(/\"/g, "&quot;").replace(/&/g, "&amp;")
+}
+
+function ub(b) {
+ return b ? "1" : "0";
+}
+
+function uul(getToken, getData) {
+ var tok = getToken();
+ if (tok == "Nil") {
+ return null;
+ } else if (tok == "Cons") {
+ var d = getData();
+ var l = uul(getToken, getData);
+ return {_1:d, _2:l};
+ } else
+ whine("Can't unmarshal list (" + tok + ")");
+}
+
+function strcmp(str1, str2) {
+ return ((str1 == str2) ? 0 : ((str1 > str2) ? 1 : -1));
+}
+
+function chr(n) {
+ return String.fromCharCode(n);
+}
+
+function htmlifySpecialChar(ch) {
+ return "&#" + ch.charCodeAt(0) + ";";
+}
+
+
+// Remote calls
+
+var client_id = null;
+var client_pass = 0;
+var url_prefix = "/";
+var timeout = 60;
+var isPost = false;
+
+function getXHR(uri)
+{
+ try {
+ return new XMLHttpRequest();
+ } catch (e) {
+ try {
+ return new ActiveXObject("Msxml2.XMLHTTP");
+ } catch (e) {
+ try {
+ return new ActiveXObject("Microsoft.XMLHTTP");
+ } catch (e) {
+ whine("Your browser doesn't seem to support AJAX.");
+ }
+ }
+ }
+}
+
+var sig = null;
+
+var unloading = false, inFlight = null;
+
+function unload() {
+ for (; inFlight; inFlight = inFlight.next) {
+ inFlight.data.abort();
+ }
+}
+
+function requestUri(xhr, uri, needsSig, isRpc) {
+ var extraData = null;
+
+ if (isRpc && uri.length > 2000) {
+ extraData = uri.substring(2000);
+ uri = uri.substring(0, 2000);
+ }
+
+ xhr.open("POST", uri, !unloading);
+ xhr.setRequestHeader("Content-type", "text/plain");
+
+ if (client_id != null) {
+ xhr.setRequestHeader("UrWeb-Client", client_id.toString());
+ xhr.setRequestHeader("UrWeb-Pass", client_pass.toString());
+ }
+
+ if (needsSig) {
+ if (sig == null)
+ whine("Missing cookie signature!");
+
+ xhr.setRequestHeader("UrWeb-Sig", sig);
+ }
+
+ inFlight = cons(xhr, inFlight);
+ xhr.send(extraData);
+}
+
+function xhrFinished(xhr) {
+ xhr.abort();
+ inFlight = remove(xhr, inFlight);
+}
+
+function unurlify(parse, s) {
+ return parse(s);
+}
+
+function redirect(s) {
+ window.location = s;
+}
+
+function makeSome(isN, v) {
+ if (isN)
+ return {v: v};
+ else
+ return v;
+}
+
+function rc(prefix, uri, parse, k, needsSig, isN) {
+ if (!maySuspend)
+ er("May not 'rpc' in main thread of 'code' for <active>");
+
+ uri = cat(prefix, uri);
+ uri = flattenLocal(uri);
+ var xhr = getXHR();
+
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState == 4) {
+ var isok = false;
+
+ try {
+ if (xhr.status == 200)
+ isok = true;
+ } catch (e) { }
+
+ if (isok) {
+ var lines = xhr.responseText.split("\n");
+ if (lines.length != 2) {
+ if (isN == null)
+ whine("Bad RPC response lines");
+ else
+ k(null);
+ } else {
+ eval(lines[0]);
+
+ try {
+ var v = parse(lines[1]);
+ try {
+ k(makeSome(isN, v));
+ } catch (v) {
+ doExn(v);
+ }
+ } catch (v) {
+ k(null);
+ }
+ }
+ } else {
+ if (isN == null)
+ conn(xhr.responseText);
+ else
+ k(null);
+ }
+
+ xhrFinished(xhr);
+ }
+ };
+
+ requestUri(xhr, uri, needsSig, true);
+}
+
+function path_join(s1, s2) {
+ if (s1.length > 0 && s1.charAt(s1.length-1) == '/')
+ return s1 + s2;
+ else
+ return s1 + "/" + s2;
+}
+
+var channels = [];
+
+function newQueue() {
+ return { front : null, back : null };
+}
+function enqueue(q, v) {
+ if (q.front == null) {
+ q.front = cons(v, null);
+ q.back = q.front;
+ } else {
+ var node = cons(v, null);
+ q.back.next = node;
+ q.back = node;
+ }
+}
+function dequeue(q) {
+ if (q.front == null)
+ return null;
+ else {
+ var r = q.front.data;
+ q.front = q.front.next;
+ if (q.front == null)
+ q.back = null;
+ return r;
+ }
+}
+
+function newChannel() {
+ return { msgs : newQueue(), listeners : newQueue() };
+}
+
+function listener() {
+ var uri = path_join(url_prefix, ".msgs");
+ var xhr = getXHR();
+ var tid, orsc, onTimeout, lastTick;
+
+ var connect = function () {
+ xhr.onreadystatechange = orsc;
+ lastTick = new Date().getTime();
+ tid = window.setTimeout(onTimeout, timeout * 500);
+ requestUri(xhr, uri, false, false);
+ }
+
+ orsc = function() {
+ if (xhr.readyState == 4) {
+ window.clearTimeout(tid);
+
+ var isok = false;
+
+ try {
+ if (xhr.status == 200)
+ isok = true;
+ } catch (e) { }
+
+ if (isok) {
+ var text = xhr.responseText;
+ if (text == "")
+ return;
+ var lines = text.split("\n");
+
+ if (lines.length == 1 && lines[0] == "R") {
+ lameDuck = true;
+
+ if (isPost)
+ history.back();
+ else
+ location.reload();
+
+ return;
+ }
+
+ if (lines.length < 2) {
+ discon();
+ return;
+ }
+
+ var messageReader = function(i) {
+ if (i+1 >= lines.length) {
+ xhrFinished(xhr);
+ connect();
+ }
+ else {
+ var chn = lines[i];
+ var msg = lines[i+1];
+
+ if (chn == "E") {
+ eval(msg);
+ window.setTimeout(function() { messageReader(i+2); }, 0);
+ } else {
+ if (chn < 0)
+ whine("Out-of-bounds channel in message from remote server");
+
+ var ch;
+
+ if (chn >= channels.length || channels[chn] == null) {
+ ch = newChannel();
+ channels[chn] = ch;
+ } else
+ ch = channels[chn];
+
+ var listener = dequeue(ch.listeners);
+ if (listener == null) {
+ enqueue(ch.msgs, msg);
+ } else {
+ try {
+ listener(msg);
+ } catch (v) {
+ doExn(v);
+ }
+ }
+
+ messageReader(i+2);
+ }
+ }
+ }
+
+ messageReader(0);
+ }
+ else {
+ try {
+ if (xhr.status != 0)
+ servErr("Error querying remote server for messages: " + xhr.status);
+ } catch (e) { }
+ }
+ }
+ };
+
+ onTimeout = function() {
+ var thisTick = new Date().getTime();
+ xhrFinished(xhr);
+
+ if (thisTick - lastTick > timeout * 1000) {
+ if (confirm("The session for this page has expired. Please choose \"OK\" to reload.")) {
+ if (isPost)
+ history.back();
+ else
+ location.reload();
+ }
+ } else {
+ connect();
+ }
+ };
+
+ connect();
+}
+
+function rv(chn, parse, k) {
+ if (!maySuspend)
+ er("May not 'recv' in main thread of 'code' for <active>");
+
+ if (chn == null)
+ er("Client-side code tried to recv() from a channel belonging to a different page view.");
+
+ if (chn < 0)
+ whine("Out-of-bounds channel receive");
+
+ var ch;
+
+ if (chn >= channels.length || channels[chn] == null) {
+ ch = newChannel();
+ channels[chn] = ch;
+ } else
+ ch = channels[chn];
+
+ var msg = dequeue(ch.msgs);
+ if (msg == null) {
+ enqueue(ch.listeners, function(msg) { k(parse(msg)); });
+ } else {
+ try {
+ k(parse(msg));
+ } catch (v) {
+ doExn(v);
+ }
+ }
+}
+
+function sl(ms, k) {
+ if (!maySuspend)
+ er("May not 'sleep' in main thread of 'code' for <active>");
+
+ window.setTimeout(function() { k(null); }, ms);
+}
+
+function sp(e) {
+ window.setTimeout(function() { execF(e); }, 0);
+}
+
+
+// The Ur interpreter
+
+var urfuncs = [];
+
+function lookup(env, n) {
+ while (env != null) {
+ if (n == 0)
+ return env.data;
+ else {
+ --n;
+ env = env.next;
+ }
+ }
+
+ whine("Out-of-bounds Ur variable reference");
+}
+
+function execP(env, p, v) {
+ switch (p.c) {
+ case "v":
+ return cons(v, env);
+ case "c":
+ if (v == p.v)
+ return env;
+ else
+ return false;
+ case "s":
+ if (v == null)
+ return false;
+ else
+ return execP(env, p.p, p.n ? v.v : v);
+ case "1":
+ if (v.n != p.n)
+ return false;
+ else
+ return execP(env, p.p, v.v);
+ case "r":
+ for (var fs = p.l; fs != null; fs = fs.next) {
+ env = execP(env, fs.data.p, v["_" + fs.data.n]);
+ if (env == false)
+ return false;
+ }
+ return env;
+ default:
+ whine("Unknown Ur pattern kind " + p.c);
+ }
+}
+
+function exec0(env, e) {
+ return exec1(env, null, e);
+}
+
+function exec1(env, stack, e) {
+ var stack, usedK = false;
+
+ var saveEnv = function() {
+ if (stack.next != null && stack.next.data.c != "<")
+ stack = cons({c: "<", env: env}, stack.next);
+ else
+ stack = stack.next;
+ };
+
+ while (true) {
+ switch (e.c) {
+ case "c":
+ var v = e.v;
+ if (stack == null)
+ return v;
+ var fr = stack.data;
+
+ switch (fr.c) {
+ case "s":
+ e = {c: "c", v: {v: v}};
+ stack = stack.next;
+ break;
+ case "1":
+ e = {c: "c", v: {n: fr.n, v: v}};
+ stack = stack.next;
+ break;
+ case "f":
+ fr.args[fr.pos++] = v;
+ if (fr.a == null) {
+ var res;
+ stack = stack.next;
+
+ if (fr.f.apply)
+ res = fr.f.apply(null, fr.args);
+ else if (fr.args.length == 0)
+ res = fr.f();
+ else if (fr.args.length == 1)
+ res = fr.f(fr.args[0]);
+ else if (fr.args.length == 2)
+ res = fr.f(fr.args[0], fr.args[1]);
+ else if (fr.args.length == 3)
+ res = fr.f(fr.args[0], fr.args[1], fr.args[2]);
+ else if (fr.args.length == 4)
+ res = fr.f(fr.args[0], fr.args[1], fr.args[2], fr.args[3]);
+ else if (fr.args.length == 5)
+ res = fr.f(fr.args[0], fr.args[1], fr.args[2], fr.args[3], fr.args[4]);
+ else
+ whine("Native function has " + fr.args.length + " args, but there is no special case for that count.");
+
+ e = {c: "c", v: res};
+ if (usedK) return null;
+ } else {
+ e = fr.a.data;
+ fr.a = fr.a.next;
+ }
+ break;
+ case "a1":
+ e = fr.x;
+ stack = cons({c: "a2", f: v}, stack.next);
+ break;
+ case "a2":
+ if (fr.f == null)
+ whine("Ur: applying null function");
+ else if (fr.f.body) {
+ saveEnv();
+ env = cons(v, fr.f.env);
+ e = fr.f.body;
+ } else {
+ e = {c: "c", v: fr.f(v)};
+ stack = stack.next;
+ }
+ break;
+ case "<":
+ env = fr.env;
+ stack = stack.next;
+ break;
+ case "r":
+ fr.fs["_" + fr.n] = v;
+ if (fr.l == null) {
+ e = {c: "c", v: fr.fs};
+ stack = stack.next;
+ } else {
+ fr.n = fr.l.data.n;
+ e = fr.l.data.v;
+ fr.l = fr.l.next;
+ }
+ break;
+ case ".":
+ e = {c: "c", v: v["_" + fr.f]};
+ stack = stack.next;
+ break;
+ case ";":
+ e = fr.e2;
+ stack = stack.next;
+ break;
+ case "=":
+ saveEnv();
+ env = cons(v, env);
+ e = fr.e2;
+ break;
+ case "m":
+ var ps;
+ for (ps = fr.p; ps != null; ps = ps.next) {
+ var r = execP(env, ps.data.p, v);
+ if (r != false) {
+ saveEnv();
+ env = r;
+ e = ps.data.b;
+ break;
+ }
+ }
+ if (ps == null)
+ whine("Match failure in Ur interpretation");
+ break;
+ default:
+ whine("Unknown Ur continuation kind " + fr.c);
+ }
+
+ break;
+ case "v":
+ e = {c: "c", v: lookup(env, e.n)};
+ break;
+ case "n":
+ var idx = e.n;
+ e = urfuncs[idx];
+ if (e.c == "t")
+ e = urfuncs[idx] = eval("(" + e.f + ")");
+ break;
+ case "s":
+ stack = cons({c: "s"}, stack);
+ e = e.v;
+ break;
+ case "1":
+ stack = cons({c: "1", n: e.n}, stack);
+ e = e.v;
+ break;
+ case "f":
+ if (e.a == null)
+ e = {c: "c", v: e.f()};
+ else {
+ var args = [];
+ stack = cons({c: "f", f: e.f, args: args, pos: 0, a: e.a.next}, stack);
+ if (!e.a.data.c) alert("[2] fr.f = " + e.f + "; 0 = " + e.a.data);
+ e = e.a.data;
+ }
+ break;
+ case "l":
+ e = {c: "c", v: {env: env, body: e.b}};
+ break;
+ case "a":
+ stack = cons({c: "a1", x: e.x}, stack);
+ e = e.f;
+ break;
+ case "r":
+ if (e.l == null)
+ whine("Empty Ur record in interpretation");
+ var fs = {};
+ stack = cons({c: "r", n: e.l.data.n, fs: fs, l: e.l.next}, stack);
+ e = e.l.data.v;
+ break;
+ case ".":
+ stack = cons({c: ".", f: e.f}, stack);
+ e = e.r;
+ break;
+ case ";":
+ stack = cons({c: ";", e2: e.e2}, stack);
+ e = e.e1;
+ break;
+ case "=":
+ stack = cons({c: "=", e2: e.e2}, stack);
+ e = e.e1;
+ break;
+ case "m":
+ stack = cons({c: "m", p: e.p}, stack);
+ e = e.e;
+ break;
+ case "e":
+ e = {c: "c", v: cs({c: "wc", env: env, body: e.e})};
+ break;
+ case "wc":
+ env = e.env;
+ e = e.body;
+ break;
+ case "K":
+ { var savedStack = stack.next, savedEnv = env;
+ e = {c: "c", v: function(v) { return exec1(savedEnv, savedStack, {c: "c", v: v}); } };}
+ usedK = true;
+ break;
+ default:
+ whine("Unknown Ur expression kind " + e.c);
+ }
+ }
+}
+
+function execD(e) {
+ return exec0(null, e);
+}
+
+function exec(e) {
+ var r = exec0(null, e);
+
+ if (r != null && r.body != null)
+ return function(v) { return exec0(cons(v, r.env), r.body); };
+ else
+ return r;
+}
+
+function execF(f, x) {
+ return exec0(cons(x, f.env), f.body);
+}
+
+
+// Wrappers
+
+function confrm(s) {
+ return confirm(s) ? true : false;
+}
+
+
+// URL blessing
+
+var urlRules = null;
+
+function checkUrl(s) {
+ for (var r = urlRules; r; r = r.next) {
+ var ru = r.data;
+ if (ru.prefix ? s.indexOf(ru.pattern) == 0 : s == ru.pattern)
+ return ru.allow ? s : null;
+ }
+
+ return null;
+}
+
+function bless(s) {
+ u = checkUrl(s);
+ if (u == null)
+ er("Disallowed URL: " + s);
+ return u;
+}
+
+
+// Attribute name blessing
+
+function blessData(s) {
+ for (var i = 0; i < s.length; ++i) {
+ var c = s[i];
+ if (!isAlnum(c) && c != '-' && c != '_')
+ er("Disallowed character in data-* attribute name");
+ }
+
+ return s;
+}
+
+
+// CSS validation
+
+function atom(s) {
+ for (var i = 0; i < s.length; ++i) {
+ var c = s[i];
+ if (!isAlnum(c) && c != '+' && c != '-' && c != '.' && c != '%' && c != '#')
+ er("Disallowed character in CSS atom");
+ }
+
+ return s;
+}
+
+function css_url(s) {
+ for (var i = 0; i < s.length; ++i) {
+ var c = s[i];
+ if (!isAlnum(c) && c != ':' && c != '/' && c != '.' && c != '_' && c != '+'
+ && c != '-' && c != '%' && c != '?' && c != '&' && c != '=' && c != '#')
+ er("Disallowed character in CSS URL");
+ }
+
+ return s;
+}
+
+function property(s) {
+ if (s.length <= 0)
+ er("Empty CSS property");
+
+ if (!isLower(s[0]) && s[0] != '_')
+ er("Bad initial character in CSS property");
+
+ for (var i = 0; i < s.length; ++i) {
+ var c = s[i];
+ if (!isLower(c) && !isDigit(c) && c != '_' && c != '-')
+ er("Disallowed character in CSS property");
+ }
+
+ return s;
+}
+
+
+// ID generation
+
+var nextId = 0;
+
+function fresh() {
+ return "uw" + (--nextId);
+}
+
+function giveFocus(id) {
+ var node = document.getElementById(id);
+
+ if (node)
+ node.focus();
+ else
+ er("Tried to give focus to ID not used in document: " + id);
+}
+
+
+// App-specific code