Skip to content

fix(platform): change isBrowser check to use Angular PLATFORM_ID #10659

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 11, 2018

Conversation

CaerusKaru
Copy link
Member

@CaerusKaru CaerusKaru commented Apr 2, 2018

  • 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

@googlebot googlebot added the cla: yes PR author has agreed to Google's Contributor License Agreement label Apr 2, 2018
@CaerusKaru CaerusKaru force-pushed the platform branch 2 times, most recently from 10835f6 to ae598a8 Compare April 2, 2018 07:03
@@ -59,4 +60,8 @@ export class Platform {
// this and just place the Safari keyword in the userAgent. To be more safe about Safari every
// Safari browser should also use Webkit as its layout engine.
SAFARI: boolean = this.isBrowser && /safari/i.test(navigator.userAgent) && this.WEBKIT;

constructor(@Inject(PLATFORM_ID) private _platformId: Object) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a breaking change, because it changes the constructor signature.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally agree, but I still think it's a change that eventually needs to go in. I'm going through the rest of the tests to update the signature

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still isn't the proper way to handle it though. Instead it should be marked as an optional parameter with a deletion target for 7.0.0 and it should fall back to the old way of checking.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, will change

/**
* @deletion-target v7.0.0 remove optional decorator
*/
constructor(@Optional() @Inject(PLATFORM_ID) private _platformId: Object) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still doesn't make it a non-breaking change. You also have to mark the _platformId as an optional param by adding a question mark.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thought I did, my mistake. Will add, thanks for the catch

@CaerusKaru CaerusKaru force-pushed the platform branch 3 times, most recently from cc13cef to 6cdfdca Compare April 2, 2018 07:54
@CaerusKaru
Copy link
Member Author

Note: this is failing on one test case for the InteractivityChecker. Unless there's a simple way to refactor the test to avoid the undefined error, I'll leave it as a TODO for when the Platform constructor parameter is no longer optional.

@@ -5,6 +5,7 @@ import {InteractivityChecker} from './interactivity-checker';
describe('InteractivityChecker', () => {
let testContainerElement: HTMLElement;
let checker: InteractivityChecker;
// TODO: refactor this to be injected
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, will add

@@ -20,7 +21,8 @@ const hasV8BreakIterator = (typeof Intl !== 'undefined' && (Intl as any).v8Break
@Injectable({providedIn: 'root'})
export class Platform {
/** Whether the Angular application is being rendered in the browser. */
isBrowser: boolean = typeof document === 'object' && !!document;
isBrowser: boolean = this._platformId ?
isPlatformBrowser(this._platformId) : typeof document === 'object' && !!document;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I see the benefit of making this change. If someone wants to shim the document to pretend this is the browser, why not respect that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because if they shim the document but not the navigator, like Domino does, all of the other checks result in errors

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not to mention that it might not be an intentional shim

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have to go through a bit more trouble to declare a global variable in Node though (e.g. global.document = document).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but it's happening to me. This PR didn't just come out of nowhere. The Angular testing utilities are polluting the global namespace for Node tests (see here)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add some commenting here that explains that? Especially the part about what Domino does

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, will add. Alternatively I can add a check for the navigator to each of the below checks. Let me know which you prefer

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the platform id works, I just want people who look at this in the future to be able to take advantage of all of the information you picked up while figuring this out

@@ -37,11 +39,11 @@ export class Platform {
// Webkit is part of the userAgent in EdgeHTML, Blink and Trident. Therefore we need to
// ensure that Webkit runs standalone and is not used as another engine's base.
WEBKIT: boolean = this.isBrowser &&
/AppleWebKit/i.test(navigator.userAgent) && !this.BLINK && !this.EDGE && !this.TRIDENT;
/AppleWebKit/i.test(navigator.userAgent) && !this.BLINK && !this.EDGE && !this.TRIDENT;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The indent was right before (+4 for overflow)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix here and other places

@@ -279,7 +279,7 @@ describe('MatTabGroup', () => {
tick();

tabs = component._tabs.toArray();
expect(tabs[3].origin).toBeGreaterThanOrEqual(0);
expect(tabs[3].origin! >= 0).toBe(true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain what's going on here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was left over from when I was reviewing #10642, will remove

* 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
Copy link
Member

@jelbourn jelbourn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jelbourn jelbourn added P1 Impacts a large percentage of users; if a workaround exists it is partial or overly painful pr: lgtm action: merge The PR is ready for merge by the caretaker target: patch This PR is targeted for the next patch release labels Apr 9, 2018
@tinayuangao tinayuangao merged commit f023579 into angular:master Apr 11, 2018
@CaerusKaru CaerusKaru deleted the platform branch April 11, 2018 17:50
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 8, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes PR author has agreed to Google's Contributor License Agreement P1 Impacts a large percentage of users; if a workaround exists it is partial or overly painful target: patch This PR is targeted for the next patch release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants