Skip to content

Commit

Permalink
perf(core): Make PlatformLocation tree-shakable
Browse files Browse the repository at this point in the history
Convert `PlatformLocation` into a tree-shakable provider
  • Loading branch information
mhevery committed Aug 15, 2019
1 parent 3cf2005 commit 2fc9b4c
Show file tree
Hide file tree
Showing 73 changed files with 182 additions and 202 deletions.
6 changes: 1 addition & 5 deletions packages/common/src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
* @description
* Entry point for all public APIs of the common package.
*/
export * from './private_export';
export * from './location/index';
export {formatDate} from './i18n/format_date';
export {formatCurrency, formatNumber, formatPercent} from './i18n/format_number';
Expand All @@ -26,8 +27,3 @@ export {DeprecatedDatePipe, DeprecatedCurrencyPipe, DeprecatedDecimalPipe, Depre
export {PLATFORM_BROWSER_ID as ɵPLATFORM_BROWSER_ID, PLATFORM_SERVER_ID as ɵPLATFORM_SERVER_ID, PLATFORM_WORKER_APP_ID as ɵPLATFORM_WORKER_APP_ID, PLATFORM_WORKER_UI_ID as ɵPLATFORM_WORKER_UI_ID, isPlatformBrowser, isPlatformServer, isPlatformWorkerApp, isPlatformWorkerUi} from './platform_id';
export {VERSION} from './version';
export {ViewportScroller, NullViewportScroller as ɵNullViewportScroller} from './viewport_scroller';

export {NgClassImplProvider__POST_R3__ as ɵNgClassImplProvider__POST_R3__, NgClassR2Impl as ɵNgClassR2Impl, NgClassImpl as ɵNgClassImpl} from './directives/ng_class_impl';
export {NgStyleImplProvider__POST_R3__ as ɵNgStyleImplProvider__POST_R3__, NgStyleR2Impl as ɵNgStyleR2Impl, NgStyleImpl as ɵNgStyleImpl} from './directives/ng_style_impl';
export {ngStyleDirectiveDef__POST_R3__ as ɵngStyleDirectiveDef__POST_R3__} from './directives/ng_style';
export {ngClassDirectiveDef__POST_R3__ as ɵngClassDirectiveDef__POST_R3__} from './directives/ng_class';
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {Type} from '@angular/core';

let _DOM: DomAdapter = null !;

export function getDOM() {
export function getDOM(): DomAdapter {
return _DOM;
}

Expand Down
10 changes: 5 additions & 5 deletions packages/common/src/location/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/

export * from './platform_location';
export * from './location_strategy';
export * from './hash_location_strategy';
export * from './path_location_strategy';
export * from './location';
export {HashLocationStrategy} from './hash_location_strategy';
export {Location, PopStateEvent} from './location';
export {APP_BASE_HREF, LocationStrategy} from './location_strategy';
export {PathLocationStrategy} from './path_location_strategy';
export {PlatformLocation} from './platform_location';
2 changes: 1 addition & 1 deletion packages/common/src/location/location.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export interface PopStateEvent {
*
* @publicApi
*/
@Injectable()
@Injectable({providedIn: 'root'})
export class Location {
/** @internal */
_subject: EventEmitter<any> = new EventEmitter();
Expand Down
13 changes: 12 additions & 1 deletion packages/common/src/location/location_strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {InjectionToken} from '@angular/core';
import {Injectable, InjectionToken} from '@angular/core';
import {LocationChangeListener} from './platform_location';

/**
Expand All @@ -26,6 +26,10 @@ import {LocationChangeListener} from './platform_location';
*
* @publicApi
*/
@Injectable({
providedIn: 'root',
useFactory: provideLocationStrategy,
})
export abstract class LocationStrategy {
abstract path(includeHash?: boolean): string;
abstract prepareExternalUrl(internal: string): string;
Expand All @@ -37,6 +41,13 @@ export abstract class LocationStrategy {
abstract getBaseHref(): string;
}

export function provideLocationStrategy() {
throw new Error(
ngDevMode ?
`'LocationStrategy' needs to be configured. Did you forget to include 'LocationUpgradeModule' or 'RouterModule'?` :
`Configure 'LocationStrategy'`);
}


/**
* A predefined [DI token](guide/glossary#di-token) for the base href
Expand Down
78 changes: 77 additions & 1 deletion packages/common/src/location/platform_location.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
* found in the LICENSE file at https://angular.io/license
*/

import {InjectionToken} from '@angular/core';
import {Inject, Injectable, InjectionToken, forwardRef} from '@angular/core';
import {getDOM} from '../dom_adapter';
import {DOCUMENT} from '../dom_tokens';

/**
* This class should not be used directly by an application developer. Instead, use
* {@link Location}.
Expand All @@ -29,6 +32,7 @@ import {InjectionToken} from '@angular/core';
*
* @publicApi
*/
@Injectable({providedIn: 'root', useClass: forwardRef(() => BrowserPlatformLocation)})
export abstract class PlatformLocation {
abstract getBaseHrefFromDOM(): string;
abstract getState(): unknown;
Expand Down Expand Up @@ -75,3 +79,75 @@ export interface LocationChangeEvent {
* @publicApi
*/
export interface LocationChangeListener { (event: LocationChangeEvent): any; }



/**
* `PlatformLocation` encapsulates all of the direct calls to platform APIs.
* This class should not be used directly by an application developer. Instead, use
* {@link Location}.
*/
@Injectable()
export class BrowserPlatformLocation extends PlatformLocation {
// TODO(issue/24571): remove '!'.
public readonly location !: Location;
// TODO(issue/24571): remove '!'.
private _history !: History;

constructor(@Inject(DOCUMENT) private _doc: any) {
super();
this._init();
}

// This is moved to its own method so that `MockPlatformLocationStrategy` can overwrite it
/** @internal */
_init() {
(this as{location: Location}).location = getDOM().getLocation();
this._history = getDOM().getHistory();
}

getBaseHrefFromDOM(): string { return getDOM().getBaseHref(this._doc) !; }

onPopState(fn: LocationChangeListener): void {
getDOM().getGlobalEventTarget(this._doc, 'window').addEventListener('popstate', fn, false);
}

onHashChange(fn: LocationChangeListener): void {
getDOM().getGlobalEventTarget(this._doc, 'window').addEventListener('hashchange', fn, false);
}

get href(): string { return this.location.href; }
get protocol(): string { return this.location.protocol; }
get hostname(): string { return this.location.hostname; }
get port(): string { return this.location.port; }
get pathname(): string { return this.location.pathname; }
get search(): string { return this.location.search; }
get hash(): string { return this.location.hash; }
set pathname(newPath: string) { this.location.pathname = newPath; }

pushState(state: any, title: string, url: string): void {
if (supportsState()) {
this._history.pushState(state, title, url);
} else {
this.location.hash = url;
}
}

replaceState(state: any, title: string, url: string): void {
if (supportsState()) {
this._history.replaceState(state, title, url);
} else {
this.location.hash = url;
}
}

forward(): void { this._history.forward(); }

back(): void { this._history.back(); }

getState(): unknown { return this._history.state; }
}

export function supportsState(): boolean {
return !!window.history.pushState;
}
14 changes: 14 additions & 0 deletions packages/common/src/private_export.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

export {ngClassDirectiveDef__POST_R3__ as ɵngClassDirectiveDef__POST_R3__} from './directives/ng_class';
export {NgClassImpl as ɵNgClassImpl, NgClassImplProvider__POST_R3__ as ɵNgClassImplProvider__POST_R3__, NgClassR2Impl as ɵNgClassR2Impl} from './directives/ng_class_impl';
export {ngStyleDirectiveDef__POST_R3__ as ɵngStyleDirectiveDef__POST_R3__} from './directives/ng_style';
export {NgStyleImpl as ɵNgStyleImpl, NgStyleImplProvider__POST_R3__ as ɵNgStyleImplProvider__POST_R3__, NgStyleR2Impl as ɵNgStyleR2Impl} from './directives/ng_style_impl';
export {DomAdapter as ɵDomAdapter, getDOM as ɵgetDOM, setRootDomAdapter as ɵsetRootDomAdapter} from './dom_adapter';
export {BrowserPlatformLocation as ɵBrowserPlatformLocation} from './location/platform_location';
2 changes: 1 addition & 1 deletion packages/common/test/directives/ng_if_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
*/

import {CommonModule} from '@angular/common';
import {getDOM} from '@angular/common/src/dom_adapter';
import {Component} from '@angular/core';
import {ComponentFixture, TestBed, async} from '@angular/core/testing';
import {By} from '@angular/platform-browser/src/dom/debug/by';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {expect} from '@angular/platform-browser/testing/src/matchers';

{
Expand Down
2 changes: 1 addition & 1 deletion packages/common/test/directives/non_bindable_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
* found in the LICENSE file at https://angular.io/license
*/

import {getDOM} from '@angular/common/src/dom_adapter';
import {Component, Directive} from '@angular/core';
import {ElementRef} from '@angular/core/src/linker/element_ref';
import {ComponentFixture, TestBed, async} from '@angular/core/testing';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {expect} from '@angular/platform-browser/testing/src/matchers';

{
Expand Down
2 changes: 1 addition & 1 deletion packages/common/test/pipes/async_pipe_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
*/

import {AsyncPipe} from '@angular/common';
import {getDOM} from '@angular/common/src/dom_adapter';
import {EventEmitter, WrappedValue} from '@angular/core';
import {AsyncTestCompleter, beforeEach, describe, expect, inject, it} from '@angular/core/testing/src/testing_internal';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {browserDetection} from '@angular/platform-browser/testing/src/browser_util';

import {SpyChangeDetectorRef} from '../spies';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2785,7 +2785,7 @@ describe('compiler compliance', () => {
$r3$.ɵɵelementStart(1, "div");
$r3$.ɵɵtext(2);
$r3$.ɵɵelementEnd();
$r3$.ɵɵelementStart(3, "ul");
$r3$.��ɵelementStart(3, "ul");
$r3$.ɵɵtemplate(4, MyComponent_li_1_li_4_Template, 2, 2, "li", $t4_attrs$);
$r3$.ɵɵelementEnd();
$r3$.ɵɵelementEnd();
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler/test/selector/selector_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/

import {getDOM} from '@angular/common/src/dom_adapter';
import {CssSelector, SelectorMatcher} from '@angular/compiler/src/selector';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {el} from '@angular/platform-browser/testing/src/browser_util';

{
Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/animation/animation_integration_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
import {AUTO_STYLE, AnimationEvent, AnimationOptions, animate, animateChild, group, keyframes, query, state, style, transition, trigger, ɵPRE_STYLE as PRE_STYLE} from '@angular/animations';
import {AnimationDriver, ɵAnimationEngine, ɵNoopAnimationDriver as NoopAnimationDriver} from '@angular/animations/browser';
import {MockAnimationDriver, MockAnimationPlayer} from '@angular/animations/browser/testing';
import {getDOM} from '@angular/common/src/dom_adapter';
import {ChangeDetectorRef, Component, HostBinding, HostListener, Inject, RendererFactory2, ViewChild} from '@angular/core';
import {TestBed, fakeAsync, flushMicrotasks} from '@angular/core/testing';
import {ɵDomRendererFactory2} from '@angular/platform-browser';
import {ANIMATION_MODULE_TYPE, BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {ivyEnabled, modifiedInIvy} from '@angular/private/testing';

const DEFAULT_NAMESPACE_ID = 'id';
Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/application_ref_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
*/

import {DOCUMENT} from '@angular/common';
import {getDOM} from '@angular/common/src/dom_adapter';
import {ResourceLoader} from '@angular/compiler';
import {APP_BOOTSTRAP_LISTENER, APP_INITIALIZER, Compiler, CompilerFactory, Component, InjectionToken, LOCALE_ID, NgModule, NgZone, PlatformRef, TemplateRef, Type, ViewChild, ViewContainerRef} from '@angular/core';
import {ApplicationRef} from '@angular/core/src/application_ref';
import {ErrorHandler} from '@angular/core/src/error_handler';
import {ComponentRef} from '@angular/core/src/linker/component_factory';
import {getLocaleId} from '@angular/core/src/render3';
import {BrowserModule} from '@angular/platform-browser';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {dispatchEvent} from '@angular/platform-browser/testing/src/browser_util';
import {expect} from '@angular/platform-browser/testing/src/matchers';
import {onlyInIvy} from '@angular/private/testing';
Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/debug/debug_node_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@


import {CommonModule, NgIfContext} from '@angular/common';
import {getDOM} from '@angular/common/src/dom_adapter';
import {Component, DebugNode, Directive, ElementRef, EmbeddedViewRef, EventEmitter, HostBinding, Injectable, Input, NO_ERRORS_SCHEMA, OnInit, Output, Renderer2, TemplateRef, ViewChild, ViewContainerRef} from '@angular/core';
import {ComponentFixture, TestBed, async} from '@angular/core/testing';
import {By} from '@angular/platform-browser/src/dom/debug/by';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {expect} from '@angular/platform-browser/testing/src/matchers';
import {ivyEnabled} from '@angular/private/testing';

Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/dom/dom_adapter_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/

import {getDOM} from '@angular/common/src/dom_adapter';
import {beforeEach, describe, expect, it} from '@angular/core/testing/src/testing_internal';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {el, stringifyElement} from '@angular/platform-browser/testing/src/browser_util';

{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
* found in the LICENSE file at https://angular.io/license
*/

import {getDOM} from '@angular/common/src/dom_adapter';
import {ResourceLoader, UrlResolver} from '@angular/compiler';
import {MockResourceLoader} from '@angular/compiler/testing';
import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, DebugElement, Directive, DoCheck, EventEmitter, HostBinding, Inject, Injectable, Input, OnChanges, OnDestroy, OnInit, Output, Pipe, PipeTransform, Provider, RenderComponentType, Renderer, RendererFactory2, RendererType2, RootRenderer, SimpleChange, SimpleChanges, TemplateRef, Type, ViewChild, ViewContainerRef, WrappedValue} from '@angular/core';
import {ComponentFixture, TestBed, fakeAsync} from '@angular/core/testing';
import {By} from '@angular/platform-browser/src/dom/debug/by';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {expect} from '@angular/platform-browser/testing/src/matchers';
import {ivyEnabled, modifiedInIvy, onlyInIvy} from '@angular/private/testing';

Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/linker/integration_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import {CommonModule, DOCUMENT} from '@angular/common';
import {getDOM} from '@angular/common/src/dom_adapter';
import {Compiler, ComponentFactory, ComponentRef, ErrorHandler, EventEmitter, Host, Inject, Injectable, InjectionToken, Injector, NO_ERRORS_SCHEMA, NgModule, NgModuleRef, OnDestroy, SkipSelf, ViewRef, ɵivyEnabled as ivyEnabled} from '@angular/core';
import {ChangeDetectionStrategy, ChangeDetectorRef, PipeTransform} from '@angular/core/src/change_detection/change_detection';
import {getDebugContext} from '@angular/core/src/errors';
Expand All @@ -18,7 +19,6 @@ import {ViewContainerRef} from '@angular/core/src/linker/view_container_ref';
import {EmbeddedViewRef} from '@angular/core/src/linker/view_ref';
import {Attribute, Component, ContentChildren, Directive, HostBinding, HostListener, Input, Output, Pipe} from '@angular/core/src/metadata';
import {TestBed, async, fakeAsync, getTestBed, tick} from '@angular/core/testing';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {dispatchEvent, el} from '@angular/platform-browser/testing/src/browser_util';
import {expect} from '@angular/platform-browser/testing/src/matchers';
import {modifiedInIvy, obsoleteInIvy, onlyInIvy} from '@angular/private/testing';
Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/linker/ng_container_integration_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
*/


import {getDOM} from '@angular/common/src/dom_adapter';
import {AfterContentInit, AfterViewInit, Component, ContentChildren, Directive, Input, QueryList, ViewChildren, ɵivyEnabled as ivyEnabled} from '@angular/core';
import {TestBed} from '@angular/core/testing';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {expect} from '@angular/platform-browser/testing/src/matchers';
import {modifiedInIvy} from '@angular/private/testing';

Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/linker/projection_integration_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
*/

import {CommonModule} from '@angular/common';
import {getDOM} from '@angular/common/src/dom_adapter';
import {Component, ComponentFactoryResolver, ComponentRef, Directive, ElementRef, Injector, Input, NO_ERRORS_SCHEMA, NgModule, OnInit, TemplateRef, ViewChild, ViewContainerRef, ViewEncapsulation} from '@angular/core';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {By} from '@angular/platform-browser/src/dom/debug/by';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {expect} from '@angular/platform-browser/testing/src/matchers';
import {modifiedInIvy} from '@angular/private/testing';

Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/linker/query_list_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
* found in the LICENSE file at https://angular.io/license
*/

import {getDOM} from '@angular/common/src/dom_adapter';
import {iterateListLike} from '@angular/core/src/change_detection/change_detection_util';
import {QueryList} from '@angular/core/src/linker/query_list';
import {fakeAsync, tick} from '@angular/core/testing';
import {beforeEach, describe, expect, it} from '@angular/core/testing/src/testing_internal';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';

{
describe('QueryList', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/linker/regression_integration_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
*/

import {DOCUMENT} from '@angular/common';
import {getDOM} from '@angular/common/src/dom_adapter';
import {ANALYZE_FOR_ENTRY_COMPONENTS, ApplicationRef, Component, ComponentRef, ContentChild, Directive, ErrorHandler, EventEmitter, HostListener, InjectionToken, Injector, Input, NgModule, NgModuleRef, NgZone, Output, Pipe, PipeTransform, Provider, QueryList, Renderer2, SimpleChanges, TemplateRef, ViewChild, ViewChildren, ViewContainerRef, destroyPlatform, ɵivyEnabled as ivyEnabled} from '@angular/core';
import {TestBed, fakeAsync, inject, tick} from '@angular/core/testing';
import {BrowserModule, By} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {expect} from '@angular/platform-browser/testing/src/matchers';
import {modifiedInIvy, onlyInIvy} from '@angular/private/testing';

Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/linker/security_integration_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
* found in the LICENSE file at https://angular.io/license
*/

import {getDOM} from '@angular/common/src/dom_adapter';
import {Component, Directive, HostBinding, Input, NO_ERRORS_SCHEMA, ɵivyEnabled as ivyEnabled} from '@angular/core';
import {ComponentFixture, TestBed, getTestBed} from '@angular/core/testing';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {DomSanitizer} from '@angular/platform-browser/src/security/dom_sanitization_service';
import {modifiedInIvy, onlyInIvy} from '@angular/private/testing';

Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/render3/content_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1073,7 +1073,7 @@ describe('content projection', () => {
{
ɵɵelementStart(1, 'span', ['class', 'toFirst']);
{ ɵɵtext(2, '1'); }
ɵɵelementEnd();
ɵ��elementEnd();
ɵɵelementStart(3, 'span', ['class', 'toSecond']);
{ ɵɵtext(4, '2'); }
ɵɵelementEnd();
Expand Down
Loading

0 comments on commit 2fc9b4c

Please sign in to comment.