Revision: 3724
Author: maoziqing
Date: Thu Sep 10 18:33:03 2009
Log: Unbundled sync module loading for Cajita, Valija and CommonJS.


http://code.google.com/p/google-caja/source/detail?r=3724

Added:
 /trunk/src/com/google/caja/commonjs-sandbox.js
 /trunk/tests/com/google/caja/commonJsRecursion.js
 /trunk/tests/com/google/caja/foo/f.js
 /trunk/tests/com/google/caja/foo/staticinc.js
 /trunk/tests/com/google/caja/sum.js
Deleted:
 /trunk/src/com/google/caja/serverjs-sandbox.js
 /trunk/tests/com/google/caja/serverJsRecursion.js
Modified:
 /trunk/build.xml
 /trunk/src/com/google/caja/cajita-module.js
 /trunk/src/com/google/caja/cajita.js
 /trunk/src/com/google/caja/parser/quasiliteral/CajitaRewriter.java
 /trunk/src/com/google/caja/parser/quasiliteral/DefaultValijaRewriter.java
 /trunk/tests/com/google/caja/a.js
 /trunk/tests/com/google/caja/add.js
 /trunk/tests/com/google/caja/c.js
 /trunk/tests/com/google/caja/demos/applet/caja-applet-cajita-golden.js
 /trunk/tests/com/google/caja/demos/applet/caja-applet-valija-golden.js
 /trunk/tests/com/google/caja/foo/b.js
 /trunk/tests/com/google/caja/foo/inc.js
 /trunk/tests/com/google/caja/opensocial/example-rewritten.xml
 /trunk/tests/com/google/caja/parser/quasiliteral/ModuleFormatTest.java
 /trunk/tests/com/google/caja/parser/quasiliteral/c.js
 /trunk/tests/com/google/caja/parser/quasiliteral/foo/b.js
 /trunk/tests/com/google/caja/parser/quasiliteral/testModule.co.js
 /trunk/tests/com/google/caja/parser/quasiliteral/x.js
 /trunk/tests/com/google/caja/plugin/domita_test.html
 /trunk/tests/com/google/caja/plugin/domita_test_untrusted.html
 /trunk/tests/com/google/caja/recursion.js
 /trunk/tests/com/google/caja/service/CajolingServiceTest.java
 /trunk/tests/com/google/caja/x.js

=======================================
--- /dev/null
+++ /trunk/src/com/google/caja/commonjs-sandbox.js      Thu Sep 10 18:33:03 2009
@@ -0,0 +1,84 @@
+// Copyright (C) 2009 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @author [email protected]
+ * @provides commonJsSandboxMaker
+ *
+ */
+var commonJsSandboxMaker = (function(env, valijaMaker) {
+  if (env.Q === undefined) {
+    throw new Error('Include Q in env for serverJS sandbox modules.');
+  }
+  var exportsTable = cajita.newTable();
+
+  function requireMaker(mid) {
+    function theRequire(securedModule) {
+      var theExports = exportsTable.get(securedModule.moduleId);
+      if (theExports !== void 0) {
+        return theExports;
+      } else {
+        var require = requireMaker(securedModule.moduleId);
+        var exports = {};
+        exportsTable.set(newMid, exports);
+
+        var valijaOuters = {env: env, require: require, exports: exports};
+        var cajitaImports = cajita.freeze({$v: valijaMaker(valijaOuters)});
+        securedModule(cajitaImports);
+        return exports;
+      }
+    }
+
+    function async(m) {
+      var Q = env.Q;
+      var r = Q.defer();
+      Q.when(m, function(module) {
+                  var theExports = exportsTable.get(module.moduleId);
+                  if (theExports !== void 0) {
+                    r.resolve(theExports);
+                  } else {
+                       var require = requireMaker(module.moduleId);
+                    var exports = {};
+                    exportsTable.set(module.moduleId, exports);
+
+                    var valijaOuters
+                        = {env: env, require: require, exports: exports};
+                    var cajitaImports
+                        = cajita.freeze({$v: valijaMaker(valijaOuters)});
+                    module(cajitaImports);
+                    r.resolve(exports);
+                  }
+                },
+                function(reason) {
+                  r.resolve(Q.reject(
+                      "Loading module " + src + " failed, " + reason));
+                });
+      return r.promise;
+    }
+
+    theRequire.async = async;
+    theRequire.moduleId = mid;
+    return cajita.freeze(theRequire);
+  }
+
+  function loadModule(securedModulePromise) {
+    return requireMaker('').async(securedModulePromise);
+  }
+
+  return cajita.freeze({ loadModule: loadModule });
+});
+
+if (typeof loader !== 'undefined') {
+  loader.provide(commonJsSandboxMaker);
+}
=======================================
--- /dev/null
+++ /trunk/tests/com/google/caja/commonJsRecursion.js Thu Sep 10 18:33:03 2009
@@ -0,0 +1,29 @@
+// Copyright (C) 2009 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @author [email protected]
+ *
+ * A test file for recursive commonJS-style module loading in Valija
+ */
+exports.isNegative = function(a) {
+  if (a < 0) { return true; } else { return false; }
+};
+exports.isNonNegative = function (a) {
+  var m = require.async('./commonJsRecursion.vo');
+  var r = env.Q.defer();
+  env.Q.when(m, function(module) { r.resolve(!module.isNegative(a)); },
+                function(reason) { r.resolve(env.Q.reject(reason)); });
+  return r.promise;
+};
=======================================
--- /dev/null
+++ /trunk/tests/com/google/caja/foo/f.js       Thu Sep 10 18:33:03 2009
@@ -0,0 +1,21 @@
+// Copyright (C) 2009 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @author [email protected]
+ *
+ * A test file for unbundled synchronous module loading in Cajita
+ */
+var m = load('../c.co');
+m({x: x}) + m({x: y});
=======================================
--- /dev/null
+++ /trunk/tests/com/google/caja/foo/staticinc.js       Thu Sep 10 18:33:03 2009
@@ -0,0 +1,23 @@
+// Copyright (C) 2009 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @author [email protected]
+ *
+ * A test file for unbundled synchronous commonJS-style module loading in Valija
+ */
+env.assertEquals(env.w, 6);
+exports.inc = function(x) {
+  return require('../sum').add(x, 1);
+};
=======================================
--- /dev/null
+++ /trunk/tests/com/google/caja/sum.js Thu Sep 10 18:33:03 2009
@@ -0,0 +1,23 @@
+// Copyright (C) 2009 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @author [email protected]
+ *
+ * A test file for commonJS-style module loading in Valija
+ */
+env.assertEquals(env.w, 6);
+exports.add = function(a, b) {
+  return a + b;
+};
=======================================
--- /trunk/src/com/google/caja/serverjs-sandbox.js      Wed Sep  2 13:52:16 2009
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (C) 2009 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/**
- * @author [email protected]
- * @provides serverJsSandboxMaker
- *
- */
-var serverJsSandboxMaker = (function(env, valijaMaker, load) {
-  if (env.Q === undefined) {
-    throw new Error('Include Q in env for serverJS sandbox modules.');
-  }
-  var exportsTable = cajita.newTable();
-
-  function resolveModuleId(mid, src) {
-    if (src.substring(src.length - 3) !== '.js') {
-      src = src + '.js';
-    }
-
-    if (src[0] !== '.') {
-      return src;
-    }
-
-    var k = mid.lastIndexOf("/");
-    var newMid;
-    if (k === -1) {
-      newMid = src;
-    } else {
-      newMid = mid.substring(0, k + 1) + src;
-    }
-
-    while((k = newMid.indexOf("/./")) !== -1) {
-      newMid = newMid.substring(0, k) + newMid.substring(k + 2);
-    }
-
-    while((k = newMid.indexOf("/../")) !== -1) {
-      var p = newMid.lastIndexOf("/", k - 1);
-      if (p === -1) {
-        newMid = newMid.substring(k + 4);
-      } else {
-        newMid = newMid.substring(0, p - 1) + newMid.substring(k + 4);
-      }
-    }
-
-    return newMid;
-  }
-
-  function requireMaker(mid) {
-    function async(src) {
-      var newMid = resolveModuleId(mid, src);
-      var theExports = exportsTable.get(newMid);
-      var Q = env.Q;
-      var r = Q.defer();
-      if (theExports !== void 0) {
-        r.resolve(theExports);
-      } else {
-       var require = requireMaker(newMid);
-        var exports = {};
-        exportsTable.set(newMid, exports);
-
-        var valijaOuters = {env: env, require: require, exports: exports};
-        var cajitaImports = cajita.freeze(
-            {load: load, $v: valijaMaker(valijaOuters)});
-
-        var m = load.async(newMid);
-        Q.when(m, function(module) {
-                    module(cajitaImports);
-                    r.resolve(exports);
-                  },
-                  function(reason) {
-                    r.resolve(Q.reject(
-                        "Loading module " + newMid + "failed, " + reason));
-                  });
-      }
-      return r.promise;
-    }
-
-    var theRequire = {};
-    theRequire.async = async;
-    theRequire.moduleId = mid;
-    return cajita.freeze(theRequire);
-  }
-
-  function loadModule(mid) {
-    return requireMaker('').async(mid);
-  }
-
-  return cajita.freeze({ loadModule: loadModule });
-});
-
-if (typeof loader !== 'undefined') {
-  loader.provide(serverJsSandboxMaker);
-}
=======================================
--- /trunk/tests/com/google/caja/serverJsRecursion.js Wed Sep 2 13:52:16 2009
+++ /dev/null
@@ -1,10 +0,0 @@
-exports.isNegative = function(a) {
-  if (a < 0) { return true; } else { return false; }
-};
-exports.isNonNegative = function (a) {
-  var m = require.async('./serverJsRecursion.vo');
-  var r = env.Q.defer();
-  env.Q.when(m, function(module) { r.resolve(!module.isNegative(a)); },
-                function(reason) { r.resolve(env.Q.reject(reason)); });
-  return r.promise;
-};
=======================================
--- /trunk/build.xml    Wed Sep  2 13:52:16 2009
+++ /trunk/build.xml    Thu Sep 10 18:33:03 2009
@@ -429,10 +429,23 @@
      <output file="${lib}/com/google/caja/add.vo.js" language="valija"/>
     </transform>
     <transform>
-     <include file="${tests}/com/google/caja/serverJsRecursion.js"/>
-     <output file="${lib}/com/google/caja/serverJsRecursion.vo.js"
+     <include file="${tests}/com/google/caja/commonJsRecursion.js"/>
+     <output file="${lib}/com/google/caja/commonJsRecursion.vo.js"
       language="valija"/>
     </transform>
+    <transform>
+     <include file="${tests}/com/google/caja/foo/f.js"/>
+     <output file="${lib}/com/google/caja/foo/f.co.js" language="cajita"/>
+    </transform>
+    <transform>
+     <include file="${tests}/com/google/caja/foo/staticinc.js"/>
+     <output file="${lib}/com/google/caja/foo/staticinc.vo.js"
+       language="valija"/>
+    </transform>
+    <transform>
+     <include file="${tests}/com/google/caja/sum.js"/>
+     <output file="${lib}/com/google/caja/sum.vo.js" language="valija"/>
+    </transform>
     <copy todir="${lib}">
       <fileset dir="${src}" includes="**/*.html"/>
       <fileset dir="${tests}" includes="**/*.html"/>
@@ -445,9 +458,9 @@
       <include file="${src}/com/google/caja/valija-cajita.js"/>
     </transform>
     <transform>
-      <output file="${lib}/com/google/caja/plugin/serverjs-sandbox.co.js"
+      <output file="${lib}/com/google/caja/plugin/commonjs-sandbox.co.js"
         language="cajita"/>
-      <include file="${src}/com/google/caja/serverjs-sandbox.js"/>
+      <include file="${src}/com/google/caja/commonjs-sandbox.js"/>
     </transform>
   </target>

=======================================
--- /trunk/src/com/google/caja/cajita-module.js Wed Sep  2 13:52:16 2009
+++ /trunk/src/com/google/caja/cajita-module.js Thu Sep 10 18:33:03 2009
@@ -15,14 +15,17 @@
 /**
  * @author [email protected]
  * @requires ___
- * @provides xhrModuleLoad, scriptModuleLoad
+ * @provides xhrModuleLoadMaker, scriptModuleLoadMaker, clearModuleCache
  *
- * Each load object contains one method
- * load.async(src): given the source URL, fetches the module asynchronously
- *                   and returns a promise to the module function.
+ * Each load maker object, given a current module identifier and an
+ * identifier resolver, returns a load object.
+ *
+ * A load object is a function object, load() returns the module object,
+ * given the source URL.
+ * load.async() returns a promise to the module, given the source URL.
  */
-var xhrModuleLoad;
-var scriptModuleLoad;
+var xhrModuleLoadMaker;
+var scriptModuleLoadMaker;
 var clearModuleCache;

 (function() {
@@ -35,58 +38,149 @@
     return src;
   }

-  function xhrLoad(src) {
-    var r = Q.defer();
-
-    if (cache[src] !== undefined) {
-      r.resolve(cache[src]);
-    }
-    else {
-      var xhr = new XMLHttpRequest();
-      xhr.onreadystatechange = function() {
-        if (xhr.readyState === 4) {
-          if (xhr.status === 200) {
-            var savedModuleHandler = ___.getNewModuleHandler();
-            ___.setNewModuleHandler(___.primFreeze({
-              handle: ___.markFuncFreeze(function theHandler(module) {
-                try {
-                  var securedModule = ___.prepareModule(module);
-                  cache[src] = securedModule;
-                  r.resolve(securedModule);
-               } catch (e) {
-                 r.resolve(Q.reject(e));
-               }
-              })
-            }));
-            //TODO: validate the response before eval it
-            eval(xhr.responseText);
-            ___.setNewModuleHandler(savedModuleHandler);
-          } else {
-            r.resolve(Q.reject(
-                "Retrieving the module " + src + "failed, "
-                + "status code = " + xhr.status));
-          }
-        }
-      };
-
-      src = addJsExtension(src);
-      xhr.open("GET", src, true);
-      xhr.overrideMimeType("application/javascript");
-      xhr.send(null);
+  function defaultMidResolver(mid, src) {
+    if (src[0] !== '.') {
+      return src;
+    }
+
+    var k = mid.lastIndexOf("/");
+    var newMid;
+    if (k === -1) {
+      newMid = src;
+    } else {
+      newMid = mid.substring(0, k + 1) + src;
+    }
+
+    while((k = newMid.indexOf("/./")) !== -1) {
+      newMid = newMid.substring(0, k) + newMid.substring(k + 2);
+    }
+
+    while((k = newMid.indexOf("/../")) !== -1) {
+      var p = newMid.lastIndexOf("/", k - 1);
+      if (p === -1) {
+        newMid = newMid.substring(k + 4);
+      } else {
+        newMid = newMid.substring(0, p) + newMid.substring(k + 3);
+      }
+    }
+
+    return newMid;
+  }
+
+  function syncLoad(mid) {
+    mid = addJsExtension(mid);
+    if (cache[mid] === undefined || Q.near(cache[mid]).isPromise___) {
+      throw new Error("The static module " + mid + " cannot be resolved.");
+    }
+    return Q.near(cache[mid]);
+  }
+
+  function loadMaker(mid, midResolver, asyncLoad) {
+    var load = function(src) {
+      return syncLoad(midResolver(mid, src));
+    };
+    load.FUNC___ = 'load';
+    ___.setStatic(load, 'async', ___.markFuncFreeze(function (src) {
+      return asyncLoad(midResolver(mid, src), midResolver);
+    }));
+    return ___.primFreeze(load);
+  }
+
+  function resolveDependency(module, load) {
+    var r = Q.defer();
+    if (module.includedModules !== undefined
+        && module.includedModules.length !== 0) {
+      var size = module.includedModules.length;
+      var count = 0;
+      for (var i = 0; i < size; i++) {
+        var src = module.includedModules[i];
+        var m = load.async(src);
+        Q.when(m, function(childModule) {
+                    count++;
+                    if (count === size) {
+                      r.resolve(true);
+                    }
+                  },
+                  function(reason) {
+                    r.resolve(Q.reject(
+                        "Retrieving the module " + newMid + " failed."));
+                  });
+      }
+    } else {
+      r.resolve(true);
     }
     return r.promise;
   }
-
-  xhrModuleLoad = ___.primFreeze({ async: ___.markFuncFreeze(xhrLoad) });
+
+  function xhrAsyncLoad(mid, midResolver) {
+    mid = addJsExtension(mid);
+    if (cache[mid] !== undefined) {
+      return cache[mid];
+    }
+
+    var r = Q.defer();
+    var xhr = new XMLHttpRequest();
+    xhr.onreadystatechange = function() {
+      if (xhr.readyState === 4) {
+        if (xhr.status === 200) {
+          var savedModuleHandler = ___.getNewModuleHandler();
+          ___.setNewModuleHandler(___.primFreeze({
+            handle: ___.markFuncFreeze(function theHandler(module) {
+              try {
+                var load = loadMaker(mid, midResolver, xhrAsyncLoad);
+                module.moduleId = mid;
+                var securedModule = ___.prepareModule(module, load);
+                cache[mid] = r.promise;
+                var dependency = resolveDependency(module, load);
+                Q.when(dependency, function(result) {
+                                     r.resolve(securedModule);
+                                   },
+                                   function(reason) {
+                                     r.resolve(Q.reject(
+                                         "Resolving dependency for the"
+                                         + "module " + mid + " failed."));
+                                   });
+              } catch (e) {
+                r.resolve(Q.reject(e));
+              }
+            })
+          }));
+          //TODO: validate the response before eval it
+          eval(xhr.responseText);
+          ___.setNewModuleHandler(savedModuleHandler);
+        } else {
+          r.resolve(Q.reject(
+              "Retrieving the module " + mid + " failed, "
+              + "status code = " + xhr.status));
+        }
+      }
+    };
+
+    xhr.open("GET", mid, true);
+    xhr.overrideMimeType("application/javascript");
+    xhr.send(null);
+    return r.promise;
+  }
+
+  xhrModuleLoadMaker = ___.markFuncFreeze(function(mid, midResolver) {
+    if (midResolver === undefined) {
+      midResolver = defaultMidResolver;
+    }
+
+    return loadMaker(mid, midResolver, xhrAsyncLoad);
+  });

   var head = 0;
   var queue = [];
   var busy = false;

-  function scriptLoad(src) {
+  function scriptAsyncLoad(mid, midResolver) {
+    mid = addJsExtension(mid);
+    if (cache[mid] !== undefined) {
+      return cache[mid];
+    }
+
     var r = Q.defer();
-
-    src = addJsExtension(src);

     function dequeue() {
       if (head < queue.length) {
@@ -98,9 +192,21 @@
                if (savedHead === head) {
               var r = queue[head].defer;
               try {
-                var securedModule = ___.prepareModule(module);
-                r.resolve(securedModule);
-                cache[queue[head].src] = securedModule;
+                var curMid = queue[head].mid;
+                var load = loadMaker(curMid, midResolver, scriptAsyncLoad);
+                module.moduleId = mid;
+                var securedModule = ___.prepareModule(module, load);
+                cache[curMid] = r.promise;
+
+                var dependency = resolveDependency(module, load);
+                Q.when(dependency, function(result) {
+                                     r.resolve(securedModule);
+                                   },
+                                   function(reason) {
+                                     r.resolve(Q.reject(
+ "Resolving dependency for the module "
+                                         + curMid + " failed."));
+                                   });
               } catch (e) {
                 r.resolve(Q.reject(e));
               }
@@ -118,7 +224,7 @@
           if (savedHead === head) {
             var r = queue[head].defer;
             r.resolve(Q.reject(
-                "Retrieving the module" + queue[head].src + " failed."));
+                "Retrieving the module " + queue[head].mid + " failed."));
             delete queue[head];
             head++;
             dequeue();
@@ -128,7 +234,7 @@
         }

         var script = document.createElement("script");
-       script.src = queue[head].src;
+       script.src = queue[head].mid;
        script.onerror = function() {
          timeout();
           script.onreadystatechange = script.onerror = null;
@@ -146,24 +252,25 @@
       }
     }

-    if (cache[src] !== undefined) {
-      r.resolve(cache[src]);
-    } else {
-      var e = new Object();
-      e.src = src;
-      e.defer = r;
-      queue.push(e);
-
-      if (!busy) {
-        dequeue();
-      }
-    }
-
+    var e = new Object();
+    e.mid = mid;
+    e.defer = r;
+    queue.push(e);
+
+    if (!busy) {
+      dequeue();
+    }
+
     return r.promise;
   }

-  scriptModuleLoad = ___.primFreeze(
-      { async: ___.markFuncFreeze(scriptLoad) });
+  scriptModuleLoadMaker =  ___.markFuncFreeze(function(mid, midResolver) {
+    if (midResolver === undefined) {
+         midResolver = defaultMidResolver;
+    }
+
+    return loadMaker(mid, midResolver, scriptAsyncLoad);
+  });

   clearModuleCache = ___.markFuncFreeze(function() {
     cajita.forOwnKeys(cache, ___.markFuncFreeze(function(k, v) {
=======================================
--- /trunk/src/com/google/caja/cajita.js        Wed Sep  2 15:06:36 2009
+++ /trunk/src/com/google/caja/cajita.js        Thu Sep 10 18:33:03 2009
@@ -2693,12 +2693,13 @@
   /**
    * Produces a function module given an object literal module
    */
-  function prepareModule(module) {
+  function prepareModule(module, load) {
     function theModule(imports) {
// The supplied 'imports' contain arguments supplied by the caller of the // module. We need to add the primordials (Array, Object, ...) to these
       // before invoking the Cajita module.
       var completeImports = copy(sharedImports);
+      completeImports.load = load;
       forOwnKeys(imports, markFuncFreeze(function(k, v) {
         completeImports[k] = v;
       }));
=======================================
--- /trunk/src/com/google/caja/parser/quasiliteral/CajitaRewriter.java Wed Sep 2 13:52:16 2009 +++ /trunk/src/com/google/caja/parser/quasiliteral/CajitaRewriter.java Thu Sep 10 18:33:03 2009
@@ -68,6 +68,7 @@

 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
@@ -88,6 +89,10 @@

   private final BuildInfo buildInfo;
   private final ModuleManager moduleManager;
+ // TODO: move this into scope if we use a single CajitaRewriter to rewrite
+  // multiple modules
+  private final Set<StringLiteral> moduleNameList
+      = new HashSet<StringLiteral>();

   /** Mark a tree as having been translated from another language. */
   private static void markTranslated(ParseTreeNode node) {
@@ -234,16 +239,25 @@
         if (bindings != null && scope.isImported("load")) {
           ParseTreeNode arg = bindings.get("arg");
           if (arg instanceof StringLiteral) {
-            assert(moduleManager != null);
-            int index = moduleManager.getModule((StringLiteral) arg);
-            if (index != -1) {
-              return QuasiBuilder.substV(
-                  "modulemap_...@moduleindex]",
-                  "moduleIndex",
-                  new IntegerLiteral(FilePosition.UNKNOWN, index));
+            if (moduleManager != null) {
+              int index = moduleManager.getModule((StringLiteral) arg);
+              if (index != -1) {
+                return QuasiBuilder.substV(
+                    "modulemap_...@moduleindex]",
+                    "moduleIndex",
+                    new IntegerLiteral(FilePosition.UNKNOWN, index));
+              } else {
+                // error messages were logged in the function getModule
+                return node;
+              }
             } else {
-              // error messages were logged in the function getModule
-              return node;
+              String name = ((StringLiteral) arg).getUnquotedValue();
+              moduleNameList.add(new StringLiteral(
+                  FilePosition.UNKNOWN, name));
+              return QuasiBuilder.substV(
+                  "load(@name)",
+                  "name",
+                  new StringLiteral(FilePosition.UNKNOWN, name));
             }
           } else {
             mq.addMessage(
@@ -276,6 +290,7 @@
               + "        @rewrittenModuleStmts*;"
               + "        return moduleResult___;"
               + "      },"
+              + "      includedModules: @moduleNames,"
               + "      cajolerName: @cajolerName,"
               + "      cajolerVersion: @cajolerVersion,"
               + "      cajoledDate: @cajoledDate"
@@ -290,6 +305,9 @@
Block rewrittenModuleStmts = (Block) expand(inputModuleStmts, null); ObjectConstructor moduleObjectLiteral = (ObjectConstructor) substV(
               "rewrittenModuleStmts", returnLast(rewrittenModuleStmts),
+              "moduleNames", new ArrayConstructor(
+                  FilePosition.UNKNOWN,
+                  new ArrayList<StringLiteral>(moduleNameList)),
               "cajolerName", new StringLiteral(
                   FilePosition.UNKNOWN, "com.google.caja"),
               "cajolerVersion", new StringLiteral(
=======================================
--- /trunk/src/com/google/caja/parser/quasiliteral/DefaultValijaRewriter.java Mon Aug 31 13:09:32 2009 +++ /trunk/src/com/google/caja/parser/quasiliteral/DefaultValijaRewriter.java Thu Sep 10 18:33:03 2009
@@ -207,6 +207,66 @@
       }
     },

+    new Rule() {
+      @Override
+      @RuleDescription(
+          name="staticCommonJsModuleLoading",
+          synopsis="based on the Cajita module loading",
+          reason="",
+          matches="require(@arg)",
+          substitutes="$v.cf($v.ro('require'), [load(@arg)])")
+      public ParseTreeNode fire(ParseTreeNode node, Scope scope) {
+        Map<String, ParseTreeNode> bindings = match(node);
+        if (bindings != null && scope.isOuter("includeScript")) {
+          ParseTreeNode arg = bindings.get("arg");
+          if (arg instanceof StringLiteral) {
+            String src = ((StringLiteral) arg).getUnquotedValue();
+            if (!src.endsWith(".vo")) {
+              src = src + ".vo";
+            }
+            return substV("arg",
+                new StringLiteral(FilePosition.UNKNOWN, src));
+          } else {
+            mq.addMessage(
+                RewriterMessageType.CANNOT_LOAD_A_DYNAMIC_SERVERJS_MODULE,
+                node.getFilePosition());
+            return node;
+          }
+        }
+        return NONE;
+      }
+    },
+
+    new Rule() {
+      @Override
+      @RuleDescription(
+          name="dynamicCommonJsModuleLoading",
+          synopsis="based on the Cajita module loading",
+          reason="",
+          matches="require.async(@arg)",
+ substitutes="$v.cm($v.ro('require'), 'async', [load.async(@arg)])")
+      public ParseTreeNode fire(ParseTreeNode node, Scope scope) {
+        Map<String, ParseTreeNode> bindings = match(node);
+        if (bindings != null && scope.isOuter("includeScript")) {
+          ParseTreeNode arg = bindings.get("arg");
+          if (arg instanceof StringLiteral) {
+            String src = ((StringLiteral) arg).getUnquotedValue();
+            if (!src.endsWith(".vo")) {
+              src = src + ".vo";
+            }
+            return substV("arg",
+                new StringLiteral(FilePosition.UNKNOWN, src));
+          } else {
+            mq.addMessage(
+                RewriterMessageType.CANNOT_LOAD_A_DYNAMIC_SERVERJS_MODULE,
+                node.getFilePosition());
+            return node;
+          }
+        }
+        return NONE;
+      }
+    },
+
////////////////////////////////////////////////////////////////////////
     // Module envelope
////////////////////////////////////////////////////////////////////////
=======================================
--- /trunk/tests/com/google/caja/a.js   Fri Aug 21 10:14:19 2009
+++ /trunk/tests/com/google/caja/a.js   Thu Sep 10 18:33:03 2009
@@ -1,1 +1,20 @@
+// Copyright (C) 2009 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @author [email protected]
+ *
+ * A test file for module loading in Cajita
+ */
 x + y
=======================================
--- /trunk/tests/com/google/caja/add.js Wed Sep  2 13:52:16 2009
+++ /trunk/tests/com/google/caja/add.js Thu Sep 10 18:33:03 2009
@@ -1,3 +1,22 @@
+// Copyright (C) 2009 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @author [email protected]
+ *
+ * A test file for commonJS-style module loading in Valija
+ */
 env.assertEquals(env.x, 6);
 exports.add = function(a, b) {
   return a + b;
=======================================
--- /trunk/tests/com/google/caja/c.js   Fri Aug 21 10:14:19 2009
+++ /trunk/tests/com/google/caja/c.js   Thu Sep 10 18:33:03 2009
@@ -1,1 +1,20 @@
+// Copyright (C) 2009 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @author [email protected]
+ *
+ * A test file for module loading in Cajita
+ */
 x + 1
=======================================
--- /trunk/tests/com/google/caja/demos/applet/caja-applet-cajita-golden.js Wed Sep 9 13:59:29 2009 +++ /trunk/tests/com/google/caja/demos/applet/caja-applet-cajita-golden.js Thu Sep 10 18:33:03 2009
@@ -23,6 +23,7 @@
         }
         return moduleResult___;
       },
+      \'includedModules\': [ ],
       \'cajolerName\': \'com.google.caja\',
       \'cajolerVersion\': \'testBuildVersion\',
       \'cajoledDate\': 0
=======================================
--- /trunk/tests/com/google/caja/demos/applet/caja-applet-valija-golden.js Wed Sep 9 13:59:29 2009 +++ /trunk/tests/com/google/caja/demos/applet/caja-applet-valija-golden.js Thu Sep 10 18:33:03 2009
@@ -37,6 +37,7 @@
         }
         return moduleResult___;
       },
+      \'includedModules\': [ ],
       \'cajolerName\': \'com.google.caja\',
       \'cajolerVersion\': \'testBuildVersion\',
       \'cajoledDate\': 0
=======================================
--- /trunk/tests/com/google/caja/foo/b.js       Fri Aug 21 10:14:19 2009
+++ /trunk/tests/com/google/caja/foo/b.js       Thu Sep 10 18:33:03 2009
@@ -1,3 +1,22 @@
+// Copyright (C) 2009 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @author [email protected]
+ *
+ * A test file for asynchronous module loading in Cajita
+ */
 var m = load.async('../c.co');
 var f1 = function(module) {
   var r1 = module({x: x});
=======================================
--- /trunk/tests/com/google/caja/foo/inc.js     Wed Sep  2 13:52:16 2009
+++ /trunk/tests/com/google/caja/foo/inc.js     Thu Sep 10 18:33:03 2009
@@ -1,7 +1,26 @@
+// Copyright (C) 2009 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @author [email protected]
+ *
+ * A test file for asynchronous commonJS-style module loading in Valija
+ */
 env.assertEquals(env.x, 6);
 exports.inc = function(x) {
   var r = env.Q.defer();
-  var m = require.async('../add.vo');
+  var m = require.async('../add');
   env.Q.when(m, function(module) {
                   r.resolve(module.add(x, 1));
                 },
=======================================
--- /trunk/tests/com/google/caja/opensocial/example-rewritten.xml Wed Sep 9 13:59:29 2009 +++ /trunk/tests/com/google/caja/opensocial/example-rewritten.xml Thu Sep 10 18:33:03 2009
@@ -66,6 +66,7 @@
         }
         return moduleResult___;
       },
+      'includedModules': [ ],
       'cajolerName': 'com.google.caja',
       'cajolerVersion': 'testBuildVersion',
       'cajoledDate': 0
=======================================
--- /trunk/tests/com/google/caja/parser/quasiliteral/ModuleFormatTest.java Mon Aug 10 14:00:55 2009 +++ /trunk/tests/com/google/caja/parser/quasiliteral/ModuleFormatTest.java Thu Sep 10 18:33:03 2009
@@ -61,6 +61,7 @@
     assertTrue(QuasiBuilder.match(
         "  ({"
         + "  instantiate: @instantiate,"
+        + "  includedModules: @includedModules,"
         + "  cajolerName: @cajolerName,"
         + "  cajolerVersion: @cajolerVersion,"
         + "  cajoledDate: @cajoledDate"
=======================================
--- /trunk/tests/com/google/caja/parser/quasiliteral/c.js Tue Jul 14 13:50:32 2009 +++ /trunk/tests/com/google/caja/parser/quasiliteral/c.js Thu Sep 10 18:33:03 2009
@@ -1,1 +1,20 @@
+// Copyright (C) 2009 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @author [email protected]
+ *
+ * A test file for bundled synchronous module loading in Cajita
+ */
 x + y
=======================================
--- /trunk/tests/com/google/caja/parser/quasiliteral/foo/b.js Fri Aug 21 10:14:19 2009 +++ /trunk/tests/com/google/caja/parser/quasiliteral/foo/b.js Thu Sep 10 18:33:03 2009
@@ -1,1 +1,20 @@
+// Copyright (C) 2009 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @author [email protected]
+ *
+ * A test file for bundled synchronous module loading in Cajita
+ */
 load('../c')({x: x + 1, y: y + 1});
=======================================
--- /trunk/tests/com/google/caja/parser/quasiliteral/testModule.co.js Wed Sep 9 13:59:29 2009 +++ /trunk/tests/com/google/caja/parser/quasiliteral/testModule.co.js Thu Sep 10 18:33:03 2009
@@ -8,6 +8,7 @@
  return moduleResult___;
 }
 ,
+'includedModules': [ ],
 'cajolerName': 'com.google.caja',
 'cajolerVersion': 'testBuildVersion',
 'cajoledDate': 0,
=======================================
--- /trunk/tests/com/google/caja/parser/quasiliteral/x.js Fri Aug 21 10:14:19 2009 +++ /trunk/tests/com/google/caja/parser/quasiliteral/x.js Thu Sep 10 18:33:03 2009
@@ -1,1 +1,20 @@
+// Copyright (C) 2009 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @author [email protected]
+ *
+ * A test file for module loading in Valija (using includeScript)
+ */
 x = 3;
=======================================
--- /trunk/tests/com/google/caja/plugin/domita_test.html Wed Sep 2 13:52:16 2009 +++ /trunk/tests/com/google/caja/plugin/domita_test.html Thu Sep 10 18:33:03 2009
@@ -206,16 +206,16 @@
     })();</script>

     <script type="text/javascript">
-    var serverJsSandboxMaker;
+    var commonJsSandboxMaker;
     (function () {
       if (isValija) {
         var testImports = ___.copy(___.sharedImports);
         testImports.loader = ___.freeze({
               provide: ___.markFuncFreeze(function (v)
-                  { serverJsSandboxMaker = v; })
+                  { commonJsSandboxMaker = v; })
             });
         ___.getNewModuleHandler().setImports(testImports);
-        loadScript('serverjs-sandbox.co.js');
+        loadScript('commonjs-sandbox.co.js');
       }
     })();</script>

@@ -404,25 +404,18 @@

       testImports.Q = Q;

-      testImports.xhrModuleLoad = ___.primFreeze({
-        async: ___.markFuncFreeze(function(src) {
-          return xhrModuleLoad.async(
-              '/ant-lib/com/google/caja/' + src);
-        })
-      });
-
-      testImports.scriptModuleLoad = ___.primFreeze({
-        async: ___.markFuncFreeze(function(src) {
-          return scriptModuleLoad.async(
-              'http://localhost:8000/ant-lib/com/google/caja/' + src);
-        })
-      });
+      testImports.xhrModuleLoad = xhrModuleLoadMaker(
+        '/ant-lib/com/google/caja/domita_test');
+
+      testImports.scriptModuleLoad = scriptModuleLoadMaker(
+        'http://localhost:8000/ant-lib/com/google/caja/domita_test');

       if (isValija) {
         testImports.xhrIncludeScript = ___.primFreeze({
           async: ___.markFuncFreeze(function(src) {
-            var m = xhrModuleLoad.async(
-                '/ant-lib/com/google/caja/' + src);
+            var m = xhrModuleLoadMaker(
+                '/ant-lib/com/google/caja/domita_test'
+                ).async(src);
             return Q.when(m,
                 function(module) { return module({$v: testImports.$v}); });
           })
@@ -430,8 +423,9 @@

         testImports.scriptIncludeScript = ___.primFreeze({
           async: ___.markFuncFreeze(function(src) {
-            var m = scriptModuleLoad.async(
-                'http://localhost:8000/ant-lib/com/google/caja/' + src);
+            var m = scriptModuleLoadMaker(
+                'http://localhost:8000/ant-lib/com/google/caja/domita_test'
+                ).async(src);
             return Q.when(m,
                 function(module) { return module({$v: testImports.$v}); });
           })
@@ -439,9 +433,11 @@

         testImports.env = testImports;
         testImports.env.x = 6;
-        var $s = serverJsSandboxMaker.CALL___(
-                testImports.env, valijaMaker, testImports.xhrModuleLoad);
-        testImports.serverJsModuleLoad = $s.loadModule;
+        testImports.env.w = 6;
+ var $s = commonJsSandboxMaker.CALL___(testImports.env, valijaMaker);
+        testImports.commonJsModuleLoad = ___.markFuncFreeze(function(src) {
+          return $s.loadModule(testImports.xhrModuleLoad.async(src));
+        });
       }

       attachDocumentStub(
@@ -481,7 +477,7 @@
       window.toString = function () { return '[WINDOW]'; };

       inlineHtml(isValija ? 'domita_test.vo.html' : 'domita_test.co.html',
-                 testDomContainer);
+          testDomContainer);
     })(); </script>

   </body>
=======================================
--- /trunk/tests/com/google/caja/plugin/domita_test_untrusted.html Thu Sep 10 15:07:14 2009 +++ /trunk/tests/com/google/caja/plugin/domita_test_untrusted.html Thu Sep 10 18:33:03 2009
@@ -424,10 +424,19 @@
 <p class="testcontainer" id="recursive-module">
 Recursive Module</p>

-<p class="testcontainer" id="server-js-module">ServerJS Module</p>
-
-<p class="testcontainer" id="server-js-recursive-module">
-ServerJS Recursive Module</p>
+<p class="testcontainer" id="common-js-module">CommonJS Module</p>
+
+<p class="testcontainer" id="common-js-recursive-module">
+CommonJS Recursive Module</p>
+
+<p class="testcontainer" id="xhr-unbundled-module-loader">
+XHR Unbundled Module Loader</p>
+
+<p class="testcontainer" id="script-unbundled-module-loader">
+Script Unbundled Module Loader</p>
+
+<p class="testcontainer" id="static-common-js-module">
+Static CommonJS Module</p>

 <p class="testcontainer" id="test-document-body-appendChild"
>I should be the last element until something is appended to document.body</p>
@@ -2798,7 +2807,7 @@
 function testAsyncModuleLoader(load, includeScript, prefix) {
   directAccess.clearModuleCache();
   if (!valijaMode) {
-    var m = load.async('a.co');
+    var m = load.async('./a.co');
     var f1 = function(module) {
       var r = module({x: 1, y: 2});
       assertEquals(r, 3);
@@ -2809,7 +2818,7 @@
     };
     Q.when(m, f1, f2);
   } else {
-    var m = includeScript.async('x.vo');
+    var m = includeScript.async('./x.vo');
     var f1 = function(result) {
       assertEquals(x, 3);
       pass(prefix + '-module-loader');
@@ -2834,11 +2843,9 @@
 function testAsyncModuleLoader2(load, prefix) {
   directAccess.clearModuleCache();
   if (!valijaMode) {
-    var m = load.async('foo/b.co');
+    var m = load.async('./foo/b.co');
     var f1 = function(module) {
-      var r = module({x: 1, y: 2, load: { async: function(src)
-          { return load.async('foo/' + src); } },
-          Q: Q, fail: fail});
+      var r = module({x: 1, y: 2, Q: Q, fail: fail});
       Q.when(r, function(result) {
                   assertEquals(result, 5);
                   pass(prefix + '-module-loader-2');
@@ -2879,17 +2886,17 @@
   };

   if (!valijaMode) {
-    var m = xhrModuleLoad.async('b.co');
+    var m = xhrModuleLoad.async('./b.co');
     Q.when(m, f1, f2);
   } else {
-    var m = xhrIncludeScript.async('foo/x.vo');
+    var m = xhrIncludeScript.async('./foo/x.vo');
     Q.when(m, f1, f2);
   }
 }

 jsunitRegister('testXhrModuleLoaderFailure',
                function testXhrModuleLoaderFailure() {
-   testAsyncModuleLoaderFailure(xhrModuleLoad, xhrIncludeScript, 'xhr');
+  testAsyncModuleLoaderFailure(xhrModuleLoad, xhrIncludeScript, 'xhr');
 });

 jsunitRegister('testScriptModuleLoaderFailure',
@@ -2901,9 +2908,9 @@
                function testRecursiveModule() {
   directAccess.clearModuleCache();
   if (!valijaMode) {
-    var m = scriptModuleLoad.async('recursion.co');
+    var m = scriptModuleLoad.async('./recursion.co');
     var f1 = function(module) {
-      var r = module({x: 5, load: scriptModuleLoad, Q: Q});
+      var r = module({x: 5, Q: Q});
         Q.when(r, function(result) {
                     assertEquals(result, 120);
                     pass('recursive-module');
@@ -2921,15 +2928,16 @@
   }
 });

-jsunitRegister('testServerJsModule',
-        function testServerJsModule() {
+jsunitRegister('testCommonJsModule',
+               function testCommonJsModule() {
+  directAccess.clearModuleCache();
   if (valijaMode) {
-    var m = serverJsModuleLoad('foo/inc.vo');
+    var m = commonJsModuleLoad('./foo/inc.vo');
     Q.when(m, function(module) {
                 var r = module.inc(env.x);
                 Q.when(r, function(result) {
                             assertEquals(result, 7);
-                            pass("server-js-module");
+                            pass("common-js-module");
                           },
                           function(reason) {
                             fail(reason);
@@ -2939,29 +2947,76 @@
                     fail("Loading module inc failed, " + reason);
                   });
   } else {
-    pass("server-js-module");
+    pass("common-js-module");
   }
 });

-jsunitRegister('testServerJsRecursiveModule',
-        function testServerJsRecursiveModule() {
+jsunitRegister('testCommonJsRecursiveModule',
+               function testCommonJsRecursiveModule() {
+  directAccess.clearModuleCache();
   if (valijaMode) {
-    var m = serverJsModuleLoad('serverJsRecursion.vo');
+    var m = commonJsModuleLoad('./commonJsRecursion.vo');
     Q.when(m, function(module) {
                 var r = module.isNonNegative(env.x);
                 Q.when(r, function(result) {
                             assertEquals(result, true);
-                            pass("server-js-recursive-module");
+                            pass("common-js-recursive-module");
                           },
                           function(reason) {
                             fail("Waiting for result failed, " + reason);
                           });
               },
               function(reason) {
-                fail("Loading module Recursion failed, " + reason);
+                fail("Loading module CommonJsRecursion failed, " + reason);
               });
   } else {
-    pass("server-js-recursive-module");
+    pass("common-js-recursive-module");
+  }
+});
+
+function testUnbundledModuleLoader(load, prefix) {
+  //directAccess.clearModuleCache();
+  if (!valijaMode) {
+    var m = load.async('./foo/f.co');
+    var f1 = function(module) {
+               var result = module({x: 1, y: 2});
+               assertEquals(result, 5);
+               pass(prefix + '-unbundled-module-loader');
+             };
+    var f2 = function(reason) {
+      fail("loading module F failed, " + reason);
+    };
+    Q.when(m, f1, f2);
+  } else {
+    pass(prefix + '-unbundled-module-loader');
+  }
+}
+
+jsunitRegister('testXhrUnbundledModuleLoader',
+               function testXhrUnbundledModuleLoader() {
+  testUnbundledModuleLoader(xhrModuleLoad, "xhr");
+});
+
+jsunitRegister('testScriptUnbundledModuleLoader',
+               function testScriptUnbundledModuleLoader() {
+  testUnbundledModuleLoader(scriptModuleLoad, "script");
+});
+
+jsunitRegister('testStaticCommonJsModule',
+               function testStaticCommonJsModule() {
+  directAccess.clearModuleCache();
+  if (valijaMode) {
+    var m = commonJsModuleLoad('./foo/staticinc.vo');
+    Q.when(m, function(module) {
+                var r = module.inc(env.w);
+                assertEquals(r, 7);
+                pass("static-common-js-module");
+              },
+              function(reason) {
+                fail("Loading module staticinc failed, " + reason);
+              });
+  } else {
+    pass("static-common-js-module");
   }
 });

=======================================
--- /trunk/tests/com/google/caja/recursion.js   Fri Aug 21 10:14:19 2009
+++ /trunk/tests/com/google/caja/recursion.js   Thu Sep 10 18:33:03 2009
@@ -1,3 +1,22 @@
+// Copyright (C) 2009 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @author [email protected]
+ *
+ * A test file for recursive asynchronous module loading in Cajita
+ */
 var result = Q.defer();
 if (x <= 0) {
   result.resolve(-1);
@@ -6,7 +25,7 @@
   result.resolve(1);
 }
 else {
-  var m = load.async('recursion.co');
+  var m = load.async('./recursion.co');
   Q.when(m, function(module) {
        var r = module({x: x - 1, load: load, Q: Q});
        Q.when(r, function(r) {result.resolve(x * r); });
=======================================
--- /trunk/tests/com/google/caja/service/CajolingServiceTest.java Thu Sep 10 15:16:44 2009 +++ /trunk/tests/com/google/caja/service/CajolingServiceTest.java Thu Sep 10 18:33:03 2009
@@ -196,6 +196,7 @@
               + "}"
               + "return moduleResult___;"
             + "},"
+          + "'includedModules':[],"
           + "'cajolerName':'com.google.caja',"
           + "'cajolerVersion':'testBuildVersion',"
           + "'cajoledDate':0"
@@ -237,6 +238,7 @@
             + "        }\n"
             + "        return moduleResult___;\n"
             + "      },\n"
+            + "      'includedModules': [ ],\n"
             + "      'cajolerName': 'com.google.caja',\n"
             + "      'cajolerVersion': 'testBuildVersion',\n"
             + "      'cajoledDate': 0\n"
@@ -273,6 +275,7 @@
         ""
         + "        return moduleResult___;\n"
         + "      },\n"
+        + "      'includedModules': [ ],\n"
         + "      'cajolerName': 'com.google.caja',\n"
         + "      'cajolerVersion': 'testBuildVersion',\n"
         + "      'cajoledDate': 0\n"
=======================================
--- /trunk/tests/com/google/caja/x.js   Fri Aug 21 10:14:19 2009
+++ /trunk/tests/com/google/caja/x.js   Thu Sep 10 18:33:03 2009
@@ -1,1 +1,20 @@
+// Copyright (C) 2009 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @author [email protected]
+ *
+ * A test file for module loading in Valija (using includeScript)
+ */
 x = 3;

Reply via email to