comparison lib/js/urweb.js @ 729:7c6b6c3c7b79

Some client-side error handling
author Adam Chlipala <adamc@hcoop.net>
date Thu, 16 Apr 2009 13:47:20 -0400
parents 2197f0e24a9f
children 796e42c93c48
comparison
equal deleted inserted replaced
728:2197f0e24a9f 729:7c6b6c3c7b79
18 function union(ls1, ls2) { 18 function union(ls1, ls2) {
19 return (ls1 ? (member(ls1.data, ls2) ? union(ls1.next, ls2) : cons(ls1.data, union(ls1.next, ls2))) : ls2); 19 return (ls1 ? (member(ls1.data, ls2) ? union(ls1.next, ls2) : cons(ls1.data, union(ls1.next, ls2))) : ls2);
20 } 20 }
21 function length(ls) { 21 function length(ls) {
22 return (ls ? 1 + length(ls.next) : 0); 22 return (ls ? 1 + length(ls.next) : 0);
23 }
24
25
26 // Error handling
27
28 function whine(msg) {
29 alert(msg);
30 throw msg;
31 }
32
33 function pf() {
34 whine("Pattern match failure");
35 }
36
37 function runHandlers(ls, arg) {
38 for (; ls; ls = ls.next)
39 try {
40 ls.data(arg)(null);
41 } catch (v) { }
42 }
43
44 var errorHandlers = null;
45
46 function onError(f) {
47 errorHandlers = cons(f, errorHandlers);
48 }
49
50 function er(s) {
51 runHandlers(errorHandlers, s);
52 throw {uw_error: s};
53 }
54
55 var failHandlers = null;
56
57 function onFail(f) {
58 failHandlers = cons(f, failHandlers);
59 }
60
61 function doExn(v) {
62 if (v == null || v.uw_error == null) {
63 var s = (v == null ? "null" : v.toString());
64 runHandlers(failHandlers, s);
65 }
66 }
67
68 var disconnectHandlers = null;
69
70 function onDisconnect(f) {
71 disconnectHandlers = cons(function (_){return f}, disconnectHandlers);
72 }
73
74 function discon() {
75 runHandlers(disconnectHandlers, null);
76 }
77
78 var connectHandlers = null;
79
80 function onConnectFail(f) {
81 connectHandlers = cons(function (_){return f}, connectHandlers);
82 }
83
84 function conn() {
85 runHandlers(connectHandlers, null);
86 }
87
88 var serverHandlers = null;
89
90 function onServerError(f) {
91 serverHandlers = cons(f, serverHandlers);
92 }
93
94 function servErr(s) {
95 runHandlers(serverHandlers, s);
23 } 96 }
24 97
25 98
26 // Embedding closures in XML strings 99 // Embedding closures in XML strings
27 100
88 // Dynamic tree management 161 // Dynamic tree management
89 162
90 function populate(node) { 163 function populate(node) {
91 var s = node.signal; 164 var s = node.signal;
92 var oldSources = node.sources; 165 var oldSources = node.sources;
93 var sr = s(); 166 try {
94 var newSources = sr.sources; 167 var sr = s();
95 168 var newSources = sr.sources;
96 for (var sp = oldSources; sp; sp = sp.next) 169
97 if (!member(sp.data, newSources)) 170 for (var sp = oldSources; sp; sp = sp.next)
98 sp.data.dyns = remove(node, sp.data.dyns); 171 if (!member(sp.data, newSources))
99 172 sp.data.dyns = remove(node, sp.data.dyns);
100 for (var sp = newSources; sp; sp = sp.next) 173
101 if (!member(sp.data, oldSources)) 174 for (var sp = newSources; sp; sp = sp.next)
102 sp.data.dyns = cons(node, sp.data.dyns); 175 if (!member(sp.data, oldSources))
103 176 sp.data.dyns = cons(node, sp.data.dyns);
104 node.sources = newSources; 177
105 node.recreate(sr.data); 178 node.sources = newSources;
179 node.recreate(sr.data);
180 } catch (v) {
181 doExn(v);
182 }
106 } 183 }
107 184
108 function sc(v) { 185 function sc(v) {
109 return {data : v, dyns : null}; 186 return {data : v, dyns : null};
110 } 187 }
158 var len = scripts.length; 235 var len = scripts.length;
159 for (var i = 0; i < len; ++i) 236 for (var i = 0; i < len; ++i)
160 scriptsCopy[i] = scripts[i]; 237 scriptsCopy[i] = scripts[i];
161 for (var i = 0; i < len; ++i) { 238 for (var i = 0; i < len; ++i) {
162 thisScript = scriptsCopy[i]; 239 thisScript = scriptsCopy[i];
163 eval(thisScript.textContent); 240 try {
241 eval(thisScript.textContent);
242 } catch (v) {
243 doExn(v);
244 }
164 } 245 }
165 246
166 thisScript = savedScript; 247 thisScript = savedScript;
167 } 248 }
168 249
225 function pi(s) { 306 function pi(s) {
226 var r = parseInt(s); 307 var r = parseInt(s);
227 if (r.toString() == s) 308 if (r.toString() == s)
228 return r; 309 return r;
229 else 310 else
230 throw "Can't parse int: " + s; 311 er("Can't parse int: " + s);
231 } 312 }
232 313
233 function pfl(s) { 314 function pfl(s) {
234 var r = parseFloat(s); 315 var r = parseFloat(s);
235 if (r.toString() == s) 316 if (r.toString() == s)
236 return r; 317 return r;
237 else 318 else
238 throw "Can't parse float: " + s; 319 er("Can't parse float: " + s);
239 } 320 }
240 321
241 function uf(s) { 322 function uf(s) {
242 return escape(s).replace(new RegExp ("/", "g"), "%2F"); 323 return escape(s).replace(new RegExp ("/", "g"), "%2F");
243 } 324 }
244 325
245 function uu(s) { 326 function uu(s) {
246 return unescape(s).replace(new RegExp ("\\+", "g"), " "); 327 return unescape(s).replace(new RegExp ("\\+", "g"), " ");
247 } 328 }
248 329
249
250 // Error handling
251
252 function whine(msg) {
253 alert(msg);
254 throw msg;
255 }
256
257 function pf() {
258 whine("Pattern match failure");
259 }
260
261 var errorHandlers = null;
262
263 function onError(f) {
264 errorHandlers = cons(f, errorHandlers);
265 }
266
267 function er(s) {
268 for (var ls = errorHandlers; ls; ls = ls.next)
269 ls.data(s)(null);
270 throw {uw_error: s};
271 }
272
273 var failHandlers = null;
274
275 function onFail(f) {
276 failHandlers = cons(f, failHandlers);
277 }
278
279 function doExn(v) {
280 if (v == null || v.uw_error == null) {
281 var s = (v == null ? "null" : v.toString());
282 for (var ls = failHandlers; ls; ls = ls.next)
283 ls.data(s)(null);
284 }
285 }
286 330
287 331
288 // Remote calls 332 // Remote calls
289 333
290 var client_id = null; 334 var client_id = null;
331 try { 375 try {
332 if (xhr.status == 200) 376 if (xhr.status == 200)
333 isok = true; 377 isok = true;
334 } catch (e) { } 378 } catch (e) { }
335 379
336 if (isok) 380 if (isok) {
337 k(parse(xhr.responseText)); 381 try {
338 else { 382 k(parse(xhr.responseText));
339 whine("Error querying remote server!"); 383 } catch (v) {
384 doExn(v);
385 }
386 } else {
387 conn();
340 } 388 }
341 } 389 }
342 }; 390 };
343 391
344 requestUri(xhr, uri); 392 requestUri(xhr, uri);
404 isok = true; 452 isok = true;
405 } catch (e) { } 453 } catch (e) { }
406 454
407 if (isok) { 455 if (isok) {
408 var lines = xhr.responseText.split("\n"); 456 var lines = xhr.responseText.split("\n");
409 if (lines.length < 2) 457 if (lines.length < 2) {
410 return; // throw "Empty message from remote server"; 458 discon();
459 return;
460 }
411 461
412 for (var i = 0; i+1 < lines.length; i += 2) { 462 for (var i = 0; i+1 < lines.length; i += 2) {
413 var chn = lines[i]; 463 var chn = lines[i];
414 var msg = lines[i+1]; 464 var msg = lines[i+1];
415 465
437 } 487 }
438 488
439 connect(); 489 connect();
440 } 490 }
441 else { 491 else {
442 /*try { 492 try {
443 whine("Error querying remote server for messages! " + xhr.status); 493 servError("Error querying remote server for messages: " + xhr.status);
444 } catch (e) { }*/ 494 } catch (e) { servError("Error querying remote server for messages"); }
445 } 495 }
446 } 496 }
447 }; 497 };
448 498
449 onTimeout = function() { 499 onTimeout = function() {