From e50b7ef686e865cc8b6bb7caa5e05292de4148a6 Mon Sep 17 00:00:00 2001 From: Patrick Mueller Date: Thu, 22 Mar 2012 16:28:17 -0400 Subject: [PATCH] [CB-280] Improve layout of cordova-js scripts https://issues.apache.org/jira/browse/CB-280 This was basically a refactoring of the lib subdirectories, without changing any of the code IN the lib subdirectories. Other changes: - build/packager.js modified to build based on the new lib subdirectories - Jakefile modified to call a new method in build/packager - README.md updated file/directory locations - test/runner.js changed the runner to run off a new 'test' platform, instead of using an on-the-fly platform it pieced together when the tests run. also changed the static() URL bits for the browser-based test - it was pulling in more than it needed - test/suite.html changed the urls of the jasmine files, based on the updates to the static() URL bits in the runner.js - - lib/common/exec.js - lib/common/platform.js stub files that will be replaced with platform-specific ones --- Jakefile | 13 +- README.md | 72 +++-- build/packager.js | 279 ++++++++++-------- lib/{exec/android.js => android/exec.js} | 0 .../android.js => android/platform.js} | 0 lib/{ => android}/plugin/android/app.js | 0 lib/{ => android}/plugin/android/callback.js | 0 lib/{ => android}/plugin/android/device.js | 0 lib/{ => android}/plugin/android/polling.js | 0 lib/{ => android}/plugin/android/storage.js | 0 .../blackberry.js => blackberry/exec.js} | 0 .../blackberry.js => blackberry/platform.js} | 0 .../plugin/blackberry/Contact.js | 0 .../plugin/blackberry/ContactUtils.js | 0 .../plugin/blackberry/DirectoryEntry.js | 0 .../plugin/blackberry/Entry.js | 0 lib/{ => blackberry}/plugin/blackberry/app.js | 0 .../plugin/blackberry/contacts.js | 0 .../plugin/blackberry/device.js | 0 .../plugin/blackberry/manager.js | 0 .../plugin/blackberry/notification.js | 0 lib/{ => common}/builder.js | 0 lib/{ => common}/channel.js | 0 lib/{platform => common}/common.js | 0 lib/common/exec.js | 1 + lib/common/platform.js | 1 + lib/{ => common}/plugin/Acceleration.js | 0 lib/{ => common}/plugin/Camera.js | 0 lib/{ => common}/plugin/CameraConstants.js | 0 .../plugin/CaptureAudioOptions.js | 0 lib/{ => common}/plugin/CaptureError.js | 0 .../plugin/CaptureImageOptions.js | 0 .../plugin/CaptureVideoOptions.js | 0 lib/{ => common}/plugin/CompassError.js | 0 lib/{ => common}/plugin/CompassHeading.js | 0 lib/{ => common}/plugin/ConfigurationData.js | 0 lib/{ => common}/plugin/Connection.js | 0 lib/{ => common}/plugin/Contact.js | 0 lib/{ => common}/plugin/ContactAddress.js | 0 lib/{ => common}/plugin/ContactError.js | 0 lib/{ => common}/plugin/ContactField.js | 0 lib/{ => common}/plugin/ContactFindOptions.js | 0 lib/{ => common}/plugin/ContactName.js | 0 .../plugin/ContactOrganization.js | 0 lib/{ => common}/plugin/Coordinates.js | 0 lib/{ => common}/plugin/DirectoryEntry.js | 0 lib/{ => common}/plugin/DirectoryReader.js | 0 lib/{ => common}/plugin/Entry.js | 0 lib/{ => common}/plugin/File.js | 0 lib/{ => common}/plugin/FileEntry.js | 0 lib/{ => common}/plugin/FileError.js | 0 lib/{ => common}/plugin/FileReader.js | 0 lib/{ => common}/plugin/FileSystem.js | 0 lib/{ => common}/plugin/FileTransfer.js | 0 lib/{ => common}/plugin/FileTransferError.js | 0 lib/{ => common}/plugin/FileUploadOptions.js | 0 lib/{ => common}/plugin/FileUploadResult.js | 0 lib/{ => common}/plugin/FileWriter.js | 0 lib/{ => common}/plugin/Flags.js | 0 lib/{ => common}/plugin/LocalFileSystem.js | 0 lib/{ => common}/plugin/Media.js | 0 lib/{ => common}/plugin/MediaError.js | 0 lib/{ => common}/plugin/MediaFile.js | 0 lib/{ => common}/plugin/MediaFileData.js | 0 lib/{ => common}/plugin/Metadata.js | 0 lib/{ => common}/plugin/Position.js | 0 lib/{ => common}/plugin/PositionError.js | 0 lib/{ => common}/plugin/ProgressEvent.js | 0 lib/{ => common}/plugin/accelerometer.js | 0 lib/{ => common}/plugin/battery.js | 0 lib/{ => common}/plugin/capture.js | 0 lib/{ => common}/plugin/compass.js | 0 lib/{ => common}/plugin/contacts.js | 0 lib/{ => common}/plugin/geolocation.js | 0 lib/{ => common}/plugin/network.js | 0 lib/{ => common}/plugin/notification.js | 0 lib/{ => common}/plugin/requestFileSystem.js | 0 .../plugin/resolveLocalFileSystemURI.js | 0 lib/{ => common}/utils.js | 0 lib/{exec/errgen.js => errgen/exec.js} | 0 .../errgen.js => errgen/platform.js} | 0 lib/{ => errgen}/plugin/errgen/device.js | 0 lib/{exec/ios.js => ios/exec.js} | 0 lib/{platform/ios.js => ios/platform.js} | 0 lib/{ => ios}/plugin/ios/Entry.js | 0 lib/{ => ios}/plugin/ios/FileReader.js | 0 lib/{ => ios}/plugin/ios/console.js | 0 lib/{ => ios}/plugin/ios/device.js | 0 lib/{ => ios}/plugin/ios/nativecomm.js | 0 lib/{ => ios}/plugin/ios/notification.js | 0 lib/{exec/playbook.js => playbook/exec.js} | 0 .../playbook.js => playbook/platform.js} | 0 lib/{ => playbook}/plugin/playbook/device.js | 0 lib/{ => playbook}/plugin/playbook/manager.js | 0 .../errgen.js => scripts/bootstrap-errgen.js} | 0 .../bootstrap-playbook.js} | 0 lib/{ => scripts}/bootstrap.js | 0 lib/{ => scripts}/require.js | 0 lib/{exec/test.js => test/exec.js} | 0 lib/{ => webworks}/plugin/webworks/manager.js | 0 lib/{exec/wp7.js => wp7/exec.js} | 0 lib/{platform/wp7.js => wp7/platform.js} | 0 lib/{ => wp7}/plugin/wp7/device.js | 0 test/runner.js | 25 +- test/suite.html | 8 +- 105 files changed, 236 insertions(+), 163 deletions(-) rename lib/{exec/android.js => android/exec.js} (100%) rename lib/{platform/android.js => android/platform.js} (100%) rename lib/{ => android}/plugin/android/app.js (100%) rename lib/{ => android}/plugin/android/callback.js (100%) rename lib/{ => android}/plugin/android/device.js (100%) rename lib/{ => android}/plugin/android/polling.js (100%) rename lib/{ => android}/plugin/android/storage.js (100%) rename lib/{exec/blackberry.js => blackberry/exec.js} (100%) rename lib/{platform/blackberry.js => blackberry/platform.js} (100%) rename lib/{ => blackberry}/plugin/blackberry/Contact.js (100%) rename lib/{ => blackberry}/plugin/blackberry/ContactUtils.js (100%) rename lib/{ => blackberry}/plugin/blackberry/DirectoryEntry.js (100%) rename lib/{ => blackberry}/plugin/blackberry/Entry.js (100%) rename lib/{ => blackberry}/plugin/blackberry/app.js (100%) rename lib/{ => blackberry}/plugin/blackberry/contacts.js (100%) rename lib/{ => blackberry}/plugin/blackberry/device.js (100%) rename lib/{ => blackberry}/plugin/blackberry/manager.js (100%) rename lib/{ => blackberry}/plugin/blackberry/notification.js (100%) rename lib/{ => common}/builder.js (100%) rename lib/{ => common}/channel.js (100%) rename lib/{platform => common}/common.js (100%) create mode 100644 lib/common/exec.js create mode 100644 lib/common/platform.js rename lib/{ => common}/plugin/Acceleration.js (100%) rename lib/{ => common}/plugin/Camera.js (100%) rename lib/{ => common}/plugin/CameraConstants.js (100%) rename lib/{ => common}/plugin/CaptureAudioOptions.js (100%) rename lib/{ => common}/plugin/CaptureError.js (100%) rename lib/{ => common}/plugin/CaptureImageOptions.js (100%) rename lib/{ => common}/plugin/CaptureVideoOptions.js (100%) rename lib/{ => common}/plugin/CompassError.js (100%) rename lib/{ => common}/plugin/CompassHeading.js (100%) rename lib/{ => common}/plugin/ConfigurationData.js (100%) rename lib/{ => common}/plugin/Connection.js (100%) rename lib/{ => common}/plugin/Contact.js (100%) rename lib/{ => common}/plugin/ContactAddress.js (100%) rename lib/{ => common}/plugin/ContactError.js (100%) rename lib/{ => common}/plugin/ContactField.js (100%) rename lib/{ => common}/plugin/ContactFindOptions.js (100%) rename lib/{ => common}/plugin/ContactName.js (100%) rename lib/{ => common}/plugin/ContactOrganization.js (100%) rename lib/{ => common}/plugin/Coordinates.js (100%) rename lib/{ => common}/plugin/DirectoryEntry.js (100%) rename lib/{ => common}/plugin/DirectoryReader.js (100%) rename lib/{ => common}/plugin/Entry.js (100%) rename lib/{ => common}/plugin/File.js (100%) rename lib/{ => common}/plugin/FileEntry.js (100%) rename lib/{ => common}/plugin/FileError.js (100%) rename lib/{ => common}/plugin/FileReader.js (100%) rename lib/{ => common}/plugin/FileSystem.js (100%) rename lib/{ => common}/plugin/FileTransfer.js (100%) rename lib/{ => common}/plugin/FileTransferError.js (100%) rename lib/{ => common}/plugin/FileUploadOptions.js (100%) rename lib/{ => common}/plugin/FileUploadResult.js (100%) rename lib/{ => common}/plugin/FileWriter.js (100%) rename lib/{ => common}/plugin/Flags.js (100%) rename lib/{ => common}/plugin/LocalFileSystem.js (100%) rename lib/{ => common}/plugin/Media.js (100%) rename lib/{ => common}/plugin/MediaError.js (100%) rename lib/{ => common}/plugin/MediaFile.js (100%) rename lib/{ => common}/plugin/MediaFileData.js (100%) rename lib/{ => common}/plugin/Metadata.js (100%) rename lib/{ => common}/plugin/Position.js (100%) rename lib/{ => common}/plugin/PositionError.js (100%) rename lib/{ => common}/plugin/ProgressEvent.js (100%) rename lib/{ => common}/plugin/accelerometer.js (100%) rename lib/{ => common}/plugin/battery.js (100%) rename lib/{ => common}/plugin/capture.js (100%) rename lib/{ => common}/plugin/compass.js (100%) rename lib/{ => common}/plugin/contacts.js (100%) rename lib/{ => common}/plugin/geolocation.js (100%) rename lib/{ => common}/plugin/network.js (100%) rename lib/{ => common}/plugin/notification.js (100%) rename lib/{ => common}/plugin/requestFileSystem.js (100%) rename lib/{ => common}/plugin/resolveLocalFileSystemURI.js (100%) rename lib/{ => common}/utils.js (100%) rename lib/{exec/errgen.js => errgen/exec.js} (100%) rename lib/{platform/errgen.js => errgen/platform.js} (100%) rename lib/{ => errgen}/plugin/errgen/device.js (100%) rename lib/{exec/ios.js => ios/exec.js} (100%) rename lib/{platform/ios.js => ios/platform.js} (100%) rename lib/{ => ios}/plugin/ios/Entry.js (100%) rename lib/{ => ios}/plugin/ios/FileReader.js (100%) rename lib/{ => ios}/plugin/ios/console.js (100%) rename lib/{ => ios}/plugin/ios/device.js (100%) rename lib/{ => ios}/plugin/ios/nativecomm.js (100%) rename lib/{ => ios}/plugin/ios/notification.js (100%) rename lib/{exec/playbook.js => playbook/exec.js} (100%) rename lib/{platform/playbook.js => playbook/platform.js} (100%) rename lib/{ => playbook}/plugin/playbook/device.js (100%) rename lib/{ => playbook}/plugin/playbook/manager.js (100%) rename lib/{bootstrap/errgen.js => scripts/bootstrap-errgen.js} (100%) rename lib/{bootstrap/playbook.js => scripts/bootstrap-playbook.js} (100%) rename lib/{ => scripts}/bootstrap.js (100%) rename lib/{ => scripts}/require.js (100%) rename lib/{exec/test.js => test/exec.js} (100%) rename lib/{ => webworks}/plugin/webworks/manager.js (100%) rename lib/{exec/wp7.js => wp7/exec.js} (100%) rename lib/{platform/wp7.js => wp7/platform.js} (100%) rename lib/{ => wp7}/plugin/wp7/device.js (100%) diff --git a/Jakefile b/Jakefile index af05af69..f8cd07aa 100644 --- a/Jakefile +++ b/Jakefile @@ -22,12 +22,13 @@ task('build', ['clean'], function () { var packager = require("./build/packager"); - packager.write("blackberry"); - packager.write("playbook"); - packager.write("ios"); - packager.write("wp7"); - packager.write("android"); - packager.write("errgen"); + packager.generate("blackberry"); + packager.generate("playbook"); + packager.generate("ios"); + packager.generate("wp7"); + packager.generate("android"); + packager.generate("errgen"); + packager.generate("test"); }); diff --git a/README.md b/README.md index 5dd4e92a..b8ca0dcb 100644 --- a/README.md +++ b/README.md @@ -5,45 +5,57 @@ A unified JavaScript layer for [Apache Cordova](http://incubator.apache.org/proj cordova-js | |-build/ - | Will contain any build modules (currently nothing here as it is all hacked - | into the JakeFile) + | Will contain any build modules (currently nothing here as it is all + | hacked into the JakeFile) | |-lib - | |-bootstrap.js - | | Code to bootstrap the Cordova platform, inject APIs and fire events - | | - | |-builder.js - | | Injects in our classes onto window and navigator (or wherever else is needed) - | | - | |-channel.js - | | A pub/sub implementation to handle custom framework events - | | | |-cordova.js | | Common Cordova stuff such as callback handling and | | window/document add/removeEventListener hijacking | | - | |-require.js - | | Our own module definition and require implementation. + | |-common/ + | | Contains the common-across-platforms base modules + | | + | |-common/builder.js + | | Injects in our classes onto window and navigator (or wherever else + | | is needed) + | | + | |-common/channel.js + | | A pub/sub implementation to handle custom framework events | | - | |-utils.js + | |-common/common.js + | | Common locations to add Cordova objects to browser globals. + | | + | |-common/exec.js + | | Stub for platform's specific version of exec.js + | | + | |-common/platform.js + | | Stub for platform's specific version of platform.js + | | + | |-common/utils.js | | General purpose JS utility stuff: closures, uuids, object | | cloning, extending prototypes | | - | |-exec/ - | | Contains the platform specific definitions of the exec method + | |-common/plugin + | | Contains the common-across-platforms plugin modules | | - | |-platform/ - | | Definitions of each platform that help us describe where - | | and what to put on the window object, and what to run to - | | initialize the platform. A common set of globals are also - | | defined (common.js) + | |-scripts/ + | | Contains non-module JavaScript source that gets added to the + | | resulting cordova..js files closures, uuids, object + | | + | |-scripts/bootstrap.js + | | Code to bootstrap the Cordova platform, inject APIs and fire events | | - | |-plugin/ - | | | All API definitions as plugins, ones common to all - | | | platforms reside at the top level... - | | `- - | | ... and platform-specific ones reside in their respective - | | folders + | |-scripts/require.js + | | Our own module definition and require implementation. + | | + | |-/ + | | Contains the platform-specific base modules. + | | + | |-/plugin + | | Contains the platform-specific plugin modules. + +The way the resulting `cordova..js` files will be built is by combining the scripts in the `lib/scripts` directory with modules from the `lib/common` and `lib/` directories. For cases where there is the same named module in `lib/common` and `lib/`, the `lib/` version wins. For instance, every `lib/` includes an `exec.js`, and there is also a version in `lib/common`, so the `lib/` version will always be used. In fact, the `lib/common` one will throw errors, so if you build a new platform and forget `exec.js`, the resulting `cordova..js` file will also throw errors. # Building @@ -77,13 +89,13 @@ This will run the `build` and `test` tasks by default. All of the available task The `build/packager.js` tool is a node.js script that concatenates all of the core Cordova plugins in this repository into a `cordova..js` file under the `pkg/` folder. It also wraps the plugins with a RequireJS-compatible module syntax that works in both browser and node environments. We end up with a cordova.js file that wraps each Cordova plugin into its own module. -Cordova defines a `channel` module under `lib/channel.js`, which is a publish/subscribe implementation that the project uses for event management. +Cordova defines a `channel` module under `lib/common/channel.js`, which is a publish/subscribe implementation that the project uses for event management. -The Cordova native-to-webview bridge is initialized in `lib/bootstrap.js`. This file attaches the `boot` function to the `channel.onNativeReady` event - fired by native with a call to: +The Cordova native-to-webview bridge is initialized in `lib/scripts/bootstrap.js`. This file attaches the `boot` function to the `channel.onNativeReady` event - fired by native with a call to: cordova.require('cordova/channel).onNativeReady.fire() -The `boot` method does all the work. First, it grabs the common platform definition (under `lib/platform/common.js`) and injects all of the objects defined there onto `window` and other global namespaces. Next, it grabs all of the platform-specific object definitions (as defined under `lib/platform/.js`) and overrides those onto `window`. Finally, it calls the platform-specific `initialize` function (located in the platform definition). At this point, Cordova is fully initialized and ready to roll. Last thing we do is wait for the `DOMContentLoaded` event to fire to make sure the page has loaded properly. Once that is done, Cordova fires the `deviceready` event where you can safely attach functions that consume the Cordova APIs. +The `boot` method does all the work. First, it grabs the common platform definition (under `lib/common/common.js`) and injects all of the objects defined there onto `window` and other global namespaces. Next, it grabs all of the platform-specific object definitions (as defined under `lib//platform.js`) and overrides those onto `window`. Finally, it calls the platform-specific `initialize` function (located in the platform definition). At this point, Cordova is fully initialized and ready to roll. Last thing we do is wait for the `DOMContentLoaded` event to fire to make sure the page has loaded properly. Once that is done, Cordova fires the `deviceready` event where you can safely attach functions that consume the Cordova APIs. # Testing diff --git a/build/packager.js b/build/packager.js index 39a9704a..65690208 100644 --- a/build/packager.js +++ b/build/packager.js @@ -1,135 +1,184 @@ -var util = require('util'), - debug = false, - fs = require('fs'); - -// (Recursively) list contents of a directory -function walk(dir, doRecursive) { - var results = []; - try { - var list = fs.readdirSync(dir); - for (var i = 0, l = list.length; i < l; i++) { - var file = list[i]; - file = dir + '/' + file; - var stat = fs.statSync(file); - if (stat && doRecursive && stat.isDirectory()) { - results = results.concat(walk(file,doRecursive)); - } else { - if (list[i] != ".DS_Store") { - results.push(file); - } - } - } - } catch (e) { - //do nothing - } - return results; -} - -// Simply inline includes the specified file(s) with an optional transform function. -function include(files, transform) { - files = files.map ? files : [files]; - return files.map(function (file) { - try { - var str = fs.readFileSync(file, "utf-8") + "\n"; - str = transform ? transform(str, file) : str; - str = debug ? "try {" + str + "} catch (e) { alert('" + file + ":' + e);}" : str; - return str; - } catch (e) { - //do nothing - } - }).join('\n'); +var fs = require('fs') +var util = require('util') +var path = require('path') + +var packager = module.exports + +//------------------------------------------------------------------------------ +packager.generate = function(platform) { + var time = new Date().valueOf() + + var libraryRelease = packager.bundle(platform, false) + var libraryDebug = packager.bundle(platform, true) + + time = new Date().valueOf() - time + + var outFile + + outFile = path.join('pkg', 'cordova.' + platform + '.js') + fs.writeFileSync(outFile, libraryRelease, 'utf8') + + outFile = path.join('pkg', 'cordova.' + platform + '-debug.js') + fs.writeFileSync(outFile, libraryDebug, 'utf8') + + console.log('generated platform: ' + platform + ' in ' + time + 'ms') } -// Includes the specified file(s) with optional overriding id -// Wraps the specified file(s) in a define statement which implicitly -// creates a closure as well. -function drop(files, id) { - return include(files, function(file, path) { - var define_id = (typeof id != 'undefined' && id.length > 0 ? id : path.replace(/lib\//, "cordova/").replace(/\.js$/, '')); - return "define('" + define_id + "', function(require, exports, module) {\n" + file + "});\n"; - }); -} - -module.exports = { - modules: function (platform) { - var baseFiles = [ - "lib/utils.js", - "lib/builder.js" - ], - platformFiles = walk('lib/plugin/' + platform, true), - output = ""; - - //HACK: ummm .... we really need to figure out this webworks common file stuff - if (platform === "blackberry" || platform === "playbook") { - platformFiles = platformFiles.concat(walk('lib/plugin/webworks', true)); - } - - //include all common platform files that are under lib/plugin - baseFiles = baseFiles.concat(walk('lib/plugin')); - - //include require - output += include("lib/require.js"); - - //include channel - output += drop('lib/channel.js', 'cordova/channel'); +//------------------------------------------------------------------------------ +packager.bundle = function(platform, debug) { + var modules = collectFiles('lib/common') + var scripts = collectFiles('lib/scripts') + + modules[''] = 'lib/cordova.js' + + if (['playbook', 'blackberry'].indexOf(platform) > -1) { + copyProps(modules, collectFiles(path.join('lib', 'webworks'))) + } + + copyProps(modules, collectFiles(path.join('lib', platform))) + + var output = [] + + // write header + output.push('/*\n' + getContents('LICENSE-for-js-file.txt') + '\n*/') + output.push('\n;(function() {\n') + + // write initial scripts + if (!scripts['require']) { + throw new Error("didn't find a script for 'require'") + } + + writeScript(output, scripts['require'], debug) + + // write modules + var moduleIds = Object.keys(modules) + moduleIds.sort() + + for (var i=0; i EXTERMINATE! - + - - - + + +