perf(common): remove unused methods from DomAdapter (#41102)

The `DomAdapter` is present in all Angular apps and its methods aren't tree shakeable.
These changes remove the methods that either aren't being used anymore or were only
used by our own tests. Note that these changes aren't breaking, because the adapter
is an internal API.

The following methods were removed:
* `getProperty` - only used within our own tests.
* `log` - Guaranteed to be defined on `console`.
* `logGroup` and `logGroupEnd` - Only used in one place. It was in the DomAdapter for built-in null checking.
* `logGroupEnd` - Only used in one place. It was placed in the DomAdapter for built in null checking.
* `performanceNow` - Only used in one place that has to be invoked through the browser console.
* `supportsCookies` - Unused.
* `getCookie` - Unused.
* `getLocation` and `getHistory` - Only used in one place which appears to have access to the DOM
already, because it had direct accesses to `window`. Furthermore, even if this was being used
in a non-browser context already, the `DominoAdapter` was set up to throw an error.

The following APIs were changed to be more compact:
* `supportsDOMEvents` - Changed to a readonly property.
* `remove` - No longer returns the removed node.

PR Close #41102
This commit is contained in:
Kristiyan Kostadinov 2021-03-10 08:20:40 +01:00 committed by Andrew Kushnir
parent 4c79b8a644
commit 3c66b100dd
21 changed files with 84 additions and 224 deletions

View File

@ -3,7 +3,7 @@
"master": {
"uncompressed": {
"runtime-es2015": 1485,
"main-es2015": 138937,
"main-es2015": 138189,
"polyfills-es2015": 36964
}
}
@ -21,7 +21,7 @@
"master": {
"uncompressed": {
"runtime-es2015": 1485,
"main-es2015": 144899,
"main-es2015": 144151,
"polyfills-es2015": 36964
}
}
@ -30,7 +30,7 @@
"master": {
"uncompressed": {
"runtime-es2015": 1485,
"main-es2015": 137236,
"main-es2015": 136546,
"polyfills-es2015": 37641
}
}
@ -39,7 +39,7 @@
"master": {
"uncompressed": {
"runtime-es2015": 2285,
"main-es2015": 241085,
"main-es2015": 240352,
"polyfills-es2015": 36975,
"5-es2015": 753
}
@ -49,7 +49,7 @@
"master": {
"uncompressed": {
"runtime-es2015": 2289,
"main-es2015": 216925,
"main-es2015": 216267,
"polyfills-es2015": 36723,
"5-es2015": 781
}
@ -59,7 +59,7 @@
"master": {
"uncompressed": {
"runtime-es2015": 1485,
"main-es2015": 169047,
"main-es2015": 168534,
"polyfills-es2015": 36975
}
}

View File

@ -31,16 +31,11 @@ export function setRootDomAdapter(adapter: DomAdapter) {
*/
export abstract class DomAdapter {
// Needs Domino-friendly test utility
abstract getProperty(el: Element, name: string): any;
abstract dispatchEvent(el: any, evt: any): any;
// Used by router
abstract log(error: any): any;
abstract logGroup(error: any): any;
abstract logGroupEnd(): any;
abstract readonly supportsDOMEvents: boolean;
// Used by Meta
abstract remove(el: any): Node;
abstract remove(el: any): void;
abstract createElement(tagName: any, doc?: any): HTMLElement;
abstract createHtmlDocument(): HTMLDocument;
abstract getDefaultDocument(): Document;
@ -53,25 +48,17 @@ export abstract class DomAdapter {
// Used by KeyEventsPlugin
abstract onAndCancel(el: any, evt: any, listener: any): Function;
abstract supportsDOMEvents(): boolean;
// Used by PlatformLocation and ServerEventManagerPlugin
abstract getGlobalEventTarget(doc: Document, target: string): any;
// Used by PlatformLocation
abstract getHistory(): History;
abstract getLocation():
any; /** This is the ambient Location definition, NOT Location from @angular/common. */
abstract getBaseHref(doc: Document): string|null;
abstract resetBaseElement(): void;
// TODO: remove dependency in DefaultValueAccessor
abstract getUserAgent(): string;
// Used by AngularProfiler
abstract performanceNow(): number;
// Used by CookieXSRFStrategy
abstract supportsCookies(): boolean;
// Used in the legacy @angular/http package which has some usage in g3.
abstract getCookie(name: string): string|null;
}

View File

@ -120,8 +120,8 @@ export class BrowserPlatformLocation extends PlatformLocation {
// 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();
(this as {location: Location}).location = window.location;
this._history = window.history;
}
getBaseHrefFromDOM(): string {

View File

@ -59,7 +59,7 @@ class SomeComponent {
const errorHandler = new ErrorHandler();
(errorHandler as any)._console = mockConsole as any;
const platformModule = getDOM().supportsDOMEvents() ?
const platformModule = getDOM().supportsDOMEvents ?
BrowserModule :
require('@angular/platform-server').ServerModule;

View File

@ -14,7 +14,7 @@ import {isTextNode} from '@angular/platform-browser/testing/src/browser_util';
describe('dom adapter', () => {
let defaultDoc: any;
beforeEach(() => {
defaultDoc = getDOM().supportsDOMEvents() ? document : getDOM().createHtmlDocument();
defaultDoc = getDOM().supportsDOMEvents ? document : getDOM().createHtmlDocument();
});
it('should be able to create text nodes and use them with the other APIs', () => {
@ -36,7 +36,7 @@ import {isTextNode} from '@angular/platform-browser/testing/src/browser_util';
expect(() => getDOM().remove(d)).not.toThrow();
});
if (getDOM().supportsDOMEvents()) {
if (getDOM().supportsDOMEvents) {
describe('getBaseHref', () => {
beforeEach(() => getDOM().resetBaseElement());

View File

@ -109,8 +109,7 @@ function declareTests(config?: {useJit: boolean}) {
fixture.componentInstance.ctxProp = 'Hello World!';
fixture.detectChanges();
expect(getDOM().getProperty(fixture.debugElement.children[0].nativeElement, 'id'))
.toEqual('Hello World!');
expect(fixture.debugElement.children[0].nativeElement.id).toEqual('Hello World!');
});
it('should consume binding to aria-* attributes', () => {
@ -168,13 +167,11 @@ function declareTests(config?: {useJit: boolean}) {
const fixture = TestBed.createComponent(MyComp);
fixture.detectChanges();
expect(getDOM().getProperty(fixture.debugElement.children[0].nativeElement, 'tabIndex'))
.toEqual(0);
expect(fixture.debugElement.children[0].nativeElement.tabIndex).toEqual(0);
fixture.componentInstance.ctxNumProp = 5;
fixture.detectChanges();
expect(getDOM().getProperty(fixture.debugElement.children[0].nativeElement, 'tabIndex'))
.toEqual(5);
expect(fixture.debugElement.children[0].nativeElement.tabIndex).toEqual(5);
});
it('should consume binding to camel-cased properties', () => {
@ -184,13 +181,11 @@ function declareTests(config?: {useJit: boolean}) {
const fixture = TestBed.createComponent(MyComp);
fixture.detectChanges();
expect(getDOM().getProperty(fixture.debugElement.children[0].nativeElement, 'readOnly'))
.toBeFalsy();
expect(fixture.debugElement.children[0].nativeElement.readOnly).toBeFalsy();
fixture.componentInstance.ctxBoolProp = true;
fixture.detectChanges();
expect(getDOM().getProperty(fixture.debugElement.children[0].nativeElement, 'readOnly'))
.toBeTruthy();
expect(fixture.debugElement.children[0].nativeElement.readOnly).toBeTruthy();
});
it('should consume binding to innerHtml', () => {
@ -236,7 +231,7 @@ function declareTests(config?: {useJit: boolean}) {
fixture.debugElement.componentInstance.ctxProp = 'foo';
fixture.detectChanges();
expect(getDOM().getProperty(nativeEl, 'htmlFor')).toBe('foo');
expect(nativeEl.htmlFor).toBe('foo');
});
it('should consume directive watch expression change.', () => {
@ -617,7 +612,7 @@ function declareTests(config?: {useJit: boolean}) {
expect(cmp.numberOfChecks).toEqual(2);
});
if (getDOM().supportsDOMEvents()) {
if (getDOM().supportsDOMEvents) {
it('should allow to destroy a component from within a host event handler',
fakeAsync(() => {
TestBed.configureTestingModule({declarations: [MyComp, [[PushCmpWithHostEvent]]]});
@ -922,7 +917,7 @@ function declareTests(config?: {useJit: boolean}) {
fixture.detectChanges();
expect(getDOM().getProperty(tc.nativeElement, 'id')).toEqual('newId');
expect(tc.nativeElement.id).toEqual('newId');
});
it('should not use template variables for expressions in hostProperties', () => {
@ -996,7 +991,7 @@ function declareTests(config?: {useJit: boolean}) {
if (getDOM().supportsDOMEvents()) {
if (getDOM().supportsDOMEvents) {
it('should support preventing default on render events', () => {
TestBed.configureTestingModule({
declarations:
@ -1881,7 +1876,7 @@ function declareTests(config?: {useJit: boolean}) {
fixture.detectChanges();
const el = fixture.nativeElement.querySelector('span');
expect(getDOM().getProperty(el, 'title')).toEqual('TITLE');
expect(el.title).toEqual('TITLE');
});
});
@ -2097,7 +2092,7 @@ function declareTests(config?: {useJit: boolean}) {
expect(fixture.debugElement.children[0].nativeElement.outerHTML).toContain('my-attr="aaa"');
});
if (getDOM().supportsDOMEvents()) {
if (getDOM().supportsDOMEvents) {
it('should support event decorators', fakeAsync(() => {
TestBed.configureTestingModule({
declarations: [MyComp, DirectiveWithPropDecorators],
@ -2200,7 +2195,7 @@ function declareTests(config?: {useJit: boolean}) {
}));
});
if (getDOM().supportsDOMEvents()) {
if (getDOM().supportsDOMEvents) {
describe('svg', () => {
it('should support svg elements', () => {
TestBed.configureTestingModule({declarations: [MyComp]});
@ -2211,12 +2206,10 @@ function declareTests(config?: {useJit: boolean}) {
const el = fixture.nativeElement;
const svg = el.childNodes[0];
const use = svg.childNodes[0];
expect(getDOM().getProperty(<Element>svg, 'namespaceURI'))
.toEqual('http://www.w3.org/2000/svg');
expect(getDOM().getProperty(<Element>use, 'namespaceURI'))
.toEqual('http://www.w3.org/2000/svg');
expect(svg.namespaceURI).toEqual('http://www.w3.org/2000/svg');
expect(use.namespaceURI).toEqual('http://www.w3.org/2000/svg');
const firstAttribute = getDOM().getProperty(<Element>use, 'attributes')[0];
const firstAttribute = use.attributes[0];
expect(firstAttribute.name).toEqual('xlink:href');
expect(firstAttribute.namespaceURI).toEqual('http://www.w3.org/1999/xlink');
});
@ -2232,12 +2225,9 @@ function declareTests(config?: {useJit: boolean}) {
const svg = el.childNodes[0];
const foreignObject = svg.childNodes[0];
const p = foreignObject.childNodes[0];
expect(getDOM().getProperty(<Element>svg, 'namespaceURI'))
.toEqual('http://www.w3.org/2000/svg');
expect(getDOM().getProperty(<Element>foreignObject, 'namespaceURI'))
.toEqual('http://www.w3.org/2000/svg');
expect(getDOM().getProperty(<Element>p, 'namespaceURI'))
.toEqual('http://www.w3.org/1999/xhtml');
expect(svg.namespaceURI).toEqual('http://www.w3.org/2000/svg');
expect(foreignObject.namespaceURI).toEqual('http://www.w3.org/2000/svg');
expect(p.namespaceURI).toEqual('http://www.w3.org/1999/xhtml');
});
});

View File

@ -508,7 +508,7 @@ describe('projection', () => {
});
}
if (getDOM().supportsDOMEvents()) {
if (getDOM().supportsDOMEvents) {
it('should support non emulated styles', () => {
TestBed.configureTestingModule({declarations: [OtherComp]});
TestBed.overrideComponent(MainComp, {

View File

@ -156,7 +156,7 @@ import {beforeEach, describe, expect, it} from '@angular/core/testing/src/testin
expect(data.length).toBe(0);
});
if (getDOM().supportsDOMEvents()) {
if (getDOM().supportsDOMEvents) {
describe('simple observable interface', () => {
it('should fire callbacks on change', fakeAsync(() => {
let fires = 0;

View File

@ -462,7 +462,7 @@ function declareTestsUsingBootstrap() {
destroyPlatform();
});
if (getDOM().supportsDOMEvents()) {
if (getDOM().supportsDOMEvents) {
// This test needs a real DOM....
it('should keep change detecting if there was an error', (done) => {

View File

@ -49,13 +49,9 @@ function declareTests(config?: {useJit: boolean}) {
});
});
let originalLog: (msg: any) => any;
beforeEach(() => {
originalLog = getDOM().log;
getDOM().log = (msg) => { /* disable logging */ };
});
afterEach(() => {
getDOM().log = originalLog;
// Disable logging for these tests.
spyOn(console, 'log').and.callFake(() => {});
});
describe('events', () => {
@ -128,7 +124,7 @@ function declareTests(config?: {useJit: boolean}) {
cmp.detectChanges();
const div = cmp.debugElement.children[0];
expect(div.injector.get(OnPrefixDir).onclick).toBe(value);
expect(getDOM().getProperty(div.nativeElement, 'onclick')).not.toBe(value);
expect(div.nativeElement.onclick).not.toBe(value);
expect(div.nativeElement.hasAttribute('onclick')).toEqual(false);
});
});
@ -145,7 +141,7 @@ function declareTests(config?: {useJit: boolean}) {
const trusted = sanitizer.bypassSecurityTrustUrl('javascript:alert(1)');
ci.ctxProp = trusted;
fixture.detectChanges();
expect(getDOM().getProperty(e, 'href')).toEqual('javascript:alert(1)');
expect(e.getAttribute('href')).toEqual('javascript:alert(1)');
});
it('should error when using the wrong trusted value', () => {
@ -171,25 +167,21 @@ function declareTests(config?: {useJit: boolean}) {
const ci = fixture.componentInstance;
ci.ctxProp = trusted;
fixture.detectChanges();
expect(getDOM().getProperty(e, 'href')).toMatch(/SafeValue(%20| )must(%20| )use/);
expect(e.href).toMatch(/SafeValue(%20| )must(%20| )use/);
});
});
describe('sanitizing', () => {
function checkEscapeOfHrefProperty(fixture: ComponentFixture<any>, isAttribute: boolean) {
function checkEscapeOfHrefProperty(fixture: ComponentFixture<any>) {
const e = fixture.debugElement.children[0].nativeElement;
const ci = fixture.componentInstance;
ci.ctxProp = 'hello';
fixture.detectChanges();
// In the browser, reading href returns an absolute URL. On the server side,
// it just echoes back the property.
let value = isAttribute ? e.getAttribute('href') : getDOM().getProperty(e, 'href');
expect(value).toMatch(/.*\/?hello$/);
expect(e.getAttribute('href')).toMatch(/.*\/?hello$/);
ci.ctxProp = 'javascript:alert(1)';
fixture.detectChanges();
value = isAttribute ? e.getAttribute('href') : getDOM().getProperty(e, 'href');
expect(value).toEqual('unsafe:javascript:alert(1)');
expect(e.getAttribute('href')).toEqual('unsafe:javascript:alert(1)');
}
it('should escape unsafe properties', () => {
@ -197,7 +189,7 @@ function declareTests(config?: {useJit: boolean}) {
TestBed.overrideComponent(SecuredComponent, {set: {template}});
const fixture = TestBed.createComponent(SecuredComponent);
checkEscapeOfHrefProperty(fixture, false);
checkEscapeOfHrefProperty(fixture);
});
it('should escape unsafe attributes', () => {
@ -205,7 +197,7 @@ function declareTests(config?: {useJit: boolean}) {
TestBed.overrideComponent(SecuredComponent, {set: {template}});
const fixture = TestBed.createComponent(SecuredComponent);
checkEscapeOfHrefProperty(fixture, true);
checkEscapeOfHrefProperty(fixture);
});
it('should escape unsafe properties if they are used in host bindings', () => {
@ -220,7 +212,7 @@ function declareTests(config?: {useJit: boolean}) {
TestBed.overrideComponent(SecuredComponent, {set: {template}});
const fixture = TestBed.createComponent(SecuredComponent);
checkEscapeOfHrefProperty(fixture, false);
checkEscapeOfHrefProperty(fixture);
});
it('should escape unsafe attributes if they are used in host bindings', () => {
@ -235,7 +227,7 @@ function declareTests(config?: {useJit: boolean}) {
TestBed.overrideComponent(SecuredComponent, {set: {template}});
const fixture = TestBed.createComponent(SecuredComponent);
checkEscapeOfHrefProperty(fixture, true);
checkEscapeOfHrefProperty(fixture);
});
modifiedInIvy('Unknown property error thrown during update mode, not creation mode')

View File

@ -87,8 +87,8 @@ const removeEventListener = 'removeEventListener';
Services.checkAndUpdateView(view);
const el = rootNodes[0];
expect(getDOM().getProperty(el, 'title')).toBe('v1');
expect(getDOM().getProperty(el, 'value')).toBe('v2');
expect(el.title).toBe('v1');
expect(el.value).toBe('v2');
});
});
});

View File

@ -12,7 +12,7 @@ import {ArgumentType, initServicesIfNeeded, NodeCheckFn, NodeDef, rootRenderNode
import {TestBed} from '@angular/core/testing';
export function isBrowser() {
return getDOM().supportsDOMEvents();
return getDOM().supportsDOMEvents;
}
export const ARG_TYPE_VALUES = [ArgumentType.Inline, ArgumentType.Dynamic];

View File

@ -7,20 +7,9 @@
*/
import {ɵparseCookieValue as parseCookieValue, ɵsetRootDomAdapter as setRootDomAdapter} from '@angular/common';
import {ɵglobal as global} from '@angular/core';
import {GenericBrowserDomAdapter} from './generic_browser_adapter';
const nodeContains: (this: Node, other: Node) => boolean = (() => {
if (global['Node']) {
return global['Node'].prototype.contains || function(this: Node, node: any) {
return !!(this.compareDocumentPosition(node) & 16);
};
}
return undefined as any;
})();
/**
* A `DomAdapter` powered by full browser DOM APIs.
*
@ -32,27 +21,6 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter {
static makeCurrent() {
setRootDomAdapter(new BrowserDomAdapter());
}
getProperty(el: Node, name: string): any {
return (<any>el)[name];
}
log(error: string): void {
if (window.console) {
window.console.log && window.console.log(error);
}
}
logGroup(error: string): void {
if (window.console) {
window.console.group && window.console.group(error);
}
}
logGroupEnd(): void {
if (window.console) {
window.console.groupEnd && window.console.groupEnd();
}
}
onAndCancel(el: Node, evt: any, listener: any): Function {
el.addEventListener(evt, listener, false);
@ -65,14 +33,10 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter {
dispatchEvent(el: Node, evt: any) {
el.dispatchEvent(evt);
}
remove(node: Node): Node {
remove(node: Node): void {
if (node.parentNode) {
node.parentNode.removeChild(node);
}
return node;
}
getValue(el: any): string {
return el.value;
}
createElement(tagName: string, doc?: Document): HTMLElement {
doc = doc || this.getDefaultDocument();
@ -105,12 +69,6 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter {
}
return null;
}
getHistory(): History {
return window.history;
}
getLocation(): Location {
return window.location;
}
getBaseHref(doc: Document): string|null {
const href = getBaseElementHref();
return href == null ? null : relativePath(href);
@ -121,17 +79,6 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter {
getUserAgent(): string {
return window.navigator.userAgent;
}
performanceNow(): number {
// performance.now() is not available in all browsers, see
// https://caniuse.com/high-resolution-time
return window.performance && window.performance.now ? window.performance.now() :
new Date().getTime();
}
supportsCookies(): boolean {
return true;
}
getCookie(name: string): string|null {
return parseCookieValue(document.cookie, name);
}
@ -139,22 +86,15 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter {
let baseElement: HTMLElement|null = null;
function getBaseElementHref(): string|null {
if (!baseElement) {
baseElement = document.querySelector('base')!;
if (!baseElement) {
return null;
}
}
return baseElement.getAttribute('href');
baseElement = baseElement || document.querySelector('base');
return baseElement ? baseElement.getAttribute('href') : null;
}
// based on urlUtils.js in AngularJS 1
let urlParsingNode: any;
let urlParsingNode: HTMLAnchorElement|undefined;
function relativePath(url: any): string {
if (!urlParsingNode) {
urlParsingNode = document.createElement('a');
}
urlParsingNode = urlParsingNode || document.createElement('a');
urlParsingNode.setAttribute('href', url);
return (urlParsingNode.pathname.charAt(0) === '/') ? urlParsingNode.pathname :
'/' + urlParsingNode.pathname;
const pathName = urlParsingNode.pathname;
return pathName.charAt(0) === '/' ? pathName : `/${pathName}`;
}

View File

@ -17,11 +17,5 @@ import {ɵDomAdapter as DomAdapter} from '@angular/common';
* can introduce XSS risks.
*/
export abstract class GenericBrowserDomAdapter extends DomAdapter {
constructor() {
super();
}
supportsDOMEvents(): boolean {
return true;
}
readonly supportsDOMEvents: boolean = true;
}

View File

@ -6,7 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ɵgetDOM as getDOM} from '@angular/common';
import {ApplicationRef, ComponentRef} from '@angular/core';
import {window} from './browser';
@ -50,13 +49,13 @@ export class AngularProfiler {
if (record && isProfilerAvailable) {
window.console.profile(profileName);
}
const start = getDOM().performanceNow();
const start = performanceNow();
let numTicks = 0;
while (numTicks < 5 || (getDOM().performanceNow() - start) < 500) {
while (numTicks < 5 || (performanceNow() - start) < 500) {
this.appRef.tick();
numTicks++;
}
const end = getDOM().performanceNow();
const end = performanceNow();
if (record && isProfilerAvailable) {
window.console.profileEnd(profileName);
}
@ -67,3 +66,8 @@ export class AngularProfiler {
return new ChangeDetectionPerfRecord(msPerTick, numTicks);
}
}
function performanceNow() {
return window.performance && window.performance.now ? window.performance.now() :
new Date().getTime();
}

View File

@ -273,7 +273,7 @@ function bootstrap(
});
}));
if (getDOM().supportsDOMEvents()) {
if (getDOM().supportsDOMEvents) {
it('should forward the error to promise when bootstrap fails',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const logger = new MockConsole();

View File

@ -21,7 +21,7 @@ let zone: NgZone;
describe('EventManager', () => {
beforeEach(() => {
doc = getDOM().supportsDOMEvents() ? document : getDOM().createHtmlDocument();
doc = getDOM().supportsDOMEvents ? document : getDOM().createHtmlDocument();
zone = new NgZone({});
domEventPlugin = new DomEventsPlugin(doc);
});
@ -337,7 +337,7 @@ describe('EventManager', () => {
it('should only trigger one Change detection when bubbling with shouldCoalesceEventChangeDetection = true',
(done: DoneFn) => {
doc = getDOM().supportsDOMEvents() ? document : getDOM().createHtmlDocument();
doc = getDOM().supportsDOMEvents ? document : getDOM().createHtmlDocument();
zone = new NgZone({shouldCoalesceEventChangeDetection: true});
domEventPlugin = new DomEventsPlugin(doc);
const element = el('<div></div>');
@ -374,7 +374,7 @@ describe('EventManager', () => {
it('should only trigger one Change detection when bubbling with shouldCoalesceRunChangeDetection = true',
(done: DoneFn) => {
doc = getDOM().supportsDOMEvents() ? document : getDOM().createHtmlDocument();
doc = getDOM().supportsDOMEvents ? document : getDOM().createHtmlDocument();
zone = new NgZone({shouldCoalesceRunChangeDetection: true});
domEventPlugin = new DomEventsPlugin(doc);
const element = el('<div></div>');
@ -411,7 +411,7 @@ describe('EventManager', () => {
it('should not drain micro tasks queue too early with shouldCoalesceEventChangeDetection=true',
(done: DoneFn) => {
doc = getDOM().supportsDOMEvents() ? document : getDOM().createHtmlDocument();
doc = getDOM().supportsDOMEvents ? document : getDOM().createHtmlDocument();
zone = new NgZone({shouldCoalesceEventChangeDetection: true});
domEventPlugin = new DomEventsPlugin(doc);
const element = el('<div></div>');
@ -457,7 +457,7 @@ describe('EventManager', () => {
it('should not drain micro tasks queue too early with shouldCoalesceRunChangeDetection=true',
(done: DoneFn) => {
doc = getDOM().supportsDOMEvents() ? document : getDOM().createHtmlDocument();
doc = getDOM().supportsDOMEvents ? document : getDOM().createHtmlDocument();
zone = new NgZone({shouldCoalesceRunChangeDetection: true});
domEventPlugin = new DomEventsPlugin(doc);
const element = el('<div></div>');

View File

@ -10,10 +10,6 @@ const domino = require('domino');
import {ɵBrowserDomAdapter as BrowserDomAdapter} from '@angular/platform-browser';
import {ɵsetRootDomAdapter as setRootDomAdapter} from '@angular/common';
function _notImplemented(methodName: string) {
return new Error('This method is not implemented in DominoAdapter: ' + methodName);
}
export function setDomTypes() {
// Make all Domino types available in the global env.
Object.assign(global, domino.impl);
@ -45,23 +41,9 @@ export class DominoAdapter extends BrowserDomAdapter {
setRootDomAdapter(new DominoAdapter());
}
readonly supportsDOMEvents = false;
private static defaultDoc: Document;
log(error: string) {
// tslint:disable-next-line:no-console
console.log(error);
}
logGroup(error: string) {
console.error(error);
}
logGroupEnd() {}
supportsDOMEvents(): boolean {
return false;
}
createHtmlDocument(): HTMLDocument {
return parseDocument('<html><head><title>fakeTitle</title></head><body></body></html>');
}
@ -80,18 +62,6 @@ export class DominoAdapter extends BrowserDomAdapter {
return node.shadowRoot == node;
}
getProperty(el: Element, name: string): any {
if (name === 'href') {
// Domino tries to resolve href-s which we do not want. Just return the
// attribute value.
return el.getAttribute('href');
} else if (name === 'innerText') {
// Domino does not support innerText. Just map it to textContent.
return el.textContent;
}
return (<any>el)[name];
}
getGlobalEventTarget(doc: Document, target: string): EventTarget|null {
if (target === 'window') {
return doc.defaultView;
@ -106,13 +76,8 @@ export class DominoAdapter extends BrowserDomAdapter {
}
getBaseHref(doc: Document): string {
const base = doc.documentElement!.querySelector('base');
let href = '';
if (base) {
href = base.getAttribute('href')!;
}
// TODO(alxhub): Need relative path logic from BrowserDomAdapter here?
return href;
return doc.documentElement!.querySelector('base')?.getAttribute('href') || '';
}
dispatchEvent(el: Node, evt: any) {
@ -126,24 +91,11 @@ export class DominoAdapter extends BrowserDomAdapter {
}
}
getHistory(): History {
throw _notImplemented('getHistory');
}
getLocation(): Location {
throw _notImplemented('getLocation');
}
getUserAgent(): string {
return 'Fake user agent';
}
performanceNow(): number {
return Date.now();
}
supportsCookies(): boolean {
return false;
}
getCookie(name: string): string {
throw _notImplemented('getCookie');
throw new Error('getCookie has not been implemented');
}
}

View File

@ -402,7 +402,7 @@ class HiddenModule {
}
(function() {
if (getDOM().supportsDOMEvents()) return; // NODE only
if (getDOM().supportsDOMEvents) return; // NODE only
describe('platform-server integration', () => {
beforeEach(() => {

View File

@ -11,7 +11,7 @@ import {ServerStylesHost} from '@angular/platform-server/src/styles_host';
(function() {
if (getDOM().supportsDOMEvents()) return; // NODE only
if (getDOM().supportsDOMEvents) return; // NODE only
describe('ServerStylesHost', () => {
let ssh: ServerStylesHost;

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {APP_BASE_HREF, HashLocationStrategy, Location, LOCATION_INITIALIZED, LocationStrategy, PathLocationStrategy, PlatformLocation, ViewportScroller, ɵgetDOM as getDOM} from '@angular/common';
import {APP_BASE_HREF, HashLocationStrategy, Location, LOCATION_INITIALIZED, LocationStrategy, PathLocationStrategy, PlatformLocation, ViewportScroller} from '@angular/common';
import {ANALYZE_FOR_ENTRY_COMPONENTS, APP_BOOTSTRAP_LISTENER, APP_INITIALIZER, ApplicationRef, Compiler, ComponentRef, Inject, Injectable, InjectionToken, Injector, ModuleWithProviders, NgModule, NgModuleFactoryLoader, NgProbeToken, Optional, Provider, SkipSelf, SystemJsNgModuleLoader} from '@angular/core';
import {of, Subject} from 'rxjs';
@ -448,12 +448,13 @@ export function setupRouter(
assignExtraOptionsToRouter(opts, router);
if (opts.enableTracing) {
const dom = getDOM();
router.events.subscribe((e: Event) => {
dom.logGroup(`Router Event: ${(<any>e.constructor).name}`);
dom.log(e.toString());
dom.log(e);
dom.logGroupEnd();
// tslint:disable:no-console
console.group?.(`Router Event: ${(<any>e.constructor).name}`);
console.log(e.toString());
console.log(e);
console.groupEnd?.();
// tslint:enable:no-console
});
}