Skip to content
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

fix: browser detection #8315

Merged

Conversation

JoseVSeb
Copy link
Contributor

@JoseVSeb JoseVSeb commented Jun 13, 2024

Update browser detection logic:
Detect either window or web worker (WorkerGlobalScope).

Fixes #8299
Fixes #8284

@JoseVSeb JoseVSeb requested review from a team as code owners June 13, 2024 13:53
Copy link

changeset-bot bot commented Jun 13, 2024

🦋 Changeset detected

Latest commit: 3a2a1ba

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 29 packages
Name Type
@firebase/util Patch
@firebase/app Patch
@firebase/analytics-compat Patch
@firebase/analytics Patch
@firebase/app-check-compat Patch
@firebase/app-check Patch
@firebase/app-compat Patch
@firebase/auth-compat Patch
@firebase/auth Patch
@firebase/component Patch
@firebase/database-compat Patch
@firebase/database-types Patch
@firebase/database Patch
firebase Patch
@firebase/firestore-compat Patch
@firebase/firestore Patch
@firebase/functions-compat Patch
@firebase/functions Patch
@firebase/installations-compat Patch
@firebase/installations Patch
@firebase/messaging-compat Patch
@firebase/messaging Patch
@firebase/performance-compat Patch
@firebase/performance Patch
@firebase/remote-config-compat Patch
@firebase/remote-config Patch
@firebase/storage-compat Patch
@firebase/storage Patch
@firebase/vertexai-preview Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@jdgamble555
Copy link

Thanks for working on this guys!

@DellaBitta
Copy link
Contributor

Hi @JoseVSeb,

Unfortunately adding "WebWorker" to the list of libs breaks our build enviornment. That lib includes symbols with the same name as those within other libs but with significantly different signatures.

I'm still working on this issue, though, and trying to find alternatives to a change that requires the use of WorkerGlobalScope. Could you please see if this code properly returns when you're in a webworker?

export function isWebWorker(): boolean {
  return !isNode() && typeof window === 'undefined' && typeof self !== 'undefined';
}

isNode() is the function in the same enviornment.ts file you added edits to. Thanks!

@JoseVSeb
Copy link
Contributor Author

Hi @DellaBitta,

export function isWebWorker(): boolean {
  return !isNode() && typeof window === 'undefined' && typeof self !== 'undefined';
}

this detects web worker fine but it also detects Edge runtime (unless forceEnvironment is set to "node", not ideal), which was the issue to begin with.

Unfortunately adding "WebWorker" to the list of libs breaks our build enviornment. That lib includes symbols with the same name as those within other libs but with significantly different signatures.

I added WebWorker to libs since I was using WorkerGlobalScope to detect web worker, but it's not technically necessary. If it's causing issues, just putting declare class WorkerGlobalScope {} in environment.ts might be enough.

I'll update the PR.

update browser detection logic:
detect either window or web worker (WorkerGlobalScope).

fixes firebase#8299 firebase#8284
@JoseVSeb JoseVSeb force-pushed the bugfix/detect-browser-or-web-worker branch from 5f7c0d0 to baa96ce Compare June 26, 2024 02:43
@DellaBitta
Copy link
Contributor

Ok, thank you! Another change request, if you would!

The current PR adds a call to isWebWorker() to the implementation of isBrowser(), but there could be situations where this isn't quite valid. If some code wants to determine if they're in a browser, and expects all of the browser elements to be there, then this code could cause probelms because a Browser is also a WebWorker with this logic

Instead of adding || isWebWorker() to the implementation of isBrowser(), could you move the check to the implementation of initializeServerApp()?

Something like this:

export function initializeServerApp(
  _options: FirebaseOptions | FirebaseApp,
  _serverAppConfig: FirebaseServerAppSettings
): FirebaseServerApp {
  if (isBrowser() && !isWebWorker()) {
    // FirebaseServerApp isn't designed to be run in browsers.
    throw ERROR_FACTORY.create(AppError.INVALID_SERVER_APP_ENVIRONMENT);
  }
  ...

This would mean that the PR doesn't fix issue #8284 (the Auth Lite issue), but perhaps it will enable FirebaseServerApp in those environments. I can escalate that issue with the Auth team directly.

@JoseVSeb
Copy link
Contributor Author

The current PR adds a call to isWebWorker() to the implementation of isBrowser(), but there could be situations where this isn't quite valid. If some code wants to determine if they're in a browser, and expects all of the browser elements to be there, then this code could cause probelms because a Browser is also a WebWorker with this logic

I called isWebWorker() inside isBrowser() so as not to break the intention behind the previous commit (see #1773) affecting this function as I am not entirely sure of the impact of that commit. in #1773 (comment), it refers this usage:

if (isBrowser() && 'firebase' in self) {


  if (isBrowser() && !isWebWorker()) {

did you mean isBrowser() || isWebWorker()? Since window and WorkerGlobalScope are never both defined in the same place, checking isBrowser() && !isWebWorker() is the same as just checking isBrowser(). also, FirebaseServerApp can technically work in a web worker and there are scenarios where that might be needed. so, in my opinion, if we are to remove isWebWorker() check from inside isBrowser(), initializeServerApp should check for just window.


This would mean that the PR doesn't fix issue #8284 (the Auth Lite issue), but perhaps it will enable FirebaseServerApp in those environments. I can escalate that issue with the Auth team directly.

I'm not exactly certain of that issue but #8284 (comment) seems to suggest that this could be a possible fix, that's why I mentioned it.

@DellaBitta
Copy link
Contributor

I suppose it's worth mentioning some of the team's goals:

  • I'm trying to get to place where initializeServerApp() is enabled for WebWorkers, at least experimentally.
  • Currently initializeServerApp() throws an error for WebWorkers because isBrowser() is returning true when running in a WebWorker. We want to fix this.
  • As a team we don't want FirebaseServerApp to be used in standard browser environments (ie: non-WebWorkers) so we want initializeServerApp() to still throw an error for standard browser runtimes.
  • If we keep the implementation of isBrowser() as it is right now, it can be used as a tool to detect an environment that is in a browser and is NOT a web worker, ie: (isBrowser() && !isWebWorker()), which is advantageous for the SDK.
  • isBrowser() is used by the Auth Compat SDK, too. I would rather not change the Auth Compat SDK's behavior (by changing the isBrowser() implementation) as that could have unknown repercussions. We can further consult the Auth team but that will take some time.
  • With all of this, I think the best path forward is to add the isWebWorker() function, keep isBrowser() as is, and update initializeServerApp() so that it allows WebWorkers to proceed without throwing an error:
if (isBrowser() && !isWebWorker()) {
    // FirebaseServerApp isn't designed to be run in browsers.
    throw ERROR_FACTORY.create(AppError.INVALID_SERVER_APP_ENVIRONMENT);
}

I know this is a lot, so if you'd rather I do this this work in a new PR then let me know!

@DellaBitta DellaBitta requested a review from hsubox76 June 27, 2024 14:36
@DellaBitta
Copy link
Contributor

Please revert the change to isBrowser's implementation and then we should be good to go!

@JoseVSeb
Copy link
Contributor Author

@DellaBitta, I raised this PR because isBrowser() has issues. The existing logic uses self to detect a browser, which returns true for every runtime that has self defined (not just browser), including Next.JS Edge Runtime, which is one of the two reasons behind #8299. Edge Runtime is NOT a web worker.

I traced the source of change to #1773 where browser detection was changed from window to self and the reasoning stated as "Web Workers are browser too".

I raised this PR so that isBrowser does what it's supposed to do and also, not break #1773; explicitly detecting either window or WorkerGlobalScope (for web worker) so that it covers both the runtimes available in a browser and not detect other runtimes, which solves the first cause of #8299 (second cause is covered by #8320).

@DellaBitta
Copy link
Contributor

Ah, I see! Sorry for the confusion. This looks ok to me but let me get one more pair of eyes on it.

@DellaBitta
Copy link
Contributor

Merging. Thanks for the contribution!

@DellaBitta DellaBitta merged commit 192561b into firebase:master Jun 28, 2024
35 of 38 checks passed
@JoseVSeb JoseVSeb deleted the bugfix/detect-browser-or-web-worker branch June 28, 2024 20:42
@google-oss-bot google-oss-bot mentioned this pull request Jul 2, 2024
tom-andersen pushed a commit that referenced this pull request Jul 24, 2024
Update browser detection logic: Detect either window or web worker (WorkerGlobalScope).
This updates the implementation to `isBrowser()` and adds a new function `isWebWorker()`.

Fixes #8299 #8284
@firebase firebase locked and limited conversation to collaborators Jul 29, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[FirebaseServerApp] Failed to initialize in Next.JS Edge Runtime
4 participants