Skip to content

Commit 26ada51

Browse files
committed
fix(platform): change isBrowser check to use Angular PLATFORM_ID
* Use the Angular PLATFORM_ID token as a more reliable check for whether the current platform is browser. This is because the previous check for a global document could be a false positive if another application pollutes the global namespace BREAKING CHANGE: * Platform now takes the PLATFORM_ID as an optional parameter in its constructor. This will become a required parameter in v7
1 parent 7857b92 commit 26ada51

File tree

6 files changed

+31
-12
lines changed

6 files changed

+31
-12
lines changed

src/cdk/a11y/focus-trap/focus-trap.spec.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {Platform} from '@angular/cdk/platform';
2-
import {Component, ViewChild} from '@angular/core';
2+
import {Component, PLATFORM_ID, ViewChild} from '@angular/core';
33
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
44
import {A11yModule, FocusTrap, CdkTrapFocus} from '../index';
55

@@ -47,8 +47,9 @@ describe('FocusTrap', () => {
4747
// focus event handler directly.
4848
const result = focusTrapInstance.focusLastTabbableElement();
4949

50+
const platformId = TestBed.get(PLATFORM_ID);
5051
// In iOS button elements are never tabbable, so the last element will be the input.
51-
const lastElement = new Platform().IOS ? 'input' : 'button';
52+
const lastElement = new Platform(platformId).IOS ? 'input' : 'button';
5253

5354
expect(document.activeElement.nodeName.toLowerCase())
5455
.toBe(lastElement, `Expected ${lastElement} element to be focused`);

src/cdk/a11y/interactivity-checker/interactivity-checker.spec.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import {Platform} from '@angular/cdk/platform';
22
import {InteractivityChecker} from './interactivity-checker';
3+
import {inject} from '@angular/core/testing';
34

45

56
describe('InteractivityChecker', () => {
67
let testContainerElement: HTMLElement;
78
let checker: InteractivityChecker;
8-
let platform: Platform = new Platform();
9+
let platform: Platform;
10+
11+
beforeEach(inject([Platform], (_platform: Platform) => {
12+
platform = _platform;
13+
}));
914

1015
beforeEach(() => {
1116
testContainerElement = document.createElement('div');

src/cdk/overlay/scroll/block-scroll-strategy.spec.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {Overlay, OverlayContainer, OverlayModule, OverlayRef, OverlayConfig} fro
77

88

99
describe('BlockScrollStrategy', () => {
10-
let platform = new Platform();
10+
let platform: Platform;
1111
let viewport: ViewportRuler;
1212
let overlayRef: OverlayRef;
1313
let componentPortal: ComponentPortal<FocacciaMsg>;
@@ -22,7 +22,8 @@ describe('BlockScrollStrategy', () => {
2222
}).compileComponents();
2323
}));
2424

25-
beforeEach(inject([Overlay, ViewportRuler], (overlay: Overlay, viewportRuler: ViewportRuler) => {
25+
beforeEach(inject([Overlay, ViewportRuler, Platform],
26+
(overlay: Overlay, viewportRuler: ViewportRuler, _platform: Platform) => {
2627
let overlayConfig = new OverlayConfig({scrollStrategy: overlay.scrollStrategies.block()});
2728

2829
overlayRef = overlay.create(overlayConfig);
@@ -34,6 +35,7 @@ describe('BlockScrollStrategy', () => {
3435
forceScrollElement.style.width = '100px';
3536
forceScrollElement.style.height = '3000px';
3637
forceScrollElement.style.background = 'rebeccapurple';
38+
platform = _platform;
3739
}));
3840

3941
afterEach(inject([OverlayContainer], (container: OverlayContainer) => {

src/cdk/platform/platform.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {Injectable} from '@angular/core';
9+
import {Inject, Injectable, Optional, PLATFORM_ID} from '@angular/core';
10+
import {isPlatformBrowser} from '@angular/common';
1011

1112

1213
// Whether the current platform supports the V8 Break Iterator. The V8 check
@@ -20,7 +21,8 @@ const hasV8BreakIterator = (typeof Intl !== 'undefined' && (Intl as any).v8Break
2021
@Injectable({providedIn: 'root'})
2122
export class Platform {
2223
/** Whether the Angular application is being rendered in the browser. */
23-
isBrowser: boolean = typeof document === 'object' && !!document;
24+
isBrowser: boolean = this._platformId ?
25+
isPlatformBrowser(this._platformId) : typeof document === 'object' && !!document;
2426

2527
/** Whether the current browser is Microsoft Edge. */
2628
EDGE: boolean = this.isBrowser && /(edge)/i.test(navigator.userAgent);
@@ -37,11 +39,11 @@ export class Platform {
3739
// Webkit is part of the userAgent in EdgeHTML, Blink and Trident. Therefore we need to
3840
// ensure that Webkit runs standalone and is not used as another engine's base.
3941
WEBKIT: boolean = this.isBrowser &&
40-
/AppleWebKit/i.test(navigator.userAgent) && !this.BLINK && !this.EDGE && !this.TRIDENT;
42+
/AppleWebKit/i.test(navigator.userAgent) && !this.BLINK && !this.EDGE && !this.TRIDENT;
4143

4244
/** Whether the current platform is Apple iOS. */
4345
IOS: boolean = this.isBrowser && /iPad|iPhone|iPod/.test(navigator.userAgent) &&
44-
!(window as any).MSStream;
46+
!(window as any).MSStream;
4547

4648
/** Whether the current browser is Firefox. */
4749
// It's difficult to detect the plain Gecko engine, because most of the browsers identify
@@ -59,4 +61,11 @@ export class Platform {
5961
// this and just place the Safari keyword in the userAgent. To be more safe about Safari every
6062
// Safari browser should also use Webkit as its layout engine.
6163
SAFARI: boolean = this.isBrowser && /safari/i.test(navigator.userAgent) && this.WEBKIT;
64+
65+
/**
66+
* @deletion-target v7.0.0 remove optional decorator
67+
*/
68+
constructor(@Optional() @Inject(PLATFORM_ID) private _platformId: Object) {
69+
}
6270
}
71+

src/lib/core/datetime/native-date-adapter.spec.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const SUPPORTS_INTL = typeof Intl != 'undefined';
88

99

1010
describe('NativeDateAdapter', () => {
11-
const platform = new Platform();
11+
let platform: Platform;
1212
let adapter: NativeDateAdapter;
1313
let assertValidDate: (d: Date | null, valid: boolean) => void;
1414

@@ -18,8 +18,10 @@ describe('NativeDateAdapter', () => {
1818
}).compileComponents();
1919
}));
2020

21-
beforeEach(inject([DateAdapter], (dateAdapter: NativeDateAdapter) => {
21+
beforeEach(inject([DateAdapter, Platform],
22+
(dateAdapter: NativeDateAdapter, _platform: Platform) => {
2223
adapter = dateAdapter;
24+
platform = _platform;
2325

2426
assertValidDate = (d: Date | null, valid: boolean) => {
2527
expect(adapter.isDateInstance(d)).not.toBeNull(`Expected ${d} to be a date instance`);

src/lib/tabs/tab-group.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ describe('MatTabGroup', () => {
279279
tick();
280280

281281
tabs = component._tabs.toArray();
282-
expect(tabs[3].origin).toBeGreaterThanOrEqual(0);
282+
expect(tabs[3].origin! >= 0).toBe(true);
283283

284284
// Add a new tab in the beginning and select it, expect an origin < than 0 (animate left)
285285
fixture.componentInstance.tabs.push({label: 'New tab', content: 'to left of index'});

0 commit comments

Comments
 (0)