| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 | 
							- /* appjet:version 0.1 */
 
- /* appjet:library */
 
- // Copyright (c) 2009, Herbert Vojčík
 
- // Licensed by MIT license (http://www.opensource.org/licenses/mit-license.php)
 
- /**@overview This library contains various utility functions
 
-  * that appeared during developing other apps but are general enough.
 
-  */
 
- /**
 
-  * Returns global object.
 
-  */
 
- function global() { return {}.valueOf.call(); }
 
- /**
 
-  * Read-only wrapper on an object.
 
-  */
 
- function readonly(o) {
 
-     return appjet._native.createProxyObject(
 
-         function(name) { return o[name]; },
 
-         function() {},
 
-         function() {},
 
-         function() { return []; },
 
-         o
 
-     );
 
- }
 
- /**
 
-  * Extends an object by copying all other object's own properties.
 
-  * Returns the extended object. This implies you can create clone
 
-  * of simple object by extend({}, x).
 
-  */
 
- function extend(dst, src) {
 
-     eachProperty(src, function(p) { dst[p] = src[p]; });
 
-     return dst;
 
- }
 
- /**
 
-  * Akin to <code>Array >> streamContents:</code> in Smalltalk.
 
-  * Calls f and returns array of every item that was printed using print.
 
-  * Useful for collecting any item in some loop(s) for which
 
-  * filter or map can not be straightforwardly used. Both examples get keys
 
-  * of own properties
 
-  @example
 
-  collectPrint(function() { eachProperty(object, print); });
 
-  collectPrint(function() {for (var p in object) { if (object.hasOwnProperty(p) print(p); }});
 
-  */
 
- function collectPrint(f) {
 
-     var result = [];
 
-     var _g = global();
 
-     var savedPrint = _g.print;
 
-     _g.print = function() { result.push.apply(result, arguments); }; // cannot inline, or f***ing try/finally bug which nobody is willing to fix appears
 
-     try { f(); } finally { _g.print = savedPrint; }
 
-     return result;
 
- }
 
- function _collector(result) { return function() { result.push.apply(result, arguments); }; }
 
- /**
 
-  * Akin to <code>Array >> streamContents:</code> in Smalltalk.
 
-  * Calls f and returns array of every item that was yielded using yield.
 
-  * Useful for collecting any item in some loop(s) for which
 
-  * filter or map can not be straightforwardly used. An example gets keys
 
-  * of own properties
 
-  @example
 
-  collectYield(function () {for (var p in object) { if (object.hasOwnProperty(p) yield p; }});
 
-  */
 
- /*function collectYield(f) {
 
-     var result = [];
 
-     var gen = f();
 
-     try {
 
-         for(;;) { result.push(gen.next()); }
 
-     } catch (ex) {
 
-     	if (ex instanceof StopIteration) {
 
-     		//gen.close(); //strange, not needed
 
-     	} else throw ex;
 
-     }
 
-     return result;
 
- }*/
 
- //from web; then edited
 
- /** Converts h,s,v (0-1) to rgb (0-255). Returns array [r, g, b]. */
 
- function hsv2rgb(h,s,v) {
 
-     // Adapted from http://www.easyrgb.com/math.html
 
-     // hsv values = 0 - 1, rgb values = 0 - 255
 
-     var r, g, b;
 
-     if (s == 0) {
 
-     	r = g = b = v;
 
-     } else {
 
-         var vh = 6*h;
 
-         var vi = Math.floor(vh);
 
-         var v1 = v*(1-s);
 
-         var v2 = v*(1-s*(vh-vi));
 
-         var v3 = v*(1-s*(1-(vh-vi)));
 
-         switch(vi) {
 
-             case 0: r = v; g = v3; b = v1; break;
 
-             case 1: r = v2; g = v; b = v1; break;
 
-             case 2: r = v1; g = v; b = v3; break;
 
-             case 3: r = v1; g = v2; b = v; break;
 
-             case 4: r = v3; g = v1; b = v; break;
 
-             case 5: r = v; g = v1; b = v2; break;
 
-         }
 
-     }
 
-     return [ Math.round(255*r), Math.round(255*g), Math.round(255*b) ];
 
- }
 
- /**
 
-  * Call this function with etag of actual requested resource.
 
-  * Includes caching headers in the response,
 
-  * and if the ETag matches, it immediately stops the response
 
-  * with "304 Not Modified"; in other case it returns
 
-  * and lets you continue with populating the response data.
 
-  * Call after you KNOW the resource exists! It is illegal
 
-  * to change response status to 404 or similar after this call.
 
-  */
 
- function etagCaching(etag) {
 
-     response.setCacheable(null);
 
-     response.setHeader("Cache-Control", "public, must-revalidate");
 
-     response.setHeader("ETag", etag);
 
-     var cond = request.headers["If-None-Match"];
 
-     if (cond && (cond === "*" || ([].concat(cond).indexOf(etag) !== -1))) {
 
-         response.setStatusCode(304);
 
-         response.stop();
 
-     }
 
- }
 
- /**
 
-   * Splits all elements of an array by delimiter
 
-   * and insert o in places where split occurred.
 
-   * Returns modified array with split parts and delimiting o's.
 
-   */
 
- function splitReplace(array, delimiter, o) {
 
-   var i, j, k, l = 0, m = array.length;
 
-   array.forEach(function (v, k, a) {
 
-     var split = a[k] = v.split ? v.split(delimiter) : [v];
 
-     l += 2 * split.length - 1;
 
-   });
 
-   array.length = l;
 
-   for (var i = m-1, j = l-1; i >= 0; i--) {
 
-     var parts = array[i];
 
-     for (var k = parts.length - 1; k > 0; --k) {
 
-       array[j--] = parts[k--];
 
-       array[j--] = o;
 
-     }
 
-     array[j--] = parts[0];
 
-   }
 
-   return array;
 
- }
 
- /* appjet:server */
 
- import("lib-support/jsunit");
 
- var _l = import({}, "lib-support/useful");
 
- // ==== Test cases ====
 
- page.testSuite = [
 
- 	function collectPrintCollectsPrintedArguments() {
 
- 	    var collected = _l.collectPrint(function() {
 
- 	        print("Hello", "world", "!");
 
- 	        print();
 
- 	        print(3,1,4);
 
- 	    });
 
- 	    assertArrayEquals("Incorrect items collected.", ["Hello", "world", "!", 3, 1, 4], collected);
 
- 	},
 
- 	
 
- 	function collectPrintRetainsLegacyPrint() {
 
- 	    var savedPrint = this.print;
 
- 	    _l.collectPrint(function() {
 
- 	        print("Hello", "world", "!");
 
- 	        print();
 
- 	        print(3,1,4);
 
- 	    });
 
- 	    assertEquals("Print not retained.", savedPrint, this.print);
 
- 	},
 
- 	
 
- 	function collectPrintRetainsLegacyPrintInCaseOfException() {
 
- 	    var savedPrint = this.print;
 
- 	    var f = function() { throw "exception"; };
 
- 	    try {
 
- 	        _l.collectPrint(f);
 
- 	        fail("Exception not thrown");
 
- 	    } catch(ex) {
 
- 	    	if (ex === "exception") {
 
- 	    		// pass
 
- 	    	} else throw ex;
 
- 	    }
 
- 	    assertEquals("Print not retained.", savedPrint, this.print);
 
- 	},
 
- 	
 
- 	function collectPrintRetainsLegacyPrintInCaseOfUndefinedException() {
 
- 	    var savedPrint = this.print;
 
- 	    var f = function() { throw undefined; };
 
- 	    try {
 
- 	        _l.collectPrint(f);
 
- 	        fail("Exception not thrown");
 
- 	    } catch(ex) {
 
- 	    	if (ex === undefined) {
 
- 	    		// pass
 
- 	    	} else throw ex;
 
- 	    }
 
- 	    assertEquals("Print not retained.", savedPrint, this.print);
 
- 	},
 
- 	
 
- 	/*function collectYieldCollectsYieldedArguments() {
 
- 	    var collected = _l.collectYield(function() {
 
- 	        yield "Hello";
 
- 	        yield 3;
 
- 	    });
 
- 	    assertArrayEquals("Incorrect items collected.", ["Hello", 3], collected);
 
- 	},
 
- 	
 
- 	function collectYieldCollectsYieldeesFromTryBlockAndFinallyRuns() {
 
- 	    var frun = false;
 
- 	    var collected = _l.collectYield(function() {
 
- 	        try {
 
- 	            yield "Hello";
 
- 	            yield 3;
 
- 	        } finally { frun = true; }
 
- 	    });
 
- 	    assertArrayEquals("Incorrect items collected.", ["Hello", 3], collected);
 
- 	    assertTrue("Finally did not run", frun);
 
- 	},
 
- 	
 
- 	function collectYieldThrowsExceptionIfThrownInF() {
 
- 	    try {
 
- 	        var collected = _l.collectYield(function() {
 
- 	            yield "Hello";
 
- 	            throw "exception";
 
- 	            yield "world";
 
- 	        });
 
- 	        fail("Exception not thrown.");
 
- 	    } catch(ex) {
 
- 	    	if (ex === "exception") {
 
- 	    		// pass
 
- 	    	} else throw ex;
 
- 	    }
 
- 	},
 
- 	
 
- 	function collectYieldThrowsUndefinedIfThrownInF() {
 
- 	    try {
 
- 	        var collected = _l.collectYield(function() {
 
- 	            yield "Hello";
 
- 	            throw undefined;
 
- 	            yield "world";
 
- 	        });
 
- 	        fail("Exception not thrown.");
 
- 	    } catch(ex) {
 
- 	    	if (ex === undefined) {
 
- 	    		// pass
 
- 	    	} else throw ex;
 
- 	    }
 
- 	},
 
- 	
 
- 	function collectYieldThrowsExceptionIfExceptionThrownInF_AndFinallyInFRuns() {
 
- 	    var finallyRun = false;
 
- 	    try {
 
- 	        var collected = _l.collectYield(function() {
 
- 	            try {
 
- 	                yield "Hello";
 
- 	                throw "exception";
 
- 	                yield "world";
 
- 	            } finally { finallyRun = true; }
 
- 	        });
 
- 	        fail("Exception not thrown.");
 
- 	    } catch(ex) {
 
- 	    	if (ex === "exception") {
 
- 	    		// pass
 
- 	    	} else throw ex;
 
- 	    }
 
- 	    assertTrue("Finally in f did not run.", finallyRun);
 
- 	},*/
 
- 	
 
- 	function readonlyReadsCorrectlyAndIsDynamic() {
 
- 	    var x = {hello: "world"};
 
- 	    var rx = _l.readonly(x);
 
- 	    assertEquals("Hello read incorrectly", "world", rx.hello);
 
- 	    assertUndefined("Nonexistent property is not undefined", rx.thisIsNot);
 
- 	    x.hello = "again";
 
- 	    x.thisIsNot = "this is";
 
- 	    assertEquals("Hello read incorrectly", "again", rx.hello);
 
- 	    assertEquals("ThisIsNot read incorrectly", "this is", rx.thisIsNot);
 
- 	},
 
- 	
 
- 	function readonlyIsReadOnly() {
 
- 	    var x = {hello: "world"};
 
- 	    var rx = _l.readonly(x);
 
- 	    rx.thisIsNot = "this is";
 
- 	    delete rx.hello;
 
- 	    assertEquals("Hello read incorrectly", "world", rx.hello);
 
- 	    assertUndefined("Nonexistent property is not undefined", rx.thisIsNot);
 
- 	},
 
- 	
 
- 	function extendExtendsCorrectlyForAllCombinations() {
 
- 	    var srcProto = { pro: "to" };
 
- 	    var src = object(srcProto);
 
- 	    src.a = "b"; src.c = "d";
 
- 	    var dst = { pro: "fi", a: "bc", yes: "true" };
 
- 	    var result = _l.extend(dst, src);
 
- 	    assertEquals("extend did not return extended object", dst, result);
 
- 	    assertEquals("a wasn't copied", "b", dst.a);
 
- 	    assertEquals("c wasn't copied", "d", dst.c);
 
- 	    assertEquals("pro was changed", "fi", dst.pro);
 
- 	    assertEquals("yes was changed", "true", dst.yes);
 
- 	},
 
- 	
 
- 	  //TODO tests for splitReplace
 
- ];
 
- // ==== Test runner ====
 
- import("lib-support/runner");
 
- runTestsByDefault();
 
 
  |