Mercurial > urweb
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() { |