react-router-rails 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/README.md +34 -0
- data/lib/react/router/rails.rb +2 -0
- data/lib/react/router/rails/engine.rb +8 -0
- data/lib/react/router/rails/version.rb +7 -0
- data/vendor/assets/javascripts/react_router.js +3891 -0
- data/vendor/assets/javascripts/react_router.min.js +2 -0
- metadata +93 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a68409d4877d9e9a1fbd0c91f318a273721b4edb
|
4
|
+
data.tar.gz: 6adc1694dad4a5d3b1a252928b3a675718d57eda
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8a73f7cc3f58d6d6a969eff52b0062ea29e3dc64eac9b9198c6b186906358125b8fb92f0e41c765e929ec08ff541b87055244e74b9d037596525768b518ea597
|
7
|
+
data.tar.gz: 004890fee3d875a49989ffa640df4530e2aa12e00a7192d4666c24695e75b7a6e0c633a568ad9d3e22a97cfd9d46ed7431a9918f59f993ad23c1c46b26b68f07
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Mario Peixoto
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# react-router-rails
|
2
|
+
|
3
|
+
[React Router](https://github.com/rackt/react-router/) for Rails asset pipeline
|
4
|
+
|
5
|
+
- React Router version: [0.11.6](https://github.com/rackt/react-router/tree/v0.11.6)
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
1. Add to your `Gemfile` and install with bundler:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'react-router-rails', '~>0.11.6'
|
13
|
+
```
|
14
|
+
|
15
|
+
```bash
|
16
|
+
bundle install
|
17
|
+
|
18
|
+
2. Require the modified React-Router javascript file in `app/assets/javascripts/application.js`:
|
19
|
+
|
20
|
+
```js
|
21
|
+
//= require react_router
|
22
|
+
```
|
23
|
+
|
24
|
+
Or in `app/assets/javascripts/application.js.coffee`:
|
25
|
+
|
26
|
+
```coffeescript
|
27
|
+
#= require react_router
|
28
|
+
```
|
29
|
+
|
30
|
+
## Acknowledgements
|
31
|
+
|
32
|
+
[React Router](https://github.com/rackt/react-router/) licensed under the [MIT license](https://github.com/rackt/react-router/blob/master/LICENSE)
|
33
|
+
|
34
|
+
Copyright [Mario Peixoto](https://github.com/mariopeixoto), released under the [MIT license](https://github.com/mariopeixoto/react-router-rails/LICENSE).
|
@@ -0,0 +1,3891 @@
|
|
1
|
+
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.ReactRouter=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
|
2
|
+
/**
|
3
|
+
* Actions that modify the URL.
|
4
|
+
*/
|
5
|
+
var LocationActions = {
|
6
|
+
|
7
|
+
/**
|
8
|
+
* Indicates a new location is being pushed to the history stack.
|
9
|
+
*/
|
10
|
+
PUSH: 'push',
|
11
|
+
|
12
|
+
/**
|
13
|
+
* Indicates the current location should be replaced.
|
14
|
+
*/
|
15
|
+
REPLACE: 'replace',
|
16
|
+
|
17
|
+
/**
|
18
|
+
* Indicates the most recent entry should be removed from the history stack.
|
19
|
+
*/
|
20
|
+
POP: 'pop'
|
21
|
+
|
22
|
+
};
|
23
|
+
|
24
|
+
module.exports = LocationActions;
|
25
|
+
|
26
|
+
},{}],2:[function(_dereq_,module,exports){
|
27
|
+
var LocationActions = _dereq_('../actions/LocationActions');
|
28
|
+
|
29
|
+
/**
|
30
|
+
* A scroll behavior that attempts to imitate the default behavior
|
31
|
+
* of modern browsers.
|
32
|
+
*/
|
33
|
+
var ImitateBrowserBehavior = {
|
34
|
+
|
35
|
+
updateScrollPosition: function (position, actionType) {
|
36
|
+
switch (actionType) {
|
37
|
+
case LocationActions.PUSH:
|
38
|
+
case LocationActions.REPLACE:
|
39
|
+
window.scrollTo(0, 0);
|
40
|
+
break;
|
41
|
+
case LocationActions.POP:
|
42
|
+
if (position) {
|
43
|
+
window.scrollTo(position.x, position.y);
|
44
|
+
} else {
|
45
|
+
window.scrollTo(0, 0);
|
46
|
+
}
|
47
|
+
break;
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
};
|
52
|
+
|
53
|
+
module.exports = ImitateBrowserBehavior;
|
54
|
+
|
55
|
+
},{"../actions/LocationActions":1}],3:[function(_dereq_,module,exports){
|
56
|
+
/**
|
57
|
+
* A scroll behavior that always scrolls to the top of the page
|
58
|
+
* after a transition.
|
59
|
+
*/
|
60
|
+
var ScrollToTopBehavior = {
|
61
|
+
|
62
|
+
updateScrollPosition: function () {
|
63
|
+
window.scrollTo(0, 0);
|
64
|
+
}
|
65
|
+
|
66
|
+
};
|
67
|
+
|
68
|
+
module.exports = ScrollToTopBehavior;
|
69
|
+
|
70
|
+
},{}],4:[function(_dereq_,module,exports){
|
71
|
+
var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
|
72
|
+
var FakeNode = _dereq_('../mixins/FakeNode');
|
73
|
+
var PropTypes = _dereq_('../utils/PropTypes');
|
74
|
+
|
75
|
+
/**
|
76
|
+
* A <DefaultRoute> component is a special kind of <Route> that
|
77
|
+
* renders when its parent matches but none of its siblings do.
|
78
|
+
* Only one such route may be used at any given level in the
|
79
|
+
* route hierarchy.
|
80
|
+
*/
|
81
|
+
var DefaultRoute = React.createClass({
|
82
|
+
|
83
|
+
displayName: 'DefaultRoute',
|
84
|
+
|
85
|
+
mixins: [ FakeNode ],
|
86
|
+
|
87
|
+
propTypes: {
|
88
|
+
name: React.PropTypes.string,
|
89
|
+
path: PropTypes.falsy,
|
90
|
+
handler: React.PropTypes.func.isRequired
|
91
|
+
}
|
92
|
+
|
93
|
+
});
|
94
|
+
|
95
|
+
module.exports = DefaultRoute;
|
96
|
+
|
97
|
+
},{"../mixins/FakeNode":14,"../utils/PropTypes":25}],5:[function(_dereq_,module,exports){
|
98
|
+
var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
|
99
|
+
var classSet = _dereq_('react/lib/cx');
|
100
|
+
var assign = _dereq_('react/lib/Object.assign');
|
101
|
+
var Navigation = _dereq_('../mixins/Navigation');
|
102
|
+
var State = _dereq_('../mixins/State');
|
103
|
+
|
104
|
+
function isLeftClickEvent(event) {
|
105
|
+
return event.button === 0;
|
106
|
+
}
|
107
|
+
|
108
|
+
function isModifiedEvent(event) {
|
109
|
+
return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
|
110
|
+
}
|
111
|
+
|
112
|
+
/**
|
113
|
+
* <Link> components are used to create an <a> element that links to a route.
|
114
|
+
* When that route is active, the link gets an "active" class name (or the
|
115
|
+
* value of its `activeClassName` prop).
|
116
|
+
*
|
117
|
+
* For example, assuming you have the following route:
|
118
|
+
*
|
119
|
+
* <Route name="showPost" path="/posts/:postID" handler={Post}/>
|
120
|
+
*
|
121
|
+
* You could use the following component to link to that route:
|
122
|
+
*
|
123
|
+
* <Link to="showPost" params={{ postID: "123" }} />
|
124
|
+
*
|
125
|
+
* In addition to params, links may pass along query string parameters
|
126
|
+
* using the `query` prop.
|
127
|
+
*
|
128
|
+
* <Link to="showPost" params={{ postID: "123" }} query={{ show:true }}/>
|
129
|
+
*/
|
130
|
+
var Link = React.createClass({
|
131
|
+
|
132
|
+
displayName: 'Link',
|
133
|
+
|
134
|
+
mixins: [ Navigation, State ],
|
135
|
+
|
136
|
+
propTypes: {
|
137
|
+
activeClassName: React.PropTypes.string.isRequired,
|
138
|
+
to: React.PropTypes.string.isRequired,
|
139
|
+
params: React.PropTypes.object,
|
140
|
+
query: React.PropTypes.object,
|
141
|
+
onClick: React.PropTypes.func
|
142
|
+
},
|
143
|
+
|
144
|
+
getDefaultProps: function () {
|
145
|
+
return {
|
146
|
+
activeClassName: 'active'
|
147
|
+
};
|
148
|
+
},
|
149
|
+
|
150
|
+
handleClick: function (event) {
|
151
|
+
var allowTransition = true;
|
152
|
+
var clickResult;
|
153
|
+
|
154
|
+
if (this.props.onClick)
|
155
|
+
clickResult = this.props.onClick(event);
|
156
|
+
|
157
|
+
if (isModifiedEvent(event) || !isLeftClickEvent(event))
|
158
|
+
return;
|
159
|
+
|
160
|
+
if (clickResult === false || event.defaultPrevented === true)
|
161
|
+
allowTransition = false;
|
162
|
+
|
163
|
+
event.preventDefault();
|
164
|
+
|
165
|
+
if (allowTransition)
|
166
|
+
this.transitionTo(this.props.to, this.props.params, this.props.query);
|
167
|
+
},
|
168
|
+
|
169
|
+
/**
|
170
|
+
* Returns the value of the "href" attribute to use on the DOM element.
|
171
|
+
*/
|
172
|
+
getHref: function () {
|
173
|
+
return this.makeHref(this.props.to, this.props.params, this.props.query);
|
174
|
+
},
|
175
|
+
|
176
|
+
/**
|
177
|
+
* Returns the value of the "class" attribute to use on the DOM element, which contains
|
178
|
+
* the value of the activeClassName property when this <Link> is active.
|
179
|
+
*/
|
180
|
+
getClassName: function () {
|
181
|
+
var classNames = {};
|
182
|
+
|
183
|
+
if (this.props.className)
|
184
|
+
classNames[this.props.className] = true;
|
185
|
+
|
186
|
+
if (this.isActive(this.props.to, this.props.params, this.props.query))
|
187
|
+
classNames[this.props.activeClassName] = true;
|
188
|
+
|
189
|
+
return classSet(classNames);
|
190
|
+
},
|
191
|
+
|
192
|
+
render: function () {
|
193
|
+
var props = assign({}, this.props, {
|
194
|
+
href: this.getHref(),
|
195
|
+
className: this.getClassName(),
|
196
|
+
onClick: this.handleClick
|
197
|
+
});
|
198
|
+
|
199
|
+
return React.DOM.a(props, this.props.children);
|
200
|
+
}
|
201
|
+
|
202
|
+
});
|
203
|
+
|
204
|
+
module.exports = Link;
|
205
|
+
|
206
|
+
},{"../mixins/Navigation":15,"../mixins/State":19,"react/lib/Object.assign":40,"react/lib/cx":41}],6:[function(_dereq_,module,exports){
|
207
|
+
var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
|
208
|
+
var FakeNode = _dereq_('../mixins/FakeNode');
|
209
|
+
var PropTypes = _dereq_('../utils/PropTypes');
|
210
|
+
|
211
|
+
/**
|
212
|
+
* A <NotFoundRoute> is a special kind of <Route> that
|
213
|
+
* renders when the beginning of its parent's path matches
|
214
|
+
* but none of its siblings do, including any <DefaultRoute>.
|
215
|
+
* Only one such route may be used at any given level in the
|
216
|
+
* route hierarchy.
|
217
|
+
*/
|
218
|
+
var NotFoundRoute = React.createClass({
|
219
|
+
|
220
|
+
displayName: 'NotFoundRoute',
|
221
|
+
|
222
|
+
mixins: [ FakeNode ],
|
223
|
+
|
224
|
+
propTypes: {
|
225
|
+
name: React.PropTypes.string,
|
226
|
+
path: PropTypes.falsy,
|
227
|
+
handler: React.PropTypes.func.isRequired
|
228
|
+
}
|
229
|
+
|
230
|
+
});
|
231
|
+
|
232
|
+
module.exports = NotFoundRoute;
|
233
|
+
|
234
|
+
},{"../mixins/FakeNode":14,"../utils/PropTypes":25}],7:[function(_dereq_,module,exports){
|
235
|
+
var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
|
236
|
+
var FakeNode = _dereq_('../mixins/FakeNode');
|
237
|
+
var PropTypes = _dereq_('../utils/PropTypes');
|
238
|
+
|
239
|
+
/**
|
240
|
+
* A <Redirect> component is a special kind of <Route> that always
|
241
|
+
* redirects to another route when it matches.
|
242
|
+
*/
|
243
|
+
var Redirect = React.createClass({
|
244
|
+
|
245
|
+
displayName: 'Redirect',
|
246
|
+
|
247
|
+
mixins: [ FakeNode ],
|
248
|
+
|
249
|
+
propTypes: {
|
250
|
+
path: React.PropTypes.string,
|
251
|
+
from: React.PropTypes.string, // Alias for path.
|
252
|
+
to: React.PropTypes.string,
|
253
|
+
handler: PropTypes.falsy
|
254
|
+
}
|
255
|
+
|
256
|
+
});
|
257
|
+
|
258
|
+
module.exports = Redirect;
|
259
|
+
|
260
|
+
},{"../mixins/FakeNode":14,"../utils/PropTypes":25}],8:[function(_dereq_,module,exports){
|
261
|
+
var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
|
262
|
+
var FakeNode = _dereq_('../mixins/FakeNode');
|
263
|
+
|
264
|
+
/**
|
265
|
+
* <Route> components specify components that are rendered to the page when the
|
266
|
+
* URL matches a given pattern.
|
267
|
+
*
|
268
|
+
* Routes are arranged in a nested tree structure. When a new URL is requested,
|
269
|
+
* the tree is searched depth-first to find a route whose path matches the URL.
|
270
|
+
* When one is found, all routes in the tree that lead to it are considered
|
271
|
+
* "active" and their components are rendered into the DOM, nested in the same
|
272
|
+
* order as they are in the tree.
|
273
|
+
*
|
274
|
+
* The preferred way to configure a router is using JSX. The XML-like syntax is
|
275
|
+
* a great way to visualize how routes are laid out in an application.
|
276
|
+
*
|
277
|
+
* var routes = [
|
278
|
+
* <Route handler={App}>
|
279
|
+
* <Route name="login" handler={Login}/>
|
280
|
+
* <Route name="logout" handler={Logout}/>
|
281
|
+
* <Route name="about" handler={About}/>
|
282
|
+
* </Route>
|
283
|
+
* ];
|
284
|
+
*
|
285
|
+
* Router.run(routes, function (Handler) {
|
286
|
+
* React.render(<Handler/>, document.body);
|
287
|
+
* });
|
288
|
+
*
|
289
|
+
* Handlers for Route components that contain children can render their active
|
290
|
+
* child route using a <RouteHandler> element.
|
291
|
+
*
|
292
|
+
* var App = React.createClass({
|
293
|
+
* render: function () {
|
294
|
+
* return (
|
295
|
+
* <div class="application">
|
296
|
+
* <RouteHandler/>
|
297
|
+
* </div>
|
298
|
+
* );
|
299
|
+
* }
|
300
|
+
* });
|
301
|
+
*/
|
302
|
+
var Route = React.createClass({
|
303
|
+
|
304
|
+
displayName: 'Route',
|
305
|
+
|
306
|
+
mixins: [ FakeNode ],
|
307
|
+
|
308
|
+
propTypes: {
|
309
|
+
name: React.PropTypes.string,
|
310
|
+
path: React.PropTypes.string,
|
311
|
+
handler: React.PropTypes.func.isRequired,
|
312
|
+
ignoreScrollBehavior: React.PropTypes.bool
|
313
|
+
}
|
314
|
+
|
315
|
+
});
|
316
|
+
|
317
|
+
module.exports = Route;
|
318
|
+
|
319
|
+
},{"../mixins/FakeNode":14}],9:[function(_dereq_,module,exports){
|
320
|
+
var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
|
321
|
+
var RouteHandlerMixin = _dereq_('../mixins/RouteHandler');
|
322
|
+
|
323
|
+
/**
|
324
|
+
* A <RouteHandler> component renders the active child route handler
|
325
|
+
* when routes are nested.
|
326
|
+
*/
|
327
|
+
var RouteHandler = React.createClass({
|
328
|
+
|
329
|
+
displayName: 'RouteHandler',
|
330
|
+
|
331
|
+
mixins: [RouteHandlerMixin],
|
332
|
+
|
333
|
+
getDefaultProps: function () {
|
334
|
+
return {
|
335
|
+
ref: '__routeHandler__'
|
336
|
+
};
|
337
|
+
},
|
338
|
+
|
339
|
+
render: function () {
|
340
|
+
return this.getRouteHandler();
|
341
|
+
}
|
342
|
+
|
343
|
+
});
|
344
|
+
|
345
|
+
module.exports = RouteHandler;
|
346
|
+
|
347
|
+
},{"../mixins/RouteHandler":17}],10:[function(_dereq_,module,exports){
|
348
|
+
exports.DefaultRoute = _dereq_('./components/DefaultRoute');
|
349
|
+
exports.Link = _dereq_('./components/Link');
|
350
|
+
exports.NotFoundRoute = _dereq_('./components/NotFoundRoute');
|
351
|
+
exports.Redirect = _dereq_('./components/Redirect');
|
352
|
+
exports.Route = _dereq_('./components/Route');
|
353
|
+
exports.RouteHandler = _dereq_('./components/RouteHandler');
|
354
|
+
|
355
|
+
exports.HashLocation = _dereq_('./locations/HashLocation');
|
356
|
+
exports.HistoryLocation = _dereq_('./locations/HistoryLocation');
|
357
|
+
exports.RefreshLocation = _dereq_('./locations/RefreshLocation');
|
358
|
+
|
359
|
+
exports.ImitateBrowserBehavior = _dereq_('./behaviors/ImitateBrowserBehavior');
|
360
|
+
exports.ScrollToTopBehavior = _dereq_('./behaviors/ScrollToTopBehavior');
|
361
|
+
|
362
|
+
exports.Navigation = _dereq_('./mixins/Navigation');
|
363
|
+
exports.State = _dereq_('./mixins/State');
|
364
|
+
|
365
|
+
exports.create = _dereq_('./utils/createRouter');
|
366
|
+
exports.run = _dereq_('./utils/runRouter');
|
367
|
+
|
368
|
+
exports.History = _dereq_('./utils/History');
|
369
|
+
|
370
|
+
},{"./behaviors/ImitateBrowserBehavior":2,"./behaviors/ScrollToTopBehavior":3,"./components/DefaultRoute":4,"./components/Link":5,"./components/NotFoundRoute":6,"./components/Redirect":7,"./components/Route":8,"./components/RouteHandler":9,"./locations/HashLocation":11,"./locations/HistoryLocation":12,"./locations/RefreshLocation":13,"./mixins/Navigation":15,"./mixins/State":19,"./utils/History":22,"./utils/createRouter":28,"./utils/runRouter":32}],11:[function(_dereq_,module,exports){
|
371
|
+
var LocationActions = _dereq_('../actions/LocationActions');
|
372
|
+
var History = _dereq_('../utils/History');
|
373
|
+
var Path = _dereq_('../utils/Path');
|
374
|
+
|
375
|
+
/**
|
376
|
+
* Returns the current URL path from the `hash` portion of the URL, including
|
377
|
+
* query string.
|
378
|
+
*/
|
379
|
+
function getHashPath() {
|
380
|
+
return Path.decode(
|
381
|
+
// We can't use window.location.hash here because it's not
|
382
|
+
// consistent across browsers - Firefox will pre-decode it!
|
383
|
+
window.location.href.split('#')[1] || ''
|
384
|
+
);
|
385
|
+
}
|
386
|
+
|
387
|
+
var _actionType;
|
388
|
+
|
389
|
+
function ensureSlash() {
|
390
|
+
var path = getHashPath();
|
391
|
+
|
392
|
+
if (path.charAt(0) === '/')
|
393
|
+
return true;
|
394
|
+
|
395
|
+
HashLocation.replace('/' + path);
|
396
|
+
|
397
|
+
return false;
|
398
|
+
}
|
399
|
+
|
400
|
+
var _changeListeners = [];
|
401
|
+
|
402
|
+
function notifyChange(type) {
|
403
|
+
if (type === LocationActions.PUSH)
|
404
|
+
History.length += 1;
|
405
|
+
|
406
|
+
var change = {
|
407
|
+
path: getHashPath(),
|
408
|
+
type: type
|
409
|
+
};
|
410
|
+
|
411
|
+
_changeListeners.forEach(function (listener) {
|
412
|
+
listener(change);
|
413
|
+
});
|
414
|
+
}
|
415
|
+
|
416
|
+
var _isListening = false;
|
417
|
+
|
418
|
+
function onHashChange() {
|
419
|
+
if (ensureSlash()) {
|
420
|
+
// If we don't have an _actionType then all we know is the hash
|
421
|
+
// changed. It was probably caused by the user clicking the Back
|
422
|
+
// button, but may have also been the Forward button or manual
|
423
|
+
// manipulation. So just guess 'pop'.
|
424
|
+
notifyChange(_actionType || LocationActions.POP);
|
425
|
+
_actionType = null;
|
426
|
+
}
|
427
|
+
}
|
428
|
+
|
429
|
+
/**
|
430
|
+
* A Location that uses `window.location.hash`.
|
431
|
+
*/
|
432
|
+
var HashLocation = {
|
433
|
+
|
434
|
+
addChangeListener: function (listener) {
|
435
|
+
_changeListeners.push(listener);
|
436
|
+
|
437
|
+
// Do this BEFORE listening for hashchange.
|
438
|
+
ensureSlash();
|
439
|
+
|
440
|
+
if (_isListening)
|
441
|
+
return;
|
442
|
+
|
443
|
+
if (window.addEventListener) {
|
444
|
+
window.addEventListener('hashchange', onHashChange, false);
|
445
|
+
} else {
|
446
|
+
window.attachEvent('onhashchange', onHashChange);
|
447
|
+
}
|
448
|
+
|
449
|
+
_isListening = true;
|
450
|
+
},
|
451
|
+
|
452
|
+
removeChangeListener: function(listener) {
|
453
|
+
for (var i = 0, l = _changeListeners.length; i < l; i ++) {
|
454
|
+
if (_changeListeners[i] === listener) {
|
455
|
+
_changeListeners.splice(i, 1);
|
456
|
+
break;
|
457
|
+
}
|
458
|
+
}
|
459
|
+
|
460
|
+
if (window.removeEventListener) {
|
461
|
+
window.removeEventListener('hashchange', onHashChange, false);
|
462
|
+
} else {
|
463
|
+
window.removeEvent('onhashchange', onHashChange);
|
464
|
+
}
|
465
|
+
|
466
|
+
if (_changeListeners.length === 0)
|
467
|
+
_isListening = false;
|
468
|
+
},
|
469
|
+
|
470
|
+
|
471
|
+
|
472
|
+
push: function (path) {
|
473
|
+
_actionType = LocationActions.PUSH;
|
474
|
+
window.location.hash = Path.encode(path);
|
475
|
+
},
|
476
|
+
|
477
|
+
replace: function (path) {
|
478
|
+
_actionType = LocationActions.REPLACE;
|
479
|
+
window.location.replace(window.location.pathname + '#' + Path.encode(path));
|
480
|
+
},
|
481
|
+
|
482
|
+
pop: function () {
|
483
|
+
_actionType = LocationActions.POP;
|
484
|
+
History.back();
|
485
|
+
},
|
486
|
+
|
487
|
+
getCurrentPath: getHashPath,
|
488
|
+
|
489
|
+
toString: function () {
|
490
|
+
return '<HashLocation>';
|
491
|
+
}
|
492
|
+
|
493
|
+
};
|
494
|
+
|
495
|
+
module.exports = HashLocation;
|
496
|
+
|
497
|
+
},{"../actions/LocationActions":1,"../utils/History":22,"../utils/Path":23}],12:[function(_dereq_,module,exports){
|
498
|
+
var LocationActions = _dereq_('../actions/LocationActions');
|
499
|
+
var History = _dereq_('../utils/History');
|
500
|
+
var Path = _dereq_('../utils/Path');
|
501
|
+
|
502
|
+
/**
|
503
|
+
* Returns the current URL path from `window.location`, including query string.
|
504
|
+
*/
|
505
|
+
function getWindowPath() {
|
506
|
+
return Path.decode(
|
507
|
+
window.location.pathname + window.location.search
|
508
|
+
);
|
509
|
+
}
|
510
|
+
|
511
|
+
var _changeListeners = [];
|
512
|
+
|
513
|
+
function notifyChange(type) {
|
514
|
+
var change = {
|
515
|
+
path: getWindowPath(),
|
516
|
+
type: type
|
517
|
+
};
|
518
|
+
|
519
|
+
_changeListeners.forEach(function (listener) {
|
520
|
+
listener(change);
|
521
|
+
});
|
522
|
+
}
|
523
|
+
|
524
|
+
var _isListening = false;
|
525
|
+
|
526
|
+
function onPopState() {
|
527
|
+
notifyChange(LocationActions.POP);
|
528
|
+
}
|
529
|
+
|
530
|
+
/**
|
531
|
+
* A Location that uses HTML5 history.
|
532
|
+
*/
|
533
|
+
var HistoryLocation = {
|
534
|
+
|
535
|
+
addChangeListener: function (listener) {
|
536
|
+
_changeListeners.push(listener);
|
537
|
+
|
538
|
+
if (_isListening)
|
539
|
+
return;
|
540
|
+
|
541
|
+
if (window.addEventListener) {
|
542
|
+
window.addEventListener('popstate', onPopState, false);
|
543
|
+
} else {
|
544
|
+
window.attachEvent('popstate', onPopState);
|
545
|
+
}
|
546
|
+
|
547
|
+
_isListening = true;
|
548
|
+
},
|
549
|
+
|
550
|
+
removeChangeListener: function(listener) {
|
551
|
+
for (var i = 0, l = _changeListeners.length; i < l; i ++) {
|
552
|
+
if (_changeListeners[i] === listener) {
|
553
|
+
_changeListeners.splice(i, 1);
|
554
|
+
break;
|
555
|
+
}
|
556
|
+
}
|
557
|
+
|
558
|
+
if (window.addEventListener) {
|
559
|
+
window.removeEventListener('popstate', onPopState);
|
560
|
+
} else {
|
561
|
+
window.removeEvent('popstate', onPopState);
|
562
|
+
}
|
563
|
+
|
564
|
+
if (_changeListeners.length === 0)
|
565
|
+
_isListening = false;
|
566
|
+
},
|
567
|
+
|
568
|
+
|
569
|
+
|
570
|
+
push: function (path) {
|
571
|
+
window.history.pushState({ path: path }, '', Path.encode(path));
|
572
|
+
History.length += 1;
|
573
|
+
notifyChange(LocationActions.PUSH);
|
574
|
+
},
|
575
|
+
|
576
|
+
replace: function (path) {
|
577
|
+
window.history.replaceState({ path: path }, '', Path.encode(path));
|
578
|
+
notifyChange(LocationActions.REPLACE);
|
579
|
+
},
|
580
|
+
|
581
|
+
pop: History.back,
|
582
|
+
|
583
|
+
getCurrentPath: getWindowPath,
|
584
|
+
|
585
|
+
toString: function () {
|
586
|
+
return '<HistoryLocation>';
|
587
|
+
}
|
588
|
+
|
589
|
+
};
|
590
|
+
|
591
|
+
module.exports = HistoryLocation;
|
592
|
+
|
593
|
+
},{"../actions/LocationActions":1,"../utils/History":22,"../utils/Path":23}],13:[function(_dereq_,module,exports){
|
594
|
+
var HistoryLocation = _dereq_('./HistoryLocation');
|
595
|
+
var History = _dereq_('../utils/History');
|
596
|
+
var Path = _dereq_('../utils/Path');
|
597
|
+
|
598
|
+
/**
|
599
|
+
* A Location that uses full page refreshes. This is used as
|
600
|
+
* the fallback for HistoryLocation in browsers that do not
|
601
|
+
* support the HTML5 history API.
|
602
|
+
*/
|
603
|
+
var RefreshLocation = {
|
604
|
+
|
605
|
+
push: function (path) {
|
606
|
+
window.location = Path.encode(path);
|
607
|
+
},
|
608
|
+
|
609
|
+
replace: function (path) {
|
610
|
+
window.location.replace(Path.encode(path));
|
611
|
+
},
|
612
|
+
|
613
|
+
pop: History.back,
|
614
|
+
|
615
|
+
getCurrentPath: HistoryLocation.getCurrentPath,
|
616
|
+
|
617
|
+
toString: function () {
|
618
|
+
return '<RefreshLocation>';
|
619
|
+
}
|
620
|
+
|
621
|
+
};
|
622
|
+
|
623
|
+
module.exports = RefreshLocation;
|
624
|
+
|
625
|
+
},{"../utils/History":22,"../utils/Path":23,"./HistoryLocation":12}],14:[function(_dereq_,module,exports){
|
626
|
+
var invariant = _dereq_('react/lib/invariant');
|
627
|
+
|
628
|
+
var FakeNode = {
|
629
|
+
|
630
|
+
render: function () {
|
631
|
+
invariant(
|
632
|
+
false,
|
633
|
+
'%s elements should not be rendered',
|
634
|
+
this.constructor.displayName
|
635
|
+
);
|
636
|
+
}
|
637
|
+
|
638
|
+
};
|
639
|
+
|
640
|
+
module.exports = FakeNode;
|
641
|
+
|
642
|
+
},{"react/lib/invariant":43}],15:[function(_dereq_,module,exports){
|
643
|
+
var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
|
644
|
+
|
645
|
+
/**
|
646
|
+
* A mixin for components that modify the URL.
|
647
|
+
*
|
648
|
+
* Example:
|
649
|
+
*
|
650
|
+
* var MyLink = React.createClass({
|
651
|
+
* mixins: [ Router.Navigation ],
|
652
|
+
* handleClick: function (event) {
|
653
|
+
* event.preventDefault();
|
654
|
+
* this.transitionTo('aRoute', { the: 'params' }, { the: 'query' });
|
655
|
+
* },
|
656
|
+
* render: function () {
|
657
|
+
* return (
|
658
|
+
* <a onClick={this.handleClick}>Click me!</a>
|
659
|
+
* );
|
660
|
+
* }
|
661
|
+
* });
|
662
|
+
*/
|
663
|
+
var Navigation = {
|
664
|
+
|
665
|
+
contextTypes: {
|
666
|
+
makePath: React.PropTypes.func.isRequired,
|
667
|
+
makeHref: React.PropTypes.func.isRequired,
|
668
|
+
transitionTo: React.PropTypes.func.isRequired,
|
669
|
+
replaceWith: React.PropTypes.func.isRequired,
|
670
|
+
goBack: React.PropTypes.func.isRequired
|
671
|
+
},
|
672
|
+
|
673
|
+
/**
|
674
|
+
* Returns an absolute URL path created from the given route
|
675
|
+
* name, URL parameters, and query values.
|
676
|
+
*/
|
677
|
+
makePath: function (to, params, query) {
|
678
|
+
return this.context.makePath(to, params, query);
|
679
|
+
},
|
680
|
+
|
681
|
+
/**
|
682
|
+
* Returns a string that may safely be used as the href of a
|
683
|
+
* link to the route with the given name.
|
684
|
+
*/
|
685
|
+
makeHref: function (to, params, query) {
|
686
|
+
return this.context.makeHref(to, params, query);
|
687
|
+
},
|
688
|
+
|
689
|
+
/**
|
690
|
+
* Transitions to the URL specified in the arguments by pushing
|
691
|
+
* a new URL onto the history stack.
|
692
|
+
*/
|
693
|
+
transitionTo: function (to, params, query) {
|
694
|
+
this.context.transitionTo(to, params, query);
|
695
|
+
},
|
696
|
+
|
697
|
+
/**
|
698
|
+
* Transitions to the URL specified in the arguments by replacing
|
699
|
+
* the current URL in the history stack.
|
700
|
+
*/
|
701
|
+
replaceWith: function (to, params, query) {
|
702
|
+
this.context.replaceWith(to, params, query);
|
703
|
+
},
|
704
|
+
|
705
|
+
/**
|
706
|
+
* Transitions to the previous URL.
|
707
|
+
*/
|
708
|
+
goBack: function () {
|
709
|
+
this.context.goBack();
|
710
|
+
}
|
711
|
+
|
712
|
+
};
|
713
|
+
|
714
|
+
module.exports = Navigation;
|
715
|
+
|
716
|
+
},{}],16:[function(_dereq_,module,exports){
|
717
|
+
var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
|
718
|
+
|
719
|
+
/**
|
720
|
+
* Provides the router with context for Router.Navigation.
|
721
|
+
*/
|
722
|
+
var NavigationContext = {
|
723
|
+
|
724
|
+
childContextTypes: {
|
725
|
+
makePath: React.PropTypes.func.isRequired,
|
726
|
+
makeHref: React.PropTypes.func.isRequired,
|
727
|
+
transitionTo: React.PropTypes.func.isRequired,
|
728
|
+
replaceWith: React.PropTypes.func.isRequired,
|
729
|
+
goBack: React.PropTypes.func.isRequired
|
730
|
+
},
|
731
|
+
|
732
|
+
getChildContext: function () {
|
733
|
+
return {
|
734
|
+
makePath: this.constructor.makePath,
|
735
|
+
makeHref: this.constructor.makeHref,
|
736
|
+
transitionTo: this.constructor.transitionTo,
|
737
|
+
replaceWith: this.constructor.replaceWith,
|
738
|
+
goBack: this.constructor.goBack
|
739
|
+
};
|
740
|
+
}
|
741
|
+
|
742
|
+
};
|
743
|
+
|
744
|
+
module.exports = NavigationContext;
|
745
|
+
|
746
|
+
},{}],17:[function(_dereq_,module,exports){
|
747
|
+
var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
|
748
|
+
|
749
|
+
module.exports = {
|
750
|
+
contextTypes: {
|
751
|
+
getRouteAtDepth: React.PropTypes.func.isRequired,
|
752
|
+
getRouteComponents: React.PropTypes.func.isRequired,
|
753
|
+
routeHandlers: React.PropTypes.array.isRequired
|
754
|
+
},
|
755
|
+
|
756
|
+
childContextTypes: {
|
757
|
+
routeHandlers: React.PropTypes.array.isRequired
|
758
|
+
},
|
759
|
+
|
760
|
+
getChildContext: function () {
|
761
|
+
return {
|
762
|
+
routeHandlers: this.context.routeHandlers.concat([ this ])
|
763
|
+
};
|
764
|
+
},
|
765
|
+
|
766
|
+
getRouteDepth: function () {
|
767
|
+
return this.context.routeHandlers.length - 1;
|
768
|
+
},
|
769
|
+
|
770
|
+
componentDidMount: function () {
|
771
|
+
this._updateRouteComponent();
|
772
|
+
},
|
773
|
+
|
774
|
+
componentDidUpdate: function () {
|
775
|
+
this._updateRouteComponent();
|
776
|
+
},
|
777
|
+
|
778
|
+
_updateRouteComponent: function () {
|
779
|
+
var depth = this.getRouteDepth();
|
780
|
+
var components = this.context.getRouteComponents();
|
781
|
+
components[depth] = this.refs[this.props.ref || '__routeHandler__'];
|
782
|
+
},
|
783
|
+
|
784
|
+
getRouteHandler: function (props) {
|
785
|
+
var route = this.context.getRouteAtDepth(this.getRouteDepth());
|
786
|
+
return route ? React.createElement(route.handler, props || this.props) : null;
|
787
|
+
}
|
788
|
+
};
|
789
|
+
},{}],18:[function(_dereq_,module,exports){
|
790
|
+
var invariant = _dereq_('react/lib/invariant');
|
791
|
+
var canUseDOM = _dereq_('react/lib/ExecutionEnvironment').canUseDOM;
|
792
|
+
var getWindowScrollPosition = _dereq_('../utils/getWindowScrollPosition');
|
793
|
+
|
794
|
+
function shouldUpdateScroll(state, prevState) {
|
795
|
+
if (!prevState)
|
796
|
+
return true;
|
797
|
+
|
798
|
+
// Don't update scroll position when only the query has changed.
|
799
|
+
if (state.pathname === prevState.pathname)
|
800
|
+
return false;
|
801
|
+
|
802
|
+
var routes = state.routes;
|
803
|
+
var prevRoutes = prevState.routes;
|
804
|
+
|
805
|
+
var sharedAncestorRoutes = routes.filter(function (route) {
|
806
|
+
return prevRoutes.indexOf(route) !== -1;
|
807
|
+
});
|
808
|
+
|
809
|
+
return !sharedAncestorRoutes.some(function (route) {
|
810
|
+
return route.ignoreScrollBehavior;
|
811
|
+
});
|
812
|
+
}
|
813
|
+
|
814
|
+
/**
|
815
|
+
* Provides the router with the ability to manage window scroll position
|
816
|
+
* according to its scroll behavior.
|
817
|
+
*/
|
818
|
+
var Scrolling = {
|
819
|
+
|
820
|
+
statics: {
|
821
|
+
/**
|
822
|
+
* Records curent scroll position as the last known position for the given URL path.
|
823
|
+
*/
|
824
|
+
recordScrollPosition: function (path) {
|
825
|
+
if (!this.scrollHistory)
|
826
|
+
this.scrollHistory = {};
|
827
|
+
|
828
|
+
this.scrollHistory[path] = getWindowScrollPosition();
|
829
|
+
},
|
830
|
+
|
831
|
+
/**
|
832
|
+
* Returns the last known scroll position for the given URL path.
|
833
|
+
*/
|
834
|
+
getScrollPosition: function (path) {
|
835
|
+
if (!this.scrollHistory)
|
836
|
+
this.scrollHistory = {};
|
837
|
+
|
838
|
+
return this.scrollHistory[path] || null;
|
839
|
+
}
|
840
|
+
},
|
841
|
+
|
842
|
+
componentWillMount: function () {
|
843
|
+
invariant(
|
844
|
+
this.getScrollBehavior() == null || canUseDOM,
|
845
|
+
'Cannot use scroll behavior without a DOM'
|
846
|
+
);
|
847
|
+
},
|
848
|
+
|
849
|
+
componentDidMount: function () {
|
850
|
+
this._updateScroll();
|
851
|
+
},
|
852
|
+
|
853
|
+
componentDidUpdate: function (prevProps, prevState) {
|
854
|
+
this._updateScroll(prevState);
|
855
|
+
},
|
856
|
+
|
857
|
+
_updateScroll: function (prevState) {
|
858
|
+
if (!shouldUpdateScroll(this.state, prevState))
|
859
|
+
return;
|
860
|
+
|
861
|
+
var scrollBehavior = this.getScrollBehavior();
|
862
|
+
|
863
|
+
if (scrollBehavior)
|
864
|
+
scrollBehavior.updateScrollPosition(
|
865
|
+
this.constructor.getScrollPosition(this.state.path),
|
866
|
+
this.state.action
|
867
|
+
);
|
868
|
+
}
|
869
|
+
|
870
|
+
};
|
871
|
+
|
872
|
+
module.exports = Scrolling;
|
873
|
+
|
874
|
+
},{"../utils/getWindowScrollPosition":30,"react/lib/ExecutionEnvironment":39,"react/lib/invariant":43}],19:[function(_dereq_,module,exports){
|
875
|
+
var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
|
876
|
+
|
877
|
+
/**
|
878
|
+
* A mixin for components that need to know the path, routes, URL
|
879
|
+
* params and query that are currently active.
|
880
|
+
*
|
881
|
+
* Example:
|
882
|
+
*
|
883
|
+
* var AboutLink = React.createClass({
|
884
|
+
* mixins: [ Router.State ],
|
885
|
+
* render: function () {
|
886
|
+
* var className = this.props.className;
|
887
|
+
*
|
888
|
+
* if (this.isActive('about'))
|
889
|
+
* className += ' is-active';
|
890
|
+
*
|
891
|
+
* return React.DOM.a({ className: className }, this.props.children);
|
892
|
+
* }
|
893
|
+
* });
|
894
|
+
*/
|
895
|
+
var State = {
|
896
|
+
|
897
|
+
contextTypes: {
|
898
|
+
getCurrentPath: React.PropTypes.func.isRequired,
|
899
|
+
getCurrentRoutes: React.PropTypes.func.isRequired,
|
900
|
+
getCurrentPathname: React.PropTypes.func.isRequired,
|
901
|
+
getCurrentParams: React.PropTypes.func.isRequired,
|
902
|
+
getCurrentQuery: React.PropTypes.func.isRequired,
|
903
|
+
isActive: React.PropTypes.func.isRequired
|
904
|
+
},
|
905
|
+
|
906
|
+
/**
|
907
|
+
* Returns the current URL path.
|
908
|
+
*/
|
909
|
+
getPath: function () {
|
910
|
+
return this.context.getCurrentPath();
|
911
|
+
},
|
912
|
+
|
913
|
+
/**
|
914
|
+
* Returns an array of the routes that are currently active.
|
915
|
+
*/
|
916
|
+
getRoutes: function () {
|
917
|
+
return this.context.getCurrentRoutes();
|
918
|
+
},
|
919
|
+
|
920
|
+
/**
|
921
|
+
* Returns the current URL path without the query string.
|
922
|
+
*/
|
923
|
+
getPathname: function () {
|
924
|
+
return this.context.getCurrentPathname();
|
925
|
+
},
|
926
|
+
|
927
|
+
/**
|
928
|
+
* Returns an object of the URL params that are currently active.
|
929
|
+
*/
|
930
|
+
getParams: function () {
|
931
|
+
return this.context.getCurrentParams();
|
932
|
+
},
|
933
|
+
|
934
|
+
/**
|
935
|
+
* Returns an object of the query params that are currently active.
|
936
|
+
*/
|
937
|
+
getQuery: function () {
|
938
|
+
return this.context.getCurrentQuery();
|
939
|
+
},
|
940
|
+
|
941
|
+
/**
|
942
|
+
* A helper method to determine if a given route, params, and query
|
943
|
+
* are active.
|
944
|
+
*/
|
945
|
+
isActive: function (to, params, query) {
|
946
|
+
return this.context.isActive(to, params, query);
|
947
|
+
}
|
948
|
+
|
949
|
+
};
|
950
|
+
|
951
|
+
module.exports = State;
|
952
|
+
|
953
|
+
},{}],20:[function(_dereq_,module,exports){
|
954
|
+
var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
|
955
|
+
var assign = _dereq_('react/lib/Object.assign');
|
956
|
+
var Path = _dereq_('../utils/Path');
|
957
|
+
|
958
|
+
function routeIsActive(activeRoutes, routeName) {
|
959
|
+
return activeRoutes.some(function (route) {
|
960
|
+
return route.name === routeName;
|
961
|
+
});
|
962
|
+
}
|
963
|
+
|
964
|
+
function paramsAreActive(activeParams, params) {
|
965
|
+
for (var property in params)
|
966
|
+
if (String(activeParams[property]) !== String(params[property]))
|
967
|
+
return false;
|
968
|
+
|
969
|
+
return true;
|
970
|
+
}
|
971
|
+
|
972
|
+
function queryIsActive(activeQuery, query) {
|
973
|
+
for (var property in query)
|
974
|
+
if (String(activeQuery[property]) !== String(query[property]))
|
975
|
+
return false;
|
976
|
+
|
977
|
+
return true;
|
978
|
+
}
|
979
|
+
|
980
|
+
/**
|
981
|
+
* Provides the router with context for Router.State.
|
982
|
+
*/
|
983
|
+
var StateContext = {
|
984
|
+
|
985
|
+
/**
|
986
|
+
* Returns the current URL path + query string.
|
987
|
+
*/
|
988
|
+
getCurrentPath: function () {
|
989
|
+
return this.state.path;
|
990
|
+
},
|
991
|
+
|
992
|
+
/**
|
993
|
+
* Returns a read-only array of the currently active routes.
|
994
|
+
*/
|
995
|
+
getCurrentRoutes: function () {
|
996
|
+
return this.state.routes.slice(0);
|
997
|
+
},
|
998
|
+
|
999
|
+
/**
|
1000
|
+
* Returns the current URL path without the query string.
|
1001
|
+
*/
|
1002
|
+
getCurrentPathname: function () {
|
1003
|
+
return this.state.pathname;
|
1004
|
+
},
|
1005
|
+
|
1006
|
+
/**
|
1007
|
+
* Returns a read-only object of the currently active URL parameters.
|
1008
|
+
*/
|
1009
|
+
getCurrentParams: function () {
|
1010
|
+
return assign({}, this.state.params);
|
1011
|
+
},
|
1012
|
+
|
1013
|
+
/**
|
1014
|
+
* Returns a read-only object of the currently active query parameters.
|
1015
|
+
*/
|
1016
|
+
getCurrentQuery: function () {
|
1017
|
+
return assign({}, this.state.query);
|
1018
|
+
},
|
1019
|
+
|
1020
|
+
/**
|
1021
|
+
* Returns true if the given route, params, and query are active.
|
1022
|
+
*/
|
1023
|
+
isActive: function (to, params, query) {
|
1024
|
+
if (Path.isAbsolute(to))
|
1025
|
+
return to === this.state.path;
|
1026
|
+
|
1027
|
+
return routeIsActive(this.state.routes, to) &&
|
1028
|
+
paramsAreActive(this.state.params, params) &&
|
1029
|
+
(query == null || queryIsActive(this.state.query, query));
|
1030
|
+
},
|
1031
|
+
|
1032
|
+
childContextTypes: {
|
1033
|
+
getCurrentPath: React.PropTypes.func.isRequired,
|
1034
|
+
getCurrentRoutes: React.PropTypes.func.isRequired,
|
1035
|
+
getCurrentPathname: React.PropTypes.func.isRequired,
|
1036
|
+
getCurrentParams: React.PropTypes.func.isRequired,
|
1037
|
+
getCurrentQuery: React.PropTypes.func.isRequired,
|
1038
|
+
isActive: React.PropTypes.func.isRequired
|
1039
|
+
},
|
1040
|
+
|
1041
|
+
getChildContext: function () {
|
1042
|
+
return {
|
1043
|
+
getCurrentPath: this.getCurrentPath,
|
1044
|
+
getCurrentRoutes: this.getCurrentRoutes,
|
1045
|
+
getCurrentPathname: this.getCurrentPathname,
|
1046
|
+
getCurrentParams: this.getCurrentParams,
|
1047
|
+
getCurrentQuery: this.getCurrentQuery,
|
1048
|
+
isActive: this.isActive
|
1049
|
+
};
|
1050
|
+
}
|
1051
|
+
|
1052
|
+
};
|
1053
|
+
|
1054
|
+
module.exports = StateContext;
|
1055
|
+
|
1056
|
+
},{"../utils/Path":23,"react/lib/Object.assign":40}],21:[function(_dereq_,module,exports){
|
1057
|
+
/**
|
1058
|
+
* Represents a cancellation caused by navigating away
|
1059
|
+
* before the previous transition has fully resolved.
|
1060
|
+
*/
|
1061
|
+
function Cancellation() { }
|
1062
|
+
|
1063
|
+
module.exports = Cancellation;
|
1064
|
+
|
1065
|
+
},{}],22:[function(_dereq_,module,exports){
|
1066
|
+
var invariant = _dereq_('react/lib/invariant');
|
1067
|
+
var canUseDOM = _dereq_('react/lib/ExecutionEnvironment').canUseDOM;
|
1068
|
+
|
1069
|
+
var History = {
|
1070
|
+
|
1071
|
+
/**
|
1072
|
+
* Sends the browser back one entry in the history.
|
1073
|
+
*/
|
1074
|
+
back: function () {
|
1075
|
+
invariant(
|
1076
|
+
canUseDOM,
|
1077
|
+
'Cannot use History.back without a DOM'
|
1078
|
+
);
|
1079
|
+
|
1080
|
+
// Do this first so that History.length will
|
1081
|
+
// be accurate in location change listeners.
|
1082
|
+
History.length -= 1;
|
1083
|
+
|
1084
|
+
window.history.back();
|
1085
|
+
},
|
1086
|
+
|
1087
|
+
/**
|
1088
|
+
* The current number of entries in the history.
|
1089
|
+
*/
|
1090
|
+
length: 1
|
1091
|
+
|
1092
|
+
};
|
1093
|
+
|
1094
|
+
module.exports = History;
|
1095
|
+
|
1096
|
+
},{"react/lib/ExecutionEnvironment":39,"react/lib/invariant":43}],23:[function(_dereq_,module,exports){
|
1097
|
+
var invariant = _dereq_('react/lib/invariant');
|
1098
|
+
var merge = _dereq_('qs/lib/utils').merge;
|
1099
|
+
var qs = _dereq_('qs');
|
1100
|
+
|
1101
|
+
var paramCompileMatcher = /:([a-zA-Z_$][a-zA-Z0-9_$]*)|[*.()\[\]\\+|{}^$]/g;
|
1102
|
+
var paramInjectMatcher = /:([a-zA-Z_$][a-zA-Z0-9_$?]*[?]?)|[*]/g;
|
1103
|
+
var paramInjectTrailingSlashMatcher = /\/\/\?|\/\?/g;
|
1104
|
+
var queryMatcher = /\?(.+)/;
|
1105
|
+
|
1106
|
+
var _compiledPatterns = {};
|
1107
|
+
|
1108
|
+
function compilePattern(pattern) {
|
1109
|
+
if (!(pattern in _compiledPatterns)) {
|
1110
|
+
var paramNames = [];
|
1111
|
+
var source = pattern.replace(paramCompileMatcher, function (match, paramName) {
|
1112
|
+
if (paramName) {
|
1113
|
+
paramNames.push(paramName);
|
1114
|
+
return '([^/?#]+)';
|
1115
|
+
} else if (match === '*') {
|
1116
|
+
paramNames.push('splat');
|
1117
|
+
return '(.*?)';
|
1118
|
+
} else {
|
1119
|
+
return '\\' + match;
|
1120
|
+
}
|
1121
|
+
});
|
1122
|
+
|
1123
|
+
_compiledPatterns[pattern] = {
|
1124
|
+
matcher: new RegExp('^' + source + '$', 'i'),
|
1125
|
+
paramNames: paramNames
|
1126
|
+
};
|
1127
|
+
}
|
1128
|
+
|
1129
|
+
return _compiledPatterns[pattern];
|
1130
|
+
}
|
1131
|
+
|
1132
|
+
var Path = {
|
1133
|
+
|
1134
|
+
/**
|
1135
|
+
* Safely decodes special characters in the given URL path.
|
1136
|
+
*/
|
1137
|
+
decode: function (path) {
|
1138
|
+
return decodeURI(path.replace(/\+/g, ' '));
|
1139
|
+
},
|
1140
|
+
|
1141
|
+
/**
|
1142
|
+
* Safely encodes special characters in the given URL path.
|
1143
|
+
*/
|
1144
|
+
encode: function (path) {
|
1145
|
+
return encodeURI(path).replace(/%20/g, '+');
|
1146
|
+
},
|
1147
|
+
|
1148
|
+
/**
|
1149
|
+
* Returns an array of the names of all parameters in the given pattern.
|
1150
|
+
*/
|
1151
|
+
extractParamNames: function (pattern) {
|
1152
|
+
return compilePattern(pattern).paramNames;
|
1153
|
+
},
|
1154
|
+
|
1155
|
+
/**
|
1156
|
+
* Extracts the portions of the given URL path that match the given pattern
|
1157
|
+
* and returns an object of param name => value pairs. Returns null if the
|
1158
|
+
* pattern does not match the given path.
|
1159
|
+
*/
|
1160
|
+
extractParams: function (pattern, path) {
|
1161
|
+
var object = compilePattern(pattern);
|
1162
|
+
var match = path.match(object.matcher);
|
1163
|
+
|
1164
|
+
if (!match)
|
1165
|
+
return null;
|
1166
|
+
|
1167
|
+
var params = {};
|
1168
|
+
|
1169
|
+
object.paramNames.forEach(function (paramName, index) {
|
1170
|
+
params[paramName] = match[index + 1];
|
1171
|
+
});
|
1172
|
+
|
1173
|
+
return params;
|
1174
|
+
},
|
1175
|
+
|
1176
|
+
/**
|
1177
|
+
* Returns a version of the given route path with params interpolated. Throws
|
1178
|
+
* if there is a dynamic segment of the route path for which there is no param.
|
1179
|
+
*/
|
1180
|
+
injectParams: function (pattern, params) {
|
1181
|
+
params = params || {};
|
1182
|
+
|
1183
|
+
var splatIndex = 0;
|
1184
|
+
|
1185
|
+
return pattern.replace(paramInjectMatcher, function (match, paramName) {
|
1186
|
+
paramName = paramName || 'splat';
|
1187
|
+
|
1188
|
+
// If param is optional don't check for existence
|
1189
|
+
if (paramName.slice(-1) !== '?') {
|
1190
|
+
invariant(
|
1191
|
+
params[paramName] != null,
|
1192
|
+
'Missing "' + paramName + '" parameter for path "' + pattern + '"'
|
1193
|
+
);
|
1194
|
+
} else {
|
1195
|
+
paramName = paramName.slice(0, -1);
|
1196
|
+
|
1197
|
+
if (params[paramName] == null)
|
1198
|
+
return '';
|
1199
|
+
}
|
1200
|
+
|
1201
|
+
var segment;
|
1202
|
+
if (paramName === 'splat' && Array.isArray(params[paramName])) {
|
1203
|
+
segment = params[paramName][splatIndex++];
|
1204
|
+
|
1205
|
+
invariant(
|
1206
|
+
segment != null,
|
1207
|
+
'Missing splat # ' + splatIndex + ' for path "' + pattern + '"'
|
1208
|
+
);
|
1209
|
+
} else {
|
1210
|
+
segment = params[paramName];
|
1211
|
+
}
|
1212
|
+
|
1213
|
+
return segment;
|
1214
|
+
}).replace(paramInjectTrailingSlashMatcher, '/');
|
1215
|
+
},
|
1216
|
+
|
1217
|
+
/**
|
1218
|
+
* Returns an object that is the result of parsing any query string contained
|
1219
|
+
* in the given path, null if the path contains no query string.
|
1220
|
+
*/
|
1221
|
+
extractQuery: function (path) {
|
1222
|
+
var match = path.match(queryMatcher);
|
1223
|
+
return match && qs.parse(match[1]);
|
1224
|
+
},
|
1225
|
+
|
1226
|
+
/**
|
1227
|
+
* Returns a version of the given path without the query string.
|
1228
|
+
*/
|
1229
|
+
withoutQuery: function (path) {
|
1230
|
+
return path.replace(queryMatcher, '');
|
1231
|
+
},
|
1232
|
+
|
1233
|
+
/**
|
1234
|
+
* Returns a version of the given path with the parameters in the given
|
1235
|
+
* query merged into the query string.
|
1236
|
+
*/
|
1237
|
+
withQuery: function (path, query) {
|
1238
|
+
var existingQuery = Path.extractQuery(path);
|
1239
|
+
|
1240
|
+
if (existingQuery)
|
1241
|
+
query = query ? merge(existingQuery, query) : existingQuery;
|
1242
|
+
|
1243
|
+
var queryString = query && qs.stringify(query);
|
1244
|
+
|
1245
|
+
if (queryString)
|
1246
|
+
return Path.withoutQuery(path) + '?' + queryString;
|
1247
|
+
|
1248
|
+
return path;
|
1249
|
+
},
|
1250
|
+
|
1251
|
+
/**
|
1252
|
+
* Returns true if the given path is absolute.
|
1253
|
+
*/
|
1254
|
+
isAbsolute: function (path) {
|
1255
|
+
return path.charAt(0) === '/';
|
1256
|
+
},
|
1257
|
+
|
1258
|
+
/**
|
1259
|
+
* Returns a normalized version of the given path.
|
1260
|
+
*/
|
1261
|
+
normalize: function (path, parentRoute) {
|
1262
|
+
return path.replace(/^\/*/, '/');
|
1263
|
+
},
|
1264
|
+
|
1265
|
+
/**
|
1266
|
+
* Joins two URL paths together.
|
1267
|
+
*/
|
1268
|
+
join: function (a, b) {
|
1269
|
+
return a.replace(/\/*$/, '/') + b;
|
1270
|
+
}
|
1271
|
+
|
1272
|
+
};
|
1273
|
+
|
1274
|
+
module.exports = Path;
|
1275
|
+
|
1276
|
+
},{"qs":34,"qs/lib/utils":38,"react/lib/invariant":43}],24:[function(_dereq_,module,exports){
|
1277
|
+
var Promise = _dereq_('when/lib/Promise');
|
1278
|
+
|
1279
|
+
// TODO: Use process.env.NODE_ENV check + envify to enable
|
1280
|
+
// when's promise monitor here when in dev.
|
1281
|
+
|
1282
|
+
module.exports = Promise;
|
1283
|
+
|
1284
|
+
},{"when/lib/Promise":45}],25:[function(_dereq_,module,exports){
|
1285
|
+
var PropTypes = {
|
1286
|
+
|
1287
|
+
/**
|
1288
|
+
* Requires that the value of a prop be falsy.
|
1289
|
+
*/
|
1290
|
+
falsy: function (props, propName, componentName) {
|
1291
|
+
if (props[propName])
|
1292
|
+
return new Error('<' + componentName + '> may not have a "' + propName + '" prop');
|
1293
|
+
}
|
1294
|
+
|
1295
|
+
};
|
1296
|
+
|
1297
|
+
module.exports = PropTypes;
|
1298
|
+
|
1299
|
+
},{}],26:[function(_dereq_,module,exports){
|
1300
|
+
/**
|
1301
|
+
* Encapsulates a redirect to the given route.
|
1302
|
+
*/
|
1303
|
+
function Redirect(to, params, query) {
|
1304
|
+
this.to = to;
|
1305
|
+
this.params = params;
|
1306
|
+
this.query = query;
|
1307
|
+
}
|
1308
|
+
|
1309
|
+
module.exports = Redirect;
|
1310
|
+
|
1311
|
+
},{}],27:[function(_dereq_,module,exports){
|
1312
|
+
var assign = _dereq_('react/lib/Object.assign');
|
1313
|
+
var reversedArray = _dereq_('./reversedArray');
|
1314
|
+
var Redirect = _dereq_('./Redirect');
|
1315
|
+
var Promise = _dereq_('./Promise');
|
1316
|
+
|
1317
|
+
/**
|
1318
|
+
* Runs all hook functions serially and calls callback(error) when finished.
|
1319
|
+
* A hook may return a promise if it needs to execute asynchronously.
|
1320
|
+
*/
|
1321
|
+
function runHooks(hooks, callback) {
|
1322
|
+
var promise;
|
1323
|
+
try {
|
1324
|
+
promise = hooks.reduce(function (promise, hook) {
|
1325
|
+
// The first hook to use transition.wait makes the rest
|
1326
|
+
// of the transition async from that point forward.
|
1327
|
+
return promise ? promise.then(hook) : hook();
|
1328
|
+
}, null);
|
1329
|
+
} catch (error) {
|
1330
|
+
return callback(error); // Sync error.
|
1331
|
+
}
|
1332
|
+
|
1333
|
+
if (promise) {
|
1334
|
+
// Use setTimeout to break the promise chain.
|
1335
|
+
promise.then(function () {
|
1336
|
+
setTimeout(callback);
|
1337
|
+
}, function (error) {
|
1338
|
+
setTimeout(function () {
|
1339
|
+
callback(error);
|
1340
|
+
});
|
1341
|
+
});
|
1342
|
+
} else {
|
1343
|
+
callback();
|
1344
|
+
}
|
1345
|
+
}
|
1346
|
+
|
1347
|
+
/**
|
1348
|
+
* Calls the willTransitionFrom hook of all handlers in the given matches
|
1349
|
+
* serially in reverse with the transition object and the current instance of
|
1350
|
+
* the route's handler, so that the deepest nested handlers are called first.
|
1351
|
+
* Calls callback(error) when finished.
|
1352
|
+
*/
|
1353
|
+
function runTransitionFromHooks(transition, routes, components, callback) {
|
1354
|
+
components = reversedArray(components);
|
1355
|
+
|
1356
|
+
var hooks = reversedArray(routes).map(function (route, index) {
|
1357
|
+
return function () {
|
1358
|
+
var handler = route.handler;
|
1359
|
+
|
1360
|
+
if (!transition.isAborted && handler.willTransitionFrom)
|
1361
|
+
return handler.willTransitionFrom(transition, components[index]);
|
1362
|
+
|
1363
|
+
var promise = transition._promise;
|
1364
|
+
transition._promise = null;
|
1365
|
+
|
1366
|
+
return promise;
|
1367
|
+
};
|
1368
|
+
});
|
1369
|
+
|
1370
|
+
runHooks(hooks, callback);
|
1371
|
+
}
|
1372
|
+
|
1373
|
+
/**
|
1374
|
+
* Calls the willTransitionTo hook of all handlers in the given matches
|
1375
|
+
* serially with the transition object and any params that apply to that
|
1376
|
+
* handler. Calls callback(error) when finished.
|
1377
|
+
*/
|
1378
|
+
function runTransitionToHooks(transition, routes, params, query, callback) {
|
1379
|
+
var hooks = routes.map(function (route) {
|
1380
|
+
return function () {
|
1381
|
+
var handler = route.handler;
|
1382
|
+
|
1383
|
+
if (!transition.isAborted && handler.willTransitionTo)
|
1384
|
+
handler.willTransitionTo(transition, params, query);
|
1385
|
+
|
1386
|
+
var promise = transition._promise;
|
1387
|
+
transition._promise = null;
|
1388
|
+
|
1389
|
+
return promise;
|
1390
|
+
};
|
1391
|
+
});
|
1392
|
+
|
1393
|
+
runHooks(hooks, callback);
|
1394
|
+
}
|
1395
|
+
|
1396
|
+
/**
|
1397
|
+
* Encapsulates a transition to a given path.
|
1398
|
+
*
|
1399
|
+
* The willTransitionTo and willTransitionFrom handlers receive
|
1400
|
+
* an instance of this class as their first argument.
|
1401
|
+
*/
|
1402
|
+
function Transition(path, retry) {
|
1403
|
+
this.path = path;
|
1404
|
+
this.abortReason = null;
|
1405
|
+
this.isAborted = false;
|
1406
|
+
this.retry = retry.bind(this);
|
1407
|
+
this._promise = null;
|
1408
|
+
}
|
1409
|
+
|
1410
|
+
assign(Transition.prototype, {
|
1411
|
+
|
1412
|
+
abort: function (reason) {
|
1413
|
+
if (this.isAborted) {
|
1414
|
+
// First abort wins.
|
1415
|
+
return;
|
1416
|
+
}
|
1417
|
+
|
1418
|
+
this.abortReason = reason;
|
1419
|
+
this.isAborted = true;
|
1420
|
+
},
|
1421
|
+
|
1422
|
+
redirect: function (to, params, query) {
|
1423
|
+
this.abort(new Redirect(to, params, query));
|
1424
|
+
},
|
1425
|
+
|
1426
|
+
wait: function (value) {
|
1427
|
+
this._promise = Promise.resolve(value);
|
1428
|
+
},
|
1429
|
+
|
1430
|
+
from: function (routes, components, callback) {
|
1431
|
+
return runTransitionFromHooks(this, routes, components, callback);
|
1432
|
+
},
|
1433
|
+
|
1434
|
+
to: function (routes, params, query, callback) {
|
1435
|
+
return runTransitionToHooks(this, routes, params, query, callback);
|
1436
|
+
}
|
1437
|
+
|
1438
|
+
});
|
1439
|
+
|
1440
|
+
module.exports = Transition;
|
1441
|
+
|
1442
|
+
},{"./Promise":24,"./Redirect":26,"./reversedArray":31,"react/lib/Object.assign":40}],28:[function(_dereq_,module,exports){
|
1443
|
+
/* jshint -W058 */
|
1444
|
+
var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
|
1445
|
+
var warning = _dereq_('react/lib/warning');
|
1446
|
+
var invariant = _dereq_('react/lib/invariant');
|
1447
|
+
var canUseDOM = _dereq_('react/lib/ExecutionEnvironment').canUseDOM;
|
1448
|
+
var ImitateBrowserBehavior = _dereq_('../behaviors/ImitateBrowserBehavior');
|
1449
|
+
var RouteHandler = _dereq_('../components/RouteHandler');
|
1450
|
+
var LocationActions = _dereq_('../actions/LocationActions');
|
1451
|
+
var HashLocation = _dereq_('../locations/HashLocation');
|
1452
|
+
var HistoryLocation = _dereq_('../locations/HistoryLocation');
|
1453
|
+
var RefreshLocation = _dereq_('../locations/RefreshLocation');
|
1454
|
+
var NavigationContext = _dereq_('../mixins/NavigationContext');
|
1455
|
+
var StateContext = _dereq_('../mixins/StateContext');
|
1456
|
+
var Scrolling = _dereq_('../mixins/Scrolling');
|
1457
|
+
var createRoutesFromChildren = _dereq_('./createRoutesFromChildren');
|
1458
|
+
var supportsHistory = _dereq_('./supportsHistory');
|
1459
|
+
var Transition = _dereq_('./Transition');
|
1460
|
+
var PropTypes = _dereq_('./PropTypes');
|
1461
|
+
var Redirect = _dereq_('./Redirect');
|
1462
|
+
var History = _dereq_('./History');
|
1463
|
+
var Cancellation = _dereq_('./Cancellation');
|
1464
|
+
var Path = _dereq_('./Path');
|
1465
|
+
|
1466
|
+
/**
|
1467
|
+
* The default location for new routers.
|
1468
|
+
*/
|
1469
|
+
var DEFAULT_LOCATION = canUseDOM ? HashLocation : '/';
|
1470
|
+
|
1471
|
+
/**
|
1472
|
+
* The default scroll behavior for new routers.
|
1473
|
+
*/
|
1474
|
+
var DEFAULT_SCROLL_BEHAVIOR = canUseDOM ? ImitateBrowserBehavior : null;
|
1475
|
+
|
1476
|
+
/**
|
1477
|
+
* The default error handler for new routers.
|
1478
|
+
*/
|
1479
|
+
function defaultErrorHandler(error) {
|
1480
|
+
// Throw so we don't silently swallow async errors.
|
1481
|
+
throw error; // This error probably originated in a transition hook.
|
1482
|
+
}
|
1483
|
+
|
1484
|
+
/**
|
1485
|
+
* The default aborted transition handler for new routers.
|
1486
|
+
*/
|
1487
|
+
function defaultAbortHandler(abortReason, location) {
|
1488
|
+
if (typeof location === 'string')
|
1489
|
+
throw new Error('Unhandled aborted transition! Reason: ' + abortReason);
|
1490
|
+
|
1491
|
+
if (abortReason instanceof Cancellation) {
|
1492
|
+
return;
|
1493
|
+
} else if (abortReason instanceof Redirect) {
|
1494
|
+
location.replace(this.makePath(abortReason.to, abortReason.params, abortReason.query));
|
1495
|
+
} else {
|
1496
|
+
location.pop();
|
1497
|
+
}
|
1498
|
+
}
|
1499
|
+
|
1500
|
+
function findMatch(pathname, routes, defaultRoute, notFoundRoute) {
|
1501
|
+
var match, route, params;
|
1502
|
+
|
1503
|
+
for (var i = 0, len = routes.length; i < len; ++i) {
|
1504
|
+
route = routes[i];
|
1505
|
+
|
1506
|
+
// Check the subtree first to find the most deeply-nested match.
|
1507
|
+
match = findMatch(pathname, route.childRoutes, route.defaultRoute, route.notFoundRoute);
|
1508
|
+
|
1509
|
+
if (match != null) {
|
1510
|
+
match.routes.unshift(route);
|
1511
|
+
return match;
|
1512
|
+
}
|
1513
|
+
|
1514
|
+
// No routes in the subtree matched, so check this route.
|
1515
|
+
params = Path.extractParams(route.path, pathname);
|
1516
|
+
|
1517
|
+
if (params)
|
1518
|
+
return createMatch(route, params);
|
1519
|
+
}
|
1520
|
+
|
1521
|
+
// No routes matched, so try the default route if there is one.
|
1522
|
+
if (defaultRoute && (params = Path.extractParams(defaultRoute.path, pathname)))
|
1523
|
+
return createMatch(defaultRoute, params);
|
1524
|
+
|
1525
|
+
// Last attempt: does the "not found" route match?
|
1526
|
+
if (notFoundRoute && (params = Path.extractParams(notFoundRoute.path, pathname)))
|
1527
|
+
return createMatch(notFoundRoute, params);
|
1528
|
+
|
1529
|
+
return match;
|
1530
|
+
}
|
1531
|
+
|
1532
|
+
function createMatch(route, params) {
|
1533
|
+
return { routes: [ route ], params: params };
|
1534
|
+
}
|
1535
|
+
|
1536
|
+
function hasProperties(object, properties) {
|
1537
|
+
for (var propertyName in properties)
|
1538
|
+
if (properties.hasOwnProperty(propertyName) && object[propertyName] !== properties[propertyName])
|
1539
|
+
return false;
|
1540
|
+
|
1541
|
+
return true;
|
1542
|
+
}
|
1543
|
+
|
1544
|
+
function hasMatch(routes, route, prevParams, nextParams, prevQuery, nextQuery) {
|
1545
|
+
return routes.some(function (r) {
|
1546
|
+
if (r !== route)
|
1547
|
+
return false;
|
1548
|
+
|
1549
|
+
var paramNames = route.paramNames;
|
1550
|
+
var paramName;
|
1551
|
+
|
1552
|
+
// Ensure that all params the route cares about did not change.
|
1553
|
+
for (var i = 0, len = paramNames.length; i < len; ++i) {
|
1554
|
+
paramName = paramNames[i];
|
1555
|
+
|
1556
|
+
if (nextParams[paramName] !== prevParams[paramName])
|
1557
|
+
return false;
|
1558
|
+
}
|
1559
|
+
|
1560
|
+
// Ensure the query hasn't changed.
|
1561
|
+
return hasProperties(prevQuery, nextQuery) && hasProperties(nextQuery, prevQuery);
|
1562
|
+
});
|
1563
|
+
}
|
1564
|
+
|
1565
|
+
/**
|
1566
|
+
* Creates and returns a new router using the given options. A router
|
1567
|
+
* is a ReactComponent class that knows how to react to changes in the
|
1568
|
+
* URL and keep the contents of the page in sync.
|
1569
|
+
*
|
1570
|
+
* Options may be any of the following:
|
1571
|
+
*
|
1572
|
+
* - routes (required) The route config
|
1573
|
+
* - location The location to use. Defaults to HashLocation when
|
1574
|
+
* the DOM is available, "/" otherwise
|
1575
|
+
* - scrollBehavior The scroll behavior to use. Defaults to ImitateBrowserBehavior
|
1576
|
+
* when the DOM is available, null otherwise
|
1577
|
+
* - onError A function that is used to handle errors
|
1578
|
+
* - onAbort A function that is used to handle aborted transitions
|
1579
|
+
*
|
1580
|
+
* When rendering in a server-side environment, the location should simply
|
1581
|
+
* be the URL path that was used in the request, including the query string.
|
1582
|
+
*/
|
1583
|
+
function createRouter(options) {
|
1584
|
+
options = options || {};
|
1585
|
+
|
1586
|
+
if (typeof options === 'function') {
|
1587
|
+
options = { routes: options }; // Router.create(<Route>)
|
1588
|
+
} else if (Array.isArray(options)) {
|
1589
|
+
options = { routes: options }; // Router.create([ <Route>, <Route> ])
|
1590
|
+
}
|
1591
|
+
|
1592
|
+
var routes = [];
|
1593
|
+
var namedRoutes = {};
|
1594
|
+
var components = [];
|
1595
|
+
var location = options.location || DEFAULT_LOCATION;
|
1596
|
+
var scrollBehavior = options.scrollBehavior || DEFAULT_SCROLL_BEHAVIOR;
|
1597
|
+
var onError = options.onError || defaultErrorHandler;
|
1598
|
+
var onAbort = options.onAbort || defaultAbortHandler;
|
1599
|
+
var state = {};
|
1600
|
+
var nextState = {};
|
1601
|
+
var pendingTransition = null;
|
1602
|
+
|
1603
|
+
function updateState() {
|
1604
|
+
state = nextState;
|
1605
|
+
nextState = {};
|
1606
|
+
}
|
1607
|
+
|
1608
|
+
if (typeof location === 'string') {
|
1609
|
+
warning(
|
1610
|
+
!canUseDOM || "production" === 'test',
|
1611
|
+
'You should not use a static location in a DOM environment because ' +
|
1612
|
+
'the router will not be kept in sync with the current URL'
|
1613
|
+
);
|
1614
|
+
} else {
|
1615
|
+
invariant(
|
1616
|
+
canUseDOM,
|
1617
|
+
'You cannot use %s without a DOM',
|
1618
|
+
location
|
1619
|
+
);
|
1620
|
+
}
|
1621
|
+
|
1622
|
+
// Automatically fall back to full page refreshes in
|
1623
|
+
// browsers that don't support the HTML history API.
|
1624
|
+
if (location === HistoryLocation && !supportsHistory())
|
1625
|
+
location = RefreshLocation;
|
1626
|
+
|
1627
|
+
var router = React.createClass({
|
1628
|
+
|
1629
|
+
displayName: 'Router',
|
1630
|
+
|
1631
|
+
mixins: [ NavigationContext, StateContext, Scrolling ],
|
1632
|
+
|
1633
|
+
statics: {
|
1634
|
+
|
1635
|
+
defaultRoute: null,
|
1636
|
+
notFoundRoute: null,
|
1637
|
+
|
1638
|
+
/**
|
1639
|
+
* Adds routes to this router from the given children object (see ReactChildren).
|
1640
|
+
*/
|
1641
|
+
addRoutes: function (children) {
|
1642
|
+
routes.push.apply(routes, createRoutesFromChildren(children, this, namedRoutes));
|
1643
|
+
},
|
1644
|
+
|
1645
|
+
/**
|
1646
|
+
* Returns an absolute URL path created from the given route
|
1647
|
+
* name, URL parameters, and query.
|
1648
|
+
*/
|
1649
|
+
makePath: function (to, params, query) {
|
1650
|
+
var path;
|
1651
|
+
if (Path.isAbsolute(to)) {
|
1652
|
+
path = Path.normalize(to);
|
1653
|
+
} else {
|
1654
|
+
var route = namedRoutes[to];
|
1655
|
+
|
1656
|
+
invariant(
|
1657
|
+
route,
|
1658
|
+
'Unable to find <Route name="%s">',
|
1659
|
+
to
|
1660
|
+
);
|
1661
|
+
|
1662
|
+
path = route.path;
|
1663
|
+
}
|
1664
|
+
|
1665
|
+
return Path.withQuery(Path.injectParams(path, params), query);
|
1666
|
+
},
|
1667
|
+
|
1668
|
+
/**
|
1669
|
+
* Returns a string that may safely be used as the href of a link
|
1670
|
+
* to the route with the given name, URL parameters, and query.
|
1671
|
+
*/
|
1672
|
+
makeHref: function (to, params, query) {
|
1673
|
+
var path = this.makePath(to, params, query);
|
1674
|
+
return (location === HashLocation) ? '#' + path : path;
|
1675
|
+
},
|
1676
|
+
|
1677
|
+
/**
|
1678
|
+
* Transitions to the URL specified in the arguments by pushing
|
1679
|
+
* a new URL onto the history stack.
|
1680
|
+
*/
|
1681
|
+
transitionTo: function (to, params, query) {
|
1682
|
+
invariant(
|
1683
|
+
typeof location !== 'string',
|
1684
|
+
'You cannot use transitionTo with a static location'
|
1685
|
+
);
|
1686
|
+
|
1687
|
+
var path = this.makePath(to, params, query);
|
1688
|
+
|
1689
|
+
if (pendingTransition) {
|
1690
|
+
// Replace so pending location does not stay in history.
|
1691
|
+
location.replace(path);
|
1692
|
+
} else {
|
1693
|
+
location.push(path);
|
1694
|
+
}
|
1695
|
+
},
|
1696
|
+
|
1697
|
+
/**
|
1698
|
+
* Transitions to the URL specified in the arguments by replacing
|
1699
|
+
* the current URL in the history stack.
|
1700
|
+
*/
|
1701
|
+
replaceWith: function (to, params, query) {
|
1702
|
+
invariant(
|
1703
|
+
typeof location !== 'string',
|
1704
|
+
'You cannot use replaceWith with a static location'
|
1705
|
+
);
|
1706
|
+
|
1707
|
+
location.replace(this.makePath(to, params, query));
|
1708
|
+
},
|
1709
|
+
|
1710
|
+
/**
|
1711
|
+
* Transitions to the previous URL if one is available. Returns true if the
|
1712
|
+
* router was able to go back, false otherwise.
|
1713
|
+
*
|
1714
|
+
* Note: The router only tracks history entries in your application, not the
|
1715
|
+
* current browser session, so you can safely call this function without guarding
|
1716
|
+
* against sending the user back to some other site. However, when using
|
1717
|
+
* RefreshLocation (which is the fallback for HistoryLocation in browsers that
|
1718
|
+
* don't support HTML5 history) this method will *always* send the client back
|
1719
|
+
* because we cannot reliably track history length.
|
1720
|
+
*/
|
1721
|
+
goBack: function () {
|
1722
|
+
invariant(
|
1723
|
+
typeof location !== 'string',
|
1724
|
+
'You cannot use goBack with a static location'
|
1725
|
+
);
|
1726
|
+
|
1727
|
+
if (History.length > 1 || location === RefreshLocation) {
|
1728
|
+
location.pop();
|
1729
|
+
return true;
|
1730
|
+
}
|
1731
|
+
|
1732
|
+
warning(false, 'goBack() was ignored because there is no router history');
|
1733
|
+
|
1734
|
+
return false;
|
1735
|
+
},
|
1736
|
+
|
1737
|
+
/**
|
1738
|
+
* Performs a match of the given pathname against this router and returns an object
|
1739
|
+
* with the { routes, params } that match. Returns null if no match can be made.
|
1740
|
+
*/
|
1741
|
+
match: function (pathname) {
|
1742
|
+
return findMatch(pathname, routes, this.defaultRoute, this.notFoundRoute) || null;
|
1743
|
+
},
|
1744
|
+
|
1745
|
+
/**
|
1746
|
+
* Performs a transition to the given path and calls callback(error, abortReason)
|
1747
|
+
* when the transition is finished. If both arguments are null the router's state
|
1748
|
+
* was updated. Otherwise the transition did not complete.
|
1749
|
+
*
|
1750
|
+
* In a transition, a router first determines which routes are involved by beginning
|
1751
|
+
* with the current route, up the route tree to the first parent route that is shared
|
1752
|
+
* with the destination route, and back down the tree to the destination route. The
|
1753
|
+
* willTransitionFrom hook is invoked on all route handlers we're transitioning away
|
1754
|
+
* from, in reverse nesting order. Likewise, the willTransitionTo hook is invoked on
|
1755
|
+
* all route handlers we're transitioning to.
|
1756
|
+
*
|
1757
|
+
* Both willTransitionFrom and willTransitionTo hooks may either abort or redirect the
|
1758
|
+
* transition. To resolve asynchronously, they may use transition.wait(promise). If no
|
1759
|
+
* hooks wait, the transition is fully synchronous.
|
1760
|
+
*/
|
1761
|
+
dispatch: function (path, action, callback) {
|
1762
|
+
if (pendingTransition) {
|
1763
|
+
pendingTransition.abort(new Cancellation);
|
1764
|
+
pendingTransition = null;
|
1765
|
+
}
|
1766
|
+
|
1767
|
+
var prevPath = state.path;
|
1768
|
+
if (prevPath === path)
|
1769
|
+
return; // Nothing to do!
|
1770
|
+
|
1771
|
+
// Record the scroll position as early as possible to
|
1772
|
+
// get it before browsers try update it automatically.
|
1773
|
+
if (prevPath && action !== LocationActions.REPLACE)
|
1774
|
+
this.recordScrollPosition(prevPath);
|
1775
|
+
|
1776
|
+
var pathname = Path.withoutQuery(path);
|
1777
|
+
var match = this.match(pathname);
|
1778
|
+
|
1779
|
+
warning(
|
1780
|
+
match != null,
|
1781
|
+
'No route matches path "%s". Make sure you have <Route path="%s"> somewhere in your routes',
|
1782
|
+
path, path
|
1783
|
+
);
|
1784
|
+
|
1785
|
+
if (match == null)
|
1786
|
+
match = {};
|
1787
|
+
|
1788
|
+
var prevRoutes = state.routes || [];
|
1789
|
+
var prevParams = state.params || {};
|
1790
|
+
var prevQuery = state.query || {};
|
1791
|
+
|
1792
|
+
var nextRoutes = match.routes || [];
|
1793
|
+
var nextParams = match.params || {};
|
1794
|
+
var nextQuery = Path.extractQuery(path) || {};
|
1795
|
+
|
1796
|
+
var fromRoutes, toRoutes;
|
1797
|
+
if (prevRoutes.length) {
|
1798
|
+
fromRoutes = prevRoutes.filter(function (route) {
|
1799
|
+
return !hasMatch(nextRoutes, route, prevParams, nextParams, prevQuery, nextQuery);
|
1800
|
+
});
|
1801
|
+
|
1802
|
+
toRoutes = nextRoutes.filter(function (route) {
|
1803
|
+
return !hasMatch(prevRoutes, route, prevParams, nextParams, prevQuery, nextQuery);
|
1804
|
+
});
|
1805
|
+
} else {
|
1806
|
+
fromRoutes = [];
|
1807
|
+
toRoutes = nextRoutes;
|
1808
|
+
}
|
1809
|
+
|
1810
|
+
var transition = new Transition(path, this.replaceWith.bind(this, path));
|
1811
|
+
pendingTransition = transition;
|
1812
|
+
|
1813
|
+
transition.from(fromRoutes, components, function (error) {
|
1814
|
+
if (error || transition.isAborted)
|
1815
|
+
return callback.call(router, error, transition);
|
1816
|
+
|
1817
|
+
transition.to(toRoutes, nextParams, nextQuery, function (error) {
|
1818
|
+
if (error || transition.isAborted)
|
1819
|
+
return callback.call(router, error, transition);
|
1820
|
+
|
1821
|
+
nextState.path = path;
|
1822
|
+
nextState.action = action;
|
1823
|
+
nextState.pathname = pathname;
|
1824
|
+
nextState.routes = nextRoutes;
|
1825
|
+
nextState.params = nextParams;
|
1826
|
+
nextState.query = nextQuery;
|
1827
|
+
|
1828
|
+
callback.call(router, null, transition);
|
1829
|
+
});
|
1830
|
+
});
|
1831
|
+
},
|
1832
|
+
|
1833
|
+
/**
|
1834
|
+
* Starts this router and calls callback(router, state) when the route changes.
|
1835
|
+
*
|
1836
|
+
* If the router's location is static (i.e. a URL path in a server environment)
|
1837
|
+
* the callback is called only once. Otherwise, the location should be one of the
|
1838
|
+
* Router.*Location objects (e.g. Router.HashLocation or Router.HistoryLocation).
|
1839
|
+
*/
|
1840
|
+
run: function (callback) {
|
1841
|
+
var dispatchHandler = function (error, transition) {
|
1842
|
+
pendingTransition = null;
|
1843
|
+
|
1844
|
+
if (error) {
|
1845
|
+
onError.call(router, error);
|
1846
|
+
} else if (transition.isAborted) {
|
1847
|
+
onAbort.call(router, transition.abortReason, location);
|
1848
|
+
} else {
|
1849
|
+
callback.call(router, router, nextState);
|
1850
|
+
}
|
1851
|
+
};
|
1852
|
+
|
1853
|
+
if (typeof location === 'string') {
|
1854
|
+
router.dispatch(location, null, dispatchHandler);
|
1855
|
+
} else {
|
1856
|
+
// Listen for changes to the location.
|
1857
|
+
var changeListener = function (change) {
|
1858
|
+
router.dispatch(change.path, change.type, dispatchHandler);
|
1859
|
+
};
|
1860
|
+
|
1861
|
+
if (location.addChangeListener)
|
1862
|
+
location.addChangeListener(changeListener);
|
1863
|
+
|
1864
|
+
// Bootstrap using the current path.
|
1865
|
+
router.dispatch(location.getCurrentPath(), null, dispatchHandler);
|
1866
|
+
}
|
1867
|
+
},
|
1868
|
+
|
1869
|
+
teardown: function() {
|
1870
|
+
location.removeChangeListener(this.changeListener);
|
1871
|
+
}
|
1872
|
+
|
1873
|
+
},
|
1874
|
+
|
1875
|
+
propTypes: {
|
1876
|
+
children: PropTypes.falsy
|
1877
|
+
},
|
1878
|
+
|
1879
|
+
getLocation: function () {
|
1880
|
+
return location;
|
1881
|
+
},
|
1882
|
+
|
1883
|
+
getScrollBehavior: function () {
|
1884
|
+
return scrollBehavior;
|
1885
|
+
},
|
1886
|
+
|
1887
|
+
getRouteAtDepth: function (depth) {
|
1888
|
+
var routes = this.state.routes;
|
1889
|
+
return routes && routes[depth];
|
1890
|
+
},
|
1891
|
+
|
1892
|
+
getRouteComponents: function () {
|
1893
|
+
return components;
|
1894
|
+
},
|
1895
|
+
|
1896
|
+
getInitialState: function () {
|
1897
|
+
updateState();
|
1898
|
+
return state;
|
1899
|
+
},
|
1900
|
+
|
1901
|
+
componentWillReceiveProps: function () {
|
1902
|
+
updateState();
|
1903
|
+
this.setState(state);
|
1904
|
+
},
|
1905
|
+
|
1906
|
+
componentWillUnmount: function() {
|
1907
|
+
router.teardown();
|
1908
|
+
},
|
1909
|
+
|
1910
|
+
render: function () {
|
1911
|
+
return this.getRouteAtDepth(0) ? React.createElement(RouteHandler, this.props) : null;
|
1912
|
+
},
|
1913
|
+
|
1914
|
+
childContextTypes: {
|
1915
|
+
getRouteAtDepth: React.PropTypes.func.isRequired,
|
1916
|
+
getRouteComponents: React.PropTypes.func.isRequired,
|
1917
|
+
routeHandlers: React.PropTypes.array.isRequired
|
1918
|
+
},
|
1919
|
+
|
1920
|
+
getChildContext: function () {
|
1921
|
+
return {
|
1922
|
+
getRouteComponents: this.getRouteComponents,
|
1923
|
+
getRouteAtDepth: this.getRouteAtDepth,
|
1924
|
+
routeHandlers: [ this ]
|
1925
|
+
};
|
1926
|
+
}
|
1927
|
+
|
1928
|
+
});
|
1929
|
+
|
1930
|
+
if (options.routes)
|
1931
|
+
router.addRoutes(options.routes);
|
1932
|
+
|
1933
|
+
return router;
|
1934
|
+
}
|
1935
|
+
|
1936
|
+
module.exports = createRouter;
|
1937
|
+
|
1938
|
+
},{"../actions/LocationActions":1,"../behaviors/ImitateBrowserBehavior":2,"../components/RouteHandler":9,"../locations/HashLocation":11,"../locations/HistoryLocation":12,"../locations/RefreshLocation":13,"../mixins/NavigationContext":16,"../mixins/Scrolling":18,"../mixins/StateContext":20,"./Cancellation":21,"./History":22,"./Path":23,"./PropTypes":25,"./Redirect":26,"./Transition":27,"./createRoutesFromChildren":29,"./supportsHistory":33,"react/lib/ExecutionEnvironment":39,"react/lib/invariant":43,"react/lib/warning":44}],29:[function(_dereq_,module,exports){
|
1939
|
+
/* jshint -W084 */
|
1940
|
+
var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null);
|
1941
|
+
var warning = _dereq_('react/lib/warning');
|
1942
|
+
var invariant = _dereq_('react/lib/invariant');
|
1943
|
+
var DefaultRoute = _dereq_('../components/DefaultRoute');
|
1944
|
+
var NotFoundRoute = _dereq_('../components/NotFoundRoute');
|
1945
|
+
var Redirect = _dereq_('../components/Redirect');
|
1946
|
+
var Route = _dereq_('../components/Route');
|
1947
|
+
var Path = _dereq_('./Path');
|
1948
|
+
|
1949
|
+
var CONFIG_ELEMENT_TYPES = [
|
1950
|
+
DefaultRoute.type,
|
1951
|
+
NotFoundRoute.type,
|
1952
|
+
Redirect.type,
|
1953
|
+
Route.type
|
1954
|
+
];
|
1955
|
+
|
1956
|
+
function createRedirectHandler(to, _params, _query) {
|
1957
|
+
return React.createClass({
|
1958
|
+
statics: {
|
1959
|
+
willTransitionTo: function (transition, params, query) {
|
1960
|
+
transition.redirect(to, _params || params, _query || query);
|
1961
|
+
}
|
1962
|
+
},
|
1963
|
+
|
1964
|
+
render: function () {
|
1965
|
+
return null;
|
1966
|
+
}
|
1967
|
+
});
|
1968
|
+
}
|
1969
|
+
|
1970
|
+
function checkPropTypes(componentName, propTypes, props) {
|
1971
|
+
for (var propName in propTypes) {
|
1972
|
+
if (propTypes.hasOwnProperty(propName)) {
|
1973
|
+
var error = propTypes[propName](props, propName, componentName);
|
1974
|
+
|
1975
|
+
if (error instanceof Error)
|
1976
|
+
warning(false, error.message);
|
1977
|
+
}
|
1978
|
+
}
|
1979
|
+
}
|
1980
|
+
|
1981
|
+
function createRoute(element, parentRoute, namedRoutes) {
|
1982
|
+
var type = element.type;
|
1983
|
+
var props = element.props;
|
1984
|
+
var componentName = (type && type.displayName) || 'UnknownComponent';
|
1985
|
+
|
1986
|
+
invariant(
|
1987
|
+
CONFIG_ELEMENT_TYPES.indexOf(type) !== -1,
|
1988
|
+
'Unrecognized route configuration element "<%s>"',
|
1989
|
+
componentName
|
1990
|
+
);
|
1991
|
+
|
1992
|
+
if (type.propTypes)
|
1993
|
+
checkPropTypes(componentName, type.propTypes, props);
|
1994
|
+
|
1995
|
+
var route = { name: props.name };
|
1996
|
+
|
1997
|
+
if (props.ignoreScrollBehavior) {
|
1998
|
+
route.ignoreScrollBehavior = true;
|
1999
|
+
}
|
2000
|
+
|
2001
|
+
if (type === Redirect.type) {
|
2002
|
+
route.handler = createRedirectHandler(props.to, props.params, props.query);
|
2003
|
+
props.path = props.path || props.from || '*';
|
2004
|
+
} else {
|
2005
|
+
route.handler = props.handler;
|
2006
|
+
}
|
2007
|
+
|
2008
|
+
var parentPath = (parentRoute && parentRoute.path) || '/';
|
2009
|
+
|
2010
|
+
if ((props.path || props.name) && type !== DefaultRoute.type && type !== NotFoundRoute.type) {
|
2011
|
+
var path = props.path || props.name;
|
2012
|
+
|
2013
|
+
// Relative paths extend their parent.
|
2014
|
+
if (!Path.isAbsolute(path))
|
2015
|
+
path = Path.join(parentPath, path);
|
2016
|
+
|
2017
|
+
route.path = Path.normalize(path);
|
2018
|
+
} else {
|
2019
|
+
route.path = parentPath;
|
2020
|
+
|
2021
|
+
if (type === NotFoundRoute.type)
|
2022
|
+
route.path += '*';
|
2023
|
+
}
|
2024
|
+
|
2025
|
+
route.paramNames = Path.extractParamNames(route.path);
|
2026
|
+
|
2027
|
+
// Make sure the route's path has all params its parent needs.
|
2028
|
+
if (parentRoute && Array.isArray(parentRoute.paramNames)) {
|
2029
|
+
parentRoute.paramNames.forEach(function (paramName) {
|
2030
|
+
invariant(
|
2031
|
+
route.paramNames.indexOf(paramName) !== -1,
|
2032
|
+
'The nested route path "%s" is missing the "%s" parameter of its parent path "%s"',
|
2033
|
+
route.path, paramName, parentRoute.path
|
2034
|
+
);
|
2035
|
+
});
|
2036
|
+
}
|
2037
|
+
|
2038
|
+
// Make sure the route can be looked up by <Link>s.
|
2039
|
+
if (props.name) {
|
2040
|
+
invariant(
|
2041
|
+
namedRoutes[props.name] == null,
|
2042
|
+
'You cannot use the name "%s" for more than one route',
|
2043
|
+
props.name
|
2044
|
+
);
|
2045
|
+
|
2046
|
+
namedRoutes[props.name] = route;
|
2047
|
+
}
|
2048
|
+
|
2049
|
+
// Handle <NotFoundRoute>.
|
2050
|
+
if (type === NotFoundRoute.type) {
|
2051
|
+
invariant(
|
2052
|
+
parentRoute,
|
2053
|
+
'<NotFoundRoute> must have a parent <Route>'
|
2054
|
+
);
|
2055
|
+
|
2056
|
+
invariant(
|
2057
|
+
parentRoute.notFoundRoute == null,
|
2058
|
+
'You may not have more than one <NotFoundRoute> per <Route>'
|
2059
|
+
);
|
2060
|
+
|
2061
|
+
parentRoute.notFoundRoute = route;
|
2062
|
+
|
2063
|
+
return null;
|
2064
|
+
}
|
2065
|
+
|
2066
|
+
// Handle <DefaultRoute>.
|
2067
|
+
if (type === DefaultRoute.type) {
|
2068
|
+
invariant(
|
2069
|
+
parentRoute,
|
2070
|
+
'<DefaultRoute> must have a parent <Route>'
|
2071
|
+
);
|
2072
|
+
|
2073
|
+
invariant(
|
2074
|
+
parentRoute.defaultRoute == null,
|
2075
|
+
'You may not have more than one <DefaultRoute> per <Route>'
|
2076
|
+
);
|
2077
|
+
|
2078
|
+
parentRoute.defaultRoute = route;
|
2079
|
+
|
2080
|
+
return null;
|
2081
|
+
}
|
2082
|
+
|
2083
|
+
route.childRoutes = createRoutesFromChildren(props.children, route, namedRoutes);
|
2084
|
+
|
2085
|
+
return route;
|
2086
|
+
}
|
2087
|
+
|
2088
|
+
/**
|
2089
|
+
* Creates and returns an array of route objects from the given ReactChildren.
|
2090
|
+
*/
|
2091
|
+
function createRoutesFromChildren(children, parentRoute, namedRoutes) {
|
2092
|
+
var routes = [];
|
2093
|
+
|
2094
|
+
React.Children.forEach(children, function (child) {
|
2095
|
+
// Exclude <DefaultRoute>s and <NotFoundRoute>s.
|
2096
|
+
if (child = createRoute(child, parentRoute, namedRoutes))
|
2097
|
+
routes.push(child);
|
2098
|
+
});
|
2099
|
+
|
2100
|
+
return routes;
|
2101
|
+
}
|
2102
|
+
|
2103
|
+
module.exports = createRoutesFromChildren;
|
2104
|
+
|
2105
|
+
},{"../components/DefaultRoute":4,"../components/NotFoundRoute":6,"../components/Redirect":7,"../components/Route":8,"./Path":23,"react/lib/invariant":43,"react/lib/warning":44}],30:[function(_dereq_,module,exports){
|
2106
|
+
var invariant = _dereq_('react/lib/invariant');
|
2107
|
+
var canUseDOM = _dereq_('react/lib/ExecutionEnvironment').canUseDOM;
|
2108
|
+
|
2109
|
+
/**
|
2110
|
+
* Returns the current scroll position of the window as { x, y }.
|
2111
|
+
*/
|
2112
|
+
function getWindowScrollPosition() {
|
2113
|
+
invariant(
|
2114
|
+
canUseDOM,
|
2115
|
+
'Cannot get current scroll position without a DOM'
|
2116
|
+
);
|
2117
|
+
|
2118
|
+
return {
|
2119
|
+
x: window.pageXOffset || document.documentElement.scrollLeft,
|
2120
|
+
y: window.pageYOffset || document.documentElement.scrollTop
|
2121
|
+
};
|
2122
|
+
}
|
2123
|
+
|
2124
|
+
module.exports = getWindowScrollPosition;
|
2125
|
+
|
2126
|
+
},{"react/lib/ExecutionEnvironment":39,"react/lib/invariant":43}],31:[function(_dereq_,module,exports){
|
2127
|
+
function reversedArray(array) {
|
2128
|
+
return array.slice(0).reverse();
|
2129
|
+
}
|
2130
|
+
|
2131
|
+
module.exports = reversedArray;
|
2132
|
+
|
2133
|
+
},{}],32:[function(_dereq_,module,exports){
|
2134
|
+
var createRouter = _dereq_('./createRouter');
|
2135
|
+
|
2136
|
+
/**
|
2137
|
+
* A high-level convenience method that creates, configures, and
|
2138
|
+
* runs a router in one shot. The method signature is:
|
2139
|
+
*
|
2140
|
+
* Router.run(routes[, location ], callback);
|
2141
|
+
*
|
2142
|
+
* Using `window.location.hash` to manage the URL, you could do:
|
2143
|
+
*
|
2144
|
+
* Router.run(routes, function (Handler) {
|
2145
|
+
* React.render(<Handler/>, document.body);
|
2146
|
+
* });
|
2147
|
+
*
|
2148
|
+
* Using HTML5 history and a custom "cursor" prop:
|
2149
|
+
*
|
2150
|
+
* Router.run(routes, Router.HistoryLocation, function (Handler) {
|
2151
|
+
* React.render(<Handler cursor={cursor}/>, document.body);
|
2152
|
+
* });
|
2153
|
+
*
|
2154
|
+
* Returns the newly created router.
|
2155
|
+
*
|
2156
|
+
* Note: If you need to specify further options for your router such
|
2157
|
+
* as error/abort handling or custom scroll behavior, use Router.create
|
2158
|
+
* instead.
|
2159
|
+
*
|
2160
|
+
* var router = Router.create(options);
|
2161
|
+
* router.run(function (Handler) {
|
2162
|
+
* // ...
|
2163
|
+
* });
|
2164
|
+
*/
|
2165
|
+
function runRouter(routes, location, callback) {
|
2166
|
+
if (typeof location === 'function') {
|
2167
|
+
callback = location;
|
2168
|
+
location = null;
|
2169
|
+
}
|
2170
|
+
|
2171
|
+
var router = createRouter({
|
2172
|
+
routes: routes,
|
2173
|
+
location: location
|
2174
|
+
});
|
2175
|
+
|
2176
|
+
router.run(callback);
|
2177
|
+
|
2178
|
+
return router;
|
2179
|
+
}
|
2180
|
+
|
2181
|
+
module.exports = runRouter;
|
2182
|
+
|
2183
|
+
},{"./createRouter":28}],33:[function(_dereq_,module,exports){
|
2184
|
+
function supportsHistory() {
|
2185
|
+
/*! taken from modernizr
|
2186
|
+
* https://github.com/Modernizr/Modernizr/blob/master/LICENSE
|
2187
|
+
* https://github.com/Modernizr/Modernizr/blob/master/feature-detects/history.js
|
2188
|
+
* changed to avoid false negatives for Windows Phones: https://github.com/rackt/react-router/issues/586
|
2189
|
+
*/
|
2190
|
+
var ua = navigator.userAgent;
|
2191
|
+
if ((ua.indexOf('Android 2.') !== -1 ||
|
2192
|
+
(ua.indexOf('Android 4.0') !== -1)) &&
|
2193
|
+
ua.indexOf('Mobile Safari') !== -1 &&
|
2194
|
+
ua.indexOf('Chrome') === -1 &&
|
2195
|
+
ua.indexOf('Windows Phone') === -1) {
|
2196
|
+
return false;
|
2197
|
+
}
|
2198
|
+
return (window.history && 'pushState' in window.history);
|
2199
|
+
}
|
2200
|
+
|
2201
|
+
module.exports = supportsHistory;
|
2202
|
+
|
2203
|
+
},{}],34:[function(_dereq_,module,exports){
|
2204
|
+
module.exports = _dereq_('./lib');
|
2205
|
+
|
2206
|
+
},{"./lib":35}],35:[function(_dereq_,module,exports){
|
2207
|
+
// Load modules
|
2208
|
+
|
2209
|
+
var Stringify = _dereq_('./stringify');
|
2210
|
+
var Parse = _dereq_('./parse');
|
2211
|
+
|
2212
|
+
|
2213
|
+
// Declare internals
|
2214
|
+
|
2215
|
+
var internals = {};
|
2216
|
+
|
2217
|
+
|
2218
|
+
module.exports = {
|
2219
|
+
stringify: Stringify,
|
2220
|
+
parse: Parse
|
2221
|
+
};
|
2222
|
+
|
2223
|
+
},{"./parse":36,"./stringify":37}],36:[function(_dereq_,module,exports){
|
2224
|
+
// Load modules
|
2225
|
+
|
2226
|
+
var Utils = _dereq_('./utils');
|
2227
|
+
|
2228
|
+
|
2229
|
+
// Declare internals
|
2230
|
+
|
2231
|
+
var internals = {
|
2232
|
+
delimiter: '&',
|
2233
|
+
depth: 5,
|
2234
|
+
arrayLimit: 20,
|
2235
|
+
parameterLimit: 1000
|
2236
|
+
};
|
2237
|
+
|
2238
|
+
|
2239
|
+
internals.parseValues = function (str, options) {
|
2240
|
+
|
2241
|
+
var obj = {};
|
2242
|
+
var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit);
|
2243
|
+
|
2244
|
+
for (var i = 0, il = parts.length; i < il; ++i) {
|
2245
|
+
var part = parts[i];
|
2246
|
+
var pos = part.indexOf(']=') === -1 ? part.indexOf('=') : part.indexOf(']=') + 1;
|
2247
|
+
|
2248
|
+
if (pos === -1) {
|
2249
|
+
obj[Utils.decode(part)] = '';
|
2250
|
+
}
|
2251
|
+
else {
|
2252
|
+
var key = Utils.decode(part.slice(0, pos));
|
2253
|
+
var val = Utils.decode(part.slice(pos + 1));
|
2254
|
+
|
2255
|
+
if (!obj[key]) {
|
2256
|
+
obj[key] = val;
|
2257
|
+
}
|
2258
|
+
else {
|
2259
|
+
obj[key] = [].concat(obj[key]).concat(val);
|
2260
|
+
}
|
2261
|
+
}
|
2262
|
+
}
|
2263
|
+
|
2264
|
+
return obj;
|
2265
|
+
};
|
2266
|
+
|
2267
|
+
|
2268
|
+
internals.parseObject = function (chain, val, options) {
|
2269
|
+
|
2270
|
+
if (!chain.length) {
|
2271
|
+
return val;
|
2272
|
+
}
|
2273
|
+
|
2274
|
+
var root = chain.shift();
|
2275
|
+
|
2276
|
+
var obj = {};
|
2277
|
+
if (root === '[]') {
|
2278
|
+
obj = [];
|
2279
|
+
obj = obj.concat(internals.parseObject(chain, val, options));
|
2280
|
+
}
|
2281
|
+
else {
|
2282
|
+
var cleanRoot = root[0] === '[' && root[root.length - 1] === ']' ? root.slice(1, root.length - 1) : root;
|
2283
|
+
var index = parseInt(cleanRoot, 10);
|
2284
|
+
if (!isNaN(index) &&
|
2285
|
+
root !== cleanRoot &&
|
2286
|
+
index <= options.arrayLimit) {
|
2287
|
+
|
2288
|
+
obj = [];
|
2289
|
+
obj[index] = internals.parseObject(chain, val, options);
|
2290
|
+
}
|
2291
|
+
else {
|
2292
|
+
obj[cleanRoot] = internals.parseObject(chain, val, options);
|
2293
|
+
}
|
2294
|
+
}
|
2295
|
+
|
2296
|
+
return obj;
|
2297
|
+
};
|
2298
|
+
|
2299
|
+
|
2300
|
+
internals.parseKeys = function (key, val, options) {
|
2301
|
+
|
2302
|
+
if (!key) {
|
2303
|
+
return;
|
2304
|
+
}
|
2305
|
+
|
2306
|
+
// The regex chunks
|
2307
|
+
|
2308
|
+
var parent = /^([^\[\]]*)/;
|
2309
|
+
var child = /(\[[^\[\]]*\])/g;
|
2310
|
+
|
2311
|
+
// Get the parent
|
2312
|
+
|
2313
|
+
var segment = parent.exec(key);
|
2314
|
+
|
2315
|
+
// Don't allow them to overwrite object prototype properties
|
2316
|
+
|
2317
|
+
if (Object.prototype.hasOwnProperty(segment[1])) {
|
2318
|
+
return;
|
2319
|
+
}
|
2320
|
+
|
2321
|
+
// Stash the parent if it exists
|
2322
|
+
|
2323
|
+
var keys = [];
|
2324
|
+
if (segment[1]) {
|
2325
|
+
keys.push(segment[1]);
|
2326
|
+
}
|
2327
|
+
|
2328
|
+
// Loop through children appending to the array until we hit depth
|
2329
|
+
|
2330
|
+
var i = 0;
|
2331
|
+
while ((segment = child.exec(key)) !== null && i < options.depth) {
|
2332
|
+
|
2333
|
+
++i;
|
2334
|
+
if (!Object.prototype.hasOwnProperty(segment[1].replace(/\[|\]/g, ''))) {
|
2335
|
+
keys.push(segment[1]);
|
2336
|
+
}
|
2337
|
+
}
|
2338
|
+
|
2339
|
+
// If there's a remainder, just add whatever is left
|
2340
|
+
|
2341
|
+
if (segment) {
|
2342
|
+
keys.push('[' + key.slice(segment.index) + ']');
|
2343
|
+
}
|
2344
|
+
|
2345
|
+
return internals.parseObject(keys, val, options);
|
2346
|
+
};
|
2347
|
+
|
2348
|
+
|
2349
|
+
module.exports = function (str, options) {
|
2350
|
+
|
2351
|
+
if (str === '' ||
|
2352
|
+
str === null ||
|
2353
|
+
typeof str === 'undefined') {
|
2354
|
+
|
2355
|
+
return {};
|
2356
|
+
}
|
2357
|
+
|
2358
|
+
options = options || {};
|
2359
|
+
options.delimiter = typeof options.delimiter === 'string' || Utils.isRegExp(options.delimiter) ? options.delimiter : internals.delimiter;
|
2360
|
+
options.depth = typeof options.depth === 'number' ? options.depth : internals.depth;
|
2361
|
+
options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : internals.arrayLimit;
|
2362
|
+
options.parameterLimit = typeof options.parameterLimit === 'number' ? options.parameterLimit : internals.parameterLimit;
|
2363
|
+
|
2364
|
+
var tempObj = typeof str === 'string' ? internals.parseValues(str, options) : str;
|
2365
|
+
var obj = {};
|
2366
|
+
|
2367
|
+
// Iterate over the keys and setup the new object
|
2368
|
+
|
2369
|
+
var keys = Object.keys(tempObj);
|
2370
|
+
for (var i = 0, il = keys.length; i < il; ++i) {
|
2371
|
+
var key = keys[i];
|
2372
|
+
var newObj = internals.parseKeys(key, tempObj[key], options);
|
2373
|
+
obj = Utils.merge(obj, newObj);
|
2374
|
+
}
|
2375
|
+
|
2376
|
+
return Utils.compact(obj);
|
2377
|
+
};
|
2378
|
+
|
2379
|
+
},{"./utils":38}],37:[function(_dereq_,module,exports){
|
2380
|
+
// Load modules
|
2381
|
+
|
2382
|
+
var Utils = _dereq_('./utils');
|
2383
|
+
|
2384
|
+
|
2385
|
+
// Declare internals
|
2386
|
+
|
2387
|
+
var internals = {
|
2388
|
+
delimiter: '&'
|
2389
|
+
};
|
2390
|
+
|
2391
|
+
|
2392
|
+
internals.stringify = function (obj, prefix) {
|
2393
|
+
|
2394
|
+
if (Utils.isBuffer(obj)) {
|
2395
|
+
obj = obj.toString();
|
2396
|
+
}
|
2397
|
+
else if (obj instanceof Date) {
|
2398
|
+
obj = obj.toISOString();
|
2399
|
+
}
|
2400
|
+
else if (obj === null) {
|
2401
|
+
obj = '';
|
2402
|
+
}
|
2403
|
+
|
2404
|
+
if (typeof obj === 'string' ||
|
2405
|
+
typeof obj === 'number' ||
|
2406
|
+
typeof obj === 'boolean') {
|
2407
|
+
|
2408
|
+
return [encodeURIComponent(prefix) + '=' + encodeURIComponent(obj)];
|
2409
|
+
}
|
2410
|
+
|
2411
|
+
var values = [];
|
2412
|
+
|
2413
|
+
for (var key in obj) {
|
2414
|
+
if (obj.hasOwnProperty(key)) {
|
2415
|
+
values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']'));
|
2416
|
+
}
|
2417
|
+
}
|
2418
|
+
|
2419
|
+
return values;
|
2420
|
+
};
|
2421
|
+
|
2422
|
+
|
2423
|
+
module.exports = function (obj, options) {
|
2424
|
+
|
2425
|
+
options = options || {};
|
2426
|
+
var delimiter = typeof options.delimiter === 'undefined' ? internals.delimiter : options.delimiter;
|
2427
|
+
|
2428
|
+
var keys = [];
|
2429
|
+
|
2430
|
+
for (var key in obj) {
|
2431
|
+
if (obj.hasOwnProperty(key)) {
|
2432
|
+
keys = keys.concat(internals.stringify(obj[key], key));
|
2433
|
+
}
|
2434
|
+
}
|
2435
|
+
|
2436
|
+
return keys.join(delimiter);
|
2437
|
+
};
|
2438
|
+
|
2439
|
+
},{"./utils":38}],38:[function(_dereq_,module,exports){
|
2440
|
+
// Load modules
|
2441
|
+
|
2442
|
+
|
2443
|
+
// Declare internals
|
2444
|
+
|
2445
|
+
var internals = {};
|
2446
|
+
|
2447
|
+
|
2448
|
+
exports.arrayToObject = function (source) {
|
2449
|
+
|
2450
|
+
var obj = {};
|
2451
|
+
for (var i = 0, il = source.length; i < il; ++i) {
|
2452
|
+
if (typeof source[i] !== 'undefined') {
|
2453
|
+
|
2454
|
+
obj[i] = source[i];
|
2455
|
+
}
|
2456
|
+
}
|
2457
|
+
|
2458
|
+
return obj;
|
2459
|
+
};
|
2460
|
+
|
2461
|
+
|
2462
|
+
exports.merge = function (target, source) {
|
2463
|
+
|
2464
|
+
if (!source) {
|
2465
|
+
return target;
|
2466
|
+
}
|
2467
|
+
|
2468
|
+
if (Array.isArray(source)) {
|
2469
|
+
for (var i = 0, il = source.length; i < il; ++i) {
|
2470
|
+
if (typeof source[i] !== 'undefined') {
|
2471
|
+
if (typeof target[i] === 'object') {
|
2472
|
+
target[i] = exports.merge(target[i], source[i]);
|
2473
|
+
}
|
2474
|
+
else {
|
2475
|
+
target[i] = source[i];
|
2476
|
+
}
|
2477
|
+
}
|
2478
|
+
}
|
2479
|
+
|
2480
|
+
return target;
|
2481
|
+
}
|
2482
|
+
|
2483
|
+
if (Array.isArray(target)) {
|
2484
|
+
if (typeof source !== 'object') {
|
2485
|
+
target.push(source);
|
2486
|
+
return target;
|
2487
|
+
}
|
2488
|
+
else {
|
2489
|
+
target = exports.arrayToObject(target);
|
2490
|
+
}
|
2491
|
+
}
|
2492
|
+
|
2493
|
+
var keys = Object.keys(source);
|
2494
|
+
for (var k = 0, kl = keys.length; k < kl; ++k) {
|
2495
|
+
var key = keys[k];
|
2496
|
+
var value = source[key];
|
2497
|
+
|
2498
|
+
if (value &&
|
2499
|
+
typeof value === 'object') {
|
2500
|
+
|
2501
|
+
if (!target[key]) {
|
2502
|
+
target[key] = value;
|
2503
|
+
}
|
2504
|
+
else {
|
2505
|
+
target[key] = exports.merge(target[key], value);
|
2506
|
+
}
|
2507
|
+
}
|
2508
|
+
else {
|
2509
|
+
target[key] = value;
|
2510
|
+
}
|
2511
|
+
}
|
2512
|
+
|
2513
|
+
return target;
|
2514
|
+
};
|
2515
|
+
|
2516
|
+
|
2517
|
+
exports.decode = function (str) {
|
2518
|
+
|
2519
|
+
try {
|
2520
|
+
return decodeURIComponent(str.replace(/\+/g, ' '));
|
2521
|
+
} catch (e) {
|
2522
|
+
return str;
|
2523
|
+
}
|
2524
|
+
};
|
2525
|
+
|
2526
|
+
|
2527
|
+
exports.compact = function (obj, refs) {
|
2528
|
+
|
2529
|
+
if (typeof obj !== 'object' ||
|
2530
|
+
obj === null) {
|
2531
|
+
|
2532
|
+
return obj;
|
2533
|
+
}
|
2534
|
+
|
2535
|
+
refs = refs || [];
|
2536
|
+
var lookup = refs.indexOf(obj);
|
2537
|
+
if (lookup !== -1) {
|
2538
|
+
return refs[lookup];
|
2539
|
+
}
|
2540
|
+
|
2541
|
+
refs.push(obj);
|
2542
|
+
|
2543
|
+
if (Array.isArray(obj)) {
|
2544
|
+
var compacted = [];
|
2545
|
+
|
2546
|
+
for (var i = 0, l = obj.length; i < l; ++i) {
|
2547
|
+
if (typeof obj[i] !== 'undefined') {
|
2548
|
+
compacted.push(obj[i]);
|
2549
|
+
}
|
2550
|
+
}
|
2551
|
+
|
2552
|
+
return compacted;
|
2553
|
+
}
|
2554
|
+
|
2555
|
+
var keys = Object.keys(obj);
|
2556
|
+
for (var i = 0, il = keys.length; i < il; ++i) {
|
2557
|
+
var key = keys[i];
|
2558
|
+
obj[key] = exports.compact(obj[key], refs);
|
2559
|
+
}
|
2560
|
+
|
2561
|
+
return obj;
|
2562
|
+
};
|
2563
|
+
|
2564
|
+
|
2565
|
+
exports.isRegExp = function (obj) {
|
2566
|
+
return Object.prototype.toString.call(obj) === '[object RegExp]';
|
2567
|
+
};
|
2568
|
+
|
2569
|
+
|
2570
|
+
exports.isBuffer = function (obj) {
|
2571
|
+
|
2572
|
+
if (typeof Buffer !== 'undefined') {
|
2573
|
+
return Buffer.isBuffer(obj);
|
2574
|
+
}
|
2575
|
+
else {
|
2576
|
+
return false;
|
2577
|
+
}
|
2578
|
+
};
|
2579
|
+
|
2580
|
+
},{}],39:[function(_dereq_,module,exports){
|
2581
|
+
/**
|
2582
|
+
* Copyright 2013-2014, Facebook, Inc.
|
2583
|
+
* All rights reserved.
|
2584
|
+
*
|
2585
|
+
* This source code is licensed under the BSD-style license found in the
|
2586
|
+
* LICENSE file in the root directory of this source tree. An additional grant
|
2587
|
+
* of patent rights can be found in the PATENTS file in the same directory.
|
2588
|
+
*
|
2589
|
+
* @providesModule ExecutionEnvironment
|
2590
|
+
*/
|
2591
|
+
|
2592
|
+
/*jslint evil: true */
|
2593
|
+
|
2594
|
+
"use strict";
|
2595
|
+
|
2596
|
+
var canUseDOM = !!(
|
2597
|
+
typeof window !== 'undefined' &&
|
2598
|
+
window.document &&
|
2599
|
+
window.document.createElement
|
2600
|
+
);
|
2601
|
+
|
2602
|
+
/**
|
2603
|
+
* Simple, lightweight module assisting with the detection and context of
|
2604
|
+
* Worker. Helps avoid circular dependencies and allows code to reason about
|
2605
|
+
* whether or not they are in a Worker, even if they never include the main
|
2606
|
+
* `ReactWorker` dependency.
|
2607
|
+
*/
|
2608
|
+
var ExecutionEnvironment = {
|
2609
|
+
|
2610
|
+
canUseDOM: canUseDOM,
|
2611
|
+
|
2612
|
+
canUseWorkers: typeof Worker !== 'undefined',
|
2613
|
+
|
2614
|
+
canUseEventListeners:
|
2615
|
+
canUseDOM && !!(window.addEventListener || window.attachEvent),
|
2616
|
+
|
2617
|
+
canUseViewport: canUseDOM && !!window.screen,
|
2618
|
+
|
2619
|
+
isInWorker: !canUseDOM // For now, this is true - might change in the future.
|
2620
|
+
|
2621
|
+
};
|
2622
|
+
|
2623
|
+
module.exports = ExecutionEnvironment;
|
2624
|
+
|
2625
|
+
},{}],40:[function(_dereq_,module,exports){
|
2626
|
+
/**
|
2627
|
+
* Copyright 2014, Facebook, Inc.
|
2628
|
+
* All rights reserved.
|
2629
|
+
*
|
2630
|
+
* This source code is licensed under the BSD-style license found in the
|
2631
|
+
* LICENSE file in the root directory of this source tree. An additional grant
|
2632
|
+
* of patent rights can be found in the PATENTS file in the same directory.
|
2633
|
+
*
|
2634
|
+
* @providesModule Object.assign
|
2635
|
+
*/
|
2636
|
+
|
2637
|
+
// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign
|
2638
|
+
|
2639
|
+
function assign(target, sources) {
|
2640
|
+
if (target == null) {
|
2641
|
+
throw new TypeError('Object.assign target cannot be null or undefined');
|
2642
|
+
}
|
2643
|
+
|
2644
|
+
var to = Object(target);
|
2645
|
+
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
2646
|
+
|
2647
|
+
for (var nextIndex = 1; nextIndex < arguments.length; nextIndex++) {
|
2648
|
+
var nextSource = arguments[nextIndex];
|
2649
|
+
if (nextSource == null) {
|
2650
|
+
continue;
|
2651
|
+
}
|
2652
|
+
|
2653
|
+
var from = Object(nextSource);
|
2654
|
+
|
2655
|
+
// We don't currently support accessors nor proxies. Therefore this
|
2656
|
+
// copy cannot throw. If we ever supported this then we must handle
|
2657
|
+
// exceptions and side-effects. We don't support symbols so they won't
|
2658
|
+
// be transferred.
|
2659
|
+
|
2660
|
+
for (var key in from) {
|
2661
|
+
if (hasOwnProperty.call(from, key)) {
|
2662
|
+
to[key] = from[key];
|
2663
|
+
}
|
2664
|
+
}
|
2665
|
+
}
|
2666
|
+
|
2667
|
+
return to;
|
2668
|
+
};
|
2669
|
+
|
2670
|
+
module.exports = assign;
|
2671
|
+
|
2672
|
+
},{}],41:[function(_dereq_,module,exports){
|
2673
|
+
/**
|
2674
|
+
* Copyright 2013-2014, Facebook, Inc.
|
2675
|
+
* All rights reserved.
|
2676
|
+
*
|
2677
|
+
* This source code is licensed under the BSD-style license found in the
|
2678
|
+
* LICENSE file in the root directory of this source tree. An additional grant
|
2679
|
+
* of patent rights can be found in the PATENTS file in the same directory.
|
2680
|
+
*
|
2681
|
+
* @providesModule cx
|
2682
|
+
*/
|
2683
|
+
|
2684
|
+
/**
|
2685
|
+
* This function is used to mark string literals representing CSS class names
|
2686
|
+
* so that they can be transformed statically. This allows for modularization
|
2687
|
+
* and minification of CSS class names.
|
2688
|
+
*
|
2689
|
+
* In static_upstream, this function is actually implemented, but it should
|
2690
|
+
* eventually be replaced with something more descriptive, and the transform
|
2691
|
+
* that is used in the main stack should be ported for use elsewhere.
|
2692
|
+
*
|
2693
|
+
* @param string|object className to modularize, or an object of key/values.
|
2694
|
+
* In the object case, the values are conditions that
|
2695
|
+
* determine if the className keys should be included.
|
2696
|
+
* @param [string ...] Variable list of classNames in the string case.
|
2697
|
+
* @return string Renderable space-separated CSS className.
|
2698
|
+
*/
|
2699
|
+
function cx(classNames) {
|
2700
|
+
if (typeof classNames == 'object') {
|
2701
|
+
return Object.keys(classNames).filter(function(className) {
|
2702
|
+
return classNames[className];
|
2703
|
+
}).join(' ');
|
2704
|
+
} else {
|
2705
|
+
return Array.prototype.join.call(arguments, ' ');
|
2706
|
+
}
|
2707
|
+
}
|
2708
|
+
|
2709
|
+
module.exports = cx;
|
2710
|
+
|
2711
|
+
},{}],42:[function(_dereq_,module,exports){
|
2712
|
+
/**
|
2713
|
+
* Copyright 2013-2014, Facebook, Inc.
|
2714
|
+
* All rights reserved.
|
2715
|
+
*
|
2716
|
+
* This source code is licensed under the BSD-style license found in the
|
2717
|
+
* LICENSE file in the root directory of this source tree. An additional grant
|
2718
|
+
* of patent rights can be found in the PATENTS file in the same directory.
|
2719
|
+
*
|
2720
|
+
* @providesModule emptyFunction
|
2721
|
+
*/
|
2722
|
+
|
2723
|
+
function makeEmptyFunction(arg) {
|
2724
|
+
return function() {
|
2725
|
+
return arg;
|
2726
|
+
};
|
2727
|
+
}
|
2728
|
+
|
2729
|
+
/**
|
2730
|
+
* This function accepts and discards inputs; it has no side effects. This is
|
2731
|
+
* primarily useful idiomatically for overridable function endpoints which
|
2732
|
+
* always need to be callable, since JS lacks a null-call idiom ala Cocoa.
|
2733
|
+
*/
|
2734
|
+
function emptyFunction() {}
|
2735
|
+
|
2736
|
+
emptyFunction.thatReturns = makeEmptyFunction;
|
2737
|
+
emptyFunction.thatReturnsFalse = makeEmptyFunction(false);
|
2738
|
+
emptyFunction.thatReturnsTrue = makeEmptyFunction(true);
|
2739
|
+
emptyFunction.thatReturnsNull = makeEmptyFunction(null);
|
2740
|
+
emptyFunction.thatReturnsThis = function() { return this; };
|
2741
|
+
emptyFunction.thatReturnsArgument = function(arg) { return arg; };
|
2742
|
+
|
2743
|
+
module.exports = emptyFunction;
|
2744
|
+
|
2745
|
+
},{}],43:[function(_dereq_,module,exports){
|
2746
|
+
/**
|
2747
|
+
* Copyright 2013-2014, Facebook, Inc.
|
2748
|
+
* All rights reserved.
|
2749
|
+
*
|
2750
|
+
* This source code is licensed under the BSD-style license found in the
|
2751
|
+
* LICENSE file in the root directory of this source tree. An additional grant
|
2752
|
+
* of patent rights can be found in the PATENTS file in the same directory.
|
2753
|
+
*
|
2754
|
+
* @providesModule invariant
|
2755
|
+
*/
|
2756
|
+
|
2757
|
+
"use strict";
|
2758
|
+
|
2759
|
+
/**
|
2760
|
+
* Use invariant() to assert state which your program assumes to be true.
|
2761
|
+
*
|
2762
|
+
* Provide sprintf-style format (only %s is supported) and arguments
|
2763
|
+
* to provide information about what broke and what you were
|
2764
|
+
* expecting.
|
2765
|
+
*
|
2766
|
+
* The invariant message will be stripped in production, but the invariant
|
2767
|
+
* will remain to ensure logic does not differ in production.
|
2768
|
+
*/
|
2769
|
+
|
2770
|
+
var invariant = function(condition, format, a, b, c, d, e, f) {
|
2771
|
+
if ("production" !== "production") {
|
2772
|
+
if (format === undefined) {
|
2773
|
+
throw new Error('invariant requires an error message argument');
|
2774
|
+
}
|
2775
|
+
}
|
2776
|
+
|
2777
|
+
if (!condition) {
|
2778
|
+
var error;
|
2779
|
+
if (format === undefined) {
|
2780
|
+
error = new Error(
|
2781
|
+
'Minified exception occurred; use the non-minified dev environment ' +
|
2782
|
+
'for the full error message and additional helpful warnings.'
|
2783
|
+
);
|
2784
|
+
} else {
|
2785
|
+
var args = [a, b, c, d, e, f];
|
2786
|
+
var argIndex = 0;
|
2787
|
+
error = new Error(
|
2788
|
+
'Invariant Violation: ' +
|
2789
|
+
format.replace(/%s/g, function() { return args[argIndex++]; })
|
2790
|
+
);
|
2791
|
+
}
|
2792
|
+
|
2793
|
+
error.framesToPop = 1; // we don't care about invariant's own frame
|
2794
|
+
throw error;
|
2795
|
+
}
|
2796
|
+
};
|
2797
|
+
|
2798
|
+
module.exports = invariant;
|
2799
|
+
|
2800
|
+
},{}],44:[function(_dereq_,module,exports){
|
2801
|
+
/**
|
2802
|
+
* Copyright 2014, Facebook, Inc.
|
2803
|
+
* All rights reserved.
|
2804
|
+
*
|
2805
|
+
* This source code is licensed under the BSD-style license found in the
|
2806
|
+
* LICENSE file in the root directory of this source tree. An additional grant
|
2807
|
+
* of patent rights can be found in the PATENTS file in the same directory.
|
2808
|
+
*
|
2809
|
+
* @providesModule warning
|
2810
|
+
*/
|
2811
|
+
|
2812
|
+
"use strict";
|
2813
|
+
|
2814
|
+
var emptyFunction = _dereq_("./emptyFunction");
|
2815
|
+
|
2816
|
+
/**
|
2817
|
+
* Similar to invariant but only logs a warning if the condition is not met.
|
2818
|
+
* This can be used to log issues in development environments in critical
|
2819
|
+
* paths. Removing the logging code for production environments will keep the
|
2820
|
+
* same logic and follow the same code paths.
|
2821
|
+
*/
|
2822
|
+
|
2823
|
+
var warning = emptyFunction;
|
2824
|
+
|
2825
|
+
if ("production" !== "production") {
|
2826
|
+
warning = function(condition, format ) {for (var args=[],$__0=2,$__1=arguments.length;$__0<$__1;$__0++) args.push(arguments[$__0]);
|
2827
|
+
if (format === undefined) {
|
2828
|
+
throw new Error(
|
2829
|
+
'`warning(condition, format, ...args)` requires a warning ' +
|
2830
|
+
'message argument'
|
2831
|
+
);
|
2832
|
+
}
|
2833
|
+
|
2834
|
+
if (!condition) {
|
2835
|
+
var argIndex = 0;
|
2836
|
+
console.warn('Warning: ' + format.replace(/%s/g, function() {return args[argIndex++];}));
|
2837
|
+
}
|
2838
|
+
};
|
2839
|
+
}
|
2840
|
+
|
2841
|
+
module.exports = warning;
|
2842
|
+
|
2843
|
+
},{"./emptyFunction":42}],45:[function(_dereq_,module,exports){
|
2844
|
+
/** @license MIT License (c) copyright 2010-2014 original author or authors */
|
2845
|
+
/** @author Brian Cavalier */
|
2846
|
+
/** @author John Hann */
|
2847
|
+
|
2848
|
+
(function(define) { 'use strict';
|
2849
|
+
define(function (_dereq_) {
|
2850
|
+
|
2851
|
+
var makePromise = _dereq_('./makePromise');
|
2852
|
+
var Scheduler = _dereq_('./Scheduler');
|
2853
|
+
var async = _dereq_('./async');
|
2854
|
+
|
2855
|
+
return makePromise({
|
2856
|
+
scheduler: new Scheduler(async)
|
2857
|
+
});
|
2858
|
+
|
2859
|
+
});
|
2860
|
+
})(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(_dereq_); });
|
2861
|
+
|
2862
|
+
},{"./Scheduler":47,"./async":48,"./makePromise":49}],46:[function(_dereq_,module,exports){
|
2863
|
+
/** @license MIT License (c) copyright 2010-2014 original author or authors */
|
2864
|
+
/** @author Brian Cavalier */
|
2865
|
+
/** @author John Hann */
|
2866
|
+
|
2867
|
+
(function(define) { 'use strict';
|
2868
|
+
define(function() {
|
2869
|
+
/**
|
2870
|
+
* Circular queue
|
2871
|
+
* @param {number} capacityPow2 power of 2 to which this queue's capacity
|
2872
|
+
* will be set initially. eg when capacityPow2 == 3, queue capacity
|
2873
|
+
* will be 8.
|
2874
|
+
* @constructor
|
2875
|
+
*/
|
2876
|
+
function Queue(capacityPow2) {
|
2877
|
+
this.head = this.tail = this.length = 0;
|
2878
|
+
this.buffer = new Array(1 << capacityPow2);
|
2879
|
+
}
|
2880
|
+
|
2881
|
+
Queue.prototype.push = function(x) {
|
2882
|
+
if(this.length === this.buffer.length) {
|
2883
|
+
this._ensureCapacity(this.length * 2);
|
2884
|
+
}
|
2885
|
+
|
2886
|
+
this.buffer[this.tail] = x;
|
2887
|
+
this.tail = (this.tail + 1) & (this.buffer.length - 1);
|
2888
|
+
++this.length;
|
2889
|
+
return this.length;
|
2890
|
+
};
|
2891
|
+
|
2892
|
+
Queue.prototype.shift = function() {
|
2893
|
+
var x = this.buffer[this.head];
|
2894
|
+
this.buffer[this.head] = void 0;
|
2895
|
+
this.head = (this.head + 1) & (this.buffer.length - 1);
|
2896
|
+
--this.length;
|
2897
|
+
return x;
|
2898
|
+
};
|
2899
|
+
|
2900
|
+
Queue.prototype._ensureCapacity = function(capacity) {
|
2901
|
+
var head = this.head;
|
2902
|
+
var buffer = this.buffer;
|
2903
|
+
var newBuffer = new Array(capacity);
|
2904
|
+
var i = 0;
|
2905
|
+
var len;
|
2906
|
+
|
2907
|
+
if(head === 0) {
|
2908
|
+
len = this.length;
|
2909
|
+
for(; i<len; ++i) {
|
2910
|
+
newBuffer[i] = buffer[i];
|
2911
|
+
}
|
2912
|
+
} else {
|
2913
|
+
capacity = buffer.length;
|
2914
|
+
len = this.tail;
|
2915
|
+
for(; head<capacity; ++i, ++head) {
|
2916
|
+
newBuffer[i] = buffer[head];
|
2917
|
+
}
|
2918
|
+
|
2919
|
+
for(head=0; head<len; ++i, ++head) {
|
2920
|
+
newBuffer[i] = buffer[head];
|
2921
|
+
}
|
2922
|
+
}
|
2923
|
+
|
2924
|
+
this.buffer = newBuffer;
|
2925
|
+
this.head = 0;
|
2926
|
+
this.tail = this.length;
|
2927
|
+
};
|
2928
|
+
|
2929
|
+
return Queue;
|
2930
|
+
|
2931
|
+
});
|
2932
|
+
}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
|
2933
|
+
|
2934
|
+
},{}],47:[function(_dereq_,module,exports){
|
2935
|
+
/** @license MIT License (c) copyright 2010-2014 original author or authors */
|
2936
|
+
/** @author Brian Cavalier */
|
2937
|
+
/** @author John Hann */
|
2938
|
+
|
2939
|
+
(function(define) { 'use strict';
|
2940
|
+
define(function(_dereq_) {
|
2941
|
+
|
2942
|
+
var Queue = _dereq_('./Queue');
|
2943
|
+
|
2944
|
+
// Credit to Twisol (https://github.com/Twisol) for suggesting
|
2945
|
+
// this type of extensible queue + trampoline approach for next-tick conflation.
|
2946
|
+
|
2947
|
+
/**
|
2948
|
+
* Async task scheduler
|
2949
|
+
* @param {function} async function to schedule a single async function
|
2950
|
+
* @constructor
|
2951
|
+
*/
|
2952
|
+
function Scheduler(async) {
|
2953
|
+
this._async = async;
|
2954
|
+
this._queue = new Queue(15);
|
2955
|
+
this._afterQueue = new Queue(5);
|
2956
|
+
this._running = false;
|
2957
|
+
|
2958
|
+
var self = this;
|
2959
|
+
this.drain = function() {
|
2960
|
+
self._drain();
|
2961
|
+
};
|
2962
|
+
}
|
2963
|
+
|
2964
|
+
/**
|
2965
|
+
* Enqueue a task
|
2966
|
+
* @param {{ run:function }} task
|
2967
|
+
*/
|
2968
|
+
Scheduler.prototype.enqueue = function(task) {
|
2969
|
+
this._add(this._queue, task);
|
2970
|
+
};
|
2971
|
+
|
2972
|
+
/**
|
2973
|
+
* Enqueue a task to run after the main task queue
|
2974
|
+
* @param {{ run:function }} task
|
2975
|
+
*/
|
2976
|
+
Scheduler.prototype.afterQueue = function(task) {
|
2977
|
+
this._add(this._afterQueue, task);
|
2978
|
+
};
|
2979
|
+
|
2980
|
+
/**
|
2981
|
+
* Drain the handler queue entirely, and then the after queue
|
2982
|
+
*/
|
2983
|
+
Scheduler.prototype._drain = function() {
|
2984
|
+
runQueue(this._queue);
|
2985
|
+
this._running = false;
|
2986
|
+
runQueue(this._afterQueue);
|
2987
|
+
};
|
2988
|
+
|
2989
|
+
/**
|
2990
|
+
* Add a task to the q, and schedule drain if not already scheduled
|
2991
|
+
* @param {Queue} queue
|
2992
|
+
* @param {{run:function}} task
|
2993
|
+
* @private
|
2994
|
+
*/
|
2995
|
+
Scheduler.prototype._add = function(queue, task) {
|
2996
|
+
queue.push(task);
|
2997
|
+
if(!this._running) {
|
2998
|
+
this._running = true;
|
2999
|
+
this._async(this.drain);
|
3000
|
+
}
|
3001
|
+
};
|
3002
|
+
|
3003
|
+
/**
|
3004
|
+
* Run all the tasks in the q
|
3005
|
+
* @param queue
|
3006
|
+
*/
|
3007
|
+
function runQueue(queue) {
|
3008
|
+
while(queue.length > 0) {
|
3009
|
+
queue.shift().run();
|
3010
|
+
}
|
3011
|
+
}
|
3012
|
+
|
3013
|
+
return Scheduler;
|
3014
|
+
|
3015
|
+
});
|
3016
|
+
}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(_dereq_); }));
|
3017
|
+
|
3018
|
+
},{"./Queue":46}],48:[function(_dereq_,module,exports){
|
3019
|
+
/** @license MIT License (c) copyright 2010-2014 original author or authors */
|
3020
|
+
/** @author Brian Cavalier */
|
3021
|
+
/** @author John Hann */
|
3022
|
+
|
3023
|
+
(function(define) { 'use strict';
|
3024
|
+
define(function(_dereq_) {
|
3025
|
+
|
3026
|
+
// Sniff "best" async scheduling option
|
3027
|
+
// Prefer process.nextTick or MutationObserver, then check for
|
3028
|
+
// vertx and finally fall back to setTimeout
|
3029
|
+
|
3030
|
+
/*jshint maxcomplexity:6*/
|
3031
|
+
/*global process,document,setTimeout,MutationObserver,WebKitMutationObserver*/
|
3032
|
+
var nextTick, MutationObs;
|
3033
|
+
|
3034
|
+
if (typeof process !== 'undefined' && process !== null &&
|
3035
|
+
typeof process.nextTick === 'function') {
|
3036
|
+
nextTick = function(f) {
|
3037
|
+
process.nextTick(f);
|
3038
|
+
};
|
3039
|
+
|
3040
|
+
} else if (MutationObs =
|
3041
|
+
(typeof MutationObserver === 'function' && MutationObserver) ||
|
3042
|
+
(typeof WebKitMutationObserver === 'function' && WebKitMutationObserver)) {
|
3043
|
+
nextTick = (function (document, MutationObserver) {
|
3044
|
+
var scheduled;
|
3045
|
+
var el = document.createElement('div');
|
3046
|
+
var o = new MutationObserver(run);
|
3047
|
+
o.observe(el, { attributes: true });
|
3048
|
+
|
3049
|
+
function run() {
|
3050
|
+
var f = scheduled;
|
3051
|
+
scheduled = void 0;
|
3052
|
+
f();
|
3053
|
+
}
|
3054
|
+
|
3055
|
+
return function (f) {
|
3056
|
+
scheduled = f;
|
3057
|
+
el.setAttribute('class', 'x');
|
3058
|
+
};
|
3059
|
+
}(document, MutationObs));
|
3060
|
+
|
3061
|
+
} else {
|
3062
|
+
nextTick = (function(cjsRequire) {
|
3063
|
+
var vertx;
|
3064
|
+
try {
|
3065
|
+
// vert.x 1.x || 2.x
|
3066
|
+
vertx = cjsRequire('vertx');
|
3067
|
+
} catch (ignore) {}
|
3068
|
+
|
3069
|
+
if (vertx) {
|
3070
|
+
if (typeof vertx.runOnLoop === 'function') {
|
3071
|
+
return vertx.runOnLoop;
|
3072
|
+
}
|
3073
|
+
if (typeof vertx.runOnContext === 'function') {
|
3074
|
+
return vertx.runOnContext;
|
3075
|
+
}
|
3076
|
+
}
|
3077
|
+
|
3078
|
+
// capture setTimeout to avoid being caught by fake timers
|
3079
|
+
// used in time based tests
|
3080
|
+
var capturedSetTimeout = setTimeout;
|
3081
|
+
return function (t) {
|
3082
|
+
capturedSetTimeout(t, 0);
|
3083
|
+
};
|
3084
|
+
}(_dereq_));
|
3085
|
+
}
|
3086
|
+
|
3087
|
+
return nextTick;
|
3088
|
+
});
|
3089
|
+
}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(_dereq_); }));
|
3090
|
+
|
3091
|
+
},{}],49:[function(_dereq_,module,exports){
|
3092
|
+
/** @license MIT License (c) copyright 2010-2014 original author or authors */
|
3093
|
+
/** @author Brian Cavalier */
|
3094
|
+
/** @author John Hann */
|
3095
|
+
|
3096
|
+
(function(define) { 'use strict';
|
3097
|
+
define(function() {
|
3098
|
+
|
3099
|
+
return function makePromise(environment) {
|
3100
|
+
|
3101
|
+
var tasks = environment.scheduler;
|
3102
|
+
|
3103
|
+
var objectCreate = Object.create ||
|
3104
|
+
function(proto) {
|
3105
|
+
function Child() {}
|
3106
|
+
Child.prototype = proto;
|
3107
|
+
return new Child();
|
3108
|
+
};
|
3109
|
+
|
3110
|
+
/**
|
3111
|
+
* Create a promise whose fate is determined by resolver
|
3112
|
+
* @constructor
|
3113
|
+
* @returns {Promise} promise
|
3114
|
+
* @name Promise
|
3115
|
+
*/
|
3116
|
+
function Promise(resolver, handler) {
|
3117
|
+
this._handler = resolver === Handler ? handler : init(resolver);
|
3118
|
+
}
|
3119
|
+
|
3120
|
+
/**
|
3121
|
+
* Run the supplied resolver
|
3122
|
+
* @param resolver
|
3123
|
+
* @returns {Pending}
|
3124
|
+
*/
|
3125
|
+
function init(resolver) {
|
3126
|
+
var handler = new Pending();
|
3127
|
+
|
3128
|
+
try {
|
3129
|
+
resolver(promiseResolve, promiseReject, promiseNotify);
|
3130
|
+
} catch (e) {
|
3131
|
+
promiseReject(e);
|
3132
|
+
}
|
3133
|
+
|
3134
|
+
return handler;
|
3135
|
+
|
3136
|
+
/**
|
3137
|
+
* Transition from pre-resolution state to post-resolution state, notifying
|
3138
|
+
* all listeners of the ultimate fulfillment or rejection
|
3139
|
+
* @param {*} x resolution value
|
3140
|
+
*/
|
3141
|
+
function promiseResolve (x) {
|
3142
|
+
handler.resolve(x);
|
3143
|
+
}
|
3144
|
+
/**
|
3145
|
+
* Reject this promise with reason, which will be used verbatim
|
3146
|
+
* @param {Error|*} reason rejection reason, strongly suggested
|
3147
|
+
* to be an Error type
|
3148
|
+
*/
|
3149
|
+
function promiseReject (reason) {
|
3150
|
+
handler.reject(reason);
|
3151
|
+
}
|
3152
|
+
|
3153
|
+
/**
|
3154
|
+
* Issue a progress event, notifying all progress listeners
|
3155
|
+
* @param {*} x progress event payload to pass to all listeners
|
3156
|
+
*/
|
3157
|
+
function promiseNotify (x) {
|
3158
|
+
handler.notify(x);
|
3159
|
+
}
|
3160
|
+
}
|
3161
|
+
|
3162
|
+
// Creation
|
3163
|
+
|
3164
|
+
Promise.resolve = resolve;
|
3165
|
+
Promise.reject = reject;
|
3166
|
+
Promise.never = never;
|
3167
|
+
|
3168
|
+
Promise._defer = defer;
|
3169
|
+
Promise._handler = getHandler;
|
3170
|
+
|
3171
|
+
/**
|
3172
|
+
* Returns a trusted promise. If x is already a trusted promise, it is
|
3173
|
+
* returned, otherwise returns a new trusted Promise which follows x.
|
3174
|
+
* @param {*} x
|
3175
|
+
* @return {Promise} promise
|
3176
|
+
*/
|
3177
|
+
function resolve(x) {
|
3178
|
+
return isPromise(x) ? x
|
3179
|
+
: new Promise(Handler, new Async(getHandler(x)));
|
3180
|
+
}
|
3181
|
+
|
3182
|
+
/**
|
3183
|
+
* Return a reject promise with x as its reason (x is used verbatim)
|
3184
|
+
* @param {*} x
|
3185
|
+
* @returns {Promise} rejected promise
|
3186
|
+
*/
|
3187
|
+
function reject(x) {
|
3188
|
+
return new Promise(Handler, new Async(new Rejected(x)));
|
3189
|
+
}
|
3190
|
+
|
3191
|
+
/**
|
3192
|
+
* Return a promise that remains pending forever
|
3193
|
+
* @returns {Promise} forever-pending promise.
|
3194
|
+
*/
|
3195
|
+
function never() {
|
3196
|
+
return foreverPendingPromise; // Should be frozen
|
3197
|
+
}
|
3198
|
+
|
3199
|
+
/**
|
3200
|
+
* Creates an internal {promise, resolver} pair
|
3201
|
+
* @private
|
3202
|
+
* @returns {Promise}
|
3203
|
+
*/
|
3204
|
+
function defer() {
|
3205
|
+
return new Promise(Handler, new Pending());
|
3206
|
+
}
|
3207
|
+
|
3208
|
+
// Transformation and flow control
|
3209
|
+
|
3210
|
+
/**
|
3211
|
+
* Transform this promise's fulfillment value, returning a new Promise
|
3212
|
+
* for the transformed result. If the promise cannot be fulfilled, onRejected
|
3213
|
+
* is called with the reason. onProgress *may* be called with updates toward
|
3214
|
+
* this promise's fulfillment.
|
3215
|
+
* @param {function=} onFulfilled fulfillment handler
|
3216
|
+
* @param {function=} onRejected rejection handler
|
3217
|
+
* @deprecated @param {function=} onProgress progress handler
|
3218
|
+
* @return {Promise} new promise
|
3219
|
+
*/
|
3220
|
+
Promise.prototype.then = function(onFulfilled, onRejected) {
|
3221
|
+
var parent = this._handler;
|
3222
|
+
var state = parent.join().state();
|
3223
|
+
|
3224
|
+
if ((typeof onFulfilled !== 'function' && state > 0) ||
|
3225
|
+
(typeof onRejected !== 'function' && state < 0)) {
|
3226
|
+
// Short circuit: value will not change, simply share handler
|
3227
|
+
return new this.constructor(Handler, parent);
|
3228
|
+
}
|
3229
|
+
|
3230
|
+
var p = this._beget();
|
3231
|
+
var child = p._handler;
|
3232
|
+
|
3233
|
+
parent.chain(child, parent.receiver, onFulfilled, onRejected,
|
3234
|
+
arguments.length > 2 ? arguments[2] : void 0);
|
3235
|
+
|
3236
|
+
return p;
|
3237
|
+
};
|
3238
|
+
|
3239
|
+
/**
|
3240
|
+
* If this promise cannot be fulfilled due to an error, call onRejected to
|
3241
|
+
* handle the error. Shortcut for .then(undefined, onRejected)
|
3242
|
+
* @param {function?} onRejected
|
3243
|
+
* @return {Promise}
|
3244
|
+
*/
|
3245
|
+
Promise.prototype['catch'] = function(onRejected) {
|
3246
|
+
return this.then(void 0, onRejected);
|
3247
|
+
};
|
3248
|
+
|
3249
|
+
/**
|
3250
|
+
* Creates a new, pending promise of the same type as this promise
|
3251
|
+
* @private
|
3252
|
+
* @returns {Promise}
|
3253
|
+
*/
|
3254
|
+
Promise.prototype._beget = function() {
|
3255
|
+
var parent = this._handler;
|
3256
|
+
var child = new Pending(parent.receiver, parent.join().context);
|
3257
|
+
return new this.constructor(Handler, child);
|
3258
|
+
};
|
3259
|
+
|
3260
|
+
// Array combinators
|
3261
|
+
|
3262
|
+
Promise.all = all;
|
3263
|
+
Promise.race = race;
|
3264
|
+
|
3265
|
+
/**
|
3266
|
+
* Return a promise that will fulfill when all promises in the
|
3267
|
+
* input array have fulfilled, or will reject when one of the
|
3268
|
+
* promises rejects.
|
3269
|
+
* @param {array} promises array of promises
|
3270
|
+
* @returns {Promise} promise for array of fulfillment values
|
3271
|
+
*/
|
3272
|
+
function all(promises) {
|
3273
|
+
/*jshint maxcomplexity:8*/
|
3274
|
+
var resolver = new Pending();
|
3275
|
+
var pending = promises.length >>> 0;
|
3276
|
+
var results = new Array(pending);
|
3277
|
+
|
3278
|
+
var i, h, x, s;
|
3279
|
+
for (i = 0; i < promises.length; ++i) {
|
3280
|
+
x = promises[i];
|
3281
|
+
|
3282
|
+
if (x === void 0 && !(i in promises)) {
|
3283
|
+
--pending;
|
3284
|
+
continue;
|
3285
|
+
}
|
3286
|
+
|
3287
|
+
if (maybeThenable(x)) {
|
3288
|
+
h = getHandlerMaybeThenable(x);
|
3289
|
+
|
3290
|
+
s = h.state();
|
3291
|
+
if (s === 0) {
|
3292
|
+
h.fold(settleAt, i, results, resolver);
|
3293
|
+
} else if (s > 0) {
|
3294
|
+
results[i] = h.value;
|
3295
|
+
--pending;
|
3296
|
+
} else {
|
3297
|
+
unreportRemaining(promises, i+1, h);
|
3298
|
+
resolver.become(h);
|
3299
|
+
break;
|
3300
|
+
}
|
3301
|
+
|
3302
|
+
} else {
|
3303
|
+
results[i] = x;
|
3304
|
+
--pending;
|
3305
|
+
}
|
3306
|
+
}
|
3307
|
+
|
3308
|
+
if(pending === 0) {
|
3309
|
+
resolver.become(new Fulfilled(results));
|
3310
|
+
}
|
3311
|
+
|
3312
|
+
return new Promise(Handler, resolver);
|
3313
|
+
|
3314
|
+
function settleAt(i, x, resolver) {
|
3315
|
+
/*jshint validthis:true*/
|
3316
|
+
this[i] = x;
|
3317
|
+
if(--pending === 0) {
|
3318
|
+
resolver.become(new Fulfilled(this));
|
3319
|
+
}
|
3320
|
+
}
|
3321
|
+
}
|
3322
|
+
|
3323
|
+
function unreportRemaining(promises, start, rejectedHandler) {
|
3324
|
+
var i, h, x;
|
3325
|
+
for(i=start; i<promises.length; ++i) {
|
3326
|
+
x = promises[i];
|
3327
|
+
if(maybeThenable(x)) {
|
3328
|
+
h = getHandlerMaybeThenable(x);
|
3329
|
+
|
3330
|
+
if(h !== rejectedHandler) {
|
3331
|
+
h.visit(h, void 0, h._unreport);
|
3332
|
+
}
|
3333
|
+
}
|
3334
|
+
}
|
3335
|
+
}
|
3336
|
+
|
3337
|
+
/**
|
3338
|
+
* Fulfill-reject competitive race. Return a promise that will settle
|
3339
|
+
* to the same state as the earliest input promise to settle.
|
3340
|
+
*
|
3341
|
+
* WARNING: The ES6 Promise spec requires that race()ing an empty array
|
3342
|
+
* must return a promise that is pending forever. This implementation
|
3343
|
+
* returns a singleton forever-pending promise, the same singleton that is
|
3344
|
+
* returned by Promise.never(), thus can be checked with ===
|
3345
|
+
*
|
3346
|
+
* @param {array} promises array of promises to race
|
3347
|
+
* @returns {Promise} if input is non-empty, a promise that will settle
|
3348
|
+
* to the same outcome as the earliest input promise to settle. if empty
|
3349
|
+
* is empty, returns a promise that will never settle.
|
3350
|
+
*/
|
3351
|
+
function race(promises) {
|
3352
|
+
// Sigh, race([]) is untestable unless we return *something*
|
3353
|
+
// that is recognizable without calling .then() on it.
|
3354
|
+
if(Object(promises) === promises && promises.length === 0) {
|
3355
|
+
return never();
|
3356
|
+
}
|
3357
|
+
|
3358
|
+
var h = new Pending();
|
3359
|
+
var i, x;
|
3360
|
+
for(i=0; i<promises.length; ++i) {
|
3361
|
+
x = promises[i];
|
3362
|
+
if (x !== void 0 && i in promises) {
|
3363
|
+
getHandler(x).visit(h, h.resolve, h.reject);
|
3364
|
+
}
|
3365
|
+
}
|
3366
|
+
return new Promise(Handler, h);
|
3367
|
+
}
|
3368
|
+
|
3369
|
+
// Promise internals
|
3370
|
+
// Below this, everything is @private
|
3371
|
+
|
3372
|
+
/**
|
3373
|
+
* Get an appropriate handler for x, without checking for cycles
|
3374
|
+
* @param {*} x
|
3375
|
+
* @returns {object} handler
|
3376
|
+
*/
|
3377
|
+
function getHandler(x) {
|
3378
|
+
if(isPromise(x)) {
|
3379
|
+
return x._handler.join();
|
3380
|
+
}
|
3381
|
+
return maybeThenable(x) ? getHandlerUntrusted(x) : new Fulfilled(x);
|
3382
|
+
}
|
3383
|
+
|
3384
|
+
/**
|
3385
|
+
* Get a handler for thenable x.
|
3386
|
+
* NOTE: You must only call this if maybeThenable(x) == true
|
3387
|
+
* @param {object|function|Promise} x
|
3388
|
+
* @returns {object} handler
|
3389
|
+
*/
|
3390
|
+
function getHandlerMaybeThenable(x) {
|
3391
|
+
return isPromise(x) ? x._handler.join() : getHandlerUntrusted(x);
|
3392
|
+
}
|
3393
|
+
|
3394
|
+
/**
|
3395
|
+
* Get a handler for potentially untrusted thenable x
|
3396
|
+
* @param {*} x
|
3397
|
+
* @returns {object} handler
|
3398
|
+
*/
|
3399
|
+
function getHandlerUntrusted(x) {
|
3400
|
+
try {
|
3401
|
+
var untrustedThen = x.then;
|
3402
|
+
return typeof untrustedThen === 'function'
|
3403
|
+
? new Thenable(untrustedThen, x)
|
3404
|
+
: new Fulfilled(x);
|
3405
|
+
} catch(e) {
|
3406
|
+
return new Rejected(e);
|
3407
|
+
}
|
3408
|
+
}
|
3409
|
+
|
3410
|
+
/**
|
3411
|
+
* Handler for a promise that is pending forever
|
3412
|
+
* @constructor
|
3413
|
+
*/
|
3414
|
+
function Handler() {}
|
3415
|
+
|
3416
|
+
Handler.prototype.when
|
3417
|
+
= Handler.prototype.become
|
3418
|
+
= Handler.prototype.notify
|
3419
|
+
= Handler.prototype.fail
|
3420
|
+
= Handler.prototype._unreport
|
3421
|
+
= Handler.prototype._report
|
3422
|
+
= noop;
|
3423
|
+
|
3424
|
+
Handler.prototype._state = 0;
|
3425
|
+
|
3426
|
+
Handler.prototype.state = function() {
|
3427
|
+
return this._state;
|
3428
|
+
};
|
3429
|
+
|
3430
|
+
/**
|
3431
|
+
* Recursively collapse handler chain to find the handler
|
3432
|
+
* nearest to the fully resolved value.
|
3433
|
+
* @returns {object} handler nearest the fully resolved value
|
3434
|
+
*/
|
3435
|
+
Handler.prototype.join = function() {
|
3436
|
+
var h = this;
|
3437
|
+
while(h.handler !== void 0) {
|
3438
|
+
h = h.handler;
|
3439
|
+
}
|
3440
|
+
return h;
|
3441
|
+
};
|
3442
|
+
|
3443
|
+
Handler.prototype.chain = function(to, receiver, fulfilled, rejected, progress) {
|
3444
|
+
this.when({
|
3445
|
+
resolver: to,
|
3446
|
+
receiver: receiver,
|
3447
|
+
fulfilled: fulfilled,
|
3448
|
+
rejected: rejected,
|
3449
|
+
progress: progress
|
3450
|
+
});
|
3451
|
+
};
|
3452
|
+
|
3453
|
+
Handler.prototype.visit = function(receiver, fulfilled, rejected, progress) {
|
3454
|
+
this.chain(failIfRejected, receiver, fulfilled, rejected, progress);
|
3455
|
+
};
|
3456
|
+
|
3457
|
+
Handler.prototype.fold = function(f, z, c, to) {
|
3458
|
+
this.visit(to, function(x) {
|
3459
|
+
f.call(c, z, x, this);
|
3460
|
+
}, to.reject, to.notify);
|
3461
|
+
};
|
3462
|
+
|
3463
|
+
/**
|
3464
|
+
* Handler that invokes fail() on any handler it becomes
|
3465
|
+
* @constructor
|
3466
|
+
*/
|
3467
|
+
function FailIfRejected() {}
|
3468
|
+
|
3469
|
+
inherit(Handler, FailIfRejected);
|
3470
|
+
|
3471
|
+
FailIfRejected.prototype.become = function(h) {
|
3472
|
+
h.fail();
|
3473
|
+
};
|
3474
|
+
|
3475
|
+
var failIfRejected = new FailIfRejected();
|
3476
|
+
|
3477
|
+
/**
|
3478
|
+
* Handler that manages a queue of consumers waiting on a pending promise
|
3479
|
+
* @constructor
|
3480
|
+
*/
|
3481
|
+
function Pending(receiver, inheritedContext) {
|
3482
|
+
Promise.createContext(this, inheritedContext);
|
3483
|
+
|
3484
|
+
this.consumers = void 0;
|
3485
|
+
this.receiver = receiver;
|
3486
|
+
this.handler = void 0;
|
3487
|
+
this.resolved = false;
|
3488
|
+
}
|
3489
|
+
|
3490
|
+
inherit(Handler, Pending);
|
3491
|
+
|
3492
|
+
Pending.prototype._state = 0;
|
3493
|
+
|
3494
|
+
Pending.prototype.resolve = function(x) {
|
3495
|
+
this.become(getHandler(x));
|
3496
|
+
};
|
3497
|
+
|
3498
|
+
Pending.prototype.reject = function(x) {
|
3499
|
+
if(this.resolved) {
|
3500
|
+
return;
|
3501
|
+
}
|
3502
|
+
|
3503
|
+
this.become(new Rejected(x));
|
3504
|
+
};
|
3505
|
+
|
3506
|
+
Pending.prototype.join = function() {
|
3507
|
+
if (!this.resolved) {
|
3508
|
+
return this;
|
3509
|
+
}
|
3510
|
+
|
3511
|
+
var h = this;
|
3512
|
+
|
3513
|
+
while (h.handler !== void 0) {
|
3514
|
+
h = h.handler;
|
3515
|
+
if (h === this) {
|
3516
|
+
return this.handler = cycle();
|
3517
|
+
}
|
3518
|
+
}
|
3519
|
+
|
3520
|
+
return h;
|
3521
|
+
};
|
3522
|
+
|
3523
|
+
Pending.prototype.run = function() {
|
3524
|
+
var q = this.consumers;
|
3525
|
+
var handler = this.join();
|
3526
|
+
this.consumers = void 0;
|
3527
|
+
|
3528
|
+
for (var i = 0; i < q.length; ++i) {
|
3529
|
+
handler.when(q[i]);
|
3530
|
+
}
|
3531
|
+
};
|
3532
|
+
|
3533
|
+
Pending.prototype.become = function(handler) {
|
3534
|
+
if(this.resolved) {
|
3535
|
+
return;
|
3536
|
+
}
|
3537
|
+
|
3538
|
+
this.resolved = true;
|
3539
|
+
this.handler = handler;
|
3540
|
+
if(this.consumers !== void 0) {
|
3541
|
+
tasks.enqueue(this);
|
3542
|
+
}
|
3543
|
+
|
3544
|
+
if(this.context !== void 0) {
|
3545
|
+
handler._report(this.context);
|
3546
|
+
}
|
3547
|
+
};
|
3548
|
+
|
3549
|
+
Pending.prototype.when = function(continuation) {
|
3550
|
+
if(this.resolved) {
|
3551
|
+
tasks.enqueue(new ContinuationTask(continuation, this.handler));
|
3552
|
+
} else {
|
3553
|
+
if(this.consumers === void 0) {
|
3554
|
+
this.consumers = [continuation];
|
3555
|
+
} else {
|
3556
|
+
this.consumers.push(continuation);
|
3557
|
+
}
|
3558
|
+
}
|
3559
|
+
};
|
3560
|
+
|
3561
|
+
Pending.prototype.notify = function(x) {
|
3562
|
+
if(!this.resolved) {
|
3563
|
+
tasks.enqueue(new ProgressTask(x, this));
|
3564
|
+
}
|
3565
|
+
};
|
3566
|
+
|
3567
|
+
Pending.prototype.fail = function(context) {
|
3568
|
+
var c = typeof context === 'undefined' ? this.context : context;
|
3569
|
+
this.resolved && this.handler.join().fail(c);
|
3570
|
+
};
|
3571
|
+
|
3572
|
+
Pending.prototype._report = function(context) {
|
3573
|
+
this.resolved && this.handler.join()._report(context);
|
3574
|
+
};
|
3575
|
+
|
3576
|
+
Pending.prototype._unreport = function() {
|
3577
|
+
this.resolved && this.handler.join()._unreport();
|
3578
|
+
};
|
3579
|
+
|
3580
|
+
/**
|
3581
|
+
* Wrap another handler and force it into a future stack
|
3582
|
+
* @param {object} handler
|
3583
|
+
* @constructor
|
3584
|
+
*/
|
3585
|
+
function Async(handler) {
|
3586
|
+
this.handler = handler;
|
3587
|
+
}
|
3588
|
+
|
3589
|
+
inherit(Handler, Async);
|
3590
|
+
|
3591
|
+
Async.prototype.when = function(continuation) {
|
3592
|
+
tasks.enqueue(new ContinuationTask(continuation, this));
|
3593
|
+
};
|
3594
|
+
|
3595
|
+
Async.prototype._report = function(context) {
|
3596
|
+
this.join()._report(context);
|
3597
|
+
};
|
3598
|
+
|
3599
|
+
Async.prototype._unreport = function() {
|
3600
|
+
this.join()._unreport();
|
3601
|
+
};
|
3602
|
+
|
3603
|
+
/**
|
3604
|
+
* Handler that wraps an untrusted thenable and assimilates it in a future stack
|
3605
|
+
* @param {function} then
|
3606
|
+
* @param {{then: function}} thenable
|
3607
|
+
* @constructor
|
3608
|
+
*/
|
3609
|
+
function Thenable(then, thenable) {
|
3610
|
+
Pending.call(this);
|
3611
|
+
tasks.enqueue(new AssimilateTask(then, thenable, this));
|
3612
|
+
}
|
3613
|
+
|
3614
|
+
inherit(Pending, Thenable);
|
3615
|
+
|
3616
|
+
/**
|
3617
|
+
* Handler for a fulfilled promise
|
3618
|
+
* @param {*} x fulfillment value
|
3619
|
+
* @constructor
|
3620
|
+
*/
|
3621
|
+
function Fulfilled(x) {
|
3622
|
+
Promise.createContext(this);
|
3623
|
+
this.value = x;
|
3624
|
+
}
|
3625
|
+
|
3626
|
+
inherit(Handler, Fulfilled);
|
3627
|
+
|
3628
|
+
Fulfilled.prototype._state = 1;
|
3629
|
+
|
3630
|
+
Fulfilled.prototype.fold = function(f, z, c, to) {
|
3631
|
+
runContinuation3(f, z, this, c, to);
|
3632
|
+
};
|
3633
|
+
|
3634
|
+
Fulfilled.prototype.when = function(cont) {
|
3635
|
+
runContinuation1(cont.fulfilled, this, cont.receiver, cont.resolver);
|
3636
|
+
};
|
3637
|
+
|
3638
|
+
var errorId = 0;
|
3639
|
+
|
3640
|
+
/**
|
3641
|
+
* Handler for a rejected promise
|
3642
|
+
* @param {*} x rejection reason
|
3643
|
+
* @constructor
|
3644
|
+
*/
|
3645
|
+
function Rejected(x) {
|
3646
|
+
Promise.createContext(this);
|
3647
|
+
|
3648
|
+
this.id = ++errorId;
|
3649
|
+
this.value = x;
|
3650
|
+
this.handled = false;
|
3651
|
+
this.reported = false;
|
3652
|
+
|
3653
|
+
this._report();
|
3654
|
+
}
|
3655
|
+
|
3656
|
+
inherit(Handler, Rejected);
|
3657
|
+
|
3658
|
+
Rejected.prototype._state = -1;
|
3659
|
+
|
3660
|
+
Rejected.prototype.fold = function(f, z, c, to) {
|
3661
|
+
to.become(this);
|
3662
|
+
};
|
3663
|
+
|
3664
|
+
Rejected.prototype.when = function(cont) {
|
3665
|
+
if(typeof cont.rejected === 'function') {
|
3666
|
+
this._unreport();
|
3667
|
+
}
|
3668
|
+
runContinuation1(cont.rejected, this, cont.receiver, cont.resolver);
|
3669
|
+
};
|
3670
|
+
|
3671
|
+
Rejected.prototype._report = function(context) {
|
3672
|
+
tasks.afterQueue(new ReportTask(this, context));
|
3673
|
+
};
|
3674
|
+
|
3675
|
+
Rejected.prototype._unreport = function() {
|
3676
|
+
this.handled = true;
|
3677
|
+
tasks.afterQueue(new UnreportTask(this));
|
3678
|
+
};
|
3679
|
+
|
3680
|
+
Rejected.prototype.fail = function(context) {
|
3681
|
+
Promise.onFatalRejection(this, context === void 0 ? this.context : context);
|
3682
|
+
};
|
3683
|
+
|
3684
|
+
function ReportTask(rejection, context) {
|
3685
|
+
this.rejection = rejection;
|
3686
|
+
this.context = context;
|
3687
|
+
}
|
3688
|
+
|
3689
|
+
ReportTask.prototype.run = function() {
|
3690
|
+
if(!this.rejection.handled) {
|
3691
|
+
this.rejection.reported = true;
|
3692
|
+
Promise.onPotentiallyUnhandledRejection(this.rejection, this.context);
|
3693
|
+
}
|
3694
|
+
};
|
3695
|
+
|
3696
|
+
function UnreportTask(rejection) {
|
3697
|
+
this.rejection = rejection;
|
3698
|
+
}
|
3699
|
+
|
3700
|
+
UnreportTask.prototype.run = function() {
|
3701
|
+
if(this.rejection.reported) {
|
3702
|
+
Promise.onPotentiallyUnhandledRejectionHandled(this.rejection);
|
3703
|
+
}
|
3704
|
+
};
|
3705
|
+
|
3706
|
+
// Unhandled rejection hooks
|
3707
|
+
// By default, everything is a noop
|
3708
|
+
|
3709
|
+
// TODO: Better names: "annotate"?
|
3710
|
+
Promise.createContext
|
3711
|
+
= Promise.enterContext
|
3712
|
+
= Promise.exitContext
|
3713
|
+
= Promise.onPotentiallyUnhandledRejection
|
3714
|
+
= Promise.onPotentiallyUnhandledRejectionHandled
|
3715
|
+
= Promise.onFatalRejection
|
3716
|
+
= noop;
|
3717
|
+
|
3718
|
+
// Errors and singletons
|
3719
|
+
|
3720
|
+
var foreverPendingHandler = new Handler();
|
3721
|
+
var foreverPendingPromise = new Promise(Handler, foreverPendingHandler);
|
3722
|
+
|
3723
|
+
function cycle() {
|
3724
|
+
return new Rejected(new TypeError('Promise cycle'));
|
3725
|
+
}
|
3726
|
+
|
3727
|
+
// Task runners
|
3728
|
+
|
3729
|
+
/**
|
3730
|
+
* Run a single consumer
|
3731
|
+
* @constructor
|
3732
|
+
*/
|
3733
|
+
function ContinuationTask(continuation, handler) {
|
3734
|
+
this.continuation = continuation;
|
3735
|
+
this.handler = handler;
|
3736
|
+
}
|
3737
|
+
|
3738
|
+
ContinuationTask.prototype.run = function() {
|
3739
|
+
this.handler.join().when(this.continuation);
|
3740
|
+
};
|
3741
|
+
|
3742
|
+
/**
|
3743
|
+
* Run a queue of progress handlers
|
3744
|
+
* @constructor
|
3745
|
+
*/
|
3746
|
+
function ProgressTask(value, handler) {
|
3747
|
+
this.handler = handler;
|
3748
|
+
this.value = value;
|
3749
|
+
}
|
3750
|
+
|
3751
|
+
ProgressTask.prototype.run = function() {
|
3752
|
+
var q = this.handler.consumers;
|
3753
|
+
if(q === void 0) {
|
3754
|
+
return;
|
3755
|
+
}
|
3756
|
+
|
3757
|
+
for (var c, i = 0; i < q.length; ++i) {
|
3758
|
+
c = q[i];
|
3759
|
+
runNotify(c.progress, this.value, this.handler, c.receiver, c.resolver);
|
3760
|
+
}
|
3761
|
+
};
|
3762
|
+
|
3763
|
+
/**
|
3764
|
+
* Assimilate a thenable, sending it's value to resolver
|
3765
|
+
* @param {function} then
|
3766
|
+
* @param {object|function} thenable
|
3767
|
+
* @param {object} resolver
|
3768
|
+
* @constructor
|
3769
|
+
*/
|
3770
|
+
function AssimilateTask(then, thenable, resolver) {
|
3771
|
+
this._then = then;
|
3772
|
+
this.thenable = thenable;
|
3773
|
+
this.resolver = resolver;
|
3774
|
+
}
|
3775
|
+
|
3776
|
+
AssimilateTask.prototype.run = function() {
|
3777
|
+
var h = this.resolver;
|
3778
|
+
tryAssimilate(this._then, this.thenable, _resolve, _reject, _notify);
|
3779
|
+
|
3780
|
+
function _resolve(x) { h.resolve(x); }
|
3781
|
+
function _reject(x) { h.reject(x); }
|
3782
|
+
function _notify(x) { h.notify(x); }
|
3783
|
+
};
|
3784
|
+
|
3785
|
+
function tryAssimilate(then, thenable, resolve, reject, notify) {
|
3786
|
+
try {
|
3787
|
+
then.call(thenable, resolve, reject, notify);
|
3788
|
+
} catch (e) {
|
3789
|
+
reject(e);
|
3790
|
+
}
|
3791
|
+
}
|
3792
|
+
|
3793
|
+
// Other helpers
|
3794
|
+
|
3795
|
+
/**
|
3796
|
+
* @param {*} x
|
3797
|
+
* @returns {boolean} true iff x is a trusted Promise
|
3798
|
+
*/
|
3799
|
+
function isPromise(x) {
|
3800
|
+
return x instanceof Promise;
|
3801
|
+
}
|
3802
|
+
|
3803
|
+
/**
|
3804
|
+
* Test just enough to rule out primitives, in order to take faster
|
3805
|
+
* paths in some code
|
3806
|
+
* @param {*} x
|
3807
|
+
* @returns {boolean} false iff x is guaranteed *not* to be a thenable
|
3808
|
+
*/
|
3809
|
+
function maybeThenable(x) {
|
3810
|
+
return (typeof x === 'object' || typeof x === 'function') && x !== null;
|
3811
|
+
}
|
3812
|
+
|
3813
|
+
function runContinuation1(f, h, receiver, next) {
|
3814
|
+
if(typeof f !== 'function') {
|
3815
|
+
return next.become(h);
|
3816
|
+
}
|
3817
|
+
|
3818
|
+
Promise.enterContext(h);
|
3819
|
+
tryCatchReject(f, h.value, receiver, next);
|
3820
|
+
Promise.exitContext();
|
3821
|
+
}
|
3822
|
+
|
3823
|
+
function runContinuation3(f, x, h, receiver, next) {
|
3824
|
+
if(typeof f !== 'function') {
|
3825
|
+
return next.become(h);
|
3826
|
+
}
|
3827
|
+
|
3828
|
+
Promise.enterContext(h);
|
3829
|
+
tryCatchReject3(f, x, h.value, receiver, next);
|
3830
|
+
Promise.exitContext();
|
3831
|
+
}
|
3832
|
+
|
3833
|
+
function runNotify(f, x, h, receiver, next) {
|
3834
|
+
if(typeof f !== 'function') {
|
3835
|
+
return next.notify(x);
|
3836
|
+
}
|
3837
|
+
|
3838
|
+
Promise.enterContext(h);
|
3839
|
+
tryCatchReturn(f, x, receiver, next);
|
3840
|
+
Promise.exitContext();
|
3841
|
+
}
|
3842
|
+
|
3843
|
+
/**
|
3844
|
+
* Return f.call(thisArg, x), or if it throws return a rejected promise for
|
3845
|
+
* the thrown exception
|
3846
|
+
*/
|
3847
|
+
function tryCatchReject(f, x, thisArg, next) {
|
3848
|
+
try {
|
3849
|
+
next.become(getHandler(f.call(thisArg, x)));
|
3850
|
+
} catch(e) {
|
3851
|
+
next.become(new Rejected(e));
|
3852
|
+
}
|
3853
|
+
}
|
3854
|
+
|
3855
|
+
/**
|
3856
|
+
* Same as above, but includes the extra argument parameter.
|
3857
|
+
*/
|
3858
|
+
function tryCatchReject3(f, x, y, thisArg, next) {
|
3859
|
+
try {
|
3860
|
+
f.call(thisArg, x, y, next);
|
3861
|
+
} catch(e) {
|
3862
|
+
next.become(new Rejected(e));
|
3863
|
+
}
|
3864
|
+
}
|
3865
|
+
|
3866
|
+
/**
|
3867
|
+
* Return f.call(thisArg, x), or if it throws, *return* the exception
|
3868
|
+
*/
|
3869
|
+
function tryCatchReturn(f, x, thisArg, next) {
|
3870
|
+
try {
|
3871
|
+
next.notify(f.call(thisArg, x));
|
3872
|
+
} catch(e) {
|
3873
|
+
next.notify(e);
|
3874
|
+
}
|
3875
|
+
}
|
3876
|
+
|
3877
|
+
function inherit(Parent, Child) {
|
3878
|
+
Child.prototype = objectCreate(Parent.prototype);
|
3879
|
+
Child.prototype.constructor = Child;
|
3880
|
+
}
|
3881
|
+
|
3882
|
+
function noop() {}
|
3883
|
+
|
3884
|
+
return Promise;
|
3885
|
+
};
|
3886
|
+
});
|
3887
|
+
}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
|
3888
|
+
|
3889
|
+
},{}]},{},[10])
|
3890
|
+
(10)
|
3891
|
+
});
|