|
1 /*** |
|
2 |
|
3 MochiKit.Async 1.4 |
|
4 |
|
5 See <http://mochikit.com/> for documentation, downloads, license, etc. |
|
6 |
|
7 (c) 2005 Bob Ippolito. All rights Reserved. |
|
8 |
|
9 ***/ |
|
10 |
|
11 if (typeof(dojo) != 'undefined') { |
|
12 dojo.provide("MochiKit.Async"); |
|
13 dojo.require("MochiKit.Base"); |
|
14 } |
|
15 if (typeof(JSAN) != 'undefined') { |
|
16 JSAN.use("MochiKit.Base", []); |
|
17 } |
|
18 |
|
19 try { |
|
20 if (typeof(MochiKit.Base) == 'undefined') { |
|
21 throw ""; |
|
22 } |
|
23 } catch (e) { |
|
24 throw "MochiKit.Async depends on MochiKit.Base!"; |
|
25 } |
|
26 |
|
27 if (typeof(MochiKit.Async) == 'undefined') { |
|
28 MochiKit.Async = {}; |
|
29 } |
|
30 |
|
31 MochiKit.Async.NAME = "MochiKit.Async"; |
|
32 MochiKit.Async.VERSION = "1.4"; |
|
33 MochiKit.Async.__repr__ = function () { |
|
34 return "[" + this.NAME + " " + this.VERSION + "]"; |
|
35 }; |
|
36 MochiKit.Async.toString = function () { |
|
37 return this.__repr__(); |
|
38 }; |
|
39 |
|
40 /** @id MochiKit.Async.Deferred */ |
|
41 MochiKit.Async.Deferred = function (/* optional */ canceller) { |
|
42 this.chain = []; |
|
43 this.id = this._nextId(); |
|
44 this.fired = -1; |
|
45 this.paused = 0; |
|
46 this.results = [null, null]; |
|
47 this.canceller = canceller; |
|
48 this.silentlyCancelled = false; |
|
49 this.chained = false; |
|
50 }; |
|
51 |
|
52 MochiKit.Async.Deferred.prototype = { |
|
53 /** @id MochiKit.Async.Deferred.prototype.repr */ |
|
54 repr: function () { |
|
55 var state; |
|
56 if (this.fired == -1) { |
|
57 state = 'unfired'; |
|
58 } else if (this.fired === 0) { |
|
59 state = 'success'; |
|
60 } else { |
|
61 state = 'error'; |
|
62 } |
|
63 return 'Deferred(' + this.id + ', ' + state + ')'; |
|
64 }, |
|
65 |
|
66 toString: MochiKit.Base.forwardCall("repr"), |
|
67 |
|
68 _nextId: MochiKit.Base.counter(), |
|
69 |
|
70 /** @id MochiKit.Async.Deferred.prototype.cancel */ |
|
71 cancel: function () { |
|
72 var self = MochiKit.Async; |
|
73 if (this.fired == -1) { |
|
74 if (this.canceller) { |
|
75 this.canceller(this); |
|
76 } else { |
|
77 this.silentlyCancelled = true; |
|
78 } |
|
79 if (this.fired == -1) { |
|
80 this.errback(new self.CancelledError(this)); |
|
81 } |
|
82 } else if ((this.fired === 0) && (this.results[0] instanceof self.Deferred)) { |
|
83 this.results[0].cancel(); |
|
84 } |
|
85 }, |
|
86 |
|
87 _resback: function (res) { |
|
88 /*** |
|
89 |
|
90 The primitive that means either callback or errback |
|
91 |
|
92 ***/ |
|
93 this.fired = ((res instanceof Error) ? 1 : 0); |
|
94 this.results[this.fired] = res; |
|
95 this._fire(); |
|
96 }, |
|
97 |
|
98 _check: function () { |
|
99 if (this.fired != -1) { |
|
100 if (!this.silentlyCancelled) { |
|
101 throw new MochiKit.Async.AlreadyCalledError(this); |
|
102 } |
|
103 this.silentlyCancelled = false; |
|
104 return; |
|
105 } |
|
106 }, |
|
107 |
|
108 /** @id MochiKit.Async.Deferred.prototype.callback */ |
|
109 callback: function (res) { |
|
110 this._check(); |
|
111 if (res instanceof MochiKit.Async.Deferred) { |
|
112 throw new Error("Deferred instances can only be chained if they are the result of a callback"); |
|
113 } |
|
114 this._resback(res); |
|
115 }, |
|
116 |
|
117 /** @id MochiKit.Async.Deferred.prototype.errback */ |
|
118 errback: function (res) { |
|
119 this._check(); |
|
120 var self = MochiKit.Async; |
|
121 if (res instanceof self.Deferred) { |
|
122 throw new Error("Deferred instances can only be chained if they are the result of a callback"); |
|
123 } |
|
124 if (!(res instanceof Error)) { |
|
125 res = new self.GenericError(res); |
|
126 } |
|
127 this._resback(res); |
|
128 }, |
|
129 |
|
130 /** @id MochiKit.Async.Deferred.prototype.addBoth */ |
|
131 addBoth: function (fn) { |
|
132 if (arguments.length > 1) { |
|
133 fn = MochiKit.Base.partial.apply(null, arguments); |
|
134 } |
|
135 return this.addCallbacks(fn, fn); |
|
136 }, |
|
137 |
|
138 /** @id MochiKit.Async.Deferred.prototype.addCallback */ |
|
139 addCallback: function (fn) { |
|
140 if (arguments.length > 1) { |
|
141 fn = MochiKit.Base.partial.apply(null, arguments); |
|
142 } |
|
143 return this.addCallbacks(fn, null); |
|
144 }, |
|
145 |
|
146 /** @id MochiKit.Async.Deferred.prototype.addErrback */ |
|
147 addErrback: function (fn) { |
|
148 if (arguments.length > 1) { |
|
149 fn = MochiKit.Base.partial.apply(null, arguments); |
|
150 } |
|
151 return this.addCallbacks(null, fn); |
|
152 }, |
|
153 |
|
154 /** @id MochiKit.Async.Deferred.prototype.addCallbacks */ |
|
155 addCallbacks: function (cb, eb) { |
|
156 if (this.chained) { |
|
157 throw new Error("Chained Deferreds can not be re-used"); |
|
158 } |
|
159 this.chain.push([cb, eb]); |
|
160 if (this.fired >= 0) { |
|
161 this._fire(); |
|
162 } |
|
163 return this; |
|
164 }, |
|
165 |
|
166 _fire: function () { |
|
167 /*** |
|
168 |
|
169 Used internally to exhaust the callback sequence when a result |
|
170 is available. |
|
171 |
|
172 ***/ |
|
173 var chain = this.chain; |
|
174 var fired = this.fired; |
|
175 var res = this.results[fired]; |
|
176 var self = this; |
|
177 var cb = null; |
|
178 while (chain.length > 0 && this.paused === 0) { |
|
179 // Array |
|
180 var pair = chain.shift(); |
|
181 var f = pair[fired]; |
|
182 if (f === null) { |
|
183 continue; |
|
184 } |
|
185 try { |
|
186 res = f(res); |
|
187 fired = ((res instanceof Error) ? 1 : 0); |
|
188 if (res instanceof MochiKit.Async.Deferred) { |
|
189 cb = function (res) { |
|
190 self._resback(res); |
|
191 self.paused--; |
|
192 if ((self.paused === 0) && (self.fired >= 0)) { |
|
193 self._fire(); |
|
194 } |
|
195 }; |
|
196 this.paused++; |
|
197 } |
|
198 } catch (err) { |
|
199 fired = 1; |
|
200 if (!(err instanceof Error)) { |
|
201 err = new MochiKit.Async.GenericError(err); |
|
202 } |
|
203 res = err; |
|
204 } |
|
205 } |
|
206 this.fired = fired; |
|
207 this.results[fired] = res; |
|
208 if (cb && this.paused) { |
|
209 // this is for "tail recursion" in case the dependent deferred |
|
210 // is already fired |
|
211 res.addBoth(cb); |
|
212 res.chained = true; |
|
213 } |
|
214 } |
|
215 }; |
|
216 |
|
217 MochiKit.Base.update(MochiKit.Async, { |
|
218 /** @id MochiKit.Async.evalJSONRequest */ |
|
219 evalJSONRequest: function (req) { |
|
220 return MochiKit.Base.evalJSON(req.responseText); |
|
221 }, |
|
222 |
|
223 /** @id MochiKit.Async.succeed */ |
|
224 succeed: function (/* optional */result) { |
|
225 var d = new MochiKit.Async.Deferred(); |
|
226 d.callback.apply(d, arguments); |
|
227 return d; |
|
228 }, |
|
229 |
|
230 /** @id MochiKit.Async.fail */ |
|
231 fail: function (/* optional */result) { |
|
232 var d = new MochiKit.Async.Deferred(); |
|
233 d.errback.apply(d, arguments); |
|
234 return d; |
|
235 }, |
|
236 |
|
237 /** @id MochiKit.Async.getXMLHttpRequest */ |
|
238 getXMLHttpRequest: function () { |
|
239 var self = arguments.callee; |
|
240 if (!self.XMLHttpRequest) { |
|
241 var tryThese = [ |
|
242 function () { return new XMLHttpRequest(); }, |
|
243 function () { return new ActiveXObject('Msxml2.XMLHTTP'); }, |
|
244 function () { return new ActiveXObject('Microsoft.XMLHTTP'); }, |
|
245 function () { return new ActiveXObject('Msxml2.XMLHTTP.4.0'); }, |
|
246 function () { |
|
247 throw new MochiKit.Async.BrowserComplianceError("Browser does not support XMLHttpRequest"); |
|
248 } |
|
249 ]; |
|
250 for (var i = 0; i < tryThese.length; i++) { |
|
251 var func = tryThese[i]; |
|
252 try { |
|
253 self.XMLHttpRequest = func; |
|
254 return func(); |
|
255 } catch (e) { |
|
256 // pass |
|
257 } |
|
258 } |
|
259 } |
|
260 return self.XMLHttpRequest(); |
|
261 }, |
|
262 |
|
263 _xhr_onreadystatechange: function (d) { |
|
264 // MochiKit.Logging.logDebug('this.readyState', this.readyState); |
|
265 var m = MochiKit.Base; |
|
266 if (this.readyState == 4) { |
|
267 // IE SUCKS |
|
268 try { |
|
269 this.onreadystatechange = null; |
|
270 } catch (e) { |
|
271 try { |
|
272 this.onreadystatechange = m.noop; |
|
273 } catch (e) { |
|
274 } |
|
275 } |
|
276 var status = null; |
|
277 try { |
|
278 status = this.status; |
|
279 if (!status && m.isNotEmpty(this.responseText)) { |
|
280 // 0 or undefined seems to mean cached or local |
|
281 status = 304; |
|
282 } |
|
283 } catch (e) { |
|
284 // pass |
|
285 // MochiKit.Logging.logDebug('error getting status?', repr(items(e))); |
|
286 } |
|
287 // 200 is OK, 201 is CREATED, 204 is NO CONTENT |
|
288 // 304 is NOT MODIFIED, 1223 is apparently a bug in IE |
|
289 if (status == 200 || status == 201 || status == 204 || |
|
290 status == 304 || status == 1223) { |
|
291 d.callback(this); |
|
292 } else { |
|
293 var err = new MochiKit.Async.XMLHttpRequestError(this, "Request failed"); |
|
294 if (err.number) { |
|
295 // XXX: This seems to happen on page change |
|
296 d.errback(err); |
|
297 } else { |
|
298 // XXX: this seems to happen when the server is unreachable |
|
299 d.errback(err); |
|
300 } |
|
301 } |
|
302 } |
|
303 }, |
|
304 |
|
305 _xhr_canceller: function (req) { |
|
306 // IE SUCKS |
|
307 try { |
|
308 req.onreadystatechange = null; |
|
309 } catch (e) { |
|
310 try { |
|
311 req.onreadystatechange = MochiKit.Base.noop; |
|
312 } catch (e) { |
|
313 } |
|
314 } |
|
315 req.abort(); |
|
316 }, |
|
317 |
|
318 |
|
319 /** @id MochiKit.Async.sendXMLHttpRequest */ |
|
320 sendXMLHttpRequest: function (req, /* optional */ sendContent) { |
|
321 if (typeof(sendContent) == "undefined" || sendContent === null) { |
|
322 sendContent = ""; |
|
323 } |
|
324 |
|
325 var m = MochiKit.Base; |
|
326 var self = MochiKit.Async; |
|
327 var d = new self.Deferred(m.partial(self._xhr_canceller, req)); |
|
328 |
|
329 try { |
|
330 req.onreadystatechange = m.bind(self._xhr_onreadystatechange, |
|
331 req, d); |
|
332 req.send(sendContent); |
|
333 } catch (e) { |
|
334 try { |
|
335 req.onreadystatechange = null; |
|
336 } catch (ignore) { |
|
337 // pass |
|
338 } |
|
339 d.errback(e); |
|
340 } |
|
341 |
|
342 return d; |
|
343 |
|
344 }, |
|
345 |
|
346 /** @id MochiKit.Async.doXHR */ |
|
347 doXHR: function (url, opts) { |
|
348 /* |
|
349 Work around a Firefox bug by dealing with XHR during |
|
350 the next event loop iteration. Maybe it's this one: |
|
351 https://bugzilla.mozilla.org/show_bug.cgi?id=249843 |
|
352 */ |
|
353 var self = MochiKit.Async; |
|
354 return self.callLater(0, self._doXHR, url, opts); |
|
355 }, |
|
356 |
|
357 _doXHR: function (url, opts) { |
|
358 var m = MochiKit.Base; |
|
359 opts = m.update({ |
|
360 method: 'GET', |
|
361 sendContent: '' |
|
362 /* |
|
363 queryString: undefined, |
|
364 username: undefined, |
|
365 password: undefined, |
|
366 headers: undefined, |
|
367 mimeType: undefined |
|
368 */ |
|
369 }, opts); |
|
370 var self = MochiKit.Async; |
|
371 var req = self.getXMLHttpRequest(); |
|
372 if (opts.queryString) { |
|
373 var qs = m.queryString(opts.queryString); |
|
374 if (qs) { |
|
375 url += "?" + qs; |
|
376 } |
|
377 } |
|
378 // Safari will send undefined:undefined, so we have to check. |
|
379 // We can't use apply, since the function is native. |
|
380 if ('username' in opts) { |
|
381 req.open(opts.method, url, true, opts.username, opts.password); |
|
382 } else { |
|
383 req.open(opts.method, url, true); |
|
384 } |
|
385 if (req.overrideMimeType && opts.mimeType) { |
|
386 req.overrideMimeType(opts.mimeType); |
|
387 } |
|
388 if (opts.headers) { |
|
389 var headers = opts.headers; |
|
390 if (!m.isArrayLike(headers)) { |
|
391 headers = m.items(headers); |
|
392 } |
|
393 for (var i = 0; i < headers.length; i++) { |
|
394 var header = headers[i]; |
|
395 var name = header[0]; |
|
396 var value = header[1]; |
|
397 req.setRequestHeader(name, value); |
|
398 } |
|
399 } |
|
400 return self.sendXMLHttpRequest(req, opts.sendContent); |
|
401 }, |
|
402 |
|
403 _buildURL: function (url/*, ...*/) { |
|
404 if (arguments.length > 1) { |
|
405 var m = MochiKit.Base; |
|
406 var qs = m.queryString.apply(null, m.extend(null, arguments, 1)); |
|
407 if (qs) { |
|
408 return url + "?" + qs; |
|
409 } |
|
410 } |
|
411 return url; |
|
412 }, |
|
413 |
|
414 /** @id MochiKit.Async.doSimpleXMLHttpRequest */ |
|
415 doSimpleXMLHttpRequest: function (url/*, ...*/) { |
|
416 var self = MochiKit.Async; |
|
417 url = self._buildURL.apply(self, arguments); |
|
418 return self.doXHR(url); |
|
419 }, |
|
420 |
|
421 /** @id MochiKit.Async.loadJSONDoc */ |
|
422 loadJSONDoc: function (url/*, ...*/) { |
|
423 var self = MochiKit.Async; |
|
424 url = self._buildURL.apply(self, arguments); |
|
425 var d = self.doXHR(url, { |
|
426 'mimeType': 'text/plain', |
|
427 'headers': [['Accept', 'application/json']] |
|
428 }); |
|
429 d = d.addCallback(self.evalJSONRequest); |
|
430 return d; |
|
431 }, |
|
432 |
|
433 /** @id MochiKit.Async.wait */ |
|
434 wait: function (seconds, /* optional */value) { |
|
435 var d = new MochiKit.Async.Deferred(); |
|
436 var m = MochiKit.Base; |
|
437 if (typeof(value) != 'undefined') { |
|
438 d.addCallback(function () { return value; }); |
|
439 } |
|
440 var timeout = setTimeout( |
|
441 m.bind("callback", d), |
|
442 Math.floor(seconds * 1000)); |
|
443 d.canceller = function () { |
|
444 try { |
|
445 clearTimeout(timeout); |
|
446 } catch (e) { |
|
447 // pass |
|
448 } |
|
449 }; |
|
450 return d; |
|
451 }, |
|
452 |
|
453 /** @id MochiKit.Async.callLater */ |
|
454 callLater: function (seconds, func) { |
|
455 var m = MochiKit.Base; |
|
456 var pfunc = m.partial.apply(m, m.extend(null, arguments, 1)); |
|
457 return MochiKit.Async.wait(seconds).addCallback( |
|
458 function (res) { return pfunc(); } |
|
459 ); |
|
460 } |
|
461 }); |
|
462 |
|
463 |
|
464 /** @id MochiKit.Async.DeferredLock */ |
|
465 MochiKit.Async.DeferredLock = function () { |
|
466 this.waiting = []; |
|
467 this.locked = false; |
|
468 this.id = this._nextId(); |
|
469 }; |
|
470 |
|
471 MochiKit.Async.DeferredLock.prototype = { |
|
472 __class__: MochiKit.Async.DeferredLock, |
|
473 /** @id MochiKit.Async.DeferredLock.prototype.acquire */ |
|
474 acquire: function () { |
|
475 var d = new MochiKit.Async.Deferred(); |
|
476 if (this.locked) { |
|
477 this.waiting.push(d); |
|
478 } else { |
|
479 this.locked = true; |
|
480 d.callback(this); |
|
481 } |
|
482 return d; |
|
483 }, |
|
484 /** @id MochiKit.Async.DeferredLock.prototype.release */ |
|
485 release: function () { |
|
486 if (!this.locked) { |
|
487 throw TypeError("Tried to release an unlocked DeferredLock"); |
|
488 } |
|
489 this.locked = false; |
|
490 if (this.waiting.length > 0) { |
|
491 this.locked = true; |
|
492 this.waiting.shift().callback(this); |
|
493 } |
|
494 }, |
|
495 _nextId: MochiKit.Base.counter(), |
|
496 repr: function () { |
|
497 var state; |
|
498 if (this.locked) { |
|
499 state = 'locked, ' + this.waiting.length + ' waiting'; |
|
500 } else { |
|
501 state = 'unlocked'; |
|
502 } |
|
503 return 'DeferredLock(' + this.id + ', ' + state + ')'; |
|
504 }, |
|
505 toString: MochiKit.Base.forwardCall("repr") |
|
506 |
|
507 }; |
|
508 |
|
509 /** @id MochiKit.Async.DeferredList */ |
|
510 MochiKit.Async.DeferredList = function (list, /* optional */fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller) { |
|
511 |
|
512 // call parent constructor |
|
513 MochiKit.Async.Deferred.apply(this, [canceller]); |
|
514 |
|
515 this.list = list; |
|
516 var resultList = []; |
|
517 this.resultList = resultList; |
|
518 |
|
519 this.finishedCount = 0; |
|
520 this.fireOnOneCallback = fireOnOneCallback; |
|
521 this.fireOnOneErrback = fireOnOneErrback; |
|
522 this.consumeErrors = consumeErrors; |
|
523 |
|
524 var cb = MochiKit.Base.bind(this._cbDeferred, this); |
|
525 for (var i = 0; i < list.length; i++) { |
|
526 var d = list[i]; |
|
527 resultList.push(undefined); |
|
528 d.addCallback(cb, i, true); |
|
529 d.addErrback(cb, i, false); |
|
530 } |
|
531 |
|
532 if (list.length === 0 && !fireOnOneCallback) { |
|
533 this.callback(this.resultList); |
|
534 } |
|
535 |
|
536 }; |
|
537 |
|
538 MochiKit.Async.DeferredList.prototype = new MochiKit.Async.Deferred(); |
|
539 |
|
540 MochiKit.Async.DeferredList.prototype._cbDeferred = function (index, succeeded, result) { |
|
541 this.resultList[index] = [succeeded, result]; |
|
542 this.finishedCount += 1; |
|
543 if (this.fired == -1) { |
|
544 if (succeeded && this.fireOnOneCallback) { |
|
545 this.callback([index, result]); |
|
546 } else if (!succeeded && this.fireOnOneErrback) { |
|
547 this.errback(result); |
|
548 } else if (this.finishedCount == this.list.length) { |
|
549 this.callback(this.resultList); |
|
550 } |
|
551 } |
|
552 if (!succeeded && this.consumeErrors) { |
|
553 result = null; |
|
554 } |
|
555 return result; |
|
556 }; |
|
557 |
|
558 /** @id MochiKit.Async.gatherResults */ |
|
559 MochiKit.Async.gatherResults = function (deferredList) { |
|
560 var d = new MochiKit.Async.DeferredList(deferredList, false, true, false); |
|
561 d.addCallback(function (results) { |
|
562 var ret = []; |
|
563 for (var i = 0; i < results.length; i++) { |
|
564 ret.push(results[i][1]); |
|
565 } |
|
566 return ret; |
|
567 }); |
|
568 return d; |
|
569 }; |
|
570 |
|
571 /** @id MochiKit.Async.maybeDeferred */ |
|
572 MochiKit.Async.maybeDeferred = function (func) { |
|
573 var self = MochiKit.Async; |
|
574 var result; |
|
575 try { |
|
576 var r = func.apply(null, MochiKit.Base.extend([], arguments, 1)); |
|
577 if (r instanceof self.Deferred) { |
|
578 result = r; |
|
579 } else if (r instanceof Error) { |
|
580 result = self.fail(r); |
|
581 } else { |
|
582 result = self.succeed(r); |
|
583 } |
|
584 } catch (e) { |
|
585 result = self.fail(e); |
|
586 } |
|
587 return result; |
|
588 }; |
|
589 |
|
590 |
|
591 MochiKit.Async.EXPORT = [ |
|
592 "AlreadyCalledError", |
|
593 "CancelledError", |
|
594 "BrowserComplianceError", |
|
595 "GenericError", |
|
596 "XMLHttpRequestError", |
|
597 "Deferred", |
|
598 "succeed", |
|
599 "fail", |
|
600 "getXMLHttpRequest", |
|
601 "doSimpleXMLHttpRequest", |
|
602 "loadJSONDoc", |
|
603 "wait", |
|
604 "callLater", |
|
605 "sendXMLHttpRequest", |
|
606 "DeferredLock", |
|
607 "DeferredList", |
|
608 "gatherResults", |
|
609 "maybeDeferred", |
|
610 "doXHR" |
|
611 ]; |
|
612 |
|
613 MochiKit.Async.EXPORT_OK = [ |
|
614 "evalJSONRequest" |
|
615 ]; |
|
616 |
|
617 MochiKit.Async.__new__ = function () { |
|
618 var m = MochiKit.Base; |
|
619 var ne = m.partial(m._newNamedError, this); |
|
620 |
|
621 ne("AlreadyCalledError", |
|
622 /** @id MochiKit.Async.AlreadyCalledError */ |
|
623 function (deferred) { |
|
624 /*** |
|
625 |
|
626 Raised by the Deferred if callback or errback happens |
|
627 after it was already fired. |
|
628 |
|
629 ***/ |
|
630 this.deferred = deferred; |
|
631 } |
|
632 ); |
|
633 |
|
634 ne("CancelledError", |
|
635 /** @id MochiKit.Async.CancelledError */ |
|
636 function (deferred) { |
|
637 /*** |
|
638 |
|
639 Raised by the Deferred cancellation mechanism. |
|
640 |
|
641 ***/ |
|
642 this.deferred = deferred; |
|
643 } |
|
644 ); |
|
645 |
|
646 ne("BrowserComplianceError", |
|
647 /** @id MochiKit.Async.BrowserComplianceError */ |
|
648 function (msg) { |
|
649 /*** |
|
650 |
|
651 Raised when the JavaScript runtime is not capable of performing |
|
652 the given function. Technically, this should really never be |
|
653 raised because a non-conforming JavaScript runtime probably |
|
654 isn't going to support exceptions in the first place. |
|
655 |
|
656 ***/ |
|
657 this.message = msg; |
|
658 } |
|
659 ); |
|
660 |
|
661 ne("GenericError", |
|
662 /** @id MochiKit.Async.GenericError */ |
|
663 function (msg) { |
|
664 this.message = msg; |
|
665 } |
|
666 ); |
|
667 |
|
668 ne("XMLHttpRequestError", |
|
669 /** @id MochiKit.Async.XMLHttpRequestError */ |
|
670 function (req, msg) { |
|
671 /*** |
|
672 |
|
673 Raised when an XMLHttpRequest does not complete for any reason. |
|
674 |
|
675 ***/ |
|
676 this.req = req; |
|
677 this.message = msg; |
|
678 try { |
|
679 // Strange but true that this can raise in some cases. |
|
680 this.number = req.status; |
|
681 } catch (e) { |
|
682 // pass |
|
683 } |
|
684 } |
|
685 ); |
|
686 |
|
687 |
|
688 this.EXPORT_TAGS = { |
|
689 ":common": this.EXPORT, |
|
690 ":all": m.concat(this.EXPORT, this.EXPORT_OK) |
|
691 }; |
|
692 |
|
693 m.nameFunctions(this); |
|
694 |
|
695 }; |
|
696 |
|
697 MochiKit.Async.__new__(); |
|
698 |
|
699 MochiKit.Base._exportSymbols(this, MochiKit.Async); |