aboutsummaryrefslogtreecommitdiff
path: root/node_modules/montage/core/promise.js
diff options
context:
space:
mode:
authorPierre Frisch2011-12-22 07:25:50 -0800
committerValerio Virgillito2012-01-27 11:18:17 -0800
commitb89a7ee8b956c96a1dcee995ea840feddc5d4b27 (patch)
tree0f3136ab0ecdbbbed6a83576581af0a53124d6f1 /node_modules/montage/core/promise.js
parent2401f05d1f4b94d45e4568b81fc73e67b969d980 (diff)
downloadninja-b89a7ee8b956c96a1dcee995ea840feddc5d4b27.tar.gz
First commit of Ninja to ninja-internal
Signed-off-by: Valerio Virgillito <rmwh84@motorola.com>
Diffstat (limited to 'node_modules/montage/core/promise.js')
-rwxr-xr-xnode_modules/montage/core/promise.js694
1 files changed, 694 insertions, 0 deletions
diff --git a/node_modules/montage/core/promise.js b/node_modules/montage/core/promise.js
new file mode 100755
index 00000000..80c63943
--- /dev/null
+++ b/node_modules/montage/core/promise.js
@@ -0,0 +1,694 @@
1/* <copyright>
2 This file contains proprietary software owned by Motorola Mobility, Inc.<br/>
3 No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/>
4 (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved.
5 </copyright> */
6
7// Scope:
8// * ES5, W3C setImmediate (shimmed if necessary)
9// * speed and economy of memory before safety and securability
10// * run-time compatibility via thenability
11
12// TODO note the comps/promiseSend/sendPromise and argument order
13// changes from Q
14
15// This module is used during the boot-strapping, so it can be required as
16// a normal CommonJS module, but alternately bootstraps Montage if there
17// is a bootstrap global variable.
18(function (definition) {
19 if (typeof bootstrap !== "undefined") {
20 bootstrap("core/promise", definition);
21 } else if (typeof require !== "undefined") {
22 // module
23 definition(require, exports, module);
24 } else {
25 // global script
26 Q = {};
27 definition(function () {}, Q);
28 }
29})(function (require, exports, module) {
30
31"use strict";
32
33try {
34 // bootstrapping can't handle relative identifiers
35 require("core/shim/timers"); // setImmediate
36} catch (exception) {
37 // in this case, node can't handle absolute identifiers
38 require("./shim/timers"); // setImmediate
39}
40
41// merely ensures that the returned value can respond to
42// messages; does not guarantee a full promise API
43function toPromise(value) {
44 if (value && typeof value.sendPromise !== "undefined") {
45 return value;
46 } else if (value && typeof value.then !== "undefined") {
47 var deferred = Promise.defer();
48 value.then(function (value) {
49 deferred.resolve(value);
50 }, function (reason, error, rejection) {
51 if (rejection) {
52 deferred.resolve(rejection);
53 } else {
54 deferred.reject(reason, error);
55 }
56 });
57 return deferred.promise;
58 } else {
59 return Promise.fulfill(value);
60 }
61}
62
63var Creatable = Object.create(Object.prototype, {
64 create: {
65 value: function (descriptor) {
66 return Object.create(this, descriptor);
67 }
68 },
69});
70
71// Common implementation details of FulfilledPromise, RejectedPromise, and
72// DeferredPromise
73var AbstractPromise = Creatable.create({
74
75 // Common implementation of sendPromise for FulfiledPromise and
76 // RejectedPromise, but overridden by DeferredPromise to buffer
77 // messages instead of handling them.
78 sendPromise: {
79 value: function (resolve, op /*, ...args*/) {
80 var result;
81 try {
82 result = (this._handlers[op] || this._fallback)
83 .apply(this, arguments);
84 } catch (error) {
85 result = this.Promise.reject(error && error.message, error);
86 }
87 resolve(result);
88 }
89 },
90
91 // Defers polymorphically to toString
92 toSource: {
93 value: function () {
94 return this.toString();
95 }
96 }
97
98});
99
100// Basic implementation of the Promise object and prototypes for its
101// Fulfilled, Rejected, and Deferred subtypes. The mixin descriptors that
102// give the promise types useful methods like "then" are not applied until
103// .create() is used the first time to make the actual Promise export.
104var PrimordialPromise = Creatable.create({
105
106 create: {
107 value: function (descriptor, promiseDescriptor) {
108
109 // automatically subcreate each of the contained promise types
110 var creation = Object.create(this, {
111 DeferredPromise: {
112 value: this.DeferredPromise.create(promiseDescriptor)
113 },
114 FulfilledPromise: {
115 value: this.FulfilledPromise.create(promiseDescriptor)
116 },
117 RejectedPromise: {
118 value: this.RejectedPromise.create(promiseDescriptor)
119 }
120 });
121
122 if (descriptor) {
123 Object.defineProperties(creation, descriptor);
124 }
125
126 // create static reflections of all new promise methods
127 if (promiseDescriptor) {
128 var statics = {};
129 Object.keys(promiseDescriptor).forEach(function (name) {
130 statics[name] = {
131 value: function (value) {
132 var args = Array.prototype.slice.call(arguments, 1);
133 var promise = this.ref(value);
134 return promise[name].apply(promise, args);
135 }
136 };
137 });
138 Object.defineProperties(creation, statics);
139 }
140
141 return creation;
142 }
143 },
144
145 isPromise: {
146 value: function (value) {
147 return value && typeof value.sendPromise !== "undefined";
148 }
149 },
150
151 ref: {
152 value: function (object) {
153 // if it is already a promise, wrap it to guarantee
154 // the full public API of this promise variety.
155 if (object && typeof object.sendPromise === "function") {
156 var deferred = this.defer();
157 deferred.resolve(object);
158 return deferred.promise;
159 // if it is at least a thenable duck-type, wrap it
160 } else if (object && typeof object.then === "function") {
161 var deferred = this.defer();
162 object.then(function (value) {
163 deferred.resolve(value);
164 }, function (reason, error, rejection) {
165 // if the thenable recognizes rejection
166 // forwarding, accept the given rejection
167 if (rejection) {
168 deferred.resolve(rejection);
169 // otherwise, handle reason and optional error forwarding
170 } else {
171 deferred.reject(reason, error);
172 }
173 })
174 return deferred.promise;
175 // if it is a fulfillment value, wrap it with a fulfillment
176 // promise
177 } else {
178 return this.fulfill(object);
179 }
180 }
181 },
182
183 fulfill: {
184 value: function (value) {
185 return this.FulfilledPromise.create({
186 _value: {
187 value: value,
188 writable: true
189 },
190 Promise: {
191 value: this
192 }
193 });
194 }
195 },
196
197 FulfilledPromise: {
198 value: AbstractPromise.create({
199
200 _handlers: {
201 value: {
202 then: function (r, o) {
203 return this._value;
204 },
205 get: function (r, o, key) {
206 return this._value[key];
207 },
208 put: function (r, o, key, value) {
209 return this._value[key] = value;
210 },
211 "delete": function (r, o, key) {
212 return delete this._value[key];
213 },
214 post: function (r, o, key, value) {
215 return this._value[key].apply(this._value, value);
216 },
217 apply: function (r, o, self, args) {
218 return this._value.apply(self, args);
219 },
220 keys: function (r, o) {
221 return Object.keys(this._value);
222 }
223 }
224 },
225
226 _fallback: {
227 value: function (callback, operator) {
228 return this.Promise.reject("Promise does not support operation: " + operator);
229 }