@@ -248,6 +248,14 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
248248 var TransitionPrevented = $q . reject ( new Error ( 'transition prevented' ) ) ;
249249 var TransitionAborted = $q . reject ( new Error ( 'transition aborted' ) ) ;
250250 var TransitionFailed = $q . reject ( new Error ( 'transition failed' ) ) ;
251+ var currentLocation = $location . url ( ) ;
252+
253+ function syncUrl ( ) {
254+ if ( $location . url ( ) !== currentLocation ) {
255+ $location . url ( currentLocation ) ;
256+ $location . replace ( ) ;
257+ }
258+ }
251259
252260 root . locals = { resolve : null , globals : { $stateParams : { } } } ;
253261 $state = {
@@ -267,20 +275,23 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
267275 options = extend ( { location : true , inherit : false , relative : null , notify : true , $retry : false } , options ) ;
268276
269277 var from = $state . $current , fromParams = $state . params , fromPath = from . path ;
270-
271- var toState = findState ( to , options . relative ) ;
272-
273- var evt ;
278+ var evt , toState = findState ( to , options . relative ) ;
274279
275280 if ( ! isDefined ( toState ) ) {
276281 // Broadcast not found event and abort the transition if prevented
277282 var redirect = { to : to , toParams : toParams , options : options } ;
278283 evt = $rootScope . $broadcast ( '$stateNotFound' , redirect , from . self , fromParams ) ;
279- if ( evt . defaultPrevented ) return TransitionAborted ;
284+ if ( evt . defaultPrevented ) {
285+ syncUrl ( ) ;
286+ return TransitionAborted ;
287+ }
280288
281289 // Allow the handler to return a promise to defer state lookup retry
282290 if ( evt . retry ) {
283- if ( options . $retry ) return TransitionFailed ;
291+ if ( options . $retry ) {
292+ syncUrl ( ) ;
293+ return TransitionFailed ;
294+ }
284295 var retryTransition = $state . transition = $q . when ( evt . retry ) ;
285296 retryTransition . then ( function ( ) {
286297 if ( retryTransition !== $state . transition ) return TransitionSuperseded ;
@@ -290,6 +301,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
290301 function ( ) {
291302 return TransitionAborted ;
292303 } ) ;
304+ syncUrl ( ) ;
293305 return retryTransition ;
294306 }
295307
@@ -323,6 +335,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
323335 // TODO: We may not want to bump 'transition' if we're called from a location change that we've initiated ourselves,
324336 // because we might accidentally abort a legitimate transition initiated from code?
325337 if ( to === from && locals === from . locals ) {
338+ syncUrl ( ) ;
326339 $state . transition = null ;
327340 return $q . when ( $state . current ) ;
328341 }
@@ -333,7 +346,10 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
333346 // Broadcast start event and cancel the transition if requested
334347 if ( options . notify ) {
335348 evt = $rootScope . $broadcast ( '$stateChangeStart' , to . self , toParams , from . self , fromParams ) ;
336- if ( evt . defaultPrevented ) return TransitionPrevented ;
349+ if ( evt . defaultPrevented ) {
350+ syncUrl ( ) ;
351+ return TransitionPrevented ;
352+ }
337353 }
338354
339355 // Resolve locals for the remaining states, but don't update any global state just
@@ -399,13 +415,15 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
399415 if ( options . notify ) {
400416 $rootScope . $broadcast ( '$stateChangeSuccess' , to . self , toParams , from . self , fromParams ) ;
401417 }
418+ currentLocation = $location . url ( ) ;
402419
403420 return $state . current ;
404421 } , function ( error ) {
405422 if ( $state . transition !== transition ) return TransitionSuperseded ;
406423
407424 $state . transition = null ;
408425 $rootScope . $broadcast ( '$stateChangeError' , to . self , toParams , from . self , fromParams , error ) ;
426+ syncUrl ( ) ;
409427
410428 return $q . reject ( error ) ;
411429 } ) ;
0 commit comments