Comparing version 7.1.1 to 7.2.0
@@ -0,1 +1,25 @@ | ||
## v7.2.0 (2021-03-07) | ||
#### :bug: Bug Fix | ||
* [#319](https://github.com/tildeio/router.js/pull/319) Ensure query params are preserved through an intermediate loading state transition ([@sly7-7](https://github.com/sly7-7)) | ||
#### :memo: Documentation | ||
* [#316](https://github.com/tildeio/router.js/pull/316) Publish type declaration ([@xg-wang](https://github.com/xg-wang)) | ||
#### :house: Internal | ||
* [#318](https://github.com/tildeio/router.js/pull/318) add livereload so tests reload when i make changes ([@stefanpenner](https://github.com/stefanpenner)) | ||
* [#309](https://github.com/tildeio/router.js/pull/309) Refactor TransitionAbort to builder interface ([@rwjblue](https://github.com/rwjblue)) | ||
* [#306](https://github.com/tildeio/router.js/pull/306) Simplify TransitionState resolution system. ([@rwjblue](https://github.com/rwjblue)) | ||
* [#314](https://github.com/tildeio/router.js/pull/314) [Closes [#313](https://github.com/tildeio/router.js/issues/313)] Fix Typo shouldSupercede -> shouldSupersede ([@stefanpenner](https://github.com/stefanpenner)) | ||
* [#315](https://github.com/tildeio/router.js/pull/315) Fix other typo’s ([@stefanpenner](https://github.com/stefanpenner)) | ||
* [#312](https://github.com/tildeio/router.js/pull/312) Upgrade `devDependencies` ([@stefanpenner](https://github.com/stefanpenner)) | ||
* [#311](https://github.com/tildeio/router.js/pull/311) Upgrade CI ([@stefanpenner](https://github.com/stefanpenner)) | ||
#### Committers: 4 | ||
- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) | ||
- Stefan Penner ([@stefanpenner](https://github.com/stefanpenner)) | ||
- Sylvain MINA ([@sly7-7](https://github.com/sly7-7)) | ||
- Thomas Wang ([@xg-wang](https://github.com/xg-wang)) | ||
## v7.1.1 (2020-11-06) | ||
@@ -2,0 +26,0 @@ |
@@ -1,1 +0,5 @@ | ||
"use strict"; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); |
@@ -27,3 +27,2 @@ import { Promise } from 'rsvp'; | ||
} | ||
export declare type Continuation = () => PromiseLike<boolean> | boolean; | ||
export interface RouteInfo { | ||
@@ -57,5 +56,5 @@ readonly name: string; | ||
serialize(_context?: Dict<unknown>): Dict<unknown> | undefined; | ||
resolve(shouldContinue: Continuation, transition: InternalTransition<T>): Promise<ResolvedRouteInfo<T>>; | ||
resolve(transition: InternalTransition<T>): Promise<ResolvedRouteInfo<T>>; | ||
becomeResolved(transition: InternalTransition<T> | null, resolvedContext: Dict<unknown>): ResolvedRouteInfo<T>; | ||
shouldSupercede(routeInfo?: InternalRouteInfo<T>): boolean; | ||
shouldSupersede(routeInfo?: InternalRouteInfo<T>): boolean; | ||
get route(): T | undefined; | ||
@@ -69,3 +68,2 @@ set route(route: T | undefined); | ||
private runAfterModelHook; | ||
private checkForAbort; | ||
private stashResolvedModel; | ||
@@ -78,3 +76,3 @@ private fetchRoute; | ||
constructor(router: Router<T>, name: string, paramNames: string[], params: Dict<unknown>, route: T, context?: Dict<unknown>); | ||
resolve(_shouldContinue: Continuation, transition: InternalTransition<T>): Promise<InternalRouteInfo<T>>; | ||
resolve(transition: InternalTransition<T>): Promise<InternalRouteInfo<T>>; | ||
} | ||
@@ -81,0 +79,0 @@ export declare class UnresolvedRouteInfoByParam<T extends Route> extends InternalRouteInfo<T> { |
@@ -15,2 +15,4 @@ "use strict"; | ||
var _transitionAbortedError = require("./transition-aborted-error"); | ||
let ROUTE_INFOS = new WeakMap(); | ||
@@ -173,4 +175,10 @@ | ||
resolve(shouldContinue, transition) { | ||
return _rsvp.Promise.resolve(this.routePromise).then(route => this.checkForAbort(shouldContinue, route)).then(() => this.runBeforeModelHook(transition)).then(() => this.checkForAbort(shouldContinue, null)).then(() => this.getModel(transition)).then(resolvedModel => this.checkForAbort(shouldContinue, resolvedModel)).then(resolvedModel => this.runAfterModelHook(transition, resolvedModel)).then(resolvedModel => this.becomeResolved(transition, resolvedModel)); | ||
resolve(transition) { | ||
return _rsvp.Promise.resolve(this.routePromise).then(route => { | ||
(0, _transitionAbortedError.throwIfAborted)(transition); | ||
return route; | ||
}).then(() => this.runBeforeModelHook(transition)).then(() => (0, _transitionAbortedError.throwIfAborted)(transition)).then(() => this.getModel(transition)).then(resolvedModel => { | ||
(0, _transitionAbortedError.throwIfAborted)(transition); | ||
return resolvedModel; | ||
}).then(resolvedModel => this.runAfterModelHook(transition, resolvedModel)).then(resolvedModel => this.becomeResolved(transition, resolvedModel)); | ||
} | ||
@@ -204,3 +212,3 @@ | ||
shouldSupercede(routeInfo) { | ||
shouldSupersede(routeInfo) { | ||
// Prefer this newer routeInfo over `other` if: | ||
@@ -301,10 +309,2 @@ // 1) The other one doesn't exist | ||
checkForAbort(shouldContinue, value) { | ||
return _rsvp.Promise.resolve(shouldContinue()).then(function () { | ||
// We don't care about shouldContinue's resolve value; | ||
// pass along the original value passed to this fn. | ||
return value; | ||
}, null); | ||
} | ||
stashResolvedModel(transition, resolvedModel) { | ||
@@ -350,3 +350,3 @@ transition.resolvedModels = transition.resolvedModels || {}; | ||
resolve(_shouldContinue, transition) { | ||
resolve(transition) { | ||
// A ResolvedRouteInfo just resolved with itself. | ||
@@ -353,0 +353,0 @@ if (transition && transition.resolvedModels) { |
@@ -16,3 +16,3 @@ "use strict"; | ||
var _transitionAbortedError = _interopRequireDefault(require("./transition-aborted-error")); | ||
var _transitionAbortedError = require("./transition-aborted-error"); | ||
@@ -277,3 +277,3 @@ var _namedTransitionIntent = _interopRequireDefault(require("./transition-intent/named-transition-intent")); | ||
} catch (e) { | ||
if (!(e instanceof _transitionAbortedError.default)) { | ||
if (!(0, _transitionAbortedError.isTransitionAborted)(e)) { | ||
let infos = transition[_transition.STATE_SYMBOL].routeInfos; | ||
@@ -408,6 +408,3 @@ transition.trigger(true, 'error', e, transition, infos[infos.length - 1].route); | ||
if (transition && transition.isAborted) { | ||
throw new _transitionAbortedError.default(); | ||
} | ||
(0, _transitionAbortedError.throwIfAborted)(transition); | ||
route.context = context; | ||
@@ -423,6 +420,3 @@ | ||
if (transition && transition.isAborted) { | ||
throw new _transitionAbortedError.default(); | ||
} | ||
(0, _transitionAbortedError.throwIfAborted)(transition); | ||
currentRouteInfos.push(routeInfo); | ||
@@ -557,3 +551,3 @@ return route; | ||
let initial = transition.isCausedByInitialTransition; // say you are at / and you click a link to route /foo. In /foo's | ||
// route, the transition is aborted using replacewith('/bar'). | ||
// route, the transition is aborted using replaceWith('/bar'). | ||
// Because the current url is still /, the history entry for / is | ||
@@ -813,6 +807,6 @@ // removed from the history. Clicking back will take you to the page | ||
let targetHandler = targetRouteInfos[targetRouteInfos.length - 1].name; | ||
let recogHandlers = this.recognizer.handlersFor(targetHandler); | ||
let recognizerHandlers = this.recognizer.handlersFor(targetHandler); | ||
let index = 0; | ||
for (len = recogHandlers.length; index < len; ++index) { | ||
for (len = recognizerHandlers.length; index < len; ++index) { | ||
routeInfo = targetRouteInfos[index]; | ||
@@ -825,3 +819,3 @@ | ||
if (index === recogHandlers.length) { | ||
if (index === recognizerHandlers.length) { | ||
// The provided route name isn't even in the route hierarchy. | ||
@@ -833,5 +827,5 @@ return false; | ||
testState.routeInfos = targetRouteInfos.slice(0, index + 1); | ||
recogHandlers = recogHandlers.slice(0, index + 1); | ||
recognizerHandlers = recognizerHandlers.slice(0, index + 1); | ||
let intent = new _namedTransitionIntent.default(this, targetHandler, undefined, contexts); | ||
let newState = intent.applyToHandlers(testState, recogHandlers, targetHandler, true, true); | ||
let newState = intent.applyToHandlers(testState, recognizerHandlers, targetHandler, true, true); | ||
let routesEqual = routeInfosEqual(newState.routeInfos, testState.routeInfos); | ||
@@ -838,0 +832,0 @@ |
@@ -1,9 +0,13 @@ | ||
export interface TransitionAbortedErrorContructor { | ||
new (message?: string): ITransitionAbortedError; | ||
readonly prototype: ITransitionAbortedError; | ||
export interface TransitionAbortedError extends Error { | ||
name: 'TransitionAborted'; | ||
code: 'TRANSITION_ABORTED'; | ||
} | ||
export interface ITransitionAbortedError extends Error { | ||
constructor: TransitionAbortedErrorContructor; | ||
export declare function buildTransitionAborted(): TransitionAbortedError; | ||
export declare function isTransitionAborted(maybeError: unknown): maybeError is TransitionAbortedError; | ||
interface Abortable<T extends boolean> { | ||
isAborted: T; | ||
[key: string]: unknown; | ||
} | ||
declare const TransitionAbortedError: TransitionAbortedErrorContructor; | ||
export default TransitionAbortedError; | ||
export declare function throwIfAborted(maybe: Abortable<true>): never; | ||
export declare function throwIfAborted(maybe: unknown): void; | ||
export {}; |
@@ -6,24 +6,25 @@ "use strict"; | ||
}); | ||
exports.default = void 0; | ||
exports.buildTransitionAborted = buildTransitionAborted; | ||
exports.isTransitionAborted = isTransitionAborted; | ||
exports.throwIfAborted = throwIfAborted; | ||
const TransitionAbortedError = function () { | ||
TransitionAbortedError.prototype = Object.create(Error.prototype); | ||
TransitionAbortedError.prototype.constructor = TransitionAbortedError; | ||
function buildTransitionAborted() { | ||
let error = new Error('TransitionAborted'); | ||
error.name = 'TransitionAborted'; | ||
error.code = 'TRANSITION_ABORTED'; | ||
return error; | ||
} | ||
function TransitionAbortedError(message) { | ||
let error = Error.call(this, message); | ||
this.name = 'TransitionAborted'; | ||
this.message = message || 'TransitionAborted'; | ||
function isTransitionAborted(maybeError) { | ||
return typeof maybeError === 'object' && maybeError !== null && maybeError.code === 'TRANSITION_ABORTED'; | ||
} | ||
if (Error.captureStackTrace) { | ||
Error.captureStackTrace(this, TransitionAbortedError); | ||
} else { | ||
this.stack = error.stack; | ||
} | ||
function isAbortable(maybeAbortable) { | ||
return typeof maybeAbortable === 'object' && maybeAbortable !== null && typeof maybeAbortable.isAborted === 'boolean'; | ||
} | ||
function throwIfAborted(maybe) { | ||
if (isAbortable(maybe) && maybe.isAborted) { | ||
throw buildTransitionAborted(); | ||
} | ||
return TransitionAbortedError; | ||
}(); | ||
var _default = TransitionAbortedError; | ||
exports.default = _default; | ||
} |
@@ -10,3 +10,3 @@ import { Route } from './route-info'; | ||
preTransitionState?: TransitionState<T>; | ||
abstract applyToState(oldState: TransitionState<T>, isIntermidate: boolean): TransitionState<T>; | ||
abstract applyToState(oldState: TransitionState<T>, isIntermediate: boolean): TransitionState<T>; | ||
} |
@@ -91,3 +91,3 @@ "use strict"; | ||
if (i >= invalidateIndex || newHandlerInfo.shouldSupercede(oldHandlerInfo)) { | ||
if (i >= invalidateIndex || newHandlerInfo.shouldSupersede(oldHandlerInfo)) { | ||
invalidateIndex = Math.min(i, invalidateIndex); | ||
@@ -113,2 +113,7 @@ handlerToUse = newHandlerInfo; | ||
(0, _utils.merge)(newState.queryParams, this.queryParams || {}); | ||
if (isIntermediate && oldState.queryParams) { | ||
(0, _utils.merge)(newState.queryParams, oldState.queryParams); | ||
} | ||
return newState; | ||
@@ -115,0 +120,0 @@ } |
@@ -65,3 +65,3 @@ "use strict"; | ||
} else { | ||
// If the hanlder is being loaded asynchronously, check if we can | ||
// If the handler is being loaded asynchronously, check if we can | ||
// access it after it has resolved | ||
@@ -73,3 +73,3 @@ newRouteInfo.routePromise = newRouteInfo.routePromise.then(checkHandlerAccessibility); | ||
if (statesDiffer || newRouteInfo.shouldSupercede(oldRouteInfo)) { | ||
if (statesDiffer || newRouteInfo.shouldSupersede(oldRouteInfo)) { | ||
statesDiffer = true; | ||
@@ -76,0 +76,0 @@ newState.routeInfos[i] = newRouteInfo; |
import { Promise } from 'rsvp'; | ||
import { Dict } from './core'; | ||
import InternalRouteInfo, { Continuation, Route } from './route-info'; | ||
import InternalRouteInfo, { Route } from './route-info'; | ||
import Transition from './transition'; | ||
@@ -13,3 +13,3 @@ interface IParams { | ||
promiseLabel(label: string): string; | ||
resolve(shouldContinue: Continuation, transition: Transition<T>): Promise<TransitionState<T>>; | ||
resolve(transition: Transition<T>): Promise<TransitionState<T>>; | ||
} | ||
@@ -16,0 +16,0 @@ export declare class TransitionError { |
@@ -12,2 +12,52 @@ "use strict"; | ||
var _transitionAbortedError = require("./transition-aborted-error"); | ||
function handleError(currentState, transition, error) { | ||
// This is the only possible | ||
// reject value of TransitionState#resolve | ||
let routeInfos = currentState.routeInfos; | ||
let errorHandlerIndex = transition.resolveIndex >= routeInfos.length ? routeInfos.length - 1 : transition.resolveIndex; | ||
let wasAborted = transition.isAborted; | ||
throw new TransitionError(error, currentState.routeInfos[errorHandlerIndex].route, wasAborted, currentState); | ||
} | ||
function resolveOneRouteInfo(currentState, transition) { | ||
if (transition.resolveIndex === currentState.routeInfos.length) { | ||
// This is is the only possible | ||
// fulfill value of TransitionState#resolve | ||
return; | ||
} | ||
let routeInfo = currentState.routeInfos[transition.resolveIndex]; | ||
return routeInfo.resolve(transition).then(proceed.bind(null, currentState, transition), null, currentState.promiseLabel('Proceed')); | ||
} | ||
function proceed(currentState, transition, resolvedRouteInfo) { | ||
let wasAlreadyResolved = currentState.routeInfos[transition.resolveIndex].isResolved; // Swap the previously unresolved routeInfo with | ||
// the resolved routeInfo | ||
currentState.routeInfos[transition.resolveIndex++] = resolvedRouteInfo; | ||
if (!wasAlreadyResolved) { | ||
// Call the redirect hook. The reason we call it here | ||
// vs. afterModel is so that redirects into child | ||
// routes don't re-run the model hooks for this | ||
// already-resolved route. | ||
let { | ||
route | ||
} = resolvedRouteInfo; | ||
if (route !== undefined) { | ||
if (route.redirect) { | ||
route.redirect(resolvedRouteInfo.context, transition); | ||
} | ||
} | ||
} // Proceed after ensuring that the redirect hook | ||
// didn't abort this transition by transitioning elsewhere. | ||
(0, _transitionAbortedError.throwIfAborted)(transition); | ||
return resolveOneRouteInfo(currentState, transition); | ||
} | ||
class TransitionState { | ||
@@ -33,3 +83,3 @@ constructor() { | ||
resolve(shouldContinue, transition) { | ||
resolve(transition) { | ||
// First, calculate params for this state. This is useful | ||
@@ -42,63 +92,5 @@ // information to provide to the various route hooks. | ||
}); | ||
transition.resolveIndex = 0; | ||
let currentState = this; | ||
let wasAborted = false; // The prelude RSVP.resolve() asyncs us into the promise land. | ||
transition.resolveIndex = 0; // The prelude RSVP.resolve() async moves us into the promise land. | ||
return _rsvp.Promise.resolve(null, this.promiseLabel('Start transition')).then(resolveOneRouteInfo, null, this.promiseLabel('Resolve route')).catch(handleError, this.promiseLabel('Handle error')); | ||
function innerShouldContinue() { | ||
return _rsvp.Promise.resolve(shouldContinue(), currentState.promiseLabel('Check if should continue')).catch(function (reason) { | ||
// We distinguish between errors that occurred | ||
// during resolution (e.g. before"Model/model/afterModel), | ||
// and aborts due to a rejecting promise from shouldContinue(). | ||
wasAborted = true; | ||
return _rsvp.Promise.reject(reason); | ||
}, currentState.promiseLabel('Handle abort')); | ||
} | ||
function handleError(error) { | ||
// This is the only possible | ||
// reject value of TransitionState#resolve | ||
let routeInfos = currentState.routeInfos; | ||
let errorHandlerIndex = transition.resolveIndex >= routeInfos.length ? routeInfos.length - 1 : transition.resolveIndex; | ||
return _rsvp.Promise.reject(new TransitionError(error, currentState.routeInfos[errorHandlerIndex].route, wasAborted, currentState)); | ||
} | ||
function proceed(resolvedRouteInfo) { | ||
let wasAlreadyResolved = currentState.routeInfos[transition.resolveIndex].isResolved; // Swap the previously unresolved routeInfo with | ||
// the resolved routeInfo | ||
currentState.routeInfos[transition.resolveIndex++] = resolvedRouteInfo; | ||
if (!wasAlreadyResolved) { | ||
// Call the redirect hook. The reason we call it here | ||
// vs. afterModel is so that redirects into child | ||
// routes don't re-run the model hooks for this | ||
// already-resolved route. | ||
let { | ||
route | ||
} = resolvedRouteInfo; | ||
if (route !== undefined) { | ||
if (route.redirect) { | ||
route.redirect(resolvedRouteInfo.context, transition); | ||
} | ||
} | ||
} // Proceed after ensuring that the redirect hook | ||
// didn't abort this transition by transitioning elsewhere. | ||
return innerShouldContinue().then(resolveOneRouteInfo, null, currentState.promiseLabel('Resolve route')); | ||
} | ||
function resolveOneRouteInfo() { | ||
if (transition.resolveIndex === currentState.routeInfos.length) { | ||
// This is is the only possible | ||
// fulfill value of TransitionState#resolve | ||
return currentState; | ||
} | ||
let routeInfo = currentState.routeInfos[transition.resolveIndex]; | ||
return routeInfo.resolve(innerShouldContinue, transition).then(proceed, null, currentState.promiseLabel('Proceed')); | ||
} | ||
return _rsvp.Promise.resolve(null, this.promiseLabel('Start transition')).then(resolveOneRouteInfo.bind(null, this, transition), null, this.promiseLabel('Resolve route')).catch(handleError.bind(null, this, transition), this.promiseLabel('Handle error')).then(() => this); | ||
} | ||
@@ -105,0 +97,0 @@ |
@@ -5,3 +5,3 @@ import { Promise } from 'rsvp'; | ||
import Router from './router'; | ||
import { ITransitionAbortedError } from './transition-aborted-error'; | ||
import { TransitionAbortedError } from './transition-aborted-error'; | ||
import { OpaqueIntent } from './transition-intent'; | ||
@@ -17,3 +17,3 @@ import TransitionState from './transition-state'; | ||
/** | ||
A Transition is a thennable (a promise-like object) that represents | ||
A Transition is a thenable (a promise-like object) that represents | ||
an attempt to transition to another route. It can be aborted, either | ||
@@ -113,3 +113,3 @@ explicitly via `abort` or by attempting another transition while a | ||
Forwards to the internal `promise` property which you can | ||
use in situations where you want to pass around a thennable, | ||
use in situations where you want to pass around a thenable, | ||
but not the Transition itself. | ||
@@ -143,3 +143,3 @@ | ||
Forwards to the internal `promise` property which you can | ||
use in situations where you want to pass around a thennable, | ||
use in situations where you want to pass around a thenable, | ||
but not the Transition itself. | ||
@@ -237,4 +237,4 @@ | ||
*/ | ||
export declare function logAbort(transition: Transition<any>): ITransitionAbortedError; | ||
export declare function logAbort(transition: Transition<any>): TransitionAbortedError; | ||
export declare function isTransition(obj: unknown): obj is typeof Transition; | ||
export declare function prepareResult(obj: Dict<unknown> | undefined): Dict<unknown> | null | undefined; |
@@ -13,3 +13,3 @@ "use strict"; | ||
var _transitionAbortedError = _interopRequireDefault(require("./transition-aborted-error")); | ||
var _transitionAbortedError = require("./transition-aborted-error"); | ||
@@ -20,4 +20,2 @@ var _utils = require("./utils"); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
const STATE_SYMBOL = `__STATE__-2619860001345920-3322w3`; | ||
@@ -29,3 +27,3 @@ exports.STATE_SYMBOL = STATE_SYMBOL; | ||
/** | ||
A Transition is a thennable (a promise-like object) that represents | ||
A Transition is a thenable (a promise-like object) that represents | ||
an attempt to transition to another route. It can be aborted, either | ||
@@ -122,10 +120,5 @@ explicitly via `abort` or by attempting another transition while a | ||
this.sequence = router.currentSequence++; | ||
this.promise = state.resolve(() => { | ||
if (this.isAborted) { | ||
return _rsvp.Promise.reject(false, (0, _utils.promiseLabel)('Transition aborted - reject')); | ||
} | ||
return _rsvp.Promise.resolve(true); | ||
}, this).catch(result => { | ||
return _rsvp.Promise.reject(this.router.transitionDidError(result, this)); | ||
this.promise = state.resolve(this).catch(result => { | ||
let error = this.router.transitionDidError(result, this); | ||
throw error; | ||
}, (0, _utils.promiseLabel)('Handle Abort')); | ||
@@ -164,3 +157,3 @@ } else { | ||
Forwards to the internal `promise` property which you can | ||
use in situations where you want to pass around a thennable, | ||
use in situations where you want to pass around a thenable, | ||
but not the Transition itself. | ||
@@ -198,3 +191,3 @@ @method then | ||
Forwards to the internal `promise` property which you can | ||
use in situations where you want to pass around a thennable, | ||
use in situations where you want to pass around a thenable, | ||
but not the Transition itself. | ||
@@ -382,3 +375,3 @@ @method finally | ||
(0, _utils.log)(transition.router, transition.sequence, 'detected abort.'); | ||
return new _transitionAbortedError.default(); | ||
return (0, _transitionAbortedError.buildTransitionAborted)(); | ||
} | ||
@@ -385,0 +378,0 @@ |
@@ -1,2 +0,2 @@ | ||
export interface UnrecognizedURLContructor { | ||
export interface UnrecognizedURLConstructor { | ||
new (message?: string): UnrecognizedURLError; | ||
@@ -6,5 +6,5 @@ readonly prototype: UnrecognizedURLError; | ||
export interface UnrecognizedURLError extends Error { | ||
constructor: UnrecognizedURLContructor; | ||
constructor: UnrecognizedURLConstructor; | ||
} | ||
declare const UnrecognizedURLError: UnrecognizedURLContructor; | ||
declare const UnrecognizedURLError: UnrecognizedURLConstructor; | ||
export default UnrecognizedURLError; |
@@ -0,1 +1,2 @@ | ||
export {}; | ||
//# sourceMappingURL=core.js.map |
@@ -27,3 +27,2 @@ import { Promise } from 'rsvp'; | ||
} | ||
export declare type Continuation = () => PromiseLike<boolean> | boolean; | ||
export interface RouteInfo { | ||
@@ -57,5 +56,5 @@ readonly name: string; | ||
serialize(_context?: Dict<unknown>): Dict<unknown> | undefined; | ||
resolve(shouldContinue: Continuation, transition: InternalTransition<T>): Promise<ResolvedRouteInfo<T>>; | ||
resolve(transition: InternalTransition<T>): Promise<ResolvedRouteInfo<T>>; | ||
becomeResolved(transition: InternalTransition<T> | null, resolvedContext: Dict<unknown>): ResolvedRouteInfo<T>; | ||
shouldSupercede(routeInfo?: InternalRouteInfo<T>): boolean; | ||
shouldSupersede(routeInfo?: InternalRouteInfo<T>): boolean; | ||
get route(): T | undefined; | ||
@@ -69,3 +68,2 @@ set route(route: T | undefined); | ||
private runAfterModelHook; | ||
private checkForAbort; | ||
private stashResolvedModel; | ||
@@ -78,3 +76,3 @@ private fetchRoute; | ||
constructor(router: Router<T>, name: string, paramNames: string[], params: Dict<unknown>, route: T, context?: Dict<unknown>); | ||
resolve(_shouldContinue: Continuation, transition: InternalTransition<T>): Promise<InternalRouteInfo<T>>; | ||
resolve(transition: InternalTransition<T>): Promise<InternalRouteInfo<T>>; | ||
} | ||
@@ -81,0 +79,0 @@ export declare class UnresolvedRouteInfoByParam<T extends Route> extends InternalRouteInfo<T> { |
import { Promise } from 'rsvp'; | ||
import { isTransition, PARAMS_SYMBOL, prepareResult, QUERY_PARAMS_SYMBOL, } from './transition'; | ||
import { isParam, isPromise, merge } from './utils'; | ||
import { throwIfAborted } from './transition-aborted-error'; | ||
let ROUTE_INFOS = new WeakMap(); | ||
@@ -118,9 +119,15 @@ export function toReadOnlyRouteInfo(routeInfos, queryParams = {}, includeAttributes = false) { | ||
} | ||
resolve(shouldContinue, transition) { | ||
resolve(transition) { | ||
return Promise.resolve(this.routePromise) | ||
.then((route) => this.checkForAbort(shouldContinue, route)) | ||
.then((route) => { | ||
throwIfAborted(transition); | ||
return route; | ||
}) | ||
.then(() => this.runBeforeModelHook(transition)) | ||
.then(() => this.checkForAbort(shouldContinue, null)) | ||
.then(() => throwIfAborted(transition)) | ||
.then(() => this.getModel(transition)) | ||
.then((resolvedModel) => this.checkForAbort(shouldContinue, resolvedModel)) | ||
.then((resolvedModel) => { | ||
throwIfAborted(transition); | ||
return resolvedModel; | ||
}) | ||
.then((resolvedModel) => this.runAfterModelHook(transition, resolvedModel)) | ||
@@ -148,3 +155,3 @@ .then((resolvedModel) => this.becomeResolved(transition, resolvedModel)); | ||
} | ||
shouldSupercede(routeInfo) { | ||
shouldSupersede(routeInfo) { | ||
// Prefer this newer routeInfo over `other` if: | ||
@@ -229,9 +236,2 @@ // 1) The other one doesn't exist | ||
} | ||
checkForAbort(shouldContinue, value) { | ||
return Promise.resolve(shouldContinue()).then(function () { | ||
// We don't care about shouldContinue's resolve value; | ||
// pass along the original value passed to this fn. | ||
return value; | ||
}, null); | ||
} | ||
stashResolvedModel(transition, resolvedModel) { | ||
@@ -270,3 +270,3 @@ transition.resolvedModels = transition.resolvedModels || {}; | ||
} | ||
resolve(_shouldContinue, transition) { | ||
resolve(transition) { | ||
// A ResolvedRouteInfo just resolved with itself. | ||
@@ -273,0 +273,0 @@ if (transition && transition.resolvedModels) { |
@@ -5,3 +5,3 @@ import RouteRecognizer from 'route-recognizer'; | ||
import InternalTransition, { logAbort, QUERY_PARAMS_SYMBOL, STATE_SYMBOL, } from './transition'; | ||
import TransitionAbortedError from './transition-aborted-error'; | ||
import { throwIfAborted, isTransitionAborted } from './transition-aborted-error'; | ||
import NamedTransitionIntent from './transition-intent/named-transition-intent'; | ||
@@ -228,3 +228,3 @@ import URLTransitionIntent from './transition-intent/url-transition-intent'; | ||
catch (e) { | ||
if (!(e instanceof TransitionAbortedError)) { | ||
if (!isTransitionAborted(e)) { | ||
let infos = transition[STATE_SYMBOL].routeInfos; | ||
@@ -353,5 +353,3 @@ transition.trigger(true, 'error', e, transition, infos[infos.length - 1].route); | ||
} | ||
if (transition && transition.isAborted) { | ||
throw new TransitionAbortedError(); | ||
} | ||
throwIfAborted(transition); | ||
route.context = context; | ||
@@ -364,5 +362,3 @@ if (route.contextDidChange !== undefined) { | ||
} | ||
if (transition && transition.isAborted) { | ||
throw new TransitionAbortedError(); | ||
} | ||
throwIfAborted(transition); | ||
currentRouteInfos.push(routeInfo); | ||
@@ -484,3 +480,3 @@ return route; | ||
// say you are at / and you click a link to route /foo. In /foo's | ||
// route, the transition is aborted using replacewith('/bar'). | ||
// route, the transition is aborted using replaceWith('/bar'). | ||
// Because the current url is still /, the history entry for / is | ||
@@ -701,5 +697,5 @@ // removed from the history. Clicking back will take you to the page | ||
let targetHandler = targetRouteInfos[targetRouteInfos.length - 1].name; | ||
let recogHandlers = this.recognizer.handlersFor(targetHandler); | ||
let recognizerHandlers = this.recognizer.handlersFor(targetHandler); | ||
let index = 0; | ||
for (len = recogHandlers.length; index < len; ++index) { | ||
for (len = recognizerHandlers.length; index < len; ++index) { | ||
routeInfo = targetRouteInfos[index]; | ||
@@ -710,3 +706,3 @@ if (routeInfo.name === routeName) { | ||
} | ||
if (index === recogHandlers.length) { | ||
if (index === recognizerHandlers.length) { | ||
// The provided route name isn't even in the route hierarchy. | ||
@@ -717,5 +713,5 @@ return false; | ||
testState.routeInfos = targetRouteInfos.slice(0, index + 1); | ||
recogHandlers = recogHandlers.slice(0, index + 1); | ||
recognizerHandlers = recognizerHandlers.slice(0, index + 1); | ||
let intent = new NamedTransitionIntent(this, targetHandler, undefined, contexts); | ||
let newState = intent.applyToHandlers(testState, recogHandlers, targetHandler, true, true); | ||
let newState = intent.applyToHandlers(testState, recognizerHandlers, targetHandler, true, true); | ||
let routesEqual = routeInfosEqual(newState.routeInfos, testState.routeInfos); | ||
@@ -722,0 +718,0 @@ if (!queryParams || !routesEqual) { |
@@ -1,9 +0,13 @@ | ||
export interface TransitionAbortedErrorContructor { | ||
new (message?: string): ITransitionAbortedError; | ||
readonly prototype: ITransitionAbortedError; | ||
export interface TransitionAbortedError extends Error { | ||
name: 'TransitionAborted'; | ||
code: 'TRANSITION_ABORTED'; | ||
} | ||
export interface ITransitionAbortedError extends Error { | ||
constructor: TransitionAbortedErrorContructor; | ||
export declare function buildTransitionAborted(): TransitionAbortedError; | ||
export declare function isTransitionAborted(maybeError: unknown): maybeError is TransitionAbortedError; | ||
interface Abortable<T extends boolean> { | ||
isAborted: T; | ||
[key: string]: unknown; | ||
} | ||
declare const TransitionAbortedError: TransitionAbortedErrorContructor; | ||
export default TransitionAbortedError; | ||
export declare function throwIfAborted(maybe: Abortable<true>): never; | ||
export declare function throwIfAborted(maybe: unknown): void; | ||
export {}; |
@@ -1,18 +0,22 @@ | ||
const TransitionAbortedError = (function () { | ||
TransitionAbortedError.prototype = Object.create(Error.prototype); | ||
TransitionAbortedError.prototype.constructor = TransitionAbortedError; | ||
function TransitionAbortedError(message) { | ||
let error = Error.call(this, message); | ||
this.name = 'TransitionAborted'; | ||
this.message = message || 'TransitionAborted'; | ||
if (Error.captureStackTrace) { | ||
Error.captureStackTrace(this, TransitionAbortedError); | ||
} | ||
else { | ||
this.stack = error.stack; | ||
} | ||
export function buildTransitionAborted() { | ||
let error = new Error('TransitionAborted'); | ||
error.name = 'TransitionAborted'; | ||
error.code = 'TRANSITION_ABORTED'; | ||
return error; | ||
} | ||
export function isTransitionAborted(maybeError) { | ||
return (typeof maybeError === 'object' && | ||
maybeError !== null && | ||
maybeError.code === 'TRANSITION_ABORTED'); | ||
} | ||
function isAbortable(maybeAbortable) { | ||
return (typeof maybeAbortable === 'object' && | ||
maybeAbortable !== null && | ||
typeof maybeAbortable.isAborted === 'boolean'); | ||
} | ||
export function throwIfAborted(maybe) { | ||
if (isAbortable(maybe) && maybe.isAborted) { | ||
throw buildTransitionAborted(); | ||
} | ||
return TransitionAbortedError; | ||
})(); | ||
export default TransitionAbortedError; | ||
} | ||
//# sourceMappingURL=transition-aborted-error.js.map |
@@ -10,3 +10,3 @@ import { Route } from './route-info'; | ||
preTransitionState?: TransitionState<T>; | ||
abstract applyToState(oldState: TransitionState<T>, isIntermidate: boolean): TransitionState<T>; | ||
abstract applyToState(oldState: TransitionState<T>, isIntermediate: boolean): TransitionState<T>; | ||
} |
@@ -71,3 +71,3 @@ import { UnresolvedRouteInfoByObject, UnresolvedRouteInfoByParam, } from '../route-info'; | ||
let handlerToUse = oldHandlerInfo; | ||
if (i >= invalidateIndex || newHandlerInfo.shouldSupercede(oldHandlerInfo)) { | ||
if (i >= invalidateIndex || newHandlerInfo.shouldSupersede(oldHandlerInfo)) { | ||
invalidateIndex = Math.min(i, invalidateIndex); | ||
@@ -89,2 +89,5 @@ handlerToUse = newHandlerInfo; | ||
merge(newState.queryParams, this.queryParams || {}); | ||
if (isIntermediate && oldState.queryParams) { | ||
merge(newState.queryParams, oldState.queryParams); | ||
} | ||
return newState; | ||
@@ -91,0 +94,0 @@ } |
@@ -42,3 +42,3 @@ import { UnresolvedRouteInfoByParam } from '../route-info'; | ||
else { | ||
// If the hanlder is being loaded asynchronously, check if we can | ||
// If the handler is being loaded asynchronously, check if we can | ||
// access it after it has resolved | ||
@@ -48,3 +48,3 @@ newRouteInfo.routePromise = newRouteInfo.routePromise.then(checkHandlerAccessibility); | ||
let oldRouteInfo = oldState.routeInfos[i]; | ||
if (statesDiffer || newRouteInfo.shouldSupercede(oldRouteInfo)) { | ||
if (statesDiffer || newRouteInfo.shouldSupersede(oldRouteInfo)) { | ||
statesDiffer = true; | ||
@@ -51,0 +51,0 @@ newState.routeInfos[i] = newRouteInfo; |
import { Promise } from 'rsvp'; | ||
import { Dict } from './core'; | ||
import InternalRouteInfo, { Continuation, Route } from './route-info'; | ||
import InternalRouteInfo, { Route } from './route-info'; | ||
import Transition from './transition'; | ||
@@ -13,3 +13,3 @@ interface IParams { | ||
promiseLabel(label: string): string; | ||
resolve(shouldContinue: Continuation, transition: Transition<T>): Promise<TransitionState<T>>; | ||
resolve(transition: Transition<T>): Promise<TransitionState<T>>; | ||
} | ||
@@ -16,0 +16,0 @@ export declare class TransitionError { |
import { Promise } from 'rsvp'; | ||
import { forEach, promiseLabel } from './utils'; | ||
import { throwIfAborted } from './transition-aborted-error'; | ||
function handleError(currentState, transition, error) { | ||
// This is the only possible | ||
// reject value of TransitionState#resolve | ||
let routeInfos = currentState.routeInfos; | ||
let errorHandlerIndex = transition.resolveIndex >= routeInfos.length ? routeInfos.length - 1 : transition.resolveIndex; | ||
let wasAborted = transition.isAborted; | ||
throw new TransitionError(error, currentState.routeInfos[errorHandlerIndex].route, wasAborted, currentState); | ||
} | ||
function resolveOneRouteInfo(currentState, transition) { | ||
if (transition.resolveIndex === currentState.routeInfos.length) { | ||
// This is is the only possible | ||
// fulfill value of TransitionState#resolve | ||
return; | ||
} | ||
let routeInfo = currentState.routeInfos[transition.resolveIndex]; | ||
return routeInfo | ||
.resolve(transition) | ||
.then(proceed.bind(null, currentState, transition), null, currentState.promiseLabel('Proceed')); | ||
} | ||
function proceed(currentState, transition, resolvedRouteInfo) { | ||
let wasAlreadyResolved = currentState.routeInfos[transition.resolveIndex].isResolved; | ||
// Swap the previously unresolved routeInfo with | ||
// the resolved routeInfo | ||
currentState.routeInfos[transition.resolveIndex++] = resolvedRouteInfo; | ||
if (!wasAlreadyResolved) { | ||
// Call the redirect hook. The reason we call it here | ||
// vs. afterModel is so that redirects into child | ||
// routes don't re-run the model hooks for this | ||
// already-resolved route. | ||
let { route } = resolvedRouteInfo; | ||
if (route !== undefined) { | ||
if (route.redirect) { | ||
route.redirect(resolvedRouteInfo.context, transition); | ||
} | ||
} | ||
} | ||
// Proceed after ensuring that the redirect hook | ||
// didn't abort this transition by transitioning elsewhere. | ||
throwIfAborted(transition); | ||
return resolveOneRouteInfo(currentState, transition); | ||
} | ||
export default class TransitionState { | ||
@@ -20,3 +62,3 @@ constructor() { | ||
} | ||
resolve(shouldContinue, transition) { | ||
resolve(transition) { | ||
// First, calculate params for this state. This is useful | ||
@@ -30,58 +72,7 @@ // information to provide to the various route hooks. | ||
transition.resolveIndex = 0; | ||
let currentState = this; | ||
let wasAborted = false; | ||
// The prelude RSVP.resolve() asyncs us into the promise land. | ||
// The prelude RSVP.resolve() async moves us into the promise land. | ||
return Promise.resolve(null, this.promiseLabel('Start transition')) | ||
.then(resolveOneRouteInfo, null, this.promiseLabel('Resolve route')) | ||
.catch(handleError, this.promiseLabel('Handle error')); | ||
function innerShouldContinue() { | ||
return Promise.resolve(shouldContinue(), currentState.promiseLabel('Check if should continue')).catch(function (reason) { | ||
// We distinguish between errors that occurred | ||
// during resolution (e.g. before"Model/model/afterModel), | ||
// and aborts due to a rejecting promise from shouldContinue(). | ||
wasAborted = true; | ||
return Promise.reject(reason); | ||
}, currentState.promiseLabel('Handle abort')); | ||
} | ||
function handleError(error) { | ||
// This is the only possible | ||
// reject value of TransitionState#resolve | ||
let routeInfos = currentState.routeInfos; | ||
let errorHandlerIndex = transition.resolveIndex >= routeInfos.length | ||
? routeInfos.length - 1 | ||
: transition.resolveIndex; | ||
return Promise.reject(new TransitionError(error, currentState.routeInfos[errorHandlerIndex].route, wasAborted, currentState)); | ||
} | ||
function proceed(resolvedRouteInfo) { | ||
let wasAlreadyResolved = currentState.routeInfos[transition.resolveIndex].isResolved; | ||
// Swap the previously unresolved routeInfo with | ||
// the resolved routeInfo | ||
currentState.routeInfos[transition.resolveIndex++] = resolvedRouteInfo; | ||
if (!wasAlreadyResolved) { | ||
// Call the redirect hook. The reason we call it here | ||
// vs. afterModel is so that redirects into child | ||
// routes don't re-run the model hooks for this | ||
// already-resolved route. | ||
let { route } = resolvedRouteInfo; | ||
if (route !== undefined) { | ||
if (route.redirect) { | ||
route.redirect(resolvedRouteInfo.context, transition); | ||
} | ||
} | ||
} | ||
// Proceed after ensuring that the redirect hook | ||
// didn't abort this transition by transitioning elsewhere. | ||
return innerShouldContinue().then(resolveOneRouteInfo, null, currentState.promiseLabel('Resolve route')); | ||
} | ||
function resolveOneRouteInfo() { | ||
if (transition.resolveIndex === currentState.routeInfos.length) { | ||
// This is is the only possible | ||
// fulfill value of TransitionState#resolve | ||
return currentState; | ||
} | ||
let routeInfo = currentState.routeInfos[transition.resolveIndex]; | ||
return routeInfo | ||
.resolve(innerShouldContinue, transition) | ||
.then(proceed, null, currentState.promiseLabel('Proceed')); | ||
} | ||
.then(resolveOneRouteInfo.bind(null, this, transition), null, this.promiseLabel('Resolve route')) | ||
.catch(handleError.bind(null, this, transition), this.promiseLabel('Handle error')) | ||
.then(() => this); | ||
} | ||
@@ -88,0 +79,0 @@ } |
@@ -5,3 +5,3 @@ import { Promise } from 'rsvp'; | ||
import Router from './router'; | ||
import { ITransitionAbortedError } from './transition-aborted-error'; | ||
import { TransitionAbortedError } from './transition-aborted-error'; | ||
import { OpaqueIntent } from './transition-intent'; | ||
@@ -17,3 +17,3 @@ import TransitionState from './transition-state'; | ||
/** | ||
A Transition is a thennable (a promise-like object) that represents | ||
A Transition is a thenable (a promise-like object) that represents | ||
an attempt to transition to another route. It can be aborted, either | ||
@@ -113,3 +113,3 @@ explicitly via `abort` or by attempting another transition while a | ||
Forwards to the internal `promise` property which you can | ||
use in situations where you want to pass around a thennable, | ||
use in situations where you want to pass around a thenable, | ||
but not the Transition itself. | ||
@@ -143,3 +143,3 @@ | ||
Forwards to the internal `promise` property which you can | ||
use in situations where you want to pass around a thennable, | ||
use in situations where you want to pass around a thenable, | ||
but not the Transition itself. | ||
@@ -237,4 +237,4 @@ | ||
*/ | ||
export declare function logAbort(transition: Transition<any>): ITransitionAbortedError; | ||
export declare function logAbort(transition: Transition<any>): TransitionAbortedError; | ||
export declare function isTransition(obj: unknown): obj is typeof Transition; | ||
export declare function prepareResult(obj: Dict<unknown> | undefined): Dict<unknown> | null | undefined; |
import { Promise } from 'rsvp'; | ||
import TransitionAborted from './transition-aborted-error'; | ||
import { buildTransitionAborted } from './transition-aborted-error'; | ||
import { log, promiseLabel } from './utils'; | ||
@@ -9,3 +9,3 @@ import { DEBUG } from '@glimmer/env'; | ||
/** | ||
A Transition is a thennable (a promise-like object) that represents | ||
A Transition is a thenable (a promise-like object) that represents | ||
an attempt to transition to another route. It can be aborted, either | ||
@@ -94,11 +94,5 @@ explicitly via `abort` or by attempting another transition while a | ||
this.sequence = router.currentSequence++; | ||
this.promise = state | ||
.resolve(() => { | ||
if (this.isAborted) { | ||
return Promise.reject(false, promiseLabel('Transition aborted - reject')); | ||
} | ||
return Promise.resolve(true); | ||
}, this) | ||
.catch((result) => { | ||
return Promise.reject(this.router.transitionDidError(result, this)); | ||
this.promise = state.resolve(this).catch((result) => { | ||
let error = this.router.transitionDidError(result, this); | ||
throw error; | ||
}, promiseLabel('Handle Abort')); | ||
@@ -139,3 +133,3 @@ } | ||
Forwards to the internal `promise` property which you can | ||
use in situations where you want to pass around a thennable, | ||
use in situations where you want to pass around a thenable, | ||
but not the Transition itself. | ||
@@ -173,3 +167,3 @@ | ||
Forwards to the internal `promise` property which you can | ||
use in situations where you want to pass around a thennable, | ||
use in situations where you want to pass around a thenable, | ||
but not the Transition itself. | ||
@@ -338,3 +332,3 @@ | ||
log(transition.router, transition.sequence, 'detected abort.'); | ||
return new TransitionAborted(); | ||
return buildTransitionAborted(); | ||
} | ||
@@ -341,0 +335,0 @@ export function isTransition(obj) { |
@@ -1,2 +0,2 @@ | ||
export interface UnrecognizedURLContructor { | ||
export interface UnrecognizedURLConstructor { | ||
new (message?: string): UnrecognizedURLError; | ||
@@ -6,5 +6,5 @@ readonly prototype: UnrecognizedURLError; | ||
export interface UnrecognizedURLError extends Error { | ||
constructor: UnrecognizedURLContructor; | ||
constructor: UnrecognizedURLConstructor; | ||
} | ||
declare const UnrecognizedURLError: UnrecognizedURLContructor; | ||
declare const UnrecognizedURLError: UnrecognizedURLConstructor; | ||
export default UnrecognizedURLError; |
{ | ||
"name": "router_js", | ||
"version": "7.1.1", | ||
"version": "7.2.0", | ||
"description": "A lightweight JavaScript library is built on top of route-recognizer and rsvp.js to provide an API for handling routes", | ||
@@ -25,2 +25,3 @@ "keywords": [ | ||
], | ||
"types": "dist/modules/index.d.ts", | ||
"scripts": { | ||
@@ -39,26 +40,27 @@ "lint": "npm-run-all lint:*", | ||
"devDependencies": { | ||
"@babel/plugin-transform-modules-amd": "^7.10.5", | ||
"@babel/plugin-transform-modules-commonjs": "^7.10.4", | ||
"@types/node": "^12.7.5", | ||
"@types/qunit": "^2.9.1", | ||
"@typescript-eslint/eslint-plugin": "^3.7.0", | ||
"@typescript-eslint/parser": "^3.7.0", | ||
"@babel/plugin-transform-modules-amd": "^7.12.1", | ||
"@babel/plugin-transform-modules-commonjs": "^7.12.1", | ||
"@types/node": "^14.14.6", | ||
"@types/qunit": "^2.9.6", | ||
"@typescript-eslint/eslint-plugin": "^4.6.1", | ||
"@typescript-eslint/parser": "^4.6.1", | ||
"babel-plugin-debug-macros": "^0.3.3", | ||
"backburner.js": "^2.6.0", | ||
"broccoli-babel-transpiler": "^7.6.0", | ||
"broccoli-babel-transpiler": "^7.8.0", | ||
"broccoli-concat": "^4.2.4", | ||
"broccoli-funnel": "^3.0.3", | ||
"broccoli-merge-trees": "^4.2.0", | ||
"broccoli-typescript-compiler": "^6.0.0", | ||
"ember-cli": "~3.19.0", | ||
"broccoli-typescript-compiler": "^7.0.0", | ||
"ember-cli": "~3.22.0", | ||
"ember-cli-inject-live-reload": "^2.0.2", | ||
"ensure-posix-path": "^1.1.1", | ||
"eslint": "^7.5.0", | ||
"eslint-config-prettier": "^6.11.0", | ||
"eslint": "^7.12.1", | ||
"eslint-config-prettier": "^6.15.0", | ||
"eslint-plugin-prettier": "^3.1.4", | ||
"loader.js": "^4.7.0", | ||
"npm-run-all": "^4.1.5", | ||
"prettier": "2.0.5", | ||
"qunit": "^2.10.1", | ||
"release-it": "^14.0.2", | ||
"release-it-lerna-changelog": "^2.4.0", | ||
"prettier": "^2.1.2", | ||
"qunit": "^2.11.3", | ||
"release-it": "^14.2.1", | ||
"release-it-lerna-changelog": "^3.1.0", | ||
"route-recognizer": "^0.3.4", | ||
@@ -92,3 +94,7 @@ "rsvp": "^4.8.5" | ||
} | ||
}, | ||
"volta": { | ||
"node": "14.15.0", | ||
"yarn": "1.22.10" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
355319
27
5219