Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

build scripts for dev and prod

  • Loading branch information...
commit a66ca793c3aeb7c936d15347cd43c02e0279f08f 1 parent 7598b26
Jeffrey Zhao authored
296 bin/dev/jscex-0.6.5.js
View
@@ -0,0 +1,296 @@
+(function () {
+ "use strict";
+
+ var Jscex;
+
+ var _ = (function () {
+
+ var isArray = function (obj) {
+ return Object.prototype.toString.call(obj) === '[object Array]';
+ }
+
+ var each = function (obj, action) {
+ if (isArray(obj)) {
+ for (var i = 0, len = obj.length; i < len; i++) {
+ var value = action(i, obj[i]);
+ if (value !== undefined)
+ return value;
+ }
+ } else {
+ for (var key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ var value = action(key, obj[key]);
+ if (value !== undefined)
+ return value;
+ }
+ }
+ }
+ }
+
+ var map = function (obj, mapper, valueMapper) {
+ if (isArray(obj)) {
+ var array = new Array(obj.length);
+ for (var i = 0, len = obj.length; i < len; i++) {
+ array[i] = mapper(obj[i]);
+ }
+ return array;
+ } else {
+ var newObj = {};
+ for (var key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ var value = obj[key];
+ var newKey = mapper ? mapper(key) : key;
+ var newValue = valueMapper ? valueMapper(value) : value;
+ newObj[newKey] = newValue;
+ }
+ }
+ return newObj;
+ }
+ }
+
+ var v2n = function (version) {
+ var value = 0;
+
+ var parts = version.split(".");
+ for (var i = 0; i < 3; i++) {
+ value *= 100;
+ if (i < parts.length) {
+ value += parseInt(parts[i], 10);
+ }
+ }
+
+ return value;
+ }
+
+ var testVersion = function (expected, version) {
+ var expectedMinVersion = expected.substring(1); // remove leading "~"
+
+ var expectedMaxParts = expectedMinVersion.split(".");
+ expectedMaxParts[expectedMaxParts.length - 1] = "0";
+ expectedMaxParts[expectedMaxParts.length - 2] = (parseInt(expectedMaxParts[expectedMaxParts.length - 2], 10) + 1).toString();
+ var expectedMaxVersion = expectedMaxParts.join(".");
+
+ var versionNumber = v2n(version);
+ return v2n(expectedMinVersion) <= versionNumber && versionNumber < v2n(expectedMaxVersion);
+ }
+
+ var format = function (f, args) {
+ // support _.format(f, a0, a1, ...);
+ if (!isArray(args)) {
+ var newArgs = new Array(arguments.length - 1);
+ for (var i = 1; i < arguments.length; i++) {
+ newArgs[i - 1] = arguments[i];
+ }
+
+ return format(f, newArgs);
+ }
+
+ return f.replace(/\{{1,2}\d+\}{1,2}/g, function (ph) {
+ if (ph.indexOf("{{") == 0 && ph.indexOf("}}") == ph.length - 2) {
+ return ph.substring(1, ph.length - 1);
+ }
+
+ var left = 0;
+ while (ph[left] == "{") left++;
+
+ var right = ph.length - 1;
+ while (ph[right] == "}") right--;
+
+ var index = parseInt(ph.substring(left, right + 1), 10);
+ return ph.replace("{" + index + "}", args[index]);
+ });
+ }
+
+ var once = function (fn) {
+ var called = false;
+ return function () {
+ if (called) return;
+ fn.apply(this, arguments);
+ called = true;
+ }
+ };
+
+ return {
+ isArray: isArray,
+ each: each,
+ map: map,
+ v2n: v2n,
+ testVersion: testVersion,
+ format: format,
+ once: once
+ };
+ })();
+
+ var Level = {
+ ALL: 0,
+ TRACE: 1,
+ DEBUG: 2,
+ INFO: 3,
+ WARN: 4,
+ ERROR: 5,
+ OFF: 100
+ };
+
+ var Logger = function () {
+ this.level = Level.DEBUG;
+ };
+ Logger.prototype = {
+ log: function (level, msg) {
+ if (this.level <= level) {
+ try { console.log(msg); } catch (ex) { }
+ }
+ },
+
+ trace: function (msg) {
+ this.log(Level.TRACE, msg);
+ },
+
+ debug: function (msg) {
+ this.log(Level.DEBUG, msg);
+ },
+
+ info: function (msg) {
+ this.log(Level.INFO, msg);
+ },
+
+ warn: function (msg) {
+ this.log(Level.WARN, msg);
+ },
+
+ error: function (msg) {
+ this.log(Level.ERROR, msg);
+ }
+ };
+
+ var loadModules = function (require, modules) {
+ if (require) {
+ _.each(modules, function (i, name) {
+ require("./jscex-" + name).init();
+ });
+ } else {
+ _.each(modules, function (i, m) {
+ m.init();
+ });
+ }
+ }
+
+ var initModule = function (options) {
+ var existingVersion = Jscex.modules[options.name];
+ if (existingVersion && existingVersion != options.version) {
+ Jscex.logger.warn(_.format(
+ 'The module "{0}" with version "{1}" has already been initialized, skip version "{2}".',
+ options.name,
+ existingVersion,
+ options.version));
+ }
+
+ checkDependencies(options);
+ options.init();
+ Jscex.modules[options.name] = options.version;
+ }
+
+ var checkDependencies = function (options) {
+ _.each(options.dependencies, function (name, expectedVersion) {
+ if (name == "core") {
+ if (!_.testVersion(expectedVersion, Jscex.coreVersion)) {
+ throw new Error(_.format(
+ 'Version of core component mismatched, expected: "{0}", actual: "{1}".',
+ expectedVersion,
+ Jscex.coreVersion));
+ }
+ } else {
+ var version = Jscex.modules[name];
+ if (!version) {
+ throw new Error(_.format(
+ 'Missing required module: "{0}" (expected version: "{1}").',
+ name,
+ expectedVersion));
+ }
+
+ if (!_.testVersion(expectedVersion, version)) {
+ throw new Error(_.format(
+ 'Version of module "{0}" mismatched, expected: "{1}", actual: "{2}".',
+ name,
+ expectedVersion,
+ version));
+ }
+ }
+ });
+ }
+
+ var exportBasicOptions = function (exports, options) {
+ exports.name = options.name;
+ exports.version = options.version;
+ }
+
+ // CommonJS
+ var isCommonJS = !!(typeof require === "function" && typeof module !== "undefined" && module.exports);
+ // CommonJS AMD
+ var isAmd = !!(typeof require === "function" && typeof define === "function" && define.amd);
+
+ var defineModule = function (options) {
+ var autoloads = options.autoloads || [];
+
+ if (isCommonJS) {
+ exportBasicOptions(options.exports, options);
+ options.exports.init = _.once(function () {
+ loadModules(options.require, autoloads);
+ initModule(options);
+ });
+ } else if (isAmd) {
+ var dependencies = _.map(autoloads, function (name) { return "jscex-" + name; });
+
+ define("jscex-" + options.name, dependencies, function () {
+ var loadedModules = arguments;
+
+ var exports = {};
+ exportBasicOptions(exports, options);
+ exports.init = _.once(function () {
+ loadModules(null, loadedModules);
+ initModule(options);
+ });
+
+ return exports;
+ });
+ } else {
+ initModule(options);
+ }
+ }
+
+ var init = function () {
+ Jscex.coreVersion = "0.6.5";
+
+ Jscex.logger = new Logger();
+ Jscex.Logging = {
+ Logger: Logger,
+ Level: Level
+ };
+
+ Jscex._ = _;
+ Jscex.modules = { };
+ Jscex.binders = { };
+ Jscex.builders = { };
+ Jscex.define = defineModule;
+ };
+
+ if (isCommonJS) {
+ Jscex = module.exports;
+ init();
+ } else if (isAmd) {
+ define("jscex", function () {
+ Jscex = { };
+ init();
+ return Jscex;
+ });
+ } else {
+ // Get the global object.
+ var Fn = Function, global = Fn('return this')();
+
+ if (global.Jscex) {
+ throw new Error("There's already a Jscex root here, please load the component only once.");
+ }
+
+ Jscex = global.Jscex = { };
+ init();
+ }
+})();
283 bin/dev/jscex-async-0.6.5.js
View
@@ -0,0 +1,283 @@
+(function () {
+ "use strict";
+
+ var Jscex;
+
+ var CanceledErrorTypeID = "670a1076-712b-4edd-9b70-64b152fe1cd9";
+ var isCanceledError = function (ex) { return ex._typeId == CanceledErrorTypeID; }
+ var CanceledError = function () { }
+ CanceledError.prototype = {
+ isTypeOf: isCanceledError,
+ _typeId: CanceledErrorTypeID,
+ message: "The task has been cancelled."
+ }
+
+ var Fn = Function, global = Fn('return this')();
+
+ // seed defined in global
+ if (global.__jscex__async__taskIdSeed === undefined) {
+ global.__jscex__async__taskIdSeed = 0;
+ }
+
+ var isTask = function (t) {
+ return (typeof t.start === "function") && (typeof t.addEventListener) === "function" && (typeof t.removeEventListener) === "function" && (typeof t.complete) === "function";
+ }
+
+ var CancellationToken = function () { }
+ CancellationToken.prototype = {
+ register: function (handler) {
+ if (this.isCancellationRequested) {
+ handler();
+ }
+
+ if (!this._handlers) {
+ this._handlers = [];
+ }
+
+ this._handlers.push(handler);
+ },
+
+ unregister: function (handler) {
+ if (!this._handlers) {
+ return;
+ }
+
+ var index = this._handlers.indexOf(handler);
+ if (index >= 0) {
+ this._handlers.splice(index, 1);
+ }
+ },
+
+ cancel: function () {
+ if (this.isCancellationRequested) {
+ return;
+ }
+
+ this.isCancellationRequested = true;
+
+ var handlers = this._handlers;
+ delete this._handlers;
+
+ for (var i = 0; i < handlers.length; i++) {
+ try {
+ handlers[i]();
+ } catch (ex) {
+ Jscex.logger.warn("[WARNING] Cancellation handler threw an error: " + ex);
+ }
+ }
+ },
+
+ throwIfCancellationRequested: function () {
+ if (this.isCancellationRequested) {
+ throw new CanceledError();
+ }
+ }
+ };
+
+ var Task = function (delegate) {
+ this.id = (++__jscex__async__taskIdSeed);
+ this._delegate = delegate;
+ this._listeners = { };
+ this.status = "ready";
+ }
+ Task.prototype = {
+ start: function () {
+ if (this.status != "ready") {
+ throw new Error('Task can only be started in "ready" status.');
+ }
+
+ this.status = "running";
+ this._delegate(this);
+
+ return this;
+ },
+
+ complete: function (type, value) {
+ if (this.status != "running") {
+ throw new Error('The "complete" method can only be called in "running" status.');
+ }
+
+ var listeners = this._listeners;
+ delete this._listeners;
+
+ if (type == "success") {
+
+ this.result = value;
+ this.status = "succeeded";
+ this._notify("success", listeners["success"]);
+
+ } else if (type == "failure") {
+
+ this.error = value;
+
+ if (isCanceledError(value)) {
+ this.status = "canceled";
+ } else {
+ this.status = "faulted";
+ }
+
+ this._notify("failure", listeners["failure"]);
+
+ } else {
+ throw new Error("Unsupported type: " + type);
+ }
+
+ this._notify("complete", listeners["complete"]);
+
+ if (this.error && !listeners["failure"] && !listeners["complete"]) {
+ Jscex.logger.warn("[WARNING] An unhandled error occurred: " + this.error);
+ }
+ },
+
+ _notify: function (ev, listeners) {
+ if (!listeners) {
+ return;
+ }
+
+ for (var i = 0; i < listeners.length; i++) {
+ listeners[i].call(this);
+ }
+ },
+
+ addEventListener: function (ev, listener) {
+ if (!this._listeners) {
+ return this;
+ }
+
+ if (!this._listeners[ev]) {
+ this._listeners[ev] = [];
+ }
+
+ this._listeners[ev].push(listener);
+ return this;
+ },
+
+ removeEventListener: function (ev, listener) {
+ if (!this._listeners) {
+ return this;
+ }
+
+ var evListeners = this._listeners[ev];
+ if (!evListeners) return this;
+
+ var index = evListeners.indexOf(listener);
+ if (index >= 0) {
+ evListeners.splice(index, 1);
+ }
+
+ return this;
+ }
+ };
+
+ Task.create = function (delegate) {
+ return new Task(delegate);
+ }
+
+ Task.isTask = isTask;
+
+ var AsyncBuilder = function () { }
+ AsyncBuilder.prototype = {
+ Start: function (_this, task) {
+ return Task.create(function (t) {
+ task.next(_this, function (type, value, target) {
+ if (type == "normal" || type == "return") {
+ t.complete("success", value);
+ } else if (type == "throw") {
+ t.complete("failure", value);
+ } else {
+ throw new Error("Unsupported type: " + type);
+ }
+ });
+ });
+ },
+
+ Bind: function (task, generator) {
+ return {
+ next: function (_this, callback) {
+
+ var onComplete = function (t) {
+ if (this.error) {
+ callback("throw", this.error);
+ } else {
+ var nextTask;
+ try {
+ nextTask = generator.call(_this, this.result);
+ } catch (ex) {
+ callback("throw", ex);
+ return;
+ }
+
+ nextTask.next(_this, callback);
+ }
+ }
+
+ if (task.status == "ready") {
+ task.addEventListener("complete", onComplete);
+ task.start();
+ } else if (task.status == "running") {
+ task.addEventListener("complete", onComplete);
+ } else {
+ onComplete(task);
+ }
+ }
+ };
+ }
+ }
+
+ // CommonJS
+ var isCommonJS = !!(typeof require === "function" && typeof module !== "undefined" && module.exports);
+ // CommonJS AMD
+ var isAmd = !!(typeof require === "function" && typeof define === "function" && define.amd);
+
+ var defineModule = function () {
+ Jscex.define({
+ name: "async",
+ version: "0.6.5",
+ exports: isCommonJS && module.exports,
+ require: isCommonJS && require,
+ autoloads: [ "builderbase" ],
+ dependencies: { builderbase: "~0.6.5" },
+ init: function () {
+
+ Jscex._.each(Jscex.BuilderBase.prototype, function (m, fn) {
+ AsyncBuilder.prototype[m] = fn;
+ });
+
+ if (!Jscex.Async) {
+ Jscex.Async = {};
+ }
+
+ var Async = Jscex.Async;
+ Async.CancellationToken = CancellationToken;
+ Async.CanceledError = CanceledError;
+ Async.Task = Task;
+ Async.AsyncBuilder = AsyncBuilder;
+
+ Jscex.binders["async"] = "$await";
+ Jscex.builders["async"] = new AsyncBuilder();
+ }
+ });
+ }
+
+ if (isCommonJS) {
+ try {
+ Jscex = require("./jscex");
+ } catch (ex) {
+ Jscex = require("jscex");
+ }
+
+ defineModule();
+ } else if (isAmd) {
+ require("jscex", function (jscex) {
+ Jscex = jscex;
+ defineModule();
+ });
+ } else {
+ if (!global.Jscex) {
+ throw new Error('Missing the root object, please load "jscex" component first.');
+ }
+
+ Jscex = global.Jscex;
+ defineModule();
+ }
+})();
442 bin/dev/jscex-async-powerpack-0.6.5.js
View
@@ -0,0 +1,442 @@
+(function () {
+ "use strict";
+
+ var Jscex, Task, CanceledError, _;
+
+ var collectCallbackArgNames = function (args) {
+ if (args.length <= 1) return null;
+
+ var result = [];
+ for (var i = 1; i < args.length; i++) {
+ result.push(args[i]);
+ }
+
+ return result;
+ }
+
+ var collectArgs = function (args, requiredArgs) {
+ var result = [];
+ for (var i = 0; i < args.length; i++) {
+ result.push(args[i]);
+ }
+
+ while (result.length < requiredArgs) {
+ result.push(undefined);
+ }
+
+ return result;
+ }
+
+ // Async members
+
+ var AggregateErrorTypeID = "4a73efb8-c2e2-4305-a05c-72385288650a";
+ var AggregateError = function (errors) {
+ this.children = [];
+
+ if (errors) {
+ for (var i = 0; i < errors.length; i++) {
+ this.children.push(errors[i]);
+ }
+ }
+ }
+ AggregateError.prototype = {
+ _typeId: AggregateErrorTypeID,
+ message: "This is an error contains sub-errors, please check the 'children' collection for more details.",
+ isTypeOf: function (ex) {
+ return ex._typeId == AggregateErrorTypeID;
+ }
+ }
+
+ var sleep = function (delay, /* CancellationToken */ ct) {
+ return Task.create(function (t) {
+ if (ct && ct.isCancellationRequested) {
+ t.complete("failure", new CanceledError());
+ }
+
+ var seed;
+ var cancelHandler;
+
+ if (ct) {
+ cancelHandler = function () {
+ clearTimeout(seed);
+ t.complete("failure", new CanceledError());
+ }
+ }
+
+ var seed = setTimeout(function () {
+ if (ct) {
+ ct.unregister(cancelHandler);
+ }
+
+ t.complete("success");
+ }, delay);
+
+ if (ct) {
+ ct.register(cancelHandler);
+ }
+ });
+ }
+
+ var onEvent = function (target, eventName, /* CancellationToken*/ ct) {
+ return Task.create(function (t) {
+ if (ct && ct.isCancellationRequested) {
+ t.complete("failure", new CanceledError());
+ }
+
+ var cleanUp = function () {
+ if (target.removeEventListener) {
+ target.removeEventListener(eventName, eventHandler);
+ } else if (target.removeListener) {
+ target.removeListener(eventName, eventHandler);
+ } else {
+ target.detachEvent(eventName, eventHandler);
+ }
+ }
+
+ var eventHandler;
+ var cancelHandler;
+
+ if (ct) {
+ cancelHandler = function () {
+ cleanUp();
+ t.complete("failure", new CanceledError());
+ }
+ }
+
+ var eventHandler = function (ev) {
+ if (ct) {
+ ct.unregister(cancelHandler);
+ }
+
+ cleanUp();
+ t.complete("success", ev);
+ }
+
+ if (target.addEventListener) {
+ target.addEventListener(eventName, eventHandler);
+ } else if (target.addListener) {
+ target.addListener(eventName, eventHandler);
+ } else {
+ target.attachEvent(eventName, eventHandler);
+ }
+
+ if (ct) {
+ ct.register(cancelHandler);
+ }
+ });
+ }
+
+ // Task members
+
+ var whenAll = function () {
+ var inputTasks;
+
+ if (arguments.length == 1) {
+ var arg = arguments[0];
+
+ if (Task.isTask(arg)) { // a single task
+ inputTasks = [arg];
+ } else {
+ inputTasks = arg;
+ }
+ } else {
+ inputTasks = new Array(arguments.length);
+ for (var i = 0; i < arguments.length; i++) {
+ inputTasks[i] = arguments[i];
+ }
+ }
+
+ return Task.create(function (taskWhenAll) {
+ var taskKeys = {};
+
+ _.each(inputTasks, function (key, task) {
+ if (!task) return;
+
+ if (!Task.isTask(task)) {
+ inputTasks[key] = task = whenAll(task);
+ }
+
+ taskKeys[task.id] = key;
+ });
+
+ // start all the tasks
+ _.each(taskKeys, function (id, key) {
+ var task = inputTasks[key];
+ if (task.status === "ready") {
+ task.start();
+ }
+ });
+
+ var done = function () {
+ var results = _.isArray(inputTasks) ? new Array(inputTasks.length) : { };
+ var errors = [];
+
+ _.each(taskKeys, function (id, key) {
+ var task = inputTasks[key];
+ if (task.error) {
+ errors.push(task.error);
+ } else {
+ results[key] = task.result;
+ }
+ });
+
+ if (errors.length > 0) {
+ taskWhenAll.complete("failure", new AggregateError(errors));
+ } else {
+ taskWhenAll.complete("success", results);
+ }
+ }
+
+ var runningNumber = 0;
+
+ _.each(taskKeys, function (id, key) {
+ var task = inputTasks[key];
+
+ if (task.status == "running") {
+ runningNumber++;
+
+ task.addEventListener("complete", function () {
+ if (--runningNumber == 0) {
+ done();
+ }
+ });
+ }
+ });
+
+ if (runningNumber == 0) {
+ done();
+ }
+ });
+ };
+
+ var whenAny = function () {
+
+ var tasks = { };
+
+ if (arguments.length == 1) {
+ var arg = arguments[0];
+ if (Task.isTask(arg)) {
+ tasks[0] = arg;
+ } else {
+ tasks = arg;
+ }
+ } else {
+ for (var i = 0; i < arguments.length; i++)
+ tasks[i] = arguments[i];
+ }
+
+ return Task.create(function (taskWhenAny) {
+ var taskKeys = {};
+ for (var key in tasks) {
+ if (tasks.hasOwnProperty(key)) {
+ var t = tasks[key];
+ if (Task.isTask(t)) {
+ taskKeys[t.id] = key;
+ }
+ }
+ }
+
+ // start all the tasks
+ for (var id in taskKeys) {
+ var t = tasks[taskKeys[id]];
+ if (t.status == "ready") {
+ t.start();
+ }
+ }
+
+ // if there's a task already failed/succeeded, then return
+ for (var id in taskKeys) {
+ var key = taskKeys[id];
+ var t = tasks[key];
+ if (t.error || t.status == "succeeded") {
+ taskWhenAny.complete("success", { key: key, task: t });
+ return;
+ }
+ }
+
+ var onComplete = function (t) {
+ for (var id in taskKeys) {
+ tasks[taskKeys[id]].removeEventListener("complete", onComplete);
+ }
+
+ taskWhenAny.complete("success", { key: taskKeys[this.id], task: this });
+ }
+
+ // now all the tasks are in "running" status.
+ for (var id in taskKeys) {
+ tasks[taskKeys[id]].addEventListener("complete", onComplete);
+ }
+ });
+ }
+
+ var then = function (nextGenerator) {
+ var firstTask = this;
+
+ return Task.create(function (t) {
+
+ var nextOnComplete = function () {
+ if (this.error) {
+ t.complete("failure", this.error);
+ } else {
+ t.complete("success", this.result);
+ }
+ };
+
+ var processNext = function (nextTask) {
+ if (nextTask.status == "ready") {
+ nextTask.start();
+ }
+
+ if (nextTask.status == "running") {
+ nextTask.addEventListener("complete", nextOnComplete);
+ } else {
+ nextOnComplete.call(nextTask);
+ }
+ };
+
+ var firstOnComplete = function () {
+ if (this.error) {
+ return t.complete("failure", this.error);
+ }
+
+ var nextTask;
+ try {
+ nextTask = nextGenerator(this.result);
+ } catch (ex) {
+ return t.complete("failure", ex);
+ }
+
+ processNext(nextTask);
+ };
+
+ if (firstTask.status == "ready") {
+ firstTask.start();
+ }
+
+ if (firstTask.status == "running") {
+ firstTask.addEventListener("complete", firstOnComplete);
+ } else {
+ firstOnComplete.call(firstTask);
+ }
+ });
+ };
+
+ // Binding members
+
+ var fromStandard = function (fn) {
+ var callbackArgNames = collectCallbackArgNames(arguments);
+
+ return function () {
+ var _this = this;
+ var args = collectArgs(arguments, fn.length - 1);
+
+ return Task.create(function (t) {
+ args.push(function (error, result) {
+ if (error) {
+ t.complete("failure", error);
+ } else if (!callbackArgNames) {
+ t.complete("success", result);
+ } else {
+ var data = {};
+ for (var i = 0; i < callbackArgNames.length; i++) {
+ data[callbackArgNames[i]] = arguments[i + 1];
+ }
+
+ return t.complete("success", data);
+ }
+ });
+
+ fn.apply(_this, args);
+ });
+ };
+ };
+
+ var fromCallback = function (fn) {
+ var callbackArgNames = collectCallbackArgNames(arguments);
+
+ return function () {
+ var _this = this;
+ var args = collectArgs(arguments, fn.length - 1);
+
+ return Task.create(function (t) {
+ args.push(function (result) {
+ if (callbackArgNames) {
+ var data = {};
+ for (var i = 0; i < callbackArgNames.length; i++) {
+ data[callbackArgNames[i]] = arguments[i];
+ }
+
+ t.complete("success", data);
+ } else {
+ t.complete("success", result);
+ }
+ });
+
+ fn.apply(_this, args);
+ });
+ };
+ };
+
+ // CommonJS
+ var isCommonJS = !!(typeof require === "function" && typeof module !== "undefined" && module.exports);
+ // CommonJS AMD
+ var isAmd = !!(typeof require === "function" && typeof define === "function" && define.amd);
+
+ var defineModule = function () {
+ Jscex.define({
+ name: "async-powerpack",
+ version: "0.6.5",
+ exports: isCommonJS && module.exports,
+ require: isCommonJS && require,
+ dependencies: { async: "~0.6.5" },
+ init: function () {
+
+ _ = Jscex._;
+ Task = Jscex.Async.Task;
+ CanceledError = Jscex.Async.CanceledError;
+
+ var Async = Jscex.Async;
+ Async.sleep = sleep;
+ Async.onEvent = onEvent;
+ Async.AggregateError = AggregateError;
+
+ Task.whenAll = whenAll;
+ Task.whenAny = whenAny;
+ Task.prototype.then = Task.prototype.continueWith = then;
+
+ if (!Async.Binding) {
+ Async.Binding = {};
+ }
+
+ var Binding = Async.Binding;
+ Async.Jscexify = Binding;
+
+ Binding.fromStandard = fromStandard;
+ Binding.fromCallback = fromCallback;
+ }
+ });
+ }
+
+ if (isCommonJS) {
+ try {
+ Jscex = require("./jscex");
+ } catch (ex) {
+ Jscex = require("jscex");
+ }
+
+ defineModule();
+ } else if (isAmd) {
+ require("jscex", function (jscex) {
+ Jscex = jscex;
+ defineModule();
+ });
+ } else {
+ var Fn = Function, global = Fn('return this')();
+ if (!global.Jscex) {
+ throw new Error('Missing the root object, please load "jscex" component first.');
+ }
+
+ Jscex = global.Jscex;
+ defineModule();
+ }
+})();
334 bin/dev/jscex-builderbase-0.6.5.js
View
@@ -0,0 +1,334 @@
+(function () {
+ "use strict";
+
+ var BuilderBase = function () { }
+ BuilderBase.prototype = {
+ For: function (condition, update, body) {
+ return {
+ next: function (_this, callback) {
+
+ var loop = function (skipUpdate) {
+ try {
+ if (update && !skipUpdate) {
+ update.call(_this);
+ }
+
+ if (!condition || condition.call(_this)) {
+ body.next(_this, function (type, value, target) {
+ if (type == "normal" || type == "continue") {
+ loop(false);
+ } else if (type == "throw" || type == "return") {
+ callback(type, value);
+ } else if (type == "break") {
+ callback("normal");
+ } else {
+ throw new Error('Invalid type for "Loop": ' + type);
+ }
+ });
+ } else {
+ callback("normal");
+ }
+ } catch (ex) {
+ callback("throw", ex);
+ }
+ }
+
+ loop(true);
+ }
+ };
+ },
+
+ ForIn: function (obj, bodyGenerator) {
+ return {
+ next: function (_this, callback) {
+
+ var keys = [];
+ for (var k in obj) {
+ keys.push(k);
+ }
+
+ var loop = function (i) {
+ try {
+ if (i < keys.length) {
+ var body = bodyGenerator(keys[i]);
+ body.next(_this, function (type, value, target) {
+ if (type == "normal" || type == "continue") {
+ loop(i + 1);
+ } else if (type == "throw" || type == "return") {
+ callback(type, value);
+ } else if (type == "break") {
+ callback("normal");
+ } else {
+ throw new Error('Invalid type for "Loop": ' + type);
+ }
+ });
+ } else {
+ callback("normal");
+ }
+ } catch (ex) {
+ callback("throw", ex);
+ }
+ }
+
+ loop(0);
+ }
+ };
+ },
+
+ While: function (condition, body) {
+ return {
+ next: function (_this, callback) {
+ var loop = function () {
+ try {
+ if (condition.call(_this)) {
+ body.next(_this, function (type, value, target) {
+ if (type == "normal" || type == "continue") {
+ loop();
+ } else if (type == "throw" || type == "return") {
+ callback(type, value);
+ } else if (type == "break") {
+ callback("normal");
+ } else {
+ throw new Error('Invalid type for "Loop": ' + type);
+ }
+ });
+ } else {
+ callback("normal");
+ }
+ } catch (ex) {
+ callback("throw", ex);
+ }
+ }
+
+ loop();
+ }
+ };
+ },
+
+ Do: function (body, condition) {
+ return {
+ next: function (_this, callback) {
+
+ var loop = function () {
+ body.next(_this, function (type, value, target) {
+ if (type == "normal" || type == "continue") {
+ try {
+ if (condition.call(_this)) {
+ loop();
+ } else {
+ callback("normal");
+ }
+ } catch (ex) {
+ callback("throw", ex);
+ }
+ } else if (type == "throw" || type == "return") {
+ callback(type, value);
+ } else if (type == "break") {
+ callback("normal");
+ } else {
+ throw new Error('Invalid type for "Loop": ' + type);
+ }
+ });
+ };
+
+ loop();
+ }
+ };
+ },
+
+ Delay: function (generator) {
+ return {
+ next: function (_this, callback) {
+ try {
+ var step = generator.call(_this);
+ step.next(_this, callback);
+ } catch (ex) {
+ callback("throw", ex);
+ }
+ }
+ };
+ },
+
+ Combine: function (s1, s2) {
+ return {
+ next: function (_this, callback) {
+ s1.next(_this, function (type, value, target) {
+ if (type == "normal") {
+ try {
+ s2.next(_this, callback);
+ } catch (ex) {
+ callback("throw", ex);
+ }
+ } else {
+ callback(type, value, target);
+ }
+ });
+ }
+ };
+ },
+
+ Return: function (result) {
+ return {
+ next: function (_this, callback) {
+ callback("return", result);
+ }
+ };
+ },
+
+ Normal: function () {
+ return {
+ next: function (_this, callback) {
+ callback("normal");
+ }
+ };
+ },
+
+ Break: function () {
+ return {
+ next: function (_this, callback) {
+ callback("break");
+ }
+ };
+ },
+
+ Continue: function () {
+ return {
+ next: function (_this, callback) {
+ callback("continue");
+ }
+ };
+ },
+
+ Throw: function (ex) {
+ return {
+ next: function (_this, callback) {
+ callback("throw", ex);
+ }
+ };
+ },
+
+ Try: function (tryTask, catchGenerator, finallyStep) {
+ return {
+ next: function (_this, callback) {
+ tryTask.next(_this, function (type, value, target) {
+ if (type != "throw" || !catchGenerator) {
+ if (!finallyStep) {
+ callback(type, value, target);
+ } else {
+ finallyStep.next(_this, function (finallyType, finallyValue, finallyTarget) {
+ if (finallyType == "normal") {
+ callback(type, value, target);
+ } else {
+ callback(finallyType, finallyValue, finallyTarget);
+ }
+ });
+ }
+ } else {
+
+ if (catchGenerator) {
+
+ var catchTask;
+ try {
+ catchTask = catchGenerator.call(_this, value);
+ } catch (ex) {
+ if (finallyStep) {
+ finallyStep.next(_this, function (finallyType, finallyValue, finallyTarget) {
+ if (finallyType == "normal") {
+ callback("throw", ex);
+ } else {
+ callback(finallyType, finallyValue, finallyTarget);
+ }
+ });
+ } else {
+ callback("throw", ex);
+ }
+ }
+
+ if (catchTask) {
+ catchTask.next(_this, function (catchType, catchValue, catchTarget) {
+ if (catchType == "throw") {
+ if (finallyStep) {
+ finallyStep.next(_this, function (finallyType, finallyValue, finallyTarget) {
+ if (finallyType == "normal") {
+ callback(catchType, catchValue, catchTarget);
+ } else {
+ callback(finallyType, finallyValue, finallyTarget);
+ }
+ });
+ } else {
+ callback(catchType, catchValue, catchTarget);
+ }
+ } else {
+ if (finallyStep) {
+ finallyStep.next(_this, function (finallyType, finallyValue, finallyTarget) {
+ if (finallyType == "normal") {
+ callback(catchType, catchValue, catchTarget);
+ } else {
+ callback(finallyType, finallyValue, finallyTarget);
+ }
+ });
+ } else {
+ callback(catchType, catchValue, catchTarget);
+ }
+ }
+ });
+ }
+ } else {
+ finallyStep.next(_this, function (finallyType, finallyValue, finallyTarget) {
+ if (finallyType == "normal") {
+ callback(type, value, target);
+ } else {
+ callback(finallyType, finallyValue, finallyTarget);
+ }
+ });
+ }
+ }
+ });
+ }
+ };
+ }
+ }
+
+ // CommonJS
+ var isCommonJS = !!(typeof require === "function" && typeof module !== "undefined" && module.exports);
+ // CommonJS AMD
+ var isAmd = !!(typeof require === "function" && typeof define === "function" && define.amd);
+
+ var Jscex;
+
+ var defineModule = function () {
+ Jscex.define({
+ name: "builderbase",
+ version: "0.6.5",
+ exports: isCommonJS && module.exports,
+ require: isCommonJS && require,
+ dependencies: { core: "~0.6.5" },
+ init: function () {
+ Jscex.BuilderBase = BuilderBase;
+ }
+ });
+ }
+
+ if (isCommonJS) {
+ try {
+ Jscex = require("./jscex");
+ } catch (ex) {
+ Jscex = require("jscex");
+ }
+
+ defineModule();
+ } else if (isAmd) {
+ require("jscex", function (jscex) {
+ Jscex = jscex;
+ defineModule();
+ });
+ } else {
+ var Fn = Function, global = Fn('return this')();
+ if (!global.Jscex) {
+ throw new Error('Missing the root object, please load "jscex" component first.');
+ }
+
+ Jscex = global.Jscex;
+ defineModule();
+ }
+})();
1,696 bin/dev/jscex-jit-0.6.5.js
View
@@ -0,0 +1,1696 @@
+(function () {
+ "use strict";
+
+ var Jscex;
+
+ var codeGenerator = (typeof eval("(function () {})") == "function") ?
+ function (code) { return code; } :
+ function (code) { return "false || " + code; };
+
+ // support string type only.
+ var stringify = (typeof JSON !== "undefined" && JSON.stringify) ?
+ function (s) { return JSON.stringify(s); } :
+ (function () {
+ // Implementation comes from JSON2 (http://www.json.org/js.html)
+
+ var escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
+
+ var meta = { // table of character substitutions
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '"' : '\\"',
+ '\\': '\\\\'
+ }
+
+ return function (s) {
+ // If the string contains no control characters, no quote characters, and no
+ // backslash characters, then we can safely slap some quotes around it.
+ // Otherwise we must also replace the offending characters with safe escape
+ // sequences.
+
+ escapable.lastIndex = 0;
+ return escapable.test(s) ? '"' + s.replace(escapable, function (a) {
+ var c = meta[a];
+ return typeof c === 's' ? c :
+ '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ }) + '"' : '"' + s + '"';
+ };
+ })();
+
+ function sprintf(format) {
+ var args = arguments;
+ return format.toString().replace(new RegExp("{\\d+}", "g"), function (p) {
+ var n = parseInt(p.substring(1, p.length - 1), 10);
+ return args[n + 1];
+ });
+ }
+
+ function trim(s) {
+ return s.replace(/ +/g, "");
+ }
+
+ function getPrecedence(ast) {
+ var type = ast[0];
+ switch (type) {
+ case "dot": // .
+ case "sub": // []
+ case "call": // ()
+ return 1;
+ case "unary-postfix": // ++ -- - ~ ! delete new typeof void
+ case "unary-prefix":
+ return 2;
+ case "var":
+ case "binary":
+ switch (ast[1]) {
+ case "*":
+ case "/":
+ case "%":
+ return 3;
+ case "+":
+ case "-":
+ return 4;
+ case "<<":
+ case ">>":
+ case ">>>":
+ return 5;
+ case "<":
+ case "<=":
+ case ">":
+ case ">=":
+ case "instanceof":
+ return 6;
+ case "==":
+ case "!=":
+ case "===":
+ case "!==":
+ return 7;
+ case "&":
+ return 8;
+ case "^":
+ return 9;
+ case "|":
+ return 10;
+ case "&&":
+ return 11;
+ case "||":
+ return 12;
+ }
+ case "conditional":
+ return 13;
+ case "assign":
+ return 14;
+ case "new":
+ return 15;
+ case "seq":
+ case "stat":
+ case "name":
+ case "object":
+ case "array":
+ case "num":
+ case "regexp":
+ case "string":
+ case "function":
+ case "defun":
+ case "for":
+ case "for-in":
+ case "block":
+ case "while":
+ case "do":
+ case "if":
+ case "break":
+ case "continue":
+ case "return":
+ case "throw":
+ case "try":
+ case "switch":
+ return 0;
+ default:
+ return 100; // the lowest
+ }
+ }
+
+ var CodeWriter = function (indent) {
+ this._indent = indent || " ";
+ this._indentLevel = 0;
+
+ this.lines = [];
+ }
+ CodeWriter.prototype = {
+ write: function (format) {
+ if (this.lines.length == 0) {
+ this.lines.push("");
+ }
+
+ var args = arguments;
+ if (args.length <= 0) return this;
+
+ var str = format.toString().replace(new RegExp("{\\d+}", "g"), function (p) {
+ var n = parseInt(p.substring(1, p.length - 1), 10);
+ return args[n + 1];
+ });
+
+ this.lines[this.lines.length - 1] += str;
+ return this;
+ },
+
+ writeLine: function () {
+ this.write.apply(this, arguments);
+ this.lines.push("");
+ return this;
+ },
+
+ writeIndents: function () {
+ var indents = new Array(this._indentLevel);
+ for (var i = 0; i < this._indentLevel; i++) {
+ indents[i] = this._indent;
+ }
+
+ this.write(indents.join(""));
+ return this;
+ },
+
+ addIndentLevel: function (diff) {
+ this._indentLevel += diff;
+ return this;
+ }
+ };
+
+ var SeedProvider = function () {
+ this._seeds = {};
+ }
+ SeedProvider.prototype.next = function (key) {
+ var value = this._seeds[key];
+ if (value == undefined) {
+ this._seeds[key] = 0;
+ return 0;
+ } else {
+ this._seeds[key] = ++value;
+ return value;
+ }
+ }
+
+ function isJscexPattern(ast) {
+ if (ast[0] != "call") return false;
+
+ var evalName = ast[1];
+ if (evalName[0] != "name" || evalName[1] != "eval") return false;
+
+ var compileCall = ast[2][0];
+ if (!compileCall || compileCall[0] != "call") return false;
+
+ var compileMethod = compileCall[1];
+ if (!compileMethod || compileMethod[0] != "dot" || compileMethod[2] != "compile") return false;
+
+ var jscexName = compileMethod[1];
+ if (!jscexName || jscexName[0] != "name" || jscexName[1] != "Jscex") return false;
+
+ var builder = compileCall[2][0];
+ if (!builder || builder[0] != "string") return false;
+
+ var func = compileCall[2][1];
+ if (!func || func[0] != "function") return false;
+
+ return true;
+ }
+
+ function compileJscexPattern(ast, seedProvider, codeWriter, commentWriter) {
+
+ var builderName = ast[2][0][2][0][1];
+ var funcAst = ast[2][0][2][1];
+
+ var jscexTreeGenerator = new JscexTreeGenerator(builderName, seedProvider);
+ var jscexAst = jscexTreeGenerator.generate(funcAst);
+
+ commentWriter.write("{0} << ", builderName);
+ var codeGenerator = new CodeGenerator(builderName, seedProvider, codeWriter, commentWriter);
+ codeGenerator.generate(funcAst[2], jscexAst);
+ }
+
+ var JscexTreeGenerator = function (builderName, seedProvider) {
+ this._binder = Jscex.binders[builderName];
+ this._seedProvider = seedProvider;
+ }
+ JscexTreeGenerator.prototype = {
+
+ generate: function (ast) {
+
+ var params = ast[2], statements = ast[3];
+
+ var rootAst = { type: "delay", stmts: [] };
+
+ this._visitStatements(statements, rootAst.stmts);
+
+ return rootAst;
+ },
+
+ _getBindInfo: function (stmt) {
+
+ var type = stmt[0];
+ if (type == "stat") {
+ var expr = stmt[1];
+ if (expr[0] == "call") {
+ var callee = expr[1];
+ if (callee[0] == "name" && callee[1] == this._binder && expr[2].length == 1) {
+ return {
+ expression: expr[2][0],
+ argName: "",
+ assignee: null
+ };
+ }
+ } else if (expr[0] == "assign") {
+ var assignee = expr[2];
+ expr = expr[3];
+ if (expr[0] == "call") {
+ var callee = expr[1];
+ if (callee[0] == "name" && callee[1] == this._binder && expr[2].length == 1) {
+ return {
+ expression: expr[2][0],
+ argName: "_result_$",
+ assignee: assignee
+ };
+ }
+ }
+ }
+ } else if (type == "var") {
+ var defs = stmt[1];
+ if (defs.length == 1) {
+ var item = defs[0];
+ var name = item[0];
+ var expr = item[1];
+ if (expr && expr[0] == "call") {
+ var callee = expr[1];
+ if (callee[0] == "name" && callee[1] == this._binder && expr[2].length == 1) {
+ return {
+ expression: expr[2][0],
+ argName: name,
+ assignee: null
+ };
+ }
+ }
+ }
+ } else if (type == "return") {
+ var expr = stmt[1];
+ if (expr && expr[0] == "call") {
+ var callee = expr[1];
+ if (callee[0] == "name" && callee[1] == this._binder && expr[2].length == 1) {
+ return {
+ expression: expr[2][0],
+ argName: "_result_$",
+ assignee: "return"
+ };
+ }
+ }
+ }
+
+ return null;
+ },
+
+ _visitStatements: function (statements, stmts, index) {
+ if (arguments.length <= 2) index = 0;
+
+ if (index >= statements.length) {
+ stmts.push({ type: "normal" });
+ return this;
+ }
+
+ var currStmt = statements[index];
+ var bindInfo = this._getBindInfo(currStmt);
+
+ if (bindInfo) {
+ var bindStmt = { type: "bind", info: bindInfo };
+ stmts.push(bindStmt);
+
+ if (bindInfo.assignee != "return") {
+ bindStmt.stmts = [];
+ this._visitStatements(statements, bindStmt.stmts, index + 1);
+ }
+
+ } else {
+ var type = currStmt[0];
+ if (type == "return" || type == "break" || type == "continue" || type == "throw") {
+
+ stmts.push({ type: type, stmt: currStmt });
+
+ } else if (type == "if" || type == "try" || type == "for" || type == "do"
+ || type == "while" || type == "switch" || type == "for-in") {
+
+ var newStmt = this._visit(currStmt);
+
+ if (newStmt.type == "raw") {
+ stmts.push(newStmt);
+ this._visitStatements(statements, stmts, index + 1);
+ } else {
+ var isLast = (index == statements.length - 1);
+ if (isLast) {
+ stmts.push(newStmt);
+ } else {
+
+ var combineStmt = {
+ type: "combine",
+ first: { type: "delay", stmts: [newStmt] },
+ second: { type: "delay", stmts: [] }
+ };
+ stmts.push(combineStmt);
+
+ this._visitStatements(statements, combineStmt.second.stmts, index + 1);
+ }
+ }
+
+ } else {
+
+ stmts.push({ type: "raw", stmt: currStmt });
+
+ this._visitStatements(statements, stmts, index + 1);
+ }
+ }
+
+ return this;
+ },
+
+ _visit: function (ast) {
+
+ var type = ast[0];
+
+ function throwUnsupportedError() {
+ throw new Error('"' + type + '" is not currently supported.');
+ }
+
+ var visitor = this._visitors[type];
+
+ if (visitor) {
+ return visitor.call(this, ast);
+ } else {
+ throwUnsupportedError();
+ }
+ },
+
+ _visitBody: function (ast, stmts) {
+ if (ast[0] == "block") {
+ this._visitStatements(ast[1], stmts);
+ } else {
+ this._visitStatements([ast], stmts);
+ }
+ },
+
+ _noBinding: function (stmts) {
+ switch (stmts[stmts.length - 1].type) {
+ case "normal":
+ case "return":
+ case "break":
+ case "throw":
+ case "continue":
+ return true;
+ }
+
+ return false;
+ },
+
+ _collectCaseStatements: function (cases, index) {
+ var res = [];
+
+ for (var i = index; i < cases.length; i++) {
+ var rawStmts = cases[i][1];
+ for (var j = 0; j < rawStmts.length; j++) {
+ if (rawStmts[j][0] == "break") {
+ return res
+ }
+
+ res.push(rawStmts[j]);
+ }
+ }
+
+ return res;
+ },
+
+ _visitors: {
+
+ "for": function (ast) {
+ var bodyStmts = [];
+ var body = ast[4];
+ this._visitBody(body, bodyStmts);
+
+ if (this._noBinding(bodyStmts)) {
+ return { type: "raw", stmt: ast };
+ }
+
+ var delayStmt = { type: "delay", stmts: [] };
+
+ var setup = ast[1];
+ if (setup) {
+ delayStmt.stmts.push({ type: "raw", stmt: setup });
+ }
+
+ var forStmt = { type: "for", bodyStmt: { type: "delay", stmts: bodyStmts } };
+ delayStmt.stmts.push(forStmt);
+
+ var condition = ast[2];
+ if (condition) {
+ forStmt.condition = condition;
+ }
+
+ var update = ast[3];
+ if (update) {
+ forStmt.update = update;
+ }
+
+ return delayStmt;
+ },
+
+ "for-in": function (ast) {
+
+ var body = ast[4];
+
+ var bodyStmts = [];
+ this._visitBody(body, bodyStmts);
+
+ if (this._noBinding(bodyStmts)) {
+ return { type: "raw", stmt: ast };
+ }
+
+ var forInStmt = { type: "for-in", bodyStmts: bodyStmts, obj: ast[3] };
+
+ var argName = ast[2][1]; // ast[2] == ["name", m]
+ if (ast[1][0] == "var") {
+ forInStmt.argName = argName;
+ } else {
+ var keyVar = "_forInKey_$" + this._seedProvider.next("forInKey");
+ forInStmt.argName = keyVar;
+ forInStmt.bodyStmts.unshift({
+ type: "raw",
+ stmt: Jscex.parse(argName + " = " + keyVar + ";")[1][0]
+ });
+ }
+
+ return forInStmt;
+ },
+
+ "while": function (ast) {
+
+ var bodyStmts = [];
+ var body = ast[2];
+ this._visitBody(body, bodyStmts);
+
+ if (this._noBinding(bodyStmts)) {
+ return { type: "raw", stmt: ast }
+ }
+
+ var loopStmt = { type: "while", bodyStmt: { type: "delay", stmts: bodyStmts } };
+
+ var condition = ast[1];
+ loopStmt.condition = condition;
+
+ return loopStmt;
+ },
+
+ "do": function (ast) {
+
+ var bodyStmts = [];
+ var body = ast[2];
+ this._visitBody(body, bodyStmts);
+
+ if (this._noBinding(bodyStmts)) {
+ return { type: "raw", stmt: ast };
+ }
+
+ var doStmt = {
+ type: "do",
+ bodyStmt: { type: "delay", stmts: bodyStmts },
+ condition: ast[1]
+ };
+
+ return doStmt;
+ },
+
+ "switch": function (ast) {
+ var noBinding = true;
+
+ var switchStmt = { type: "switch", item: ast[1], caseStmts: [] };
+
+ var cases = ast[2];
+ for (var i = 0; i < cases.length; i++) {
+ var caseStmt = { item: cases[i][0], stmts: [] };
+ switchStmt.caseStmts.push(caseStmt);
+
+ var statements = this._collectCaseStatements(cases, i);
+ this._visitStatements(statements, caseStmt.stmts);
+ noBinding = noBinding && this._noBinding(caseStmt.stmts);
+ }
+
+ if (noBinding) {
+ return { type: "raw", stmt: ast };
+ } else {
+ return switchStmt;
+ }
+ },
+
+ "if": function (ast) {
+
+ var noBinding = true;
+
+ var ifStmt = { type: "if", conditionStmts: [] };
+
+ var currAst = ast;
+ while (true) {
+ var condition = currAst[1];
+ var condStmt = { cond: condition, stmts: [] };
+ ifStmt.conditionStmts.push(condStmt);
+
+ var thenPart = currAst[2];
+ this._visitBody(thenPart, condStmt.stmts);
+
+ noBinding = noBinding && this._noBinding(condStmt.stmts);
+
+ var elsePart = currAst[3];
+ if (elsePart && elsePart[0] == "if") {
+ currAst = elsePart;
+ } else {
+ break;
+ }
+ }
+
+ var elsePart = currAst[3];
+ if (elsePart) {
+ ifStmt.elseStmts = [];
+
+ this._visitBody(elsePart, ifStmt.elseStmts);
+
+ noBinding = noBinding && this._noBinding(ifStmt.elseStmts);
+ }
+
+ if (noBinding) {
+ return { type: "raw", stmt: ast };
+ } else {
+ return ifStmt;
+ }
+ },
+
+ "try": function (ast, stmts) {
+
+ var bodyStmts = [];
+ var bodyStatements = ast[1];
+ this._visitStatements(bodyStatements, bodyStmts);
+
+ var noBinding = this._noBinding(bodyStmts)
+
+ var tryStmt = { type: "try", bodyStmt: { type: "delay", stmts: bodyStmts } };
+
+ var catchClause = ast[2];
+ if (catchClause) {
+ var exVar = catchClause[0];
+ tryStmt.exVar = exVar;
+ tryStmt.catchStmts = [];
+
+ this._visitStatements(catchClause[1], tryStmt.catchStmts);
+
+ noBinding = noBinding && this._noBinding(tryStmt.catchStmts);
+ }
+
+ var finallyStatements = ast[3];
+ if (finallyStatements) {
+ tryStmt.finallyStmt = { type: "delay", stmts: [] };
+
+ this._visitStatements(finallyStatements, tryStmt.finallyStmt.stmts);
+
+ noBinding = noBinding && this._noBinding(tryStmt.finallyStmt.stmts);
+ }
+
+ if (noBinding) {
+ return { type: "raw", stmt: ast };
+ } else {
+ return tryStmt;
+ }
+ }
+ }
+ }
+
+ var CodeGenerator = function (builderName, seedProvider, codeWriter, commentWriter) {
+ this._builderName = builderName;
+ this._binder = Jscex.binders[builderName];
+ this._seedProvider = seedProvider;
+
+ this._codeWriter = codeWriter;
+ this._commentWriter = commentWriter;
+ }
+ CodeGenerator.prototype = {
+
+ _code: function () {
+ this._codeWriter.write.apply(this._codeWriter, arguments);
+ return this;
+ },
+
+ _codeLine: function () {
+ this._codeWriter.writeLine.apply(this._codeWriter, arguments);
+ return this;
+ },
+
+ _codeIndents: function () {
+ this._codeWriter.writeIndents();
+ return this;
+ },
+
+ _codeIndentLevel: function (diff) {
+ this._codeWriter.addIndentLevel(diff);
+ return this;
+ },
+
+ _comment: function () {
+ this._commentWriter.write.apply(this._commentWriter, arguments);
+ return this;
+ },
+
+ _commentLine: function () {
+ this._commentWriter.writeLine.apply(this._commentWriter, arguments);
+ return this;
+ },
+
+ _commentIndents: function () {
+ this._commentWriter.writeIndents();
+ return this;
+ },
+
+ _commentIndentLevel: function (diff) {
+ this._commentWriter.addIndentLevel(diff);
+ return this;
+ },
+
+ _both: function () {
+ this._codeWriter.write.apply(this._codeWriter, arguments);
+ this._commentWriter.write.apply(this._commentWriter, arguments);
+
+ return this;
+ },
+
+ _bothLine: function () {
+ this._codeWriter.writeLine.apply(this._codeWriter, arguments);
+ this._commentWriter.writeLine.apply(this._commentWriter, arguments);
+
+ return this;
+ },
+
+ _bothIndents: function () {
+ this._codeWriter.writeIndents();
+ this._commentWriter.writeIndents();
+
+ return this;
+ },
+
+ _bothIndentLevel: function (diff) {
+ this._codeWriter.addIndentLevel(diff);
+ this._commentWriter.addIndentLevel(diff);
+
+ return this;
+ },
+
+ _newLine: function () {
+ this._codeWriter.writeLine.apply(this._codeWriter, arguments);
+ this._commentWriter.writeLine(); // To Remove
+ return this;
+ },
+
+ generate: function (params, jscexAst) {
+ this._normalMode = false;
+ this._builderVar = "_builder_$" + this._seedProvider.next("builderId");
+
+ this._codeLine("(function ({0}) {", params.join(", "))._commentLine("function ({0}) {", params.join(", "));
+ this._bothIndentLevel(1);
+
+ this._codeIndents()._newLine("var {0} = Jscex.builders[{1}];", this._builderVar, stringify(this._builderName));
+
+ this._codeIndents()._newLine("return {0}.Start(this,", this._builderVar);
+ this._codeIndentLevel(1);
+
+ this._pos = { };
+
+ this._bothIndents()._visitJscex(jscexAst)._newLine();
+ this._codeIndentLevel(-1);
+
+ this._codeIndents()._newLine(");");
+ this._bothIndentLevel(-1);
+
+ this._bothIndents()._code("})")._comment("}");
+ },
+
+ _visitJscex: function (ast) {
+ this._jscexVisitors[ast.type].call(this, ast);
+ return this;
+ },
+
+ _visitRaw: function (ast) {
+ var type = ast[0];
+
+ var visitor = this._rawVisitors[type];
+ if (visitor) {
+ visitor.call(this, ast);
+ } else {
+ throw new Error('"' + type + '" is not currently supported.');
+ }
+
+ return this;
+ },
+
+ _visitJscexStatements: function (statements) {
+ for (var i = 0; i < statements.length; i++) {
+ var stmt = statements[i];
+
+ if (stmt.type == "raw" || stmt.type == "if" || stmt.type == "switch") {
+ this._bothIndents()._visitJscex(stmt)._newLine();
+ } else if (stmt.type == "delay") {
+ this._visitJscexStatements(stmt.stmts);
+ } else {
+ this._bothIndents()._code("return ")._visitJscex(stmt)._newLine(";");
+ }
+ }
+ },
+
+ _visitRawStatements: function (statements) {
+ for (var i = 0; i < statements.length; i++) {
+ var s = statements[i];
+
+ this._bothIndents()._visitRaw(s)._bothLine();
+
+ switch (s[0]) {
+ case "break":
+ case "return":
+ case "continue":
+ case "throw":
+ return;
+ }
+ }
+ },
+
+ _visitRawBody: function (body) {
+ if (body[0] == "block") {
+ this._visitRaw(body);
+ } else {
+ this._bothLine();
+ this._bothIndentLevel(1);
+
+ this._bothIndents()._visitRaw(body);
+ this._bothIndentLevel(-1);
+ }
+
+ return this;
+ },
+
+ _visitRawFunction: function (ast) {
+ var funcName = ast[1] || "";
+ var args = ast[2];
+ var statements = ast[3];
+
+ this._bothLine("function " + funcName + "(" + args.join(", ") + ") {")
+ this._bothIndentLevel(1);
+
+ var currInFunction = this._pos.inFunction;
+ this._pos.inFunction = true;
+
+ this._visitRawStatements(statements);
+ this._bothIndentLevel(-1);
+
+ this._pos.inFunction = currInFunction;
+
+ this._bothIndents()._both("}");
+ },
+
+ _jscexVisitors: {
+ "delay": function (ast) {
+ if (ast.stmts.length == 1) {
+ var subStmt = ast.stmts[0];
+ switch (subStmt.type) {
+ case "delay":
+ case "combine":
+ case "normal":
+ case "break":
+ case "continue":
+ case "for":
+ case "for-in":
+ case "while":
+ case "do":
+ case "try":
+ this._visitJscex(subStmt);
+ return;
+ case "return":
+ if (!subStmt.stmt[1]) {
+ this._visitJscex(subStmt);
+ return;
+ }
+ }
+ }
+
+ this._newLine(this._builderVar + ".Delay(function () {");
+ this._codeIndentLevel(1);
+
+ this._visitJscexStatements(ast.stmts);
+ this._codeIndentLevel(-1);
+
+ this._codeIndents()._code("})");
+ },
+
+ "combine": function (ast) {
+ this._newLine(this._builderVar + ".Combine(");
+ this._codeIndentLevel(1);
+
+ this._bothIndents()._visitJscex(ast.first)._newLine(",");
+ this._bothIndents()._visitJscex(ast.second)._newLine();
+ this._codeIndentLevel(-1);
+
+ this._codeIndents()._code(")");
+ },
+
+ "for": function (ast) {
+ if (ast.condition) {
+ this._codeLine(this._builderVar + ".For(function () {")
+ ._commentLine("for (");
+ this._codeIndentLevel(1);
+
+ this._bothIndents()
+ ._code("return ")
+ ._comment("; ")
+ ._visitRaw(ast.condition)
+ ._newLine(";");
+ this._codeIndentLevel(-1);
+
+ this._bothIndents()._code("}, ");
+ } else {
+ this._code(this._builderVar + ".For(null, ")
+ ._comment("for (; ");
+ }
+
+ if (ast.update) {
+ this._newLine("function () {");
+ this._codeIndentLevel(1);
+
+ this._bothIndents()
+ ._comment("; ")
+ ._visitRaw(ast.update)
+ ._codeLine(";")
+ ._commentLine(") {");
+ this._codeIndentLevel(-1);
+
+ this._codeIndents()._newLine("},");
+ } else {
+ this._codeLine("null,")._commentLine("; ) {");
+ }
+ this._bothIndentLevel(1);
+
+ this._bothIndents()._visitJscex(ast.bodyStmt)._newLine();
+ this._bothIndentLevel(-1);
+
+ this._bothIndents()._code(")")._comment("}");
+ },
+
+ "for-in": function (ast) {
+ this._code(this._builderVar + ".ForIn(")
+ ._comment("for (var {0} in ", ast.argName)
+ ._visitRaw(ast.obj)
+ ._codeLine(", function ({0}) {", ast.argName)
+ ._commentLine(") {");
+ this._bothIndentLevel(1);
+
+ this._visitJscexStatements(ast.bodyStmts);
+ this._bothIndentLevel(-1);
+
+ this._bothIndents()._code("})")._comment("}");
+ },
+
+ "while": function (ast) {
+ this._newLine(this._builderVar + ".While(function () {");
+ this._codeIndentLevel(1);
+
+ this._bothIndents()
+ ._code("return ")
+ ._comment("while (")
+ ._visitRaw(ast.condition)
+ ._codeLine(";")
+ ._commentLine(") {");
+ this._codeIndentLevel(-1);
+
+ this._codeIndents()._newLine("},");
+ this._bothIndentLevel(1);
+
+ this._bothIndents()._visitJscex(ast.bodyStmt)._newLine();
+ this._bothIndentLevel(-1);
+
+ this._bothIndents()._code(")")._comment("}");
+ },
+
+ "do": function (ast) {
+ this._codeLine(this._builderVar + ".Do(")._commentLine("do {");
+ this._bothIndentLevel(1);
+
+ this._bothIndents()._visitJscex(ast.bodyStmt)._newLine(",");
+ this._commentIndentLevel(-1);
+
+ this._codeIndents()._newLine("function () {");
+ this._codeIndentLevel(1);
+
+ this._bothIndents()
+ ._code("return ")
+ ._comment("} while (")
+ ._visitRaw(ast.condition)
+ ._codeLine(";")
+ ._commentLine(");");
+ this._codeIndentLevel(-1);
+
+ this._codeIndents()._newLine("}");
+ this._codeIndentLevel(-1);
+
+ this._codeIndents()._code(")");
+ },
+
+ "raw": function (ast) {
+ this._visitRaw(ast.stmt, true);
+ },
+
+ "bind": function (ast) {
+ var info = ast.info;
+
+ var commentPrefix = "";
+ if (info.assignee == "return") {
+ commentPrefix = "return ";
+ } else if (info.argName != "") {
+ commentPrefix = "var " + info.argName + " = ";
+ }
+
+ this._code(this._builderVar + ".Bind(")._comment(commentPrefix + this._binder + "(")._visitRaw(info.expression)._comment(");")._newLine(", function (" + info.argName + ") {");
+ this._codeIndentLevel(1);
+
+ if (info.assignee == "return") {
+ this._codeIndents()
+ ._newLine("return " + this._builderVar + ".Return(" + info.argName + ");");
+ } else {
+ if (info.assignee) {
+ this._bothIndents()
+ ._visitRaw(info.assignee)._bothLine(" = " + info.argName + ";");
+ }
+
+ this._visitJscexStatements(ast.stmts);
+ }
+ this._codeIndentLevel(-1);
+
+ this._codeIndents()
+ ._code("})");
+ },
+
+ "if": function (ast) {
+
+ for (var i = 0; i < ast.conditionStmts.length; i++) {
+ var stmt = ast.conditionStmts[i];
+
+ this._both("if (")._visitRaw(stmt.cond)._bothLine(") {");
+ this._bothIndentLevel(1);
+
+ this._visitJscexStatements(stmt.stmts);
+ this._bothIndentLevel(-1);
+
+ if (i < ast.conditionStmts.length - 1 || ast.elseStmts) {
+ this._bothIndents()._both("} else ");
+ } else {
+ this._bothIndents()._code("} else ")._comment("}");
+ }
+ }
+
+ if (ast.elseStmts) {
+ this._bothLine("{");
+ this._bothIndentLevel(1);
+ } else {
+ this._newLine("{");
+ this._codeIndentLevel(1);
+ }
+
+ if (ast.elseStmts) {
+ this._visitJscexStatements(ast.elseStmts);
+ } else {
+ this._codeIndents()
+ ._newLine("return " + this._builderVar + ".Normal();");
+ }
+
+ if (ast.elseStmts) {
+ this._bothIndentLevel(-1);
+ } else {
+ this._codeIndentLevel(-1);
+ }
+
+ if (ast.elseStmts) {
+ this._bothIndents()
+ ._both("}");
+ } else {
+ this._codeIndents()
+ ._code("}");
+ }
+ },
+
+ "switch": function (ast) {
+ this._both("switch (")._visitRaw(ast.item)._bothLine(") {");
+ this._bothIndentLevel(1);
+
+ for (var i = 0; i < ast.caseStmts.length; i++) {
+ var caseStmt = ast.caseStmts[i];
+
+ if (caseStmt.item) {
+ this._bothIndents()
+ ._both("case ")._visitRaw(caseStmt.item)._bothLine(":");
+ } else {
+ this._bothIndents()._bothLine("default:");
+ }
+ this._bothIndentLevel(1);
+
+ this._visitJscexStatements(caseStmt.stmts);
+ this._bothIndentLevel(-1);
+ }
+
+ this._bothIndents()._code("}");
+ },
+
+ "try": function (ast) {
+ this._codeLine(this._builderVar + ".Try(")._commentLine("try {");
+ this._bothIndentLevel(1);
+
+ this._bothIndents()._visitJscex(ast.bodyStmt)._newLine(",");
+ this._commentIndentLevel(-1);
+
+ if (ast.catchStmts) {
+ this._bothIndents()
+ ._codeLine("function ({0}) {", ast.exVar)
+ ._commentLine("} catch ({0}) {", ast.exVar);
+ this._bothIndentLevel(1);
+
+ this._visitJscexStatements(ast.catchStmts);
+ this._bothIndentLevel(-1);
+
+ this._bothIndents()._codeLine("},");
+ if (ast.finallyStmt) {
+ this._commentLine("} finally {");
+ } else {
+ this._commentLine("}");
+ }
+ } else {
+ this._bothIndents()._codeLine("null,")._commentLine("} finally {");
+ }
+
+ if (ast.finallyStmt) {
+ this._commentIndentLevel(1);
+ this._bothIndents()._visitJscex(ast.finallyStmt)._newLine();
+ this._commentIndentLevel(-1);
+ } else {
+ this._codeIndents()._newLine("null");
+ }
+ this._codeIndentLevel(-1);
+
+ this._codeIndents()._code(")");
+ if (ast.finallyStmt) {
+ this._commentIndents()._comment("}");
+ }
+ },
+
+ "normal": function (ast) {
+ this._code(this._builderVar + ".Normal()");
+ },
+
+ "throw": function (ast) {
+ this
+ ._code(this._builderVar + ".Throw(")
+ ._comment("throw ")
+ ._visitRaw(ast.stmt[1])
+ ._code(")")._comment(";");
+ },
+
+ "break": function (ast) {
+ this._code(this._builderVar + ".Break()")._comment("break;");
+ },
+
+ "continue": function (ast) {
+ this._code(this._builderVar + ".Continue()")._comment("continue;");
+ },
+
+ "return": function (ast) {
+ this._code(this._builderVar + ".Return(")._comment("return");
+ if (ast.stmt[1]) {
+ this._comment(" ")._visitRaw(ast.stmt[1]);
+ }
+
+ this._code(")")._comment(";");
+ }
+ },
+
+ _rawVisitors: {
+ "var": function (ast) {
+ this._both("var ");
+
+ var items = ast[1];
+ for (var i = 0; i < items.length; i++) {
+ this._both(items[i][0]);
+ if (items[i].length > 1) {
+ this._both(" = ")._visitRaw(items[i][1]);
+ }
+ if (i < items.length - 1) this._both(", ");
+ }
+
+ this._both(";");
+ },
+
+ "seq": function (ast, noBracket) {
+ var left = ast[1];
+ var right = ast[2];
+
+ if (!noBracket) this._both("(");
+
+ this._visitRaw(left);
+ this._both(", ");
+
+ if (right[0] == "seq") {
+ arguments.callee.call(this, right, true);
+ } else {
+ this._visitRaw(right);
+ }
+
+ if (!noBracket) this._both(")");
+ },
+
+ "binary": function (ast) {
+ var op = ast[1], left = ast[2], right = ast[3];
+
+ if (getPrecedence(ast) < getPrecedence(left)) {
+ this._both("(")._visitRaw(left)._both(") ");
+ } else {
+ this._visitRaw(left)._both(" ");
+ }
+
+ this._both(op);
+
+ if (getPrecedence(ast) <= getPrecedence(right)) {
+ this._both(" (")._visitRaw(right)._both(")");
+ } else {
+ this._both(" ")._visitRaw(right);
+ }
+ },
+
+ "sub": function (ast) {
+ var prop = ast[1], index = ast[2];
+
+ if (getPrecedence(ast) < getPrecedence(prop)) {
+ this._both("(")._visitRaw(prop)._both(")[")._visitRaw(index)._both("]");
+ } else {
+ this._visitRaw(prop)._both("[")._visitRaw(index)._both("]");
+ }
+ },
+
+ "unary-postfix": function (ast) {
+ var op = ast[1];
+ var item = ast[2];
+
+ if (getPrecedence(ast) <= getPrecedence(item)) {
+ this._both("(")._visitRaw(item)._both(")");
+ } else {
+ this._visitRaw(item);