Socket
Socket
Sign inDemoInstall

@aurelia/router-lite

Package Overview
Dependencies
7
Maintainers
1
Versions
248
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.1.0-dev.202306061010 to 2.1.0-dev.202306130710

dist/types/events.d.ts

20

dist/types/component-agent.d.ts

@@ -1,6 +0,5 @@

import type { ICustomElementController, ICustomElementViewModel } from '@aurelia/runtime-html';
import type { ICustomElementViewModel } from '@aurelia/runtime-html';
import { NavigationInstruction, Params } from './instructions';
import type { IRouteConfig } from './options';
import type { RouteNode } from './route-tree';
import { IRouteContext } from './route-context';
import { Params, NavigationInstruction } from './instructions';
import type { RouterOptions, IRouteConfig } from './options';
export interface IRouteViewModel extends ICustomElementViewModel {

@@ -13,15 +12,2 @@ getRouteConfig?(parentConfig: IRouteConfig | null, routeNode: RouteNode | null): IRouteConfig | Promise<IRouteConfig>;

}
/**
* A component agent handles an instance of a routed view-model (a component).
* It deals with invoking the hooks (`canLoad`, `loading`, `canUnload`, `unloading`),
* and activating, deactivating, and disposing the component (via the associated controller).
*/
export declare class ComponentAgent<T extends IRouteViewModel = IRouteViewModel> {
readonly instance: T;
readonly controller: ICustomElementController<T>;
readonly routeNode: RouteNode;
readonly ctx: IRouteContext;
private readonly routerOptions;
constructor(instance: T, controller: ICustomElementController<T>, routeNode: RouteNode, ctx: IRouteContext, routerOptions: RouterOptions);
}
//# sourceMappingURL=component-agent.d.ts.map
export { type IViewport, } from './resources/viewport';
export { RouterConfiguration, RouterRegistration, DefaultComponents, DefaultResources, ViewportCustomElement, ViewportCustomElementRegistration, LoadCustomAttribute, LoadCustomAttributeRegistration, HrefCustomAttribute, HrefCustomAttributeRegistration, type IRouterConfigurationOptions, } from './configuration';
export { type IRouteViewModel, ComponentAgent, } from './component-agent';
export { type IRouteViewModel, } from './component-agent';
export { type RouteableComponent, type NavigationInstruction, type IViewportInstruction, type Params, type ViewportInstruction, type ITypedNavigationInstruction, type ITypedNavigationInstruction_string, type ITypedNavigationInstruction_ViewportInstruction, type ITypedNavigationInstruction_CustomElementDefinition, type ITypedNavigationInstruction_Promise, type ITypedNavigationInstruction_IRouteViewModel, } from './instructions';

@@ -5,0 +5,0 @@ export { ILocationManager, } from './location-manager';

@@ -30,5 +30,7 @@ import { IModule } from '@aurelia/kernel';

};
export interface IViewportInstruction {
export type IExtendedViewportInstruction = IViewportInstruction & {
readonly open?: number;
readonly close?: number;
};
export interface IViewportInstruction {
/**

@@ -66,5 +68,5 @@ * The component to load.

}
export declare class ViewportInstruction<TComponent extends ITypedNavigationInstruction_T = ITypedNavigationInstruction_Component> implements IViewportInstruction {
open: number;
close: number;
export declare class ViewportInstruction<TComponent extends ITypedNavigationInstruction_T = ITypedNavigationInstruction_Component> implements IExtendedViewportInstruction {
readonly open: number;
readonly close: number;
readonly recognizedRoute: $RecognizedRoute | null;

@@ -76,22 +78,8 @@ readonly component: TComponent;

private constructor();
static create(instruction: NavigationInstruction): ViewportInstruction;
static create(instruction: NavigationInstruction | IExtendedViewportInstruction): ViewportInstruction;
contains(other: ViewportInstruction): boolean;
equals(other: ViewportInstruction): boolean;
clone(): this;
toUrlComponent(recursive?: boolean): string;
toString(): string;
}
export interface IRedirectInstruction {
readonly path: string;
readonly redirectTo: string;
}
export declare class RedirectInstruction implements IRedirectInstruction {
readonly path: string;
readonly redirectTo: string;
private constructor();
static create(instruction: IRedirectInstruction): RedirectInstruction;
equals(other: RedirectInstruction): boolean;
toUrlComponent(): string;
toString(): string;
}
export declare class ViewportInstructionTree {

@@ -122,3 +110,3 @@ readonly options: NavigationOptions;

toUrlComponent(): string;
clone(): this;
_clone(): this;
}

@@ -150,3 +138,2 @@ export interface ITypedNavigationInstruction_string extends ITypedNavigationInstruction<string, NavigationInstructionType.string> {

equals(this: ITypedNavigationInstruction_T, other: ITypedNavigationInstruction_T): boolean;
clone(): this;
toUrlComponent(this: ITypedNavigationInstruction_T): string;

@@ -153,0 +140,0 @@ toString(this: ITypedNavigationInstruction_T): string;

@@ -1,5 +0,1 @@

import { ILogger } from '@aurelia/kernel';
import { IHistory, ILocation, IWindow } from '@aurelia/runtime-html';
import { type RouterOptions } from './options';
import { IRouterEvents } from './router-events';
export interface IPopStateEvent extends PopStateEvent {

@@ -21,10 +17,3 @@ }

export declare class BrowserLocationManager {
private readonly logger;
private readonly events;
private readonly history;
private readonly location;
private readonly window;
private readonly baseHref;
private eventId;
constructor(logger: ILogger, events: IRouterEvents, history: IHistory, location: ILocation, window: IWindow, baseHref: URL, routerOptions: Readonly<RouterOptions>);
constructor();
startListening(): void;

@@ -36,10 +25,5 @@ stopListening(): void;

getPath(): string;
currentPathEquals(path: string): boolean;
addBaseHref(path: string): string;
removeBaseHref(path: string): string;
}
/**
* Strip trailing `/index.html` and trailing `/` from the path, if present.
*/
export declare function normalizePath(path: string): string;
//# sourceMappingURL=location-manager.d.ts.map

@@ -1,2 +0,2 @@

import type { Params, RouteContextLike, RouteableComponent, ViewportInstruction, ViewportInstructionTree } from './instructions';
import type { IViewportInstruction, Params, RouteContextLike, RouteableComponent, ViewportInstructionTree } from './instructions';
import type { RouteNode } from './route-tree';

@@ -41,2 +41,8 @@ import type { Transition } from './router';

readonly activeClass: string | null;
/**
* When set to `true`, the router will try to restore previous route tree, when a routing instruction errs.
* Set this to `false`, if a stricter behavior is desired. However, in that case, you need to ensure the avoidance of errors.
* The default value is `true`.
*/
readonly restorePreviousRouteTreeOnError: boolean;
protected constructor(useUrlFragmentHash: boolean, useHref: boolean,

@@ -70,3 +76,9 @@ /**

*/
activeClass: string | null);
activeClass: string | null,
/**
* When set to `true`, the router will try to restore previous route tree, when a routing instruction errs.
* Set this to `false`, if a stricter behavior is desired. However, in that case, you need to ensure the avoidance of errors.
* The default value is `true`.
*/
restorePreviousRouteTreeOnError: boolean);
static create(input: IRouterOptions): RouterOptions;

@@ -109,5 +121,4 @@ toString(): string;

static create(routerOptions: RouterOptions, input: INavigationOptions): NavigationOptions;
clone(): NavigationOptions;
}
export type FallbackFunction = (viewportInstruction: ViewportInstruction, routeNode: RouteNode, context: IRouteContext) => Routeable | null;
export type FallbackFunction = (viewportInstruction: IViewportInstruction, routeNode: RouteNode, context: IRouteContext) => Routeable | null;
/**

@@ -114,0 +125,0 @@ * Either a `RouteableComponent` or a name/config that can be resolved to a one:

@@ -1,14 +0,6 @@

import { ICustomAttributeViewModel, ICustomAttributeController, INode, IWindow } from '@aurelia/runtime-html';
import { IRouter } from '../router';
import { IRouteContext } from '../route-context';
import { ICustomAttributeViewModel, ICustomAttributeController } from '@aurelia/runtime-html';
export declare class HrefCustomAttribute implements ICustomAttributeViewModel {
private readonly el;
private readonly router;
private readonly ctx;
value: unknown;
private isInitialized;
private isEnabled;
private get isExternal();
readonly $controller: ICustomAttributeController<this>;
constructor(el: INode<HTMLElement>, router: IRouter, ctx: IRouteContext, w: IWindow);
constructor();
binding(): void;

@@ -15,0 +7,0 @@ unbinding(): void;

@@ -1,13 +0,5 @@

import { ICustomAttributeViewModel, INode } from '@aurelia/runtime-html';
import { IRouter } from '../router';
import { ICustomAttributeViewModel } from '@aurelia/runtime-html';
import { IRouteContext } from '../route-context';
import { Params } from '../instructions';
import { IRouterEvents } from '../router-events';
import { ILocationManager } from '../location-manager';
export declare class LoadCustomAttribute implements ICustomAttributeViewModel {
private readonly el;
private readonly router;
private readonly events;
private readonly ctx;
private readonly locationMgr;
route: unknown;

@@ -21,8 +13,3 @@ params?: Params;

context?: IRouteContext;
private href;
private instructions;
private navigationEndListener;
private readonly isEnabled;
private readonly activeClass;
constructor(el: INode<HTMLElement>, router: IRouter, events: IRouterEvents, ctx: IRouteContext, locationMgr: ILocationManager);
constructor();
binding(): void;

@@ -29,0 +16,0 @@ attaching(): void | Promise<void>;

@@ -1,4 +0,2 @@

import { ILogger } from '@aurelia/kernel';
import { ICustomElementViewModel, IHydratedController, ICompiledCustomElementController } from '@aurelia/runtime-html';
import { IRouteContext } from '../route-context';
import { ICompiledCustomElementController, ICustomElementViewModel, IHydratedController } from '@aurelia/runtime-html';
import { FallbackFunction, Routeable } from '../options';

@@ -12,4 +10,2 @@ export interface IViewport {

export declare class ViewportCustomElement implements ICustomElementViewModel, IViewport {
private readonly logger;
private readonly ctx;
name: string;

@@ -19,5 +15,2 @@ usedBy: string;

fallback: Routeable | FallbackFunction;
private agent;
private controller;
constructor(logger: ILogger, ctx: IRouteContext);
hydrated(controller: ICompiledCustomElementController): void;

@@ -24,0 +17,0 @@ attaching(initiator: IHydratedController, _parent: IHydratedController): void | Promise<void>;

@@ -1,12 +0,11 @@

import { type IContainer, IModule } from '@aurelia/kernel';
import { type IContainer } from '@aurelia/kernel';
import { RecognizedRoute } from '@aurelia/route-recognizer';
import { type CustomElementDefinition, ICustomElementController, PartialCustomElementDefinition } from '@aurelia/runtime-html';
import { ComponentAgent, IRouteViewModel } from './component-agent';
import { NavigationInstruction, Params, ViewportInstruction } from './instructions';
import { type CustomElementDefinition, PartialCustomElementDefinition } from '@aurelia/runtime-html';
import { IRouteViewModel } from './component-agent';
import { IExtendedViewportInstruction, NavigationInstruction, Params, ViewportInstruction } from './instructions';
import { IChildRouteConfig } from './options';
import { IViewport } from './resources/viewport';
import { RouteConfig, RouteType } from './route';
import type { RouteNode } from './route-tree';
import { IRouter } from './router';
import { ViewportAgent, type ViewportRequest } from './viewport-agent';
import { ViewportAgent } from './viewport-agent';
export interface IRouteContext extends RouteContext {

@@ -19,7 +18,6 @@ }

};
export type EagerInstruction = {
type EagerInstruction = {
component: string | RouteConfig | PartialCustomElementDefinition | IRouteViewModel | IChildRouteConfig | RouteType;
params: Params;
};
export declare function isEagerInstruction(val: NavigationInstruction | EagerInstruction): val is EagerInstruction;
/**

@@ -39,3 +37,2 @@ * Holds the information of a component in the context of a specific container.

private readonly _router;
private readonly childViewportAgents;
readonly root: IRouteContext;

@@ -49,16 +46,7 @@ get isRoot(): boolean;

/**
* The stringified path from the root RouteContext up to this one, consisting of the component names they're associated with, separated by slashes.
*
* Mainly for debugging/introspection purposes.
*/
readonly friendlyPath: string;
/**
* The (fully resolved) configured child routes of this context's `RouteConfig`
*/
readonly childRoutes: (RouteConfig | Promise<RouteConfig>)[];
get resolved(): Promise<void> | null;
get allResolved(): Promise<void> | null;
private prevNode;
get node(): RouteNode;
set node(value: RouteNode);
/**

@@ -70,10 +58,5 @@ * The viewport hosting the component associated with this RouteContext.

readonly container: IContainer;
private readonly moduleLoader;
private readonly logger;
private readonly hostControllerProvider;
private _childRoutesConfigured;
private readonly _navigationModel;
get navigationModel(): INavigationModel | null;
constructor(viewportAgent: ViewportAgent | null, parent: IRouteContext | null, component: CustomElementDefinition, config: RouteConfig, parentContainer: IContainer, _router: IRouter);
private _processConfig;
/**

@@ -89,25 +72,11 @@ * Create a new `RouteContext` and register it in the provided container.

dispose(): void;
resolveViewportAgent(req: ViewportRequest): ViewportAgent;
getAvailableViewportAgents(): readonly ViewportAgent[];
getFallbackViewportAgent(name: string): ViewportAgent | null;
/**
* Create a component based on the provided viewportInstruction.
*
* @param hostController - The `ICustomElementController` whose component (typically `au-viewport`) will host this component.
* @param routeNode - The routeNode that describes the component + state.
*/
createComponentAgent(hostController: ICustomElementController, routeNode: RouteNode): ComponentAgent | Promise<ComponentAgent>;
registerViewport(viewport: IViewport): ViewportAgent;
unregisterViewport(viewport: IViewport): void;
recognize(path: string, searchAncestor?: boolean): $RecognizedRoute | null;
private addRoute;
private $addRoute;
resolveLazy(promise: Promise<IModule>): Promise<CustomElementDefinition> | CustomElementDefinition;
generateViewportInstruction(instruction: {
_generateViewportInstruction(instruction: {
component: string;
params: Params;
}): PathGenerationResult | null;
generateViewportInstruction(instruction: NavigationInstruction | EagerInstruction): PathGenerationResult | null;
_generateViewportInstruction(instruction: NavigationInstruction | EagerInstruction | IExtendedViewportInstruction): PathGenerationResult | null;
toString(): string;
private printTree;
}

@@ -114,0 +83,0 @@ export declare class $RecognizedRoute {

@@ -1,22 +0,3 @@

import { ViewportInstructionTree, ViewportInstruction, Params } from './instructions';
import { ViewportInstructionTree } from './instructions';
import { type NavigationOptions } from './options';
declare class ParserState {
private readonly input;
get done(): boolean;
private rest;
private readonly buffers;
private bufferIndex;
private index;
constructor(input: string);
startsWith(...values: readonly string[]): boolean;
consumeOptional(str: string): boolean;
consume(str: string): void;
expect(msg: string): void;
ensureDone(): void;
advance(): void;
record(): void;
playback(): string;
discard(): void;
private append;
}
export declare const enum ExpressionKind {

@@ -45,3 +26,2 @@ Route = 0,

static parse(path: string, fragmentIsRoute: boolean): RouteExpression;
private static $parse;
toInstructionTree(options: NavigationOptions): ViewportInstructionTree;

@@ -78,4 +58,2 @@ toString(): string;

constructor(raw: string, siblings: readonly ScopedSegmentExpressionOrHigher[]);
static parse(state: ParserState): CompositeSegmentExpressionOrHigher;
toInstructions(open: number, close: number): ViewportInstruction[];
toString(): string;

@@ -104,4 +82,2 @@ }

constructor(raw: string, left: SegmentGroupExpressionOrHigher, right: ScopedSegmentExpressionOrHigher);
static parse(state: ParserState): ScopedSegmentExpressionOrHigher;
toInstructions(open: number, close: number): ViewportInstruction[];
toString(): string;

@@ -145,4 +121,2 @@ }

constructor(raw: string, expression: CompositeSegmentExpressionOrHigher);
static parse(state: ParserState): SegmentGroupExpressionOrHigher;
toInstructions(open: number, close: number): ViewportInstruction[];
toString(): string;

@@ -162,4 +136,2 @@ }

constructor(raw: string, component: ComponentExpression, action: ActionExpression, viewport: ViewportExpression, scoped: boolean);
static parse(state: ParserState): SegmentExpression;
toInstructions(open: number, close: number): ViewportInstruction[];
toString(): string;

@@ -190,3 +162,2 @@ }

constructor(raw: string, name: string, parameterList: ParameterListExpression);
static parse(state: ParserState): ComponentExpression;
toString(): string;

@@ -201,3 +172,2 @@ }

constructor(raw: string, name: string, parameterList: ParameterListExpression);
static parse(state: ParserState): ActionExpression;
toString(): string;

@@ -207,7 +177,6 @@ }

readonly raw: string;
readonly name: string;
readonly name: string | null;
get kind(): ExpressionKind.Viewport;
static get EMPTY(): ViewportExpression;
constructor(raw: string, name: string);
static parse(state: ParserState): ViewportExpression;
constructor(raw: string, name: string | null);
toString(): string;

@@ -221,4 +190,2 @@ }

constructor(raw: string, expressions: readonly ParameterExpression[]);
static parse(state: ParserState): ParameterListExpression;
toObject(): Params;
toString(): string;

@@ -233,3 +200,2 @@ }

constructor(raw: string, key: string, value: string);
static parse(state: ParserState, index: number): ParameterExpression;
toString(): string;

@@ -249,3 +215,2 @@ }

}>;
export {};
//# sourceMappingURL=route-expression.d.ts.map

@@ -16,3 +16,3 @@ import { type ILogger } from '@aurelia/kernel';

data?: Record<string, unknown>;
viewport?: string | null;
_viewport?: string | null;
title?: string | ((node: RouteNode) => string | null) | null;

@@ -23,2 +23,8 @@ component: CustomElementDefinition;

}
export interface RouteNodeMatchOptions {
/** Endpoints will be matched instead of instruction */
matchEndpoint: boolean;
/** Original instruction will be matched */
matchOriginalInstruction: boolean;
}
export declare class RouteNode implements IRouteNode {

@@ -28,7 +34,7 @@ /**

*/
path: string;
readonly path: string;
/**
* If one or more redirects have occurred, then this is the final path match, in all other cases this is identical to `path`
*/
finalPath: string;
readonly finalPath: string;
/**

@@ -44,16 +50,8 @@ * The `RouteContext` associated with this route.

readonly instruction: ViewportInstruction<ITypedNavigationInstruction_ResolvedComponent> | null;
params: Params;
queryParams: Readonly<URLSearchParams>;
fragment: string | null;
data: Record<string, unknown>;
/**
* The viewport is always `null` for the root `RouteNode`.
*
* NOTE: It might make sense to have a `null` viewport mean other things as well (such as, don't load this component)
* but that is currently not a deliberately implemented feature and we might want to explicitly validate against it
* if we decide not to implement that.
*/
viewport: string | null;
title: string | ((node: RouteNode) => string | null) | null;
component: CustomElementDefinition;
readonly params: Readonly<Params>;
readonly queryParams: Readonly<URLSearchParams>;
readonly fragment: string | null;
readonly data: Readonly<Record<string, unknown>>;
readonly title: string | ((node: RouteNode) => string | null) | null;
readonly component: CustomElementDefinition;
readonly children: RouteNode[];

@@ -70,2 +68,3 @@ /**

get root(): RouteNode;
get isInstructionsFinalized(): boolean;
private constructor();

@@ -75,7 +74,4 @@ static create(input: IRouteNode & {

}): RouteNode;
contains(instructions: ViewportInstructionTree, preferEndpointMatch: boolean): boolean;
appendChild(child: RouteNode): void;
clearChildren(): void;
contains(instructions: ViewportInstructionTree, options: Partial<RouteNodeMatchOptions>): boolean;
getTitle(separator: string): string | null;
getTitlePart(): string | null;
computeAbsolutePath(): string;

@@ -90,5 +86,3 @@ toString(): string;

constructor(options: NavigationOptions, queryParams: Readonly<URLSearchParams>, fragment: string | null, root: RouteNode);
contains(instructions: ViewportInstructionTree, preferEndpointMatch: boolean): boolean;
clone(): RouteTree;
finalizeInstructions(): ViewportInstructionTree;
contains(instructions: ViewportInstructionTree, options: Partial<RouteNodeMatchOptions>): boolean;
toString(): string;

@@ -95,0 +89,0 @@ }

import { Constructable, ResourceType, IContainer } from '@aurelia/kernel';
import type { RouteNode } from './route-tree';
import type { FallbackFunction, IChildRouteConfig, IRouteConfig, Routeable, TransitionPlan, TransitionPlanOrFunc } from './options';
import type { FallbackFunction, IChildRouteConfig, IRouteConfig, Routeable, TransitionPlanOrFunc } from './options';
export declare const noRoutes: readonly Routeable[];

@@ -19,3 +19,2 @@ export declare class RouteConfig implements IRouteConfig, IChildRouteConfig {

private constructor();
getTransitionPlan(cur: RouteNode, next: RouteNode): TransitionPlan;
register(container: IContainer): void;

@@ -51,4 +50,2 @@ }

*
* (TODO: improve the formatting, better examples, etc)
*
* ```

@@ -55,0 +52,0 @@ * &#64;route('home')

@@ -1,2 +0,2 @@

import { IEventAggregator, IDisposable, ILogger } from '@aurelia/kernel';
import { IDisposable } from '@aurelia/kernel';
import type { ViewportInstructionTree } from './instructions';

@@ -14,7 +14,2 @@ export type RoutingTrigger = 'popstate' | 'hashchange' | 'api';

export declare class RouterEvents implements IRouterEvents {
private readonly ea;
private readonly logger;
private subscriptionSerial;
private readonly subscriptions;
constructor(ea: IEventAggregator, logger: ILogger);
publish(event: RouterEvent): void;

@@ -21,0 +16,0 @@ subscribe<T extends RouterEvent['name']>(event: T, callback: (message: NameToEvent[T]) => void): IDisposable;

@@ -1,6 +0,5 @@

import { IContainer, ILogger } from '@aurelia/kernel';
import { CustomElementDefinition, IPlatform } from '@aurelia/runtime-html';
import { IContainer } from '@aurelia/kernel';
import { CustomElementDefinition } from '@aurelia/runtime-html';
import { IRouteContext } from './route-context';
import { IRouterEvents, ManagedState, RoutingTrigger } from './router-events';
import { ILocationManager } from './location-manager';
import { ManagedState, RoutingTrigger } from './router-events';
import { RouteConfig, RouteType } from './route';

@@ -10,3 +9,2 @@ import { IRouteViewModel } from './component-agent';

import { IViewportInstruction, NavigationInstruction, RouteContextLike, ViewportInstructionTree } from './instructions';
import { UnwrapPromise } from './util';
import { type ViewportAgent } from './viewport-agent';

@@ -34,5 +32,2 @@ import { INavigationOptions, NavigationOptions, type RouterOptions } from './options';

private constructor();
static create(input: Omit<Transition, 'run' | 'handleError' | 'erredWithUnknownRoute'>): Transition;
run<T>(cb: () => T, next: (value: UnwrapPromise<T>) => void): void;
handleError(err: unknown): void;
toString(): string;

@@ -44,36 +39,7 @@ }

export declare class Router {
private readonly container;
private readonly p;
private readonly logger;
private readonly events;
private readonly locationMgr;
readonly options: Readonly<RouterOptions>;
private _ctx;
private get ctx();
private _routeTree;
get routeTree(): RouteTree;
private _currentTr;
get currentTr(): Transition;
private set currentTr(value);
private navigated;
private navigationId;
private instructions;
private nextTr;
private locationChangeSubscription;
private _isNavigating;
get isNavigating(): boolean;
constructor(container: IContainer, p: IPlatform, logger: ILogger, events: IRouterEvents, locationMgr: ILocationManager, options: Readonly<RouterOptions>);
/**
* Get the closest RouteContext relative to the provided component, controller or node.
*
* @param context - The object from which to resolve the closest RouteContext.
*
* @returns when the value is:
* - `null`: the root
* - `IRouteContext`: the provided value (no-op)
* - `HTMLElement`: the context of the routeable component (page) that directly or indirectly contains this element.
* - `ICustomElementViewModel` (the `this` object when working from inside a view model): the context of this component (if it was loaded as a route), or the routeable component (page) directly or indirectly containing it.
* - `ICustomElementController`: same as `ICustomElementViewModel`, but using the controller object instead of the view model object (advanced users).
*/
resolveContext(context: RouteContextLike | null): IRouteContext;
readonly options: Readonly<RouterOptions>;
constructor();
start(performInitialNavigation: boolean): void | Promise<boolean>;

@@ -152,3 +118,3 @@ stop(): void;

isActive(instructionOrInstructions: NavigationInstruction | readonly NavigationInstruction[], context: RouteContextLike): boolean;
private readonly vpaLookup;
private readonly _vpaLookup;
/**

@@ -166,18 +132,4 @@ * Retrieve the RouteContext, which contains statically configured routes combined with the customElement metadata associated with a type.

createViewportInstructions(instructionOrInstructions: NavigationInstruction | readonly NavigationInstruction[], options?: INavigationOptions): ViewportInstructionTree;
/**
* Enqueue an instruction tree to be processed as soon as possible.
*
* Will wait for any existing in-flight transition to finish, otherwise starts immediately.
*
* @param instructions - The instruction tree that determines the transition
* @param trigger - `'popstate'` or `'hashchange'` if initiated by a browser event, or `'api'` for manually initiated transitions via the `load` api.
* @param state - The state to restore, if any.
* @param failedTr - If this is a redirect / fallback from a failed transition, the previous transition is passed forward to ensure the original promise resolves with the latest result.
*/
private enqueue;
private run;
updateTitle(tr?: Transition): string;
private cancelNavigation;
private runNextTransition;
}
//# sourceMappingURL=router.d.ts.map

@@ -8,3 +8,3 @@ import { ICustomElementController } from '@aurelia/runtime-html';

export declare class ScrollStateManager implements IStateManager {
private readonly cache;
private readonly _cache;
saveState(controller: ICustomElementController): void;

@@ -11,0 +11,0 @@ restoreState(controller: ICustomElementController): void;

import { Params } from './instructions';
import type { RouteNode } from './route-tree';
export type UnwrapPromise<T> = T extends Promise<infer R> ? R : T;
export declare class Batch {
private stack;
private cb;
done: boolean;
readonly head: Batch;
private next;
private constructor();
static start(cb: (b: Batch) => void): Batch;
push(): void;
pop(): void;
private invoke;
continueWith(cb: (b: Batch) => void): Batch;
start(): Batch;
}
export declare function mergeDistinct(prev: RouteNode[], next: RouteNode[]): RouteNode[];

@@ -19,0 +5,0 @@ export declare function tryStringify(value: unknown): string;

import { type PartialCustomElementDefinition } from '@aurelia/runtime-html';
import type { IChildRouteConfig, IRedirectRouteConfig } from './options';
import type { IViewportInstruction, Params, RouteableComponent } from './instructions';
import type { IExtendedViewportInstruction, IViewportInstruction, Params, RouteableComponent } from './instructions';
export declare function isPartialCustomElementDefinition(value: RouteableComponent | IChildRouteConfig | null | undefined): value is PartialCustomElementDefinition;
export declare function isPartialChildRouteConfig(value: RouteableComponent | IChildRouteConfig | IRedirectRouteConfig | null | undefined): value is IChildRouteConfig;
export declare function isPartialRedirectRouteConfig(value: RouteableComponent | IChildRouteConfig | IRedirectRouteConfig | null | undefined): value is IRedirectRouteConfig;
export declare function isPartialViewportInstruction(value: RouteableComponent | IViewportInstruction | null | undefined): value is IViewportInstruction;
export declare function isPartialViewportInstruction(value: RouteableComponent | IViewportInstruction | null | undefined): value is IExtendedViewportInstruction;
export declare function expectType(expected: string, prop: string, value: unknown): never;

@@ -9,0 +9,0 @@ /**

@@ -13,18 +13,3 @@ import { type ICustomElementController } from '@aurelia/runtime-html';

readonly hostController: ICustomElementController;
readonly ctx: IRouteContext;
private readonly logger;
private isActive;
private curCA;
private nextCA;
private get $state();
private state;
private get currState();
private set currState(value);
private get nextState();
private set nextState(value);
private $plan;
private currNode;
private nextNode;
private currTransition;
constructor(viewport: IViewport, hostController: ICustomElementController, ctx: IRouteContext);
private constructor();
static for(viewport: IViewport, ctx: IRouteContext): ViewportAgent;

@@ -31,0 +16,0 @@ toString(): string;

{
"name": "@aurelia/router-lite",
"version": "2.1.0-dev.202306061010",
"version": "2.1.0-dev.202306130710",
"main": "dist/cjs/index.cjs",

@@ -53,9 +53,9 @@ "module": "dist/esm/index.mjs",

"dependencies": {
"@aurelia/kernel": "2.1.0-dev.202306061010",
"@aurelia/metadata": "2.1.0-dev.202306061010",
"@aurelia/platform": "2.1.0-dev.202306061010",
"@aurelia/platform-browser": "2.1.0-dev.202306061010",
"@aurelia/route-recognizer": "2.1.0-dev.202306061010",
"@aurelia/runtime": "2.1.0-dev.202306061010",
"@aurelia/runtime-html": "2.1.0-dev.202306061010"
"@aurelia/kernel": "2.1.0-dev.202306130710",
"@aurelia/metadata": "2.1.0-dev.202306130710",
"@aurelia/platform": "2.1.0-dev.202306130710",
"@aurelia/platform-browser": "2.1.0-dev.202306130710",
"@aurelia/route-recognizer": "2.1.0-dev.202306130710",
"@aurelia/runtime": "2.1.0-dev.202306130710",
"@aurelia/runtime-html": "2.1.0-dev.202306130710"
},

@@ -62,0 +62,0 @@ "devDependencies": {

import { ILogger } from '@aurelia/kernel';
import type { ICustomElementController, IHydratedController, ICustomElementViewModel, ILifecycleHooks, LifecycleHooksLookup } from '@aurelia/runtime-html';
import type { ICustomElementController, ICustomElementViewModel, IHydratedController, ILifecycleHooks, LifecycleHooksLookup } from '@aurelia/runtime-html';
import type { RouteNode } from './route-tree';
import { IRouteContext } from './route-context';
import { Events, trace } from './events';
import {
NavigationInstruction,
Params,
NavigationInstruction,
ViewportInstructionTree
} from './instructions';
import type { IRouteConfig, RouterOptions } from './options';
import { IRouteContext } from './route-context';
import type { RouteNode } from './route-tree';
import type { Transition } from './router';
import { Batch } from './util';
import type { RouterOptions, IRouteConfig } from './options';

@@ -29,2 +30,4 @@ export interface IRouteViewModel extends ICustomElementViewModel {

* and activating, deactivating, and disposing the component (via the associated controller).
*
* @internal
*/

@@ -44,13 +47,13 @@ export class ComponentAgent<T extends IRouteViewModel = IRouteViewModel> {

public constructor(
public readonly instance: T,
public readonly controller: ICustomElementController<T>,
public readonly routeNode: RouteNode,
public readonly ctx: IRouteContext,
private readonly routerOptions: RouterOptions,
/** @internal */ private readonly _instance: T,
/** @internal */ private readonly _controller: ICustomElementController<T>,
/** @internal */ public readonly _routeNode: RouteNode,
/** @internal */ private readonly _ctx: IRouteContext,
/** @internal */ private readonly _routerOptions: RouterOptions,
) {
this._logger = ctx.container.get(ILogger).scopeTo(`ComponentAgent<${ctx.friendlyPath}>`);
this._logger = _ctx.container.get(ILogger).scopeTo(`ComponentAgent<${_ctx._friendlyPath}>`);
this._logger.trace(`constructor()`);
if (__DEV__) trace(this._logger, Events.caCreated);
const lifecycleHooks = controller.lifecycleHooks as LifecycleHooksLookup<IRouteViewModel>;
const lifecycleHooks = _controller.lifecycleHooks as LifecycleHooksLookup<IRouteViewModel>;
this._canLoadHooks = (lifecycleHooks.canLoad ?? []).map(x => x.instance);

@@ -60,6 +63,6 @@ this._loadHooks = (lifecycleHooks.loading ?? []).map(x => x.instance);

this._unloadHooks = (lifecycleHooks.unloading ?? []).map(x => x.instance);
this._hasCanLoad = 'canLoad' in instance;
this._hasLoad = 'loading' in instance;
this._hasCanUnload = 'canUnload' in instance;
this._hasUnload = 'unloading' in instance;
this._hasCanLoad = 'canLoad' in _instance;
this._hasLoad = 'loading' in _instance;
this._hasCanUnload = 'canUnload' in _instance;
this._hasUnload = 'unloading' in _instance;
}

@@ -70,9 +73,9 @@

if (initiator === null) {
this._logger.trace(`activate() - initial`);
return this.controller.activate(this.controller, parent);
if (__DEV__) trace(this._logger, Events.caActivateSelf);
return this._controller.activate(this._controller, parent);
}
this._logger.trace(`activate()`);
if (__DEV__) trace(this._logger, Events.caActivateInitiator);
// Promise return values from user VM hooks are awaited by the initiator
void this.controller.activate(initiator, parent);
void this._controller.activate(initiator, parent);
}

@@ -83,9 +86,9 @@

if (initiator === null) {
this._logger.trace(`deactivate() - initial`);
return this.controller.deactivate(this.controller, parent);
if (__DEV__) trace(this._logger, Events.caDeactivateSelf);
return this._controller.deactivate(this._controller, parent);
}
this._logger.trace(`deactivate()`);
if (__DEV__) trace(this._logger, Events.caDeactivateInitiator);
// Promise return values from user VM hooks are awaited by the initiator
void this.controller.deactivate(initiator, parent);
void this._controller.deactivate(initiator, parent);
}

@@ -95,5 +98,5 @@

public _dispose(): void {
this._logger.trace(`dispose()`);
if (__DEV__) trace(this._logger, Events.caDispose);
this.controller.dispose();
this._controller.dispose();
}

@@ -103,15 +106,15 @@

public _canUnload(tr: Transition, next: RouteNode | null, b: Batch): void {
this._logger.trace(`canUnload(next:%s) - invoking ${this._canUnloadHooks.length} hooks`, next);
b.push();
if (__DEV__) trace(this._logger, Events.caCanUnload, next, this._canUnloadHooks.length);
b._push();
let promise: Promise<void> = Promise.resolve();
for (const hook of this._canUnloadHooks) {
b.push();
b._push();
promise = promise.then(() => new Promise((res) => {
if (tr.guardsResult !== true) {
b.pop();
b._pop();
res();
return;
}
tr.run(() => {
return hook.canUnload(this.instance, next, this.routeNode);
tr._run(() => {
return hook.canUnload(this._instance, next, this._routeNode);
}, ret => {

@@ -121,3 +124,3 @@ if (tr.guardsResult === true && ret !== true) {

}
b.pop();
b._pop();
res();

@@ -128,11 +131,11 @@ });

if (this._hasCanUnload) {
b.push();
b._push();
// deepscan-disable-next-line UNUSED_VAR_ASSIGN
promise = promise.then(() => {
if (tr.guardsResult !== true) {
b.pop();
b._pop();
return;
}
tr.run(() => {
return this.instance.canUnload!(next, this.routeNode);
tr._run(() => {
return this._instance.canUnload!(next, this._routeNode);
}, ret => {

@@ -142,7 +145,7 @@ if (tr.guardsResult === true && ret !== true) {

}
b.pop();
b._pop();
});
});
}
b.pop();
b._pop();
}

@@ -152,21 +155,21 @@

public _canLoad(tr: Transition, next: RouteNode, b: Batch): void {
this._logger.trace(`canLoad(next:%s) - invoking ${this._canLoadHooks.length} hooks`, next);
const rootCtx = this.ctx.root;
b.push();
if (__DEV__) trace(this._logger, Events.caCanLoad, next, this._canLoadHooks.length);
const rootCtx = this._ctx.root;
b._push();
let promise: Promise<void> = Promise.resolve();
for (const hook of this._canLoadHooks) {
b.push();
b._push();
promise = promise.then(() => new Promise((res) => {
if (tr.guardsResult !== true) {
b.pop();
b._pop();
res();
return;
}
tr.run(() => {
return hook.canLoad(this.instance, next.params, next, this.routeNode);
tr._run(() => {
return hook.canLoad(this._instance, next.params, next, this._routeNode);
}, ret => {
if (tr.guardsResult === true && ret !== true) {
tr.guardsResult = ret === false ? false : ViewportInstructionTree.create(ret, this.routerOptions, void 0, rootCtx);
tr.guardsResult = ret === false ? false : ViewportInstructionTree.create(ret, this._routerOptions, void 0, rootCtx);
}
b.pop();
b._pop();
res();

@@ -177,20 +180,20 @@ });

if (this._hasCanLoad) {
b.push();
b._push();
// deepscan-disable-next-line UNUSED_VAR_ASSIGN
promise = promise.then(() => {
if (tr.guardsResult !== true) {
b.pop();
b._pop();
return;
}
tr.run(() => {
return this.instance.canLoad!(next.params, next, this.routeNode);
tr._run(() => {
return this._instance.canLoad!(next.params, next, this._routeNode);
}, ret => {
if (tr.guardsResult === true && ret !== true) {
tr.guardsResult = ret === false ? false : ViewportInstructionTree.create(ret, this.routerOptions, void 0, rootCtx);
tr.guardsResult = ret === false ? false : ViewportInstructionTree.create(ret, this._routerOptions, void 0, rootCtx);
}
b.pop();
b._pop();
});
});
}
b.pop();
b._pop();
}

@@ -200,21 +203,21 @@

public _unloading(tr: Transition, next: RouteNode | null, b: Batch): void {
this._logger.trace(`unloading(next:%s) - invoking ${this._unloadHooks.length} hooks`, next);
b.push();
if (__DEV__) trace(this._logger, Events.caUnloading, next, this._unloadHooks.length);
b._push();
for (const hook of this._unloadHooks) {
tr.run(() => {
b.push();
return hook.unloading(this.instance, next, this.routeNode);
tr._run(() => {
b._push();
return hook.unloading(this._instance, next, this._routeNode);
}, () => {
b.pop();
b._pop();
});
}
if (this._hasUnload) {
tr.run(() => {
b.push();
return this.instance.unloading!(next, this.routeNode);
tr._run(() => {
b._push();
return this._instance.unloading!(next, this._routeNode);
}, () => {
b.pop();
b._pop();
});
}
b.pop();
b._pop();
}

@@ -224,22 +227,22 @@

public _loading(tr: Transition, next: RouteNode, b: Batch): void {
this._logger.trace(`loading(next:%s) - invoking ${this._loadHooks.length} hooks`, next);
b.push();
if (__DEV__) trace(this._logger, Events.caLoading, next, this._loadHooks.length);
b._push();
for (const hook of this._loadHooks) {
tr.run(() => {
b.push();
return hook.loading(this.instance, next.params, next, this.routeNode);
tr._run(() => {
b._push();
return hook.loading(this._instance, next.params, next, this._routeNode);
}, () => {
b.pop();
b._pop();
});
}
if (this._hasLoad) {
tr.run(() => {
b.push();
return this.instance.loading!(next.params, next, this.routeNode);
tr._run(() => {
b._push();
return this._instance.loading!(next.params, next, this._routeNode);
}, () => {
b.pop();
b._pop();
});
}
b.pop();
b._pop();
}
}

@@ -21,3 +21,2 @@ export {

type IRouteViewModel,
ComponentAgent,
} from './component-agent';

@@ -24,0 +23,0 @@

@@ -24,2 +24,3 @@ import { isObject } from '@aurelia/metadata';

import { mergeURLSearchParams, tryStringify } from './util';
import { Events, getMessage } from './events';

@@ -51,5 +52,5 @@ export const defaultViewportName = 'default';

export type IExtendedViewportInstruction = IViewportInstruction & { readonly open?: number; readonly close?: number };
export interface IViewportInstruction {
readonly open?: number;
readonly close?: number;
/**

@@ -88,6 +89,6 @@ * The component to load.

export class ViewportInstruction<TComponent extends ITypedNavigationInstruction_T = ITypedNavigationInstruction_Component> implements IViewportInstruction {
export class ViewportInstruction<TComponent extends ITypedNavigationInstruction_T = ITypedNavigationInstruction_Component> implements IExtendedViewportInstruction {
private constructor(
public open: number,
public close: number,
public readonly open: number,
public readonly close: number,
public readonly recognizedRoute: $RecognizedRoute | null,

@@ -100,3 +101,3 @@ public readonly component: TComponent,

public static create(instruction: NavigationInstruction): ViewportInstruction {
public static create(instruction: NavigationInstruction | IExtendedViewportInstruction): ViewportInstruction {
if (instruction instanceof ViewportInstruction) return instruction as ViewportInstruction; // eslint is being really weird here

@@ -119,3 +120,3 @@

const typedInstruction = TypedNavigationInstruction.create(instruction);
const typedInstruction = TypedNavigationInstruction.create(instruction) as ITypedNavigationInstruction_Component;
return new ViewportInstruction(0, 0, null, typedInstruction, null, null, []);

@@ -131,7 +132,7 @@ }

// TODO(fkleuver): incorporate viewports when null / '' descrepancies are fixed,
// as well as params when inheritance is fully fixed
if (!this.component.equals(other.component)) {
return false;
}
if (!this.component.equals(other.component)) return false;
// if either of the viewports are not set then ignore
const vp = this.viewport ?? null;
const otherVp = other.viewport ?? null;
if (vp !== null && otherVp !== null && vp !== otherVp) return false;

@@ -155,3 +156,2 @@ for (let i = 0, ii = otherChildren.length; i < ii; ++i) {

if (
// TODO(fkleuver): decide if we really need to include `context` in this comparison
!this.component.equals(other.component) ||

@@ -173,3 +173,4 @@ this.viewport !== other.viewport ||

public clone(): this {
/** @internal */
public _clone(): this {
return new ViewportInstruction(

@@ -179,3 +180,3 @@ this.open,

this.recognizedRoute,
this.component.clone(),
this.component._clone(),
this.viewport,

@@ -188,5 +189,21 @@ this.params === null ? null : { ...this.params },

public toUrlComponent(recursive: boolean = true): string {
// TODO(fkleuver): use the context to determine create full tree
const component = this.component.toUrlComponent();
const params = this.params === null || Object.keys(this.params).length === 0 ? '' : `(${stringifyParams(this.params)})`; /** TODO(sayan): review the path generation usage and correct this stringifyParams artefact. */
/**
* Note on the parenthesized parameters:
* We will land on this branch if and only if the component cannot be eagerly recognized (in the RouteContext#generateViewportInstruction) AND the parameters are also provided.
* When the routes are eagerly recognized, then there is no parameters left at this point and everything is already packed in the generated path as well as in the recognized route.
* Thus, in normal scenarios the users will never land here.
*
* Whenever, they are using a hand composed (string) path, then in that case there is no question of having parameters at this point, rather the given path is recognized in the createAndAppendNodes.
* It might be a rare edge case where users provide half the parameters in the string path and half as form of parameters; example: `load="route: r1/id1; params.bind: {id2}"`.
* We might not want to officially support such cases.
*
* However, as the route recognition is inherently lazy (think about child routes, whose routing configuration are not resolved till a child routing context is created, or
* the usage of instance level getRouteConfig), the component cannot be recognized fully eagerly. Thus, it is difficult at this point to correctly handle parameters as defined by the path templates defined for the component.
* This artifact is kept here for the purpose of fallback.
*
* We can think about a stricter mode where we throw error if any params remains unconsumed at this point.
* Or simply ignore the params while creating the URL. However, that does not feel right at all.
*/
const params = this.params === null || Object.keys(this.params).length === 0 ? '' : `(${stringifyParams(this.params)})`;
const vp = this.viewport;

@@ -205,2 +222,3 @@ const viewport = component.length === 0 || vp === null || vp.length === 0 || vp === defaultViewportName ? '' : `@${vp}`;

// Should not be adjust for DEV as it is also used of logging in production build.
public toString(): string {

@@ -241,53 +259,2 @@ const component = `c:${this.component}`;

export interface IRedirectInstruction {
readonly path: string;
readonly redirectTo: string;
}
export class RedirectInstruction implements IRedirectInstruction {
private constructor(
public readonly path: string,
public readonly redirectTo: string,
) { }
public static create(instruction: IRedirectInstruction): RedirectInstruction {
if (instruction instanceof RedirectInstruction) {
return instruction;
}
return new RedirectInstruction(instruction.path, instruction.redirectTo);
}
public equals(other: RedirectInstruction): boolean {
return this.path === other.path && this.redirectTo === other.redirectTo;
}
public toUrlComponent(): string {
return this.path;
}
public toString(): string {
return `RI(path:'${this.path}',redirectTo:'${this.redirectTo}')`;
}
}
/**
* Associate the object with an id so it can be stored in history as a serialized url segment.
*
* WARNING: As the implementation is right now, this is a memory leak disaster.
* This is really a placeholder implementation at the moment and should NOT be used / advertised for production until a leak-free solution is made.
*/
const getObjectId = (function () {
let lastId = 0;
const objectIdMap = new Map<object, number>();
return function (obj: object): number {
let id = objectIdMap.get(obj);
if (id === void 0) {
objectIdMap.set(obj, id = ++lastId);
}
return id;
};
})();
export class ViewportInstructionTree {

@@ -322,3 +289,3 @@ public constructor(

const instruction = instructionOrInstructions[i];
const eagerVi = hasContext ? context.generateViewportInstruction(instruction) : null;
const eagerVi = hasContext ? context._generateViewportInstruction(instruction) : null;
if (eagerVi !== null) {

@@ -339,3 +306,8 @@ children[i] = eagerVi.vi;

const eagerVi = hasContext ? context.generateViewportInstruction(instructionOrInstructions) : null;
const eagerVi = hasContext
? context._generateViewportInstruction(isPartialViewportInstruction(instructionOrInstructions)
? { ...instructionOrInstructions, params: instructionOrInstructions.params ?? emptyObject }
: { component: instructionOrInstructions, params: emptyObject }
)
: null;
const query = new URLSearchParams($options.queryParams ?? emptyObject);

@@ -397,2 +369,3 @@ return eagerVi !== null

// Should not be adjust for DEV as it is also used of logging in production build.
public toString(): string {

@@ -418,3 +391,3 @@ return `[${this.children.map(String).join(',')}]`;

toUrlComponent(): string;
clone(): this;
_clone(): this;
}

@@ -482,3 +455,3 @@ export interface ITypedNavigationInstruction_string extends ITypedNavigationInstruction<string, NavigationInstructionType.string> { }

if (instruction instanceof CustomElementDefinition) return new TypedNavigationInstruction(NavigationInstructionType.CustomElementDefinition, instruction);
throw new Error(`Invalid component ${tryStringify(instruction)}: must be either a class, a custom element ViewModel, or a (partial) custom element definition`);
throw new Error(getMessage(Events.instrInvalid, tryStringify(instruction)));
}

@@ -498,3 +471,4 @@

public clone(): this {
/** @internal */
public _clone(): this {
return new TypedNavigationInstruction(

@@ -512,3 +486,3 @@ this.type,

case NavigationInstructionType.Promise:
return `au$obj${getObjectId(this.value)}`;
throw new Error(getMessage(Events.instrInvalidUrlComponentOperation, this.type));
case NavigationInstructionType.ViewportInstruction:

@@ -521,2 +495,3 @@ return this.value.toUrlComponent();

// Should not be adjust for DEV as it is also used of logging in production build.
public toString(this: ITypedNavigationInstruction_T): string {

@@ -523,0 +498,0 @@ switch (this.type) {

@@ -1,13 +0,14 @@

import { DI, ILogger } from '@aurelia/kernel';
import { DI, ILogger, resolve } from '@aurelia/kernel';
import { IHistory, ILocation, IWindow } from '@aurelia/runtime-html';
import { type RouterOptions, IRouterOptions } from './options';
import { IRouterOptions } from './options';
import { IRouterEvents, LocationChangeEvent } from './router-events';
import { Events, debug, trace, warn } from './events';
export interface IPopStateEvent extends PopStateEvent {}
export interface IHashChangeEvent extends HashChangeEvent {}
export interface IPopStateEvent extends PopStateEvent { }
export interface IHashChangeEvent extends HashChangeEvent { }
export const IBaseHref = /*@__PURE__*/DI.createInterface<URL>('IBaseHref');
export const ILocationManager = /*@__PURE__*/DI.createInterface<ILocationManager>('ILocationManager', x => x.singleton(BrowserLocationManager));
export interface ILocationManager extends BrowserLocationManager {}
export interface ILocationManager extends BrowserLocationManager { }

@@ -22,35 +23,31 @@ /**

export class BrowserLocationManager {
private eventId: number = 0;
/** @internal */
private readonly _event: 'hashchange' | 'popstate';
/** @internal */ private _eventId: number = 0;
public constructor(
@ILogger private readonly logger: ILogger,
@IRouterEvents private readonly events: IRouterEvents,
@IHistory private readonly history: IHistory,
@ILocation private readonly location: ILocation,
@IWindow private readonly window: IWindow,
@IBaseHref private readonly baseHref: URL,
@IRouterOptions routerOptions: Readonly<RouterOptions>,
) {
logger = this.logger = logger.root.scopeTo('LocationManager');
logger.debug(`baseHref set to path: ${baseHref.href}`);
this._event = routerOptions.useUrlFragmentHash ? 'hashchange' : 'popstate';
/** @internal */ private readonly _logger: ILogger = resolve(ILogger).root.scopeTo('LocationManager');
/** @internal */ private readonly _events: IRouterEvents = resolve(IRouterEvents);
/** @internal */ private readonly _history: IHistory = resolve(IHistory);
/** @internal */ private readonly _location: ILocation = resolve(ILocation);
/** @internal */ private readonly _window: IWindow = resolve(IWindow);
/** @internal */ private readonly _baseHref: URL = resolve(IBaseHref);
/** @internal */ private readonly _event: 'hashchange' | 'popstate' = resolve(IRouterOptions).useUrlFragmentHash ? 'hashchange' : 'popstate';
public constructor() {
if (__DEV__) debug(this._logger, Events.lmBaseHref, this._baseHref.href);
}
public startListening(): void {
this.logger.trace(`startListening()`);
if (__DEV__) trace(this._logger, Events.lmStartListening, this._event);
this.window.addEventListener(this._event, this, false);
this._window.addEventListener(this._event, this, false);
}
public stopListening(): void {
this.logger.trace(`stopListening()`);
if (__DEV__) trace(this._logger, Events.lmStopListening, this._event);
this.window.removeEventListener(this._event, this, false);
this._window.removeEventListener(this._event, this, false);
}
public handleEvent(event: IPopStateEvent | IHashChangeEvent): void {
this.events.publish(new LocationChangeEvent(
++this.eventId,
this._events.publish(new LocationChangeEvent(
++this._eventId,
this.getPath(),

@@ -64,10 +61,12 @@ this._event,

url = this.addBaseHref(url);
try {
const stateString = JSON.stringify(state);
this.logger.trace(`pushState(state:${stateString},title:'${title}',url:'${url}')`);
} catch (err) {
this.logger.warn(`pushState(state:NOT_SERIALIZABLE,title:'${title}',url:'${url}')`);
if (__DEV__) {
try {
const stateString = JSON.stringify(state);
trace(this._logger, Events.lmPushState, stateString, title, url);
} catch (_err) {
warn(this._logger, Events.lmPushStateNonSerializable, title, url);
}
}
this.history.pushState(state, title, url);
this._history.pushState(state, title, url);
}

@@ -77,34 +76,23 @@

url = this.addBaseHref(url);
try {
const stateString = JSON.stringify(state);
this.logger.trace(`replaceState(state:${stateString},title:'${title}',url:'${url}')`);
} catch (err) {
this.logger.warn(`replaceState(state:NOT_SERIALIZABLE,title:'${title}',url:'${url}')`);
if (__DEV__) {
try {
const stateString = JSON.stringify(state);
trace(this._logger, Events.lmReplaceState, stateString, title, url);
} catch (err) {
warn(this._logger, Events.lmReplaceStateNonSerializable, title, url);
}
}
this.history.replaceState(state, title, url);
this._history.replaceState(state, title, url);
}
public getPath(): string {
const { pathname, search, hash } = this.location;
const path = this.removeBaseHref(`${pathname}${normalizeQuery(search)}${hash}`);
this.logger.trace(`getPath() -> '${path}'`);
return path;
const { pathname, search, hash } = this._location;
return this.removeBaseHref(`${pathname}${normalizeQuery(search)}${hash}`);
}
public currentPathEquals(path: string): boolean {
const equals = this.getPath() === this.removeBaseHref(path);
this.logger.trace(`currentPathEquals(path:'${path}') -> ${equals}`);
return equals;
}
public addBaseHref(path: string): string {
const initialPath = path;
let fullPath: string;
let base = this.baseHref.href;
let base = this._baseHref.href;
if (base.endsWith('/')) {

@@ -122,5 +110,2 @@ base = base.slice(0, -1);

}
this.logger.trace(`addBaseHref(path:'${initialPath}') -> '${fullPath}'`);
return fullPath;

@@ -130,12 +115,7 @@ }

public removeBaseHref(path: string): string {
const $path = path;
const basePath = this.baseHref.pathname;
const basePath = this._baseHref.pathname;
if (path.startsWith(basePath)) {
path = path.slice(basePath.length);
}
path = normalizePath(path);
this.logger.trace(`removeBaseHref(path:'${$path}') -> '${path}'`);
return path;
return normalizePath(path);
}

@@ -146,2 +126,4 @@ }

* Strip trailing `/index.html` and trailing `/` from the path, if present.
*
* @internal
*/

@@ -148,0 +130,0 @@ export function normalizePath(path: string): string {

import { DI } from '@aurelia/kernel';
import type { Params, RouteContextLike, RouteableComponent, ViewportInstruction, ViewportInstructionTree } from './instructions';
import type { IViewportInstruction, Params, RouteContextLike, RouteableComponent, ViewportInstructionTree } from './instructions';
import type { RouteNode } from './route-tree';

@@ -50,2 +50,8 @@ import type { Transition } from './router';

public readonly activeClass: string | null,
/**
* When set to `true`, the router will try to restore previous route tree, when a routing instruction errs.
* Set this to `false`, if a stricter behavior is desired. However, in that case, you need to ensure the avoidance of errors.
* The default value is `true`.
*/
public readonly restorePreviousRouteTreeOnError: boolean,
) { }

@@ -61,8 +67,9 @@

input.activeClass ?? null,
input.restorePreviousRouteTreeOnError ?? true,
);
}
/** @internal */
public _stringifyProperties(): string {
return ([
public toString(): string {
if(!__DEV__) return 'RO';
return `RO(${([
['historyStrategy', 'history'],

@@ -72,8 +79,4 @@ ] as const).map(([key, name]) => {

return `${name}:${typeof value === 'function' ? value : `'${value}'`}`;
}).join(',');
}).join(',')})`;
}
public toString(): string {
return `RO(${this._stringifyProperties()})`;
}
}

@@ -128,3 +131,4 @@

public clone(): NavigationOptions {
/** @internal */
public _clone(): NavigationOptions {
return new NavigationOptions(

@@ -148,3 +152,3 @@ this.historyStrategy,

export type FallbackFunction = (viewportInstruction: ViewportInstruction, routeNode: RouteNode, context: IRouteContext) => Routeable | null;
export type FallbackFunction = (viewportInstruction: IViewportInstruction, routeNode: RouteNode, context: IRouteContext) => Routeable | null;

@@ -151,0 +155,0 @@ /**

@@ -15,2 +15,3 @@ import {

import { IRouteContext } from '../route-context';
import { resolve } from '@aurelia/kernel';

@@ -32,10 +33,16 @@ /*

export class HrefCustomAttribute implements ICustomAttributeViewModel {
/** @internal */private readonly _el: INode<HTMLElement> = resolve<INode<HTMLElement>>(INode as unknown as INode<HTMLElement>);
/** @internal */private readonly _router: IRouter = resolve(IRouter);
/** @internal */private readonly _ctx: IRouteContext = resolve(IRouteContext);
@bindable({ mode: BindingMode.toView })
public value: unknown;
private isInitialized: boolean = false;
private isEnabled: boolean;
/** @internal */private _isInitialized: boolean = false;
/** @internal */private _isEnabled: boolean;
private get isExternal(): boolean {
return this.el.hasAttribute('external') || this.el.hasAttribute('data-external');
/** @internal */
private get _isExternal(): boolean {
return this._el.hasAttribute('external') || this._el.hasAttribute('data-external');
}

@@ -45,26 +52,22 @@

public constructor(
@INode private readonly el: INode<HTMLElement>,
@IRouter private readonly router: IRouter,
@IRouteContext private readonly ctx: IRouteContext,
@IWindow w: IWindow,
) {
public constructor() {
if (
router.options.useHref &&
this._router.options.useHref &&
// Ensure the element is an anchor
el.nodeName === 'A'
this._el.nodeName === 'A'
) {
const windowName = resolve(IWindow).name;
// Ensure the anchor targets the current window.
switch (el.getAttribute('target')) {
switch (this._el.getAttribute('target')) {
case null:
case w.name:
case windowName:
case '_self':
this.isEnabled = true;
this._isEnabled = true;
break;
default:
this.isEnabled = false;
this._isEnabled = false;
break;
}
} else {
this.isEnabled = false;
this._isEnabled = false;
}

@@ -74,8 +77,8 @@ }

public binding(): void {
if (!this.isInitialized) {
this.isInitialized = true;
this.isEnabled = this.isEnabled && getRef(this.el, CustomAttribute.getDefinition(LoadCustomAttribute).key) === null;
if (!this._isInitialized) {
this._isInitialized = true;
this._isEnabled = this._isEnabled && getRef(this._el, CustomAttribute.getDefinition(LoadCustomAttribute).key) === null;
}
this.valueChanged(this.value);
this.el.addEventListener('click', this);
this._el.addEventListener('click', this);
// this.eventListener = this.delegator.addEventListener(this.target, this.el, 'click', this);

@@ -85,3 +88,3 @@ }

// this.eventListener.dispose();
this.el.removeEventListener('click', this);
this._el.removeEventListener('click', this);
}

@@ -91,6 +94,6 @@

if (newValue == null) {
this.el.removeAttribute('href');
this._el.removeAttribute('href');
} else {
if (this.router.options.useUrlFragmentHash
&& this.ctx.isRoot
if (this._router.options.useUrlFragmentHash
&& this._ctx.isRoot
&& !/^[.#]/.test(newValue as string)

@@ -100,3 +103,3 @@ ) {

}
this.el.setAttribute('href', newValue as string);
this._el.setAttribute('href', newValue as string);
}

@@ -114,4 +117,4 @@ }

// on an internally managed link
|| this.isExternal
|| !this.isEnabled
|| this._isExternal
|| !this._isEnabled
) {

@@ -122,9 +125,9 @@ return;

// Use the normalized attribute instead of this.value to ensure consistency.
const href = this.el.getAttribute('href');
const href = this._el.getAttribute('href');
if (href !== null) {
e.preventDefault();
// Floating promises from `Router#load` are ok because the router keeps track of state and handles the errors, etc.
void this.router.load(href, { context: this.ctx });
void this._router.load(href, { context: this._ctx });
}
}
}

@@ -1,2 +0,2 @@

import { IDisposable, IIndexable } from '@aurelia/kernel';
import { IDisposable, IIndexable, resolve } from '@aurelia/kernel';
import {

@@ -19,2 +19,9 @@ BindingMode,

export class LoadCustomAttribute implements ICustomAttributeViewModel {
/** @internal */ private readonly _el: INode<HTMLElement> = resolve<INode<HTMLElement>>(INode as unknown as INode<HTMLElement>);
/** @internal */ private readonly _router: IRouter = resolve(IRouter);
/** @internal */ private readonly _ctx: IRouteContext = resolve(IRouteContext);
/** @internal */ private readonly _events: IRouterEvents = resolve(IRouterEvents);
/** @internal */ private readonly _locationMgr: ILocationManager = resolve(ILocationManager);
@bindable({ mode: BindingMode.toView, primary: true, callback: 'valueChanged' })

@@ -38,31 +45,25 @@ public route: unknown;

private href: string | null = null;
private instructions: ViewportInstructionTree | null = null;
private navigationEndListener: IDisposable | null = null;
private readonly isEnabled: boolean;
private readonly activeClass: string | null;
/** @internal */ private _href: string | null = null;
/** @internal */ private _instructions: ViewportInstructionTree | null = null;
/** @internal */ private _navigationEndListener: IDisposable | null = null;
/** @internal */ private readonly _isEnabled: boolean;
/** @internal */ private readonly _activeClass: string | null;
public constructor(
@INode private readonly el: INode<HTMLElement>,
@IRouter private readonly router: IRouter,
@IRouterEvents private readonly events: IRouterEvents,
@IRouteContext private readonly ctx: IRouteContext,
@ILocationManager private readonly locationMgr: ILocationManager,
) {
public constructor() {
const el = this._el;
// Ensure the element is not explicitly marked as external.
this.isEnabled = !el.hasAttribute('external') && !el.hasAttribute('data-external');
this.activeClass = router.options.activeClass;
this._isEnabled = !el.hasAttribute('external') && !el.hasAttribute('data-external');
this._activeClass = this._router.options.activeClass;
}
public binding(): void {
if (this.isEnabled) {
this.el.addEventListener('click', this.onClick as EventListener);
if (this._isEnabled) {
this._el.addEventListener('click', this.onClick as EventListener);
}
this.valueChanged();
this.navigationEndListener = this.events.subscribe('au:router:navigation-end', _e => {
this.valueChanged();
const active = this.active = this.instructions !== null && this.router.isActive(this.instructions, this.context!);
const activeClass = this.activeClass;
this._navigationEndListener = this._events.subscribe('au:router:navigation-end', _e => {
const active = this.active = this._instructions !== null && this._router.isActive(this._instructions, this.context!);
const activeClass = this._activeClass;
if (activeClass === null) return;
this.el.classList.toggle(activeClass, active);
this._el.classList.toggle(activeClass, active);
});

@@ -82,10 +83,10 @@ }

public unbinding(): void {
if (this.isEnabled) {
this.el.removeEventListener('click', this.onClick);
if (this._isEnabled) {
this._el.removeEventListener('click', this.onClick);
}
this.navigationEndListener!.dispose();
this._navigationEndListener!.dispose();
}
public valueChanged(): void {
const router = this.router;
const router = this._router;
const useHash = router.options.useUrlFragmentHash;

@@ -96,9 +97,9 @@ const component = this.route as NavigationInstruction;

if (ctx === void 0) {
ctx = this.context = this.ctx;
ctx = this.context = this._ctx;
} else if (ctx === null) {
ctx = this.context = this.ctx.root;
ctx = this.context = this._ctx.root;
}
if (component != null && ctx.allResolved === null) {
const params = this.params;
const instructions = this.instructions = router.createViewportInstructions(
const instructions = this._instructions = router.createViewportInstructions(
typeof params === 'object' && params !== null

@@ -108,17 +109,17 @@ ? { component, params }

{ context: ctx });
this.href = instructions.toUrl(useHash);
this._href = instructions.toUrl(useHash);
} else {
this.instructions = null;
this.href = null;
this._instructions = null;
this._href = null;
}
const controller = CustomElement.for(this.el, { optional: true });
const controller = CustomElement.for(this._el, { optional: true });
if (controller !== null) {
(controller.viewModel as IIndexable)[this.attribute] = this.instructions;
(controller.viewModel as IIndexable)[this.attribute] = this._instructions;
} else {
if (this.href === null) {
this.el.removeAttribute(this.attribute);
if (this._href === null) {
this._el.removeAttribute(this.attribute);
} else {
const value = useHash ? this.href : this.locationMgr.addBaseHref(this.href);
this.el.setAttribute(this.attribute, value);
const value = useHash ? this._href : this._locationMgr.addBaseHref(this._href);
this._el.setAttribute(this.attribute, value);
}

@@ -129,3 +130,3 @@ }

private readonly onClick = (e: MouseEvent): void => {
if (this.instructions === null) {
if (this._instructions === null) {
return;

@@ -141,4 +142,4 @@ }

// Floating promises from `Router#load` are ok because the router keeps track of state and handles the errors, etc.
void this.router.load(this.instructions, { context: this.context });
void this._router.load(this._instructions, { context: this.context });
};
}

@@ -1,17 +0,18 @@

import { Constructable, ILogger } from '@aurelia/kernel';
import { Constructable, ILogger, resolve } from '@aurelia/kernel';
import {
bindable,
customElement,
CustomElement,
ICompiledCustomElementController,
ICustomElementController,
ICustomElementViewModel,
IHydratedController,
ICustomElementController,
ICompiledCustomElementController,
CustomElement
IHydratedController
} from '@aurelia/runtime-html';
import type { ViewportAgent } from '../viewport-agent';
import { trace, Events } from '../events';
import { defaultViewportName, IViewportInstruction } from '../instructions';
import { FallbackFunction, Routeable } from '../options';
import { IRouteContext } from '../route-context';
import { defaultViewportName, type ViewportInstruction } from '../instructions';
import { type RouteNode } from '../route-tree';
import { FallbackFunction, Routeable } from '../options';
import type { ViewportAgent } from '../viewport-agent';

@@ -24,3 +25,3 @@ export interface IViewport {

/** @internal */
_getFallback(viewportInstruction: ViewportInstruction, routeNode: RouteNode, context: IRouteContext): Routeable | null;
_getFallback(viewportInstruction: IViewportInstruction, routeNode: RouteNode, context: IRouteContext): Routeable | null;
}

@@ -35,16 +36,12 @@

private agent: ViewportAgent = (void 0)!;
private controller: ICustomElementController = (void 0)!;
/** @internal */ private _agent: ViewportAgent = (void 0)!;
/** @internal */ private _controller: ICustomElementController = (void 0)!;
public constructor(
@ILogger private readonly logger: ILogger,
@IRouteContext private readonly ctx: IRouteContext,
) {
this.logger = logger.scopeTo(`au-viewport<${ctx.friendlyPath}>`);
/** @internal */
private readonly _ctx: IRouteContext = resolve(IRouteContext);
/** @internal */
private readonly _logger: ILogger = /*@__PURE__*/ (resolve(ILogger).scopeTo(`au-viewport<${this._ctx._friendlyPath}>`));
this.logger.trace('constructor()');
}
/** @internal */
public _getFallback(viewportInstruction: ViewportInstruction, routeNode: RouteNode, context: IRouteContext): Routeable | null {
public _getFallback(viewportInstruction: IViewportInstruction, routeNode: RouteNode, context: IRouteContext): Routeable | null {
const fallback = this.fallback;

@@ -58,28 +55,29 @@ return typeof fallback === 'function'

public hydrated(controller: ICompiledCustomElementController): void {
this.logger.trace('hydrated()');
if (__DEV__) trace(this._logger, Events.vpHydrated);
this.controller = controller as ICustomElementController;
this.agent = this.ctx.registerViewport(this);
this._controller = controller as ICustomElementController;
this._agent = this._ctx._registerViewport(this);
}
public attaching(initiator: IHydratedController, _parent: IHydratedController): void | Promise<void> {
this.logger.trace('attaching()');
if (__DEV__) trace(this._logger, Events.vpAttaching);
return this.agent._activateFromViewport(initiator, this.controller);
return this._agent._activateFromViewport(initiator, this._controller);
}
public detaching(initiator: IHydratedController, _parent: IHydratedController): void | Promise<void> {
this.logger.trace('detaching()');
if (__DEV__) trace(this._logger, Events.vpDetaching);
return this.agent._deactivateFromViewport(initiator, this.controller);
return this._agent._deactivateFromViewport(initiator, this._controller);
}
public dispose(): void {
this.logger.trace('dispose()');
if (__DEV__) trace(this._logger, Events.vpDispose);
this.ctx.unregisterViewport(this);
this.agent._dispose();
this.agent = (void 0)!;
this._ctx._unregisterViewport(this);
this._agent._dispose();
this._agent = (void 0)!;
}
// Should not be adjust for DEV as it is also used of logging in production build.
public toString(): string {

@@ -107,3 +105,3 @@ const propStrings: string[] = [];

}
return `VP(ctx:'${this.ctx.friendlyPath}',${propStrings.join(',')})`;
return `VP(ctx:'${this._ctx._friendlyPath}',${propStrings.join(',')})`;
}

@@ -110,0 +108,0 @@ }

@@ -33,2 +33,3 @@ import {

import {
IExtendedViewportInstruction,
ITypedNavigationInstruction_Component,

@@ -59,2 +60,3 @@ ITypedNavigationInstruction_string,

import { ViewportAgent, type ViewportRequest } from './viewport-agent';
import { Events, debug, error, getMessage, logAndThrow, trace } from './events';

@@ -66,3 +68,3 @@ export interface IRouteContext extends RouteContext { }

export type EagerInstruction = {
type EagerInstruction = {
component: string | RouteConfig | PartialCustomElementDefinition | IRouteViewModel | IChildRouteConfig | RouteType;

@@ -73,3 +75,3 @@ params: Params;

const allowedEagerComponentTypes = Object.freeze(['string', 'object', 'function']);
export function isEagerInstruction(val: NavigationInstruction | EagerInstruction): val is EagerInstruction {
function isEagerInstruction(val: NavigationInstruction | EagerInstruction): val is EagerInstruction {
// don't try to resolve an instruction with children eagerly, as the children are essentially resolved lazily, for now.

@@ -97,3 +99,3 @@ if (val == null) return false;

export class RouteContext {
private readonly childViewportAgents: ViewportAgent[] = [];
/** @internal */ private readonly _childViewportAgents: ViewportAgent[] = [];
public readonly root: IRouteContext;

@@ -115,4 +117,6 @@ public get isRoot(): boolean {

* Mainly for debugging/introspection purposes.
*
* @internal
*/
public readonly friendlyPath: string;
public readonly _friendlyPath: string;

@@ -125,8 +129,2 @@ /**

/** @internal */
private _resolved: Promise<void> | null = null;
public get resolved(): Promise<void> | null {
return this._resolved;
}
/** @internal */
private _allResolved: Promise<void> | null = null;

@@ -137,17 +135,15 @@ public get allResolved(): Promise<void> | null {

private prevNode: RouteNode | null = null;
/** @internal */
private _node: RouteNode | null = null;
/** @internal */ private _prevNode: RouteNode | null = null;
/** @internal */ private _node: RouteNode | null = null;
public get node(): RouteNode {
const node = this._node;
if (node === null) {
throw new Error(`Invariant violation: RouteNode should be set immediately after the RouteContext is created. Context: ${this}`);
}
if (node === null) throw new Error(getMessage(Events.rcNoNode, this));
return node;
}
/** @internal */
public set node(value: RouteNode) {
const prev = this.prevNode = this._node;
const prev = this._prevNode = this._node;
if (prev !== value) {
this._node = value;
this.logger.trace(`Node changed from %s to %s`, this.prevNode, value);
if (__DEV__) trace(this._logger, Events.rcNodeChanged, this._prevNode, value);
}

@@ -164,5 +160,3 @@ }

const vpa = this._vpa;
if (vpa === null) {
throw new Error(`RouteContext has no ViewportAgent: ${this}`);
}
if (vpa === null) throw new Error(getMessage(Events.rcNoVpa, this));
return vpa;

@@ -172,8 +166,7 @@ }

private readonly moduleLoader: IModuleLoader;
private readonly logger: ILogger;
private readonly hostControllerProvider: InstanceProvider<ICustomElementController>;
/** @internal */
public readonly _recognizer: RouteRecognizer<RouteConfig | Promise<RouteConfig>>;
private _childRoutesConfigured: boolean = false;
/** @internal */ private readonly _moduleLoader: IModuleLoader;
/** @internal */ private readonly _logger: ILogger;
/** @internal */ private readonly _hostControllerProvider: InstanceProvider<ICustomElementController>;
/** @internal */ public readonly _recognizer: RouteRecognizer<RouteConfig | Promise<RouteConfig>>;
/** @internal */ private _childRoutesConfigured: boolean = false;

@@ -197,12 +190,12 @@ private readonly _navigationModel: NavigationModel | null;

this.path = [this];
this.friendlyPath = component.name;
this._friendlyPath = component.name;
} else {
this.root = parent.root;
this.path = [...parent.path, this];
this.friendlyPath = `${parent.friendlyPath}/${component.name}`;
this._friendlyPath = `${parent._friendlyPath}/${component.name}`;
}
this.logger = parentContainer.get(ILogger).scopeTo(`RouteContext<${this.friendlyPath}>`);
this.logger.trace('constructor()');
this._logger = parentContainer.get(ILogger).scopeTo(`RouteContext<${this._friendlyPath}>`);
if (__DEV__) trace(this._logger, Events.rcCreated);
this.moduleLoader = parentContainer.get(IModuleLoader);
this._moduleLoader = parentContainer.get(IModuleLoader);

@@ -213,3 +206,3 @@ const container = this.container = parentContainer.createChild();

IController,
this.hostControllerProvider = new InstanceProvider(),
this._hostControllerProvider = new InstanceProvider(),
true,

@@ -233,3 +226,3 @@ );

.get(IRouterEvents)
.subscribe('au:router:navigation-end', () => navModel.setIsActive(_router, this));
.subscribe('au:router:navigation-end', () => navModel._setIsActive(_router, this));
} else {

@@ -241,4 +234,4 @@ this._navigationModel = null;

/** @internal */
private _processConfig(config: RouteConfig): void {
const promises: Promise<void>[] = [];
const allPromises: Promise<void>[] = [];

@@ -258,39 +251,32 @@ const childrenRoutes = config.routes ?? noRoutes;

if (childRoute instanceof Promise) {
const p = this.addRoute(childRoute);
promises.push(p);
allPromises.push(p);
} else {
const rdResolution = resolveRouteConfiguration(childRoute, true, config, null, this);
if (rdResolution instanceof Promise) {
if (!isPartialChildRouteConfig(childRoute) || childRoute.path == null) throw new Error(`Invalid route config. When the component property is a lazy import, the path must be specified.`);
for (const path of ensureArrayOfStrings(childRoute.path)) {
this.$addRoute(path, childRoute.caseSensitive ?? false, rdResolution);
}
const idx = this.childRoutes.length;
const p = rdResolution.then((rdConfig) => {
return this.childRoutes[idx] = rdConfig;
});
this.childRoutes.push(p);
if (hasNavModel) {
navModel.addRoute(p);
}
allPromises.push(p.then(noop));
} else {
for (const path of rdResolution.path ?? emptyArray) {
this.$addRoute(path, rdResolution.caseSensitive, rdResolution);
}
this.childRoutes.push(rdResolution);
if (hasNavModel) {
navModel.addRoute(rdResolution);
}
allPromises.push(this._addRoute(childRoute));
continue;
}
const rdResolution = resolveRouteConfiguration(childRoute, true, config, null, this);
if (rdResolution instanceof Promise) {
if (!isPartialChildRouteConfig(childRoute) || childRoute.path == null) throw new Error(getMessage(Events.rcNoPathLazyImport));
for (const path of ensureArrayOfStrings(childRoute.path)) {
this._$addRoute(path, childRoute.caseSensitive ?? false, rdResolution);
}
const idx = this.childRoutes.length;
const p = rdResolution.then((rdConfig) => {
return this.childRoutes[idx] = rdConfig;
});
this.childRoutes.push(p);
if (hasNavModel) {
navModel._addRoute(p);
}
allPromises.push(p.then(noop));
continue;
}
for (const path of rdResolution.path ?? emptyArray) {
this._$addRoute(path, rdResolution.caseSensitive, rdResolution);
}
this.childRoutes.push(rdResolution);
if (hasNavModel) {
navModel._addRoute(rdResolution);
}
}
this._childRoutesConfigured = true;
if (promises.length > 0) {
this._resolved = Promise.all(promises).then(() => {
this._resolved = null;
});
}
if (allPromises.length > 0) {

@@ -314,7 +300,7 @@ this._allResolved = Promise.all(allPromises).then(() => {

if (!container.has(IAppRoot, true)) {
logAndThrow(new Error(`The provided container has no registered IAppRoot. RouteContext.setRoot can only be used after Aurelia.app was called, on a container that is within that app's component tree.`), logger);
logAndThrow(new Error(getMessage(Events.rcNoAppRoot)), logger);
}
if (container.has(IRouteContext, true)) {
logAndThrow(new Error(`A root RouteContext is already registered. A possible cause is the RouterConfiguration being registered more than once in the same container tree. If you have a multi-rooted app, make sure you register RouterConfiguration only in the "forked" containers and not in the common root.`), logger);
logAndThrow(new Error(getMessage(Events.rcHasRootContext)), logger);
}

@@ -324,3 +310,3 @@

if (controller === void 0) {
logAndThrow(new Error(`The provided IAppRoot does not (yet) have a controller. A possible cause is calling this API manually before Aurelia.start() is called`), logger);
logAndThrow(new Error(getMessage(Events.rcNoRootCtrl)), logger);
}

@@ -350,9 +336,9 @@

if (context === null || context === void 0) {
logger.trace(`resolve(context:%s) - returning root RouteContext`, context);
if (context == null) {
if (__DEV__) trace(logger, Events.rcResolveNullishContext, context);
return root;
}
if (isRouteContext(context)) {
logger.trace(`resolve(context:%s) - returning provided RouteContext`, context);
if (context instanceof RouteContext) {
if (__DEV__) trace(logger, Events.rcResolveInstance, context);
return context;

@@ -362,2 +348,3 @@ }

if (context instanceof rootContainer.get(IPlatform).Node) {
if (__DEV__) trace(logger, Events.rcResolveNode, context.nodeName);
try {

@@ -370,6 +357,5 @@ // CustomElement.for can theoretically throw in (as of yet) unknown situations.

const controller = CustomElement.for(context, { searchParents: true });
logger.trace(`resolve(context:Node(nodeName:'${context.nodeName}'),controller:'${controller.definition.name}') - resolving RouteContext from controller's RenderContext`);
return controller.container.get(IRouteContext);
} catch (err) {
logger.error(`Failed to resolve RouteContext from Node(nodeName:'${context.nodeName}')`, err);
error(logger, Events.rcResolveNodeFailed, context.nodeName, err);
throw err;

@@ -381,3 +367,3 @@ }

const controller = context.$controller!;
logger.trace(`resolve(context:CustomElementViewModel(name:'${controller.definition.name}')) - resolving RouteContext from controller's RenderContext`);
if (__DEV__) trace(logger, Events.rcResolveCe, controller.definition.name);
return controller.container.get(IRouteContext);

@@ -388,7 +374,7 @@ }

const controller = context;
logger.trace(`resolve(context:CustomElementController(name:'${controller.definition.name}')) - resolving RouteContext from controller's RenderContext`);
if (__DEV__) trace(logger, Events.rcResolveCtrl, controller.definition.name);
return controller.container.get(IRouteContext);
}
logAndThrow(new Error(`Invalid context type: ${Object.prototype.toString.call(context)}`), logger);
logAndThrow(new Error(getMessage(Events.rcResolveInvalidCtxType, Object.prototype.toString.call(context))), logger);
}

@@ -400,10 +386,9 @@

public resolveViewportAgent(req: ViewportRequest): ViewportAgent {
this.logger.trace(`resolveViewportAgent(req:%s)`, req);
/** @internal */
public _resolveViewportAgent(req: ViewportRequest): ViewportAgent {
if (__DEV__) trace(this._logger, Events.rcResolveVpa, req);
const agent = this.childViewportAgents.find(x => { return x._handles(req); });
const agent = this._childViewportAgents.find(x => { return x._handles(req); });
if (agent === void 0) {
throw new Error(`Failed to resolve ${req} at:\n${this.printTree()}`);
}
if (agent === void 0) throw new Error(getMessage(Events.rcNoAvailableVpa, req, this._printTree()));

@@ -414,7 +399,7 @@ return agent;

public getAvailableViewportAgents(): readonly ViewportAgent[] {
return this.childViewportAgents.filter(x => x._isAvailable());
return this._childViewportAgents.filter(x => x._isAvailable());
}
public getFallbackViewportAgent(name: string): ViewportAgent | null {
return this.childViewportAgents.find(x => x._isAvailable() && x.viewport.name === name && x.viewport.fallback !== '') ?? null;
return this._childViewportAgents.find(x => x._isAvailable() && x.viewport.name === name && x.viewport.fallback !== '') ?? null;
}

@@ -427,7 +412,9 @@

* @param routeNode - The routeNode that describes the component + state.
*
* @internal
*/
public createComponentAgent(hostController: ICustomElementController, routeNode: RouteNode): ComponentAgent | Promise<ComponentAgent> {
this.logger.trace(`createComponentAgent(routeNode:%s)`, routeNode);
public _createComponentAgent(hostController: ICustomElementController, routeNode: RouteNode): ComponentAgent | Promise<ComponentAgent> {
if (__DEV__) trace(this._logger, Events.rcCreateCa, routeNode);
this.hostControllerProvider.prepare(hostController);
this._hostControllerProvider.prepare(hostController);
const container = this.container;

@@ -446,3 +433,3 @@ const componentInstance = container.get<IRouteViewModel>(routeNode.component.key);

this.hostControllerProvider.dispose();
this._hostControllerProvider.dispose();

@@ -453,26 +440,28 @@ return componentAgent;

public registerViewport(viewport: IViewport): ViewportAgent {
/** @internal */
public _registerViewport(viewport: IViewport): ViewportAgent {
const agent = ViewportAgent.for(viewport, this);
if (this.childViewportAgents.includes(agent)) {
this.logger.trace(`registerViewport(agent:%s) -> already registered, so skipping`, agent);
} else {
this.logger.trace(`registerViewport(agent:%s) -> adding`, agent);
this.childViewportAgents.push(agent);
if (this._childViewportAgents.includes(agent)) {
if (__DEV__) trace(this._logger, Events.rcRegisterVpSkip, agent);
return agent;
}
if (__DEV__) trace(this._logger, Events.rcRegisterVp, agent);
this._childViewportAgents.push(agent);
return agent;
}
public unregisterViewport(viewport: IViewport): void {
/** @internal */
public _unregisterViewport(viewport: IViewport): void {
const agent = ViewportAgent.for(viewport, this);
if (this.childViewportAgents.includes(agent)) {
this.logger.trace(`unregisterViewport(agent:%s) -> unregistering`, agent);
this.childViewportAgents.splice(this.childViewportAgents.indexOf(agent), 1);
} else {
this.logger.trace(`unregisterViewport(agent:%s) -> not registered, so skipping`, agent);
if (!this._childViewportAgents.includes(agent)) {
if (__DEV__) trace(this._logger, Events.rcUnregisterVpSkip, agent);
return;
}
if (__DEV__) trace(this._logger, Events.rcUnregisterVp, agent);
this._childViewportAgents.splice(this._childViewportAgents.indexOf(agent), 1);
}
public recognize(path: string, searchAncestor: boolean = false): $RecognizedRoute | null {
this.logger.trace(`recognize(path:'${path}')`);
if (__DEV__) trace(this._logger, Events.rcRecognizePath, path);
// eslint-disable-next-line @typescript-eslint/no-this-alias

@@ -500,6 +489,7 @@ let _current: IRouteContext = this;

private addRoute(routeable: Promise<IModule>): Promise<void>;
private addRoute(routeable: Exclude<Routeable, Promise<IModule>>): void | Promise<void>;
private addRoute(routeable: Routeable): void | Promise<void> {
this.logger.trace(`addRoute(routeable:'${routeable}')`);
/** @internal */
private _addRoute(routeable: Promise<IModule>): Promise<void>;
private _addRoute(routeable: Exclude<Routeable, Promise<IModule>>): void | Promise<void>;
private _addRoute(routeable: Routeable): void | Promise<void> {
if(__DEV__) trace(this._logger, Events.rcAddRoute, routeable);
return onResolve(

@@ -509,5 +499,5 @@ resolveRouteConfiguration(routeable, true, this.config, null, this),

for (const path of rdConfig.path ?? emptyArray) {
this.$addRoute(path, rdConfig.caseSensitive, rdConfig);
this._$addRoute(path, rdConfig.caseSensitive, rdConfig);
}
this._navigationModel?.addRoute(rdConfig);
this._navigationModel?._addRoute(rdConfig);
this.childRoutes.push(rdConfig);

@@ -517,3 +507,4 @@ });

private $addRoute(path: string, caseSensitive: boolean, handler: RouteConfig | Promise<RouteConfig>): void {
/** @internal */
private _$addRoute(path: string, caseSensitive: boolean, handler: RouteConfig | Promise<RouteConfig>): void {
this._recognizer.add({

@@ -526,4 +517,5 @@ path,

public resolveLazy(promise: Promise<IModule>): Promise<CustomElementDefinition> | CustomElementDefinition {
return this.moduleLoader.load(promise, m => {
/** @internal */
public _resolveLazy(promise: Promise<IModule>): Promise<CustomElementDefinition> | CustomElementDefinition {
return this._moduleLoader.load(promise, m => {
// when we have import('./some-path').then(x => x.somethingSpecific)

@@ -551,10 +543,5 @@ const raw = m.raw;

if (defaultExport === void 0) {
if (firstNonDefaultExport === void 0) {
// TODO: make error more accurate and add potential causes/solutions
throw new Error(`${promise} does not appear to be a component or CustomElement recognizable by Aurelia`);
}
return firstNonDefaultExport;
}
return defaultExport;
if (defaultExport === void 0 && firstNonDefaultExport === void 0) throw new Error(getMessage(Events.rcInvalidLazyImport, promise));
return firstNonDefaultExport ?? defaultExport!;
});

@@ -564,6 +551,6 @@ }

/** @internal */
public generateViewportInstruction(instruction: { component: RouteConfig; params: Params }): PathGenerationResult;
public generateViewportInstruction(instruction: { component: string; params: Params }): PathGenerationResult | null;
public generateViewportInstruction(instruction: NavigationInstruction | EagerInstruction): PathGenerationResult | null;
public generateViewportInstruction(instruction: NavigationInstruction | EagerInstruction): PathGenerationResult | null {
public _generateViewportInstruction(instruction: { component: RouteConfig; params: Params }): PathGenerationResult;
public _generateViewportInstruction(instruction: { component: string; params: Params }): PathGenerationResult | null;
public _generateViewportInstruction(instruction: NavigationInstruction | EagerInstruction | IExtendedViewportInstruction): PathGenerationResult | null;
public _generateViewportInstruction(instruction: NavigationInstruction | EagerInstruction | IExtendedViewportInstruction): PathGenerationResult | null {
if (!isEagerInstruction(instruction)) return null;

@@ -605,5 +592,4 @@ const component = instruction.component;

if (result === null) {
const message = `Unable to eagerly generate path for ${instruction}. Reasons: ${errors}.`;
if (throwError) throw new Error(message);
this.logger.debug(message);
if (throwError) throw new Error(getMessage(Events.rcEagerPathGenerationFailed, instruction, errors));
if(__DEV__) debug(this._logger, Events.rcEagerPathGenerationFailed, instruction, errors);
return null;

@@ -617,4 +603,4 @@ }

viewport: (instruction as IViewportInstruction).viewport,
open: (instruction as IViewportInstruction).open,
close: (instruction as IViewportInstruction).close,
open: (instruction as IExtendedViewportInstruction).open,
close: (instruction as IExtendedViewportInstruction).close,
}),

@@ -638,5 +624,4 @@ query: result.query,

if (result === null) {
const message = `Unable to eagerly generate path for ${instruction}. Reasons: ${errors}.`;
if (throwError) throw new Error(message);
this.logger.debug(message);
if (throwError) throw new Error(getMessage(Events.rcEagerPathGenerationFailed, instruction, errors));
if(__DEV__) debug(this._logger, Events.rcEagerPathGenerationFailed, instruction, errors);
return null;

@@ -650,4 +635,4 @@ }

viewport: (instruction as IViewportInstruction).viewport,
open: (instruction as IViewportInstruction).open,
close: (instruction as IViewportInstruction).close,
open: (instruction as IExtendedViewportInstruction).open,
close: (instruction as IExtendedViewportInstruction).close,
}),

@@ -698,9 +683,11 @@ query: result.query,

// Should not be adjust for DEV as it is also used of logging in production build.
public toString(): string {
const vpAgents = this.childViewportAgents;
const vpAgents = this._childViewportAgents;
const viewports = vpAgents.map(String).join(',');
return `RC(path:'${this.friendlyPath}',viewports:[${viewports}])`;
return `RC(path:'${this._friendlyPath}',viewports:[${viewports}])`;
}
private printTree(): string {
/** @internal */
private _printTree(): string {
const tree: string[] = [];

@@ -714,11 +701,2 @@ for (let i = 0; i < this.path.length; ++i) {

function isRouteContext(value: unknown): value is IRouteContext {
return value instanceof RouteContext;
}
function logAndThrow(err: Error, logger: ILogger): never {
logger.error(err);
throw err;
}
function isCustomElementDefinition(value: ResourceDefinition): value is CustomElementDefinition {

@@ -735,2 +713,3 @@ return CustomElement.isType(value.Type);

public toString(): string {
if(!__DEV__) return 'RR';
const route = this.route;

@@ -764,6 +743,6 @@ const cr = route.endpoint.route;

/** @internal */
public setIsActive(router: IRouter, context: IRouteContext): void {
public _setIsActive(router: IRouter, context: IRouteContext): void {
void onResolve(this._promise, () => {
for (const route of this.routes) {
route.setIsActive(router, context);
route._setIsActive(router, context);
}

@@ -774,7 +753,7 @@ });

/** @internal */
public addRoute(route: RouteConfig | Promise<RouteConfig>): void {
public _addRoute(route: RouteConfig | Promise<RouteConfig>): void {
const routes = this.routes;
if (!(route instanceof Promise)) {
if (route.nav ?? false) {
routes.push(NavigationRoute.create(route));
routes.push(NavigationRoute._create(route));
}

@@ -789,3 +768,3 @@ return;

if (rdConfig.nav) {
routes[index] = NavigationRoute.create(rdConfig);
routes[index] = NavigationRoute._create(rdConfig);
} else {

@@ -822,3 +801,3 @@ routes.splice(index, 1);

/** @internal */
public static create(rdConfig: RouteConfig) {
public static _create(rdConfig: RouteConfig) {
return new NavigationRoute(

@@ -838,3 +817,3 @@ rdConfig.id,

/** @internal */
public setIsActive(router: IRouter, context: IRouteContext): void {
public _setIsActive(router: IRouter, context: IRouteContext): void {
let trees = this._trees;

@@ -845,3 +824,3 @@ if (trees === null) {

const ep = context._recognizer.getEndpoint(p);
if (ep === null) throw new Error(`No endpoint found for path '${p}'`);
if (ep === null) throw new Error(getMessage(Events.nmNoEndpoint, p));
return new ViewportInstructionTree(

@@ -861,4 +840,4 @@ NavigationOptions.create(routerOptions, { context }),

}
this._isActive = trees.some(vit => router.routeTree.contains(vit, true));
this._isActive = trees.some(vit => router.routeTree.contains(vit, { matchEndpoint: true, matchOriginalInstruction: this.redirectTo !== null }));
}
}

@@ -8,2 +8,3 @@ // The commented-out terminal symbols below are for reference / potential future need (should there be use cases to loosen up the syntax)

import { Events, getMessage } from './events';
import { ViewportInstructionTree, ViewportInstruction, Params } from './instructions';

@@ -19,20 +20,21 @@ import { type NavigationOptions } from './options';

/** @internal */
class ParserState {
public get done() {
return this.rest.length === 0;
public get _done() {
return this._rest.length === 0;
}
private rest: string;
private readonly buffers: string[] = [];
private bufferIndex: number = 0;
private index: number = 0;
private _rest: string;
private readonly _buffers: string[] = [];
private _bufferIndex: number = 0;
private _index: number = 0;
public constructor(
private readonly input: string,
private readonly _input: string,
) {
this.rest = input;
this._rest = _input;
}
public startsWith(...values: readonly string[]): boolean {
const rest = this.rest;
public _startsWith(...values: readonly string[]): boolean {
const rest = this._rest;
return values.some(function (value) {

@@ -43,7 +45,7 @@ return rest.startsWith(value);

public consumeOptional(str: string): boolean {
if (this.startsWith(str)) {
this.rest = this.rest.slice(str.length);
this.index += str.length;
this.append(str);
public _consumeOptional(str: string): boolean {
if (this._startsWith(str)) {
this._rest = this._rest.slice(str.length);
this._index += str.length;
this._append(str);
return true;

@@ -54,32 +56,32 @@ }

public consume(str: string): void {
if (!this.consumeOptional(str)) {
this.expect(`'${str}'`);
public _consume(str: string): void {
if (!this._consumeOptional(str)) {
this._expect(`'${str}'`);
}
}
public expect(msg: string): void {
throw new Error(`Expected ${msg} at index ${this.index} of '${this.input}', but got: '${this.rest}' (rest='${this.rest}')`);
public _expect(msg: string): void {
throw new Error(getMessage(Events.exprUnexpectedSegment, msg, this._index, this._input, this._rest, this._rest));
}
public ensureDone(): void {
if (!this.done) {
throw new Error(`Unexpected '${this.rest}' at index ${this.index} of '${this.input}'`);
public _ensureDone(): void {
if (!this._done) {
throw new Error(getMessage(Events.exprNotDone, this._rest, this._index, this._input));
}
}
public advance(): void {
const char = this.rest[0];
this.rest = this.rest.slice(1);
++this.index;
this.append(char);
public _advance(): void {
const char = this._rest[0];
this._rest = this._rest.slice(1);
++this._index;
this._append(char);
}
public record(): void {
this.buffers[this.bufferIndex++] = '';
public _record(): void {
this._buffers[this._bufferIndex++] = '';
}
public playback(): string {
const bufferIndex = --this.bufferIndex;
const buffers = this.buffers;
public _playback(): string {
const bufferIndex = --this._bufferIndex;
const buffers = this._buffers;
const buffer = buffers[bufferIndex];

@@ -90,9 +92,9 @@ buffers[bufferIndex] = '';

public discard(): void {
this.buffers[--this.bufferIndex] = '';
public _discard(): void {
this._buffers[--this._bufferIndex] = '';
}
private append(str: string): void {
const bufferIndex = this.bufferIndex;
const buffers = this.buffers;
private _append(str: string): void {
const bufferIndex = this._bufferIndex;
const buffers = this._buffers;
for (let i = 0; i < bufferIndex; ++i) {

@@ -137,3 +139,3 @@ buffers[i] += str;

if (result === void 0) {
cache.set(path, result = RouteExpression.$parse(path, fragmentIsRoute));
cache.set(path, result = RouteExpression._$parse(path, fragmentIsRoute));
}

@@ -143,3 +145,4 @@ return result;

private static $parse(path: string, fragmentIsRoute: boolean): RouteExpression {
/** @internal */
private static _$parse(path: string, fragmentIsRoute: boolean): RouteExpression {
// First strip off the fragment (and if fragment should be used as route, set it as the path)

@@ -191,9 +194,9 @@ let fragment: string | null = null;

const state = new ParserState(path);
state.record();
const isAbsolute = state.consumeOptional('/');
state._record();
const isAbsolute = state._consumeOptional('/');
const root = CompositeSegmentExpression.parse(state);
state.ensureDone();
const root = CompositeSegmentExpression._parse(state);
state._ensureDone();
const raw = state.playback();
const raw = state._playback();
return new RouteExpression(raw, isAbsolute, root, queryParams !=null ? Object.freeze(queryParams) : emptyQuery, fragment, fragmentIsRoute);

@@ -206,3 +209,3 @@ }

this.isAbsolute,
this.root.toInstructions(0, 0),
this.root._toInstructions(0, 0),
mergeURLSearchParams(this.queryParams, options.queryParams, true),

@@ -249,23 +252,25 @@ this.fragment ?? options.fragment,

public static parse(state: ParserState): CompositeSegmentExpressionOrHigher {
state.record();
/** @internal */
public static _parse(state: ParserState): CompositeSegmentExpressionOrHigher {
state._record();
// If a segment starts with '+', e.g. '/+a' / '/+a@vp' / '/a/+b' / '/+a+b' etc, then its siblings
// are considered to be "append"
const append = state.consumeOptional('+');
const append = state._consumeOptional('+');
const siblings = [];
do {
siblings.push(ScopedSegmentExpression.parse(state));
} while (state.consumeOptional('+'));
siblings.push(ScopedSegmentExpression._parse(state));
} while (state._consumeOptional('+'));
if (!append && siblings.length === 1) {
state.discard();
state._discard();
return siblings[0];
}
const raw = state.playback();
const raw = state._playback();
return new CompositeSegmentExpression(raw, siblings);
}
public toInstructions(open: number, close: number): ViewportInstruction[] {
/** @internal */
public _toInstructions(open: number, close: number): ViewportInstruction[] {
switch (this.siblings.length) {

@@ -275,15 +280,15 @@ case 0:

case 1:
return this.siblings[0].toInstructions(open, close);
return this.siblings[0]._toInstructions(open, close);
case 2:
return [
...this.siblings[0].toInstructions(open, 0),
...this.siblings[1].toInstructions(0, close),
...this.siblings[0]._toInstructions(open, 0),
...this.siblings[1]._toInstructions(0, close),
];
default:
return [
...this.siblings[0].toInstructions(open, 0),
...this.siblings[0]._toInstructions(open, 0),
...this.siblings.slice(1, -1).flatMap(function (x) {
return x.toInstructions(0, 0);
return x._toInstructions(0, 0);
}),
...this.siblings[this.siblings.length - 1].toInstructions(0, close),
...this.siblings[this.siblings.length - 1]._toInstructions(0, close),
];

@@ -322,21 +327,23 @@ }

public static parse(state: ParserState): ScopedSegmentExpressionOrHigher {
state.record();
/** @internal */
public static _parse(state: ParserState): ScopedSegmentExpressionOrHigher {
state._record();
const left = SegmentGroupExpression.parse(state);
const left = SegmentGroupExpression._parse(state);
if (state.consumeOptional('/')) {
const right = ScopedSegmentExpression.parse(state);
if (state._consumeOptional('/')) {
const right = ScopedSegmentExpression._parse(state);
const raw = state.playback();
const raw = state._playback();
return new ScopedSegmentExpression(raw, left, right);
}
state.discard();
state._discard();
return left;
}
public toInstructions(open: number, close: number): ViewportInstruction[] {
const leftInstructions = this.left.toInstructions(open, 0);
const rightInstructions = this.right.toInstructions(0, close);
/** @internal */
public _toInstructions(open: number, close: number): ViewportInstruction[] {
const leftInstructions = this.left._toInstructions(open, 0);
const rightInstructions = this.right._toInstructions(0, close);
let cur = leftInstructions[leftInstructions.length - 1];

@@ -394,19 +401,21 @@ while (cur.children.length > 0) {

public static parse(state: ParserState): SegmentGroupExpressionOrHigher {
state.record();
/** @internal */
public static _parse(state: ParserState): SegmentGroupExpressionOrHigher {
state._record();
if (state.consumeOptional('(')) {
const expression = CompositeSegmentExpression.parse(state);
state.consume(')');
if (state._consumeOptional('(')) {
const expression = CompositeSegmentExpression._parse(state);
state._consume(')');
const raw = state.playback();
const raw = state._playback();
return new SegmentGroupExpression(raw, expression);
}
state.discard();
return SegmentExpression.parse(state);
state._discard();
return SegmentExpression._parse(state);
}
public toInstructions(open: number, close: number): ViewportInstruction[] {
return this.expression.toInstructions(open + 1, close + 1);
/** @internal */
public _toInstructions(open: number, close: number): ViewportInstruction[] {
return this.expression._toInstructions(open + 1, close + 1);
}

@@ -435,19 +444,21 @@

public static parse(state: ParserState): SegmentExpression {
state.record();
/** @internal */
public static _parse(state: ParserState): SegmentExpression {
state._record();
const component = ComponentExpression.parse(state);
const action = ActionExpression.parse(state);
const viewport = ViewportExpression.parse(state);
const scoped = !state.consumeOptional('!');
const component = ComponentExpression._parse(state);
const action = ActionExpression._parse(state);
const viewport = ViewportExpression._parse(state);
const scoped = !state._consumeOptional('!');
const raw = state.playback();
const raw = state._playback();
return new SegmentExpression(raw, component, action, viewport, scoped);
}
public toInstructions(open: number, close: number): ViewportInstruction[] {
/** @internal */
public _toInstructions(open: number, close: number): ViewportInstruction[] {
return [
ViewportInstruction.create({
component: this.component.name,
params: this.component.parameterList.toObject(),
params: this.component.parameterList._toObject(),
viewport: this.viewport.name,

@@ -514,14 +525,15 @@ open,

public static parse(state: ParserState): ComponentExpression {
state.record();
state.record();
if (!state.done) {
if (state.startsWith('./')) {
state.advance();
} else if (state.startsWith('../')) {
state.advance();
state.advance();
/** @internal */
public static _parse(state: ParserState): ComponentExpression {
state._record();
state._record();
if (!state._done) {
if (state._startsWith('./')) {
state._advance();
} else if (state._startsWith('../')) {
state._advance();
state._advance();
} else {
while (!state.done && !state.startsWith(...terminal)) {
state.advance();
while (!state._done && !state._startsWith(...terminal)) {
state._advance();
}

@@ -531,9 +543,9 @@ }

const name = decodeURIComponent(state.playback());
const name = decodeURIComponent(state._playback());
if (name.length === 0) {
state.expect('component name');
state._expect('component name');
}
const parameterList = ParameterListExpression.parse(state);
const parameterList = ParameterListExpression._parse(state);
const raw = state.playback();
const raw = state._playback();
return new ComponentExpression(raw, name, parameterList);

@@ -558,21 +570,22 @@ }

public static parse(state: ParserState): ActionExpression {
state.record();
/** @internal */
public static _parse(state: ParserState): ActionExpression {
state._record();
let name = '';
if (state.consumeOptional('.')) {
state.record();
while (!state.done && !state.startsWith(...terminal)) {
state.advance();
if (state._consumeOptional('.')) {
state._record();
while (!state._done && !state._startsWith(...terminal)) {
state._advance();
}
name = decodeURIComponent(state.playback());
name = decodeURIComponent(state._playback());
if (name.length === 0) {
state.expect('method name');
state._expect('method name');
}
}
const parameterList = ParameterListExpression.parse(state);
const parameterList = ParameterListExpression._parse(state);
const raw = state.playback();
const raw = state._playback();
return new ActionExpression(raw, name, parameterList);

@@ -593,22 +606,23 @@ }

public readonly raw: string,
public readonly name: string,
public readonly name: string | null,
) {}
public static parse(state: ParserState): ViewportExpression {
state.record();
let name = '';
/** @internal */
public static _parse(state: ParserState): ViewportExpression {
state._record();
let name: string | null = null;
if (state.consumeOptional('@')) {
state.record();
while (!state.done && !state.startsWith(...terminal)) {
state.advance();
if (state._consumeOptional('@')) {
state._record();
while (!state._done && !state._startsWith(...terminal)) {
state._advance();
}
name = decodeURIComponent(state.playback());
name = decodeURIComponent(state._playback());
if (name.length === 0) {
state.expect('viewport name');
state._expect('viewport name');
}
}
const raw = state.playback();
const raw = state._playback();
return new ViewportExpression(raw, name);

@@ -632,20 +646,22 @@ }

public static parse(state: ParserState): ParameterListExpression {
state.record();
/** @internal */
public static _parse(state: ParserState): ParameterListExpression {
state._record();
const expressions = [];
if (state.consumeOptional('(')) {
if (state._consumeOptional('(')) {
do {
expressions.push(ParameterExpression.parse(state, expressions.length));
if (!state.consumeOptional(',')) {
expressions.push(ParameterExpression._parse(state, expressions.length));
if (!state._consumeOptional(',')) {
break;
}
} while (!state.done && !state.startsWith(')'));
state.consume(')');
} while (!state._done && !state._startsWith(')'));
state._consume(')');
}
const raw = state.playback();
const raw = state._playback();
return new ParameterListExpression(raw, expressions);
}
public toObject(): Params {
/** @internal */
public _toObject(): Params {
const params: Params = {};

@@ -674,23 +690,24 @@ for (const expr of this.expressions) {

public static parse(state: ParserState, index: number): ParameterExpression {
state.record();
state.record();
while (!state.done && !state.startsWith(...terminal)) {
state.advance();
/** @internal */
public static _parse(state: ParserState, index: number): ParameterExpression {
state._record();
state._record();
while (!state._done && !state._startsWith(...terminal)) {
state._advance();
}
let key = decodeURIComponent(state.playback());
let key = decodeURIComponent(state._playback());
if (key.length === 0) {
state.expect('parameter key');
state._expect('parameter key');
}
let value;
if (state.consumeOptional('=')) {
state.record();
while (!state.done && !state.startsWith(...terminal)) {
state.advance();
if (state._consumeOptional('=')) {
state._record();
while (!state._done && !state._startsWith(...terminal)) {
state._advance();
}
value = decodeURIComponent(state.playback());
value = decodeURIComponent(state._playback());
if (value.length === 0) {
state.expect('parameter value');
state._expect('parameter value');
}

@@ -702,3 +719,3 @@ } else {

const raw = state.playback();
const raw = state._playback();
return new ParameterExpression(raw, key, value);

@@ -705,0 +722,0 @@ }

@@ -50,2 +50,3 @@ import {

import { resolveCustomElementDefinition, resolveRouteConfiguration, RouteConfig, RouteType } from './route';
import { Events, getMessage } from './events';

@@ -62,3 +63,3 @@ export interface IRouteNode {

data?: Record<string, unknown>;
viewport?: string | null;
_viewport?: string | null;
title?: string | ((node: RouteNode) => string | null) | null;

@@ -70,25 +71,30 @@ component: CustomElementDefinition;

let nodeId: number = 0;
export interface RouteNodeMatchOptions {
/** Endpoints will be matched instead of instruction */
matchEndpoint: boolean;
/** Original instruction will be matched */
matchOriginalInstruction: boolean;
}
export class RouteNode implements IRouteNode {
/** @internal */
public tree!: RouteTree;
/** @internal */
public version: number = 1;
/** @internal */ public _tree!: RouteTree;
/** @internal */ public _version: number = 1;
public get root(): RouteNode {
return this.tree.root;
return this._tree.root;
}
/** @internal */
private _isInstructionsFinalized: boolean = false;
public get isInstructionsFinalized(): boolean { return this._isInstructionsFinalized; }
private constructor(
/** @internal */
public id: number,
/**
* The original configured path pattern that was matched.
*/
public path: string,
public readonly path: string,
/**
* If one or more redirects have occurred, then this is the final path match, in all other cases this is identical to `path`
*/
public finalPath: string,
public readonly finalPath: string,
/**

@@ -103,9 +109,9 @@ * The `RouteContext` associated with this route.

/** @internal */
public readonly originalInstruction: ViewportInstruction<ITypedNavigationInstruction_ResolvedComponent> | null,
public readonly _originalInstruction: ViewportInstruction<ITypedNavigationInstruction_ResolvedComponent> | null,
/** Can only be `null` for the composition root */
public readonly instruction: ViewportInstruction<ITypedNavigationInstruction_ResolvedComponent> | null,
public params: Params,
public queryParams: Readonly<URLSearchParams>,
public fragment: string | null,
public data: Record<string, unknown>,
public readonly params: Readonly<Params>,
public readonly queryParams: Readonly<URLSearchParams>,
public readonly fragment: string | null,
public readonly data: Readonly<Record<string, unknown>>,
/**

@@ -117,6 +123,11 @@ * The viewport is always `null` for the root `RouteNode`.

* if we decide not to implement that.
*
* This is used simply on metadata level. Hence hiding it from the public API.
* If need be, we can expose it later.
*
* @internal
*/
public viewport: string | null,
public title: string | ((node: RouteNode) => string | null) | null,
public component: CustomElementDefinition,
public readonly _viewport: string | null,
public readonly title: string | ((node: RouteNode) => string | null) | null,
public readonly component: CustomElementDefinition,
public readonly children: RouteNode[],

@@ -133,3 +144,3 @@ /**

) {
this.originalInstruction ??= instruction;
this._originalInstruction ??= instruction;
}

@@ -141,3 +152,2 @@

return new RouteNode(
/* id */++nodeId,
/* path */input.path,

@@ -148,7 +158,7 @@ /* finalPath */input.finalPath,

/* instruction */input.instruction,
/* params */params,
/* params */Object.freeze(params),
/* queryParams */input.queryParams ?? emptyQuery,
/* fragment */input.fragment ?? null,
/* data */input.data ?? {},
/* viewport */input.viewport ?? null,
/* data */Object.freeze(input.data ?? emptyObject),
/* viewport */input._viewport ?? null,
/* title */input.title ?? null,

@@ -161,4 +171,6 @@ /* component */input.component,

public contains(instructions: ViewportInstructionTree, preferEndpointMatch: boolean): boolean {
public contains(instructions: ViewportInstructionTree, options: Partial<RouteNodeMatchOptions>): boolean {
if (this.context === instructions.options.context) {
const matchEndpoint = options.matchEndpoint ?? false;
const matchOriginalInstruction = options.matchOriginalInstruction ?? false;
const nodeChildren = this.children;

@@ -169,8 +181,12 @@ const instructionChildren = instructions.children;

const instructionChild = instructionChildren[j];
const instructionEndpoint = preferEndpointMatch ? instructionChild.recognizedRoute?.route.endpoint : null;
const nodeChild = nodeChildren[i + j];
const instructionEndpoint = matchEndpoint ? instructionChild.recognizedRoute?.route.endpoint : null;
const nodeChild = nodeChildren[i + j] ?? null;
const instruction = nodeChild !== null
? !matchOriginalInstruction && nodeChild.isInstructionsFinalized ? nodeChild.instruction : nodeChild._originalInstruction
: null;
const childEndpoint = instruction?.recognizedRoute?.route.endpoint;
if (i + j < ii
&& (
(instructionEndpoint != null && nodeChild.instruction?.recognizedRoute?.route.endpoint === instructionEndpoint)
|| (nodeChild.originalInstruction?.contains(instructionChild) ?? false)
(instructionEndpoint?.equalsOrResidual(childEndpoint) ?? false)
|| (instruction?.contains(instructionChild) ?? false)
)

@@ -189,14 +205,16 @@ ) {

return this.children.some(function (x) {
return x.contains(instructions, preferEndpointMatch);
return x.contains(instructions, options);
});
}
public appendChild(child: RouteNode): void {
/** @internal */
public _appendChild(child: RouteNode): void {
this.children.push(child);
child.setTree(this.tree);
child._setTree(this._tree);
}
public clearChildren(): void {
/** @internal */
public _clearChildren(): void {
for (const c of this.children) {
c.clearChildren();
c._clearChildren();
c.context.vpa._cancelUpdate();

@@ -210,17 +228,7 @@ }

...this.children.map(x => x.getTitle(separator)),
this.getTitlePart(),
typeof this.title === 'function' ? this.title.call(void 0, this) : this.title,
].filter(x => x !== null);
if (titleParts.length === 0) {
return null;
}
return titleParts.join(separator);
return titleParts.length === 0 ? null : titleParts.join(separator);
}
public getTitlePart(): string | null {
if (typeof this.title === 'function') {
return this.title.call(void 0, this);
}
return this.title;
}
public computeAbsolutePath(): string {

@@ -232,16 +240,14 @@ if (this.context.isRoot) {

const thisPath = this.instruction!.toUrlComponent(false);
if (parentPath.length > 0) {
if (thisPath.length > 0) {
return [parentPath, thisPath].join('/');
}
return parentPath;
}
return thisPath;
return parentPath.length > 0
? thisPath.length > 0
? `${parentPath}/${thisPath}`
: parentPath
: thisPath;
}
/** @internal */
public setTree(tree: RouteTree): void {
this.tree = tree;
public _setTree(tree: RouteTree): void {
this._tree = tree;
for (const child of this.children) {
child.setTree(tree);
child._setTree(tree);
}

@@ -251,5 +257,6 @@ }

/** @internal */
public finalizeInstruction(): ViewportInstruction {
const children = this.children.map(x => x.finalizeInstruction());
const instruction = this.instruction!.clone();
public _finalizeInstruction(): ViewportInstruction {
this._isInstructionsFinalized = true;
const children = this.children.map(x => x._finalizeInstruction());
const instruction = this.instruction!._clone();
instruction.children.splice(0, instruction.children.length, ...children);

@@ -260,9 +267,8 @@ return (this as Writable<this>).instruction = instruction;

/** @internal */
public clone(): RouteNode {
public _clone(): RouteNode {
const clone = new RouteNode(
this.id,
this.path,
this.finalPath,
this.context,
this.originalInstruction,
this._originalInstruction,
this.instruction,

@@ -273,9 +279,9 @@ { ...this.params },

{ ...this.data },
this.viewport,
this._viewport,
this.title,
this.component,
this.children.map(x => x.clone()),
this.children.map(x => x._clone()),
[...this.residue],
);
clone.version = this.version + 1;
clone._version = this._version + 1;
if (clone.context.node === this) {

@@ -287,2 +293,3 @@ clone.context.node = clone;

// Should not be adjust for DEV as it is also used of logging in production build.
public toString(): string {

@@ -314,3 +321,3 @@ const props: string[] = [];

return `RN(ctx:'${this.context?.friendlyPath}',${props.join(',')})`;
return `RN(ctx:'${this.context?._friendlyPath}',${props.join(',')})`;
}

@@ -327,22 +334,24 @@ }

public contains(instructions: ViewportInstructionTree, preferEndpointMatch: boolean): boolean {
return this.root.contains(instructions, preferEndpointMatch);
public contains(instructions: ViewportInstructionTree, options: Partial<RouteNodeMatchOptions>): boolean {
return this.root.contains(instructions, options);
}
public clone(): RouteTree {
/** @internal */
public _clone(): RouteTree {
const clone = new RouteTree(
this.options.clone(),
this.options._clone(),
new URLSearchParams(this.queryParams),
this.fragment,
this.root.clone(),
this.root._clone(),
);
clone.root.setTree(this);
clone.root._setTree(this);
return clone;
}
public finalizeInstructions(): ViewportInstructionTree {
/** @internal */
public _finalizeInstructions(): ViewportInstructionTree {
return new ViewportInstructionTree(
this.options,
true,
this.root.children.map(x => x.finalizeInstruction()),
this.root.children.map(x => x._finalizeInstruction()),
this.queryParams,

@@ -371,3 +380,3 @@ this.fragment,

node = node.context.parent?.node ?? node;
node.clearChildren();
node._clearChildren();
// falls through

@@ -381,3 +390,3 @@ case '.':

const ctx = node.context;
const originalInstruction = (vi as ViewportInstruction<ITypedNavigationInstruction_string>).clone();
const originalInstruction = (vi as ViewportInstruction<ITypedNavigationInstruction_string>)._clone();
let rr = vi.recognizedRoute;

@@ -391,5 +400,5 @@ // early return; we already have a recognized route, don't bother with the rest.

if (vi.children.length === 0) {
const result = ctx.generateViewportInstruction(vi);
const result = ctx._generateViewportInstruction(vi);
if (result !== null) {
(node.tree as Writable<RouteTree>).queryParams = mergeURLSearchParams(node.tree.queryParams, result.query, true);
(node._tree as Writable<RouteTree>).queryParams = mergeURLSearchParams(node._tree.queryParams, result.query, true);
const newVi = result.vi;

@@ -433,3 +442,3 @@ (newVi.children as NavigationInstruction[]).push(...vi.children);

// check if a route-id is used
const eagerResult = ctx.generateViewportInstruction({
const eagerResult = ctx._generateViewportInstruction({
component: vi.component.value,

@@ -443,3 +452,3 @@ params: vi.params ?? emptyObject,

if (eagerResult !== null) {
(node.tree as Writable<RouteTree>).queryParams = mergeURLSearchParams(node.tree.queryParams, eagerResult.query, true);
(node._tree as Writable<RouteTree>).queryParams = mergeURLSearchParams(node._tree.queryParams, eagerResult.query, true);
return appendNode(log, node, createConfiguredNode(

@@ -462,3 +471,3 @@ log,

: ctx.config._getFallback(vi, node, ctx);
if (fallback === null) throw new UnknownRouteError(`Neither the route '${name}' matched any configured route at '${ctx.friendlyPath}' nor a fallback is configured for the viewport '${vp}' - did you forget to add '${name}' to the routes list of the route decorator of '${ctx.component.name}'?`);
if (fallback === null) throw new UnknownRouteError(getMessage(Events.instrNoFallback, name, ctx._friendlyPath, vp, name, ctx.component.name));

@@ -491,8 +500,15 @@ if (typeof fallback === 'string') {

let addResidue = !noResidue;
for (let i = 0; i < collapse; ++i) {
const child = vi.children[0];
if (residue?.startsWith(child.component.value as string) ?? false) break;
if (residue?.startsWith(child.component.value as string) ?? false) {
addResidue = false;
break;
}
(vi as Writable<ViewportInstruction>).viewport = child.viewport;
(vi as Writable<ViewportInstruction>).children = child.children;
}
if (addResidue) {
vi.children.unshift(ViewportInstruction.create(residue!));
}
(vi as Writable<ViewportInstruction>).recognizedRoute = rr;

@@ -510,3 +526,3 @@ log.trace('createNode after adjustment vi:%s', vi);

ced => {
const { vi: newVi, query } = rc.generateViewportInstruction({
const { vi: newVi, query } = rc._generateViewportInstruction({
component: ced,

@@ -519,3 +535,3 @@ params: vi.params ?? emptyObject,

})!;
(node.tree as Writable<RouteTree>).queryParams = mergeURLSearchParams(node.tree.queryParams, query, true);
(node._tree as Writable<RouteTree>).queryParams = mergeURLSearchParams(node._tree.queryParams, query, true);
return appendNode(log, node, createConfiguredNode(

@@ -541,3 +557,3 @@ log,

const ctx = node.context;
const rt = node.tree;
const rt = node._tree;
return onResolve(route.handler, $handler => {

@@ -549,3 +565,4 @@ route.handler = $handler;

if ($handler.redirectTo === null) {
const vpName: string = ((vi.viewport?.length ?? 0) > 0 ? vi.viewport : $handler.viewport)!;
const viWithVp = (vi.viewport?.length ?? 0) > 0;
const vpName: string = (viWithVp ? vi.viewport : $handler.viewport)!;
return onResolve(

@@ -555,3 +572,3 @@ resolveCustomElementDefinition($handler.component, ctx)[1],

const vpa = ctx.resolveViewportAgent(new ViewportRequest(
const vpa = ctx._resolveViewportAgent(new ViewportRequest(
vpName,

@@ -561,2 +578,5 @@ ced.name,

if(!viWithVp) {
(vi as Writable<ViewportInstruction>).viewport = vpa.viewport.name;
}
const router = ctx.container.get(IRouter);

@@ -580,12 +600,9 @@ return onResolve(

data: $handler.data,
viewport: vpName,
_viewport: vpName,
component: ced,
title: $handler.title,
residue: [
// TODO(sayan): this can be removed; need to inspect more.
...(rr.residue === null ? [] : [ViewportInstruction.create(rr.residue)]),
...vi.children,
],
// Note: at this point, the residue from the recognized route should be converted to VI children. Hence the residues are not added back to the RouteNode.
residue: vi.children.slice(),
});
$node.setTree(node.tree);
$node._setTree(node._tree);

@@ -613,3 +630,3 @@ log.trace(`createConfiguredNode(vi:%s) -> %s`, vi, $node);

default:
throw new Error(`Unexpected expression kind ${origPath.root.kind}`);
throw new Error(getMessage(Events.exprUnexpectedKind, origPath.root.kind));
}

@@ -622,3 +639,3 @@ switch (redirPath.root.kind) {

default:
throw new Error(`Unexpected expression kind ${redirPath.root.kind}`);
throw new Error(getMessage(Events.exprUnexpectedKind, redirPath.root.kind));
}

@@ -644,6 +661,6 @@

default:
throw new Error(`Unexpected expression kind ${origCur.right.kind}`);
throw new Error(getMessage(Events.exprUnexpectedKind, origCur.right.kind));
}
} else {
throw new Error(`Unexpected expression kind ${origCur.left.kind}`);
throw new Error(getMessage(Events.exprUnexpectedKind, origCur.left.kind));
}

@@ -663,6 +680,6 @@ if (redirDone) {

default:
throw new Error(`Unexpected expression kind ${redirCur.right.kind}`);
throw new Error(getMessage(Events.exprUnexpectedKind, redirCur.right.kind));
}
} else {
throw new Error(`Unexpected expression kind ${redirCur.left.kind}`);
throw new Error(getMessage(Events.exprUnexpectedKind, redirCur.left.kind));
}

@@ -682,3 +699,3 @@

const redirRR = ctx.recognize(newPath);
if (redirRR === null) throw new UnknownRouteError(`'${newPath}' did not match any configured route or registered component name at '${ctx.friendlyPath}' - did you forget to add '${newPath}' to the routes list of the route decorator of '${ctx.component.name}'?`);
if (redirRR === null) throw new UnknownRouteError(getMessage(Events.instrUnknownRedirect, newPath, ctx._friendlyPath, newPath, ctx.component.name));

@@ -709,4 +726,4 @@ return createConfiguredNode(

log.trace(`appendNode($childNode:%s)`, $childNode);
node.appendChild($childNode);
return $childNode.context.vpa._scheduleUpdate(node.tree.options, $childNode);
node._appendChild($childNode);
return $childNode.context.vpa._scheduleUpdate(node._tree.options, $childNode);
});

@@ -713,0 +730,0 @@ }

@@ -12,2 +12,3 @@ import { Metadata } from '@aurelia/metadata';

import type { FallbackFunction, IChildRouteConfig, IRedirectRouteConfig, IRouteConfig, Routeable, TransitionPlan, TransitionPlanOrFunc } from './options';
import { Events, getMessage } from './events';

@@ -126,3 +127,3 @@ export const noRoutes = emptyArray as RouteConfig['routes'];

*/
public applyChildRouteConfig(config: IChildRouteConfig, parentConfig: RouteConfig | null): RouteConfig {
public _applyChildRouteConfig(config: IChildRouteConfig, parentConfig: RouteConfig | null): RouteConfig {
validateRouteConfig(config, this.path[0] ?? '');

@@ -146,3 +147,4 @@ const path = ensureArrayOfStrings(config.path ?? this.path);

public getTransitionPlan(cur: RouteNode, next: RouteNode) {
/** @internal */
public _getTransitionPlan(cur: RouteNode, next: RouteNode) {
const plan = this.transitionPlan ?? defaultReentryBehavior;

@@ -155,3 +157,3 @@ return typeof plan === 'function' ? plan(cur, next) : plan;

// start strict
if (this._configurationFromHookApplied) throw new Error('Invalid operation, the configuration from the get hook is already applied.');
if (this._configurationFromHookApplied) throw new Error(getMessage(Events.rtConfigFromHookApplied));
if (typeof instance.getRouteConfig !== 'function') return;

@@ -250,3 +252,3 @@ return onResolve(

// However there might still be static properties, and this API provides a unified way of accessing those.
Route.configure({}, Type/* , false */);
Route.configure({}, Type);
}

@@ -272,4 +274,2 @@

*
* (TODO: improve the formatting, better examples, etc)
*
* ```

@@ -288,3 +288,3 @@ * &#64;route('home')

return function (target) {
return Route.configure(configOrPath, target/* , true */);
return Route.configure(configOrPath, target);
};

@@ -304,3 +304,3 @@ }

// If the component is used as a child, then apply the child configuration (comping from parent) and return a new RouteConfig with the configuration applied.
if (isPartialChildRouteConfig(routeable)) return routeConfig.applyChildRouteConfig(routeable, parent);
if (isPartialChildRouteConfig(routeable)) return routeConfig._applyChildRouteConfig(routeable, parent);

@@ -328,6 +328,6 @@ // If the component is used as a child, then return a clone.

case NavigationInstructionType.string: {
if (context == null) throw new Error(`When retrieving the RouteConfig for a component name, a RouteContext (that can resolve it) must be provided`);
if (context == null) throw new Error(getMessage(Events.rtNoCtxStrComponent));
const component = context.container.find(CustomElement, instruction.value);
if (component === null) throw new Error(`Could not find a CustomElement named '${instruction.value}' in the current container scope of ${context}. This means the component is neither registered at Aurelia startup nor via the 'dependencies' decorator or static property.`);
if (component === null) throw new Error(getMessage(Events.rtNoComponent, instruction.value, context));

@@ -345,5 +345,4 @@ ceDef = component;

case NavigationInstructionType.Promise:
if (context == null)
throw new Error(`RouteContext must be provided when resolving an imported module`);
ceDef = context.resolveLazy(instruction.value);
if (context == null) throw new Error(getMessage(Events.rtNoCtxLazyImport));
ceDef = context._resolveLazy(instruction.value);
break;

@@ -350,0 +349,0 @@ }

@@ -1,4 +0,5 @@

import { DI, IEventAggregator, IDisposable, ILogger } from '@aurelia/kernel';
import { DI, IEventAggregator, IDisposable, ILogger, resolve } from '@aurelia/kernel';
import type { ViewportInstructionTree } from './instructions';
import { Events, trace } from './events';

@@ -15,6 +16,6 @@ export type RoutingTrigger = 'popstate' | 'hashchange' | 'api';

class Subscription implements IDisposable {
private disposed: boolean = false;
/** @internal */ private _disposed: boolean = false;
public constructor(
private readonly events: IRouterEvents,
/** @internal */ private readonly _events: IRouterEvents,
/**

@@ -25,12 +26,12 @@ * A unique serial number that makes individual subscribers more easily distinguishable in chronological order.

*/
public readonly serial: number,
private readonly inner: IDisposable,
/** @internal */ public readonly _serial: number,
/** @internal */ private readonly _inner: IDisposable,
) {}
public dispose(): void {
if (!this.disposed) {
this.disposed = true;
if (!this._disposed) {
this._disposed = true;
this.inner.dispose();
const subscriptions = this.events['subscriptions'];
this._inner.dispose();
const subscriptions = this._events['_subscriptions'];
subscriptions.splice(subscriptions.indexOf(this), 1);

@@ -42,18 +43,14 @@ }

export const IRouterEvents = /*@__PURE__*/DI.createInterface<IRouterEvents>('IRouterEvents', x => x.singleton(RouterEvents));
export interface IRouterEvents extends RouterEvents {}
export interface IRouterEvents extends RouterEvents { }
export class RouterEvents implements IRouterEvents {
private subscriptionSerial: number = 0;
private readonly subscriptions: Subscription[] = [];
/** @internal */ private _subscriptionSerial: number = 0;
/** @internal */ private readonly _subscriptions: Subscription[] = [];
public constructor(
@IEventAggregator private readonly ea: IEventAggregator,
@ILogger private readonly logger: ILogger,
) {
this.logger = logger.scopeTo('RouterEvents');
}
/** @internal */ private readonly _ea: IEventAggregator = resolve(IEventAggregator);
/** @internal */ private readonly _logger: ILogger = resolve(ILogger).scopeTo('RouterEvents');
public publish(event: RouterEvent): void {
this.logger.trace(`publishing %s`, event);
if(__DEV__) trace(this._logger, Events.rePublishingEvent, event);
this.ea.publish(event.name, event);
this._ea.publish(event.name, event);
}

@@ -64,5 +61,5 @@

this,
++this.subscriptionSerial,
this.ea.subscribe(event, (message: NameToEvent[T]) => {
this.logger.trace(`handling %s for subscription #${subscription.serial}`, event);
++this._subscriptionSerial,
this._ea.subscribe(event, (message: NameToEvent[T]) => {
if(__DEV__) trace(this._logger, Events.reInvokingSubscriber, subscription._serial, event);
callback(message);

@@ -72,3 +69,3 @@ })

this.subscriptions.push(subscription);
this._subscriptions.push(subscription);
return subscription;

@@ -89,3 +86,5 @@ }

public toString(): string {
return `LocationChangeEvent(id:${this.id},url:'${this.url}',trigger:'${this.trigger}')`;
return __DEV__
? `LocationChangeEvent(id:${this.id},url:'${this.url}',trigger:'${this.trigger}')`
: `LocationChangeEvent`;
}

@@ -105,3 +104,5 @@ }

public toString(): string {
return `NavigationStartEvent(id:${this.id},instructions:'${this.instructions}',trigger:'${this.trigger}')`;
return __DEV__
? `NavigationStartEvent(id:${this.id},instructions:'${this.instructions}',trigger:'${this.trigger}')`
: `NavigationStartEvent`;
}

@@ -120,3 +121,5 @@ }

public toString(): string {
return `NavigationEndEvent(id:${this.id},instructions:'${this.instructions}',finalInstructions:'${this.finalInstructions}')`;
return __DEV__
? `NavigationEndEvent(id:${this.id},instructions:'${this.instructions}',finalInstructions:'${this.finalInstructions}')`
: `NavigationEndEvent`;
}

@@ -135,3 +138,5 @@ }

public toString(): string {
return `NavigationCancelEvent(id:${this.id},instructions:'${this.instructions}',reason:${String(this.reason)})`;
return __DEV__
? `NavigationCancelEvent(id:${this.id},instructions:'${this.instructions}',reason:${String(this.reason)})`
: `NavigationCancelEvent`;
}

@@ -150,3 +155,5 @@ }

public toString(): string {
return `NavigationErrorEvent(id:${this.id},instructions:'${this.instructions}',error:${String(this.error)})`;
return __DEV__
? `NavigationErrorEvent(id:${this.id},instructions:'${this.instructions}',error:${String(this.error)})`
: `NavigationErrorEvent`;
}

@@ -153,0 +160,0 @@ }

import { isObject } from '@aurelia/metadata';
import { IContainer, ILogger, DI, IDisposable, onResolve, Writable, onResolveAll, Registration, IResolver } from '@aurelia/kernel';
import { IContainer, ILogger, DI, IDisposable, onResolve, Writable, onResolveAll, Registration, IResolver, resolve } from '@aurelia/kernel';
import { CustomElement, CustomElementDefinition, IPlatform } from '@aurelia/runtime-html';

@@ -15,2 +15,4 @@

import { INavigationOptions, NavigationOptions, type RouterOptions, IRouterOptions } from './options';
import { isPartialViewportInstruction } from './validation';
import { Events, debug, error, getMessage, trace } from './events';

@@ -53,3 +55,4 @@ /** @internal */

public static create(input: Omit<Transition, 'run' | 'handleError' | 'erredWithUnknownRoute'>): Transition {
/** @internal */
public static _create(input: Omit<Transition, '_run' | '_handleError' | 'erredWithUnknownRoute'>): Transition {
return new Transition(

@@ -74,3 +77,4 @@ input.id,

public run<T>(cb: () => T, next: (value: UnwrapPromise<T>) => void): void {
/** @internal */
public _run<T>(cb: () => T, next: (value: UnwrapPromise<T>) => void): void {
if (this.guardsResult !== true) {

@@ -83,3 +87,3 @@ return;

ret.then(next).catch(err => {
this.handleError(err);
this._handleError(err);
});

@@ -90,7 +94,8 @@ } else {

} catch (err) {
this.handleError(err);
this._handleError(err);
}
}
public handleError(err: unknown): void {
/** @internal */
public _handleError(err: unknown): void {
this._erredWithUnknownRoute = err instanceof UnknownRouteError;

@@ -100,4 +105,5 @@ this.reject!(this.error = err);

// Should not be adjust for DEV as it is also used of logging in production build.
public toString(): string {
return `T(id:${this.id},trigger:'${this.trigger}',instructions:${this.instructions},options:${this.options})`;
return `T(id:${this.id},trigger:'${this.trigger}',instructions:${this.instructions})`;
}

@@ -112,14 +118,12 @@ }

export class Router {
private _ctx: RouteContext | null = null;
private get ctx(): RouteContext {
let ctx = this._ctx;
if (ctx === null) {
if (!this.container.has(IRouteContext, true)) {
throw new Error(`Root RouteContext is not set. Did you forget to register RouteConfiguration, or try to navigate before calling Aurelia.start()?`);
}
ctx = this._ctx = this.container.get(IRouteContext);
}
return ctx;
/** @internal */ private _$ctx: RouteContext | null = null;
/** @internal */
private get _ctx(): RouteContext {
const ctx = this._$ctx;
if (ctx !== null) return ctx;
if (!this._container.has(IRouteContext, true)) throw new Error(getMessage(Events.rtrNoCtx));
return this._$ctx = this._container.get(IRouteContext);
}
/** @internal */
private _routeTree: RouteTree | null = null;

@@ -131,3 +135,3 @@ public get routeTree(): RouteTree {

// Doing it here instead of in the constructor to delay it until we have the context.
const ctx = this.ctx;
const ctx = this._ctx;
routeTree = this._routeTree = new RouteTree(

@@ -150,2 +154,3 @@ NavigationOptions.create(this.options, {}),

/** @internal */
private _currentTr: Transition | null = null;

@@ -155,7 +160,7 @@ public get currentTr(): Transition {

if (currentTr === null) {
currentTr = this._currentTr = Transition.create({
currentTr = this._currentTr = Transition._create({
id: 0,
prevInstructions: this.instructions,
instructions: this.instructions,
finalInstructions: this.instructions,
prevInstructions: this._instructions,
instructions: this._instructions,
finalInstructions: this._instructions,
instructionsChanged: true,

@@ -165,3 +170,3 @@ trigger: 'api',

managedState: null,
previousRouteTree: this.routeTree.clone(),
previousRouteTree: this.routeTree._clone(),
routeTree: this.routeTree,

@@ -177,2 +182,3 @@ resolve: null,

}
/** @internal */
private set currentTr(value: Transition) {

@@ -182,14 +188,13 @@ this._currentTr = value;

private navigated: boolean = false;
private navigationId: number = 0;
/** @internal */ private _navigated: boolean = false;
/** @internal */ private _navigationId: number = 0;
private instructions: ViewportInstructionTree;
/** @internal */ private _instructions: ViewportInstructionTree;
private nextTr: Transition | null = null;
private locationChangeSubscription: IDisposable | null = null;
/** @internal */ private _nextTr: Transition | null = null;
/** @internal */ private _locationChangeSubscription: IDisposable | null = null;
/** @internal */
public readonly _hasTitleBuilder: boolean = false;
/** @internal */ public readonly _hasTitleBuilder: boolean = false;
private _isNavigating: boolean = false;
/** @internal */ private _isNavigating: boolean = false;
public get isNavigating(): boolean {

@@ -199,13 +204,12 @@ return this._isNavigating;

public constructor(
@IContainer private readonly container: IContainer,
@IPlatform private readonly p: IPlatform,
@ILogger private readonly logger: ILogger,
@IRouterEvents private readonly events: IRouterEvents,
@ILocationManager private readonly locationMgr: ILocationManager,
@IRouterOptions public readonly options: Readonly<RouterOptions>,
) {
this.logger = logger.root.scopeTo('Router');
this.instructions = ViewportInstructionTree.create('', options);
container.registerResolver(Router, Registration.instance(Router, this) as unknown as IResolver<Router>);
/** @internal */ private readonly _container: IContainer = resolve(IContainer);
/** @internal */ private readonly _p: IPlatform = resolve(IPlatform);
/** @internal */ private readonly _logger: ILogger = /*@__PURE__*/ resolve(ILogger).root.scopeTo('Router');
/** @internal */ private readonly _events: IRouterEvents = resolve(IRouterEvents);
/** @internal */ private readonly _locationMgr: ILocationManager = resolve(ILocationManager);
public readonly options: Readonly<RouterOptions> = resolve(IRouterOptions);
public constructor() {
this._instructions = ViewportInstructionTree.create('', this.options);
this._container.registerResolver(Router, Registration.instance(Router, this) as unknown as IResolver<Router>);
}

@@ -224,5 +228,7 @@

* - `ICustomElementController`: same as `ICustomElementViewModel`, but using the controller object instead of the view model object (advanced users).
*
* @internal
*/
public resolveContext(context: RouteContextLike | null): IRouteContext {
return RouteContext.resolve(this.ctx, context);
private _resolveContext(context: RouteContextLike | null): IRouteContext {
return RouteContext.resolve(this._ctx, context);
}

@@ -233,9 +239,9 @@

this.locationMgr.startListening();
this.locationChangeSubscription = this.events.subscribe('au:router:location-change', e => {
// TODO(fkleuver): add a throttle config.
this._locationMgr.startListening();
this._locationChangeSubscription = this._events.subscribe('au:router:location-change', e => {
// At the time of writing, chromium throttles popstate events at a maximum of ~100 per second.
// While macroTasks run up to 250 times per second, it is extremely unlikely that more than ~100 per second of these will run due to the double queueing.
// However, this throttle limit could theoretically be hit by e.g. integration tests that don't mock Location/History.
this.p.taskQueue.queueTask(() => {
// If the throttle limit is hit, then add a throttle config.
this._p.taskQueue.queueTask(() => {
// Don't try to restore state that might not have anything to do with the Aurelia app

@@ -245,3 +251,3 @@ const state = isManagedState(e.state) ? e.state : null;

const options = NavigationOptions.create(routerOptions, { historyStrategy: 'replace' });
const instructions = ViewportInstructionTree.create(e.url, routerOptions, options, this.ctx);
const instructions = ViewportInstructionTree.create(e.url, routerOptions, options, this._ctx);
// The promise will be stored in the transition. However, unlike `load()`, `start()` does not return this promise in any way.

@@ -252,8 +258,8 @@ // The router merely guarantees that it will be awaited (or canceled) before the next transition, so a race condition is impossible either way.

// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.enqueue(instructions, e.trigger, state, null);
this._enqueue(instructions, e.trigger, state, null);
});
});
if (!this.navigated && performInitialNavigation) {
return this.load(this.locationMgr.getPath(), { historyStrategy: 'replace' });
if (!this._navigated && performInitialNavigation) {
return this.load(this._locationMgr.getPath(), { historyStrategy: 'replace' });
}

@@ -263,4 +269,4 @@ }

public stop(): void {
this.locationMgr.stopListening();
this.locationChangeSubscription?.dispose();
this._locationMgr.stopListening();
this._locationChangeSubscription?.dispose();
}

@@ -341,9 +347,9 @@

this.logger.trace('load(instructions:%s)', instructions);
if (__DEV__) trace(this._logger, Events.rtrLoading, instructions);
return this.enqueue(instructions, 'api', null, null);
return this._enqueue(instructions, 'api', null, null);
}
public isActive(instructionOrInstructions: NavigationInstruction | readonly NavigationInstruction[], context: RouteContextLike): boolean {
const ctx = this.resolveContext(context);
const ctx = this._resolveContext(context);
const instructions = instructionOrInstructions instanceof ViewportInstructionTree

@@ -353,9 +359,8 @@ ? instructionOrInstructions

this.logger.trace('isActive(instructions:%s,ctx:%s)', instructions, ctx);
if (__DEV__) trace(this._logger, Events.rtrIsActive, instructions, ctx);
// TODO: incorporate potential context offset by `../` etc in the instructions
return this.routeTree.contains(instructions, false);
return this.routeTree.contains(instructions, { matchEndpoint: false });
}
private readonly vpaLookup: ViewportAgentLookup = new Map();
private readonly _vpaLookup: ViewportAgentLookup = new Map();
/**

@@ -380,3 +385,3 @@ * Retrieve the RouteContext, which contains statically configured routes combined with the customElement metadata associated with a type.

): IRouteContext | Promise<IRouteContext> {
const logger = container.get(ILogger).scopeTo('RouteContext');
const logger = /*@__PURE__*/ container.get(ILogger).scopeTo('RouteContext');

@@ -395,5 +400,5 @@ // getRouteConfig is prioritized over the statically configured routes via @route decorator.

rdConfig => {
let routeConfigLookup = this.vpaLookup.get(viewportAgent);
let routeConfigLookup = this._vpaLookup.get(viewportAgent);
if (routeConfigLookup === void 0) {
this.vpaLookup.set(viewportAgent, routeConfigLookup = new WeakMap());
this._vpaLookup.set(viewportAgent, routeConfigLookup = new WeakMap());
}

@@ -403,6 +408,6 @@

if (routeContext !== void 0) {
logger.trace(`returning existing RouteContext for %s`, rdConfig);
if (__DEV__) trace(logger, Events.rtrResolvingRcExisting, rdConfig);
return routeContext;
}
logger.trace(`creating new RouteContext for %s`, rdConfig);
if (__DEV__) trace(logger, Events.rtrResolvingRcNew, rdConfig);

@@ -432,9 +437,9 @@ const parent = container.has(IRouteContext, true) ? container.get(IRouteContext) : null;

if (typeof instructionOrInstructions === 'string') {
instructionOrInstructions = this.locationMgr.removeBaseHref(instructionOrInstructions);
instructionOrInstructions = this._locationMgr.removeBaseHref(instructionOrInstructions);
}
const isVpInstr = typeof instructionOrInstructions !== 'string' && 'component' in instructionOrInstructions;
const isVpInstr = isPartialViewportInstruction(instructionOrInstructions);
let $instruction = isVpInstr ? (instructionOrInstructions as IViewportInstruction).component : instructionOrInstructions;
if (typeof $instruction === 'string' && $instruction.startsWith('../') && context !== null) {
context = this.resolveContext(context);
context = this._resolveContext(context);
while (($instruction as string).startsWith('../') && (context?.parent ?? null) !== null) {

@@ -445,3 +450,3 @@ $instruction = ($instruction as string).slice(3);

}
if(isVpInstr) {
if (isVpInstr) {
(instructionOrInstructions as Writable<IViewportInstruction>).component = $instruction;

@@ -457,3 +462,3 @@ } else {

NavigationOptions.create(routerOptions, { ...options, context }),
this.ctx
this._ctx
);

@@ -471,4 +476,6 @@ }

* @param failedTr - If this is a redirect / fallback from a failed transition, the previous transition is passed forward to ensure the original promise resolves with the latest result.
*
* @internal
*/
private enqueue(
private _enqueue(
instructions: ViewportInstructionTree,

@@ -480,7 +487,7 @@ trigger: RoutingTrigger,

const lastTr = this.currentTr;
const logger = this.logger;
const logger = this._logger;
if (trigger !== 'api' && lastTr.trigger === 'api' && lastTr.instructions.equals(instructions)) {
// User-triggered navigation that results in `replaceState` with the same URL. The API call already triggered the navigation; event is ignored.
logger.debug(`Ignoring navigation triggered by '%s' because it is the same URL as the previous navigation which was triggered by 'api'.`, trigger);
if (__DEV__) debug(logger, Events.rtrIgnoringIdenticalNav, trigger);
return true;

@@ -493,3 +500,4 @@ }

if (failedTr === null || failedTr.erredWithUnknownRoute) {
const restorePrevRT = this.options.restorePreviousRouteTreeOnError;
if (failedTr === null || failedTr.erredWithUnknownRoute || (failedTr.error != null && restorePrevRT)) {
promise = new Promise(function ($resolve, $reject) { resolve = $resolve; reject = $reject; });

@@ -499,3 +507,3 @@ } else {

// any previously failed transition that caused a recovering backwards navigation.
logger.debug(`Reusing promise/resolve/reject from the previously failed transition %s`, failedTr);
if (__DEV__) debug(logger, Events.rtrReusingPromise, failedTr);
promise = failedTr.promise!;

@@ -509,4 +517,4 @@ resolve = failedTr.resolve!;

// This is consistent with the runtime's controller behavior, where if you rapidly call async activate -> deactivate -> activate (for example), then the deactivate is canceled.
const nextTr = this.nextTr = Transition.create({
id: ++this.navigationId,
const nextTr = this._nextTr = Transition._create({
id: ++this._navigationId,
trigger,

@@ -523,3 +531,3 @@ managedState: state,

previousRouteTree: this.routeTree,
routeTree: this._routeTree = this.routeTree.clone(),
routeTree: this._routeTree = this.routeTree._clone(),
guardsResult: true,

@@ -529,3 +537,3 @@ error: void 0,

logger.debug(`Scheduling transition: %s`, nextTr);
if (__DEV__) debug(logger, Events.rtrSchedulingTr, nextTr);

@@ -535,5 +543,5 @@ if (!this._isNavigating) {

try {
this.run(nextTr);
this._run(nextTr);
} catch (err) {
nextTr.handleError(err);
nextTr._handleError(err);
}

@@ -543,17 +551,21 @@ }

return nextTr.promise!.then(ret => {
logger.debug(`Transition succeeded: %s`, nextTr);
if (__DEV__) debug(logger, Events.rtrTrSucceeded, nextTr);
return ret;
}).catch(err => {
logger.error(`Transition %s failed: %s`, nextTr, err);
error(logger, Events.rtrTrFailed, nextTr, err);
if (nextTr.erredWithUnknownRoute) {
this.cancelNavigation(nextTr);
this._cancelNavigation(nextTr);
} else {
this._isNavigating = false;
this.events.publish(new NavigationErrorEvent(nextTr.id, nextTr.instructions, err));
const $nextTr = this.nextTr;
// because the navigation failed it makes sense to restore the previous route-tree so that with next navigation, lifecycle hooks are correctly invoked.
if ($nextTr !== null) {
($nextTr as Writable<Transition>).previousRouteTree = nextTr.previousRouteTree;
this._events.publish(new NavigationErrorEvent(nextTr.id, nextTr.instructions, err));
if (restorePrevRT) {
this._cancelNavigation(nextTr);
} else {
this._routeTree = nextTr.previousRouteTree;
const $nextTr = this._nextTr;
// because the navigation failed it makes sense to restore the previous route-tree so that with next navigation, lifecycle hooks are correctly invoked.
if ($nextTr !== null) {
($nextTr as Writable<Transition>).previousRouteTree = nextTr.previousRouteTree;
} else {
this._routeTree = nextTr.previousRouteTree;
}
}

@@ -565,5 +577,6 @@ }

private run(tr: Transition): void {
/** @internal */
private _run(tr: Transition): void {
this.currentTr = tr;
this.nextTr = null;
this._nextTr = null;

@@ -582,23 +595,19 @@ /**

this._isNavigating = true;
let navigationContext = this.resolveContext(tr.options.context);
let navigationContext = this._resolveContext(tr.options.context);
const logger = /*@__PURE__*/ this._logger.scopeTo('run()');
this.logger.trace(`run(tr:%s) - processing route`, tr);
if (__DEV__) trace(logger, Events.rtrRunBegin, tr);
this.events.publish(new NavigationStartEvent(tr.id, tr.instructions, tr.trigger, tr.managedState));
this._events.publish(new NavigationStartEvent(tr.id, tr.instructions, tr.trigger, tr.managedState));
// If user triggered a new transition in response to the NavigationStartEvent
// (in which case `this.nextTransition` will NOT be null), we short-circuit here and go straight to processing the next one.
if (this.nextTr !== null) {
this.logger.debug(`run(tr:%s) - aborting because a new transition was queued in response to the NavigationStartEvent`, tr);
return this.run(this.nextTr);
if (this._nextTr !== null) {
if (__DEV__) debug(logger, Events.rtrRunCancelled, tr);
return this._run(this._nextTr);
}
// TODO: run global guards
//
//
// ---
tr.run(() => {
tr._run(() => {
const vit = tr.finalInstructions;
this.logger.trace(`run() - compiling route tree: %s`, vit);
if (__DEV__) trace(logger, Events.rtrRunVitCompile, vit);

@@ -621,10 +630,10 @@ /**

// other than by reading (deps, optional route config, owned viewports) from it.
const rootCtx = this.ctx;
const rootCtx = this._ctx;
const rt = tr.routeTree;
(rt as Writable<RouteTree>).options = vit.options;
(rt as Writable<RouteTree>).queryParams = (rootCtx.node.tree as Writable<RouteTree>).queryParams = vit.queryParams;
(rt as Writable<RouteTree>).fragment = (rootCtx.node.tree as Writable<RouteTree>).fragment = vit.fragment;
(rt as Writable<RouteTree>).queryParams = (rootCtx.node._tree as Writable<RouteTree>).queryParams = vit.queryParams;
(rt as Writable<RouteTree>).fragment = (rootCtx.node._tree as Writable<RouteTree>).fragment = vit.fragment;
const log = navigationContext.container.get(ILogger).scopeTo('RouteTree');
const log = /*@__PURE__*/ navigationContext.container.get(ILogger).scopeTo('RouteTree');
if (vit.isAbsolute) {

@@ -634,11 +643,11 @@ navigationContext = rootCtx;

if (navigationContext === rootCtx) {
rt.root.setTree(rt);
rt.root._setTree(rt);
rootCtx.node = rt.root;
}
const suffix = navigationContext.resolved instanceof Promise ? ' - awaiting promise' : '';
const suffix = navigationContext.allResolved instanceof Promise ? ' - awaiting promise' : '';
log.trace(`updateRouteTree(rootCtx:%s,rt:%s,vit:%s)${suffix}`, rootCtx, rt, vit);
// Wait till the promises to resolve the child routes are resolved.
// Note that a route configuration can be a promise.
return onResolve(navigationContext.resolved, () => updateNode(log, vit, navigationContext, rootCtx.node));
return onResolve(navigationContext.allResolved, () => updateNode(log, vit, navigationContext, rootCtx.node));
}, () => {

@@ -649,39 +658,39 @@ const prev = tr.previousRouteTree.root.children;

Batch.start(b => {
this.logger.trace(`run() - invoking canUnload on ${prev.length} nodes`);
Batch._start(b => {
if (__DEV__) trace(logger, Events.rtrRunCanUnload, prev.length);
for (const node of prev) {
node.context.vpa._canUnload(tr, b);
}
}).continueWith(b => {
})._continueWith(b => {
if (tr.guardsResult !== true) {
b.push(); // prevent the next step in the batch from running
this.cancelNavigation(tr);
b._push(); // prevent the next step in the batch from running
this._cancelNavigation(tr);
}
}).continueWith(b => {
this.logger.trace(`run() - invoking canLoad on ${next.length} nodes`);
})._continueWith(b => {
if (__DEV__) trace(logger, Events.rtrRunCanLoad, next.length);
for (const node of next) {
node.context.vpa._canLoad(tr, b);
}
}).continueWith(b => {
})._continueWith(b => {
if (tr.guardsResult !== true) {
b.push();
this.cancelNavigation(tr);
b._push();
this._cancelNavigation(tr);
}
}).continueWith(b => {
this.logger.trace(`run() - invoking unloading on ${prev.length} nodes`);
})._continueWith(b => {
if (__DEV__) trace(logger, Events.rtrRunUnloading, prev.length);
for (const node of prev) {
node.context.vpa._unloading(tr, b);
}
}).continueWith(b => {
this.logger.trace(`run() - invoking loading on ${next.length} nodes`);
})._continueWith(b => {
if (__DEV__) trace(logger, Events.rtrRunLoading, next.length);
for (const node of next) {
node.context.vpa._loading(tr, b);
}
}).continueWith(b => {
this.logger.trace(`run() - invoking swap on ${all.length} nodes`);
})._continueWith(b => {
if (__DEV__) trace(logger, Events.rtrRunSwapping, all.length);
for (const node of all) {
node.context.vpa._swap(tr, b);
}
}).continueWith(() => {
this.logger.trace(`run() - finalizing transition`);
})._continueWith(() => {
if (__DEV__) trace(logger, Events.rtrRunFinalizing);
// order doesn't matter for this operation

@@ -691,5 +700,5 @@ all.forEach(function (node) {

});
this.navigated = true;
this._navigated = true;
this.instructions = tr.finalInstructions = tr.routeTree.finalizeInstructions();
this._instructions = tr.finalInstructions = tr.routeTree._finalizeInstructions();
this._isNavigating = false;

@@ -699,3 +708,3 @@

const newUrl = tr.finalInstructions.toUrl(this.options.useUrlFragmentHash);
switch (tr.options._getHistoryStrategy(this.instructions)) {
switch (tr.options._getHistoryStrategy(this._instructions)) {
case 'none':

@@ -705,15 +714,15 @@ // do nothing

case 'push':
this.locationMgr.pushState(toManagedState(tr.options.state, tr.id), this.updateTitle(tr), newUrl);
this._locationMgr.pushState(toManagedState(tr.options.state, tr.id), this.updateTitle(tr), newUrl);
break;
case 'replace':
this.locationMgr.replaceState(toManagedState(tr.options.state, tr.id), this.updateTitle(tr), newUrl);
this._locationMgr.replaceState(toManagedState(tr.options.state, tr.id), this.updateTitle(tr), newUrl);
break;
}
this.events.publish(new NavigationEndEvent(tr.id, tr.instructions, this.instructions));
this._events.publish(new NavigationEndEvent(tr.id, tr.instructions, this._instructions));
tr.resolve!(true);
this.runNextTransition();
}).start();
this._runNextTransition();
})._start();
});

@@ -740,9 +749,11 @@ }

if (title.length > 0) {
this.p.document.title = title;
this._p.document.title = title;
}
return this.p.document.title;
return this._p.document.title;
}
private cancelNavigation(tr: Transition): void {
this.logger.trace(`cancelNavigation(tr:%s)`, tr);
/** @internal */
private _cancelNavigation(tr: Transition): void {
const logger = /*@__PURE__*/ this._logger.scopeTo('cancelNavigation()');
if(__DEV__) trace(logger, Events.rtrCancelNavigationStart, tr);

@@ -757,7 +768,7 @@ const prev = tr.previousRouteTree.root.children;

this.instructions = tr.prevInstructions;
this._instructions = tr.prevInstructions;
this._routeTree = tr.previousRouteTree;
this._isNavigating = false;
const guardsResult = tr.guardsResult;
this.events.publish(new NavigationCancelEvent(tr.id, tr.instructions, `guardsResult is ${guardsResult}`));
this._events.publish(new NavigationCancelEvent(tr.id, tr.instructions, `guardsResult is ${guardsResult}`));

@@ -768,7 +779,12 @@ if (guardsResult === false) {

// In case a new navigation was requested in the meantime, immediately start processing it
this.runNextTransition();
this._runNextTransition();
} else {
const instructions = tr.erredWithUnknownRoute ? tr.prevInstructions : guardsResult as ViewportInstructionTree;
void onResolve(this.enqueue(instructions, 'api', tr.managedState, tr), () => {
this.logger.trace(`cancelNavigation(tr:%s) - finished redirect`, tr);
let instructions: ViewportInstructionTree;
if (this._navigated && (tr.erredWithUnknownRoute || (tr.error != null && this.options.restorePreviousRouteTreeOnError))) instructions = tr.prevInstructions;
else if (guardsResult === true) return;
else instructions = guardsResult;
void onResolve(this._enqueue(instructions, 'api', tr.managedState, tr), () => {
if(__DEV__) trace(this._logger, Events.rtrCancelNavigationCompleted, tr);
});

@@ -778,15 +794,16 @@ }

private runNextTransition(): void {
if (this.nextTr === null) return;
this.logger.trace(`scheduling nextTransition: %s`, this.nextTr);
this.p.taskQueue.queueTask(
/** @internal */
private _runNextTransition(): void {
if (this._nextTr === null) return;
if(__DEV__) trace(this._logger, Events.rtrNextTr, this._nextTr);
this._p.taskQueue.queueTask(
() => {
// nextTransition is allowed to change up until the point when it's actually time to process it,
// so we need to check it for null again when the scheduled task runs.
const nextTr = this.nextTr;
const nextTr = this._nextTr;
if (nextTr === null) return;
try {
this.run(nextTr);
this._run(nextTr);
} catch (err) {
nextTr.handleError(err);
nextTr._handleError(err);
}

@@ -806,11 +823,11 @@ },

node.queryParams = vit.queryParams;
node.fragment = vit.fragment;
(node as Writable<RouteNode>).queryParams = vit.queryParams;
(node as Writable<RouteNode>).fragment = vit.fragment;
if (!node.context.isRoot) {
node.context.vpa._scheduleUpdate(node.tree.options, node);
node.context.vpa._scheduleUpdate(node._tree.options, node);
}
if (node.context === ctx) {
// Do an in-place update (remove children and re-add them by compiling the instructions into nodes)
node.clearChildren();
node._clearChildren();
// - first append the nodes as children, compiling the viewport instructions.

@@ -817,0 +834,0 @@ // - if afterward, any viewports are still available

@@ -5,17 +5,19 @@ import { ICustomElementController } from '@aurelia/runtime-html';

class ScrollState {
private readonly top: number;
private readonly left: number;
/** @internal */ private readonly _top: number;
/** @internal */ private readonly _left: number;
public constructor(private el: Element) {
this.top = el.scrollTop;
this.left = el.scrollLeft;
public constructor(/** @internal */ private _el: Element) {
this._top = _el.scrollTop;
this._left = _el.scrollLeft;
}
public static has(el: Element): boolean {
/** @internal */
public static _has(el: Element): boolean {
return el.scrollTop > 0 || el.scrollLeft > 0;
}
public restore(): void {
this.el.scrollTo(this.left, this.top);
this.el = null!;
/** @internal */
public _restore(): void {
this._el.scrollTo(this._left, this._top);
this._el = null!;
}

@@ -25,27 +27,29 @@ }

function restoreState(state: ScrollState): void {
state.restore();
state._restore();
}
class HostElementState {
private scrollStates: ScrollState[] = [];
/** @internal */ private _scrollStates: ScrollState[] = [];
public constructor(host: Element) {
this.save(host.children);
this._save(host.children);
}
private save(elements: HTMLCollection): void {
/** @internal */
private _save(elements: HTMLCollection): void {
let el: Element;
for (let i = 0, ii = elements.length; i < ii; ++i) {
el = elements[i];
if (ScrollState.has(el)) {
this.scrollStates.push(new ScrollState(el));
if (ScrollState._has(el)) {
this._scrollStates.push(new ScrollState(el));
}
this.save(el.children);
this._save(el.children);
}
}
public restore(): void {
this.scrollStates.forEach(restoreState);
this.scrollStates = null!;
/** @internal */
public _restore(): void {
this._scrollStates.forEach(restoreState);
this._scrollStates = null!;
}

@@ -61,15 +65,15 @@ }

export class ScrollStateManager implements IStateManager {
private readonly cache: WeakMap<HTMLElement, HostElementState> = new WeakMap();
private readonly _cache: WeakMap<HTMLElement, HostElementState> = new WeakMap();
public saveState(controller: ICustomElementController): void {
this.cache.set(controller.host, new HostElementState(controller.host));
this._cache.set(controller.host, new HostElementState(controller.host));
}
public restoreState(controller: ICustomElementController): void {
const state = this.cache.get(controller.host);
const state = this._cache.get(controller.host);
if (state !== void 0) {
state.restore();
this.cache.delete(controller.host);
state._restore();
this._cache.delete(controller.host);
}
}
}

@@ -6,57 +6,58 @@ import { Params } from './instructions';

/** @internal */
export class Batch {
public done: boolean = false;
public readonly head: Batch;
private next: Batch | null = null;
public _done: boolean = false;
public readonly _head: Batch;
private _next: Batch | null = null;
private constructor(
private stack: number,
private cb: ((b: Batch) => void) | null,
private _stack: number,
private _cb: ((b: Batch) => void) | null,
head: Batch | null,
) {
this.head = head ?? this;
this._head = head ?? this;
}
public static start(cb: (b: Batch) => void): Batch {
public static _start(cb: (b: Batch) => void): Batch {
return new Batch(0, cb, null);
}
public push(): void {
public _push(): void {
let cur = this as Batch;
do {
++cur.stack;
cur = cur.next!;
++cur._stack;
cur = cur._next!;
} while (cur !== null);
}
public pop(): void {
public _pop(): void {
let cur = this as Batch;
do {
if (--cur.stack === 0) {
cur.invoke();
if (--cur._stack === 0) {
cur._invoke();
}
cur = cur.next!;
cur = cur._next!;
} while (cur !== null);
}
private invoke(): void {
const cb = this.cb;
private _invoke(): void {
const cb = this._cb;
if (cb !== null) {
this.cb = null;
this._cb = null;
cb(this);
this.done = true;
this._done = true;
}
}
public continueWith(cb: (b: Batch) => void): Batch {
if (this.next === null) {
return this.next = new Batch(this.stack, cb, this.head);
public _continueWith(cb: (b: Batch) => void): Batch {
if (this._next === null) {
return this._next = new Batch(this._stack, cb, this._head);
} else {
return this.next.continueWith(cb);
return this._next._continueWith(cb);
}
}
public start(): Batch {
this.head.push();
this.head.pop();
public _start(): Batch {
this._head._push();
this._head._pop();
return this;

@@ -63,0 +64,0 @@ }

@@ -5,4 +5,5 @@ import type { IIndexable } from '@aurelia/kernel';

import type { IChildRouteConfig, IRedirectRouteConfig, Routeable } from './options';
import type { IViewportInstruction, Params, RouteableComponent } from './instructions';
import type { IExtendedViewportInstruction, IViewportInstruction, Params, RouteableComponent } from './instructions';
import { tryStringify } from './util';
import { Events, getMessage } from './events';

@@ -49,3 +50,3 @@ /**

// and the two are intended to be used in specific contexts, we keep these as two separate functions for now.
export function isPartialViewportInstruction(value: RouteableComponent | IViewportInstruction | null | undefined): value is IViewportInstruction {
export function isPartialViewportInstruction(value: RouteableComponent | IViewportInstruction | null | undefined): value is IExtendedViewportInstruction {
// 'component' is the only mandatory property of a INavigationInstruction

@@ -60,3 +61,3 @@ // It may overlap with RouteType and CustomElementViewModel, so this ducktype check is only valid when those are ruled out *first*

export function expectType(expected: string, prop: string, value: unknown): never {
throw new Error(`Invalid route config property: "${prop}". Expected ${expected}, but got ${tryStringify(value)}.`);
throw new Error(getMessage(Events.rtInvalidConfigProperty, prop, expected, tryStringify(value)));
}

@@ -71,5 +72,3 @@

export function validateRouteConfig(config: Partial<IChildRouteConfig> | null | undefined, parentPath: string): void {
if (config === null || config === void 0) {
throw new Error(`Invalid route config: expected an object or string, but got: ${String(config)}.`);
}
if (config == null) throw new Error(getMessage(Events.rtInvalidConfig, config));

@@ -155,3 +154,3 @@ const keys = Object.keys(config) as (keyof IChildRouteConfig)[];

// We don't *have* to throw here, but let's be as strict as possible until someone gives a valid reason for not doing so.
throw new Error(`Unknown route config property: "${parentPath}.${key as string}". Please specify known properties only.`);
throw new Error(getMessage(Events.rtUnknownConfigProperty, parentPath, key));
}

@@ -162,5 +161,3 @@ }

function validateRedirectRouteConfig(config: Partial<IRedirectRouteConfig> | null | undefined, parentPath: string): void {
if (config === null || config === void 0) {
throw new Error(`Invalid route config: expected an object or string, but got: ${String(config)}.`);
}
if (config == null) throw new Error(getMessage(Events.rtInvalidConfig, config));

@@ -190,3 +187,3 @@ const keys = Object.keys(config) as (keyof IRedirectRouteConfig)[];

// We don't *have* to throw here, but let's be as strict as possible until someone gives a valid reason for not doing so.
throw new Error(`Unknown redirect config property: "${parentPath}.${key as string}". Only 'path' and 'redirectTo' should be specified for redirects.`);
throw new Error(getMessage(Events.rtUnknownRedirectConfigProperty, parentPath, key));
}

@@ -193,0 +190,0 @@ }

@@ -14,2 +14,3 @@ // No-fallthrough disabled due to large numbers of false positives

import { ViewportInstruction, defaultViewportName } from './instructions';
import { Events, getMessage, trace } from './events';

@@ -22,2 +23,3 @@ export class ViewportRequest {

// Should not be adjust for DEV as it is also used of logging in production build.
public toString(): string {

@@ -31,32 +33,30 @@ return `VR(viewport:'${this.viewportName}',component:'${this.componentName}')`;

export class ViewportAgent {
private readonly logger: ILogger;
/** @internal */ private readonly _logger: ILogger;
private isActive: boolean = false;
/** @internal */ private _isActive: boolean = false;
private curCA: ComponentAgent | null = null;
private nextCA: ComponentAgent | null = null;
/** @internal */ private _curCA: ComponentAgent | null = null;
/** @internal */ private _nextCA: ComponentAgent | null = null;
private get $state(): string { return $state(this.state); }
private state: State = State.bothAreEmpty;
private get currState(): CurrState { return this.state & State.curr; }
private set currState(state: CurrState) { this.state = (this.state & State.next) | state; }
private get nextState(): NextState { return this.state & State.next; }
private set nextState(state: NextState) { this.state = (this.state & State.curr) | state; }
/** @internal */ private _state: State = State.bothAreEmpty;
/** @internal */ private get _currState(): CurrState { return this._state & State.curr; }
/** @internal */ private set _currState(state: CurrState) { this._state = (this._state & State.next) | state; }
/** @internal */ private get _nextState(): NextState { return this._state & State.next; }
/** @internal */ private set _nextState(state: NextState) { this._state = (this._state & State.curr) | state; }
private $plan: TransitionPlan = 'replace';
private currNode: RouteNode | null = null;
private nextNode: RouteNode | null = null;
/** @internal */ private _$plan: TransitionPlan = 'replace';
/** @internal */ private _currNode: RouteNode | null = null;
/** @internal */ private _nextNode: RouteNode | null = null;
private currTransition: Transition | null = null;
/** @internal */
private _cancellationPromise: Promise<void> | void | null = null;
/** @internal */ private _currTransition: Transition | null = null;
/** @internal */ private _cancellationPromise: Promise<void> | void | null = null;
public constructor(
private constructor(
public readonly viewport: IViewport,
public readonly hostController: ICustomElementController,
public readonly ctx: IRouteContext,
ctx: IRouteContext,
) {
this.logger = ctx.container.get(ILogger).scopeTo(`ViewportAgent<${ctx.friendlyPath}>`);
this._logger = ctx.container.get(ILogger).scopeTo(`ViewportAgent<${ctx._friendlyPath}>`);
this.logger.trace(`constructor()`);
if (__DEV__) trace(this._logger, Events.vpaCreated);
}

@@ -79,15 +79,16 @@

public _activateFromViewport(initiator: IHydratedController, parent: IHydratedController): void | Promise<void> {
const tr = this.currTransition;
const tr = this._currTransition;
if (tr !== null) { ensureTransitionHasNotErrored(tr); }
this.isActive = true;
this._isActive = true;
switch (this.nextState) {
const logger = /*@__PURE__*/ this._logger.scopeTo('activateFromViewport()');
switch (this._nextState) {
case State.nextIsEmpty:
switch (this.currState) {
switch (this._currState) {
case State.currIsEmpty:
this.logger.trace(`activateFromViewport() - nothing to activate at %s`, this);
if (__DEV__) trace(logger, Events.vpaActivateFromVpNone, this);
return;
case State.currIsActive:
this.logger.trace(`activateFromViewport() - activating existing componentAgent at %s`, this);
return this.curCA!._activate(initiator, parent);
if (__DEV__) trace(logger, Events.vpaActivateFromVpExisting, this);
return this._curCA!._activate(initiator, parent);
default:

@@ -97,9 +98,7 @@ this._unexpectedState('activateFromViewport 1');

case State.nextLoadDone: {
if (this.currTransition === null) {
throw new Error(`Unexpected viewport activation outside of a transition context at ${this}`);
}
this.logger.trace(`activateFromViewport() - running ordinary activate at %s`, this);
const b = Batch.start(b1 => { this._activate(initiator, this.currTransition!, b1); });
const p = new Promise<void>(resolve => { b.continueWith(() => { resolve(); }); });
return b.start().done ? void 0 : p;
if (this._currTransition === null) throw new Error(getMessage(Events.vpaUnexpectedActivation, this));
if (__DEV__) trace(logger, Events.vpaActivateFromVpNext, this);
const b = Batch._start(b1 => { this._activate(initiator, this._currTransition!, b1); });
const p = new Promise<void>(resolve => { b._continueWith(() => { resolve(); }); });
return b._start()._done ? void 0 : p;
}

@@ -113,13 +112,14 @@ default:

public _deactivateFromViewport(initiator: IHydratedController, parent: IHydratedController): void | Promise<void> {
const tr = this.currTransition;
const tr = this._currTransition;
if (tr !== null) { ensureTransitionHasNotErrored(tr); }
this.isActive = false;
this._isActive = false;
switch (this.currState) {
const logger = /*@__PURE__*/ this._logger.scopeTo('deactivateFromViewport()');
switch (this._currState) {
case State.currIsEmpty:
this.logger.trace(`deactivateFromViewport() - nothing to deactivate at %s`, this);
if (__DEV__) trace(logger, Events.vpaDeactivateFromVpNone, this);
return;
case State.currIsActive:
this.logger.trace(`deactivateFromViewport() - deactivating existing componentAgent at %s`, this);
return this.curCA!._deactivate(initiator, parent);
if (__DEV__) trace(logger, Events.vpaDeactivateFromVpExisting, this);
return this._curCA!._deactivate(initiator, parent);
case State.currDeactivate:

@@ -129,12 +129,10 @@ // This will happen with bottom-up deactivation because the child is already deactivated, the parent

// Since this is viewport was already deactivated, and we know the precise circumstance under which that happens, we can safely ignore the call.
this.logger.trace(`deactivateFromViewport() - already deactivating at %s`, this);
if (__DEV__) trace(logger, Events.vpaDeactivationFromVpRunning, this);
return;
default: {
if (this.currTransition === null) {
throw new Error(`Unexpected viewport deactivation outside of a transition context at ${this}`);
}
this.logger.trace(`deactivateFromViewport() - running ordinary deactivate at %s`, this);
const b = Batch.start(b1 => { this._deactivate(initiator, this.currTransition!, b1); });
const p = new Promise<void>(resolve => { b.continueWith(() => { resolve(); }); });
return b.start().done ? void 0 : p;
if (this._currTransition === null) throw new Error(getMessage(Events.vpaUnexpectedDeactivation, this));
if (__DEV__) trace(logger, Events.vpaDeactivateFromVpCurrent, this);
const b = Batch._start(b1 => { this._deactivate(initiator, this._currTransition!, b1); });
const p = new Promise<void>(resolve => { b._continueWith(() => { resolve(); }); });
return b._start()._done ? void 0 : p;
}

@@ -153,2 +151,3 @@ }

const vp = $vp.name;
const logger = /*@__PURE__*/ this._logger.scopeTo('handles()');
/*

@@ -174,3 +173,3 @@ Name from viewport request

if (reqVp !== defaultViewportName && vp !== reqVp) {
this.logger.trace(`handles(req:%s) -> false (viewport names don't match '%s')`, req, vp);
if (__DEV__) trace(logger, Events.vpaHandlesVpMismatch, req, vp);
return false;

@@ -181,7 +180,7 @@ }

if (usedBy.length > 0 && !usedBy.split(',').includes(req.componentName)) {
this.logger.trace(`handles(req:%s) -> false (componentName not included in usedBy)`, req);
if (__DEV__) trace(logger, Events.vpaHandlesUsedByMismatch, req, usedBy);
return false;
}
this.logger.trace(`viewport '%s' handles(req:%s) -> true`, vp, req);
if (__DEV__) trace(logger, Events.vpaHandles, vp, req);
return true;

@@ -192,9 +191,10 @@ }

public _isAvailable(): boolean {
if (!this.isActive) {
this.logger.trace(`isAvailable -> false (viewport is not active)`);
const logger = /*@__PURE__*/ this._logger.scopeTo('isAvailable()');
if (!this._isActive) {
if (__DEV__) trace(logger, Events.vpaIsAvailableInactive);
return false;
}
if (this.nextState !== State.nextIsEmpty) {
this.logger.trace(`isAvailable -> false (update already scheduled for %s)`, this.nextNode);
if (this._nextState !== State.nextIsEmpty) {
if (__DEV__) trace(logger, Events.vpaIsAvailableScheduled, this._nextNode);
return false;

@@ -208,46 +208,47 @@ }

public _canUnload(tr: Transition, b: Batch): void {
if (this.currTransition === null) { this.currTransition = tr; }
if (this._currTransition === null) { this._currTransition = tr; }
ensureTransitionHasNotErrored(tr);
if (tr.guardsResult !== true) { return; }
b.push();
b._push();
const logger = /*@__PURE__*/ this._logger.scopeTo('canUnload()');
void onResolve(this._cancellationPromise, () => {
// run canUnload bottom-up
Batch.start(b1 => {
this.logger.trace(`canUnload() - invoking on children at %s`, this);
for (const node of this.currNode!.children) {
Batch._start(b1 => {
if (__DEV__) trace(logger, Events.vpaCanUnloadChildren, this);
for (const node of this._currNode!.children) {
node.context.vpa._canUnload(tr, b1);
}
}).continueWith(b1 => {
switch (this.currState) {
})._continueWith(b1 => {
switch (this._currState) {
case State.currIsActive:
this.logger.trace(`canUnload() - invoking on existing component at %s`, this);
switch (this.$plan) {
if (__DEV__) trace(logger, Events.vpaCanUnloadExisting, this);
switch (this._$plan) {
case 'none':
this.currState = State.currCanUnloadDone;
this._currState = State.currCanUnloadDone;
return;
case 'invoke-lifecycles':
case 'replace':
this.currState = State.currCanUnload;
b1.push();
Batch.start(b2 => {
this.logger.trace(`canUnload() - finished invoking on children, now invoking on own component at %s`, this);
this.curCA!._canUnload(tr, this.nextNode, b2);
}).continueWith(() => {
this.logger.trace(`canUnload() - finished at %s`, this);
this.currState = State.currCanUnloadDone;
b1.pop();
}).start();
this._currState = State.currCanUnload;
b1._push();
Batch._start(b2 => {
if (__DEV__) trace(logger, Events.vpaCanUnloadSelf, this);
this._curCA!._canUnload(tr, this._nextNode, b2);
})._continueWith(() => {
if (__DEV__) trace(logger, Events.vpaCanUnloadFinished, this);
this._currState = State.currCanUnloadDone;
b1._pop();
})._start();
return;
}
case State.currIsEmpty:
this.logger.trace(`canUnload() - nothing to unload at %s`, this);
if (__DEV__) trace(logger, Events.vpaCanUnloadNone, this);
return;
default:
tr.handleError(new Error(`Unexpected state at canUnload of ${this}`));
tr._handleError(new Error(`Unexpected state at canUnload of ${this}`));
}
}).continueWith(() => {
b.pop();
}).start();
})._continueWith(() => {
b._pop();
})._start();
});

@@ -258,26 +259,27 @@ }

public _canLoad(tr: Transition, b: Batch): void {
if (this.currTransition === null) { this.currTransition = tr; }
if (this._currTransition === null) { this._currTransition = tr; }
ensureTransitionHasNotErrored(tr);
if (tr.guardsResult !== true) { return; }
b.push();
b._push();
const logger = /*@__PURE__*/ this._logger.scopeTo('canLoad()');
// run canLoad top-down
Batch.start(b1 => {
switch (this.nextState) {
Batch._start(b1 => {
switch (this._nextState) {
case State.nextIsScheduled:
this.logger.trace(`canLoad() - invoking on new component at %s`, this);
this.nextState = State.nextCanLoad;
switch (this.$plan) {
if (__DEV__) trace(logger, Events.vpaCanLoadNext, this);
this._nextState = State.nextCanLoad;
switch (this._$plan) {
case 'none':
return;
case 'invoke-lifecycles':
return this.curCA!._canLoad(tr, this.nextNode!, b1);
return this._curCA!._canLoad(tr, this._nextNode!, b1);
case 'replace':
b1.push();
b1._push();
void onResolve(
this.nextNode!.context.createComponentAgent(this.hostController, this.nextNode!),
this._nextNode!.context._createComponentAgent(this.hostController, this._nextNode!),
ca => {
(this.nextCA = ca)._canLoad(tr, this.nextNode!, b1);
b1.pop();
(this._nextCA = ca)._canLoad(tr, this._nextNode!, b1);
b1._pop();
}

@@ -287,3 +289,3 @@ );

case State.nextIsEmpty:
this.logger.trace(`canLoad() - nothing to load at %s`, this);
if (__DEV__) trace(logger, Events.vpaCanLoadNone, this);
return;

@@ -293,8 +295,8 @@ default:

}
}).continueWith(b1 => {
const next = this.nextNode!;
switch (this.$plan) {
})._continueWith(b1 => {
const next = this._nextNode!;
switch (this._$plan) {
case 'none':
case 'invoke-lifecycles': {
this.logger.trace(`canLoad(next:%s) - plan set to '%s', compiling residue`, next, this.$plan);
if (__DEV__) trace(logger, Events.vpaCanLoadResidue, next, this._$plan);

@@ -308,10 +310,10 @@ // These plans can only occur if there is already a current component active in this viewport,

// their target viewports have the appropriate updates scheduled.
b1.push();
b1._push();
const ctx = next.context;
void onResolve(
ctx.resolved,
ctx.allResolved,
() => onResolve(
onResolve(
onResolveAll(
...next.residue.splice(0).map(vi => createAndAppendNodes(this.logger, next, vi))
...next.residue.splice(0).map(vi => createAndAppendNodes(this._logger, next, vi))
),

@@ -322,7 +324,7 @@ () => onResolveAll(...ctx.getAvailableViewportAgents().reduce((acc, vpa) => {

if (component === null) return acc;
acc.push(createAndAppendNodes(this.logger, next, ViewportInstruction.create({ component, viewport: vp.name, })));
acc.push(createAndAppendNodes(this._logger, next, ViewportInstruction.create({ component, viewport: vp.name, })));
return acc;
}, ([] as (void | Promise<void>)[]))),
),
() => { b1.pop(); }
() => { b1._pop(); }
)

@@ -333,11 +335,11 @@ );

case 'replace':
this.logger.trace(`canLoad(next:%s), delaying residue compilation until activate`, next, this.$plan);
if (__DEV__) trace(logger, Events.vpaCanLoadResidueDelay, next);
return;
}
}).continueWith(b1 => {
switch (this.nextState) {
})._continueWith(b1 => {
switch (this._nextState) {
case State.nextCanLoad:
this.logger.trace(`canLoad() - finished own component, now invoking on children at %s`, this);
this.nextState = State.nextCanLoadDone;
for (const node of this.nextNode!.children) {
if (__DEV__) trace(logger, Events.vpaCanLoadChildren, this);
this._nextState = State.nextCanLoadDone;
for (const node of this._nextNode!.children) {
node.context.vpa._canLoad(tr, b1);

@@ -351,6 +353,6 @@ }

}
}).continueWith(() => {
this.logger.trace(`canLoad() - finished at %s`, this);
b.pop();
}).start();
})._continueWith(() => {
if (__DEV__) trace(logger, Events.vpaCanLoadFinished, this);
b._pop();
})._start();
}

@@ -363,35 +365,36 @@

b.push();
b._push();
const logger = /*@__PURE__*/ this._logger.scopeTo('unloading()');
// run unloading bottom-up
Batch.start(b1 => {
this.logger.trace(`unloading() - invoking on children at %s`, this);
for (const node of this.currNode!.children) {
Batch._start(b1 => {
if (__DEV__) trace(logger, Events.vpaUnloadingChildren, this);
for (const node of this._currNode!.children) {
node.context.vpa._unloading(tr, b1);
}
}).continueWith(b1 => {
switch (this.currState) {
})._continueWith(b1 => {
switch (this._currState) {
case State.currCanUnloadDone:
this.logger.trace(`unloading() - invoking on existing component at %s`, this);
switch (this.$plan) {
if (__DEV__) trace(logger, Events.vpaUnloadingExisting, this);
switch (this._$plan) {
case 'none':
this.currState = State.currUnloadDone;
this._currState = State.currUnloadDone;
return;
case 'invoke-lifecycles':
case 'replace':
this.currState = State.currUnload;
b1.push();
Batch.start(b2 => {
this.logger.trace(`unloading() - finished invoking on children, now invoking on own component at %s`, this);
this.curCA!._unloading(tr, this.nextNode, b2);
}).continueWith(() => {
this.logger.trace(`unloading() - finished at %s`, this);
this.currState = State.currUnloadDone;
b1.pop();
}).start();
this._currState = State.currUnload;
b1._push();
Batch._start(b2 => {
if (__DEV__) trace(logger, Events.vpaUnloadingSelf, this);
this._curCA!._unloading(tr, this._nextNode, b2);
})._continueWith(() => {
if (__DEV__) trace(logger, Events.vpaUnloadingFinished, this);
this._currState = State.currUnloadDone;
b1._pop();
})._start();
return;
}
case State.currIsEmpty:
this.logger.trace(`unloading() - nothing to unload at %s`, this);
for (const node of this.currNode!.children) {
if (__DEV__) trace(logger, Events.vpaUnloadingNone, this);
for (const node of this._currNode!.children) {
node.context.vpa._unloading(tr, b);

@@ -403,5 +406,5 @@ }

}
}).continueWith(() => {
b.pop();
}).start();
})._continueWith(() => {
b._pop();
})._start();
}

@@ -414,21 +417,22 @@

b.push();
b._push();
const logger = /*@__PURE__*/ this._logger.scopeTo('loading()');
// run load top-down
Batch.start(b1 => {
switch (this.nextState) {
Batch._start(b1 => {
switch (this._nextState) {
case State.nextCanLoadDone: {
this.logger.trace(`loading() - invoking on new component at %s`, this);
this.nextState = State.nextLoad;
switch (this.$plan) {
if (__DEV__) trace(logger, Events.vpaLoadingNext, this);
this._nextState = State.nextLoad;
switch (this._$plan) {
case 'none':
return;
case 'invoke-lifecycles':
return this.curCA!._loading(tr, this.nextNode!, b1);
return this._curCA!._loading(tr, this._nextNode!, b1);
case 'replace':
return this.nextCA!._loading(tr, this.nextNode!, b1);
return this._nextCA!._loading(tr, this._nextNode!, b1);
}
}
case State.nextIsEmpty:
this.logger.trace(`loading() - nothing to load at %s`, this);
if (__DEV__) trace(logger, Events.vpaLoadingNone, this);
return;

@@ -438,8 +442,8 @@ default:

}
}).continueWith(b1 => {
switch (this.nextState) {
})._continueWith(b1 => {
switch (this._nextState) {
case State.nextLoad:
this.logger.trace(`loading() - finished own component, now invoking on children at %s`, this);
this.nextState = State.nextLoadDone;
for (const node of this.nextNode!.children) {
if (__DEV__) trace(logger, Events.vpaLoadingChildren, this);
this._nextState = State.nextLoadDone;
for (const node of this._nextNode!.children) {
node.context.vpa._loading(tr, b1);

@@ -453,6 +457,6 @@ }

}
}).continueWith(() => {
this.logger.trace(`loading() - finished at %s`, this);
b.pop();
}).start();
})._continueWith(() => {
if (__DEV__) trace(logger, Events.vpaLoadingFinished, this);
b._pop();
})._start();
}

@@ -465,17 +469,18 @@

b.push();
b._push();
const logger = /*@__PURE__*/ this._logger.scopeTo('deactivate()');
switch (this.currState) {
switch (this._currState) {
case State.currUnloadDone:
this.logger.trace(`deactivate() - invoking on existing component at %s`, this);
this.currState = State.currDeactivate;
switch (this.$plan) {
if (__DEV__) trace(logger, Events.vpaDeactivateCurrent, this);
this._currState = State.currDeactivate;
switch (this._$plan) {
case 'none':
case 'invoke-lifecycles':
b.pop();
b._pop();
return;
case 'replace': {
const controller = this.hostController;
const curCa = this.curCA!;
tr.run(() => {
const curCa = this._curCA!;
tr._run(() => {
return onResolve(curCa._deactivate(initiator, controller), () => {

@@ -488,3 +493,3 @@ // Call dispose if initiator is null. If there is an initiator present, then the curCa will be disposed when the initiator is disposed.

}, () => {
b.pop();
b._pop();
});

@@ -495,8 +500,8 @@ }

case State.currIsEmpty:
this.logger.trace(`deactivate() - nothing to deactivate at %s`, this);
b.pop();
if (__DEV__) trace(logger, Events.vpaDeactivateNone, this);
b._pop();
return;
case State.currDeactivate:
this.logger.trace(`deactivate() - already deactivating at %s`, this);
b.pop();
if (__DEV__) trace(logger, Events.vpaDeactivationRunning, this);
b._pop();
return;

@@ -513,26 +518,27 @@ default:

b.push();
b._push();
const logger = /*@__PURE__*/ this._logger.scopeTo('activate()');
if (this.nextState === State.nextIsScheduled) {
this.logger.trace(`activate() - invoking canLoad(), loading() and activate() on new component due to resolution 'dynamic' at %s`, this);
if (this._nextState === State.nextIsScheduled) {
if (__DEV__) trace(logger, Events.vpaActivateNextScheduled, this);
// This is the default v2 mode "lazy loading" situation
Batch.start(b1 => {
Batch._start(b1 => {
this._canLoad(tr, b1);
}).continueWith(b1 => {
})._continueWith(b1 => {
this._loading(tr, b1);
}).continueWith(b1 => {
})._continueWith(b1 => {
this._activate(initiator, tr, b1);
}).continueWith(() => {
b.pop();
}).start();
})._continueWith(() => {
b._pop();
})._start();
return;
}
switch (this.nextState) {
switch (this._nextState) {
case State.nextLoadDone:
this.logger.trace(`activate() - invoking on existing component at %s`, this);
this.nextState = State.nextActivate;
if (__DEV__) trace(logger, Events.vpaActivateNext, this);
this._nextState = State.nextActivate;
// run activate top-down
Batch.start(b1 => {
switch (this.$plan) {
Batch._start(b1 => {
switch (this._$plan) {
case 'none':

@@ -543,19 +549,19 @@ case 'invoke-lifecycles':

const controller = this.hostController;
tr.run(() => {
b1.push();
return this.nextCA!._activate(initiator, controller);
tr._run(() => {
b1._push();
return this._nextCA!._activate(initiator, controller);
}, () => {
b1.pop();
b1._pop();
});
}
}
}).continueWith(b1 => {
})._continueWith(b1 => {
this._processDynamicChildren(tr, b1);
}).continueWith(() => {
b.pop();
}).start();
})._continueWith(() => {
b._pop();
})._start();
return;
case State.nextIsEmpty:
this.logger.trace(`activate() - nothing to activate at %s`, this);
b.pop();
if (__DEV__) trace(logger, Events.vpaActivateNone, this);
b._pop();
return;

@@ -569,9 +575,10 @@ default:

public _swap(tr: Transition, b: Batch): void {
if (this.currState === State.currIsEmpty) {
this.logger.trace(`swap() - running activate on next instead, because there is nothing to deactivate at %s`, this);
const logger = /*@__PURE__*/ this._logger.scopeTo('swap()');
if (this._currState === State.currIsEmpty) {
if (__DEV__) trace(logger, Events.vpaSwapEmptyCurr, this);
this._activate(null, tr, b);
return;
}
if (this.nextState === State.nextIsEmpty) {
this.logger.trace(`swap() - running deactivate on current instead, because there is nothing to activate at %s`, this);
if (this._nextState === State.nextIsEmpty) {
if (__DEV__) trace(logger, Events.vpaSwapEmptyNext, this);
this._deactivate(null, tr, b);

@@ -585,4 +592,4 @@ return;

if (!(
this.currState === State.currUnloadDone &&
this.nextState === State.nextLoadDone
this._currState === State.currUnloadDone &&
this._nextState === State.nextLoadDone
)) {

@@ -592,10 +599,10 @@ this._unexpectedState('swap');

this.currState = State.currDeactivate;
this.nextState = State.nextActivate;
this._currState = State.currDeactivate;
this._nextState = State.nextActivate;
switch (this.$plan) {
switch (this._$plan) {
case 'none':
case 'invoke-lifecycles': {
this.logger.trace(`swap() - skipping this level and swapping children instead at %s`, this);
const nodes = mergeDistinct(this.nextNode!.children, this.currNode!.children);
if (__DEV__) trace(logger, Events.vpaSwapSkipToChildren, this);
const nodes = mergeDistinct(this._nextNode!.children, this._currNode!.children);
for (const node of nodes) {

@@ -607,26 +614,26 @@ node.context.vpa._swap(tr, b);

case 'replace': {
this.logger.trace(`swap() - running normally at %s`, this);
if (__DEV__) trace(logger, Events.vpaSwap, this);
const controller = this.hostController;
const curCA = this.curCA!;
const nextCA = this.nextCA!;
b.push();
Batch.start(b1 => {
tr.run(() => {
b1.push();
const curCA = this._curCA!;
const nextCA = this._nextCA!;
b._push();
Batch._start(b1 => {
tr._run(() => {
b1._push();
return onResolve(curCA._deactivate(null, controller), () => curCA._dispose());
}, () => {
b1.pop();
b1._pop();
});
}).continueWith(b1 => {
tr.run(() => {
b1.push();
})._continueWith(b1 => {
tr._run(() => {
b1._push();
return nextCA._activate(null, controller);
}, () => {
b1.pop();
b1._pop();
});
}).continueWith(b1 => {
})._continueWith(b1 => {
this._processDynamicChildren(tr, b1);
}).continueWith(() => {
b.pop();
}).start();
})._continueWith(() => {
b._pop();
})._start();
return;

@@ -639,9 +646,9 @@ }

private _processDynamicChildren(tr: Transition, b: Batch): void {
this.logger.trace(`processDynamicChildren() - %s`, this);
const next = this.nextNode!;
if (__DEV__) trace(this._logger, Events.vpaProcessDynamicChildren, this);
const next = this._nextNode!;
tr.run(() => {
b.push();
tr._run(() => {
b._push();
const ctx = next.context;
return onResolve(ctx.resolved, () => {
return onResolve(ctx.allResolved, () => {
const existingChildren = next.children.slice();

@@ -652,3 +659,3 @@ return onResolve(

.splice(0)
.map(vi => createAndAppendNodes(this.logger, next, vi))),
.map(vi => createAndAppendNodes(this._logger, next, vi))),
() => onResolve(

@@ -661,3 +668,3 @@ onResolveAll(...ctx

if (component === null) return acc;
acc.push(createAndAppendNodes(this.logger, next, ViewportInstruction.create({ component, viewport: vp.name, })));
acc.push(createAndAppendNodes(this._logger, next, ViewportInstruction.create({ component, viewport: vp.name, })));
return acc;

@@ -671,32 +678,32 @@ }, ([] as (void | Promise<void>)[]))

}, newChildren => {
Batch.start(b1 => {
Batch._start(b1 => {
for (const node of newChildren) {
tr.run(() => {
b1.push();
tr._run(() => {
b1._push();
return node.context.vpa._canLoad(tr, b1);
}, () => {
b1.pop();
b1._pop();
});
}
}).continueWith(b1 => {
})._continueWith(b1 => {
for (const node of newChildren) {
tr.run(() => {
b1.push();
tr._run(() => {
b1._push();
return node.context.vpa._loading(tr, b1);
}, () => {
b1.pop();
b1._pop();
});
}
}).continueWith(b1 => {
})._continueWith(b1 => {
for (const node of newChildren) {
tr.run(() => {
b1.push();
tr._run(() => {
b1._push();
return node.context.vpa._activate(null, tr, b1);
}, () => {
b1.pop();
b1._pop();
});
}
}).continueWith(() => {
b.pop();
}).start();
})._continueWith(() => {
b._pop();
})._start();
});

@@ -707,6 +714,6 @@ }

public _scheduleUpdate(options: NavigationOptions, next: RouteNode): void {
switch (this.nextState) {
switch (this._nextState) {
case State.nextIsEmpty:
this.nextNode = next;
this.nextState = State.nextIsScheduled;
this._nextNode = next;
this._nextState = State.nextIsScheduled;
break;

@@ -717,3 +724,3 @@ default:

switch (this.currState) {
switch (this._currState) {
case State.currIsEmpty:

@@ -727,12 +734,12 @@ case State.currIsActive:

const cur = this.curCA?.routeNode ?? null;
const cur = this._curCA?._routeNode ?? null;
if (cur === null || cur.component !== next.component) {
// Component changed (or is cleared), so set to 'replace'
this.$plan = 'replace';
this._$plan = 'replace';
} else {
// Component is the same, so determine plan based on config and/or convention
this.$plan = options.transitionPlan ?? next.context.config.getTransitionPlan(cur, next);
this._$plan = options.transitionPlan ?? next.context.config._getTransitionPlan(cur, next);
}
this.logger.trace(`scheduleUpdate(next:%s) - plan set to '%s'`, next, this.$plan);
if (__DEV__) trace(this._logger, Events.vpaScheduleUpdate, this);
}

@@ -742,9 +749,9 @@

public _cancelUpdate(): void {
if (this.currNode !== null) {
this.currNode.children.forEach(function (node) {
if (this._currNode !== null) {
this._currNode.children.forEach(function (node) {
node.context.vpa._cancelUpdate();
});
}
if (this.nextNode !== null) {
this.nextNode.children.forEach(function (node) {
if (this._nextNode !== null) {
this._nextNode.children.forEach(function (node) {
node.context.vpa._cancelUpdate();

@@ -754,21 +761,28 @@ });

this.logger.trace(`cancelUpdate(nextNode:%s)`, this.nextNode);
if(__DEV__) trace(this._logger, Events.vpaCancelUpdate, this._nextNode);
switch (this.currState) {
let currentDeactivationPromise: void | Promise<void> | null = null;
let nextDeactivationPromise: void | Promise<void> | null = null;
switch (this._currState) {
case State.currIsEmpty:
case State.currIsActive:
this._currTransition = null;
break;
case State.currCanUnload:
case State.currCanUnloadDone:
this.currState = State.currIsActive;
this._currState = State.currIsActive;
this._currTransition = null;
break;
case State.currUnload:
case State.currUnloadDone:
case State.currDeactivate:
this.currState = State.currIsEmpty;
this.curCA = null;
this.currTransition = null;
currentDeactivationPromise = onResolve(this._curCA?._deactivate(null, this.hostController), () => {
this._curCA?._dispose();
this._currState = State.currIsEmpty;
this._curCA = null;
});
break;
}
switch (this.nextState) {
switch (this._nextState) {
case State.nextIsEmpty:

@@ -778,15 +792,14 @@ case State.nextIsScheduled:

case State.nextCanLoadDone:
this.nextNode = null;
this.nextState = State.nextIsEmpty;
this._nextNode = null;
this._nextState = State.nextIsEmpty;
break;
case State.nextLoad:
case State.nextLoadDone:
case State.nextActivate: {
this._cancellationPromise = onResolve(this.nextCA?._deactivate(null, this.hostController), () => {
this.nextCA?._dispose();
this.$plan = 'replace';
this.nextState = State.nextIsEmpty;
this.nextCA = null;
this.nextNode = null;
this.currTransition = null;
this._cancellationPromise = null;
nextDeactivationPromise = onResolve(this._nextCA?._deactivate(null, this.hostController), () => {
this._nextCA?._dispose();
this._$plan = 'replace';
this._nextState = State.nextIsEmpty;
this._nextCA = null;
this._nextNode = null;
});

@@ -796,2 +809,9 @@ break;

}
if (currentDeactivationPromise !== null && nextDeactivationPromise !== null) {
this._cancellationPromise = onResolve(onResolveAll(currentDeactivationPromise, nextDeactivationPromise), () => {
this._currTransition = null;
this._cancellationPromise = null;
});
}
}

@@ -801,9 +821,9 @@

public _endTransition(): void {
if (this.currNode !== null) {
this.currNode.children.forEach(function (node) {
if (this._currNode !== null) {
this._currNode.children.forEach(function (node) {
node.context.vpa._endTransition();
});
}
if (this.nextNode !== null) {
this.nextNode.children.forEach(function (node) {
if (this._nextNode !== null) {
this._nextNode.children.forEach(function (node) {
node.context.vpa._endTransition();

@@ -813,13 +833,13 @@ });

if (this.currTransition !== null) {
ensureTransitionHasNotErrored(this.currTransition);
switch (this.nextState) {
if (this._currTransition !== null) {
const logger = /*@__PURE__*/ this._logger.scopeTo('endTransition()');
ensureTransitionHasNotErrored(this._currTransition);
switch (this._nextState) {
case State.nextIsEmpty:
switch (this.currState) {
switch (this._currState) {
case State.currIsEmpty:
case State.currDeactivate:
this.logger.trace(`endTransition() - setting currState to State.nextIsEmpty at %s`, this);
this.currState = State.currIsEmpty;
this.curCA = null;
if(__DEV__) trace(logger, Events.vpaEndTransitionEmptyCurr, this);
this._currState = State.currIsEmpty;
this._curCA = null;
break;

@@ -831,20 +851,18 @@ default:

case State.nextActivate:
switch (this.currState) {
switch (this._currState) {
case State.currIsEmpty:
case State.currDeactivate:
switch (this.$plan) {
switch (this._$plan) {
case 'none':
case 'invoke-lifecycles':
this.logger.trace(`endTransition() - setting currState to State.currIsActive at %s`, this);
this.currState = State.currIsActive;
if (__DEV__) trace(logger, Events.vpaEndTransitionActiveCurrLifecycle, this);
this._currState = State.currIsActive;
break;
case 'replace':
this.logger.trace(`endTransition() - setting currState to State.currIsActive and reassigning curCA at %s`, this);
this.currState = State.currIsActive;
this.curCA = this.nextCA;
if (__DEV__) trace(logger, Events.vpaEndTransitionActiveCurrReplace, this);
this._currState = State.currIsActive;
this._curCA = this._nextCA;
break;
}
this.currNode = this.nextNode!;
this._currNode = this._nextNode!;
break;

@@ -859,12 +877,13 @@ default:

this.$plan = 'replace';
this.nextState = State.nextIsEmpty;
this.nextNode = null;
this.nextCA = null;
this.currTransition = null;
this._$plan = 'replace';
this._nextState = State.nextIsEmpty;
this._nextNode = null;
this._nextCA = null;
this._currTransition = null;
}
}
// Should not be adjust for DEV as it is also used of logging in production build.
public toString(): string {
return `VPA(state:${this.$state},plan:'${this.$plan}',n:${this.nextNode},c:${this.currNode},viewport:${this.viewport})`;
return `VPA(state:${$state(this._state)},plan:'${this._$plan}',n:${this._nextNode},c:${this._currNode},viewport:${this.viewport})`;
}

@@ -874,4 +893,4 @@

public _dispose(): void {
this.logger.trace(`dispose() - disposing %s`, this);
this.curCA?._dispose();
if (__DEV__) trace(this._logger, Events.vpaDispose, this);
this._curCA?._dispose();
}

@@ -881,3 +900,3 @@

private _unexpectedState(label: string): never {
throw new Error(`Unexpected state at ${label} of ${this}`);
throw new Error(getMessage(Events.vpaUnexpectedState, label, this));
}

@@ -887,5 +906,3 @@ }

function ensureGuardsResultIsTrue(vpa: ViewportAgent, tr: Transition): void {
if (tr.guardsResult !== true) {
throw new Error(`Unexpected guardsResult ${tr.guardsResult} at ${vpa}`);
}
if (tr.guardsResult !== true) throw new Error(getMessage(Events.vpaUnexpectedGuardsResult, tr.guardsResult, vpa));
}

@@ -892,0 +909,0 @@

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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc