getting things ready for module glomming
authorKevin Dangoor <kdangoor@mozilla.com>
Fri, 16 Oct 2009 11:20:14 -0400
changeset 131 e5b65fd41c9919849c53cc08168d19cbaa04526b
parent 130 fd690d35b7ad0e661ed8d9c54a9a7a1e2438bb45
child 132 ea14df3917c8f21b8fa9f42f325a5d46b87189ee
push id49
push userkdangoor@mozilla.com
push dateFri, 16 Oct 2009 15:20:20 +0000
getting things ready for module glomming
src/bespin-build/lib/bespin/builder.js
src/bespin-build/lib/bespin/builder/tests/commandTest.js
src/html/index.html
src/html/loader.js
src/html/test.html
--- a/src/bespin-build/lib/bespin/builder.js
+++ b/src/bespin-build/lib/bespin/builder.js
@@ -22,59 +22,125 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Bespin build system
 
 var file = require("file");
 var os = require("os");
 
-DEFAULT_PROFILE = "bespinProfile.json";
+var DEFAULT_PROFILE = "bespinProfile.json";
 
-PROFILE_FORMAT = '\nA profile is a JSON file containing an array of objects.\n' +
+var PROFILE_FORMAT = '\nA profile is a JSON file containing an array of objects.\n' +
     'Each object must minimally have an "output" defined on it. For example:\n\n' +
     '[{"output": "BespinEmbed.js"}]\n\n' +
     'is a minimally acceptable profile.\n';
+    
+var STANDARD_INCLUDES = [
+    {file: "src/html/loader.js"},
+    {file: "src/bespin-build/preloads.js"},
+    "narwhal/client"
+];
 
 var BuilderError = exports.BuilderError = function(message) {
     this.message = message;
-}
+};
 
+/*
+* Loads a JSON-format profile from disk.
+* @param {String} filename The profile file to load.
+* @type Object
+*/
 exports.loadProfile = function(filename) {
     if (!file.exists(filename)) {
         throw new BuilderError("Profile file " + filename + " does not exist.");
     }
     var data = file.read(filename);
     return JSON.parse(data);
-}
+};
 
+/*
+* Validates the information in a loaded profile object.
+* @param {Object} profile The profile object.
+*/
 exports.validateProfile = function(profile) {
     if (!Array.isArray(profile)) {
         throw new BuilderError(PROFILE_FORMAT);
     }
     for (var i = 0; i < profile.length; i++) {
-        if (!profile.output) {
+        var desc = profile[i];
+        if (!desc.output) {
             throw new BuilderError(PROFILE_FORMAT);
         }
+        if (!desc.includes) {
+            desc.includes = STANDARD_INCLUDES;
+        }
     }
-}
+};
 
+/*
+* Retrieves/augments the file contents for the filespec provided.
+* The filespec can be a string, in which case it's assumed to be
+* a module. Modules are looked up on the module path, and the
+* contents are wrapped to be properly registered with the client-side
+* module sandbox.
+* 
+* If filespec is an object with a "file" property, then that
+* file's contents will be returned directly.
+* @param {String|Object} filespec File to return contents of.
+* @type String
+*/
+exports.getFileContents = function(filespec) {
+    if (filespec instanceof String) {
+        // handle modules
+        return "";
+    } else if (filespec.file) {
+        // handle files
+        var path = new file.Path(filespec.file);
+        if (!path.exists()) {
+            throw new BuilderError("Could not find included file: " 
+                + filespec.file);
+        }
+        return path.read();
+    }
+};
+
+/*
+* Generates an output script based on one item
+* description from the profile.
+* @param {Object} description One item from the list of items in a profile.
+*/
+exports.generateScript = function(description) {
+    var outputPath = new file.Path(description.output);
+    if (!outputPath.dirname().exists()) {
+        outputPath.dirname().mkdirs();
+    }
+};
+
+/*
+* Entry point for the command line interface.
+* @param (Array) args The command line arguments.
+*/
 exports.main = function(args) {
     print("Bespin Build System\n");
     
     var profileFilename = args[1] ? args[1] : DEFAULT_PROFILE;
     
     try {
         var profile = exports.loadProfile(profileFilename);
 
         exports.validateProfile(profile);
 
         print("Using build profile: ", profileFilename);
         
+        for (var i = 0; i < profile.length; i++) {
+            exports.generateScript(profile[i]);
+        }
+        
     } catch (e) {
         if (e instanceof exports.BuilderError) {
             print("Build failed!");
             print (e.message);
             os.exit(1);
         }
     }
     
-}
\ No newline at end of file
+};
--- a/src/bespin-build/lib/bespin/builder/tests/commandTest.js
+++ b/src/bespin-build/lib/bespin/builder/tests/commandTest.js
@@ -36,27 +36,58 @@ var FAKEPROFILE = new file.Path(module.p
 var throwsBuilderError = function(func, args, message) {
     try {
         func.apply(this, args);
         qunit.ok(false, message);
     } catch (e) {
         if (e instanceof builder.BuilderError) {
             qunit.ok(true, "Got a BuilderError");
         } else {
-            throw e;
+            qunit.ok(false, "Got an unexpected exception: " + e);
         }
     }
-}
+};
 
 qunit.test("Profile loading", function() {
-    qunit.ok(FAKEPROFILE.exists(), "Expected the testing profile file to exist (fakeprofile.json)");
-    qunit.ok(FAKEPROFILE.isFile(), "Expected to find a file at " + FAKEPROFILE);
+    qunit.ok(FAKEPROFILE.exists(), 
+        "Expected the testing profile file to exist (fakeprofile.json)");
+    qunit.ok(FAKEPROFILE.isFile(), 
+        "Expected to find a file at " + FAKEPROFILE);
     throwsBuilderError(builder.loadProfile, ["BADFILENAME!!!"], 
         "Expected an exception for a bad filename");
     var profile = builder.loadProfile(FAKEPROFILE);
-    qunit.equals(1, profile.length);
-    qunit.equals("foo", profile[0].output);
+    qunit.equals(profile.length, 1);
+    qunit.equals(profile[0].output, "foo");
 });
 
 qunit.test("Profile validation", function() {
-    throwsBuilderError(builder.validateProfile, [{}], "validate profile expects a list");
-    throwsBuilderError(builder.validateProfile, [[{}]], "profiles must have an output defined");
+    throwsBuilderError(builder.validateProfile, [{}], 
+        "validate profile expects a list");
+    throwsBuilderError(builder.validateProfile, [[{}]], 
+        "profiles must have an output defined");
+    
+    var myProfile = [{output: "foo.js"}];
+    builder.validateProfile(myProfile);
+    qunit.ok(true, "Should not have encountered an error in the previous validation.");
+    qunit.ok(Array.isArray(myProfile[0].includes), 
+        "Expected profile to be augmented with includes");
 });
+
+qunit.test("Setting up for build", function() {
+    var temppath = new file.Path("testtmp");
+    if (temppath.exists()) {
+        temppath.rmtree();
+    }
+    builder.generateScript({output: temppath + "/foo.js"});
+    qunit.ok(temppath.exists(), "expected output directory to be created");
+    if (temppath.exists()) {
+        temppath.rmtree();
+    }
+});
+
+qunit.test("Get file contents", function() {
+    throwsBuilderError(builder.getFileContents, [{file: "BADFILENAME"}],
+        "file contents can only be retrieved for good files");
+    file.write("GOODFILENAME", "Just some test data.\n");
+    var contents = builder.getFileContents({file: "GOODFILENAME"});
+    qunit.equals(contents, "Just some test data.\n", "File contents not retrieved properly");
+    file.remove("GOODFILENAME");
+});
\ No newline at end of file
--- a/src/html/index.html
+++ b/src/html/index.html
@@ -1,15 +1,16 @@
 <!DOCTYPE html>
 <html><head>
 <link rel="stylesheet" href="sproutcore.css" type="text/css" />
 <link rel="stylesheet" href="bespin.css" type="text/css" />
 
 <script type="text/javascript" src="loader.js"></script>
 <script type="text/javascript">
+  require.preload(["ref-send", "sandbox", "narwhal/client", "array", "object", "string", "function", "regexp", "reactor", "date", "global", "system", "binary"]);
   require.async("bespin/boot");
 </script>
 
 <script type="text/javascript" src="dojo/dojo.js.uncompressed.js"></script>
 <script type='text/javascript' src='dojo/regexp.js'></script>
 <script type='text/javascript' src='dojo/cookie.js'></script>
 <script type='text/javascript' src='dojo/AdapterRegistry.js'></script>
 <script type='text/javascript' src='dojo/fx/easing.js'></script>
--- a/src/html/loader.js
+++ b/src/html/loader.js
@@ -2,16 +2,17 @@
 // client/browser module server defined in the narwhal/server module, or some
 // similar mechanism.  this file is simply an anonymous function declaration.
 // the server constructs an inline script to inject anywhere in an HTML page,
 // along with its "path" argument (the base URL from which to download
 // modules).  The function returns a module loader API function/object called
 // "require" that can then be chained with .preload(ids), .when(id),
 // .async(id), or other calls, depending on what services are needed to load
 // this particular page.
+
 (function (path) {
 
     // ultimately, we're exporting a "require" API to global scope, and
     // returning that same object.
     var require = this.require = function (id) {
         if (!require.require)
             throw new Error("require is not yet available");
         return require.require(id);
@@ -98,9 +99,9 @@
     // maintaining the require object along the call chain.
     require.bridge = function (block) {
         block(require);
         return require;
     };
 
     // return the require object for chaining
     return require;
-}).call(this,"/.js/").preload(["ref-send", "sandbox", "narwhal/client", "array", "object", "string", "function", "regexp", "reactor", "date", "global", "system", "binary"])
\ No newline at end of file
+}).call(this,"/.js/");
--- a/src/html/test.html
+++ b/src/html/test.html
@@ -1,13 +1,14 @@
 <!DOCTYPE html>
 <html><head>
   <link rel="stylesheet" type="text/css" href="qunit.css">
   <script type="text/javascript" src="loader.js"></script>
   <script type="text/javascript">
+    require.preload(["ref-send", "sandbox", "narwhal/client", "array", "object", "string", "function", "regexp", "reactor", "date", "global", "system", "binary"]);
     require.async("bespin/tests/bootTests");
   </script>
 </head>
 <body>
    <h1 id="qunit-header">Bespin Tests</h1>
   <h2 id="qunit-banner"></h2>
   <h2 id="qunit-userAgent"></h2>
   <ol id="qunit-tests"></ol>