diff options
Diffstat (limited to 'node_modules/montage/core/promise.js')
-rwxr-xr-x | node_modules/montage/core/promise.js | 694 |
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 | |||
33 | try { | ||
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 | ||
43 | function 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 | |||
63 | var 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 | ||
73 | var 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. | ||
104 | var 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 | } | ||
230 | }, | ||
231 | |||
232 | valueOf: { | ||
233 | value: function () { | ||
234 | return this._value; | ||
23 |