diff lib/js/urweb.js @ 692:09df0c85f306

Fix overzealous Marshalcheck; garbage-collect string-embedded closures when no dyns are active
author Adam Chlipala <adamc@hcoop.net>
date Sat, 04 Apr 2009 12:54:39 -0400
parents cc58941da3e2
children 655bcc9b77e0
line wrap: on
line diff
--- a/lib/js/urweb.js	Sat Apr 04 11:46:24 2009 -0400
+++ b/lib/js/urweb.js	Sat Apr 04 12:54:39 2009 -0400
@@ -1,3 +1,5 @@
+// Lists
+
 function cons(v, ls) {
   return { next : ls, data : v };
 }
@@ -18,6 +20,43 @@
 }
 
 
+// Embedding closures in XML strings
+
+function cat(s1, s2) {
+  if (s1.length && s2.length)
+    return s1 + s2;
+  else
+    return {_1: s1, _2: s2};
+}
+
+var closures = [];
+
+function newClosure(f) {
+  var n = closures.length;
+  closures[n] = f;
+  return n;
+}
+
+function cr(n) {
+  return closures[n]();
+}
+
+function flatten(tr) {
+  if (tr.length)
+    return tr;
+  else if (tr._1)
+    return cs(tr._1) + cs(tr._2);
+  else
+    return "cr(" + newClosure(tr) + ")";
+}
+
+function clearClosures() {
+  closures = [];
+}
+
+
+// Dynamic tree management
+
 function populate(node) {
   var s = node.signal;
   var oldSources = node.sources;
@@ -85,7 +124,7 @@
 function runScripts(node) {
   var savedScript = thisScript;
 
-  var scripts = node.getElementsByTagName("script"), scriptsCopy = {};
+  var scripts = node.getElementsByTagName("script"), scriptsCopy = [];
   var len = scripts.length;
   for (var i = 0; i < len; ++i)
     scriptsCopy[i] = scripts[i];
@@ -98,12 +137,18 @@
 }
 
 
+// Dynamic tree entry points
+
+var dynDepth = 0;
+
 function dyn(s) {
   var x = document.createElement("span");
   x.dead = false;
   x.signal = s;
   x.sources = null;
   x.recreate = function(v) {
+    ++dynDepth;
+
     var spans = x.getElementsByTagName("span");
     for (var i = 0; i < spans.length; ++i) {
       var span = spans[i];
@@ -114,6 +159,9 @@
 
     x.innerHTML = v;
     runScripts(x);
+
+    if (--dynDepth == 0)
+      clearClosures();
   };
   populate(x);
   addNode(x);
@@ -131,6 +179,9 @@
   return x;
 }
 
+
+// Basic string operations
+
 function eh(x) {
   return x.split("&").join("&amp;").split("<").join("&lt;").split(">").join("&gt;");
 }
@@ -154,10 +205,17 @@
     throw "Can't parse float: " + s;
 }
 
-function cat(s1, s2) {
-  return s1 + s2;
+function uf(s) {
+  return escape(s).replace(new RegExp ("/", "g"), "%2F");
 }
 
+function uu(s) {
+  return unescape(s).replace(new RegExp ("\\+", "g"), " ");
+}
+
+
+// Error handling
+
 function whine(msg) {
   alert(msg);
   throw msg;
@@ -167,18 +225,8 @@
   whine("Pattern match failure");
 }
 
-var closures = [];
 
-function ca(f) {
-  var n = closures.length;
-  closures[n] = f;
-  return n;
-}
-
-function cr(n) {
-  return closures[n]();
-}
-
+// Remote calls
 
 var client_id = 0;
 var client_pass = 0;
@@ -364,11 +412,3 @@
     k(parse(msg))(null);
   }
 }
-
-function uf(s) {
-  return escape(s).replace(new RegExp ("/", "g"), "%2F");
-}
-
-function uu(s) {
-  return unescape(s).replace(new RegExp ("\\+", "g"), " ");
-}