You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuscany.apache.org by js...@apache.org on 2013/08/26 05:04:34 UTC

svn commit: r1517415 [1/3] - in /tuscany/sca-cpp/trunk: ./ modules/http/ modules/js/ modules/js/htdocs/ patches/ ubuntu/

Author: jsdelfino
Date: Mon Aug 26 03:04:34 2013
New Revision: 1517415

URL: http://svn.apache.org/r1517415
Log:
Refactor base Javascript and CSS utilities and support server-side aggregation of HTML and Javascript.

Added:
    tuscany/sca-cpp/trunk/modules/http/ssinclude-html   (contents, props changed)
      - copied, changed from r1517414, tuscany/sca-cpp/trunk/modules/js/Makefile.am
    tuscany/sca-cpp/trunk/modules/js/js-extract   (contents, props changed)
      - copied, changed from r1517414, tuscany/sca-cpp/trunk/modules/js/Makefile.am
    tuscany/sca-cpp/trunk/patches/page-speed-1.9.patch
Modified:
    tuscany/sca-cpp/trunk/.gitignore
    tuscany/sca-cpp/trunk/modules/http/Makefile.am
    tuscany/sca-cpp/trunk/modules/js/Makefile.am
    tuscany/sca-cpp/trunk/modules/js/htdocs/component.js
    tuscany/sca-cpp/trunk/modules/js/htdocs/jsonutil.js
    tuscany/sca-cpp/trunk/modules/js/htdocs/ui.css
    tuscany/sca-cpp/trunk/modules/js/htdocs/ui.js
    tuscany/sca-cpp/trunk/modules/js/htdocs/util.js
    tuscany/sca-cpp/trunk/modules/js/htdocs/xmlutil.js
    tuscany/sca-cpp/trunk/modules/js/js-conf
    tuscany/sca-cpp/trunk/ubuntu/ubuntu-install-all
    tuscany/sca-cpp/trunk/ubuntu/ubuntu-install-nothreads

Modified: tuscany/sca-cpp/trunk/.gitignore
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/.gitignore?rev=1517415&r1=1517414&r2=1517415&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/.gitignore (original)
+++ tuscany/sca-cpp/trunk/.gitignore Mon Aug 26 03:04:34 2013
@@ -57,11 +57,14 @@ config.guess
 config.sub
 config.status
 all.js
+base.js
 cache-manifest.cmf
 *-min.html
+*-ssi.html
 *-min.js
 *-min.css
 *.b64
+*.off
 intro*.png
 depcomp
 install-sh

Modified: tuscany/sca-cpp/trunk/modules/http/Makefile.am
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/http/Makefile.am?rev=1517415&r1=1517414&r2=1517415&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/http/Makefile.am (original)
+++ tuscany/sca-cpp/trunk/modules/http/Makefile.am Mon Aug 26 03:04:34 2013
@@ -20,7 +20,7 @@ INCLUDES = -I${HTTPD_INCLUDE}
 incl_HEADERS = *.hpp
 incldir = $(prefix)/include/modules/http
 
-dist_mod_SCRIPTS = httpd-conf httpd-addr httpd-start httpd-stop httpd-restart ssl-ca-conf ssl-cert-conf ssl-cert-find httpd-ssl-conf base64-encode basic-auth-conf cert-auth-conf form-auth-conf open-auth-conf passwd-auth-conf group-auth-conf cache-conf cache-ssl-conf cache-manifest proxy-conf proxy-base-conf proxy-ssl-conf proxy-balancer-conf proxy-member-conf proxy-ssl-member-conf proxy-ssl-nossl-member-conf alt-host-conf mass-host-conf mass-host-ssl-conf httpd-tunnel-ssl-conf tunnel-ssl-conf httpd-worker-conf httpd-event-conf httpd-loglevel-conf minify-html minify-js minify-css
+dist_mod_SCRIPTS = httpd-conf httpd-addr httpd-start httpd-stop httpd-restart ssl-ca-conf ssl-cert-conf ssl-cert-find httpd-ssl-conf base64-encode basic-auth-conf cert-auth-conf form-auth-conf open-auth-conf passwd-auth-conf group-auth-conf cache-conf cache-ssl-conf cache-manifest proxy-conf proxy-base-conf proxy-ssl-conf proxy-balancer-conf proxy-member-conf proxy-ssl-member-conf proxy-ssl-nossl-member-conf alt-host-conf mass-host-conf mass-host-ssl-conf httpd-tunnel-ssl-conf tunnel-ssl-conf httpd-worker-conf httpd-event-conf httpd-loglevel-conf minify-html minify-js minify-css ssinclude-html
 moddir = $(prefix)/modules/http
 
 curl_test_SOURCES = curl-test.cpp

Copied: tuscany/sca-cpp/trunk/modules/http/ssinclude-html (from r1517414, tuscany/sca-cpp/trunk/modules/js/Makefile.am)
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/http/ssinclude-html?p2=tuscany/sca-cpp/trunk/modules/http/ssinclude-html&p1=tuscany/sca-cpp/trunk/modules/js/Makefile.am&r1=1517414&r2=1517415&rev=1517415&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/js/Makefile.am (original)
+++ tuscany/sca-cpp/trunk/modules/http/ssinclude-html Mon Aug 26 03:04:34 2013
@@ -1,3 +1,5 @@
+#!/bin/sh
+
 #  Licensed to the Apache Software Foundation (ASF) under one
 #  or more contributor license agreements.  See the NOTICE file
 #  distributed with this work for additional information
@@ -15,31 +17,12 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
+# Process server-side includes in an HTML file
+here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
 
-jsfiles = htdocs/util.js htdocs/elemutil.js htdocs/xmlutil.js htdocs/atomutil.js htdocs/jsonutil.js htdocs/scdl.js htdocs/ui.js htdocs/component.js
-
-BUILT_SOURCES = htdocs/all.js
-htdocs/all.js: ${jsfiles}
-	cat $^ >htdocs/all.js
-
-minified = htdocs/all-min.js htdocs/ui-min.css
-
-SUFFIXES = -min.html -min.js -min.css
-.html-min.html:
-	../../modules/http/minify-html $< $@
-
-.js-min.js:
-	../../modules/http/minify-js $< $@
-
-.css-min.css:
-	../../modules/http/minify-css $< $@
-
-CLEANFILES = htdocs/all.js ${minified}
-
-dist_mod_SCRIPTS = js-conf
-moddir = $(prefix)/modules/js
-nobase_dist_mod_DATA = ${minified}
-EXTRA_DIST = ${jsfiles} htdocs/ui.css
+html=`echo "import os; print os.path.realpath('$1')" | python`
+ssihtml=`echo "import os; print os.path.realpath('$2')" | python`
 
-dist_noinst_SCRIPTS = util-test
+cd `dirname ${html}`
+cat ${html} | awk '{ print; } /<!--#include file="[^"]+"/ { match($0, "file=\"[^\"]+\""); system("cat " substr($0, RSTART + 6, RLENGTH - 7)); }' > ${ssihtml}
 

Propchange: tuscany/sca-cpp/trunk/modules/http/ssinclude-html
------------------------------------------------------------------------------
    svn:executable = *

Modified: tuscany/sca-cpp/trunk/modules/js/Makefile.am
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/js/Makefile.am?rev=1517415&r1=1517414&r2=1517415&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/js/Makefile.am (original)
+++ tuscany/sca-cpp/trunk/modules/js/Makefile.am Mon Aug 26 03:04:34 2013
@@ -18,11 +18,14 @@
 
 jsfiles = htdocs/util.js htdocs/elemutil.js htdocs/xmlutil.js htdocs/atomutil.js htdocs/jsonutil.js htdocs/scdl.js htdocs/ui.js htdocs/component.js
 
-BUILT_SOURCES = htdocs/all.js
+BUILT_SOURCES = htdocs/base.js htdocs/all.js
+htdocs/base.js: htdocs/util.js htdocs/ui.js
+	cat $^ >htdocs/base.js
+
 htdocs/all.js: ${jsfiles}
 	cat $^ >htdocs/all.js
 
-minified = htdocs/all-min.js htdocs/ui-min.css
+minified = htdocs/all-min.js htdocs/base-min.js htdocs/ui-min.css
 
 SUFFIXES = -min.html -min.js -min.css
 .html-min.html:
@@ -34,9 +37,9 @@ SUFFIXES = -min.html -min.js -min.css
 .css-min.css:
 	../../modules/http/minify-css $< $@
 
-CLEANFILES = htdocs/all.js ${minified}
+CLEANFILES = htdocs/base.js htdocs/all.js ${minified}
 
-dist_mod_SCRIPTS = js-conf
+dist_mod_SCRIPTS = js-conf js-extract
 moddir = $(prefix)/modules/js
 nobase_dist_mod_DATA = ${minified}
 EXTRA_DIST = ${jsfiles} htdocs/ui.css

Modified: tuscany/sca-cpp/trunk/modules/js/htdocs/component.js
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/js/htdocs/component.js?rev=1517415&r1=1517414&r2=1517415&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/js/htdocs/component.js (original)
+++ tuscany/sca-cpp/trunk/modules/js/htdocs/component.js Mon Aug 26 03:04:34 2013
@@ -15,16 +15,6 @@
  * KIND, either express or implied.  See the License for the
  * specific language governing permissions and limitations
  * under the License.    
- *
- * The JSON-RPC client code is based on Jan-Klaas' JavaScript
- * o lait library (jsolait).
- *
- * $Id: jsonrpc.js,v 1.36.2.3 2006/03/08 15:09:37 mclark Exp $
- *
- * Copyright (c) 2003-2004 Jan-Klaas Kollhof
- * Copyright (c) 2005 Michael Clark, Metaparadigm Pte Ltd
- *
- * Licensed under the Apache License, Version 2.0 (the "License").
  */
 
 /**
@@ -34,72 +24,6 @@
 var JSONClient = {};
 
 /**
- * Escape a character.
- */
-JSONClient.escapeJSONChar = function(c) {
-    if(c == "\"" || c == "\\") return "\\" + c;
-    if(c == "\b") return "\\b";
-    if(c == "\f") return "\\f";
-    if(c == "\n") return "\\n";
-    if(c == "\r") return "\\r";
-    if(c == "\t") return "\\t";
-    var hex = c.charCodeAt(0).toString(16);
-    if(hex.length == 1) return "\\u000" + hex;
-    if(hex.length == 2) return "\\u00" + hex;
-    if(hex.length == 3) return "\\u0" + hex;
-    return "\\u" + hex;
-};
-
-/**
- * Encode a string into JSON format.
- */
-JSONClient.escapeJSONString = function(s) {
-    // The following should suffice but Safari's regex is broken (doesn't support callback substitutions)
-    // return "\"" + s.replace(/([^\u0020-\u007f]|[\\\"])/g, JSONClient.escapeJSONChar) + "\"";
-
-    // Rather inefficient way to do it
-    var parts = s.split("");
-    for(var i = 0; i < parts.length; i++) {
-        var c = parts[i];
-        if(c == '"' || c == '\\' || c.charCodeAt(0) < 32 || c.charCodeAt(0) >= 128)
-            parts[i] = JSONClient.escapeJSONChar(parts[i]);
-    }
-    return "\"" + parts.join("") + "\"";
-};
-
-/**
- * Marshall objects to JSON format.
- */
-JSONClient.toJSON = function(o) {
-    if(o == null)
-        return "null";
-    if(o.constructor == String)
-        return JSONClient.escapeJSONString(o);
-    if(o.constructor == Number)
-        return o.toString();
-    if(o.constructor == Boolean)
-        return o.toString();
-    if(o.constructor == Date)
-        return '{javaClass: "java.util.Date", time: ' + o.valueOf() +'}';
-    if(o.constructor == Array) {
-        var v = [];
-        for(var i = 0; i < o.length; i++)
-            v.push(JSONClient.toJSON(o[i]));
-        return "[" + v.join(", ") + "]";
-    }
-    var v = [];
-    for(attr in o) {
-        if(o[attr] == null)
-            v.push("\"" + attr + "\": null");
-        else if(typeof o[attr] == "function")
-            ; // Skip
-        else
-            v.push(JSONClient.escapeJSONString(attr) + ": " + JSONClient.toJSON(o[attr]));
-    }
-    return "{" + v.join(", ") + "}";
-};
-
-/**
  * Construct an HTTPBindingClient.
  */
 function HTTPBindingClient(name, uri, domain) {
@@ -114,6 +38,17 @@ function HTTPBindingClient(name, uri, do
  */
 
 /**
+ * Run a function asynchronously.
+ */
+HTTPBindingClient.delaying = false;
+HTTPBindingClient.delay = function(f) {
+    if (HTTPBindingClient.delaying)
+        return window.setTimeout(f, 0);
+    else
+        return f();
+};
+
+/**
  * Generate client proxy apply method.
  */
 HTTPBindingClient.prototype.createApplyMethod = function() {
@@ -121,10 +56,10 @@ HTTPBindingClient.prototype.createApplyM
         var methodName = arguments[0];
         var args = [];
         for(var i = 1; i < arguments.length; i++)
-            args.push(arguments[i]);
+            args[args.length] = arguments[i];
 
-        var cb = null;
-        if(typeof args[args.length - 1] == "function")
+        var cb;
+        if(typeof args[args.length - 1] == 'function')
             cb = args.pop();
 
         var req = HTTPBindingClient.makeJSONRequest(methodName, args, cb);
@@ -151,7 +86,7 @@ HTTPBindingClient.makeJSONRequest = func
     obj.id = req.id;
     obj.method = methodName;
     obj.params = args;
-    req.data = JSONClient.toJSON(obj);
+    req.data = JSON.stringify(obj);
     return req;
 };
 
@@ -159,62 +94,39 @@ HTTPBindingClient.makeJSONRequest = func
  * Return the JSON result from an XMLHttpRequest.
  */
 HTTPBindingClient.jsonResult = function(http) {
-    // Get the charset
-    function httpCharset(http) {
-        try {
-            var contentType = http.getResponseHeader("Content-Type");
-            var parts = contentType.split(/\s*;\s*/);
-            for(var i = 0; i < parts.length; i++) {
-                if(parts[i].substring(0, 8) == "charset=")
-                    return parts[i].substring(8, parts[i].length);
-            }
-        } catch (e) {}
-        return "UTF-8";
-    }
-    if(!HTTPBindingClient.charset)
-        HTTPBindingClient.charset = httpCharset(http);
-
-    // Unmarshall the JSON response
-    var obj;
-    eval("obj = " + http.responseText);
-    if(obj.error)
-        throw new HTTPBindingClient.Exception(obj.error.code, obj.error.msg);
-    var res = obj.result;
-    return res;
+    var obj = JSON.parse(http.responseText);
+    return obj.result;
 };
 
 /**
  * Schedule async requests, limiting the number of concurrent running requests.
  */
-HTTPBindingClient.queuedRequests = new Array();
-HTTPBindingClient.runningRequests = new Array();
-HTTPBindingClient.concurrentRequests = 2;
+HTTPBindingClient.queuedRequests = [];
+HTTPBindingClient.runningRequests = [];
+HTTPBindingClient.concurrentRequests = 4;
 
 HTTPBindingClient.scheduleAsyncRequest = function(f, cancelable) {
-    //debug('schedule async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length);
+    debug('component schedule async request', 'running', HTTPBindingClient.runningRequests.length, 'queued', HTTPBindingClient.queuedRequests.length);
 
     // Queue the request function
     var req = new Object();
     req.f = f;
     req.cancelable = cancelable;
     req.canceled = false;
-    HTTPBindingClient.queuedRequests.push(req);
+    HTTPBindingClient.queuedRequests[HTTPBindingClient.queuedRequests.length] = req;
 
     // Execute any requests in the queue
-    setTimeout(function() {
-        HTTPBindingClient.runAsyncRequests(true);
-    }, 0);
-    return true;
+    return HTTPBindingClient.runAsyncRequests();
 };
 
 HTTPBindingClient.forgetRequest = function(req) {
-    req.http = null;
+    req.http = undefined;
 
     // Remove a request from the list of running requests
-    for (i in HTTPBindingClient.runningRequests) {
+    for (var i in HTTPBindingClient.runningRequests) {
         if (HTTPBindingClient.runningRequests[i] == req) {
             HTTPBindingClient.runningRequests.splice(i, 1);
-            //debug('forget async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length);
+            debug('forget async request', 'running', HTTPBindingClient.runningRequests.length, 'queued', HTTPBindingClient.queuedRequests.length);
             return true;
         }
     }
@@ -222,33 +134,32 @@ HTTPBindingClient.forgetRequest = functi
 };
 
 HTTPBindingClient.cancelRequests = function() {
-    //debug('cancel async requests, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length);
+    debug('component cancel async requests', 'running', HTTPBindingClient.runningRequests.length, 'queued', HTTPBindingClient.queuedRequests.length);
 
     // Cancel any cancelable in flight HTTP requests
-    for (i in HTTPBindingClient.queuedRequests) {
+    for (var i in HTTPBindingClient.queuedRequests) {
         var req = HTTPBindingClient.queuedRequests[i];
         if (req.cancelable)
             req.canceled = true;
     }
-    for (i in HTTPBindingClient.runningRequests) {
+    for (var i in HTTPBindingClient.runningRequests) {
         var req = HTTPBindingClient.runningRequests[i];
         if (req.cancelable) {
             req.canceled = true;
             if (req.http) {
+                req.http.aborted = true;
                 req.http.abort();
-                req.http = null;
-                //debug('abort async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length);
+                req.http = undefined;
+                debug('component abort async request', 'running', HTTPBindingClient.runningRequests.length, 'queued', HTTPBindingClient.queuedRequests.length);
             }
         }
     }
 
     // Flush the queue
-    setTimeout(function() {
-        HTTPBindingClient.runAsyncRequests(true);
-    }, 0);
+    return HTTPBindingClient.runAsyncRequests();
 }
 
-HTTPBindingClient.runAsyncRequests = function(fromui) {
+HTTPBindingClient.runAsyncRequests = function() {
     // Stop now if we already have enough requests running or there's no request in the queue
     if(HTTPBindingClient.runningRequests.length >= HTTPBindingClient.concurrentRequests || HTTPBindingClient.queuedRequests.length == 0)
         return true;
@@ -256,41 +167,38 @@ HTTPBindingClient.runAsyncRequests = fun
     // Run the first request in the queue
     var req = HTTPBindingClient.queuedRequests.shift();
     if (!req.canceled) {
-        HTTPBindingClient.runningRequests.push(req);
-        //debug('run async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length);
-        var runAsyncRequest = function() {
-            if (req.canceled) {
-                HTTPBindingClient.forgetRequest(req);
-                //debug('canceled timed async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length);
-                return false;
-            }
+        HTTPBindingClient.runningRequests[HTTPBindingClient.runningRequests.length] = req;
+        debug('component run async request', 'running', HTTPBindingClient.runningRequests.length, 'queued', HTTPBindingClient.queuedRequests.length);
+        if (req.canceled) {
+            HTTPBindingClient.forgetRequest(req);
+            debug('component canceled timed async request', 'running', HTTPBindingClient.runningRequests.length, 'queued', HTTPBindingClient.queuedRequests.length);
+            return false;
+        }
+        HTTPBindingClient.delay(function asyncRequest() {
             try {
                 req.http = new XMLHttpRequest();
+                req.http.aborted = false;
                 return req.f(req.http, function asyncRequestDone() {
                     // Execute any requests left in the queue
                     HTTPBindingClient.forgetRequest(req);
-                    //debug('done async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length);
-                    HTTPBindingClient.runAsyncRequests(false);
+                    debug('component done async request', 'running', HTTPBindingClient.runningRequests.length, 'queued', HTTPBindingClient.queuedRequests.length);
+                    HTTPBindingClient.runAsyncRequests();
                     return true;
                 });
             } catch(e) {
                 // Execute any requests left in the queue
                 HTTPBindingClient.forgetRequest(req);
-                //debug('err async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length);
-                HTTPBindingClient.runAsyncRequests(false);
+                debug('component async request error', 'running', HTTPBindingClient.runningRequests.length, 'queued', HTTPBindingClient.queuedRequests.length, 'error', e);
+                HTTPBindingClient.runAsyncRequests();
             }
             return false;
-        };
-        if (false)
-            setTimeout(runAsyncRequest, 0);
-        else
-            runAsyncRequest();
+        });
     } else {
-        //debug('canceled queued async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length);
+        debug('component canceled queued async request', 'running', HTTPBindingClient.runningRequests.length, 'queued', HTTPBindingClient.queuedRequests.length);
     }
 
     // Execute any requests left in the queue
-    HTTPBindingClient.runAsyncRequests(fromui);
+    HTTPBindingClient.runAsyncRequests();
 };
 
 /**
@@ -298,24 +206,24 @@ HTTPBindingClient.runAsyncRequests = fun
  */
 HTTPBindingClient.getCacheItem = function(k) {
     var ls = lstorage || localStorage;
-    return ls.getItem('cache.d.' + k);
+    return ls.getItem('dc.d.' + k);
 };
 
 /**
  * Set a cache item in local storage.
  */
 HTTPBindingClient.setCacheItem = function(k, v) {
+    if (v && v.length > 65535)
+        return HTTPBindingClient.removeCacheItem(k);
     HTTPBindingClient.collectCacheItems();
     var ls = lstorage || localStorage;
-    try {
-        var s = ls.getItem('cache.size');
-        var size = parseInt(s);
-        var ov = ls.getItem('cache.d.' + k);
-        var nsize = size - (ov != null? ov.length : 0) + (v != null? v.length : 0);
-        if (nsize != size)
-            ls.setItem('cache.size', nsize.toString());
-    } catch(e) {}
-    return ls.setItem('cache.d.' + k, v);
+    var s = ls.getItem('dc.size');
+    var size = s? parseInt(s) : 0;
+    var ov = ls.getItem('dc.d.' + k);
+    var nsize = size - (ov? ov.length : 0) + (v? v.length : 0);
+    if (nsize != size)
+        ls.setItem('dc.size', nsize.toString());
+    return ls.setItem('dc.d.' + k, v);
 };
 
 /**
@@ -323,16 +231,14 @@ HTTPBindingClient.setCacheItem = functio
 */
 HTTPBindingClient.removeCacheItem = function(k) {
     var ls = lstorage || localStorage;
-    try {
-        var s = ls.getItem('cache.size');
-        var size = parseInt(s);
-        var ov = ls.getItem('cache.d' + k);
-        if (ov != null) {
-            var nsize = size - ov.length;
-            ls.setItem('cache.size', nsize.toString());
-        }
-    } catch(e) {}
-    return ls.removeItem('cache.d.' + k);
+    var s = ls.getItem('dc.size');
+    var size = s? parseInt(s) : 0;
+    var ov = ls.getItem('dc.d.' + k);
+    if (ov) {
+        var nsize = size - ov.length;
+        ls.setItem('dc.size', nsize.toString());
+    }
+    return ls.removeItem('dc.d.' + k);
 };
 
 /**
@@ -343,61 +249,59 @@ HTTPBindingClient.collectCacheSize = /* 
 HTTPBindingClient.collectCacheItems = function() {
     var ls = window.lstorage || localStorage;
     var nkeys = window.lstorage? function() { return ls.length(); } : function() { return ls.length; };
-    try {
-        // Get the current cache size
-        var size = 0;
-        var s = ls.getItem('cache.size');
-        if(s == null) {
-            // Calculate and store initial cache size
-            //debug('calculating cache size');
-            var n = nkeys();
-            for(var i = 0; i < n; i++) {
-                var k = ls.key(i);
-                if(k == null || k.substr(0, 8) != 'cache.d.')
-                    continue;
-                var v = ls.getItem(k);
-                if(v == null)
-                    continue;
-                size += v.length;
-            }
-            ls.setItem('cache.size', size.toString());
-        } else
-            size = parseInt(s);
-
-        // Nothing to do if it's below the max size
-        //debug('cache.size', size);
-        if (size <= HTTPBindingClient.maxCacheSize)
-            return false;
 
-        // Collect random cache entries until we reach our min size
-        //debug('collecting cache items');
-        var keys = new Array();
+    // Get the current cache size
+    var size = 0;
+    var s = ls.getItem('dc.size');
+    if(!s) {
+        // Calculate and store initial cache size
+        debug('component calculating cache size');
         var n = nkeys();
         for(var i = 0; i < n; i++) {
             var k = ls.key(i);
-            if(k == null || k.substr(0, 8) != 'cache.d.')
+            if(!k || k.substr(0, 5) != 'dc.d.')
                 continue;
-            keys.push(k);
-        }
-        while (keys.length != 0 && size >= HTTPBindingClient.collectCacheSize) {
-            var r = Math.floor(keys.length * Math.random());
-            if (r == keys.length)
-                continue;
-            var k = keys[r];
             var v = ls.getItem(k);
-            //debug('collect cache item', k);
-            ls.removeItem(k);
-            keys.splice(r, 1);
-            if (v != null)
-                size = size - v.length;
+            if(!v)
+                continue;
+            size += v.length;
         }
-
-        // Store the new cache size
-        //debug('updated cache.size', size);
-        ls.setItem('cache.size', size.toString());
-        return true;
-    } catch(e) {}
-    return false;
+        ls.setItem('dc.size', size.toString());
+    } else
+        size = parseInt(s);
+
+    // Nothing to do if it's below the max size
+    debug('component cache size', size);
+    if (size <= HTTPBindingClient.maxCacheSize)
+        return false;
+
+    // Collect random cache entries until we reach our min size
+    debug('component collecting cache items');
+    var keys = [];
+    var n = nkeys();
+    for(var i = 0; i < n; i++) {
+        var k = ls.key(i);
+        if(!k || k.substr(0, 5) != 'dc.d.')
+            continue;
+        keys[keys.length] = k;
+    }
+    while (keys.length != 0 && size >= HTTPBindingClient.collectCacheSize) {
+        var r = Math.floor(keys.length * Math.random());
+        if (r == keys.length)
+            continue;
+        var k = keys[r];
+        var v = ls.getItem(k);
+        debug('component collect cache item', k);
+        ls.removeItem(k);
+        keys.splice(r, 1);
+        if (v)
+            size = size - v.length;
+    }
+
+    // Store the new cache size
+    debug('component updated cache size', size);
+    ls.setItem('dc.size', size.toString());
+    return true;
 };
 
 /**
@@ -410,28 +314,19 @@ HTTPBindingClient.prototype.jsonApply = 
     if(hascb) {
         var u = this.uri;
         return HTTPBindingClient.scheduleAsyncRequest(function jsonApplyRequest(http, done) {
-            http.open("POST", u, true);
-            http.setRequestHeader("Accept", "*/*");
-            http.setRequestHeader("Content-Type", "application/json-rpc");
+            http.open('POST', u, true);
+            http.setRequestHeader('Accept', '*/*');
+            http.setRequestHeader('Content-Type', 'application/json-rpc');
+            http.setRequestHeader('X-Cache-Control', 'no-cache');
             http.onreadystatechange = function() {
                 if(http.readyState == 4) {
                     // Pass the result or exception
                     if(http.status == 200) {
-                        var res = null;
-                        try {
-                            res = HTTPBindingClient.jsonResult(http);
-                            try {
-                                req.cb(res);
-                            } catch(cbe) {}
-                        } catch(e) {
-                            try {
-                                req.cb(null, e);
-                            } catch(cbe) {}
-                        }
-                    } else {
-                        try {
-                            req.cb(null, HTTPBindingClient.Exception(http.status, http.statusText));
-                        } catch(cbe) {}
+                        var res = HTTPBindingClient.jsonResult(http);
+                        req.cb(res);
+                    } if(!http.aborted) {
+                        error('jsonApply error', 'status', http.status, http.statusText);
+                        req.cb(undefined, new Error('' + http.status + ' ' + http.statusText));
                     }
                     return done();
                 }
@@ -445,13 +340,15 @@ HTTPBindingClient.prototype.jsonApply = 
 
     // Call synchronously and return the result or exception
     var http = new XMLHttpRequest();
-    http.open("POST", this.uri, false);
-    http.setRequestHeader("Accept", "*/*");
-    http.setRequestHeader("Content-Type", "application/json-rpc");
+    http.open('POST', this.uri, false);
+    http.setRequestHeader('Accept', '*/*');
+    http.setRequestHeader('Content-Type', 'application/json-rpc');
+    http.setRequestHeader('X-Cache-Control', 'no-cache');
     http.send(req.data);
     if(http.status == 200)
         return HTTPBindingClient.jsonResult(http);
-    throw new HTTPBindingClient.Exception(http.status, http.statusText);
+    error('jsonApply error', 'status', http.status, http.statusText);
+    throw new Error('' + http.status + ' ' + http.statusText);
 };
 
 
@@ -463,69 +360,64 @@ HTTPBindingClient.prototype.get = functi
     var hascb = cb? true : false;
 
     // Get from local storage first
-    var item = null;
+    var item;
     if(mode != 'remote') {
         item = HTTPBindingClient.getCacheItem(u);
-        if(item != null && item != '') {
+        if(item && item != '') {
             if(!hascb)
                 return item;
 
             // Pass local result to callback
-            setTimeout(function() {
-                cb(item);
-            }, 0);
+            cb(item);
         }
     }
 
     // Call asynchronously with a callback
     if(hascb) {
         return HTTPBindingClient.scheduleAsyncRequest(function getRequest(http, done) {
-            http.open("GET", u, true);
-            http.setRequestHeader("Accept", "*/*");
+            http.open('GET', u, true);
+            http.setRequestHeader('Accept', '*/*');
+            http.setRequestHeader('X-Cache-Control', 'no-cache');
             http.onreadystatechange = function() {
-                //debug('readystate', http.readyState, 'status', http.status, 'headers', http.getAllResponseHeaders());
                 if(http.readyState == 4) {
+
                     // Pass result if different from local result
+                    //debug('readystate', http.readyState, 'status', http.status, 'headers', http.getAllResponseHeaders());
                     if(http.status == 200) {
-                        var xl = http.getResponseHeader("X-Login");
-                        var ct = http.getResponseHeader("Content-Type");
-                        if(xl != null && xl != '' && ct != null && ct.indexOf('text/html') == 0) {
-                            // Detect redirect to a login page
-                            try {
-                                var le = new HTTPBindingClient.Exception(403, 'X-Login');
-                                if(window.onloginredirect)
-                                    window.onloginredirect(le);
-                                cb(null, le);
-                                return done();
-                            } catch(cbe) {}
+                        var ct = http.getResponseHeader('Content-Type');
+                        if(http.responseText == '' || !ct || ct == '') {
 
-                        }
-                        if(http.responseText == '' || ct == null || ct == '') {
                             // Report empty response
-                            try {
-                                cb(null, new HTTPBindingClient.Exception(403, 'No-Content'));
-                                return done();
-                            } catch(cbe) {}
-
-                        } else {
-                            if(item == null || http.responseText != item) {
-                                // Store retrieved entry in local storage
-                                if(http.responseText != null)
-                                    HTTPBindingClient.setCacheItem(u, http.responseText);
-                                try {
-                                    cb(http.responseText);
-                                    return done();
-                                } catch(cbe) {}
-                            }
+                            error('get received empty response', 'url', u);
+                            cb(undefined, new Error('500 No-Content'));
+                            return done();
+
+                        } else if(!item || http.responseText != item) {
+
+                            // Store retrieved entry in local storage
+                            //debug('received response', 'url', u, 'response', http.responseText);
+                            if(http.responseText != null)
+                                HTTPBindingClient.setCacheItem(u, http.responseText);
+                            cb(http.responseText);
+                            return done();
                         }
-                    }
-                    else {
+                    } else if (http.status == 403) {
+
+                        // Redirect to login page
+                        error('get received 403 response', 'url', u);
+                        var le = new Error('' + http.status + ' ' + http.statusText);
+                        if(window.onloginredirect)
+                            window.onloginredirect(le);
+                        cb(undefined, le);
+                        return done();
+
+                    } else if(!http.aborted) {
+
                         // Pass exception if we didn't have a local result
-                        if(item == null) {
-                            try {
-                                cb(null, new HTTPBindingClient.Exception(http.status, http.statusText));
-                                return done();
-                            } catch(cbe) {}
+                        error('get received error', 'url', u, 'status', http.status, http.statusText);
+                        if(!item) {
+                            cb(undefined, new Error('' + http.status + ' ' + http.statusText));
+                            return done();
                         }
                     }
                     return done();
@@ -540,28 +432,29 @@ HTTPBindingClient.prototype.get = functi
 
     // Call synchronously and return the result or exception
     var http = new XMLHttpRequest();
-    http.open("GET", u, false);
-    http.setRequestHeader("Accept", "*/*");
+    http.open('GET', u, false);
+    http.setRequestHeader('Accept', '*/*');
+    http.setRequestHeader('X-Cache-Control', 'no-cache');
     http.send(null);
     if(http.status == 200) {
-        var xl = http.getResponseHeader("X-Login");
-        var ct = http.getResponseHeader("Content-Type");
-        if(xl != null && xl != '' && ct != null && ct.indexOf('text/html') == 0) {
-            // Detect redirect to a login page
-            var le = new HTTPBindingClient.Exception(403, 'X-Login');
-            if(window.onloginredirect)
-                window.onloginredirect(le);
-            throw le;
-
-        }
-        var ct = http.getResponseHeader("Content-Type");
-        if(http.responseText == '' || ct == null || ct == '') {
+        var ct = http.getResponseHeader('Content-Type');
+        if(http.responseText == '' || !ct || ct == '') {
             // Report empty response
-            throw new HTTPBindingClient.Exception(403, 'No-Content');
+            error('get received empty response', 'url', u);
+            throw new Error('500 No Content');
         }
         return http.responseText;
     }
-    throw new HTTPBindingClient.Exception(http.status, http.statusText);
+    if(http.status == 403) {
+        // Redirect to login page
+        error('get received 403 response', 'url', u);
+        var le = new Error('' + http.status + ' ' + http.statusText);
+        if(window.onloginredirect)
+            window.onloginredirect(le);
+        throw le;
+    }
+    error('get received error', 'url', u, 'status', http.status, http.statusText);
+    throw new Error('' + http.status + ' ' + http.statusText);
 };
 
 /**
@@ -574,22 +467,20 @@ HTTPBindingClient.prototype.post = funct
     if(hascb) {
         var u = this.uri;
         return HTTPBindingClient.scheduleAsyncRequest(function postRequest(http, done) {
-            http.open("POST", u, true);
-            http.setRequestHeader("Accept", "*/*");
-            http.setRequestHeader("Content-Type", "application/atom+xml");
+            http.open('POST', u, true);
+            http.setRequestHeader('Accept', '*/*');
+            http.setRequestHeader('Content-Type', 'application/atom+xml');
+            http.setRequestHeader('X-Cache-Control', 'no-cache');
             http.onreadystatechange = function() {
                 if(http.readyState == 4) {
                     if(http.status == 201) {
+
                         // Successful result
-                        try {
-                            cb(http.responseText);
-                        } catch(cbe) {}
+                        cb(http.responseText);
                     }
                     else {
                         // Report status code as an exception
-                        try {
-                            cb(null, new HTTPBindingClient.Exception(http.status, http.statusText));
-                        } catch(cbe) {}
+                        cb(undefined, new Error('' + http.status + ' ' + http.statusText));
                     }
                     return done();
                 }
@@ -603,15 +494,16 @@ HTTPBindingClient.prototype.post = funct
     // Call synchronously
     var http = new XMLHttpRequest();
     var hascb = cb? true : false;
-    http.open("POST", this.uri, false);
-    http.setRequestHeader("Accept", "*/*");
-    http.setRequestHeader("Content-Type", "application/atom+xml");
+    http.open('POST', this.uri, false);
+    http.setRequestHeader('Accept', '*/*');
+    http.setRequestHeader('Content-Type', 'application/atom+xml');
+    http.setRequestHeader('X-Cache-Control', 'no-cache');
     http.send(entry);
     if(http.status == 201)
         return http.responseText;
 
     // Return status code as an exception
-    throw new HTTPBindingClient.Exception(http.status, http.statusText);
+    throw new Error('' + http.status + ' ' + http.statusText);
 };
 
 /**
@@ -622,7 +514,7 @@ HTTPBindingClient.prototype.put = functi
     var hascb = cb? true : false;
 
     // Update local storage
-    var oentry = null;
+    var oentry;
     if(mode != 'remote') {
         oentry = HTTPBindingClient.getCacheItem(u);
         HTTPBindingClient.setCacheItem(u, entry);
@@ -631,33 +523,31 @@ HTTPBindingClient.prototype.put = functi
     // Call asynchronously with a callback
     if(hascb) {
         return HTTPBindingClient.scheduleAsyncRequest(function putRequest(http, done) {
-            http.open("PUT", u, true);
-            http.setRequestHeader("Accept", "*/*");
-            http.setRequestHeader("Content-Type", "application/atom+xml");
+            http.open('PUT', u, true);
+            http.setRequestHeader('Accept', '*/*');
+            http.setRequestHeader('Content-Type', 'application/atom+xml');
+            http.setRequestHeader('X-Cache-Control', 'no-cache');
             http.onreadystatechange = function() {
                 if(http.readyState == 4) {
                     if(http.status == 200) {
+
                         // Successful result
-                        try {
-                            cb();
-                        } catch(cbe) {}
+                        cb();
+
                     } else {
                         if(http.status == 404) {
+
                             // Undo local storage update
                             if(mode != 'remote') {
-                                try {
-                                    if(oentry != null)
-                                        HTTPBindingClient.setCacheItem(u, oentry);
-                                    else
-                                        HTTPBindingClient.removeCacheItem(u);
-                                } catch(e) {}
+                                if(oentry)
+                                    HTTPBindingClient.setCacheItem(u, oentry);
+                                else
+                                    HTTPBindingClient.removeCacheItem(u);
                             }
                         }
 
                         // Report status code as an exception
-                        try {
-                            cb(new HTTPBindingClient.Exception(http.status, http.statusText));
-                        } catch(cbe) {}
+                        cb(new Error('' + http.status + ' ' + http.statusText));
                     }
                     return done();
                 }
@@ -671,26 +561,25 @@ HTTPBindingClient.prototype.put = functi
 
     // Call synchronously
     var http = new XMLHttpRequest();
-    http.open("PUT", u, false);
-    http.setRequestHeader("Accept", "*/*");
-    http.setRequestHeader("Content-Type", "application/atom+xml");
+    http.open('PUT', u, false);
+    http.setRequestHeader('Accept', '*/*');
+    http.setRequestHeader('Content-Type', 'application/atom+xml');
+    http.setRequestHeader('X-Cache-Control', 'no-cache');
     http.send(entry);
     if(http.status == 200)
         return true;
     if(http.status == 404) {
         // Undo local storage update
         if(mode != 'remote') {
-            try {
-                if(oentry != null)
-                    HTTPBindingClient.setCacheItem(u, oentry);
-                else
-                    HTTPBindingClient.removeCacheItem(u);
-            } catch(e) {}
+            if(oentry)
+                HTTPBindingClient.setCacheItem(u, oentry);
+            else
+                HTTPBindingClient.removeCacheItem(u);
         }
     }
 
     // Return status code as an exception
-    throw new HTTPBindingClient.Exception(http.status, http.statusText);
+    throw new Error('' + http.status + ' ' + http.statusText);
 };
 
 /**
@@ -708,21 +597,19 @@ HTTPBindingClient.prototype.del = functi
     // Call asynchronously with a callback
     if(hascb) {
         return HTTPBindingClient.scheduleAsyncRequest(function delRequest(http, done) {
-            http.open("DELETE", u, true);        
-            http.setRequestHeader("Accept", "*/*");
+            http.open('DELETE', u, true);        
+            http.setRequestHeader('Accept', '*/*');
+            http.setRequestHeader('X-Cache-Control', 'no-cache');
             http.onreadystatechange = function() {
                 if(http.readyState == 4) {
                     if(http.status == 200) {
+
                         // Successful result
-                        try {
-                            cb();
-                        } catch(cbe) {}
+                        cb();
                     }
                     else {
                         // Report status code as an exception
-                        try {
-                            cb(new HTTPBindingClient.Exception(http.status, http.statusText));
-                        } catch(cbe) {}
+                        cb(new Error('' + http.status + ' ' + http.statusText));
                     }
                     return done();
                 }
@@ -736,29 +623,15 @@ HTTPBindingClient.prototype.del = functi
 
     // Call synchronously
     var http = new XMLHttpRequest();
-    http.open("DELETE", u, false);        
-    http.setRequestHeader("Accept", "*/*");
+    http.open('DELETE', u, false);        
+    http.setRequestHeader('Accept', '*/*');
+    http.setRequestHeader('X-Cache-Control', 'no-cache');
     http.send(null);
     if(http.status == 200)
         return true;
 
     // Report status code as an exception
-    throw new HTTPBindingClient.Exception(http.status, http.statusText);
-};
-
-/**
- * HTTPBindingClient exceptions.
- */
-HTTPBindingClient.Exception = function(code, message) {
-    this.name = "HTTPBindingClientException";
-    this.code = code;
-    this.message = message;
-};
-
-HTTPBindingClient.Exception.prototype = new Error();
-
-HTTPBindingClient.Exception.prototype.toString = function() {
-    return this.name + ": " + this.message;
+    throw new Error('' + http.status + ' ' + http.statusText);
 };
 
 /**
@@ -770,7 +643,7 @@ var sca = {};
 /**
  * Return an HTTP client proxy.
  */
-sca.httpclient = function(name, uri, domain) {
+sca.httpClient = function(name, uri, domain) {
     return new HTTPBindingClient(name, uri, domain);
 };
 
@@ -798,15 +671,15 @@ sca.reference = function(comp, rname) {
 sca.defun = function(ref) {
     function defapply(name) {
         return function() {
-            var args = new Array();
+            var args = [];
             args[0] = name;
-            for(i = 0, n = arguments.length; i < n; i++)
+            for(var i = 0; i < arguments.length; i++)
                 args[i + 1] = arguments[i];
             return this.apply.apply(this, args);
         };
     }
 
-    for(f = 1; f < arguments.length; f++) {
+    for(var f = 1; f < arguments.length; f++) {
         var fn = arguments[f];
         ref[fn]= defapply(fn);
     }

Modified: tuscany/sca-cpp/trunk/modules/js/htdocs/jsonutil.js
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/js/htdocs/jsonutil.js?rev=1517415&r1=1517414&r2=1517415&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/js/htdocs/jsonutil.js (original)
+++ tuscany/sca-cpp/trunk/modules/js/htdocs/jsonutil.js Mon Aug 26 03:04:34 2013
@@ -63,12 +63,11 @@ json.jsPropertiesToValues = function(pro
     var v = json.jsValToValue(jsv);
 
     if (typeof p == 'string') {
-        var n = '' + p;
-        if (n.slice(0, 1) == '@')
-            return json.jsPropertiesToValues(cons(mklist(attribute, "'" + n.slice(1), v), propertiesSoFar), o, cdr(i));
+        if (p[0] == '@')
+            return json.jsPropertiesToValues(cons(mklist(attribute, "'" + p.substring(1), v), propertiesSoFar), o, cdr(i));
         if (isList(v) && !json.isJSArray(v))
-            return json.jsPropertiesToValues(cons(cons(element, cons("'" + n, v)), propertiesSoFar), o, cdr(i));
-        return json.jsPropertiesToValues(cons(mklist(element, "'" + n, v), propertiesSoFar), o, cdr(i));
+            return json.jsPropertiesToValues(cons(cons(element, cons("'" + p, v)), propertiesSoFar), o, cdr(i));
+        return json.jsPropertiesToValues(cons(mklist(element, "'" + p, v), propertiesSoFar), o, cdr(i));
     }
     return json.jsPropertiesToValues(cons(v, propertiesSoFar), o, cdr(i));
 };
@@ -80,9 +79,9 @@ json.jsValToValue = function(jsv) {
     if (jsv == null)
         return null;
     if (isList(jsv))
-        return json.jsPropertiesToValues(mklist(), jsv, reverse(range(0, jsv.length)));
+        return json.jsPropertiesToValues(nil, jsv, reverse(seq(0, jsv.length)));
     if (typeof jsv == 'object')
-        return json.jsPropertiesToValues(mklist(), jsv, reverse(properties(jsv)));
+        return json.jsPropertiesToValues(nil, jsv, reverse(properties(jsv)));
     if (typeof jsv == 'string')
         return '' + jsv;
     return jsv;
@@ -94,7 +93,7 @@ json.jsValToValue = function(jsv) {
 json.isJSON = function(l) {
     if (isNull(l))
         return false;
-    var s = car(l).slice(0, 1);
+    var s = car(l)[0];
     return s == "[" || s == "{";
 };
 
@@ -102,10 +101,8 @@ json.isJSON = function(l) {
  * Convert a list of strings representing a JSON document to a list of values.
  */
 json.readJSON = function(l) {
-    var s = writeStrings(l);
-    var obj;
-    eval('obj = { \"val\": ' + s + " }");
-    return json.jsValToValue(obj.val);
+    var v = JSON.parse(writeStrings(l));
+    return json.jsValToValue(v);
 };
 
 /**
@@ -126,7 +123,7 @@ json.valueToJSVal = function(v) {
     if (!isList(v))
         return v;
     if (json.isJSArray(v))
-        return json.valuesToJSElements(range(0, v.length), v, 0);
+        return json.valuesToJSElements(seq(0, v.length), v, 0);
     return json.valuesToJSProperties({}, v);
 };
 
@@ -139,14 +136,14 @@ json.valuesToJSProperties = function(o, 
     var token = car(l);
     if (isTaggedList(token, attribute)) {
         var pv = json.valueToJSVal(attributeValue(token));
-        o['@' + attributeName(token).slice(1)] = pv;
+        o['@' + attributeName(token).substring(1)] = pv;
     } else if (isTaggedList(token, element)) {
         if (elementHasValue(token)) {
             var pv = json.valueToJSVal(elementValue(token));
-            o[elementName(token).slice(1)] = pv;
+            o[elementName(token).substring(1)] = pv;
         } else {
             var child = {};
-            o[elementName(token).slice(1)] = child;
+            o[elementName(token).substring(1)] = child;
             json.valuesToJSProperties(child, elementChildren(token));
         }
     }
@@ -159,11 +156,10 @@ json.valuesToJSProperties = function(o, 
 json.writeJSON = function(l) {
     var jsv;
     if (json.isJSArray(l))
-        jsv = json.valuesToJSElements(range(0, l.length), l, 0);
+        jsv = json.valuesToJSElements(seq(0, l.length), l, 0);
     else
         jsv = json.valuesToJSProperties({}, l);
-    var s = json.toJSON(jsv);
-    return mklist(s);
+    return mklist(JSON.stringify(jsv));
 }
 
 /**
@@ -193,69 +189,3 @@ json.jsonResultValue = function(s) {
     return val;
 };
 
-/**
- * Escape a character.
- */
-json.escapeJSONChar = function(c) {
-    if(c == "\"" || c == "\\") return "\\" + c;
-    if (c == "\b") return "\\b";
-    if (c == "\f") return "\\f";
-    if (c == "\n") return "\\n";
-    if (c == "\r") return "\\r";
-    if (c == "\t") return "\\t";
-    var hex = c.charCodeAt(0).toString(16);
-    if(hex.length == 1) return "\\u000" + hex;
-    if(hex.length == 2) return "\\u00" + hex;
-    if(hex.length == 3) return "\\u0" + hex;
-    return "\\u" + hex;
-};
-
-/**
- * Encode a string into JSON format.
- */
-json.escapeJSONString = function(s) {
-    // The following should suffice but Safari's regex is broken (doesn't support callback substitutions)
-    // return "\"" + s.replace(/([^\u0020-\u007f]|[\\\"])/g, json.escapeJSONChar) + "\"";
-
-    // Rather inefficient way to do it
-    var parts = s.split("");
-    for(var i = 0; i < parts.length; i++) {
-        var c = parts[i];
-        if(c == '"' || c == '\\' || c.charCodeAt(0) < 32 || c.charCodeAt(0) >= 128)
-            parts[i] = json.escapeJSONChar(parts[i]);
-    }
-    return "\"" + parts.join("") + "\"";
-};
-
-/**
- * Marshall objects to JSON format.
- */
-json.toJSON = function(o) {
-    if(o == null)
-        return "null";
-    if(o.constructor == String)
-        return json.escapeJSONString(o);
-    if(o.constructor == Number)
-        return o.toString();
-    if(o.constructor == Boolean)
-        return o.toString();
-    if(o.constructor == Date)
-        return '{javaClass: "java.util.Date", time: ' + o.valueOf() +'}';
-    if(o.constructor == Array) {
-        var v = [];
-        for(var i = 0; i < o.length; i++)
-            v.push(json.toJSON(o[i]));
-        return "[" + v.join(", ") + "]";
-    }
-    var v = [];
-    for(attr in o) {
-        if(o[attr] == null)
-            v.push("\"" + attr + "\": null");
-        else if(typeof o[attr] == "function")
-            ; // Skip
-        else
-            v.push(json.escapeJSONString(attr) + ": " + json.toJSON(o[attr]));
-    }
-    return "{" + v.join(", ") + "}";
-};
-