@@ -7,45 +7,33 @@ import {services} from "../common/coreservices";
77import { PathFactory } from "../path/pathFactory" ;
88import { PathNode } from "../path/node" ;
99
10- import { ViewService } from "../view/view" ;
11-
12- import { StateParams } from "../params/stateParams" ;
13-
14- import { UrlRouter } from "../url/urlRouter" ;
15-
1610import { TransitionOptions } from "../transition/interface" ;
17- import { TransitionService , defaultTransOpts } from "../transition/transitionService" ;
18- import { Rejection } from "../transition/rejectFactory" ;
11+ import { defaultTransOpts } from "../transition/transitionService" ;
12+ import { Rejection , RejectType } from "../transition/rejectFactory" ;
1913import { Transition } from "../transition/transition" ;
2014
2115import { StateOrName , StateDeclaration , TransitionPromise } from "./interface" ;
22- import { StateRegistry } from "./stateRegistry" ;
2316import { State } from "./stateObject" ;
2417import { TargetState } from "./targetState" ;
2518
2619import { RawParams } from "../params/interface" ;
2720import { ParamsOrArray } from "../params/interface" ;
28- import { TransitionManager } from "../hooks/transitionManager" ;
2921import { Param } from "../params/param" ;
3022import { Glob } from "../common/glob" ;
3123import { equalForKeys } from "../common/common" ;
3224import { HrefOptions } from "./interface" ;
33- import { StateProvider } from "./state" ;
3425import { bindFunctions } from "../common/common" ;
35- import { UiRouterGlobals , Globals } from "../globals" ;
26+ import { Globals } from "../globals" ;
27+ import { UiRouter } from "../router" ;
28+ import { StateParams } from "../params/stateParams" ; // for params() return type
3629
3730export class StateService {
38- get transition ( ) { return this . globals . transition ; }
39- get params ( ) { return this . globals . params ; }
40- get current ( ) { return this . globals . current ; }
41- get $current ( ) { return this . globals . $current ; }
42-
43- constructor ( private $view : ViewService ,
44- private $urlRouter : UrlRouter ,
45- private $transitions : TransitionService ,
46- private stateRegistry : StateRegistry ,
47- private stateProvider : StateProvider ,
48- private globals : Globals ) {
31+ get transition ( ) { return this . router . globals . transition ; }
32+ get params ( ) { return this . router . globals . params ; }
33+ get current ( ) { return this . router . globals . current ; }
34+ get $current ( ) { return this . router . globals . $current ; }
35+
36+ constructor ( private router : UiRouter ) {
4937 let getters = [ 'current' , '$current' , 'params' , 'transition' ] ;
5038 let boundFns = Object . keys ( StateService . prototype ) . filter ( key => getters . indexOf ( key ) === - 1 ) ;
5139 bindFunctions ( StateService . prototype , this , this , boundFns ) ;
@@ -60,10 +48,11 @@ export class StateService {
6048 * the result returned.
6149 */
6250 private _handleInvalidTargetState ( fromPath : PathNode [ ] , $to$ : TargetState ) {
63- const latestThing = ( ) => this . globals . transitionHistory . peekTail ( ) ;
51+ let globals = < Globals > this . router . globals ;
52+ const latestThing = ( ) => globals . transitionHistory . peekTail ( ) ;
6453 let latest = latestThing ( ) ;
6554 let $from$ = PathFactory . makeTargetState ( fromPath ) ;
66- let callbackQueue = new Queue < Function > ( [ ] . concat ( this . stateProvider . invalidCallbacks ) ) ;
55+ let callbackQueue = new Queue < Function > ( [ ] . concat ( this . router . stateProvider . invalidCallbacks ) ) ;
6756 let { $q, $injector} = services ;
6857
6958 const invokeCallback = ( callback : Function ) => $q . when ( $injector . invoke ( callback , null , { $to$, $from$ } ) ) ;
@@ -221,12 +210,13 @@ export class StateService {
221210 // If we're reloading, find the state object to reload from
222211 if ( isObject ( options . reload ) && ! ( < any > options . reload ) . name )
223212 throw new Error ( 'Invalid reload state object' ) ;
224- options . reloadState = options . reload === true ? this . stateRegistry . root ( ) : this . stateRegistry . matcher . find ( < any > options . reload , options . relative ) ;
213+ let reg = this . router . stateRegistry ;
214+ options . reloadState = options . reload === true ? reg . root ( ) : reg . matcher . find ( < any > options . reload , options . relative ) ;
225215
226216 if ( options . reload && ! options . reloadState )
227217 throw new Error ( `No such reload state '${ ( isString ( options . reload ) ? options . reload : ( < any > options . reload ) . name ) } '` ) ;
228218
229- let stateDefinition = this . stateRegistry . matcher . find ( identifier , options . relative ) ;
219+ let stateDefinition = reg . matcher . find ( identifier , options . relative ) ;
230220 return new TargetState ( identifier , stateDefinition , params , options ) ;
231221 } ;
232222
@@ -269,25 +259,56 @@ export class StateService {
269259 * {@link ui.router.state.$state#methods_go $state.go}.
270260 */
271261 transitionTo ( to : StateOrName , toParams : RawParams = { } , options : TransitionOptions = { } ) : TransitionPromise {
272- let transHistory = this . globals . transitionHistory ;
262+ let router = this . router ;
263+ let globals = < Globals > router . globals ;
264+ let transHistory = globals . transitionHistory ;
273265 options = defaults ( options , defaultTransOpts ) ;
274266 options = extend ( options , { current : transHistory . peekTail . bind ( transHistory ) } ) ;
275267
276268 let ref : TargetState = this . target ( to , toParams , options ) ;
277- let latestSuccess : Transition = this . globals . successfulTransitions . peekTail ( ) ;
278- const rootPath = ( ) => [ new PathNode ( this . stateRegistry . root ( ) ) ] ;
269+ let latestSuccess : Transition = globals . successfulTransitions . peekTail ( ) ;
270+ const rootPath = ( ) => [ new PathNode ( this . router . stateRegistry . root ( ) ) ] ;
279271 let currentPath : PathNode [ ] = latestSuccess ? latestSuccess . treeChanges ( ) . to : rootPath ( ) ;
280272
281273 if ( ! ref . exists ( ) )
282274 return this . _handleInvalidTargetState ( currentPath , ref ) ;
275+
283276 if ( ! ref . valid ( ) )
284277 return services . $q . reject ( ref . error ( ) ) ;
285278
286- let transition = this . $transitions . create ( currentPath , ref ) ;
287- let tMgr = new TransitionManager ( transition , this . $transitions , this . $urlRouter , this . $view , < StateService > this , this . globals ) ;
288- let transitionPromise = tMgr . runTransition ( ) ;
279+ /**
280+ * Special handling for Ignored, Aborted, and Redirected transitions
281+ *
282+ * The semantics for the transition.run() promise and the StateService.transitionTo()
283+ * promise differ. For instance, the run() promise may be rejected because it was
284+ * IGNORED, but the transitionTo() promise is resolved because from the user perspective
285+ * no error occurred. Likewise, the transition.run() promise may be rejected because of
286+ * a Redirect, but the transitionTo() promise is chained to the new Transition's promise.
287+ */
288+ const rejectedTransitionHandler = ( transition ) => ( error ) => {
289+ if ( error instanceof Rejection ) {
290+ if ( error . type === RejectType . IGNORED ) {
291+ router . urlRouter . update ( ) ;
292+ return globals . current ;
293+ }
294+
295+ if ( error . type === RejectType . SUPERSEDED && error . redirected && error . detail instanceof TargetState ) {
296+ let redirect : Transition = transition . redirect ( error . detail ) ;
297+ return redirect . run ( ) . catch ( rejectedTransitionHandler ( redirect ) ) ;
298+ }
299+
300+ if ( error . type === RejectType . ABORTED ) {
301+ router . urlRouter . update ( ) ;
302+ }
303+ }
304+
305+ return services . $q . reject ( error ) ;
306+ } ;
307+
308+ let transition = this . router . transitionService . create ( currentPath , ref ) ;
309+ let transitionToPromise = transition . run ( ) . catch ( rejectedTransitionHandler ( transition ) ) ;
289310 // Return a promise for the transition, which also has the transition object on it.
290- return extend ( transitionPromise , { transition } ) ;
311+ return extend ( transitionToPromise , { transition } ) ;
291312 } ;
292313
293314 /**
@@ -326,7 +347,7 @@ export class StateService {
326347 */
327348 is ( stateOrName : StateOrName , params ?: RawParams , options ?: TransitionOptions ) : boolean {
328349 options = defaults ( options , { relative : this . $current } ) ;
329- let state = this . stateRegistry . matcher . find ( stateOrName , options . relative ) ;
350+ let state = this . router . stateRegistry . matcher . find ( stateOrName , options . relative ) ;
330351 if ( ! isDefined ( state ) ) return undefined ;
331352 if ( this . $current !== state ) return false ;
332353 return isDefined ( params ) && params !== null ? Param . equals ( state . parameters ( ) , this . params , params ) : true ;
@@ -391,7 +412,7 @@ export class StateService {
391412 if ( ! glob . matches ( this . $current . name ) ) return false ;
392413 stateOrName = this . $current . name ;
393414 }
394- let state = this . stateRegistry . matcher . find ( stateOrName , options . relative ) , include = this . $current . includes ;
415+ let state = this . router . stateRegistry . matcher . find ( stateOrName , options . relative ) , include = this . $current . includes ;
395416
396417 if ( ! isDefined ( state ) ) return undefined ;
397418 if ( ! isDefined ( include [ state . name ] ) ) return false ;
@@ -436,7 +457,7 @@ export class StateService {
436457 } ;
437458 options = defaults ( options , defaultHrefOpts ) ;
438459
439- let state = this . stateRegistry . matcher . find ( stateOrName , options . relative ) ;
460+ let state = this . router . stateRegistry . matcher . find ( stateOrName , options . relative ) ;
440461
441462 if ( ! isDefined ( state ) ) return null ;
442463 if ( options . inherit ) params = < any > this . params . $inherit ( params || { } , this . $current , state ) ;
@@ -446,7 +467,7 @@ export class StateService {
446467 if ( ! nav || nav . url === undefined || nav . url === null ) {
447468 return null ;
448469 }
449- return this . $ urlRouter. href ( nav . url , Param . values ( state . parameters ( ) , params ) , {
470+ return this . router . urlRouter . href ( nav . url , Param . values ( state . parameters ( ) , params ) , {
450471 absolute : options . absolute
451472 } ) ;
452473 } ;
@@ -468,7 +489,8 @@ export class StateService {
468489 get ( stateOrName : StateOrName ) : StateDeclaration ;
469490 get ( stateOrName : StateOrName , base : StateOrName ) : StateDeclaration ;
470491 get ( stateOrName ?: StateOrName , base ?: StateOrName ) : any {
471- if ( arguments . length === 0 ) return this . stateRegistry . get ( ) ;
472- return this . stateRegistry . get ( stateOrName , base || this . $current ) ;
492+ let reg = this . router . stateRegistry ;
493+ if ( arguments . length === 0 ) return reg . get ( ) ;
494+ return reg . get ( stateOrName , base || this . $current ) ;
473495 }
474496}
0 commit comments