Commit 61658005 authored by Yehuda Katz's avatar Yehuda Katz

Reorganize build for multiple modules

parent 4d97d1b9
......@@ -2,56 +2,86 @@ require "bundler/setup"
require "js_module_transpiler"
directory "browser"
directory "node"
directory "tmp"
file "tmp/rsvp.js" => ["lib/loader.js", "lib/async.js", "lib/events.js", "lib/rsvp.js"] do
loader = File.read("lib/loader.js")
async = File.read("lib/async.js")
events = File.read("lib/events.js")
rsvp = File.read("lib/rsvp.js")
output = [
loader,
async,
events,
rsvp,
"export RSVP"
]
File.open("tmp/rsvp.js", "w") do |file|
file.puts output.join("\n")
end
directory "node_modules/rsvp"
def module_contents(file)
File.read("lib/#{file}.js")
end
file "browser/rsvp.js" => ["browser", "lib/rsvp.js"] do
library = File.read("lib/rsvp.js")
open "browser/rsvp.js", "w" do |file|
converter = JsModuleTranspiler::Compiler.new(File.read("./lib/rsvp.js"), "rsvp", into: "RSVP")
file.puts converter.to_globals
def amd_module(filename)
output = "browser/#{filename}.amd.js"
input = "lib/#{filename}.js"
file output => ["browser", input] do
library = File.read(input)
open output, "w" do |file|
require "js_module_transpiler"
converter = JsModuleTranspiler::Compiler.new(library)
file.puts converter.to_amd
end
end
output
end
file "browser/rsvp.amd.js" => ["browser", "lib/rsvp.js"] do
library = File.read("lib/rsvp.js")
open "browser/rsvp.amd.js", "w" do |file|
require "js_module_transpiler"
def node_module(filename, output="node_modules/rsvp/#{filename}.js")
input = "lib/#{filename}.js"
converter = JsModuleTranspiler::Compiler.new(File.read("./lib/rsvp.js"))
file.puts converter.to_amd
file output => ["browser", input] do
library = File.read(input)
open output, "w" do |file|
require "js_module_transpiler"
converter = JsModuleTranspiler::Compiler.new(library)
file.puts converter.to_cjs
end
end
output
end
def read(file)
File.read(file)
end
def name(filename, name)
body = read(filename)
body.sub(/define\(/, "define(#{name.inspect},")
end
file "node/rsvp.js" => ["node", "lib/rsvp.js"] do
library = File.read("lib/rsvp.js")
open "node/rsvp.js", "w" do |file|
require "js_module_transpiler"
# Build the AMD modules
converter = JsModuleTranspiler::Compiler.new(File.read("./lib/rsvp.js"), "rsvp")
file.puts converter.to_cjs
amd_async = amd_module "async"
amd_events = amd_module "events"
amd_rsvp = amd_module "rsvp"
# Build the node modules
node_async = node_module "async"
node_events = node_module "events"
node_main = node_module "rsvp", "main.js"
# Build a browser build based on the AMD modules
file "browser/rsvp.js" => ["browser", amd_async, amd_events, amd_rsvp] do
output = []
output << %|(function() {|
output.concat [read("lib/loader.js"), name(amd_async, "rsvp/async"), name(amd_events, "rsvp/events"), name(amd_rsvp, "rsvp")]
output << %|window.RSVP = requireModule('rsvp');|
output << %|})();|
open("browser/rsvp.js", "w") do |file|
file.puts output.join("\n")
end
end
# Entry point for node build
file node_main => ["node_modules/rsvp", node_async, node_events]
# Minified build
file "browser/rsvp.min.js" => "browser/rsvp.js" do
output = `cat browser/rsvp.js | uglifyjs`
......@@ -60,17 +90,11 @@ file "browser/rsvp.min.js" => "browser/rsvp.js" do
end
end
file "tests/rsvp.js" => "lib/rsvp.js" do
library = File.read("lib/rsvp.js")
open "tests/rsvp.js", "w" do |file|
require "js_module_transpiler"
# Build everything
converter = JsModuleTranspiler::Compiler.new(File.read("./lib/rsvp.js"), "rsvp")
file.puts converter.to_cjs
end
end
task :dist => [amd_async, amd_events, amd_rsvp, "browser/rsvp.js", "browser/rsvp.min.js", node_main]
task :dist => ["browser/rsvp.js", "browser/rsvp.min.js", "browser/rsvp.amd.js", "node/rsvp.js"]
# Testing
directory "tests/tmp"
......@@ -110,7 +134,7 @@ task :update_tests => "promises-tests" do
end
desc "Run the tests using Node"
task :test => [:update_tests, "tests/rsvp.js"] do
task :test => [:update_tests] do
cd "promises-tests" do
sh "node ./lib/cli.js ../tests/test-adapter.js"
end
......@@ -121,5 +145,7 @@ task :browser_test => [:update_tests, "tests/tmp/test-bundle.js", :dist] do
sh "open tests/index.html"
end
# Default task is build everything
desc "Build RSVP.js"
task :default => :dist
define(
["exports"],
function(__exports__) {
"use strict";
var browserGlobal = (typeof window !== 'undefined') ? window : {};
var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
var async;
if (typeof process !== 'undefined' &&
{}.toString.call(process) === '[object process]') {
async = function(callback, binding) {
process.nextTick(function() {
callback.call(binding);
});
};
} else if (BrowserMutationObserver) {
var queue = [];
var observer = new BrowserMutationObserver(function() {
var toProcess = queue.slice();
queue = [];
toProcess.forEach(function(tuple) {
var callback = tuple[0], binding = tuple[1];
callback.call(binding);
});
});
var element = document.createElement('div');
observer.observe(element, { attributes: true });
// Chrome Memory Leak: https://bugs.webkit.org/show_bug.cgi?id=93661
window.addEventListener('unload', function(){
observer.disconnect();
observer = null;
});
async = function(callback, binding) {
queue.push([callback, binding]);
element.setAttribute('drainQueue', 'drainQueue');
};
} else {
async = function(callback, binding) {
setTimeout(function() {
callback.call(binding);
}, 1);
};
}
__exports__.async = async;
});
define(
["exports"],
function(__exports__) {
"use strict";
var Event = function(type, options) {
this.type = type;
for (var option in options) {
if (!options.hasOwnProperty(option)) { continue; }
this[option] = options[option];
}
};
var indexOf = function(callbacks, callback) {
for (var i=0, l=callbacks.length; i<l; i++) {
if (callbacks[i][0] === callback) { return i; }
}
return -1;
};
var callbacksFor = function(object) {
var callbacks = object._promiseCallbacks;
if (!callbacks) {
callbacks = object._promiseCallbacks = {};
}
return callbacks;
};
var EventTarget = {
mixin: function(object) {
object.on = this.on;
object.off = this.off;
object.trigger = this.trigger;
return object;
},
on: function(eventNames, callback, binding) {
var allCallbacks = callbacksFor(this), callbacks, eventName;
eventNames = eventNames.split(/\s+/);
binding = binding || this;
while (eventName = eventNames.shift()) {
callbacks = allCallbacks[eventName];
if (!callbacks) {
callbacks = allCallbacks[eventName] = [];
}
if (indexOf(callbacks, callback) === -1) {
callbacks.push([callback, binding]);
}
}
},
off: function(eventNames, callback) {
var allCallbacks = callbacksFor(this), callbacks, eventName, index;
eventNames = eventNames.split(/\s+/);
while (eventName = eventNames.shift()) {
if (!callback) {
allCallbacks[eventName] = [];
continue;
}
callbacks = allCallbacks[eventName];
index = indexOf(callbacks, callback);
if (index !== -1) { callbacks.splice(index, 1); }
}
},
trigger: function(eventName, options) {
var allCallbacks = callbacksFor(this),
callbacks, callbackTuple, callback, binding, event;
if (callbacks = allCallbacks[eventName]) {
// Don't cache the callbacks.length since it may grow
for (var i=0; i<callbacks.length; i++) {
callbackTuple = callbacks[i];
callback = callbackTuple[0];
binding = callbackTuple[1];
if (typeof options !== 'object') {
options = { detail: options };
}
event = new Event(eventName, options);
callback.call(binding, event);
}
}
}
};
__exports__.EventTarget = EventTarget;
});
define(
["exports"],
function(__exports__) {
["rsvp/async", "rsvp/events", "exports"],
function(__dependency1__, __dependency2__, __exports__) {
"use strict";
var config = {};
var browserGlobal = (typeof window !== 'undefined') ? window : {};
var MutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
var RSVP;
if (typeof process !== 'undefined' &&
{}.toString.call(process) === '[object process]') {
config.async = function(callback, binding) {
process.nextTick(function() {
callback.call(binding);
});
};
} else if (MutationObserver) {
var queue = [];
var observer = new MutationObserver(function() {
var toProcess = queue.slice();
queue = [];
toProcess.forEach(function(tuple) {
var callback = tuple[0], binding = tuple[1];
callback.call(binding);
});
});
var element = document.createElement('div');
observer.observe(element, { attributes: true });
// Chrome Memory Leak: https://bugs.webkit.org/show_bug.cgi?id=93661
window.addEventListener('unload', function(){
observer.disconnect();
observer = null;
});
config.async = function(callback, binding) {
queue.push([callback, binding]);
element.setAttribute('drainQueue', 'drainQueue');
};
} else {
config.async = function(callback, binding) {
setTimeout(function() {
callback.call(binding);
}, 1);
};
}
var Event = function(type, options) {
this.type = type;
for (var option in options) {
if (!options.hasOwnProperty(option)) { continue; }
this[option] = options[option];
}
};
var indexOf = function(callbacks, callback) {
for (var i=0, l=callbacks.length; i<l; i++) {
if (callbacks[i][0] === callback) { return i; }
}
return -1;
};
var callbacksFor = function(object) {
var callbacks = object._promiseCallbacks;
if (!callbacks) {
callbacks = object._promiseCallbacks = {};
}
return callbacks;
};
var EventTarget = {
mixin: function(object) {
object.on = this.on;
object.off = this.off;
object.trigger = this.trigger;
return object;
},
on: function(eventNames, callback, binding) {
var allCallbacks = callbacksFor(this), callbacks, eventName;
eventNames = eventNames.split(/\s+/);
binding = binding || this;
while (eventName = eventNames.shift()) {
callbacks = allCallbacks[eventName];
if (!callbacks) {
callbacks = allCallbacks[eventName] = [];
}
if (indexOf(callbacks, callback) === -1) {
callbacks.push([callback, binding]);
}
}
},
off: function(eventNames, callback) {
var allCallbacks = callbacksFor(this), callbacks, eventName, index;
eventNames = eventNames.split(/\s+/);
var async = __dependency1__.async;
var EventTarget = __dependency2__.EventTarget;
while (eventName = eventNames.shift()) {
if (!callback) {
allCallbacks[eventName] = [];
continue;
}
callbacks = allCallbacks[eventName];
index = indexOf(callbacks, callback);
if (index !== -1) { callbacks.splice(index, 1); }
}
},
trigger: function(eventName, options) {
var allCallbacks = callbacksFor(this),
callbacks, callbackTuple, callback, binding, event;
if (callbacks = allCallbacks[eventName]) {
// Don't cache the callbacks.length since it may grow
for (var i=0; i<callbacks.length; i++) {
callbackTuple = callbacks[i];
callback = callbackTuple[0];
binding = callbackTuple[1];
if (typeof options !== 'object') {
options = { detail: options };
}
event = new Event(eventName, options);
callback.call(binding, event);
}
}
}
};
var config = {};
config.async = async;
var noop = function() {};
......@@ -212,15 +76,15 @@ define(
then: function(done, fail) {
var thenPromise = new Promise();
if (this.isResolved) {
if (this.isFulfilled) {
config.async(function() {
invokeCallback('resolve', thenPromise, done, { detail: this.resolvedValue });
invokeCallback('resolve', thenPromise, done, { detail: this.fulfillmentValue });
}, this);
}
if (this.isRejected) {
config.async(function() {
invokeCallback('reject', thenPromise, fail, { detail: this.rejectedValue });
invokeCallback('reject', thenPromise, fail, { detail: this.rejectedReason });
}, this);
}
......@@ -239,8 +103,8 @@ define(
function resolve(promise, value) {
config.async(function() {
promise.trigger('promise:resolved', { detail: value });
promise.isResolved = true;
promise.resolvedValue = value;
promise.isFulfilled = true;
promise.fulfillmentValue = value;
});
}
......@@ -248,7 +112,7 @@ define(
config.async(function() {
promise.trigger('promise:failed', { detail: value });
promise.isRejected = true;
promise.rejectedValue = value;
promise.rejectedReason = value;
});
}
......@@ -291,8 +155,6 @@ define(
}
__exports__.Promise = Promise;
__exports__.Event = Event;
__exports__.EventTarget = EventTarget;
__exports__.all = all;
__exports__.configure = configure;
});
This diff is collapsed.
(function(e){"use strict";function v(e,n){t.async(function(){e.trigger("promise:resolved",{detail:n}),e.isResolved=!0,e.resolvedValue=n})}function m(e,n){t.async(function(){e.trigger("promise:failed",{detail:n}),e.isRejected=!0,e.rejectedValue=n})}function g(e){var t,n=[],r=new p,i=e.length;i===0&&v(r,[]);var s=function(e){return function(t){o(e,t)}},o=function(e,t){n[e]=t,--i===0&&v(r,n)},u=function(e){m(r,e)};for(t=0;t<i;t++)e[t].then(s(t),u);return r}function y(e,n){t[e]=n}var t={},n=typeof window!="undefined"?window:{},r=n.MutationObserver||n.WebKitMutationObserver,i;if(typeof process!="undefined"&&{}.toString.call(process)==="[object process]")t.async=function(e,t){process.nextTick(function(){e.call(t)})};else if(r){var s=[],o=new r(function(){var e=s.slice();s=[],e.forEach(function(e){var t=e[0],n=e[1];t.call(n)})}),u=document.createElement("div");o.observe(u,{attributes:!0}),window.addEventListener("unload",function(){o.disconnect(),o=null}),t.async=function(e,t){s.push([e,t]),u.setAttribute("drainQueue","drainQueue")}}else t.async=function(e,t){setTimeout(function(){e.call(t)},1)};var a=function(e,t){this.type=e;for(var n in t){if(!t.hasOwnProperty(n))continue;this[n]=t[n]}},f=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n][0]===t)return n;return-1},l=function(e){var t=e._promiseCallbacks;return t||(t=e._promiseCallbacks={}),t},c={mixin:function(e){return e.on=this.on,e.off=this.off,e.trigger=this.trigger,e},on:function(e,t,n){var r=l(this),i,s;e=e.split(/\s+/),n=n||this;while(s=e.shift())i=r[s],i||(i=r[s]=[]),f(i,t)===-1&&i.push([t,n])},off:function(e,t){var n=l(this),r,i,s;e=e.split(/\s+/);while(i=e.shift()){if(!t){n[i]=[];continue}r=n[i],s=f(r,t),s!==-1&&r.splice(s,1)}},trigger:function(e,t){var n=l(this),r,i,s,o,u;if(r=n[e])for(var f=0;f<r.length;f++)i=r[f],s=i[0],o=i[1],typeof t!="object"&&(t={detail:t}),u=new a(e,t),s.call(o,u)}},h=function(){},p=function(e){var t=this,n=function(e){v(t,e),n=h,r=h},r=function(e){m(t,e),n=h,r=h};this.on("promise:resolved",function(e){this.trigger("success",{detail:e.detail})},this),this.on("promise:failed",function(e){this.trigger("error",{detail:e.detail})},this),e&&e(n,r)},d=function(e,t,n,r){var i=typeof n=="function",s,o,u,a;if(i)try{s=n(r.detail),u=!0}catch(f){a=!0,o=f}else s=r.detail,u=!0;s&&typeof s.then=="function"?s.then(function(e){v(t,e)},function(e){m(t,e)}):i&&u?v(t,s):a?m(t,o):e==="resolve"?v(t,s):e==="reject"&&m(t,s)};p.prototype={then:function(e,n){var r=new p;return this.isResolved&&t.async(function(){d("resolve",r,e,{detail:this.resolvedValue})},this),this.isRejected&&t.async(function(){d("reject",r,n,{detail:this.rejectedValue})},this),this.on("promise:resolved",function(t){d("resolve",r,e,t)}),this.on("promise:failed",function(e){d("reject",r,n,e)}),r}},c.mixin(p.prototype),e.Promise=p,e.Event=a,e.EventTarget=c,e.all=g,e.configure=y})(window.RSVP={});
(function(){var a,b;(function(){var c={},d={};a=function(a,b,d){c[a]={deps:b,callback:d}},b=function(a){if(d[a])return d[a];d[a]={};var e=c[a],f=e.deps,g=e.callback,h=[],i;for(var j=0,k=f.length;j<k;j++)f[j]==="exports"?h.push(i={}):h.push(b(f[j]));var l=g.apply(this,h);return d[a]=i||l}})(),a("rsvp/async",["exports"],function(a){"use strict";var b=typeof window!="undefined"?window:{},c=b.MutationObserver||b.WebKitMutationObserver,d;if(typeof process!="undefined"&&{}.toString.call(process)==="[object process]")d=function(a,b){process.nextTick(function(){a.call(b)})};else if(c){var e=[],f=new c(function(){var a=e.slice();e=[],a.forEach(function(a){var b=a[0],c=a[1];b.call(c)})}),g=document.createElement("div");f.observe(g,{attributes:!0}),window.addEventListener("unload",function(){f.disconnect(),f=null}),d=function(a,b){e.push([a,b]),g.setAttribute("drainQueue","drainQueue")}}else d=function(a,b){setTimeout(function(){a.call(b)},1)};a.async=d}),a("rsvp/events",["exports"],function(a){"use strict";var b=function(a,b){this.type=a;for(var c in b){if(!b.hasOwnProperty(c))continue;this[c]=b[c]}},c=function(a,b){for(var c=0,d=a.length;c<d;c++)if(a[c][0]===b)return c;return-1},d=function(a){var b=a._promiseCallbacks;b||(b=a._promiseCallbacks={});return b},e={mixin:function(a){a.on=this.on,a.off=this.off,a.trigger=this.trigger;return a},on:function(a,b,e){var f=d(this),g,h;a=a.split(/\s+/),e=e||this;while(h=a.shift())g=f[h],g||(g=f[h]=[]),c(g,b)===-1&&g.push([b,e])},off:function(a,b){var e=d(this),f,g,h;a=a.split(/\s+/);while(g=a.shift()){if(!b){e[g]=[];continue}f=e[g],h=c(f,b),h!==-1&&f.splice(h,1)}},trigger:function(a,c){var e=d(this),f,g,h,i,j;if(f=e[a])for(var k=0;k<f.length;k++)g=f[k],h=g[0],i=g[1],typeof c!="object"&&(c={detail:c}),j=new b(a,c),h.call(i,j)}};a.EventTarget=e}),a("rsvp",["rsvp/async","rsvp/events","exports"],function(a,b,c){function m(a,b){f[a]=b}function l(a){var b,c=[],d=new h,e=a.length;e===0&&j(d,[]);var f=function(a){return function(b){g(a,b)}},g=function(a,b){c[a]=b,--e===0&&j(d,c)},i=function(a){k(d,a)};for(b=0;b<e;b++)a[b].then(f(b),i);return d}function k(a,b){f.async(function(){a.trigger("promise:failed",{detail:b}),a.isRejected=!0,a.rejectedReason=b})}function j(a,b){f.async(function(){a.trigger("promise:resolved",{detail:b}),a.isFulfilled=!0,a.fulfillmentValue=b})}"use strict";var d=a.async,e=b.EventTarget,f={};f.async=d;var g=function(){},h=function(a){var b=this,c=function(a){j(b,a),c=g,d=g},d=function(a){k(b,a),c=g,d=g};this.on("promise:resolved",function(a){this.trigger("success",{detail:a.detail})},this),this.on("promise:failed",function(a){this.trigger("error",{detail:a.detail})},this),a&&a(c,d)},i=function(a,b,c,d){var e=typeof c=="function",f,g,h,i;if(e)try{f=c(d.detail),h=!0}catch(l){i=!0,g=l}else f=d.detail,h=!0;f&&typeof f.then=="function"?f.then(function(a){j(b,a)},function(a){k(b,a)}):e&&h?j(b,f):i?k(b,g):a==="resolve"?j(b,f):a==="reject"&&k(b,f)};h.prototype={then:function(a,b){var c=new h;this.isFulfilled&&f.async(function(){i("resolve",c,a,{detail:this.fulfillmentValue})},this),this.isRejected&&f.async(function(){i("reject",c,b,{detail:this.rejectedReason})},this),this.on("promise:resolved",function(b){i("resolve",c,a,b)}),this.on("promise:failed",function(a){i("reject",c,b,a)});return c}},e.mixin(h.prototype),c.Promise=h,c.all=l,c.configure=m}),window.RSVP=b("rsvp")})()
var browserGlobal = (typeof window !== 'undefined') ? window : {};
var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
var config;
var async;
if (typeof process !== 'undefined' &&
{}.toString.call(process) === '[object process]') {
config.async = function(callback, binding) {
async = function(callback, binding) {
process.nextTick(function() {
callback.call(binding);
});
......@@ -32,20 +32,16 @@ if (typeof process !== 'undefined' &&
observer = null;
});
config.async = function(callback, binding) {
async = function(callback, binding) {
queue.push([callback, binding]);
element.setAttribute('drainQueue', 'drainQueue');
};
} else {
config.async = function(callback, binding) {
async = function(callback, binding) {
setTimeout(function() {
callback.call(binding);
}, 1);
};
}
function configure(name, value) {
config[name] = value;
}
export { configure, async };
export { async };
......@@ -150,4 +150,4 @@ function configure(name, value) {
config[name] = value;
}
export { Promise, Event, EventTarget, all, configure };
export { Promise, all, configure };
"use strict";
var config = {};
var browserGlobal = (typeof window !== 'undefined') ? window : {};
var MutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
var RSVP;
if (typeof process !== 'undefined' &&
{}.toString.call(process) === '[object process]') {
config.async = function(callback, binding) {
process.nextTick(function() {
callback.call(binding);
});
};
} else if (MutationObserver) {
var queue = [];
var observer = new MutationObserver(function() {
var toProcess = queue.slice();
queue = [];
toProcess.forEach(function(tuple) {
var callback = tuple[0], binding = tuple[1];
callback.call(binding);
});
});
var element = document.createElement('div');
observer.observe(element, { attributes: true });
// Chrome Memory Leak: https://bugs.webkit.org/show_bug.cgi?id=93661
window.addEventListener('unload', function(){
observer.disconnect();
observer = null;
});
config.async = function(callback, binding) {
queue.push([callback, binding]);
element.setAttribute('drainQueue', 'drainQueue');
};
} else {
config.async = function(callback, binding) {
setTimeout(function() {
callback.call(binding);
}, 1);
};
}
var Event = function(type, options) {
this.type = type;
for (var option in options) {
if (!options.hasOwnProperty(option)) { continue; }
this[option] = options[option];
}
};
var indexOf = function(callbacks, callback) {
for (var i=0, l=callbacks.length; i<l; i++) {
if (callbacks[i][0] === callback) { return i; }
}
return -1;
};
var callbacksFor = function(object) {
var callbacks = object._promiseCallbacks;
if (!callbacks) {
callbacks = object._promiseCallbacks = {};
}
return callbacks;
};
var EventTarget = {
mixin: function(object) {
object.on = this.on;
object.off = this.off;
object.trigger = this.trigger;
return object;
},
on: function(eventNames, callback, binding) {
var allCallbacks = callbacksFor(this), callbacks, eventName;
eventNames = eventNames.split(/\s+/);
binding = binding || this;
while (eventName = eventNames.shift()) {
callbacks = allCallbacks[eventName];
if (!callbacks) {
callbacks = allCallbacks[eventName] = [];
}
if (indexOf(callbacks, callback) === -1) {
callbacks.push([callback, binding]);
}
}
},
off: function(eventNames, callback) {
var allCallbacks = callbacksFor(this), callbacks, eventName, index;
eventNames = eventNames.split(/\s+/);
var async = require("rsvp/async").async;
var EventTarget = require("rsvp/events").EventTarget;
while (eventName = eventNames.shift()) {
if (!callback) {
allCallbacks[eventName] = [];
continue;
}
callbacks = allCallbacks[eventName];
index = indexOf(callbacks, callback);
if (index !== -1) { callbacks.splice(index, 1); }
}
},
trigger: function(eventName, options) {
var allCallbacks = callbacksFor(this),
callbacks, callbackTuple, callback, binding, event;
if (callbacks = allCallbacks[eventName]) {
// Don't cache the callbacks.length since it may grow
for (var i=0; i<callbacks.length; i++) {
callbackTuple = callbacks[i];
callback = callbackTuple[0];
binding = callbackTuple[1];
if (typeof options !== 'object') {
options = { detail: options };
}
event = new Event(eventName, options);
callback.call(binding, event);
}
}
}
};
var config = {};
config.async = async;
var noop = function() {};
......@@ -209,15 +73,15 @@ Promise.prototype = {
then: function(done, fail) {
var thenPromise = new Promise();
if (this.isResolved) {
if (this.isFulfilled) {
config.async(function() {
invokeCallback('resolve', thenPromise, done, { detail: this.resolvedValue });
invokeCallback('resolve', thenPromise, done, { detail: this.fulfillmentValue });
}, this);
}
if (this.isRejected) {
config.async(function() {
invokeCallback('reject', thenPromise, fail, { detail: this.rejectedValue });
invokeCallback('reject', thenPromise, fail, { detail: this.rejectedReason });
}, this);
}
......@@ -236,8 +100,8 @@ Promise.prototype = {
function resolve(promise, value) {
config.async(function() {
promise.trigger('promise:resolved', { detail: value });
promise.isResolved = true;
promise.resolvedValue = value;
promise.isFulfilled = true;
promise.fulfillmentValue = value;
});
}
......@@ -245,7 +109,7 @@ function reject(promise, value) {
config.async(function() {
promise.trigger('promise:failed', { detail: value });
promise.isRejected = true;
promise.rejectedValue = value;
promise.rejectedReason = value;
});
}
......@@ -288,7 +152,5 @@ function configure(name, value) {
}
exports.Promise = Promise;
exports.Event = Event;
exports.EventTarget = EventTarget;
exports.all = all;
exports.configure = configure;
"use strict";
var config = {};
var browserGlobal = (typeof window !== 'undefined') ? window : {};
var MutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
var RSVP;
if (typeof process !== 'undefined' &&
{}.toString.call(process) === '[object process]') {
config.async = function(callback, binding) {
process.nextTick(function() {
callback.call(binding);
});
};
} else if (MutationObserver) {
var queue = [];
var observer = new MutationObserver(function() {
var toProcess = queue.slice();
queue = [];
toProcess.forEach(function(tuple) {
var callback = tuple[0], binding = tuple[1];
callback.call(binding);
});
});
var element = document.createElement('div');
observer.observe(element, { attributes: true });
// Chrome Memory Leak: https://bugs.webkit.org/show_bug.cgi?id=93661
window.addEventListener('unload', function(){
observer.disconnect();
observer = null;
});
config.async = function(callback, binding) {
queue.push([callback, binding]);
element.setAttribute('drainQueue', 'drainQueue');
};
} else {
config.async = function(callback, binding) {
setTimeout(function() {
callback.call(binding);
}, 1);
};
}
var Event = function(type, options) {
this.type = type;
for (var option in options) {
if (!options.hasOwnProperty(option)) { continue; }
this[option] = options[option];
}
};
var indexOf = function(callbacks, callback) {
for (var i=0, l=callbacks.length; i<l; i++) {
if (callbacks[i][0] === callback) { return i; }
}
return -1;
};
var callbacksFor = function(object) {
var callbacks = object._promiseCallbacks;
if (!callbacks) {
callbacks = object._promiseCallbacks = {};
}
return callbacks;
};
var EventTarget = {
mixin: function(object) {
object.on = this.on;
object.off = this.off;
object.trigger = this.trigger;
return object;
},
on: function(eventNames, callback, binding) {
var allCallbacks = callbacksFor(this), callbacks, eventName;
eventNames = eventNames.split(/\s+/);
binding = binding || this;
while (eventName = eventNames.shift()) {
callbacks = allCallbacks[eventName];
if (!callbacks) {
callbacks = allCallbacks[eventName] = [];
}
if (indexOf(callbacks, callback) === -1) {
callbacks.push([callback, binding]);
}
}
},
off: function(eventNames, callback) {
var allCallbacks = callbacksFor(this), callbacks, eventName, index;
eventNames = eventNames.split(/\s+/);
while (eventName = eventNames.shift()) {
if (!callback) {
allCallbacks[eventName] = [];
continue;
}
callbacks = allCallbacks[eventName];
index = indexOf(callbacks, callback);
if (index !== -1) { callbacks.splice(index, 1); }
}
},
trigger: function(eventName, options) {
var allCallbacks = callbacksFor(this),
callbacks, callbackTuple, callback, binding, event;
if (callbacks = allCallbacks[eventName]) {
// Don't cache the callbacks.length since it may grow
for (var i=0; i<callbacks.length; i++) {
callbackTuple = callbacks[i];
callback = callbackTuple[0];
binding = callbackTuple[1];
if (typeof options !== 'object') {
options = { detail: options };
}
event = new Event(eventName, options);
callback.call(binding, event);
}
}
}
};
var Promise = function(resolver) {
var promise = this;
function resolvePromise(value) {
resolve(promise, value);
}
function rejectPromise(value) {
reject(promise, value);
}
this.on('promise:resolved', function(event) {
this.trigger('success', { detail: event.detail });
}, this);
this.on('promise:failed', function(event) {
this.trigger('error', { detail: event.detail });
}, this);
if (resolver) {
resolver(resolvePromise, rejectPromise);
}
};
var noop = function() {};
var invokeCallback = function(type, promise, callback, event) {
var hasCallback = typeof callback === 'function',
value, error, succeeded, failed;
if (hasCallback) {
try {
value = callback(event.detail);
succeeded = true;
} catch(e) {
failed = true;
error = e;
}
} else {
value = event.detail;
succeeded = true;
}
if (value && typeof value.then === 'function') {
value.then(function(value) {
promise.resolve(value);
}, function(error) {
promise.reject(error);
});
} else if (hasCallback && succeeded) {
promise.resolve(value);
} else if (failed) {
promise.reject(error);
} else {
promise[type](value);
}
};
Promise.prototype = {
then: function(done, fail) {
var thenPromise = new Promise();
if (this.isResolved) {
config.async(function() {
invokeCallback('resolve', thenPromise, done, { detail: this.resolvedValue });
}, this);
}
if (this.isRejected) {
config.async(function() {
invokeCallback('reject', thenPromise, fail, { detail: this.rejectedValue });
}, this);
}
this.on('promise:resolved', function(event) {
invokeCallback('resolve', thenPromise, done, event);
});
this.on('promise:failed', function(event) {
invokeCallback('reject', thenPromise, fail, event);
});
return thenPromise;
},
resolve: function(value) {
resolve(this, value);
this.resolve = noop;
this.reject = noop;
},
reject: function(value) {
reject(this, value);
this.resolve = noop;
this.reject = noop;
}
};
function resolve(promise, value) {
config.async(function() {
promise.trigger('promise:resolved', { detail: value });
promise.isResolved = true;
promise.resolvedValue = value;
});
}
function reject(promise, value) {
config.async(function() {
promise.trigger('promise:failed', { detail: value });
promise.isRejected = true;
promise.rejectedValue = value;
});
}
function all(promises) {
var i, results = [];
var allPromise = new Promise();
var remaining = promises.length;
if (remaining === 0) {
allPromise.resolve([]);
}
var resolver = function(index) {
return function(value) {
resolve(index, value);
};
};
var resolve = function(index, value) {
results[index] = value;
if (--remaining === 0) {
allPromise.resolve(results);
}
};
var reject = function(error) {
allPromise.reject(error);
};
for (i = 0; i < remaining; i++) {
promises[i].then(resolver(i), reject);
}
return allPromise;
}
EventTarget.mixin(Promise.prototype);
function configure(name, value) {
config[name] = value;
}
exports.Promise = Promise;
exports.Event = Event;
exports.EventTarget = EventTarget;
exports.all = all;
exports.configure = configure;
......@@ -9,7 +9,7 @@ if (typeof RSVP !== 'undefined') {
Promise = RSVP.Promise;
} else {
// Test the Node build
var Promise = require('../node/rsvp').Promise;
var Promise = require('../main').Promise;
}
var adapter = {};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment