sproutcore 1.10.0.rc.3 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (161) hide show
  1. checksums.yaml +8 -8
  2. data/VERSION.yml +1 -1
  3. data/lib/buildtasks/manifest.rake +3 -2
  4. data/lib/frameworks/sproutcore/Buildfile +3 -1
  5. data/lib/frameworks/sproutcore/CHANGELOG.md +26 -2
  6. data/lib/frameworks/sproutcore/apps/showcase/resources/main_page.js +3 -0
  7. data/lib/frameworks/sproutcore/apps/showcase/views/views_item_view.js +1 -1
  8. data/lib/frameworks/sproutcore/apps/welcome/english.lproj/main_page.js +3 -0
  9. data/lib/frameworks/sproutcore/frameworks/bootstrap/system/browser.js +5 -5
  10. data/lib/frameworks/sproutcore/frameworks/bootstrap/tests/system/browser.js +9 -0
  11. data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane_statechart.js +2 -2
  12. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/browser.js +6 -0
  13. data/lib/frameworks/sproutcore/frameworks/core_foundation/system/root_responder.js +17 -55
  14. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/animation.js +57 -0
  15. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/isVisible.js +24 -0
  16. data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/view_states_test.js +31 -13
  17. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view.js +8 -5
  18. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/animation.js +24 -20
  19. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout.js +39 -29
  20. data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/statechart.js +400 -242
  21. data/lib/frameworks/sproutcore/frameworks/datastore/models/record.js +37 -32
  22. data/lib/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +1 -8
  23. data/lib/frameworks/sproutcore/frameworks/desktop/panes/modal.js +3 -2
  24. data/lib/frameworks/sproutcore/frameworks/desktop/panes/panel.js +4 -5
  25. data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/panel/ui.js +53 -6
  26. data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +9 -3
  27. data/lib/frameworks/sproutcore/frameworks/desktop/views/grid.js +1 -1
  28. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll.js +16 -12
  29. data/lib/frameworks/sproutcore/frameworks/desktop/views/scroller.js +16 -2
  30. data/lib/frameworks/sproutcore/frameworks/foundation/mixins/auto_resize.js +10 -8
  31. data/lib/frameworks/sproutcore/frameworks/foundation/tests/mixins/auto_resize_test.js +102 -0
  32. data/lib/frameworks/sproutcore/frameworks/foundation/tests/validators/password.js +15 -7
  33. data/lib/frameworks/sproutcore/frameworks/runtime/system/run_loop.js +2 -2
  34. data/lib/frameworks/sproutcore/frameworks/testing/system/runner.js +4 -0
  35. data/lib/frameworks/sproutcore/phantomjs/minimist.js +181 -0
  36. data/lib/frameworks/sproutcore/phantomjs/q.js +1937 -0
  37. data/lib/frameworks/sproutcore/phantomjs/test_runner.js +733 -0
  38. data/lib/frameworks/sproutcore/themes/ace/resources/button/ace/44px/button.css +2 -2
  39. data/lib/frameworks/sproutcore/themes/ace/resources/button/ace/button.css +11 -11
  40. data/lib/frameworks/sproutcore/themes/ace/resources/button/dark/button.css +5 -5
  41. data/lib/frameworks/sproutcore/themes/ace/resources/button/dark/jumbo/button.css +3 -3
  42. data/lib/frameworks/sproutcore/themes/ace/resources/button/dark/small/button.css +3 -3
  43. data/lib/frameworks/sproutcore/themes/ace/resources/button/popup/select.css +1 -1
  44. data/lib/frameworks/sproutcore/themes/ace/resources/checkbox/ace/checkbox.css +3 -3
  45. data/lib/frameworks/sproutcore/themes/ace/resources/collection/source-list/source_list_view.css +4 -4
  46. data/lib/frameworks/sproutcore/themes/ace/resources/disclosure/ace/disclosure.css +6 -6
  47. data/lib/frameworks/sproutcore/themes/ace/resources/imagebutton/ace/imagebutton.css +5 -5
  48. data/lib/frameworks/sproutcore/themes/ace/resources/menu/menu.css +16 -16
  49. data/lib/frameworks/sproutcore/themes/ace/resources/picker/popover/popover.css +42 -42
  50. data/lib/frameworks/sproutcore/themes/ace/resources/progress/ace/progress.css +19 -19
  51. data/lib/frameworks/sproutcore/themes/ace/resources/radio/radio.css +12 -12
  52. data/lib/frameworks/sproutcore/themes/ace/resources/scroller/horizontal/horizontal.css +7 -7
  53. data/lib/frameworks/sproutcore/themes/ace/resources/scroller/horizontal/horizontal_touch.css +18 -18
  54. data/lib/frameworks/sproutcore/themes/ace/resources/scroller/vertical/vertical.css +8 -8
  55. data/lib/frameworks/sproutcore/themes/ace/resources/scroller/vertical/vertical_touch.css +16 -16
  56. data/lib/frameworks/sproutcore/themes/ace/resources/segmented/44px/segmented.css +2 -2
  57. data/lib/frameworks/sproutcore/themes/ace/resources/segmented/segmented.css +13 -13
  58. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/14px/slider.css +11 -11
  59. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/16px/slider.css +11 -11
  60. data/lib/frameworks/sproutcore/themes/ace/resources/slider/ace/22px/slider.css +11 -11
  61. data/lib/frameworks/sproutcore/themes/ace/resources/split/split.css +6 -6
  62. data/lib/frameworks/sproutcore/themes/ace/resources/toolbar/toolbar.css +2 -2
  63. data/lib/frameworks/sproutcore/themes/iphone_theme/english.lproj/button.css +3 -3
  64. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/button.css +18 -18
  65. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/checkbox.css +7 -7
  66. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/collection.css +2 -2
  67. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/core.css +7 -7
  68. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/disclosure.css +3 -3
  69. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/list_item.css +4 -4
  70. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/menu.css +3 -3
  71. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/menu_item_view.css +5 -5
  72. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/panel.css +7 -7
  73. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/picker.css +3 -3
  74. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/progress.css +5 -5
  75. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/radio.css +4 -4
  76. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/scroller.css +3 -3
  77. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/segmented.css +7 -7
  78. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/slider.css +2 -2
  79. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/split_view.css +2 -2
  80. data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/toolbar.css +3 -3
  81. data/lib/sproutcore/tools/server.rb +9 -3
  82. metadata +8 -83
  83. data/lib/frameworks/sproutcore/design/Assorted Images/sproutcore-startup-landscape.jpg +0 -0
  84. data/lib/frameworks/sproutcore/design/Assorted Images/sproutcore-startup-landscape.png +0 -0
  85. data/lib/frameworks/sproutcore/design/Assorted Images/sproutcore-startup-portrait.jpg +0 -0
  86. data/lib/frameworks/sproutcore/design/Assorted Images/sproutcore-startup-portrait.png +0 -0
  87. data/lib/frameworks/sproutcore/design/Assorted Images/sproutcore-startup.png +0 -0
  88. data/lib/frameworks/sproutcore/design/Record State Table.numbers +0 -0
  89. data/lib/frameworks/sproutcore/design/greenhouse-statechart.pdf +0 -0
  90. data/lib/frameworks/sproutcore/tests/phantomjs_runner.phantomjs +0 -611
  91. data/lib/frameworks/sproutcore/themes/ace/designs/dark.png +0 -0
  92. data/lib/frameworks/sproutcore/themes/ace/designs/light.png +0 -0
  93. data/lib/frameworks/sproutcore/themes/ace/designs/psds/panel/PanelPane.opacity +0 -0
  94. data/lib/frameworks/sproutcore/themes/ace/designs/psds/panel/Pointers.opacity +0 -0
  95. data/lib/frameworks/sproutcore/themes/ace/designs/switch/switch_handle.png +0 -0
  96. data/lib/frameworks/sproutcore/themes/ace/designs/switch/switch_off.png +0 -0
  97. data/lib/frameworks/sproutcore/themes/ace/designs/switch/switch_on.png +0 -0
  98. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/10.png +0 -0
  99. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/100.png +0 -0
  100. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/102.png +0 -0
  101. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/110.png +0 -0
  102. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/120.png +0 -0
  103. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/127.png +0 -0
  104. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/18.png +0 -0
  105. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/19.png +0 -0
  106. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/2.png +0 -0
  107. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/24.png +0 -0
  108. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/26.png +0 -0
  109. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/27.png +0 -0
  110. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/28.png +0 -0
  111. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/29.png +0 -0
  112. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/30.png +0 -0
  113. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/31.png +0 -0
  114. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/33.png +0 -0
  115. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/37.png +0 -0
  116. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/41.png +0 -0
  117. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/16/99.png +0 -0
  118. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/10.png +0 -0
  119. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/100.png +0 -0
  120. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/102.png +0 -0
  121. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/110.png +0 -0
  122. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/120.png +0 -0
  123. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/127.png +0 -0
  124. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/18.png +0 -0
  125. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/19.png +0 -0
  126. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/2.png +0 -0
  127. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/24.png +0 -0
  128. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/26.png +0 -0
  129. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/27.png +0 -0
  130. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/28.png +0 -0
  131. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/29.png +0 -0
  132. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/30.png +0 -0
  133. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/31.png +0 -0
  134. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/33.png +0 -0
  135. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/37.png +0 -0
  136. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/41.png +0 -0
  137. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/24/99.png +0 -0
  138. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/10.png +0 -0
  139. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/100.png +0 -0
  140. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/102.png +0 -0
  141. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/110.png +0 -0
  142. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/120.png +0 -0
  143. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/127.png +0 -0
  144. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/18.png +0 -0
  145. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/19.png +0 -0
  146. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/2.png +0 -0
  147. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/24.png +0 -0
  148. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/26.png +0 -0
  149. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/27.png +0 -0
  150. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/28.png +0 -0
  151. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/29.png +0 -0
  152. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/30.png +0 -0
  153. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/31.png +0 -0
  154. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/33.png +0 -0
  155. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/37.png +0 -0
  156. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/41.png +0 -0
  157. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/32/99.png +0 -0
  158. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/48/10.png +0 -0
  159. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/48/18.png +0 -0
  160. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/48/19.png +0 -0
  161. data/lib/frameworks/sproutcore/themes/legacy_theme/Source/icons/48/2.png +0 -0
@@ -7,13 +7,21 @@
7
7
  // ========================================================================
8
8
  // SC.Validator.Password Base Tests
9
9
  // ========================================================================
10
- /*globals module test ok isObj equals expects */
10
+ /*globals module, test, ok, isObj, equals, expects */
11
11
  // htmlbody('<!-- Test Styles -->\
12
12
  // <form id="form" action="formaction"><input type="password" name="action" value="Test" id="field" maxlength="30"/></form>\
13
13
  // ');
14
- // module("SC.Validator.password");
15
- //
16
- // test("Attaching the field to the form", function() {
17
- // var a = SC.Validator.Password.attachTo(SC.$("#form"), SC.$('#field'));
18
- // alert(a);
19
- // });
14
+ module("SC.Validator.password");
15
+
16
+ test("Attaching the field to the form");
17
+ /* WON'T FIX AT THIS TIME.
18
+
19
+ This entire file was commented out.
20
+ An empty unit test file will cause a timeout in the test runner,
21
+ so I'm converting this to a warning.
22
+
23
+ , function() {
24
+ var a = SC.Validator.Password.attachTo(SC.$("#form"), SC.$('#field'));
25
+ alert(a);
26
+ });
27
+ */
@@ -154,7 +154,7 @@ SC.RunLoop = SC.Object.extend(/** @scope SC.RunLoop.prototype */ {
154
154
  // loop and may fire before the invokeOnce code in this case.
155
155
  var isRunLoopInProgress = this.get('isRunLoopInProgress');
156
156
  if (!isRunLoopInProgress) {
157
- SC.warn("Developer Warning: invokeOnce called outside of the run loop. This can cause problems in production code if not addressed. You likely need to wrap some event handling code within SC.run(...).");
157
+ SC.warn("Developer Warning: invokeOnce called outside of the run loop, which may cause unexpected problems. Check the stack trace below for what triggered this, and see http://blog.sproutcore.com/1-10-upgrade-invokefoo/ for more.");
158
158
  console.trace();
159
159
  }
160
160
  //@endif
@@ -226,7 +226,7 @@ SC.RunLoop = SC.Object.extend(/** @scope SC.RunLoop.prototype */ {
226
226
  // loop and may fire before the invokeLast code in this case.
227
227
  var isRunLoopInProgress = this.get('isRunLoopInProgress');
228
228
  if (!isRunLoopInProgress) {
229
- SC.warn("Developer Warning: invokeLast called outside of the run loop. This can cause problems in production code if not addressed. You likely need to wrap some event handling code within SC.run(...).");
229
+ SC.warn("Developer Warning: invokeLast called outside of the run loop, which may cause unexpected problems. Check the stack trace below for what triggered this, and see http://blog.sproutcore.com/1-10-upgrade-invokefoo/ for more.");
230
230
  console.trace();
231
231
  }
232
232
  //@endif
@@ -170,6 +170,10 @@ CoreTest.Runner = {
170
170
  }
171
171
  catch (e) {}
172
172
  }
173
+
174
+ if (typeof window.callPhantom === 'function') {
175
+ window.callPhantom(r);
176
+ }
173
177
  },
174
178
 
175
179
  planDidRecord: function(plan, module, test, assertions, timings) {
@@ -0,0 +1,181 @@
1
+ module.exports = function (args, opts) {
2
+ if (!opts) opts = {};
3
+
4
+ var flags = { bools : {}, strings : {} };
5
+
6
+ [].concat(opts['boolean']).filter(Boolean).forEach(function (key) {
7
+ flags.bools[key] = true;
8
+ });
9
+
10
+ [].concat(opts.string).filter(Boolean).forEach(function (key) {
11
+ flags.strings[key] = true;
12
+ });
13
+
14
+ var aliases = {};
15
+ Object.keys(opts.alias || {}).forEach(function (key) {
16
+ aliases[key] = [].concat(opts.alias[key]);
17
+ aliases[key].forEach(function (x) {
18
+ aliases[x] = [key].concat(aliases[key].filter(function (y) {
19
+ return x !== y;
20
+ }));
21
+ });
22
+ });
23
+
24
+ var defaults = opts['default'] || {};
25
+
26
+ var argv = { _ : [] };
27
+ Object.keys(flags.bools).forEach(function (key) {
28
+ setArg(key, defaults[key] === undefined ? false : defaults[key]);
29
+ });
30
+
31
+ function setArg (key, val) {
32
+ var value = !flags.strings[key] && isNumber(val)
33
+ ? Number(val) : val
34
+ ;
35
+ setKey(argv, key.split('.'), value);
36
+
37
+ (aliases[key] || []).forEach(function (x) {
38
+ setKey(argv, x.split('.'), value);
39
+ });
40
+ }
41
+
42
+ for (var i = 0; i < args.length; i++) {
43
+ var arg = args[i];
44
+
45
+ if (arg === '--') {
46
+ argv._.push.apply(argv._, args.slice(i + 1));
47
+ break;
48
+ }
49
+ else if (arg.match(/^--.+=/)) {
50
+ // Using [\s\S] instead of . because js doesn't support the
51
+ // 'dotall' regex modifier. See:
52
+ // http://stackoverflow.com/a/1068308/13216
53
+ var m = arg.match(/^--([^=]+)=([\s\S]*)$/);
54
+ setArg(m[1], m[2]);
55
+ }
56
+ else if (arg.match(/^--no-.+/)) {
57
+ var key = arg.match(/^--no-(.+)/)[1];
58
+ setArg(key, false);
59
+ }
60
+ else if (arg.match(/^--.+/)) {
61
+ var key = arg.match(/^--(.+)/)[1];
62
+ var next = args[i + 1];
63
+ if (next !== undefined && !next.match(/^-/)
64
+ && !flags.bools[key]
65
+ && (aliases[key] ? !flags.bools[aliases[key]] : true)) {
66
+ setArg(key, next);
67
+ i++;
68
+ }
69
+ else if (/^(true|false)$/.test(next)) {
70
+ setArg(key, next === 'true');
71
+ i++;
72
+ }
73
+ else {
74
+ setArg(key, true);
75
+ }
76
+ }
77
+ else if (arg.match(/^-[^-]+/)) {
78
+ var letters = arg.slice(1,-1).split('');
79
+
80
+ var broken = false;
81
+ for (var j = 0; j < letters.length; j++) {
82
+ var next = arg.slice(j+2);
83
+
84
+ if (next === '-') {
85
+ setArg(letters[j], next)
86
+ continue;
87
+ }
88
+
89
+ if (/[A-Za-z]/.test(letters[j])
90
+ && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
91
+ setArg(letters[j], next);
92
+ broken = true;
93
+ break;
94
+ }
95
+
96
+ if (letters[j+1] && letters[j+1].match(/\W/)) {
97
+ setArg(letters[j], arg.slice(j+2));
98
+ broken = true;
99
+ break;
100
+ }
101
+ else {
102
+ setArg(letters[j], true);
103
+ }
104
+ }
105
+
106
+ var key = arg.slice(-1)[0];
107
+ if (!broken && key !== '-') {
108
+
109
+ if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1])
110
+ && !flags.bools[key]
111
+ && (aliases[key] ? !flags.bools[aliases[key]] : true)) {
112
+ setArg(key, args[i+1]);
113
+ i++;
114
+ }
115
+ else if (args[i+1] && /true|false/.test(args[i+1])) {
116
+ setArg(key, args[i+1] === 'true');
117
+ i++;
118
+ }
119
+ else {
120
+ setArg(key, true);
121
+ }
122
+ }
123
+ }
124
+ else {
125
+ argv._.push(
126
+ flags.strings['_'] || !isNumber(arg) ? arg : Number(arg)
127
+ );
128
+ }
129
+ }
130
+
131
+ Object.keys(defaults).forEach(function (key) {
132
+ if (!hasKey(argv, key.split('.'))) {
133
+ setKey(argv, key.split('.'), defaults[key]);
134
+
135
+ (aliases[key] || []).forEach(function (x) {
136
+ setKey(argv, x.split('.'), defaults[key]);
137
+ });
138
+ }
139
+ });
140
+
141
+ return argv;
142
+ };
143
+
144
+ function hasKey (obj, keys) {
145
+ var o = obj;
146
+ keys.slice(0,-1).forEach(function (key) {
147
+ o = (o[key] || {});
148
+ });
149
+
150
+ var key = keys[keys.length - 1];
151
+ return key in o;
152
+ }
153
+
154
+ function setKey (obj, keys, value) {
155
+ var o = obj;
156
+ keys.slice(0,-1).forEach(function (key) {
157
+ if (o[key] === undefined) o[key] = {};
158
+ o = o[key];
159
+ });
160
+
161
+ var key = keys[keys.length - 1];
162
+ if (o[key] === undefined || typeof o[key] === 'boolean') {
163
+ o[key] = value;
164
+ }
165
+ else if (Array.isArray(o[key])) {
166
+ o[key].push(value);
167
+ }
168
+ else {
169
+ o[key] = [ o[key], value ];
170
+ }
171
+ }
172
+
173
+ function isNumber (x) {
174
+ if (typeof x === 'number') return true;
175
+ if (/^0x[0-9a-f]+$/i.test(x)) return true;
176
+ return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x);
177
+ }
178
+
179
+ function longest (xs) {
180
+ return Math.max.apply(null, xs.map(function (x) { return x.length }));
181
+ }
@@ -0,0 +1,1937 @@
1
+ // vim:ts=4:sts=4:sw=4:
2
+ /*!
3
+ *
4
+ * Copyright 2009-2012 Kris Kowal under the terms of the MIT
5
+ * license found at http://github.com/kriskowal/q/raw/master/LICENSE
6
+ *
7
+ * With parts by Tyler Close
8
+ * Copyright 2007-2009 Tyler Close under the terms of the MIT X license found
9
+ * at http://www.opensource.org/licenses/mit-license.html
10
+ * Forked at ref_send.js version: 2009-05-11
11
+ *
12
+ * With parts by Mark Miller
13
+ * Copyright (C) 2011 Google Inc.
14
+ *
15
+ * Licensed under the Apache License, Version 2.0 (the "License");
16
+ * you may not use this file except in compliance with the License.
17
+ * You may obtain a copy of the License at
18
+ *
19
+ * http://www.apache.org/licenses/LICENSE-2.0
20
+ *
21
+ * Unless required by applicable law or agreed to in writing, software
22
+ * distributed under the License is distributed on an "AS IS" BASIS,
23
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24
+ * See the License for the specific language governing permissions and
25
+ * limitations under the License.
26
+ *
27
+ */
28
+
29
+ (function (definition) {
30
+ // Turn off strict mode for this function so we can assign to global.Q
31
+ /* jshint strict: false */
32
+
33
+ // This file will function properly as a <script> tag, or a module
34
+ // using CommonJS and NodeJS or RequireJS module formats. In
35
+ // Common/Node/RequireJS, the module exports the Q API and when
36
+ // executed as a simple <script>, it creates a Q global instead.
37
+
38
+ // Montage Require
39
+ if (typeof bootstrap === "function") {
40
+ bootstrap("promise", definition);
41
+
42
+ // CommonJS
43
+ } else if (typeof exports === "object") {
44
+ module.exports = definition();
45
+
46
+ // RequireJS
47
+ } else if (typeof define === "function" && define.amd) {
48
+ define(definition);
49
+
50
+ // SES (Secure EcmaScript)
51
+ } else if (typeof ses !== "undefined") {
52
+ if (!ses.ok()) {
53
+ return;
54
+ } else {
55
+ ses.makeQ = definition;
56
+ }
57
+
58
+ // <script>
59
+ } else {
60
+ Q = definition();
61
+ }
62
+
63
+ })(function () {
64
+ "use strict";
65
+
66
+ var hasStacks = false;
67
+ try {
68
+ throw new Error();
69
+ } catch (e) {
70
+ hasStacks = !!e.stack;
71
+ }
72
+
73
+ // All code after this point will be filtered from stack traces reported
74
+ // by Q.
75
+ var qStartingLine = captureLine();
76
+ var qFileName;
77
+
78
+ // shims
79
+
80
+ // used for fallback in "allResolved"
81
+ var noop = function () {};
82
+
83
+ // Use the fastest possible means to execute a task in a future turn
84
+ // of the event loop.
85
+ var nextTick =(function () {
86
+ // linked list of tasks (single, with head node)
87
+ var head = {task: void 0, next: null};
88
+ var tail = head;
89
+ var flushing = false;
90
+ var requestTick = void 0;
91
+ var isNodeJS = false;
92
+
93
+ function flush() {
94
+ /* jshint loopfunc: true */
95
+
96
+ while (head.next) {
97
+ head = head.next;
98
+ var task = head.task;
99
+ head.task = void 0;
100
+ var domain = head.domain;
101
+
102
+ if (domain) {
103
+ head.domain = void 0;
104
+ domain.enter();
105
+ }
106
+
107
+ try {
108
+ task();
109
+
110
+ } catch (e) {
111
+ if (isNodeJS) {
112
+ // In node, uncaught exceptions are considered fatal errors.
113
+ // Re-throw them synchronously to interrupt flushing!
114
+
115
+ // Ensure continuation if the uncaught exception is suppressed
116
+ // listening "uncaughtException" events (as domains does).
117
+ // Continue in next event to avoid tick recursion.
118
+ if (domain) {
119
+ domain.exit();
120
+ }
121
+ setTimeout(flush, 0);
122
+ if (domain) {
123
+ domain.enter();
124
+ }
125
+
126
+ throw e;
127
+
128
+ } else {
129
+ // In browsers, uncaught exceptions are not fatal.
130
+ // Re-throw them asynchronously to avoid slow-downs.
131
+ setTimeout(function() {
132
+ throw e;
133
+ }, 0);
134
+ }
135
+ }
136
+
137
+ if (domain) {
138
+ domain.exit();
139
+ }
140
+ }
141
+
142
+ flushing = false;
143
+ }
144
+
145
+ nextTick = function (task) {
146
+ tail = tail.next = {
147
+ task: task,
148
+ domain: isNodeJS && process.domain,
149
+ next: null
150
+ };
151
+
152
+ if (!flushing) {
153
+ flushing = true;
154
+ requestTick();
155
+ }
156
+ };
157
+
158
+ if (typeof process !== "undefined" && process.nextTick) {
159
+ // Node.js before 0.9. Note that some fake-Node environments, like the
160
+ // Mocha test runner, introduce a `process` global without a `nextTick`.
161
+ isNodeJS = true;
162
+
163
+ requestTick = function () {
164
+ process.nextTick(flush);
165
+ };
166
+
167
+ } else if (typeof setImmediate === "function") {
168
+ // In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate
169
+ if (typeof window !== "undefined") {
170
+ requestTick = setImmediate.bind(window, flush);
171
+ } else {
172
+ requestTick = function () {
173
+ setImmediate(flush);
174
+ };
175
+ }
176
+
177
+ } else if (typeof MessageChannel !== "undefined") {
178
+ // modern browsers
179
+ // http://www.nonblocking.io/2011/06/windownexttick.html
180
+ var channel = new MessageChannel();
181
+ // At least Safari Version 6.0.5 (8536.30.1) intermittently cannot create
182
+ // working message ports the first time a page loads.
183
+ channel.port1.onmessage = function () {
184
+ requestTick = requestPortTick;
185
+ channel.port1.onmessage = flush;
186
+ flush();
187
+ };
188
+ var requestPortTick = function () {
189
+ // Opera requires us to provide a message payload, regardless of
190
+ // whether we use it.
191
+ channel.port2.postMessage(0);
192
+ };
193
+ requestTick = function () {
194
+ setTimeout(flush, 0);
195
+ requestPortTick();
196
+ };
197
+
198
+ } else {
199
+ // old browsers
200
+ requestTick = function () {
201
+ setTimeout(flush, 0);
202
+ };
203
+ }
204
+
205
+ return nextTick;
206
+ })();
207
+
208
+ // Attempt to make generics safe in the face of downstream
209
+ // modifications.
210
+ // There is no situation where this is necessary.
211
+ // If you need a security guarantee, these primordials need to be
212
+ // deeply frozen anyway, and if you don’t need a security guarantee,
213
+ // this is just plain paranoid.
214
+ // However, this does have the nice side-effect of reducing the size
215
+ // of the code by reducing x.call() to merely x(), eliminating many
216
+ // hard-to-minify characters.
217
+ // See Mark Miller’s explanation of what this does.
218
+ // http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
219
+ var call = Function.call;
220
+ function uncurryThis(f) {
221
+ return function () {
222
+ return call.apply(f, arguments);
223
+ };
224
+ }
225
+ // This is equivalent, but slower:
226
+ // uncurryThis = Function_bind.bind(Function_bind.call);
227
+ // http://jsperf.com/uncurrythis
228
+
229
+ var array_slice = uncurryThis(Array.prototype.slice);
230
+
231
+ var array_reduce = uncurryThis(
232
+ Array.prototype.reduce || function (callback, basis) {
233
+ var index = 0,
234
+ length = this.length;
235
+ // concerning the initial value, if one is not provided
236
+ if (arguments.length === 1) {
237
+ // seek to the first value in the array, accounting
238
+ // for the possibility that is is a sparse array
239
+ do {
240
+ if (index in this) {
241
+ basis = this[index++];
242
+ break;
243
+ }
244
+ if (++index >= length) {
245
+ throw new TypeError();
246
+ }
247
+ } while (1);
248
+ }
249
+ // reduce
250
+ for (; index < length; index++) {
251
+ // account for the possibility that the array is sparse
252
+ if (index in this) {
253
+ basis = callback(basis, this[index], index);
254
+ }
255
+ }
256
+ return basis;
257
+ }
258
+ );
259
+
260
+ var array_indexOf = uncurryThis(
261
+ Array.prototype.indexOf || function (value) {
262
+ // not a very good shim, but good enough for our one use of it
263
+ for (var i = 0; i < this.length; i++) {
264
+ if (this[i] === value) {
265
+ return i;
266
+ }
267
+ }
268
+ return -1;
269
+ }
270
+ );
271
+
272
+ var array_map = uncurryThis(
273
+ Array.prototype.map || function (callback, thisp) {
274
+ var self = this;
275
+ var collect = [];
276
+ array_reduce(self, function (undefined, value, index) {
277
+ collect.push(callback.call(thisp, value, index, self));
278
+ }, void 0);
279
+ return collect;
280
+ }
281
+ );
282
+
283
+ var object_create = Object.create || function (prototype) {
284
+ function Type() { }
285
+ Type.prototype = prototype;
286
+ return new Type();
287
+ };
288
+
289
+ var object_hasOwnProperty = uncurryThis(Object.prototype.hasOwnProperty);
290
+
291
+ var object_keys = Object.keys || function (object) {
292
+ var keys = [];
293
+ for (var key in object) {
294
+ if (object_hasOwnProperty(object, key)) {
295
+ keys.push(key);
296
+ }
297
+ }
298
+ return keys;
299
+ };
300
+
301
+ var object_toString = uncurryThis(Object.prototype.toString);
302
+
303
+ function isObject(value) {
304
+ return value === Object(value);
305
+ }
306
+
307
+ // generator related shims
308
+
309
+ // FIXME: Remove this function once ES6 generators are in SpiderMonkey.
310
+ function isStopIteration(exception) {
311
+ return (
312
+ object_toString(exception) === "[object StopIteration]" ||
313
+ exception instanceof QReturnValue
314
+ );
315
+ }
316
+
317
+ // FIXME: Remove this helper and Q.return once ES6 generators are in
318
+ // SpiderMonkey.
319
+ var QReturnValue;
320
+ if (typeof ReturnValue !== "undefined") {
321
+ QReturnValue = ReturnValue;
322
+ } else {
323
+ QReturnValue = function (value) {
324
+ this.value = value;
325
+ };
326
+ }
327
+
328
+ // Until V8 3.19 / Chromium 29 is released, SpiderMonkey is the only
329
+ // engine that has a deployed base of browsers that support generators.
330
+ // However, SM's generators use the Python-inspired semantics of
331
+ // outdated ES6 drafts. We would like to support ES6, but we'd also
332
+ // like to make it possible to use generators in deployed browsers, so
333
+ // we also support Python-style generators. At some point we can remove
334
+ // this block.
335
+ var hasES6Generators;
336
+ try {
337
+ /* jshint evil: true, nonew: false */
338
+ new Function("(function* (){ yield 1; })");
339
+ hasES6Generators = true;
340
+ } catch (e) {
341
+ hasES6Generators = false;
342
+ }
343
+
344
+ // long stack traces
345
+
346
+ var STACK_JUMP_SEPARATOR = "From previous event:";
347
+
348
+ function makeStackTraceLong(error, promise) {
349
+ // If possible, transform the error stack trace by removing Node and Q
350
+ // cruft, then concatenating with the stack trace of `promise`. See #57.
351
+ if (hasStacks &&
352
+ promise.stack &&
353
+ typeof error === "object" &&
354
+ error !== null &&
355
+ error.stack &&
356
+ error.stack.indexOf(STACK_JUMP_SEPARATOR) === -1
357
+ ) {
358
+ var stacks = [];
359
+ for (var p = promise; !!p; p = p.source) {
360
+ if (p.stack) {
361
+ stacks.unshift(p.stack);
362
+ }
363
+ }
364
+ stacks.unshift(error.stack);
365
+
366
+ var concatedStacks = stacks.join("\n" + STACK_JUMP_SEPARATOR + "\n");
367
+ error.stack = filterStackString(concatedStacks);
368
+ }
369
+ }
370
+
371
+ function filterStackString(stackString) {
372
+ var lines = stackString.split("\n");
373
+ var desiredLines = [];
374
+ for (var i = 0; i < lines.length; ++i) {
375
+ var line = lines[i];
376
+
377
+ if (!isInternalFrame(line) && !isNodeFrame(line) && line) {
378
+ desiredLines.push(line);
379
+ }
380
+ }
381
+ return desiredLines.join("\n");
382
+ }
383
+
384
+ function isNodeFrame(stackLine) {
385
+ return stackLine.indexOf("(module.js:") !== -1 ||
386
+ stackLine.indexOf("(node.js:") !== -1;
387
+ }
388
+
389
+ function getFileNameAndLineNumber(stackLine) {
390
+ // Named functions: "at functionName (filename:lineNumber:columnNumber)"
391
+ // In IE10 function name can have spaces ("Anonymous function") O_o
392
+ var attempt1 = /at .+ \((.+):(\d+):(?:\d+)\)$/.exec(stackLine);
393
+ if (attempt1) {
394
+ return [attempt1[1], Number(attempt1[2])];
395
+ }
396
+
397
+ // Anonymous functions: "at filename:lineNumber:columnNumber"
398
+ var attempt2 = /at ([^ ]+):(\d+):(?:\d+)$/.exec(stackLine);
399
+ if (attempt2) {
400
+ return [attempt2[1], Number(attempt2[2])];
401
+ }
402
+
403
+ // Firefox style: "function@filename:lineNumber or @filename:lineNumber"
404
+ var attempt3 = /.*@(.+):(\d+)$/.exec(stackLine);
405
+ if (attempt3) {
406
+ return [attempt3[1], Number(attempt3[2])];
407
+ }
408
+ }
409
+
410
+ function isInternalFrame(stackLine) {
411
+ var fileNameAndLineNumber = getFileNameAndLineNumber(stackLine);
412
+
413
+ if (!fileNameAndLineNumber) {
414
+ return false;
415
+ }
416
+
417
+ var fileName = fileNameAndLineNumber[0];
418
+ var lineNumber = fileNameAndLineNumber[1];
419
+
420
+ return fileName === qFileName &&
421
+ lineNumber >= qStartingLine &&
422
+ lineNumber <= qEndingLine;
423
+ }
424
+
425
+ // discover own file name and line number range for filtering stack
426
+ // traces
427
+ function captureLine() {
428
+ if (!hasStacks) {
429
+ return;
430
+ }
431
+
432
+ try {
433
+ throw new Error();
434
+ } catch (e) {
435
+ var lines = e.stack.split("\n");
436
+ var firstLine = lines[0].indexOf("@") > 0 ? lines[1] : lines[2];
437
+ var fileNameAndLineNumber = getFileNameAndLineNumber(firstLine);
438
+ if (!fileNameAndLineNumber) {
439
+ return;
440
+ }
441
+
442
+ qFileName = fileNameAndLineNumber[0];
443
+ return fileNameAndLineNumber[1];
444
+ }
445
+ }
446
+
447
+ function deprecate(callback, name, alternative) {
448
+ return function () {
449
+ if (typeof console !== "undefined" &&
450
+ typeof console.warn === "function") {
451
+ console.warn(name + " is deprecated, use " + alternative +
452
+ " instead.", new Error("").stack);
453
+ }
454
+ return callback.apply(callback, arguments);
455
+ };
456
+ }
457
+
458
+ // end of shims
459
+ // beginning of real work
460
+
461
+ /**
462
+ * Constructs a promise for an immediate reference, passes promises through, or
463
+ * coerces promises from different systems.
464
+ * @param value immediate reference or promise
465
+ */
466
+ function Q(value) {
467
+ // If the object is already a Promise, return it directly. This enables
468
+ // the resolve function to both be used to created references from objects,
469
+ // but to tolerably coerce non-promises to promises.
470
+ if (isPromise(value)) {
471
+ return value;
472
+ }
473
+
474
+ // assimilate thenables
475
+ if (isPromiseAlike(value)) {
476
+ return coerce(value);
477
+ } else {
478
+ return fulfill(value);
479
+ }
480
+ }
481
+ Q.resolve = Q;
482
+
483
+ /**
484
+ * Performs a task in a future turn of the event loop.
485
+ * @param {Function} task
486
+ */
487
+ Q.nextTick = nextTick;
488
+
489
+ /**
490
+ * Controls whether or not long stack traces will be on
491
+ */
492
+ Q.longStackSupport = false;
493
+
494
+ /**
495
+ * Constructs a {promise, resolve, reject} object.
496
+ *
497
+ * `resolve` is a callback to invoke with a more resolved value for the
498
+ * promise. To fulfill the promise, invoke `resolve` with any value that is
499
+ * not a thenable. To reject the promise, invoke `resolve` with a rejected
500
+ * thenable, or invoke `reject` with the reason directly. To resolve the
501
+ * promise to another thenable, thus putting it in the same state, invoke
502
+ * `resolve` with that other thenable.
503
+ */
504
+ Q.defer = defer;
505
+ function defer() {
506
+ // if "messages" is an "Array", that indicates that the promise has not yet
507
+ // been resolved. If it is "undefined", it has been resolved. Each
508
+ // element of the messages array is itself an array of complete arguments to
509
+ // forward to the resolved promise. We coerce the resolution value to a
510
+ // promise using the `resolve` function because it handles both fully
511
+ // non-thenable values and other thenables gracefully.
512
+ var messages = [], progressListeners = [], resolvedPromise;
513
+
514
+ var deferred = object_create(defer.prototype);
515
+ var promise = object_create(Promise.prototype);
516
+
517
+ promise.promiseDispatch = function (resolve, op, operands) {
518
+ var args = array_slice(arguments);
519
+ if (messages) {
520
+ messages.push(args);
521
+ if (op === "when" && operands[1]) { // progress operand
522
+ progressListeners.push(operands[1]);
523
+ }
524
+ } else {
525
+ nextTick(function () {
526
+ resolvedPromise.promiseDispatch.apply(resolvedPromise, args);
527
+ });
528
+ }
529
+ };
530
+
531
+ // XXX deprecated
532
+ promise.valueOf = deprecate(function () {
533
+ if (messages) {
534
+ return promise;
535
+ }
536
+ var nearerValue = nearer(resolvedPromise);
537
+ if (isPromise(nearerValue)) {
538
+ resolvedPromise = nearerValue; // shorten chain
539
+ }
540
+ return nearerValue;
541
+ }, "valueOf", "inspect");
542
+
543
+ promise.inspect = function () {
544
+ if (!resolvedPromise) {
545
+ return { state: "pending" };
546
+ }
547
+ return resolvedPromise.inspect();
548
+ };
549
+
550
+ if (Q.longStackSupport && hasStacks) {
551
+ try {
552
+ throw new Error();
553
+ } catch (e) {
554
+ // NOTE: don't try to use `Error.captureStackTrace` or transfer the
555
+ // accessor around; that causes memory leaks as per GH-111. Just
556
+ // reify the stack trace as a string ASAP.
557
+ //
558
+ // At the same time, cut off the first line; it's always just
559
+ // "[object Promise]\n", as per the `toString`.
560
+ promise.stack = e.stack.substring(e.stack.indexOf("\n") + 1);
561
+ }
562
+ }
563
+
564
+ // NOTE: we do the checks for `resolvedPromise` in each method, instead of
565
+ // consolidating them into `become`, since otherwise we'd create new
566
+ // promises with the lines `become(whatever(value))`. See e.g. GH-252.
567
+
568
+ function become(newPromise) {
569
+ resolvedPromise = newPromise;
570
+ promise.source = newPromise;
571
+
572
+ array_reduce(messages, function (undefined, message) {
573
+ nextTick(function () {
574
+ newPromise.promiseDispatch.apply(newPromise, message);
575
+ });
576
+ }, void 0);
577
+
578
+ messages = void 0;
579
+ progressListeners = void 0;
580
+ }
581
+
582
+ deferred.promise = promise;
583
+ deferred.resolve = function (value) {
584
+ if (resolvedPromise) {
585
+ return;
586
+ }
587
+
588
+ become(Q(value));
589
+ };
590
+
591
+ deferred.fulfill = function (value) {
592
+ if (resolvedPromise) {
593
+ return;
594
+ }
595
+
596
+ become(fulfill(value));
597
+ };
598
+ deferred.reject = function (reason) {
599
+ if (resolvedPromise) {
600
+ return;
601
+ }
602
+
603
+ become(reject(reason));
604
+ };
605
+ deferred.notify = function (progress) {
606
+ if (resolvedPromise) {
607
+ return;
608
+ }
609
+
610
+ array_reduce(progressListeners, function (undefined, progressListener) {
611
+ nextTick(function () {
612
+ progressListener(progress);
613
+ });
614
+ }, void 0);
615
+ };
616
+
617
+ return deferred;
618
+ }
619
+
620
+ /**
621
+ * Creates a Node-style callback that will resolve or reject the deferred
622
+ * promise.
623
+ * @returns a nodeback
624
+ */
625
+ defer.prototype.makeNodeResolver = function () {
626
+ var self = this;
627
+ return function (error, value) {
628
+ if (error) {
629
+ self.reject(error);
630
+ } else if (arguments.length > 2) {
631
+ self.resolve(array_slice(arguments, 1));
632
+ } else {
633
+ self.resolve(value);
634
+ }
635
+ };
636
+ };
637
+
638
+ /**
639
+ * @param resolver {Function} a function that returns nothing and accepts
640
+ * the resolve, reject, and notify functions for a deferred.
641
+ * @returns a promise that may be resolved with the given resolve and reject
642
+ * functions, or rejected by a thrown exception in resolver
643
+ */
644
+ Q.promise = promise;
645
+ function promise(resolver) {
646
+ if (typeof resolver !== "function") {
647
+ throw new TypeError("resolver must be a function.");
648
+ }
649
+ var deferred = defer();
650
+ try {
651
+ resolver(deferred.resolve, deferred.reject, deferred.notify);
652
+ } catch (reason) {
653
+ deferred.reject(reason);
654
+ }
655
+ return deferred.promise;
656
+ }
657
+
658
+ // XXX experimental. This method is a way to denote that a local value is
659
+ // serializable and should be immediately dispatched to a remote upon request,
660
+ // instead of passing a reference.
661
+ Q.passByCopy = function (object) {
662
+ //freeze(object);
663
+ //passByCopies.set(object, true);
664
+ return object;
665
+ };
666
+
667
+ Promise.prototype.passByCopy = function () {
668
+ //freeze(object);
669
+ //passByCopies.set(object, true);
670
+ return this;
671
+ };
672
+
673
+ /**
674
+ * If two promises eventually fulfill to the same value, promises that value,
675
+ * but otherwise rejects.
676
+ * @param x {Any*}
677
+ * @param y {Any*}
678
+ * @returns {Any*} a promise for x and y if they are the same, but a rejection
679
+ * otherwise.
680
+ *
681
+ */
682
+ Q.join = function (x, y) {
683
+ return Q(x).join(y);
684
+ };
685
+
686
+ Promise.prototype.join = function (that) {
687
+ return Q([this, that]).spread(function (x, y) {
688
+ if (x === y) {
689
+ // TODO: "===" should be Object.is or equiv
690
+ return x;
691
+ } else {
692
+ throw new Error("Can't join: not the same: " + x + " " + y);
693
+ }
694
+ });
695
+ };
696
+
697
+ /**
698
+ * Returns a promise for the first of an array of promises to become fulfilled.
699
+ * @param answers {Array[Any*]} promises to race
700
+ * @returns {Any*} the first promise to be fulfilled
701
+ */
702
+ Q.race = race;
703
+ function race(answerPs) {
704
+ return promise(function(resolve, reject) {
705
+ // Switch to this once we can assume at least ES5
706
+ // answerPs.forEach(function(answerP) {
707
+ // Q(answerP).then(resolve, reject);
708
+ // });
709
+ // Use this in the meantime
710
+ for (var i = 0, len = answerPs.length; i < len; i++) {
711
+ Q(answerPs[i]).then(resolve, reject);
712
+ }
713
+ });
714
+ }
715
+
716
+ Promise.prototype.race = function () {
717
+ return this.then(Q.race);
718
+ };
719
+
720
+ /**
721
+ * Constructs a Promise with a promise descriptor object and optional fallback
722
+ * function. The descriptor contains methods like when(rejected), get(name),
723
+ * set(name, value), post(name, args), and delete(name), which all
724
+ * return either a value, a promise for a value, or a rejection. The fallback
725
+ * accepts the operation name, a resolver, and any further arguments that would
726
+ * have been forwarded to the appropriate method above had a method been
727
+ * provided with the proper name. The API makes no guarantees about the nature
728
+ * of the returned object, apart from that it is usable whereever promises are
729
+ * bought and sold.
730
+ */
731
+ Q.makePromise = Promise;
732
+ function Promise(descriptor, fallback, inspect) {
733
+ if (fallback === void 0) {
734
+ fallback = function (op) {
735
+ return reject(new Error(
736
+ "Promise does not support operation: " + op
737
+ ));
738
+ };
739
+ }
740
+ if (inspect === void 0) {
741
+ inspect = function () {
742
+ return {state: "unknown"};
743
+ };
744
+ }
745
+
746
+ var promise = object_create(Promise.prototype);
747
+
748
+ promise.promiseDispatch = function (resolve, op, args) {
749
+ var result;
750
+ try {
751
+ if (descriptor[op]) {
752
+ result = descriptor[op].apply(promise, args);
753
+ } else {
754
+ result = fallback.call(promise, op, args);
755
+ }
756
+ } catch (exception) {
757
+ result = reject(exception);
758
+ }
759
+ if (resolve) {
760
+ resolve(result);
761
+ }
762
+ };
763
+
764
+ promise.inspect = inspect;
765
+
766
+ // XXX deprecated `valueOf` and `exception` support
767
+ if (inspect) {
768
+ var inspected = inspect();
769
+ if (inspected.state === "rejected") {
770
+ promise.exception = inspected.reason;
771
+ }
772
+
773
+ promise.valueOf = deprecate(function () {
774
+ var inspected = inspect();
775
+ if (inspected.state === "pending" ||
776
+ inspected.state === "rejected") {
777
+ return promise;
778
+ }
779
+ return inspected.value;
780
+ });
781
+ }
782
+
783
+ return promise;
784
+ }
785
+
786
+ Promise.prototype.toString = function () {
787
+ return "[object Promise]";
788
+ };
789
+
790
+ Promise.prototype.then = function (fulfilled, rejected, progressed) {
791
+ var self = this;
792
+ var deferred = defer();
793
+ var done = false; // ensure the untrusted promise makes at most a
794
+ // single call to one of the callbacks
795
+
796
+ function _fulfilled(value) {
797
+ try {
798
+ return typeof fulfilled === "function" ? fulfilled(value) : value;
799
+ } catch (exception) {
800
+ return reject(exception);
801
+ }
802
+ }
803
+
804
+ function _rejected(exception) {
805
+ if (typeof rejected === "function") {
806
+ makeStackTraceLong(exception, self);
807
+ try {
808
+ return rejected(exception);
809
+ } catch (newException) {
810
+ return reject(newException);
811
+ }
812
+ }
813
+ return reject(exception);
814
+ }
815
+
816
+ function _progressed(value) {
817
+ return typeof progressed === "function" ? progressed(value) : value;
818
+ }
819
+
820
+ nextTick(function () {
821
+ self.promiseDispatch(function (value) {
822
+ if (done) {
823
+ return;
824
+ }
825
+ done = true;
826
+
827
+ deferred.resolve(_fulfilled(value));
828
+ }, "when", [function (exception) {
829
+ if (done) {
830
+ return;
831
+ }
832
+ done = true;
833
+
834
+ deferred.resolve(_rejected(exception));
835
+ }]);
836
+ });
837
+
838
+ // Progress propagator need to be attached in the current tick.
839
+ self.promiseDispatch(void 0, "when", [void 0, function (value) {
840
+ var newValue;
841
+ var threw = false;
842
+ try {
843
+ newValue = _progressed(value);
844
+ } catch (e) {
845
+ threw = true;
846
+ if (Q.onerror) {
847
+ Q.onerror(e);
848
+ } else {
849
+ throw e;
850
+ }
851
+ }
852
+
853
+ if (!threw) {
854
+ deferred.notify(newValue);
855
+ }
856
+ }]);
857
+
858
+ return deferred.promise;
859
+ };
860
+
861
+ /**
862
+ * Registers an observer on a promise.
863
+ *
864
+ * Guarantees:
865
+ *
866
+ * 1. that fulfilled and rejected will be called only once.
867
+ * 2. that either the fulfilled callback or the rejected callback will be
868
+ * called, but not both.
869
+ * 3. that fulfilled and rejected will not be called in this turn.
870
+ *
871
+ * @param value promise or immediate reference to observe
872
+ * @param fulfilled function to be called with the fulfilled value
873
+ * @param rejected function to be called with the rejection exception
874
+ * @param progressed function to be called on any progress notifications
875
+ * @return promise for the return value from the invoked callback
876
+ */
877
+ Q.when = when;
878
+ function when(value, fulfilled, rejected, progressed) {
879
+ return Q(value).then(fulfilled, rejected, progressed);
880
+ }
881
+
882
+ Promise.prototype.thenResolve = function (value) {
883
+ return this.then(function () { return value; });
884
+ };
885
+
886
+ Q.thenResolve = function (promise, value) {
887
+ return Q(promise).thenResolve(value);
888
+ };
889
+
890
+ Promise.prototype.thenReject = function (reason) {
891
+ return this.then(function () { throw reason; });
892
+ };
893
+
894
+ Q.thenReject = function (promise, reason) {
895
+ return Q(promise).thenReject(reason);
896
+ };
897
+
898
+ /**
899
+ * If an object is not a promise, it is as "near" as possible.
900
+ * If a promise is rejected, it is as "near" as possible too.
901
+ * If it’s a fulfilled promise, the fulfillment value is nearer.
902
+ * If it’s a deferred promise and the deferred has been resolved, the
903
+ * resolution is "nearer".
904
+ * @param object
905
+ * @returns most resolved (nearest) form of the object
906
+ */
907
+
908
+ // XXX should we re-do this?
909
+ Q.nearer = nearer;
910
+ function nearer(value) {
911
+ if (isPromise(value)) {
912
+ var inspected = value.inspect();
913
+ if (inspected.state === "fulfilled") {
914
+ return inspected.value;
915
+ }
916
+ }
917
+ return value;
918
+ }
919
+
920
+ /**
921
+ * @returns whether the given object is a promise.
922
+ * Otherwise it is a fulfilled value.
923
+ */
924
+ Q.isPromise = isPromise;
925
+ function isPromise(object) {
926
+ return isObject(object) &&
927
+ typeof object.promiseDispatch === "function" &&
928
+ typeof object.inspect === "function";
929
+ }
930
+
931
+ Q.isPromiseAlike = isPromiseAlike;
932
+ function isPromiseAlike(object) {
933
+ return isObject(object) && typeof object.then === "function";
934
+ }
935
+
936
+ /**
937
+ * @returns whether the given object is a pending promise, meaning not
938
+ * fulfilled or rejected.
939
+ */
940
+ Q.isPending = isPending;
941
+ function isPending(object) {
942
+ return isPromise(object) && object.inspect().state === "pending";
943
+ }
944
+
945
+ Promise.prototype.isPending = function () {
946
+ return this.inspect().state === "pending";
947
+ };
948
+
949
+ /**
950
+ * @returns whether the given object is a value or fulfilled
951
+ * promise.
952
+ */
953
+ Q.isFulfilled = isFulfilled;
954
+ function isFulfilled(object) {
955
+ return !isPromise(object) || object.inspect().state === "fulfilled";
956
+ }
957
+
958
+ Promise.prototype.isFulfilled = function () {
959
+ return this.inspect().state === "fulfilled";
960
+ };
961
+
962
+ /**
963
+ * @returns whether the given object is a rejected promise.
964
+ */
965
+ Q.isRejected = isRejected;
966
+ function isRejected(object) {
967
+ return isPromise(object) && object.inspect().state === "rejected";
968
+ }
969
+
970
+ Promise.prototype.isRejected = function () {
971
+ return this.inspect().state === "rejected";
972
+ };
973
+
974
+ //// BEGIN UNHANDLED REJECTION TRACKING
975
+
976
+ // This promise library consumes exceptions thrown in handlers so they can be
977
+ // handled by a subsequent promise. The exceptions get added to this array when
978
+ // they are created, and removed when they are handled. Note that in ES6 or
979
+ // shimmed environments, this would naturally be a `Set`.
980
+ var unhandledReasons = [];
981
+ var unhandledRejections = [];
982
+ var unhandledReasonsDisplayed = false;
983
+ var trackUnhandledRejections = true;
984
+ function displayUnhandledReasons() {
985
+ if (
986
+ !unhandledReasonsDisplayed &&
987
+ typeof window !== "undefined" &&
988
+ !window.Touch &&
989
+ window.console
990
+ ) {
991
+ console.warn("[Q] Unhandled rejection reasons (should be empty):",
992
+ unhandledReasons);
993
+ }
994
+
995
+ unhandledReasonsDisplayed = true;
996
+ }
997
+
998
+ function logUnhandledReasons() {
999
+ for (var i = 0; i < unhandledReasons.length; i++) {
1000
+ var reason = unhandledReasons[i];
1001
+ console.warn("Unhandled rejection reason:", reason);
1002
+ }
1003
+ }
1004
+
1005
+ function resetUnhandledRejections() {
1006
+ unhandledReasons.length = 0;
1007
+ unhandledRejections.length = 0;
1008
+ unhandledReasonsDisplayed = false;
1009
+
1010
+ if (!trackUnhandledRejections) {
1011
+ trackUnhandledRejections = true;
1012
+
1013
+ // Show unhandled rejection reasons if Node exits without handling an
1014
+ // outstanding rejection. (Note that Browserify presently produces a
1015
+ // `process` global without the `EventEmitter` `on` method.)
1016
+ if (typeof process !== "undefined" && process.on) {
1017
+ process.on("exit", logUnhandledReasons);
1018
+ }
1019
+ }
1020
+ }
1021
+
1022
+ function trackRejection(promise, reason) {
1023
+ if (!trackUnhandledRejections) {
1024
+ return;
1025
+ }
1026
+
1027
+ unhandledRejections.push(promise);
1028
+ if (reason && typeof reason.stack !== "undefined") {
1029
+ unhandledReasons.push(reason.stack);
1030
+ } else {
1031
+ unhandledReasons.push("(no stack) " + reason);
1032
+ }
1033
+ displayUnhandledReasons();
1034
+ }
1035
+
1036
+ function untrackRejection(promise) {
1037
+ if (!trackUnhandledRejections) {
1038
+ return;
1039
+ }
1040
+
1041
+ var at = array_indexOf(unhandledRejections, promise);
1042
+ if (at !== -1) {
1043
+ unhandledRejections.splice(at, 1);
1044
+ unhandledReasons.splice(at, 1);
1045
+ }
1046
+ }
1047
+
1048
+ Q.resetUnhandledRejections = resetUnhandledRejections;
1049
+
1050
+ Q.getUnhandledReasons = function () {
1051
+ // Make a copy so that consumers can't interfere with our internal state.
1052
+ return unhandledReasons.slice();
1053
+ };
1054
+
1055
+ Q.stopUnhandledRejectionTracking = function () {
1056
+ resetUnhandledRejections();
1057
+ if (typeof process !== "undefined" && process.on) {
1058
+ process.removeListener("exit", logUnhandledReasons);
1059
+ }
1060
+ trackUnhandledRejections = false;
1061
+ };
1062
+
1063
+ resetUnhandledRejections();
1064
+
1065
+ //// END UNHANDLED REJECTION TRACKING
1066
+
1067
+ /**
1068
+ * Constructs a rejected promise.
1069
+ * @param reason value describing the failure
1070
+ */
1071
+ Q.reject = reject;
1072
+ function reject(reason) {
1073
+ var rejection = Promise({
1074
+ "when": function (rejected) {
1075
+ // note that the error has been handled
1076
+ if (rejected) {
1077
+ untrackRejection(this);
1078
+ }
1079
+ return rejected ? rejected(reason) : this;
1080
+ }
1081
+ }, function fallback() {
1082
+ return this;
1083
+ }, function inspect() {
1084
+ return { state: "rejected", reason: reason };
1085
+ });
1086
+
1087
+ // Note that the reason has not been handled.
1088
+ trackRejection(rejection, reason);
1089
+
1090
+ return rejection;
1091
+ }
1092
+
1093
+ /**
1094
+ * Constructs a fulfilled promise for an immediate reference.
1095
+ * @param value immediate reference
1096
+ */
1097
+ Q.fulfill = fulfill;
1098
+ function fulfill(value) {
1099
+ return Promise({
1100
+ "when": function () {
1101
+ return value;
1102
+ },
1103
+ "get": function (name) {
1104
+ return value[name];
1105
+ },
1106
+ "set": function (name, rhs) {
1107
+ value[name] = rhs;
1108
+ },
1109
+ "delete": function (name) {
1110
+ delete value[name];
1111
+ },
1112
+ "post": function (name, args) {
1113
+ // Mark Miller proposes that post with no name should apply a
1114
+ // promised function.
1115
+ if (name === null || name === void 0) {
1116
+ return value.apply(void 0, args);
1117
+ } else {
1118
+ return value[name].apply(value, args);
1119
+ }
1120
+ },
1121
+ "apply": function (thisp, args) {
1122
+ return value.apply(thisp, args);
1123
+ },
1124
+ "keys": function () {
1125
+ return object_keys(value);
1126
+ }
1127
+ }, void 0, function inspect() {
1128
+ return { state: "fulfilled", value: value };
1129
+ });
1130
+ }
1131
+
1132
+ /**
1133
+ * Converts thenables to Q promises.
1134
+ * @param promise thenable promise
1135
+ * @returns a Q promise
1136
+ */
1137
+ function coerce(promise) {
1138
+ var deferred = defer();
1139
+ nextTick(function () {
1140
+ try {
1141
+ promise.then(deferred.resolve, deferred.reject, deferred.notify);
1142
+ } catch (exception) {
1143
+ deferred.reject(exception);
1144
+ }
1145
+ });
1146
+ return deferred.promise;
1147
+ }
1148
+
1149
+ /**
1150
+ * Annotates an object such that it will never be
1151
+ * transferred away from this process over any promise
1152
+ * communication channel.
1153
+ * @param object
1154
+ * @returns promise a wrapping of that object that
1155
+ * additionally responds to the "isDef" message
1156
+ * without a rejection.
1157
+ */
1158
+ Q.master = master;
1159
+ function master(object) {
1160
+ return Promise({
1161
+ "isDef": function () {}
1162
+ }, function fallback(op, args) {
1163
+ return dispatch(object, op, args);
1164
+ }, function () {
1165
+ return Q(object).inspect();
1166
+ });
1167
+ }
1168
+
1169
+ /**
1170
+ * Spreads the values of a promised array of arguments into the
1171
+ * fulfillment callback.
1172
+ * @param fulfilled callback that receives variadic arguments from the
1173
+ * promised array
1174
+ * @param rejected callback that receives the exception if the promise
1175
+ * is rejected.
1176
+ * @returns a promise for the return value or thrown exception of
1177
+ * either callback.
1178
+ */
1179
+ Q.spread = spread;
1180
+ function spread(value, fulfilled, rejected) {
1181
+ return Q(value).spread(fulfilled, rejected);
1182
+ }
1183
+
1184
+ Promise.prototype.spread = function (fulfilled, rejected) {
1185
+ return this.all().then(function (array) {
1186
+ return fulfilled.apply(void 0, array);
1187
+ }, rejected);
1188
+ };
1189
+
1190
+ /**
1191
+ * The async function is a decorator for generator functions, turning
1192
+ * them into asynchronous generators. Although generators are only part
1193
+ * of the newest ECMAScript 6 drafts, this code does not cause syntax
1194
+ * errors in older engines. This code should continue to work and will
1195
+ * in fact improve over time as the language improves.
1196
+ *
1197
+ * ES6 generators are currently part of V8 version 3.19 with the
1198
+ * --harmony-generators runtime flag enabled. SpiderMonkey has had them
1199
+ * for longer, but under an older Python-inspired form. This function
1200
+ * works on both kinds of generators.
1201
+ *
1202
+ * Decorates a generator function such that:
1203
+ * - it may yield promises
1204
+ * - execution will continue when that promise is fulfilled
1205
+ * - the value of the yield expression will be the fulfilled value
1206
+ * - it returns a promise for the return value (when the generator
1207
+ * stops iterating)
1208
+ * - the decorated function returns a promise for the return value
1209
+ * of the generator or the first rejected promise among those
1210
+ * yielded.
1211
+ * - if an error is thrown in the generator, it propagates through
1212
+ * every following yield until it is caught, or until it escapes
1213
+ * the generator function altogether, and is translated into a
1214
+ * rejection for the promise returned by the decorated generator.
1215
+ */
1216
+ Q.async = async;
1217
+ function async(makeGenerator) {
1218
+ return function () {
1219
+ // when verb is "send", arg is a value
1220
+ // when verb is "throw", arg is an exception
1221
+ function continuer(verb, arg) {
1222
+ var result;
1223
+ if (hasES6Generators) {
1224
+ try {
1225
+ result = generator[verb](arg);
1226
+ } catch (exception) {
1227
+ return reject(exception);
1228
+ }
1229
+ if (result.done) {
1230
+ return result.value;
1231
+ } else {
1232
+ return when(result.value, callback, errback);
1233
+ }
1234
+ } else {
1235
+ // FIXME: Remove this case when SM does ES6 generators.
1236
+ try {
1237
+ result = generator[verb](arg);
1238
+ } catch (exception) {
1239
+ if (isStopIteration(exception)) {
1240
+ return exception.value;
1241
+ } else {
1242
+ return reject(exception);
1243
+ }
1244
+ }
1245
+ return when(result, callback, errback);
1246
+ }
1247
+ }
1248
+ var generator = makeGenerator.apply(this, arguments);
1249
+ var callback = continuer.bind(continuer, "next");
1250
+ var errback = continuer.bind(continuer, "throw");
1251
+ return callback();
1252
+ };
1253
+ }
1254
+
1255
+ /**
1256
+ * The spawn function is a small wrapper around async that immediately
1257
+ * calls the generator and also ends the promise chain, so that any
1258
+ * unhandled errors are thrown instead of forwarded to the error
1259
+ * handler. This is useful because it's extremely common to run
1260
+ * generators at the top-level to work with libraries.
1261
+ */
1262
+ Q.spawn = spawn;
1263
+ function spawn(makeGenerator) {
1264
+ Q.done(Q.async(makeGenerator)());
1265
+ }
1266
+
1267
+ // FIXME: Remove this interface once ES6 generators are in SpiderMonkey.
1268
+ /**
1269
+ * Throws a ReturnValue exception to stop an asynchronous generator.
1270
+ *
1271
+ * This interface is a stop-gap measure to support generator return
1272
+ * values in older Firefox/SpiderMonkey. In browsers that support ES6
1273
+ * generators like Chromium 29, just use "return" in your generator
1274
+ * functions.
1275
+ *
1276
+ * @param value the return value for the surrounding generator
1277
+ * @throws ReturnValue exception with the value.
1278
+ * @example
1279
+ * // ES6 style
1280
+ * Q.async(function* () {
1281
+ * var foo = yield getFooPromise();
1282
+ * var bar = yield getBarPromise();
1283
+ * return foo + bar;
1284
+ * })
1285
+ * // Older SpiderMonkey style
1286
+ * Q.async(function () {
1287
+ * var foo = yield getFooPromise();
1288
+ * var bar = yield getBarPromise();
1289
+ * Q.return(foo + bar);
1290
+ * })
1291
+ */
1292
+ Q["return"] = _return;
1293
+ function _return(value) {
1294
+ throw new QReturnValue(value);
1295
+ }
1296
+
1297
+ /**
1298
+ * The promised function decorator ensures that any promise arguments
1299
+ * are settled and passed as values (`this` is also settled and passed
1300
+ * as a value). It will also ensure that the result of a function is
1301
+ * always a promise.
1302
+ *
1303
+ * @example
1304
+ * var add = Q.promised(function (a, b) {
1305
+ * return a + b;
1306
+ * });
1307
+ * add(Q(a), Q(B));
1308
+ *
1309
+ * @param {function} callback The function to decorate
1310
+ * @returns {function} a function that has been decorated.
1311
+ */
1312
+ Q.promised = promised;
1313
+ function promised(callback) {
1314
+ return function () {
1315
+ return spread([this, all(arguments)], function (self, args) {
1316
+ return callback.apply(self, args);
1317
+ });
1318
+ };
1319
+ }
1320
+
1321
+ /**
1322
+ * sends a message to a value in a future turn
1323
+ * @param object* the recipient
1324
+ * @param op the name of the message operation, e.g., "when",
1325
+ * @param args further arguments to be forwarded to the operation
1326
+ * @returns result {Promise} a promise for the result of the operation
1327
+ */
1328
+ Q.dispatch = dispatch;
1329
+ function dispatch(object, op, args) {
1330
+ return Q(object).dispatch(op, args);
1331
+ }
1332
+
1333
+ Promise.prototype.dispatch = function (op, args) {
1334
+ var self = this;
1335
+ var deferred = defer();
1336
+ nextTick(function () {
1337
+ self.promiseDispatch(deferred.resolve, op, args);
1338
+ });
1339
+ return deferred.promise;
1340
+ };
1341
+
1342
+ /**
1343
+ * Gets the value of a property in a future turn.
1344
+ * @param object promise or immediate reference for target object
1345
+ * @param name name of property to get
1346
+ * @return promise for the property value
1347
+ */
1348
+ Q.get = function (object, key) {
1349
+ return Q(object).dispatch("get", [key]);
1350
+ };
1351
+
1352
+ Promise.prototype.get = function (key) {
1353
+ return this.dispatch("get", [key]);
1354
+ };
1355
+
1356
+ /**
1357
+ * Sets the value of a property in a future turn.
1358
+ * @param object promise or immediate reference for object object
1359
+ * @param name name of property to set
1360
+ * @param value new value of property
1361
+ * @return promise for the return value
1362
+ */
1363
+ Q.set = function (object, key, value) {
1364
+ return Q(object).dispatch("set", [key, value]);
1365
+ };
1366
+
1367
+ Promise.prototype.set = function (key, value) {
1368
+ return this.dispatch("set", [key, value]);
1369
+ };
1370
+
1371
+ /**
1372
+ * Deletes a property in a future turn.
1373
+ * @param object promise or immediate reference for target object
1374
+ * @param name name of property to delete
1375
+ * @return promise for the return value
1376
+ */
1377
+ Q.del = // XXX legacy
1378
+ Q["delete"] = function (object, key) {
1379
+ return Q(object).dispatch("delete", [key]);
1380
+ };
1381
+
1382
+ Promise.prototype.del = // XXX legacy
1383
+ Promise.prototype["delete"] = function (key) {
1384
+ return this.dispatch("delete", [key]);
1385
+ };
1386
+
1387
+ /**
1388
+ * Invokes a method in a future turn.
1389
+ * @param object promise or immediate reference for target object
1390
+ * @param name name of method to invoke
1391
+ * @param value a value to post, typically an array of
1392
+ * invocation arguments for promises that
1393
+ * are ultimately backed with `resolve` values,
1394
+ * as opposed to those backed with URLs
1395
+ * wherein the posted value can be any
1396
+ * JSON serializable object.
1397
+ * @return promise for the return value
1398
+ */
1399
+ // bound locally because it is used by other methods
1400
+ Q.mapply = // XXX As proposed by "Redsandro"
1401
+ Q.post = function (object, name, args) {
1402
+ return Q(object).dispatch("post", [name, args]);
1403
+ };
1404
+
1405
+ Promise.prototype.mapply = // XXX As proposed by "Redsandro"
1406
+ Promise.prototype.post = function (name, args) {
1407
+ return this.dispatch("post", [name, args]);
1408
+ };
1409
+
1410
+ /**
1411
+ * Invokes a method in a future turn.
1412
+ * @param object promise or immediate reference for target object
1413
+ * @param name name of method to invoke
1414
+ * @param ...args array of invocation arguments
1415
+ * @return promise for the return value
1416
+ */
1417
+ Q.send = // XXX Mark Miller's proposed parlance
1418
+ Q.mcall = // XXX As proposed by "Redsandro"
1419
+ Q.invoke = function (object, name /*...args*/) {
1420
+ return Q(object).dispatch("post", [name, array_slice(arguments, 2)]);
1421
+ };
1422
+
1423
+ Promise.prototype.send = // XXX Mark Miller's proposed parlance
1424
+ Promise.prototype.mcall = // XXX As proposed by "Redsandro"
1425
+ Promise.prototype.invoke = function (name /*...args*/) {
1426
+ return this.dispatch("post", [name, array_slice(arguments, 1)]);
1427
+ };
1428
+
1429
+ /**
1430
+ * Applies the promised function in a future turn.
1431
+ * @param object promise or immediate reference for target function
1432
+ * @param args array of application arguments
1433
+ */
1434
+ Q.fapply = function (object, args) {
1435
+ return Q(object).dispatch("apply", [void 0, args]);
1436
+ };
1437
+
1438
+ Promise.prototype.fapply = function (args) {
1439
+ return this.dispatch("apply", [void 0, args]);
1440
+ };
1441
+
1442
+ /**
1443
+ * Calls the promised function in a future turn.
1444
+ * @param object promise or immediate reference for target function
1445
+ * @param ...args array of application arguments
1446
+ */
1447
+ Q["try"] =
1448
+ Q.fcall = function (object /* ...args*/) {
1449
+ return Q(object).dispatch("apply", [void 0, array_slice(arguments, 1)]);
1450
+ };
1451
+
1452
+ Promise.prototype.fcall = function (/*...args*/) {
1453
+ return this.dispatch("apply", [void 0, array_slice(arguments)]);
1454
+ };
1455
+
1456
+ /**
1457
+ * Binds the promised function, transforming return values into a fulfilled
1458
+ * promise and thrown errors into a rejected one.
1459
+ * @param object promise or immediate reference for target function
1460
+ * @param ...args array of application arguments
1461
+ */
1462
+ Q.fbind = function (object /*...args*/) {
1463
+ var promise = Q(object);
1464
+ var args = array_slice(arguments, 1);
1465
+ return function fbound() {
1466
+ return promise.dispatch("apply", [
1467
+ this,
1468
+ args.concat(array_slice(arguments))
1469
+ ]);
1470
+ };
1471
+ };
1472
+ Promise.prototype.fbind = function (/*...args*/) {
1473
+ var promise = this;
1474
+ var args = array_slice(arguments);
1475
+ return function fbound() {
1476
+ return promise.dispatch("apply", [
1477
+ this,
1478
+ args.concat(array_slice(arguments))
1479
+ ]);
1480
+ };
1481
+ };
1482
+
1483
+ /**
1484
+ * Requests the names of the owned properties of a promised
1485
+ * object in a future turn.
1486
+ * @param object promise or immediate reference for target object
1487
+ * @return promise for the keys of the eventually settled object
1488
+ */
1489
+ Q.keys = function (object) {
1490
+ return Q(object).dispatch("keys", []);
1491
+ };
1492
+
1493
+ Promise.prototype.keys = function () {
1494
+ return this.dispatch("keys", []);
1495
+ };
1496
+
1497
+ /**
1498
+ * Turns an array of promises into a promise for an array. If any of
1499
+ * the promises gets rejected, the whole array is rejected immediately.
1500
+ * @param {Array*} an array (or promise for an array) of values (or
1501
+ * promises for values)
1502
+ * @returns a promise for an array of the corresponding values
1503
+ */
1504
+ // By Mark Miller
1505
+ // http://wiki.ecmascript.org/doku.php?id=strawman:concurrency&rev=1308776521#allfulfilled
1506
+ Q.all = all;
1507
+ function all(promises) {
1508
+ return when(promises, function (promises) {
1509
+ var countDown = 0;
1510
+ var deferred = defer();
1511
+ array_reduce(promises, function (undefined, promise, index) {
1512
+ var snapshot;
1513
+ if (
1514
+ isPromise(promise) &&
1515
+ (snapshot = promise.inspect()).state === "fulfilled"
1516
+ ) {
1517
+ promises[index] = snapshot.value;
1518
+ } else {
1519
+ ++countDown;
1520
+ when(
1521
+ promise,
1522
+ function (value) {
1523
+ promises[index] = value;
1524
+ if (--countDown === 0) {
1525
+ deferred.resolve(promises);
1526
+ }
1527
+ },
1528
+ deferred.reject,
1529
+ function (progress) {
1530
+ deferred.notify({ index: index, value: progress });
1531
+ }
1532
+ );
1533
+ }
1534
+ }, void 0);
1535
+ if (countDown === 0) {
1536
+ deferred.resolve(promises);
1537
+ }
1538
+ return deferred.promise;
1539
+ });
1540
+ }
1541
+
1542
+ Promise.prototype.all = function () {
1543
+ return all(this);
1544
+ };
1545
+
1546
+ /**
1547
+ * Waits for all promises to be settled, either fulfilled or
1548
+ * rejected. This is distinct from `all` since that would stop
1549
+ * waiting at the first rejection. The promise returned by
1550
+ * `allResolved` will never be rejected.
1551
+ * @param promises a promise for an array (or an array) of promises
1552
+ * (or values)
1553
+ * @return a promise for an array of promises
1554
+ */
1555
+ Q.allResolved = deprecate(allResolved, "allResolved", "allSettled");
1556
+ function allResolved(promises) {
1557
+ return when(promises, function (promises) {
1558
+ promises = array_map(promises, Q);
1559
+ return when(all(array_map(promises, function (promise) {
1560
+ return when(promise, noop, noop);
1561
+ })), function () {
1562
+ return promises;
1563
+ });
1564
+ });
1565
+ }
1566
+
1567
+ Promise.prototype.allResolved = function () {
1568
+ return allResolved(this);
1569
+ };
1570
+
1571
+ /**
1572
+ * @see Promise#allSettled
1573
+ */
1574
+ Q.allSettled = allSettled;
1575
+ function allSettled(promises) {
1576
+ return Q(promises).allSettled();
1577
+ }
1578
+
1579
+ /**
1580
+ * Turns an array of promises into a promise for an array of their states (as
1581
+ * returned by `inspect`) when they have all settled.
1582
+ * @param {Array[Any*]} values an array (or promise for an array) of values (or
1583
+ * promises for values)
1584
+ * @returns {Array[State]} an array of states for the respective values.
1585
+ */
1586
+ Promise.prototype.allSettled = function () {
1587
+ return this.then(function (promises) {
1588
+ return all(array_map(promises, function (promise) {
1589
+ promise = Q(promise);
1590
+ function regardless() {
1591
+ return promise.inspect();
1592
+ }
1593
+ return promise.then(regardless, regardless);
1594
+ }));
1595
+ });
1596
+ };
1597
+
1598
+ /**
1599
+ * Captures the failure of a promise, giving an oportunity to recover
1600
+ * with a callback. If the given promise is fulfilled, the returned
1601
+ * promise is fulfilled.
1602
+ * @param {Any*} promise for something
1603
+ * @param {Function} callback to fulfill the returned promise if the
1604
+ * given promise is rejected
1605
+ * @returns a promise for the return value of the callback
1606
+ */
1607
+ Q.fail = // XXX legacy
1608
+ Q["catch"] = function (object, rejected) {
1609
+ return Q(object).then(void 0, rejected);
1610
+ };
1611
+
1612
+ Promise.prototype.fail = // XXX legacy
1613
+ Promise.prototype["catch"] = function (rejected) {
1614
+ return this.then(void 0, rejected);
1615
+ };
1616
+
1617
+ /**
1618
+ * Attaches a listener that can respond to progress notifications from a
1619
+ * promise's originating deferred. This listener receives the exact arguments
1620
+ * passed to ``deferred.notify``.
1621
+ * @param {Any*} promise for something
1622
+ * @param {Function} callback to receive any progress notifications
1623
+ * @returns the given promise, unchanged
1624
+ */
1625
+ Q.progress = progress;
1626
+ function progress(object, progressed) {
1627
+ return Q(object).then(void 0, void 0, progressed);
1628
+ }
1629
+
1630
+ Promise.prototype.progress = function (progressed) {
1631
+ return this.then(void 0, void 0, progressed);
1632
+ };
1633
+
1634
+ /**
1635
+ * Provides an opportunity to observe the settling of a promise,
1636
+ * regardless of whether the promise is fulfilled or rejected. Forwards
1637
+ * the resolution to the returned promise when the callback is done.
1638
+ * The callback can return a promise to defer completion.
1639
+ * @param {Any*} promise
1640
+ * @param {Function} callback to observe the resolution of the given
1641
+ * promise, takes no arguments.
1642
+ * @returns a promise for the resolution of the given promise when
1643
+ * ``fin`` is done.
1644
+ */
1645
+ Q.fin = // XXX legacy
1646
+ Q["finally"] = function (object, callback) {
1647
+ return Q(object)["finally"](callback);
1648
+ };
1649
+
1650
+ Promise.prototype.fin = // XXX legacy
1651
+ Promise.prototype["finally"] = function (callback) {
1652
+ callback = Q(callback);
1653
+ return this.then(function (value) {
1654
+ return callback.fcall().then(function () {
1655
+ return value;
1656
+ });
1657
+ }, function (reason) {
1658
+ // TODO attempt to recycle the rejection with "this".
1659
+ return callback.fcall().then(function () {
1660
+ throw reason;
1661
+ });
1662
+ });
1663
+ };
1664
+
1665
+ /**
1666
+ * Terminates a chain of promises, forcing rejections to be
1667
+ * thrown as exceptions.
1668
+ * @param {Any*} promise at the end of a chain of promises
1669
+ * @returns nothing
1670
+ */
1671
+ Q.done = function (object, fulfilled, rejected, progress) {
1672
+ return Q(object).done(fulfilled, rejected, progress);
1673
+ };
1674
+
1675
+ Promise.prototype.done = function (fulfilled, rejected, progress) {
1676
+ var onUnhandledError = function (error) {
1677
+ // forward to a future turn so that ``when``
1678
+ // does not catch it and turn it into a rejection.
1679
+ nextTick(function () {
1680
+ makeStackTraceLong(error, promise);
1681
+ if (Q.onerror) {
1682
+ Q.onerror(error);
1683
+ } else {
1684
+ throw error;
1685
+ }
1686
+ });
1687
+ };
1688
+
1689
+ // Avoid unnecessary `nextTick`ing via an unnecessary `when`.
1690
+ var promise = fulfilled || rejected || progress ?
1691
+ this.then(fulfilled, rejected, progress) :
1692
+ this;
1693
+
1694
+ if (typeof process === "object" && process && process.domain) {
1695
+ onUnhandledError = process.domain.bind(onUnhandledError);
1696
+ }
1697
+
1698
+ promise.then(void 0, onUnhandledError);
1699
+ };
1700
+
1701
+ /**
1702
+ * Causes a promise to be rejected if it does not get fulfilled before
1703
+ * some milliseconds time out.
1704
+ * @param {Any*} promise
1705
+ * @param {Number} milliseconds timeout
1706
+ * @param {String} custom error message (optional)
1707
+ * @returns a promise for the resolution of the given promise if it is
1708
+ * fulfilled before the timeout, otherwise rejected.
1709
+ */
1710
+ Q.timeout = function (object, ms, message) {
1711
+ return Q(object).timeout(ms, message);
1712
+ };
1713
+
1714
+ Promise.prototype.timeout = function (ms, message) {
1715
+ var deferred = defer();
1716
+ var timeoutId = setTimeout(function () {
1717
+ deferred.reject(new Error(message || "Timed out after " + ms + " ms"));
1718
+ }, ms);
1719
+
1720
+ this.then(function (value) {
1721
+ clearTimeout(timeoutId);
1722
+ deferred.resolve(value);
1723
+ }, function (exception) {
1724
+ clearTimeout(timeoutId);
1725
+ deferred.reject(exception);
1726
+ }, deferred.notify);
1727
+
1728
+ return deferred.promise;
1729
+ };
1730
+
1731
+ /**
1732
+ * Returns a promise for the given value (or promised value), some
1733
+ * milliseconds after it resolved. Passes rejections immediately.
1734
+ * @param {Any*} promise
1735
+ * @param {Number} milliseconds
1736
+ * @returns a promise for the resolution of the given promise after milliseconds
1737
+ * time has elapsed since the resolution of the given promise.
1738
+ * If the given promise rejects, that is passed immediately.
1739
+ */
1740
+ Q.delay = function (object, timeout) {
1741
+ if (timeout === void 0) {
1742
+ timeout = object;
1743
+ object = void 0;
1744
+ }
1745
+ return Q(object).delay(timeout);
1746
+ };
1747
+
1748
+ Promise.prototype.delay = function (timeout) {
1749
+ return this.then(function (value) {
1750
+ var deferred = defer();
1751
+ setTimeout(function () {
1752
+ deferred.resolve(value);
1753
+ }, timeout);
1754
+ return deferred.promise;
1755
+ });
1756
+ };
1757
+
1758
+ /**
1759
+ * Passes a continuation to a Node function, which is called with the given
1760
+ * arguments provided as an array, and returns a promise.
1761
+ *
1762
+ * Q.nfapply(FS.readFile, [__filename])
1763
+ * .then(function (content) {
1764
+ * })
1765
+ *
1766
+ */
1767
+ Q.nfapply = function (callback, args) {
1768
+ return Q(callback).nfapply(args);
1769
+ };
1770
+
1771
+ Promise.prototype.nfapply = function (args) {
1772
+ var deferred = defer();
1773
+ var nodeArgs = array_slice(args);
1774
+ nodeArgs.push(deferred.makeNodeResolver());
1775
+ this.fapply(nodeArgs).fail(deferred.reject);
1776
+ return deferred.promise;
1777
+ };
1778
+
1779
+ /**
1780
+ * Passes a continuation to a Node function, which is called with the given
1781
+ * arguments provided individually, and returns a promise.
1782
+ * @example
1783
+ * Q.nfcall(FS.readFile, __filename)
1784
+ * .then(function (content) {
1785
+ * })
1786
+ *
1787
+ */
1788
+ Q.nfcall = function (callback /*...args*/) {
1789
+ var args = array_slice(arguments, 1);
1790
+ return Q(callback).nfapply(args);
1791
+ };
1792
+
1793
+ Promise.prototype.nfcall = function (/*...args*/) {
1794
+ var nodeArgs = array_slice(arguments);
1795
+ var deferred = defer();
1796
+ nodeArgs.push(deferred.makeNodeResolver());
1797
+ this.fapply(nodeArgs).fail(deferred.reject);
1798
+ return deferred.promise;
1799
+ };
1800
+
1801
+ /**
1802
+ * Wraps a NodeJS continuation passing function and returns an equivalent
1803
+ * version that returns a promise.
1804
+ * @example
1805
+ * Q.nfbind(FS.readFile, __filename)("utf-8")
1806
+ * .then(console.log)
1807
+ * .done()
1808
+ */
1809
+ Q.nfbind =
1810
+ Q.denodeify = function (callback /*...args*/) {
1811
+ var baseArgs = array_slice(arguments, 1);
1812
+ return function () {
1813
+ var nodeArgs = baseArgs.concat(array_slice(arguments));
1814
+ var deferred = defer();
1815
+ nodeArgs.push(deferred.makeNodeResolver());
1816
+ Q(callback).fapply(nodeArgs).fail(deferred.reject);
1817
+ return deferred.promise;
1818
+ };
1819
+ };
1820
+
1821
+ Promise.prototype.nfbind =
1822
+ Promise.prototype.denodeify = function (/*...args*/) {
1823
+ var args = array_slice(arguments);
1824
+ args.unshift(this);
1825
+ return Q.denodeify.apply(void 0, args);
1826
+ };
1827
+
1828
+ Q.nbind = function (callback, thisp /*...args*/) {
1829
+ var baseArgs = array_slice(arguments, 2);
1830
+ return function () {
1831
+ var nodeArgs = baseArgs.concat(array_slice(arguments));
1832
+ var deferred = defer();
1833
+ nodeArgs.push(deferred.makeNodeResolver());
1834
+ function bound() {
1835
+ return callback.apply(thisp, arguments);
1836
+ }
1837
+ Q(bound).fapply(nodeArgs).fail(deferred.reject);
1838
+ return deferred.promise;
1839
+ };
1840
+ };
1841
+
1842
+ Promise.prototype.nbind = function (/*thisp, ...args*/) {
1843
+ var args = array_slice(arguments, 0);
1844
+ args.unshift(this);
1845
+ return Q.nbind.apply(void 0, args);
1846
+ };
1847
+
1848
+ /**
1849
+ * Calls a method of a Node-style object that accepts a Node-style
1850
+ * callback with a given array of arguments, plus a provided callback.
1851
+ * @param object an object that has the named method
1852
+ * @param {String} name name of the method of object
1853
+ * @param {Array} args arguments to pass to the method; the callback
1854
+ * will be provided by Q and appended to these arguments.
1855
+ * @returns a promise for the value or error
1856
+ */
1857
+ Q.nmapply = // XXX As proposed by "Redsandro"
1858
+ Q.npost = function (object, name, args) {
1859
+ return Q(object).npost(name, args);
1860
+ };
1861
+
1862
+ Promise.prototype.nmapply = // XXX As proposed by "Redsandro"
1863
+ Promise.prototype.npost = function (name, args) {
1864
+ var nodeArgs = array_slice(args || []);
1865
+ var deferred = defer();
1866
+ nodeArgs.push(deferred.makeNodeResolver());
1867
+ this.dispatch("post", [name, nodeArgs]).fail(deferred.reject);
1868
+ return deferred.promise;
1869
+ };
1870
+
1871
+ /**
1872
+ * Calls a method of a Node-style object that accepts a Node-style
1873
+ * callback, forwarding the given variadic arguments, plus a provided
1874
+ * callback argument.
1875
+ * @param object an object that has the named method
1876
+ * @param {String} name name of the method of object
1877
+ * @param ...args arguments to pass to the method; the callback will
1878
+ * be provided by Q and appended to these arguments.
1879
+ * @returns a promise for the value or error
1880
+ */
1881
+ Q.nsend = // XXX Based on Mark Miller's proposed "send"
1882
+ Q.nmcall = // XXX Based on "Redsandro's" proposal
1883
+ Q.ninvoke = function (object, name /*...args*/) {
1884
+ var nodeArgs = array_slice(arguments, 2);
1885
+ var deferred = defer();
1886
+ nodeArgs.push(deferred.makeNodeResolver());
1887
+ Q(object).dispatch("post", [name, nodeArgs]).fail(deferred.reject);
1888
+ return deferred.promise;
1889
+ };
1890
+
1891
+ Promise.prototype.nsend = // XXX Based on Mark Miller's proposed "send"
1892
+ Promise.prototype.nmcall = // XXX Based on "Redsandro's" proposal
1893
+ Promise.prototype.ninvoke = function (name /*...args*/) {
1894
+ var nodeArgs = array_slice(arguments, 1);
1895
+ var deferred = defer();
1896
+ nodeArgs.push(deferred.makeNodeResolver());
1897
+ this.dispatch("post", [name, nodeArgs]).fail(deferred.reject);
1898
+ return deferred.promise;
1899
+ };
1900
+
1901
+ /**
1902
+ * If a function would like to support both Node continuation-passing-style and
1903
+ * promise-returning-style, it can end its internal promise chain with
1904
+ * `nodeify(nodeback)`, forwarding the optional nodeback argument. If the user
1905
+ * elects to use a nodeback, the result will be sent there. If they do not
1906
+ * pass a nodeback, they will receive the result promise.
1907
+ * @param object a result (or a promise for a result)
1908
+ * @param {Function} nodeback a Node.js-style callback
1909
+ * @returns either the promise or nothing
1910
+ */
1911
+ Q.nodeify = nodeify;
1912
+ function nodeify(object, nodeback) {
1913
+ return Q(object).nodeify(nodeback);
1914
+ }
1915
+
1916
+ Promise.prototype.nodeify = function (nodeback) {
1917
+ if (nodeback) {
1918
+ this.then(function (value) {
1919
+ nextTick(function () {
1920
+ nodeback(null, value);
1921
+ });
1922
+ }, function (error) {
1923
+ nextTick(function () {
1924
+ nodeback(error);
1925
+ });
1926
+ });
1927
+ } else {
1928
+ return this;
1929
+ }
1930
+ };
1931
+
1932
+ // All code before this point will be filtered from stack traces.
1933
+ var qEndingLine = captureLine();
1934
+
1935
+ return Q;
1936
+
1937
+ });