Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/utils/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'utils/platforms')
-rwxr-xr-xutils/platforms/browser/inline.js56
-rwxr-xr-xutils/platforms/browser/lib/modules.js1449
-rwxr-xr-xutils/platforms/browser/lib/system.js3
-rwxr-xr-xutils/platforms/default/lib/binary-platform.js53
-rwxr-xr-xutils/platforms/default/lib/binary.js719
-rwxr-xr-xutils/platforms/default/lib/os-platform.js3
-rwxr-xr-xutils/platforms/k7/bin/narwhal-k732
-rwxr-xr-xutils/platforms/k7/bootstrap.js78
-rwxr-xr-xutils/platforms/k7/lib/binary.js2
-rwxr-xr-xutils/platforms/k7/lib/file-platform.js116
-rwxr-xr-xutils/platforms/k7/lib/io-platform.js8
-rwxr-xr-xutils/platforms/k7/lib/system.js25
-rwxr-xr-xutils/platforms/rhino/bin/narwhal-rhino.cmd25
-rwxr-xr-xutils/platforms/rhino/lib/binary-platform.js44
14 files changed, 2613 insertions, 0 deletions
diff --git a/utils/platforms/browser/inline.js b/utils/platforms/browser/inline.js
new file mode 100755
index 0000000..16d8b11
--- /dev/null
+++ b/utils/platforms/browser/inline.js
@@ -0,0 +1,56 @@
+(function (ids, id, path) {
+
+ var factories = {};
+ var pending;
+
+ var require = this.require = function (id, baseId) {
+ // defer to require set later from the sandbox module
+ require(id, baseId);
+ };
+
+ require.register = function (id, factory) {
+ factories[id] = factory;
+ if (!--pending)
+ main();
+ };
+
+ var pending = ids.length;
+ var head = document.getElementsByTagName('head')[0];
+ for (var i = 0; i < pending; i++) {
+ var script = document.createElement('script');
+ script.src = path + ids[i] + '.js';
+ head.appendChild(script);
+ };
+
+ function main() {
+
+ var system = {};
+ system.print = function () {
+ if (typeof console != "undefined") {
+ console.log(Array.prototype.join.call(arguments, ' '));
+ }
+ };
+
+ var loader = {};
+ loader.reload = function (topId) {
+ return factories[topId];
+ };
+ loader.load = function (topId) {
+ return loader.reload(topId);
+ };
+
+ var sandbox = {};
+ loader.load('sandbox')(
+ null,
+ sandbox,
+ {},
+ system,
+ system.print
+ );
+ require = sandbox.Sandbox({loader: loader});
+ loader.resolve = sandbox.resolve;
+ require(id);
+
+ }
+
+})
diff --git a/utils/platforms/browser/lib/modules.js b/utils/platforms/browser/lib/modules.js
new file mode 100755
index 0000000..db89b93
--- /dev/null
+++ b/utils/platforms/browser/lib/modules.js
@@ -0,0 +1,1449 @@
+/*preamble-kriskowal
+ Copyright (c) 2002-2009 Kris Kowal <http://cixar.com/~kris.kowal>
+ MIT License
+*/
+
+/*
+ isolate the module loader in an enclosure by creating an
+ annonymous function and then--at the end of this file--
+ calling it.
+
+ also, take the evalGlobal function as an argument so that it can be
+ declared in global scope. this prevents the eval function
+ from inheriting variables from the modulesjs enclosure scope.
+*/
+(function (evalGlobal) {
+
+ /*
+ kernel module factory functions. this module bootstrapper script
+ can also be used as a module, since it contains module
+ factory functions that can be used to bootstrap platform-specific
+ modules. to that end, we export the module factory functions if
+ there is an ambient "exports" object
+ */
+ var factories = typeof exports == "undefined" ? {} : exports;
+ /* kernel module instances */
+ var modules = {};
+
+ /*
+ a rudimentary require function to jumpstart
+ the module system
+ */
+ var require = function (id) {
+ if (!Object.prototype.hasOwnProperty.call(modules, id)) {
+ var exports = {};
+ modules[id] = exports;
+ factories[id](require, exports, system);
+ }
+ return modules[id];
+ };
+
+ /* a permissive system for kernel modules */
+ var system = {
+ window: window,
+ evalGlobal: evalGlobal
+ };
+
+ factories.main = function (require, exports, system) {
+
+ var FILE = 'modules'; /* used to find the corresponding <script> */
+
+ var urls = require('urls');
+ var browser = require('browser');
+ var console = require('console');
+
+ var window = system.window;
+ var document = window.document;
+ system.print = console.print;
+ system.messages = console.messages;
+
+ /* grab the URL of modules.js relative to the containing page,
+ and remove the <script> tag that invoked this module loader
+ from the DOM for maximum stealth.
+ */
+ var PATH = urls.resolve(function () { /* enclosure */
+ var scripts = document.getElementsByTagName("script");
+ for (var i = 0; i < scripts.length; i++) {
+ var script = scripts[i];
+ if (browser.hasAttr(script, "src")) {
+ var src = script.getAttribute("src");
+ src = urls.parse(src);
+ if (src.file == FILE) {
+ script.parentNode.removeChild(script);
+ return urls.resolve(src, window.location.href);
+ }
+ }
+ }
+ throw new Error("could not find '" + FILE + "' <script>");
+ }());
+
+ /* wait for the DOM to be fully loaded */
+ browser.observeDomReady(function () {
+
+ var sandbox = require('sandbox');
+ sandbox.execUrl(PATH, PATH, system);
+
+ /* note for CSS that JavaScript is enabled, and ready */
+ document.body.className = document.body.className + ' javascript';
+
+ });
+
+ };
+
+ factories.sandbox = function (require, exports, system) {
+
+ var http = require('http');
+ var urls = require('urls');
+ var evalGlobal = system.evalGlobal;
+
+ exports.Loader = function (options) {
+ options = options || {};
+ var factories = options.factories || {};
+ var path = options.path;
+ var exportsLocal = options.exportsLocal;
+ var importsLocal = options.importsLocal;
+
+ var loader = {};
+
+ loader.fetch = function (id) {
+ var url = urls.resolve(id, path) + '.js';
+ return http.requestContent(url);
+ };
+
+ loader.evaluate = function (text, id) {
+ var iojs = /"use iojs";/.test(text);
+ /* optionally bring imports into scope with include */
+ if (importsLocal && !iojs)
+ text = "with (imports||{}) {" + text + "}";
+ /* optional bring exports into scope when assigned to exports */
+ if (exportsLocal && !iojs)
+ text = "with (exports) {" + text + "}";
+ /* safeguard "var" declarations from being
+ * applied to the "with" object in ES3-non-conformant browsers
+ * (really only Safari < 3) */
+ if ((importsLocal || exportsLocal) && !iojs)
+ text = "(function () {" + text + "}).apply(this, arguments)";
+ if (iojs)
+ text = "include = undefined; " + text;
+ text = (
+ "(function (require, exports, module, system, print, include, imports) {" +
+ text +
+ "})"
+ );
+ /* annotate with the module id */
+ if (id)
+ text = '/* ' + id + ' */ ' + text;
+ return evalGlobal(text);
+ };
+
+ loader.resolve = function (id, baseId) {
+ if (typeof id != "string")
+ throw new Error("module id '" + id + "' is not a String");
+ if (!baseId) {
+ baseId = path;
+ }
+ if (id.charAt(0) != ".") {
+ baseId = path;
+ }
+ return urls.resolve(id, baseId);
+ };
+
+ loader.load = function (id) {
+ if (!Object.prototype.hasOwnProperty.call(factories, id)) {
+ factories[id] = loader.evaluate(loader.fetch(id), id);
+ }
+ return factories[id];
+ };
+
+ loader.getPath = function () {
+ return path;
+ };
+
+ return loader;
+ };
+
+ exports.Sandbox = function (options) {
+ options = options || {};
+ var loader = options.loader || exports.Loader(options);
+ var sandboxSystem = options.system || system;
+ var modules = options.modules || {};
+ var debug = options.debug === true;
+ var main;
+
+ var debugDepth = 0;
+
+ var sandbox = function (id, baseId) {
+
+ id = loader.resolve(id, baseId);
+
+ /* populate memo with module instance */
+ if (!Object.prototype.hasOwnProperty.call(modules, id)) {
+
+
+ if (debug) {
+ debugDepth++;
+ var debugAcc = "";
+ for (var i = 0; i < debugDepth; i++) debugAcc += "+";
+ system.print(debugAcc + " " + id, 'module');
+ }
+
+ var exports = modules[id] = new Module();
+ var factory = loader.load(id);
+ var require = Require(id);
+ var module = {id: id};
+ var imports = {};
+ var include = Include(require, imports);
+ try {
+ factory.call(
+ exports,
+ require,
+ exports,
+ module,
+ sandboxSystem,
+ sandboxSystem.print,
+ include,
+ imports
+ );
+ } catch (exception) {
+ delete modules[id];
+ throw exception;
+ }
+
+ if (debug) {
+ var debugAcc = "";
+ for (var i = 0; i < debugDepth; i++) debugAcc += "-";
+ system.print(debugAcc + " " + id, 'module');
+ debugDepth--;
+ }
+
+
+ }
+
+ /* snapshot exports with requested bound methods */
+ var exports = modules[id];
+ var imports = new Module();
+ var importsUsed = false;
+ for (var name in exports) {
+ if (
+ exports[name] !== undefined &&
+ exports[name] !== null &&
+ exports[name].xChironCurryId
+ ) {
+ importsUsed = true;
+ imports[name] = (function (callback) {
+ var curried = function () {
+ return callback.apply(
+ this,
+ [baseId].concat(Array.prototype.slice.call(arguments, 0))
+ );
+ };
+ curried.xChironCurryId = callback;
+ return curried;
+ })(exports[name].xChironCurryId);
+ } else {
+ imports[name] = exports[name];
+ }
+ }
+
+ if (!importsUsed)
+ imports = exports;
+
+ return imports;
+ };
+
+ var Require = function (baseId) {
+ var require = function (id) {
+ try {
+ return sandbox(id, baseId);
+ } catch (exception) {
+ if (exception && !exception.message)
+ exception.message = 'Error';
+ try {
+ try {
+ eval("throw new Error()");
+ } catch (deliberate) {
+ if (deliberate.lineNumber !== undefined)
+ exception.message += ' at ' + (exception.lineNumber - deliberate.lineNumber + 1);
+ }
+ exception.message += ' in ' + baseId;
+ } catch (ignore) {
+ }
+ throw exception;
+ }
+ };
+
+ require.loader = loader;
+
+ /* extensions */
+ require.xChironModule = Module;
+ require.xChironId = baseId;
+ require.main = main;
+ require.xChironCurryId = function (callback) {
+ var curried = function () {
+ return callback.apply(
+ this,
+ [baseId].concat(Array.prototype.slice.call(arguments))
+ );
+ };
+ curried.curryId = callback;
+ return curried;
+ };
+ require.xChironIsLoaded = function (id) {
+ return Object.prototype.hasOwnProperty.call(modules, urls.resolve(id, baseId));
+ };
+ return require;
+ };
+
+ var Include = function (require, imports) {
+ return function (id) {
+ var exports = require(id);
+ for (var name in exports) {
+ imports[name] = exports[name];
+ };
+ return exports;
+ };
+ };
+
+ sandbox.main = function (id, baseId) {
+ main = loader.resolve(id, baseId);
+ return sandbox(main);
+ };
+
+ /* just for use as a base prototype */
+ var Module = function () {};
+
+ return sandbox;
+ };
+
+ /* execUrl is a utility method of this ipmlementation, not necessary
+ * for the interoperable modules specification. */
+ exports.execUrl = function (url, PATH, sandboxSystem) {
+
+ /* populate a list of initial ids from the query string of the PATH */
+ var mainIds = [];
+ var url = urls.parse(url);
+ if (url.query != "") {
+ mainIds = url.query.split("&");
+ if (/^path=(.*)/.test(mainIds[0])) {
+ PATH = urls.resolve(/^path=(.*)/.exec(mainIds[0])[1], system.window.location.href);
+ mainIds.shift();
+ }
+ }
+
+ /* load main modules */
+ sandboxSystem.moduleFactories = system.moduleFactories || {};
+ var sandbox = exports.Sandbox({
+ path: PATH,
+ importsLocal: true,
+ exportsLocal: true,
+ system: sandboxSystem//,
+ //factories: sandboxSystem.moduleFactories
+ });
+ for (var i = 0; i < mainIds.length; i++) {
+ try {
+ sandbox.main(mainIds[i], system.window.location.href);
+ } catch (exception) {
+ sandboxSystem.print('' + exception, 'error');
+ throw exception;
+ }
+ }
+
+ /* notify the user that all main modules have finished loading */
+ sandboxSystem.print('ready', 'info');
+
+ };
+
+ };
+
+ factories.environment = function (require, exports, system) {
+
+ if (system.window) {
+ var window = system.window;
+ var navigator = window.navigator;
+
+ exports.isIE = navigator.appVersion.indexOf("MSIE") >= 0;
+ exports.isSafari = navigator.appVersion.indexOf("Safari") >= 0;
+ exports.isOpera = !!window.opera;
+ }
+
+ };
+
+ factories.console = function (require, exports, system) {
+
+ var window = system.window;
+ var console = system.console || window.console;
+
+ /*** exports
+ */
+ exports.messages = [];
+
+ /*** print
+
+ accepts:
+ - a ``message`` and
+ - an optional ``label``.
+
+ The label, by convention, is one of `"log"``, ``"info"``,
+ ``"warn"``, or ``"error"``. Custom loggers treat labels like
+ ``"module"``, ``"pass"``, or ``"fail"``. Attempts to write
+ the message to `window.console`, progressively handling
+ `console` implementations that provide a function for the
+ given ``label``, or defaulting to `log` depending on
+ availability.
+
+ Also adds a ``[message, label]`` array to the end
+ of `messages`. ``label`` is one of ``"log"``,
+ ``"warn"``, ``"info"``, or ``"error"`` by convention.
+ In Safari, `log` writes to the Javascript debug console, which
+ is only available if you set the preference::
+
+ defaults write com.apple.Safari IncludeDebugMenu 1
+
+ Or in Safari 3::
+
+ defaults write com.apple.Safari IncludeDevelopMenu 1
+
+ And in Safari 4, the preference has been exposed
+ in the Advanced tab; check "Show Develop Menu".
+
+ In Firefox, you can get a debug console with Firebug,
+ http://getfirebug.com.
+
+ You can override the behavior of `log` by assigning
+ a different function to ``require('environment').log``
+ in any module.
+
+ Chiron can create a debug console for the purpose of
+ unit testing or page debugging. To debug a web page,
+ use `modules.js` to include `debug.js` on a page.
+ To run a unit test, view `run.html`, `lite.html`,
+ or `edit.html` with the `moduleId` of the unit test
+ as a query string.
+
+ */
+ exports.print = function (message, label) {
+
+ label = label || 'log';
+
+ /*
+ buffer messages so that console overrides
+ can retrieve and display them later.
+ */
+ exports.messages.push([message, label]);
+
+ /*
+ attempt to send the message to window.console if it
+ exists, progressively handling the availability
+ of a logging function crafted especially for the
+ requested label, or defaulting to 'log'.
+ */
+
+ if (console) {
+ if (console.print) {
+ console.print(message, label);
+ } else if (console[label]) {
+ console[label](message);
+ } else if (console.log) {
+ console.log(message);
+ }
+ }
+
+ };
+
+ };
+
+ factories.browser = function (require, exports, system) {
+
+ var environment = require('environment');
+ var window = system.window;
+ var document = window.document;
+ var top = window.top;
+
+ exports.hasAttr = function (element, key) {
+ if (element.hasAttribute) {
+ exports.hasAttr = function (element, key) {
+ return element.hasAttribute(key);
+ };
+ return exports.hasAttr(element, key);
+ } else {
+ exports.hasAttr = function (element, key) {
+ var node = element.getAttributeNode(key);
+ return node && node.specified;
+ };
+ return exports.hasAttr(element, key);
+ }
+ };
+
+ var isDomReady = false;
+ exports.observeDomReady = function (callback) {
+
+ /* call immediately if we've already noted a DOM
+ * ready event */
+ if (isDomReady)
+ return callback();
+
+ /* arrange to call back exactly once, even if multiple
+ * methods of detecting dom completion call "ready" */
+ var hasCalledBack = false;
+ var ready = function () {
+ if (hasCalledBack)
+ return;
+ hasCalledBack = true;
+ isDomReady = true;
+ callback();
+ };
+
+ /*
+ wait for the DOM and CSS to be ready, but don't wait
+ for images unless they're absolutely necessary.
+
+ ported from jQuery's event.js, with previous implementations
+ taking from similar sources, including Dean Edwards
+ and PPK.
+ */
+
+ /*
+ Opera uses DOMContentLoaded but has special code for
+ pending style sheets.
+ */
+ if (environment.isOpera)
+ document.addEventListener("DOMContentLoaded", function () {
+ if (isDomReady) return;
+ for (var i = 0; i < document.styleSheets.length; i++)
+ if (document.styleSheets[i].disabled) {
+ window.setTimeout(arguments.callee, 0);
+ return;
+ }
+ // and execute any waiting functions
+ ready();
+ }, false);
+
+ /* Mozilla and WebKit nightlies currently support this event */
+ if (document.addEventListener)
+ /* Use the handy event callback */
+ document.addEventListener("DOMContentLoaded", ready, false);
+
+ /*
+ If IE is used and is not in a frame,
+ continually check to see whether the document is ready.
+ */
+ if (environment.isIE && window == top) (function () {
+ if (isDomReady) return;
+ try {
+ /*
+ If IE is used, use the trick by Diego Perini
+ http://javascript.nwbox.com/IEContentLoaded/
+ */
+ document.documentElement.doScroll("left");
+ } catch (error) {
+ /*
+ using setTimeout with a 0 milisecond dellay
+ is effectively the equivalent of a "yield"
+ in a cooperative multi-task language.
+ This permits the browser to breathe before
+ we check whether we're ready again.
+ */
+ window.setTimeout(arguments.callee, 0);
+ return;
+ }
+ ready();
+ })();
+
+ if (environment.isSafari) {
+ (function () {
+ if (isDomReady) return;
+ if (
+ document.readyState != "loaded" &&
+ document.readyState != "complete"
+ ) {
+ window.setTimeout(arguments.callee, 0);
+ return;
+ }
+ var numStyles = document.getElementsByTagName('style').length;
+ var links = document.getElementsByTagName('link');
+ for (var i = 0; i < links.length; i++) {
+ var link = links[i];
+ numStyles += (
+ link.hasAttribute('rel') &&
+ link.getAttribute('rel').toLowerCase() ==
+ 'stylesheet'
+ );
+ }
+ if (document.styleSheets.length != numStyles) {
+ window.setTimeout(arguments.callee, 0);
+ return;
+ }
+ ready();
+ })();
+ }
+
+ /*
+ for other browsers, give up on the time saving
+ techniques and wait for all the images to load.
+ also, do this in other browsers just in case they missed
+ the boat.
+ */
+ if (window.onload) {
+ /* if there's already an onload listener, call ready after it,
+ preserving first-come-first-serve event observation */
+ window.onload = (function (onload) {
+ return function () {
+ onload.call(this);
+ ready();
+ };
+ })(window.onload);
+ } else {
+ window.onload = ready;
+ }
+
+ };
+
+ };
+
+ factories.urls = function (require, exports, system) {
+
+ /**** keys
+ members of a parsed URI object.
+ */
+ exports.keys = [
+ "url",
+ "protocol",
+ "authorityRoot",
+ "authority",
+ "userInfo",
+ "user",
+ "password",
+ "domain",
+ "domains",
+ "port",
+ "path",
+ "root",
+ "directory",
+ "directories",
+ "file",
+ "query",
+ "anchor"
+ ];
+
+ /**** expressionKeys
+ members of a parsed URI object that you get
+ from evaluting the strict regular expression.
+ */
+ exports.expressionKeys = [
+ "url",
+ "protocol",
+ "authorityRoot",
+ "authority",
+ "userInfo",
+ "user",
+ "password",
+ "domain",
+ "port",
+ "path",
+ "root",
+ "directory",
+ "file",
+ "query",
+ "anchor"
+ ];
+
+ /**** strictExpression
+ */
+ exports.strictExpression = new RegExp( /* url */
+ "^" +
+ "(?:" +
+ "([^:/?#]+):" + /* protocol */
+ ")?" +
+ "(?:" +
+ "(//)" + /* authorityRoot */
+ "(" + /* authority */
+ "(?:" +
+ "(" + /* userInfo */
+ "([^:@]*)" + /* user */
+ ":?" +
+ "([^:@]*)" + /* password */
+ ")?" +
+ "@" +
+ ")?" +
+ "([^:/?#]*)" + /* domain */
+ "(?::(\\d*))?" + /* port */
+ ")" +
+ ")?" +
+ "(" + /* path */
+ "(/?)" + /* root */
+ "((?:[^?#/]*/)*)" +
+ "([^?#]*)" + /* file */
+ ")" +
+ "(?:\\?([^#]*))?" + /* query */
+ "(?:#(.*))?" /*anchor */
+ );
+
+ /**** Parser
+ returns a URI parser function given
+ a regular expression that renders
+ `expressionKeys` and returns an `Object`
+ mapping all `keys` to values.
+ */
+ exports.Parser = function (expression) {
+ return function (url) {
+ if (typeof url == "undefined")
+ throw new Error("HttpError: URL is undefined");
+ if (typeof url != "string") return new Object(url);
+
+ var items = {};
+ var parts = expression.exec(url);
+
+ for (var i = 0; i < parts.length; i++) {
+ items[exports.expressionKeys[i]] = parts[i] ? parts[i] : "";
+ }
+
+ items.root = (items.root || items.authorityRoot) ? '/' : '';
+
+ items.directories = items.directory.split("/");
+ if (items.directories[items.directories.length - 1] == "") {
+ items.directories.pop();
+ }
+
+ /* normalize */
+ var directories = [];
+ for (var i = 0; i < items.directories.length; i++) {
+ var directory = items.directories[i];
+ if (directory == '.') {
+ } else if (directory == '..') {
+ if (directories.length && directories[directories.length - 1] != '..')
+ directories.pop();
+ else
+ directories.push('..');
+ } else {
+ directories.push(directory);
+ }
+ }
+ items.directories = directories;
+
+ items.domains = items.domain.split(".");
+
+ return items;
+ };
+ };
+
+ /**** parse
+ a strict URI parser.
+ */
+ exports.parse = exports.Parser(exports.strictExpression);
+
+ /**** format
+ accepts a parsed URI object and returns
+ the corresponding string.
+ */
+ exports.format = function (object) {
+ if (typeof(object) == 'undefined')
+ throw new Error("UrlError: URL undefined for urls#format");
+ if (object instanceof String || typeof(object) == 'string')
+ return object;
+ var domain =
+ object.domains ?
+ object.domains.join(".") :
+ object.domain;
+ var userInfo = (
+ object.user ||
+ object.password
+ ) ?
+ (
+ (object.user || "") +
+ (object.password ? ":" + object.password : "")
+ ) :
+ object.userInfo;
+ var authority = (
+ userInfo ||
+ domain ||
+ object.port
+ ) ? (
+ (userInfo ? userInfo + "@" : "") +
+ (domain || "") +
+ (object.port ? ":" + object.port : "")
+ ) :
+ object.authority;
+ var directory =
+ object.directories ?
+ object.directories.join("/") :
+ object.directory;
+ var path =
+ directory || object.file ?
+ (
+ (directory ? directory + "/" : "") +
+ (object.file || "")
+ ) :
+ object.path;
+ return (
+ (object.protocol ? object.protocol + ":" : "") +
+ (authority ? "//" + authority : "") +
+ (object.root || (authority && path) ? "/" : "") +
+ (path ? path : "") +
+ (object.query ? "?" + object.query : "") +
+ (object.anchor ? "#" + object.anchor : "")
+ ) || object.url || "";
+ };
+
+ /**** resolveObject
+ returns an object representing a URL resolved from
+ a relative location and a base location.
+ */
+ exports.resolveObject = function (relative, base) {
+ if (!base)
+ return relative;
+
+ base = exports.parse(base);
+ relative = exports.parse(relative);
+
+ if (relative.url == "")
+ return base;
+
+ delete base.url;
+ delete base.authority;
+ delete base.domain;
+ delete base.userInfo;
+ delete base.path;
+ delete base.directory;
+
+ if (
+ relative.protocol && relative.protocol != base.protocol ||
+ relative.authority && relative.authority != base.authority
+ ) {
+ base = relative;
+ } else {
+ if (relative.root) {
+ base.directories = relative.directories;
+ } else {
+
+ var directories = relative.directories;
+ for (var i = 0; i < directories.length; i++) {
+ var directory = directories[i];
+ if (directory == ".") {
+ } else if (directory == "..") {
+ if (base.directories.length) {
+ base.directories.pop();
+ } else {
+ base.directories.push('..');
+ }
+ } else {
+ base.directories.push(directory);
+ }
+ }
+
+ if (relative.file == ".") {
+ relative.file = "";
+ } else if (relative.file == "..") {
+ base.directories.pop();
+ relative.file = "";
+ }
+ }
+ }
+
+ if (relative.root)
+ base.root = relative.root;
+ if (relative.protcol)
+ base.protocol = relative.protocol;
+ if (!(!relative.path && relative.anchor))
+ base.file = relative.file;
+ base.query = relative.query;
+ base.anchor = relative.anchor;
+
+ return base;
+ };
+
+ /**** relativeObject
+ returns an object representing a relative URL to
+ a given target URL from a source URL.
+ */
+ exports.relativeObject = function (target, base) {
+ target = exports.parse(target);
+ base = exports.parse(base);
+
+ delete target.url;
+
+ if (
+ target.protocol == base.protocol &&
+ target.authority == base.authority
+ ) {
+ delete target.protocol;
+ delete target.authority;
+ delete target.userInfo;
+ delete target.user;
+ delete target.password;
+ delete target.domain;
+ delete target.domains;
+ delete target.port;
+ if (
+ !!target.root == !!base.root && !(
+ target.root &&
+ target.directories[0] != base.directories[0]
+ )
+ ) {
+ delete target.path;
+ delete target.root;
+ delete target.directory;
+ while (
+ base.directories.length &&
+ target.directories.length &&
+ target.directories[0] == base.directories[0]
+ ) {
+ target.directories.shift();
+ base.directories.shift();
+ }
+ while (base.directories.length) {
+ base.directories.shift();
+ target.directories.unshift('..');
+ }
+
+ if (!target.root && !target.directories.length && !target.file && base.file)
+ target.directories.push('.');
+
+ if (base.file == target.file)
+ delete target.file;
+ if (base.query == target.query)
+ delete target.query;
+ if (base.anchor == target.anchor)
+ delete target.anchor;
+ }
+ }
+
+ return target;
+ };
+
+ /**** resolve
+ returns a URL resovled to a relative URL from a base URL.
+ */
+ exports.resolve = function (relative, base) {
+ return exports.format(exports.resolveObject(relative, base));
+ };
+
+ /**** relative
+ returns a relative URL to a target from a source.
+ */
+ exports.relative = function (target, base) {
+ return exports.format(exports.relativeObject(target, base));
+ };
+
+ };
+
+ factories.http = function (require, exports, system) {
+
+ var urls = require('urls');
+ var environment = require('environment');
+ var window = system.window;
+
+ /**** requestContent
+ returns the text at a given URL using an HTTP
+ request.
+ supports continuation passing form for asynchronous
+ requests.
+ */
+ exports.requestContent = function (url, observer) {
+ if (observer !== undefined) {
+ return exports.request(url, function (response) {
+ if (response.isOk())
+ observer(response.getContent());
+ });
+ } else {
+ var response = exports.request(url);
+ if (response.isError())
+ throw new Error("HttpError: " + url + " status " + response.getStatus());
+ return response.getContent();
+ }
+ };
+
+ /**** request
+ sends an HTTP request to a given URL and returns
+ the response.
+ supports continuation passing form for asynchronous
+ requests.
+ */
+ exports.request = function (url, observer) {
+ var request = exports.Request();
+ var response = request.getResponse();
+
+ url = urls.resolve(url, system.window.location.href);
+
+ if (observer)
+ request.observe("ok", observer);
+
+ request.open("GET", url, !!observer);
+
+ try {
+ request.send();
+ } catch (exception) {
+ request.abort();
+ throw new Error('HttpError: "' + url + '": ' + exception);
+ }
+
+ if (observer !== undefined) {
+ return request;
+ } else {
+ return response;
+ }
+
+ };
+
+ /*todo
+ Look deeper into dojo/src/hostenv_browser.js for
+ _blockAsync lock to prevent eternal hanging in KHTML
+ */
+
+ /**** Request
+ returns a wrapped HTTP Request object.
+ */
+ exports.Request = function () {
+ /* this line permits the user to create a request with
+ * either new Request() or Request(). internally,
+ * we just use the Request() so that Request can be
+ * overloaded later in HTTP to be a type constructor
+ * function instead of a prototype constructor */
+ if (this == exports) return new exports.Request();
+
+ var self = this;
+ var method, url, asynchronous, user, password;
+ var realRequest = exports.NativeRequest();
+ var response = exports.Response(realRequest);
+ var isOpen;
+ var readyStateChanged;
+ var timeout;
+ var timeoutHandle;
+ var aborted;
+
+ var readyObservers = [];
+ var okObservers = [];
+ var errorObservers = [];
+ var warnObservers = [];
+ var timeoutObservers = [];
+
+ /***** toString
+ */
+ self.toString = function () {return "[object HttpRequest]"};
+
+ /***** getResponse
+ */
+ self.getResponse = function () {
+ return response;
+ };
+
+ var signal = function (response, observers) {
+ while (observers.length) {
+ var observer = observers.shift();
+ observer(response);
+ }
+ };
+
+ /***** pogress
+ an event function that the Request calls when it
+ receives a chunk of content.
+ */
+ self.progress = function () {
+ /* necessary: this function becomes an observable signal */
+ };
+
+ /***** ready
+ an event function that the Request calls when
+ the Reponse is ready.
+ */
+ self.ready = function () {
+ signal(response, readyObservers);
+ };
+
+ /***** ok
+ an event function that the Request calls when a Response
+ is ready and all went well. Note that Safari and FireFox, at least,
+ will fire this event even when the connection is abruptly
+ terminated by the server, reporting a 200 status and
+ an empty response content.
+ */
+ self.ok = function () {
+ signal(response, okObservers);
+ };
+
+ /***** error
+ an event function that the Request calls when a Reponse
+ is completed but failed to retrieve the requested content.
+ */
+ self.error = function () {
+ signal(response, errorObservers);
+ };
+
+ /***** warn
+ an event function that the Request calls when
+ something is amiss with message.
+ */
+ self.warn = function (message) {
+ warn(message);
+ signal(response, warnObservers);
+ };
+
+ /***** timeout
+ an event function that Request calls when a request
+ times out. The default behavior is to invoke an error.
+ */
+ self.timeout = function () {
+ signal(response, timeoutObservers);
+ };
+
+ /***** observe
+ permits a user to observe `ready`, `ok`,
+ `error`, and `warn` events with a handler
+ function. Observing any event on a `Request`
+ causes the `open` and `send` to implicitly become
+ asynchronous.
+ */
+ self.observe = function (eventName, observer) {
+ asynchronous = true;
+ if (eventName == "ready") readyObservers.push(observer);
+ else if (eventName == "ok") okObservers.push(observer);
+ else if (eventName == "error") errorObservers.push(observer);
+ else if (eventName == "warn") warnObservers.push(observer);
+ else if (eventName == "timeout") timeoutObservers.push(observer);
+ else throw new Error(
+ "HttpError: event name '" + eventName + "' " +
+ "is not recognized"
+ );
+ };
+
+ /***** setHeader
+ */
+ self.setHeader = function (key, value) {
+ realRequest.setRequestHeader(key, value);
+ };
+
+ /***** isOpen
+ */
+ self.isOpen = function () {
+ return isOpen;
+ };
+
+ /***** isSent
+ */
+ self.isSent = function () {
+ return realRequest.readyState > 0;
+ };
+
+ /***** getTimeout
+ */
+ self.getTimeout = function () {
+ return timeout;
+ };
+
+ /***** setTimeout
+ */
+ self.setTimeout = function (value) {
+ timeout = value;
+ };
+
+ /***** open
+
+ Accepts
+
+ - ``method``, an HTTP request method, for example,
+ ``GET``, ``POST``, ``PROPFIND`` and others.
+ - ``url``, a web location string
+ - ``synchronous``, whether ``send`` will block until completed,
+ for example, ``synchronous``, ``asynchronous``.
+ - ``user``, an optional HTTP user name.
+ - ``password``, an optional HTTP password.
+
+ */
+ self.open = function (_method, _url, _asynchronous, _user, _password) {
+ try {
+ return realRequest.open(
+ method = _method,
+ url = _url,
+ asynchronous = _asynchronous,
+ user = _user,
+ password = _password
+ );
+ } finally {
+ isOpen = true;
+ }
+ };
+
+ /***** send
+ Accepts an optional ``content`` argument for requests like ``POST`` method.
+ */
+ self.send = function (content) {
+
+ realRequest.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+
+ if (!content) {
+ content = "";
+ }
+
+ if (timeout !== undefined) {
+ timeoutHandle = window.setTimeout(function () {
+ timeoutHandle = undefined;
+ var status = response.getStatus();
+ if (status != 200 || status === undefined) {
+ self.timeout();
+ self.abort();
+ }
+ }, timeout);
+ }
+
+ return realRequest.send(content);
+ };
+
+ /***** abort
+ */
+ self.abort = function () {
+ if (timeoutHandle !== undefined)
+ window.clearTimeout(timeoutHandle);
+ aborted = true;
+ return realRequest.abort();
+ };
+
+ realRequest.onreadystatechange = function () {
+ readyStateChanged = true;
+
+ self.progress();
+
+ if (aborted) {
+ free();
+ } else if (realRequest.readyState == 4) {
+ try {
+
+ self.ready(response);
+
+ if (response.isOk()) {
+ self.ok(response);
+ } else {
+ self.error(response);
+ }
+
+ } catch (exception) {
+ system.print(exception.message || exception, 'error');
+ }
+ free();
+ }
+ };
+
+ var free = function () {
+ delete realRequest['onreadystatechange'];
+ realRequest.onreadystatechange = undefined;
+ };
+
+ return self;
+ };
+
+ /**** Response
+ returns a wrapped HTTP Response object.
+ */
+ exports.Response = function (realRequest) {
+ /* this line permits the user to create a request with
+ * either new Respones() or Response(). internally,
+ * we just use the Response() so that Response can be
+ * overloaded later in HTTP to be a type constructor
+ * function instead of a prototype constructor */
+ if (this == exports) return new exports.Response(realRequest);
+
+ var self = this;
+
+ /* this init function doesn't get invoked until Response becomes
+ * a type in HTTP. so, this method is merely for the future. */
+ self.init = function (realRequestValue) {
+ realRequest = realRequestValue;
+ };
+
+ /***** isReady
+ whether the request is finished. This indicates
+ whether you can call `getStatus`
+ */
+ self.isReady = function () {
+ return realRequest.readyState == 4;
+ };
+
+ /***** getStatus
+ returns the HTTP response code. Local files
+ return 0. Returns ``undefined`` if the
+ underlying XML HTTP request throws an exception,
+ `getStatus` returns ``undefined``.
+ */
+ self.getStatus = function () {
+ /* one wouldn't think this were necessary.
+ * one would be wrong. */
+ try {
+ return realRequest.status;
+ } catch (exception) {
+ return undefined;
+ }
+ };
+
+ /***** isOk
+ returns whether a request had a valid response.
+ This usually is indicative of a 200 HTTP response
+ code, but there are variations among browsers.
+
+ HTTP Status codes in the interval [200, 300] are all legal
+ HTTP Ok responses.
+
+ In Firefox and Safari 3, local files acquired with an HTTP request
+ have a status code of 0.
+
+ In Safari 2, local files acquired with an asynchronous HTTP
+ request have a status of undefined.
+
+ In Safari, a response with no content causes a status
+ of `undefined`.
+
+ Konqueror requires acceptance of 304, "using cache",
+ according to dojo/src/hostenv_browser.js
+
+ According to jQuery issue #1450, IE sometimes 1223
+ instead of 204.
+ */
+ self.isOk = function () {
+ var status = self.getStatus();
+ return (
+ /* usually */
+ status >= 200 && status < 300 ||
+ /* Firefox and Safari 3 file:// */
+ status == 0 ||
+ /* Konqueror using cache */
+ status == 304 ||
+ /* IE bug 1223 */
+ status == 1223 ||
+ /* Safari 2 asynchronous file:// and
+ all Safari for no file content */
+ (environment.isSafari && status == undefined && (
+ /^file:\/\//.test(url) ||
+ realRequest.responseText == ""
+ ))
+ );
+ };
+
+ /***** isError
+ */
+ self.isError = function () {
+ return !self.isOk();
+ };
+
+ /***** getContent
+ */
+ self.getContent = function () {
+ return realRequest.responseText;
+ };
+
+ /***** getDocument
+ */
+ self.getDocument = function () {
+ return self.getXml().documentElement;
+ };
+
+ /***** getHeader
+ */
+ self.getHeader = function (key) {
+ return realRequest.getResponseHeader(key);
+ };
+
+ /***** hasHeader
+ */
+ self.hasHeader = function (key) {
+ return realRequest.getResponseHeader(key) != undefined;
+ };
+
+ /***** getHeaders
+ */
+ self.getHeaders = function () {
+ var headers = realRequest.getAllResponseHeaders();
+ if (!headers) return {};
+ return headers;
+ };
+
+ /***** len
+ */
+ self.len = function () {
+ return realRequest.responseText.length;
+ };
+
+ };
+
+ /*** NativeRequest
+ returns an XMLHttpRequest in most browsers.
+ */
+ /* Based on dojo/src/hostenv_browser.js */
+
+ exports.NativeRequest = function () {
+ /*
+
+ subscribes to the lazy function definition pattern, since it
+ redefines itself as the first method that works on the first
+ call.
+
+ Some other AJAX implementations check
+ - Msxml2.XMLHTTP.6.0
+ - Msxml2.XMLHTTP.5.0
+ - Msxml2.XMLHTTP.4.0
+ - Msxml2.XMLHTTP.3.0
+ - Microsoft.XMLHTTP
+
+ Microsoft.XMLHTTP is an older name-space, but is equivalent to
+ the more lucid Msxml2.XMLHTTP.3.0 and only available when the
+ latter is available too.
+
+ Msxml2.XMLHTTP.4.0 has been superseded and is currently only
+ intended to support legacy applications.
+
+ Msxml2.XMLHTTP.5.0 was shipped with MS Office 2003 and was
+ intended for Office applications. IE7 has this component off
+ by default in the Internet zone, leading to canary-yellow
+ verification dialogs.
+
+ Msxml2.XMLHTTP.6.0 is currently the standard MS is pushing.
+ I originally left out 6.0 since it would increase the burden
+ of testing for functionality that cannot be trusted to work
+ in all browsers.
+ However, I've taken Jonathan Snook's advice to check for
+ Microsoft's latest and greatest.
+
+ see: http://snook.ca/archives/javascript/xmlhttprequest_activex_ie/
+
+ Msxml2.XMLHTTP.3.0 is the most widely deployed version and is
+ serviced regularly with the OS for security and other reasons.
+ It is MS's preferred alternative to MSXML6.
+
+ see: http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx
+
+ see: http://www.telerik.com/documents/AJAX%20Page/Ajax-Part1.pdf page 3
+
+ */
+
+ var trials = [
+ function () {return new window.XMLHttpRequest()},
+ function () {return new window.ActiveXObject("Msxml2.XMLHTTP.6.0")},
+ function () {return new window.ActiveXObject("Msxml2.XMLHTTP.3.0")},
+ function () {throw new Error("No HTTP Request object available for your system.")}
+ ];
+
+ var trial, result, exception;
+ for (var i = 0; i < trials.length; i++) {
+ exception = undefined;
+ /* redeclare for posterity */
+ exports.NativeRequest = trial = trials[i];
+ try {
+ result = trial();
+ } catch (trialException) {
+ exception = trialException;
+ continue;
+ }
+ break;
+ }
+
+ if (exception) throw exception;
+ else return result;
+ };
+
+ };
+
+ if (typeof exports == "undefined") {
+ require('main');
+ }
+
+/* end of module enclosure */
+})(function () {
+ return eval(arguments[0]);
+});
+
diff --git a/utils/platforms/browser/lib/system.js b/utils/platforms/browser/lib/system.js
new file mode 100755
index 0000000..d50a5cf
--- /dev/null
+++ b/utils/platforms/browser/lib/system.js
@@ -0,0 +1,3 @@
+exports.print = function () {
+ system.print.apply(system, arguments);
+};
diff --git a/utils/platforms/default/lib/binary-platform.js b/utils/platforms/default/lib/binary-platform.js
new file mode 100755
index 0000000..3bc2425
--- /dev/null
+++ b/utils/platforms/default/lib/binary-platform.js
@@ -0,0 +1,53 @@
+exports.B_LENGTH = function(bytes) {
+ return bytes.length;
+}
+
+exports.B_ALLOC = function(length) {
+ var bytes = new Array(length);
+ for (var i = 0; i < length; i++)
+ bytes[i] = 0;
+ return bytes;
+}
+
+exports.B_FILL = function(bytes, from, to, value) {
+ for (var i = from; i < to; i++)
+ bytes[i] = value;
+}
+
+exports.B_COPY = function(src, srcOffset, dst, dstOffset, length) {
+ for (var i = 0; i < length; i++)
+ dst[dstOffset+i] = src[srcOffset+i];
+}
+
+exports.B_GET = function(bytes, index) {
+ return bytes[index];
+}
+
+exports.B_SET = function(bytes, index, value) {
+ return bytes[index] = value;
+}
+
+var DEFAULT_ENCODING = "UTF-8";
+
+exports.B_DECODE = function(bytes, offset, length, codec) {
+ var newBytes = exports.B_TRANSCODE(bytes, offset, length, codec, DEFAULT_ENCODING);
+ return exports.B_DECODE_DEFAULT(newBytes, 0, exports.B_LENGTH(newBytes));
+}
+
+exports.B_DECODE_DEFAULT = function(bytes, offset, length) {
+ throw "NYI";
+}
+
+exports.B_ENCODE = function(string, codec) {
+ var bytes = exports.B_ENCODE_DEFAULT(string);
+ return exports.B_TRANSCODE(bytes, 0, exports.B_LENGTH(bytes), DEFAULT_ENCODING, codec);
+}
+
+exports.B_ENCODE_DEFAULT = function(string) {
+ throw "NYI";
+}
+
+exports.B_TRANSCODE = function(bytes, offset, length, sourceCodec, targetCodec) {
+ throw "NYI";
+}
+
diff --git a/utils/platforms/default/lib/binary.js b/utils/platforms/default/lib/binary.js
new file mode 100755
index 0000000..7c19b80
--- /dev/null
+++ b/utils/platforms/default/lib/binary.js
@@ -0,0 +1,719 @@
+/* Binary */
+
+var B_ALLOC = require("binary-platform").B_ALLOC,
+ B_LENGTH = require("binary-platform").B_LENGTH,
+ B_GET = require("binary-platform").B_GET,
+ B_SET = require("binary-platform").B_SET,
+ B_FILL = require("binary-platform").B_FILL,
+ B_COPY = require("binary-platform").B_COPY,
+ B_DECODE = require("binary-platform").B_DECODE,
+ B_ENCODE = require("binary-platform").B_ENCODE,
+ B_DECODE_DEFAULT = require("binary-platform").B_DECODE_DEFAULT,
+ B_ENCODE_DEFAULT = require("binary-platform").B_ENCODE_DEFAULT,
+ B_TRANSCODE = require("binary-platform").B_TRANSCODE;
+
+var Binary = exports.Binary = function() {
+ // this._bytes
+ // this._offset
+ // this._length
+};
+
+Binary.prototype.__defineGetter__("length", function() { return this._length; });
+Binary.prototype.__defineSetter__("length", function(length) { print("x trying to set length: " + length); });
+
+// toArray() - n array of the byte values
+// toArray(charset) - an array of the code points, decoded
+Binary.prototype.toArray = function(codec) {
+ if (arguments.length === 0) {
+ var array = new Array(this._length);
+
+ for (var i = 0; i < this.length; i++)
+ array[i] = this.get(i);
+
+ return array;
+ }
+ else if (arguments.length === 1) {
+ var string = new java.lang.String(this._bytes, this._offset, this._length, codec),
+ length = string.length(),
+ array = new Array(length);
+
+ for (var i = 0; i < length; i++)
+ array[i] = string.codePointAt(i);
+
+ return array;
+ }
+ else
+ throw new Error("Illegal arguments to toArray()");
+};
+
+// toByteArray() - just a copy
+// toByteArray(sourceCharset, targetCharset) - transcoded
+Binary.prototype.toByteArray = function(sourceCodec, targetCodec) {
+ if (arguments.length < 2)
+ return new ByteArray(this);
+ else if (arguments.length === 2 && typeof sourceCodec === "string" && typeof targetCodec === "string") {
+ var bytes = B_TRANSCODE(this._bytes, this._offset, this._length, sourceCodec, targetCodec);
+ return new ByteArray(bytes, 0, B_LENGTH(bytes));
+ }
+
+ throw new Error("Illegal arguments to ByteArray toByteArray");
+};
+
+// toByteString() - byte for byte copy
+// toByteString(sourceCharset, targetCharset) - transcoded
+Binary.prototype.toByteString = function(sourceCodec, targetCodec) {
+ if (arguments.length < 2)
+ return new ByteString(this);
+ else if (arguments.length === 2 && typeof sourceCodec === "string" && typeof targetCodec === "string") {
+ var bytes = B_TRANSCODE(this._bytes, this._offset, this._length, sourceCodec, targetCodec);
+ return new ByteString(bytes, 0, B_LENGTH(bytes));
+ }
+
+ throw new Error("Illegal arguments to ByteArray toByteString");
+};
+
+// decodeToString()
+// decodeToString(charset) - returns a String from its decoded bytes in a given charset. If no charset is provided, or if the charset is "undefined", assumes the default system encoding.
+// decodeToString(number) - returns a String from its decoded bytes in a given base, like 64, 32, 16, 8, 2
+Binary.prototype.decodeToString = function(charset) {
+ if (charset) {
+ if (typeof charset == "number")
+ return require("base" + charset).encode(this);
+ else if (charset.begins("base"))
+ return require(charset).encode(this);
+ else
+ return B_DECODE(this._bytes, this._offset, this._length, charset);
+ }
+ return B_DECODE_DEFAULT(this._bytes, this._offset, this._length);
+};
+
+// get(offset) - Return the byte at offset as a Number.
+Binary.prototype.get = function(offset) {
+ if (offset < 0 || offset >= this._length)
+ return NaN;
+
+ //var b = this._bytes[this._offset + offset];
+ //return (b >= 0) ? b : -1 * ((b ^ 0xFF) + 1);
+ return B_GET(this._bytes, this._offset + offset)
+};
+
+Binary.prototype.indexOf = function(byteValue, start, stop) {
+ // HACK: use ByteString's slice since we know we won't be modifying result
+ var array = ByteString.prototype.slice.apply(this, [start, stop]).toArray(),
+ result = array.indexOf(byteValue);
+ return (result < 0) ? -1 : result + (start || 0);
+};
+
+Binary.prototype.lastIndexOf = function(byteValue, start, stop) {
+ // HACK: use ByteString's slice since we know we won't be modifying result
+ var array = ByteString.prototype.slice.apply(this, [start, stop]).toArray(),
+ result = array.lastIndexOf(byteValue);
+ return (result < 0) ? -1 : result + (start || 0);
+};
+
+// valueOf()
+Binary.prototype.valueOf = function() {
+ return this;
+};
+
+/* ByteString */
+
+var ByteString = exports.ByteString = function() {
+ if (!(this instanceof ByteString)) {
+ if (arguments.length == 0)
+ return new ByteString();
+ if (arguments.length == 1)
+ return new ByteString(arguments[0]);
+ if (arguments.length == 2)
+ return new ByteString(arguments[0], arguments[1]);
+ if (arguments.length == 3)
+ return new ByteString(arguments[0], arguments[1], arguments[2]);
+ }
+
+ // ByteString() - Construct an empty byte string.
+ if (arguments.length === 0) {
+ this._bytes = B_ALLOC(0); // null;
+ this._offset = 0;
+ this._length = 0;
+ }
+ // ByteString(byteString) - Copies byteString.
+ else if (arguments.length === 1 && arguments[0] instanceof ByteString) {
+ return arguments[0];
+ }
+ // ByteString(byteArray) - Use the contents of byteArray.
+ else if (arguments.length === 1 && arguments[0] instanceof ByteArray) {
+ var copy = arguments[0].toByteArray();
+ this._bytes = copy._bytes;
+ this._offset = copy._offset;
+ this._length = copy._length;
+ }
+ // ByteString(arrayOfNumbers) - Use the numbers in arrayOfNumbers as the bytes.
+ else if (arguments.length === 1 && Array.isArray(arguments[0])) {
+ var array = arguments[0];
+ this._bytes = B_ALLOC(array.length);
+ for (var i = 0; i < array.length; i++) {
+ var b = array[i];
+ // If any element is outside the range 0...255, an exception (TODO) is thrown.
+ if (b < -0x80 || b > 0xFF)
+ throw new Error("ByteString constructor argument Array of integers must be -128 - 255 ("+b+")");
+ // Java "bytes" are interpreted as 2's complement
+ //this._bytes[i] = (b < 128) ? b : -1 * ((b ^ 0xFF) + 1);
+ B_SET(this._bytes, i, b);
+ }
+ this._offset = 0;
+ this._length = B_LENGTH(this._bytes);
+ }
+ // ByteString(string, charset) - Convert a string. The ByteString will contain string encoded with charset.
+ else if ((arguments.length === 1 || (arguments.length === 2 && arguments[1] === undefined)) && typeof arguments[0] === "string") {
+ this._bytes = B_ENCODE_DEFAULT(arguments[0]);
+ this._offset = 0;
+ this._length = B_LENGTH(this._bytes);
+ }
+ else if (arguments.length === 2 && typeof arguments[0] === "string" && typeof arguments[1] === "string") {
+ this._bytes = B_ENCODE(arguments[0], arguments[1]);
+ this._offset = 0;
+ this._length = B_LENGTH(this._bytes);
+ }
+ // private: ByteString(bytes, offset, length)
+ else if (arguments.length === 3 && typeof arguments[1] === "number" && typeof arguments[2] === "number") {
+ this._bytes = arguments[0];
+ this._offset = arguments[1];
+ this._length = arguments[2];
+ }
+ else
+ throw new Error("Illegal arguments to ByteString constructor: [" +
+ Array.prototype.join.apply(arguments, [","]) + "] ("+arguments.length+")");
+
+ //seal(this);
+};
+
+ByteString.prototype = new Binary();
+
+ByteString.prototype.__defineGetter__("length", function() { return this._length; });
+ByteString.prototype.__defineSetter__("length", function(length) {});
+
+// toByteArray() - Returns a byte for byte copy in a ByteArray.
+// toByteArray(sourceCharset, targetCharset) - Returns a transcoded copy in a ByteArray.
+// - implemented on Binary
+
+// toByteString() - Returns itself, since there's no need to copy an immutable ByteString.
+// toByteString(sourceCharset, targetCharset) - Returns a transcoded copy.
+// - implemented on Binary
+
+// toArray() - Returns an array containing the bytes as numbers.
+// toArray(charset) - Returns an array containing the decoded Unicode code points.
+// - implemented on Binary
+
+// toString()
+ByteString.prototype.toString = function(charset) {
+ if (charset)
+ return this.decodeToString(charset);
+
+ return "[ByteString "+this.length+"]";
+};
+
+// decodeToString(charset) - Returns the decoded ByteArray as a string.
+// - implemented on Binary
+
+ByteString.prototype.byteAt =
+ByteString.prototype.charAt = function(offset) {
+ var byteValue = this.get(offset);
+
+ if (isNaN(byteValue))
+ return new ByteString();
+
+ return new ByteString([byteValue]);
+};
+
+// indexOf() - implemented on Binary
+// lastIndexOf() - implemented on Binary
+
+// charCodeAt(offset)
+ByteString.prototype.charCodeAt = Binary.prototype.get;
+
+// get(offset) - implemented on Binary
+
+// byteAt(offset) ByteString - implemented on Binary
+// charAt(offset) ByteString - implemented on Binary
+
+// split(delimiter, [options])
+ByteString.prototype.split = function(delimiters, options) {
+ var options = options || {},
+ count = options.count === undefined ? -1 : options.count,
+ includeDelimiter = options.includeDelimiter || false;
+
+ // standardize delimiters into an array of ByteStrings:
+ if (!Array.isArray(delimiters))
+ delimiters = [delimiters];
+
+ delimiters = delimiters.map(function(delimiter) {
+ if (typeof delimiter === "number")
+ delimiter = [delimiter];
+ return new ByteString(delimiter);
+ });
+
+ var components = [],
+ startOffset = this._offset,
+ currentOffset = this._offset;
+
+ // loop until there's no more bytes to consume
+ bytes_loop :
+ while (currentOffset < this._offset + this._length) {
+
+ // try each delimiter until we find a match
+ delimiters_loop :
+ for (var i = 0; i < delimiters.length; i++) {
+ var d = delimiters[i];
+
+ for (var j = 0; j < d._length; j++) {
+ // reached the end of the bytes, OR bytes not equal
+ if (currentOffset + j > this._offset + this._length ||
+ B_GET(this._bytes, currentOffset + j) !== B_GET(d._bytes, d._offset + j)) {
+ continue delimiters_loop;
+ }
+ }
+
+ // push the part before the delimiter
+ components.push(new ByteString(this._bytes, startOffset, currentOffset - startOffset));
+
+ // optionally push the delimiter
+ if (includeDelimiter)
+ components.push(new ByteString(this._bytes, currentOffset, d._length))
+
+ // reset the offsets
+ startOffset = currentOffset = currentOffset + d._length;
+
+ continue bytes_loop;
+ }
+
+ // if there was no match, increment currentOffset to try the next one
+ currentOffset++;
+ }
+
+ // push the remaining part, if any
+ if (currentOffset > startOffset)
+ components.push(new ByteString(this._bytes, startOffset, currentOffset - startOffset));
+
+ return components;
+};
+
+// slice()
+// slice(begin)
+// slice(begin, end)
+ByteString.prototype.slice = function(begin, end) {
+ if (begin === undefined)
+ begin = 0;
+ else if (begin < 0)
+ begin = this._length + begin;
+
+ if (end === undefined)
+ end = this._length;
+ else if (end < 0)
+ end = this._length + end;
+
+ begin = Math.min(this._length, Math.max(0, begin));
+ end = Math.min(this._length, Math.max(0, end));
+
+ return new ByteString(this._bytes, this._offset + begin, end - begin);
+};
+
+// substr(start)
+// substr(start, length)
+ByteString.prototype.substr = function(start, length) {
+ if (start !== undefined) {
+ if (length !== undefined)
+ return this.slice(start);
+ else
+ return this.slice(start, start + length);
+ }
+ return this.slice();
+};
+
+// substring(first)
+// substring(first, last)
+ByteString.prototype.substring = function(from, to) {
+ if (from !== undefined) {
+ if (to !== undefined)
+ return this.slice(Math.max(Math.min(begin, this._length), 0));
+ else
+ return this.slice(Math.max(Math.min(begin, this._length), 0),
+ Math.max(Math.min(end, this._length), 0));
+ }
+ return this.slice();
+};
+
+// [] ByteString - TODO
+
+// toSource()
+ByteString.prototype.toSource = function() {
+ return "ByteString(["+this.toArray().join(",")+"])";
+};
+
+/* ByteArray */
+
+// ByteArray() - New, empty ByteArray.
+// ByteArray(length) - New ByteArray filled with length zero bytes.
+// ByteArray(byteArray) - Copy byteArray.
+// ByteArray(byteString) - Copy contents of byteString.
+// ByteArray(arrayOfBytes) - Use numbers in arrayOfBytes as contents.
+// Throws an exception if any element is outside the range 0...255 (TODO).
+// ByteArray(string, charset) - Create a ByteArray from a Javascript string, the result being encoded with charset.
+var ByteArray = exports.ByteArray = function() {
+ if (!this instanceof ByteArray) {
+ if (arguments.length == 0)
+ return new ByteArray();
+ if (arguments.length == 1)
+ return new ByteArray(arguments[0]);
+ if (arguments.length == 2)
+ return new ByteArray(arguments[0], arguments[1]);
+ if (arguments.length == 3)
+ return new ByteArray(arguments[0], arguments[1], arguments[2]);
+ }
+
+ // ByteArray() - New, empty ByteArray.
+ if (arguments.length === 0) {
+ this._bytes = B_ALLOC(0); // null;
+ this._offset = 0;
+ this._length = 0;
+ }
+ // ByteArray(length) - New ByteArray filled with length zero bytes.
+ else if (arguments.length === 1 && typeof arguments[0] === "number") {
+ this._bytes = B_ALLOC(arguments[0]); // null;
+ this._offset = 0;
+ this._length = B_LENGTH(this._bytes);
+ }
+ // ByteArray(byteArray) - Copy byteArray.
+ // ByteArray(byteString) - Copy contents of byteString.
+ else if (arguments.length === 1 && (arguments[0] instanceof ByteArray || arguments[0] instanceof ByteString)) {
+ var byteArray = new ByteArray(arguments[0]._length);
+ B_COPY(arguments[0]._bytes, arguments[0]._offset, byteArray._bytes, byteArray._offset, byteArray._length);
+ return byteArray;
+ }
+ // ByteArray(arrayOfBytes) - Use numbers in arrayOfBytes as contents.
+ // Throws an exception if any element is outside the range 0...255 (TODO).
+ else if (arguments.length === 1 && Array.isArray(arguments[0])) {
+ var array = arguments[0];
+ this._bytes = B_ALLOC(array.length);
+ for (var i = 0; i < array.length; i++) {
+ var b = array[i];
+ // If any element is outside the range 0...255, an exception (TODO) is thrown.
+ if (b < 0 || b > 0xFF)
+ throw new Error("ByteString constructor argument Array of integers must be 0 - 255 ("+b+")");
+ // Java "bytes" are interpreted as 2's complement
+ //this._bytes[i] = (b < 128) ? b : -1 * ((b ^ 0xFF) + 1);
+ B_SET(this._bytes, i, b);
+ }
+ this._offset = 0;
+ this._length = B_LENGTH(this._bytes);
+ }
+ // ByteArray(string, charset) - Create a ByteArray from a Javascript string, the result being encoded with charset.
+ else if ((arguments.length === 1 || (arguments.length === 2 && arguments[1] === undefined)) && typeof arguments[0] === "string") {
+ this._bytes = B_ENCODE_DEFAULT(arguments[0]);
+ this._offset = 0;
+ this._length = B_LENGTH(this._bytes);
+ }
+ else if (arguments.length === 2 && typeof arguments[0] === "string" && typeof arguments[1] === "string") {
+ this._bytes = B_ENCODE(arguments[0], arguments[1]);
+ this._offset = 0;
+ this._length = B_LENGTH(this._bytes);
+ }
+ // private: ByteArray(bytes, offset, length)
+ else if (arguments.length === 3 && typeof arguments[1] === "number" && typeof arguments[2] === "number") {
+ this._bytes = arguments[0];
+ this._offset = arguments[1];
+ this._length = arguments[2];
+ }
+ else
+ throw new Error("Illegal arguments to ByteString constructor: [" +
+ Array.prototype.join.apply(arguments, [","]) + "] ("+arguments.length+")");
+};
+
+ByteArray.prototype = new Binary();
+
+ByteArray.prototype.__defineGetter__("length", function() { return this._length; });
+ByteArray.prototype.__defineSetter__("length", function(length) {
+ if (typeof length !== "number")
+ return;
+
+ // same length
+ if (length === this.length) {
+ return;
+ }
+ // new length is less, truncate
+ else if (length < this._length) {
+ this._length = length;
+ }
+ // new length is more, but fits without moving, just clear new bytes
+ else if (this._offset + length <= B_LENGTH(this._bytes)) {
+ B_FILL(this._bytes, this._length, this._offset + length - 1, 0);
+ this._length = length;
+ }
+ // new length is more, but fits if we shift to bottom, so do that.
+ else if (length <= B_LENGTH(this._bytes)) {
+ B_COPY(this._bytes, this._offset, this._bytes, 0, this._length);
+ this._offset = 0;
+ B_FILL(this._bytes, this._length, this._offset + length - 1, 0);
+ this._length = length;
+ }
+ // new length is more than the allocated bytes array, allocate a new one and copy the data
+ else {
+ var newBytes = B_ALLOC(length);
+ B_COPY(this._bytes, this._offset, newBytes, 0, this._length);
+ this._bytes = newBytes;
+ this._offset = 0;
+ this._length = length;
+ }
+});
+
+// FIXME: array notation for set and get
+ByteArray.prototype.set = function(index, b) {
+ // If any element is outside the range 0...255, an exception (TODO) is thrown.
+ if (b < 0 || b > 0xFF)
+ throw new Error("ByteString constructor argument Array of integers must be 0 - 255 ("+b+")");
+
+ if (index < 0 || index >= this._length)
+ throw new Error("Out of range");
+
+ // Java "bytes" are interpreted as 2's complement
+ //this._bytes[this._offset + index] = (b < 128) ? b : -1 * ((b ^ 0xFF) + 1);
+ B_SET(this._bytes, this._offset + index, b);
+};
+
+// toArray()
+// toArray(charset)
+// - implemented on Binary
+
+// toByteArray() - just a copy
+// toByteArray(sourceCharset, targetCharset) - transcoded
+// - implemented on Binary
+
+// toByteString() - byte for byte copy
+// toByteString(sourceCharset, targetCharset) - transcoded
+// - implemented on Binary
+
+// toString() - a string representation like "[ByteArray 10]"
+// toString(charset) - an alias for decodeToString(charset)
+ByteArray.prototype.toString = function(charset) {
+ if (charset)
+ return this.decodeToString(charset);
+
+ return "[ByteArray "+this.length+"]";
+};
+
+// decodeToString(charset) - implemented on Binary
+
+// byteAt(offset) ByteString - Return the byte at offset as a ByteString.
+// - implemented on Binary
+
+// get(offset) Number - Return the byte at offset as a Number.
+// - implemented on Binary
+
+// concat(other ByteArray|ByteString|Array)
+// TODO: I'm assuming Array means an array of ByteStrings/ByteArrays, not an array of integers.
+ByteArray.prototype.concat = function() {
+ var components = [this],
+ totalLength = this.length;
+
+ for (var i = 0; i < arguments.length; i++) {
+ var component = Array.isArray(component) ? arguments[i] : [component];
+
+ for (var j = 0; j < component.length; j++) {
+ var subcomponent = component[j];
+ if (!(subcomponent instanceof ByteString) && !(subcomponent instanceof ByteArray))
+ throw "Arguments to ByteArray.concat() must be ByteStrings, ByteArrays, or Arrays of those.";
+
+ components.push(subcomponent);
+ totalLength += subcomponent.length;
+ }
+ }
+
+ var result = new ByteArray(totalLength),
+ offset = 0;
+
+ components.forEach(function(component) {
+ B_COPY(component._bytes, component._offset, result._byte, offset, component._length);
+ offset += component._length;
+ });
+
+ return result;
+};
+
+// pop() -> byte Number
+ByteArray.prototype.pop = function() {
+ if (this._length === 0)
+ return undefined;
+
+ this._length--;
+
+ return B_GET(this._bytes, this._offset + this._length);
+};
+
+// push(...variadic Numbers...)-> count Number
+ByteArray.prototype.push = function() {
+ throw "NYI";
+};
+
+// extendRight(...variadic Numbers / Arrays / ByteArrays / ByteStrings ...)
+ByteArray.prototype.extendRight = function() {
+ throw "NYI";
+};
+
+// shift() -> byte Number
+ByteArray.prototype.shift = function() {
+ if (this._length === 0)
+ return undefined;
+
+ this._length--;
+ this._offset++;
+
+ return B_GET(this._bytes, this._offset - 1);
+};
+
+// unshift(...variadic Numbers...) -> count Number
+ByteArray.prototype.unshift = function() {
+ throw "NYI";
+};
+
+// extendLeft(...variadic Numbers / Arrays / ByteArrays / ByteStrings ...)
+ByteArray.prototype.extendLeft = function() {
+ throw "NYI";
+};
+
+// reverse() in place reversal
+ByteArray.prototype.reverse = function() {
+ // "limit" is halfway, rounded down. "top" is the last index.
+ var limit = Math.floor(this._length/2) + this._offset,
+ top = this._length - 1;
+
+ // swap each pair of bytes, up to the halfway point
+ for (var i = this._offset; i < limit; i++) {
+ var tmp = B_GET(this._bytes, i);
+ B_SET(this._bytes, i, B_GET(this._bytes, top - i));
+ B_SET(this._bytes, top - i, tmp);
+ }
+
+ return this;
+};
+
+// slice()
+ByteArray.prototype.slice = function() {
+ return new ByteArray(ByteString.prototype.apply.slice(this, arguments));
+};
+
+var numericCompareFunction = function(o1, o2) { return o1 - o2; };
+
+// sort([compareFunction])
+ByteArray.prototype.sort = function(compareFunction) {
+ // FIXME: inefficient?
+
+ var array = this.toArray();
+
+ if (arguments.length)
+ array.sort(compareFunction);
+ else
+ array.sort(numericCompareFunction);
+
+ for (var i = 0; i < array.length; i++)
+ this.set(i, array[i]);
+};
+
+// splice()
+ByteArray.prototype.splice = function() {
+ throw "NYI";
+};
+
+// indexOf() - implemented on Binary
+// lastIndexOf() - implemented on Binary
+
+// split() Returns an array of ByteArrays instead of ByteStrings.
+ByteArray.prototype.split = function() {
+ var components = ByteString.prototype.split.apply(this.toByteString(), arguments);
+
+ // convert ByteStrings to ByteArrays
+ for (var i = 0; i < components.length; i++) {
+ // we know we can use these byte buffers directly since we copied them above
+ components[i] = new ByteArray(components[i]._bytes, components[i]._offset, components[i]._length);
+ }
+
+ return components;
+};
+
+// filter(callback[, thisObject])
+ByteArray.prototype.filter = function(callback, thisObject) {
+ var result = new ByteArray(this.length);
+ for (var i = 0, length = this.length; i < length; i++) {
+ var value = this.get(i);
+ if (callback.apply(thisObject, [value, i, this]))
+ result.push(value);
+ }
+ return result;
+};
+
+// forEach(callback[, thisObject]);
+ByteArray.prototype.forEach = function(callback) {
+ for (var i = 0, length = this.length; i < length; i++)
+ callback.apply(thisObject, [this.get(i), i, this]);
+};
+
+// every(callback[, thisObject])
+ByteArray.prototype.every = function(callback, thisObject) {
+ for (var i = 0, length = this.length; i < length; i++)
+ if (!callback.apply(thisObject, [this.get(i), i, this]))
+ return false;
+ return true;
+};
+
+// some(callback[, thisObject])
+ByteArray.prototype.some = function(callback, thisObject) {
+ for (var i = 0, length = this.length; i < length; i++)
+ if (callback.apply(thisObject, [this.get(i), i, this]))
+ return true;
+ return false;
+};
+
+// map(callback[, thisObject]);
+ByteArray.prototype.map = function(callback, thisObject) {
+ var result = new ByteArray(this.length);
+ for (var i = 0, length = this.length; i < length; i++)
+ result.set(i, callback.apply(thisObject, [this.get(i), i, this]));
+ return result;
+};
+
+// reduce(callback[, initialValue])
+ByteArray.prototype.reduce = function(callback, initialValue) {
+ var value = initialValue;
+ for (var i = 0, length = this.length; i < length; i++)
+ value = callback(value, this.get(i), i, this);
+ return value;
+};
+
+// reduceRight(callback[, initialValue])
+ByteArray.prototype.reduceRight = function(callback, initialValue) {
+ var value = initialValue;
+ for (var i = this.length-1; i > 0; i--)
+ value = callback(value, this.get(i), i, this);
+ return value;
+};
+
+// displace(begin, end, values/ByteStrings/ByteArrays/Arrays...) -> length
+// begin/end are specified like for slice. Can be used like splice but does not return the removed elements.
+ByteArray.prototype.displace = function(begin, end) {
+ throw "NYI";
+};
+
+// toSource() returns a string like "ByteArray([])" for a null byte-array.
+ByteArray.prototype.toSource = function() {
+ return "ByteArray(["+this.toArray().join(",")+"])";
+};
+
+/* BinaryIO */
+
+exports.BinaryIO = function(binary) {
+ if (!binary)
+ throw "NYI";
+
+ var stream = new (require("io").IO)(new java.io.ByteArrayInputStream(binary._bytes, binary._offset, binary._length), null);
+ stream.length = binary.length;
+ return stream;
+};
+
diff --git a/utils/platforms/default/lib/os-platform.js b/utils/platforms/default/lib/os-platform.js
new file mode 100755
index 0000000..9d3a6f8
--- /dev/null
+++ b/utils/platforms/default/lib/os-platform.js
@@ -0,0 +1,3 @@
+exports.exit = function(status) {
+ throw new Error("Exiting with status="+status);
+}
diff --git a/utils/platforms/k7/bin/narwhal-k7 b/utils/platforms/k7/bin/narwhal-k7
new file mode 100755
index 0000000..495c9d8
--- /dev/null
+++ b/utils/platforms/k7/bin/narwhal-k7
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+# get the absolute path of the executable
+SELF_PATH=$(cd -P -- "$(dirname -- "$0")" && pwd -P) && SELF_PATH=$SELF_PATH/$(basename -- "$0")
+
+# resolve symlinks
+while [ -h $SELF_PATH ]; do
+ DIR=$(dirname -- "$SELF_PATH")
+ SYM=$(readlink $SELF_PATH)
+ SELF_PATH=$(cd $DIR && cd $(dirname -- "$SYM") && pwd)/$(basename -- "$SYM")
+done
+
+NARWHAL_PLATFORM_HOME=$(dirname $(dirname $SELF_PATH))
+BOOTSTRAP="$NARWHAL_PLATFORM_HOME/bootstrap.js"
+
+if [ ! "$NARWHAL_HOME" ]; then
+ NARWHAL_HOME=$(dirname $(dirname $NARWHAL_PLATFORM_HOME))
+fi
+
+export NARWHAL_HOME
+
+# uses rlwrap (readline wrapper) if present
+K7="$(which rlwrap) k7"
+
+# drop into shell if there are no additional arguments
+if [ $# -lt 1 ]; then
+ # FIXME: no way to explicitly drop into shell
+ $K7 $BOOTSTRAP "$@"
+else
+ MAIN=$(cd -P -- "$(dirname -- "$1")" && pwd -P) && MAIN=$MAIN/$(basename -- "$1" .js)
+ $K7 $BOOTSTRAP $MAIN "$0" "$@"
+fi
diff --git a/utils/platforms/k7/bootstrap.js b/utils/platforms/k7/bootstrap.js
new file mode 100755
index 0000000..4fc18f5
--- /dev/null
+++ b/utils/platforms/k7/bootstrap.js
@@ -0,0 +1,78 @@
+(function (evalGlobal) {
+
+ // NOTE: Newer version of K7 (>May 2009) does not but anything
+ // else than modules in the global namespace
+ if (typeof(ENV) == "undefined") {
+ GLOBAL = system.GLOBAL
+ ENV = system.ENV;
+ print = system.shell.print;
+ }
+
+ var prefix = ENV["NARWHAL_HOME"];
+ var debug = false;
+
+ _system = system;
+
+ var fopen = _system.posix.fopen,
+ fread = _system.posix.fread,
+ fclose = _system.posix.fclose;
+
+ var isFile = function (path) {
+ try { read(path); } catch(e) { return false; }
+ return true;
+ };
+
+ var read = function(path) {
+ var result = "",
+ fd = fopen(path, "r");
+ if (!fd)
+ throw new Error("File not found: " + path);
+ try {
+ var length = 1024,
+ data;
+ do {
+ length *= 2;
+ data = fread(1, length, fd);
+ result += data;
+ } while (data.length === length);
+ } finally {
+ fclose(fd);
+ }
+ if (result.length === 0)
+ throw new Error("File not found (length=0): " + path);
+ return result;
+ };
+
+ var isFile = function(path) {
+ return _system.posix.isFile(path);
+ }
+
+ var _print = print;
+ delete print;
+
+ eval(read(prefix + "/narwhal.js"))({
+ global: GLOBAL,
+ evalGlobal: evalGlobal,
+ platform: 'k7',
+ platforms: ['k7', 'v8', 'c', 'default'],
+ debug: debug,
+ print: function (string) {
+ _print("" + string);
+ },
+ evaluate: function (text) {
+ return eval("(function(require,exports,module,system,print){" + text + "/**/\n})");
+ },
+ fs: {
+ read: read,
+ isFile: isFile
+ },
+ prefix: prefix,
+ complianceStage: "system"
+ });
+
+})(function () {
+ return eval(arguments[0]);
+});
+
+//throw "Exiting. (FIXME: this exception does not mean an actual error occurred, we just need a better way to exit)";
+// EOF - vim: ts=4 sw=4 et
diff --git a/utils/platforms/k7/lib/binary.js b/utils/platforms/k7/lib/binary.js
new file mode 100755
index 0000000..139597f
--- /dev/null
+++ b/utils/platforms/k7/lib/binary.js
@@ -0,0 +1,2 @@
+
+
diff --git a/utils/platforms/k7/lib/file-platform.js b/utils/platforms/k7/lib/file-platform.js
new file mode 100755
index 0000000..89680cc
--- /dev/null
+++ b/utils/platforms/k7/lib/file-platform.js
@@ -0,0 +1,116 @@
+
+var exports = require('./file');
+
+exports.SEPARATOR = '/';
+
+exports.cwd = function () {
+ throw Error("cwd not yet implemented.");
+};
+
+// TODO necessary for package loading
+exports.list = function (path) {
+ throw Error("list not yet implemented.");
+};
+
+// TODO necessary for package loading
+exports.canonical = function (path) {
+ throw Error("canonical not yet implemented.");
+};
+
+exports.exists = function (path) {
+ throw Error("exists not yet implemented.");
+};
+
+// TODO necessary for lazy module reloading in sandboxes
+exports.mtime = function (path) {
+ return exports.stat(path).mtime;
+};
+
+exports.size = function (path) {
+ throw Error("size not yet implemented.");
+};
+
+exports.stat = function (path) {
+ return _system.posix.stat(path);
+};
+
+// TODO necessary for package loading
+exports.isDirectory = function (path) {
+ throw Error("isDirectory not yet implemented.");
+};
+
+// TODO necessary for module loading
+exports.isFile = function (path) {
+ throw Error("isFile not yet implemented.");
+};
+
+exports.isFile = system.fs.isFile; // TEMPORARY HACK
+
+exports.isLink = function (path) {
+ throw Error("isLink not yet implemented.");
+};
+
+exports.isReadable = function (path) {
+ throw Error("isReadable not yet implemented.");
+};
+
+exports.isWritable = function (path) {
+ throw Error("isWritable not yet implemented.");
+};
+
+exports.rename = function (source, target) {
+ throw Error("rename not yet implemented.");
+};
+
+exports.move = function (source, target) {
+ throw Error("move not yet implemented.");
+};
+
+exports.remove = function (path) {
+ throw Error("remove not yet implemented.");
+};
+
+exports.mkdir = function (path) {
+ throw Error("mkdir not yet implemented.");
+};
+
+exports.rmdir = function(path) {
+ throw Error("rmdir not yet implemented.");
+};
+
+exports.touch = function (path, mtime) {
+ throw Error("touch not yet implemented.");
+};
+
+// FIXME temporary hack
+var read = system.fs.read; // from k7 bootstrap fixtures
+
+exports.FileIO = function (path, mode, permissions) {
+ mode = exports.mode(mode);
+ var read = mode.read,
+ write = mode.write,
+ append = mode.append,
+ update = mode.update;
+
+ if (update) {
+ throw new Error("Updating IO not yet implemented.");
+ } else if (write || append) {
+ throw new Error("Writing IO not yet implemented.");
+ } else if (read) {
+ // FIXME temporary hack
+ return {
+ 'read': function () {
+ return read(path);
+ },
+ 'close': function () {
+ },
+ 'isatty': function () {
+ return false;
+ }
+ };
+ } else {
+ throw new Error("Files must be opened either for read, write, or update mode.");
+ }
+};
+
+// vim: ts=4 sw=4 et
diff --git a/utils/platforms/k7/lib/io-platform.js b/utils/platforms/k7/lib/io-platform.js
new file mode 100755
index 0000000..363544f
--- /dev/null
+++ b/utils/platforms/k7/lib/io-platform.js
@@ -0,0 +1,8 @@
+
+exports.IO = function () {
+};
+
+exports.TextIOWrapper = function (raw, mode, lineBuffering, buffering, charset, options) {
+ return raw;
+};
+
diff --git a/utils/platforms/k7/lib/system.js b/utils/platforms/k7/lib/system.js
new file mode 100755
index 0000000..a92b8dd
--- /dev/null
+++ b/utils/platforms/k7/lib/system.js
@@ -0,0 +1,25 @@
+/*
+var IO = require("./io").IO;
+
+exports.stdin = new IO(function(){}, null);
+exports.stdout = new IO(null, function(string) { print(String(string).replace(/\n$/,"")); });
+exports.stderr = new IO(null, function(string) { print(String(string).replace(/\n$/,"")); });
+*/
+
+exports.args = ENV["argv"].slice(2);
+
+exports.env = {};
+
+for (var key in ENV)
+ if (key !== "argc" && key !== "argv")
+ exports.env[key] = ENV[key];
+
+delete ENV;
+
+exports.fs = require('./file');
+
+/*
+// default logger
+var Logger = require("logger").Logger;
+exports.log = new Logger(exports.stdout);
+*/
diff --git a/utils/platforms/rhino/bin/narwhal-rhino.cmd b/utils/platforms/rhino/bin/narwhal-rhino.cmd
new file mode 100755
index 0000000..646675a
--- /dev/null
+++ b/utils/platforms/rhino/bin/narwhal-rhino.cmd
@@ -0,0 +1,25 @@
+@echo off
+setlocal
+
+:: NARWHAL_PLATFORM_HOME is the parent the bin directory
+set NARWHAL_PLATFORM_HOME=%~dp0..
+
+set BOOTSTRAP=%NARWHAL_PLATFORM_HOME%\bootstrap.js
+
+if "%NARWHAL_HOME%" == "" (
+ set NARWHAL_HOME=%NARWHAL_PLATFORM_HOME%\..\..
+)
+
+set CLASSPATH=%NARWHAL_PLATFORM_HOME%\jars\js.jar;%NARWHAL_PLATFORM_HOME%\jars\jline.jar
+if not "%NARWHAL_CLASSPATH%" == "" (
+ set CLASSPATH=%NARWHAL_CLASSPATH%;%CLASSPATH%
+)
+
+set JAVA_MAIN=org.mozilla.javascript.tools.shell.Main
+
+:: drop into shell if there are no additional arguments
+if "%1" == "" (
+ java -cp "%CLASSPATH%" "%JAVA_MAIN%" -f "%BOOTSTRAP%" -f -
+) else (
+ java -cp "%CLASSPATH%" "%JAVA_MAIN%" "%BOOTSTRAP%" "%0" %*
+)
diff --git a/utils/platforms/rhino/lib/binary-platform.js b/utils/platforms/rhino/lib/binary-platform.js
new file mode 100755
index 0000000..fda53fa
--- /dev/null
+++ b/utils/platforms/rhino/lib/binary-platform.js
@@ -0,0 +1,44 @@
+exports.B_LENGTH = function(bytes) {
+ return bytes.length;
+}
+
+exports.B_ALLOC = function(length) {
+ return java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, length);
+}
+
+exports.B_FILL = function(bytes, length, offset, value) {
+ java.util.Arrays.fill(bytes, length, offset, value);
+}
+
+exports.B_COPY = function(src, srcOffset, dst, dstOffset, length) {
+ java.lang.System.arraycopy(src, srcOffset, dst, dstOffset, length);
+}
+
+exports.B_GET = function(bytes, index) {
+ var b = bytes[index];
+ return (b >= 0) ? b : -1 * ((b ^ 0xFF) + 1);
+}
+
+exports.B_SET = function(bytes, index, value) {
+ return bytes[index] = (value < 128) ? value : -1 * ((value ^ 0xFF) + 1);
+}
+
+exports.B_DECODE = function(bytes, offset, length, codec) {
+ return String(new java.lang.String(bytes, offset, length, codec));
+}
+
+exports.B_DECODE_DEFAULT = function(bytes, offset, length) {
+ return String(new java.lang.String(bytes, offset, length));
+}
+
+exports.B_ENCODE = function(string, codec) {
+ return new java.lang.String(string).getBytes(codec);
+}
+
+exports.B_ENCODE_DEFAULT = function(string) {
+ return new java.lang.String(string).getBytes();
+}
+
+exports.B_TRANSCODE = function(bytes, offset, length, sourceCodec, targetCodec) {
+ return new java.lang.String(bytes, offset, length, sourceCodec).getBytes(targetCodec);
+}