diff --git a/goldens/public-api/router/errors.md b/goldens/public-api/router/errors.md index ee4961e8c8a75..91ca86d2f1d14 100644 --- a/goldens/public-api/router/errors.md +++ b/goldens/public-api/router/errors.md @@ -13,6 +13,8 @@ export const enum RuntimeErrorCode { // (undocumented) INVALID_DOUBLE_DOTS = 4005, // (undocumented) + INVALID_ROOT_URL_SEGMENT = 4015, + // (undocumented) INVALID_ROUTE_CONFIG = 4014, // (undocumented) MISPLACED_OUTLETS_COMMAND = 4004, diff --git a/goldens/public-api/router/index.md b/goldens/public-api/router/index.md index 6b6a41617d5c1..18ad0f798e939 100644 --- a/goldens/public-api/router/index.md +++ b/goldens/public-api/router/index.md @@ -1033,6 +1033,10 @@ export abstract class UrlSerializer { // @public export class UrlTree { + constructor( + root?: UrlSegmentGroup, + queryParams?: Params, + fragment?: string | null); fragment: string | null; // (undocumented) get queryParamMap(): ParamMap; diff --git a/packages/router/src/errors.ts b/packages/router/src/errors.ts index a8c95998ebcde..1efbec6695239 100644 --- a/packages/router/src/errors.ts +++ b/packages/router/src/errors.ts @@ -25,4 +25,5 @@ export const enum RuntimeErrorCode { OUTLET_NOT_ACTIVATED = 4012, OUTLET_ALREADY_ACTIVATED = 4013, INVALID_ROUTE_CONFIG = 4014, + INVALID_ROOT_URL_SEGMENT = 4015, } diff --git a/packages/router/src/router.ts b/packages/router/src/router.ts index 9bb35101f50d2..f6e35fb39fdd7 100644 --- a/packages/router/src/router.ts +++ b/packages/router/src/router.ts @@ -32,7 +32,7 @@ import {ChildrenOutletContexts} from './router_outlet_context'; import {ActivatedRoute, ActivatedRouteSnapshot, createEmptyState, RouterState, RouterStateSnapshot} from './router_state'; import {Params} from './shared'; import {DefaultUrlHandlingStrategy, UrlHandlingStrategy} from './url_handling_strategy'; -import {containsTree, createEmptyUrlTree, IsActiveMatchOptions, isUrlTree, UrlSerializer, UrlTree} from './url_tree'; +import {containsTree, IsActiveMatchOptions, isUrlTree, UrlSerializer, UrlTree} from './url_tree'; import {flatten} from './utils/collection'; import {standardizeConfig, validateConfig} from './utils/config'; import {Checks, getAllRouteGuards} from './utils/preactivation'; @@ -582,7 +582,7 @@ export class Router { this.isNgZoneEnabled = ngZone instanceof NgZone && NgZone.isInAngularZone(); this.resetConfig(config); - this.currentUrlTree = createEmptyUrlTree(); + this.currentUrlTree = new UrlTree(); this.rawUrlTree = this.currentUrlTree; this.browserUrlTree = this.currentUrlTree; diff --git a/packages/router/src/url_tree.ts b/packages/router/src/url_tree.ts index 77e986b7d749d..84a8d693b5030 100644 --- a/packages/router/src/url_tree.ts +++ b/packages/router/src/url_tree.ts @@ -14,10 +14,6 @@ import {equalArraysOrString, forEach, shallowEqual} from './utils/collection'; const NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode; -export function createEmptyUrlTree() { - return new UrlTree(new UrlSegmentGroup([], {}), {}, null); -} - /** * A set of options which specify how to determine if a `UrlTree` is active, given the `UrlTree` * for the current router state. @@ -196,14 +192,22 @@ export class UrlTree { // TODO(issue/24571): remove '!'. _queryParamMap!: ParamMap; - /** @internal */ constructor( /** The root segment group of the URL tree */ - public root: UrlSegmentGroup, + public root: UrlSegmentGroup = new UrlSegmentGroup([], {}), /** The query params of the URL */ - public queryParams: Params, + public queryParams: Params = {}, /** The fragment of the URL */ - public fragment: string|null) {} + public fragment: string|null = null) { + if (NG_DEV_MODE) { + if (root.segments.length > 0) { + throw new RuntimeError( + RuntimeErrorCode.INVALID_ROOT_URL_SEGMENT, + 'The root `UrlSegmentGroup` should not contain `segments`. ' + + 'Instead, these segments belong in the `children` so they can be associated with a named outlet.'); + } + } + } get queryParamMap(): ParamMap { if (!this._queryParamMap) {