Skip to content

Commit 513db9d

Browse files
committed
Merge branch 'mila/BloomFilter' into mila/BloomFilter-apply-bloom-filter-in-existence-filter-mismatch
2 parents f53491a + dd66835 commit 513db9d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1548
-559
lines changed

.changeset/eleven-cycles-hang.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@firebase/storage": patch
3+
---
4+
5+
Fixed issue where pause throws an error when a request is in flight.

.changeset/heavy-mirrors-drum.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@firebase/auth-interop-types': patch
3+
---
4+
5+
Remove unused peerDependencies.

.changeset/nervous-ads-pretend.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@firebase/database": patch
3+
---
4+
5+
Fixed issue where connectDatabaseToEmulator can be called twice during a hot reload

.changeset/pretty-carrots-kneel.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@firebase/database': patch
3+
---
4+
5+
Replace `innerHTML` call with `textContent`.

.changeset/quick-radios-obey.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@firebase/firestore": patch
3+
---
4+
5+
Update canonifyFilter to compute the canonization for flat conjunctions the same as implicit AND queries.

.changeset/stupid-swans-fix.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@firebase/firestore": patch
3+
---
4+
5+
Fix an issue that stops some performance optimization being applied.

.changeset/tricky-ravens-stare.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@firebase/auth': patch
3+
---
4+
5+
Fix to minimize a potential race condition between auth init and signInWithRedirect

.changeset/wild-geckos-fetch.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@firebase/util': patch
3+
---
4+
5+
Reformat a comment that causes compile errors in some build toolchains.

.changeset/young-hornets-rescue.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@firebase/util': minor
3+
'firebase': minor
4+
---
5+
6+
Allow users to specify their environment as `node` or `browser` to override Firebase's runtime environment detection and force the SDK to act as if it were in the respective environment.

.github/workflows/merge-release-branch.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
run: |
1919
export VERSION_SCRIPT="const pkg = require('./packages/firebase/package.json'); console.log(pkg.version);"
2020
export VERSION=`node -e "${VERSION_SCRIPT}"`
21-
echo "::set-output name=RELEASE_VERSION::$VERSION"
21+
echo "RELEASE_VERSION=$VERSION" >> $GITHUB_OUTPUT
2222
- name: Echo version in shell
2323
run: |
2424
echo "Merging release ${{ steps.get-version.outputs.RELEASE_VERSION }}"

.github/workflows/release-prod.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ jobs:
9595
run: |
9696
VERSION_SCRIPT="const pkg = require('./packages/firebase/package.json'); console.log(pkg.version);"
9797
VERSION=`node -e "${VERSION_SCRIPT}"`
98-
echo "::set-output name=BASE_VERSION::$VERSION"
98+
echo "BASE_VERSION=$VERSION" >> $GITHUB_OUTPUT
9999
- name: Echo version in shell
100100
run: |
101101
echo "Base version: ${{ steps.get-version.outputs.BASE_VERSION }}"

.github/workflows/release-staging.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,9 @@ jobs:
114114
run: |
115115
VERSION_SCRIPT="const pkg = require('./packages/firebase/package.json'); console.log(pkg.version);"
116116
VERSION=`node -e "${VERSION_SCRIPT}"`
117-
echo "::set-output name=STAGING_VERSION::$VERSION"
117+
echo "STAGING_VERSION=$VERSION" >> $GITHUB_OUTPUT
118118
BASE_VERSION=$(echo $VERSION | cut -d "-" -f 1)
119-
echo "::set-output name=BASE_VERSION::$BASE_VERSION"
119+
echo "BASE_VERSION=$BASE_VERSION" >> $GITHUB_OUTPUT
120120
- name: Echo versions in shell
121121
run: |
122122
echo "Staging release ${{ steps.get-version.outputs.STAGING_VERSION }}"

common/api-review/util.api.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ export interface FirebaseDefaults {
193193
config?: Record<string, string>;
194194
// (undocumented)
195195
emulatorHosts?: Record<string, string>;
196+
forceEnvironment?: 'browser' | 'node';
196197
}
197198

198199
// Warning: (ae-missing-release-tag) "FirebaseError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
@@ -221,11 +222,12 @@ export const getDefaultEmulatorHost: (productName: string) => string | undefined
221222
// @public
222223
export const getDefaultEmulatorHostnameAndPort: (productName: string) => [hostname: string, port: number] | undefined;
223224

225+
// @public
226+
export const getDefaults: () => FirebaseDefaults | undefined;
227+
224228
// @public
225229
export const getExperimentalSetting: <T extends ExperimentalKey>(name: T) => FirebaseDefaults[`_${T}`];
226230

227-
// Warning: (ae-missing-release-tag) "getGlobal" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
228-
//
229231
// @public
230232
export function getGlobal(): typeof globalThis;
231233

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@
105105
"eslint-plugin-unused-imports": "2.0.0",
106106
"express": "4.18.2",
107107
"find-free-port": "2.0.0",
108-
"firebase-tools": "11.2.2",
108+
"firebase-tools": "11.19.0",
109109
"glob": "7.2.3",
110110
"http-server": "14.1.1",
111111
"indexeddbshim": "8.0.0",
@@ -140,7 +140,7 @@
140140
"protractor": "5.4.2",
141141
"request": "2.88.2",
142142
"semver": "7.3.8",
143-
"simple-git": "3.7.1",
143+
"simple-git": "3.15.0",
144144
"sinon": "9.2.4",
145145
"sinon-chai": "3.7.0",
146146
"source-map-loader": "1.1.3",

packages/auth-interop-types/package.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@
1111
"files": [
1212
"index.d.ts"
1313
],
14-
"peerDependencies": {
15-
"@firebase/app-types": "0.x",
16-
"@firebase/util": "1.x"
17-
},
1814
"repository": {
1915
"directory": "packages/auth-types",
2016
"type": "git",

packages/auth/demo/src/index.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1812,6 +1812,27 @@ function initApp() {
18121812
},
18131813
onAuthError);
18141814

1815+
// Try sign in with redirect once upon page load, not on subsequent loads.
1816+
// This will demonstrate the behavior when signInWithRedirect is called before
1817+
// auth is fully initialized. This will fail on firebase/auth versions 0.21.0 and lower
1818+
// due to https://github.com/firebase/firebase-js-sdk/issues/6827
1819+
/*
1820+
if (sessionStorage.getItem('redirect-race-test') !== 'done') {
1821+
console.log('Starting redirect sign in upon page load.');
1822+
try {
1823+
sessionStorage.setItem('redirect-race-test', 'done');
1824+
signInWithRedirect(
1825+
auth,
1826+
new GoogleAuthProvider(),
1827+
browserPopupRedirectResolver
1828+
).catch(onAuthError);
1829+
} catch (error) {
1830+
console.log('Error while calling signInWithRedirect');
1831+
console.error(error);
1832+
}
1833+
}
1834+
*/
1835+
18151836
// Bootstrap tooltips.
18161837
$('[data-toggle="tooltip"]').tooltip();
18171838

packages/auth/src/platform_browser/strategies/redirect.test.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,37 @@ describe('platform_browser/strategies/redirect', () => {
122122
'auth/argument-error'
123123
);
124124
});
125+
126+
it('awaits on the auth initialization promise before opening redirect', async () => {
127+
// Obtain an auth instance which does not await on the initialization promise.
128+
const authWithoutAwait: TestAuth = await testAuth(
129+
resolver,
130+
undefined,
131+
true
132+
);
133+
// completeRedirectFn calls getRedirectResult under the hood.
134+
const getRedirectResultSpy = sinon.spy(
135+
_getInstance<PopupRedirectResolverInternal>(resolver),
136+
'_completeRedirectFn'
137+
);
138+
const openRedirectSpy = sinon.spy(
139+
_getInstance<PopupRedirectResolverInternal>(resolver),
140+
'_openRedirect'
141+
);
142+
await signInWithRedirect(authWithoutAwait, provider);
143+
expect(getRedirectResultSpy).to.have.been.called;
144+
expect(getRedirectResultSpy).to.have.been.calledBefore(openRedirectSpy);
145+
expect(getRedirectResultSpy).to.have.been.calledWith(
146+
authWithoutAwait,
147+
resolver,
148+
true
149+
);
150+
expect(openRedirectSpy).to.have.been.calledWith(
151+
authWithoutAwait,
152+
provider,
153+
AuthEventType.SIGN_IN_VIA_REDIRECT
154+
);
155+
});
125156
});
126157

127158
context('linkWithRedirect', () => {
@@ -159,6 +190,39 @@ describe('platform_browser/strategies/redirect', () => {
159190
);
160191
});
161192

193+
it('awaits on the auth initialization promise before opening redirect', async () => {
194+
// Obtain an auth instance which does not await on the initialization promise.
195+
const authWithoutAwait: TestAuth = await testAuth(
196+
resolver,
197+
undefined,
198+
true
199+
);
200+
user = testUser(authWithoutAwait, 'uid', 'email', true);
201+
// completeRedirectFn calls getRedirectResult under the hood.
202+
const getRedirectResultSpy = sinon.spy(
203+
_getInstance<PopupRedirectResolverInternal>(resolver),
204+
'_completeRedirectFn'
205+
);
206+
const openRedirectSpy = sinon.spy(
207+
_getInstance<PopupRedirectResolverInternal>(resolver),
208+
'_openRedirect'
209+
);
210+
await authWithoutAwait._updateCurrentUser(user);
211+
await linkWithRedirect(user, provider, resolver);
212+
expect(getRedirectResultSpy).to.have.been.called;
213+
expect(getRedirectResultSpy).to.have.been.calledBefore(openRedirectSpy);
214+
expect(getRedirectResultSpy).to.have.been.calledWith(
215+
authWithoutAwait,
216+
resolver,
217+
true
218+
);
219+
expect(openRedirectSpy).to.have.been.calledWith(
220+
authWithoutAwait,
221+
provider,
222+
AuthEventType.LINK_VIA_REDIRECT
223+
);
224+
});
225+
162226
it('errors if no resolver available', async () => {
163227
auth._popupRedirectResolver = null;
164228
await expect(linkWithRedirect(user, provider)).to.be.rejectedWith(
@@ -236,6 +300,40 @@ describe('platform_browser/strategies/redirect', () => {
236300
);
237301
});
238302

303+
it('awaits on the auth initialization promise before opening redirect', async () => {
304+
// Obtain an auth instance which does not await on the initialization promise.
305+
const authWithoutAwait: TestAuth = await testAuth(
306+
resolver,
307+
undefined,
308+
true
309+
);
310+
user = testUser(authWithoutAwait, 'uid', 'email', true);
311+
// completeRedirectFn calls getRedirectResult under the hood.
312+
const getRedirectResultSpy = sinon.spy(
313+
_getInstance<PopupRedirectResolverInternal>(resolver),
314+
'_completeRedirectFn'
315+
);
316+
const openRedirectSpy = sinon.spy(
317+
_getInstance<PopupRedirectResolverInternal>(resolver),
318+
'_openRedirect'
319+
);
320+
await authWithoutAwait._updateCurrentUser(user);
321+
await signInWithRedirect(authWithoutAwait, provider);
322+
await reauthenticateWithRedirect(user, provider);
323+
expect(getRedirectResultSpy).to.have.been.called;
324+
expect(getRedirectResultSpy).to.have.been.calledBefore(openRedirectSpy);
325+
expect(getRedirectResultSpy).to.have.been.calledWith(
326+
authWithoutAwait,
327+
resolver,
328+
true
329+
);
330+
expect(openRedirectSpy).to.have.been.calledWith(
331+
authWithoutAwait,
332+
provider,
333+
AuthEventType.REAUTH_VIA_REDIRECT
334+
);
335+
});
336+
239337
it('errors if no resolver available', async () => {
240338
auth._popupRedirectResolver = null;
241339
await expect(

packages/auth/src/platform_browser/strategies/redirect.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import { getModularInstance } from '@firebase/util';
4242
*
4343
* @remarks
4444
* To handle the results and errors for this operation, refer to {@link getRedirectResult}.
45+
* Follow the [best practices](https://firebase.google.com/docs/auth/web/redirect-best-practices) when using {@link signInWithRedirect}.
4546
*
4647
* @example
4748
* ```javascript
@@ -91,6 +92,10 @@ export async function _signInWithRedirect(
9192
): Promise<void | never> {
9293
const authInternal = _castAuth(auth);
9394
_assertInstanceOf(auth, provider, FederatedAuthProvider);
95+
// Wait for auth initialization to complete, this will process pending redirects and clear the
96+
// PENDING_REDIRECT_KEY in persistence. This should be completed before starting a new
97+
// redirect and creating a PENDING_REDIRECT_KEY entry.
98+
await authInternal._initializationPromise;
9499
const resolverInternal = _withDefaultResolver(authInternal, resolver);
95100
await _setPendingRedirectStatus(resolverInternal, authInternal);
96101

@@ -103,6 +108,9 @@ export async function _signInWithRedirect(
103108

104109
/**
105110
* Reauthenticates the current user with the specified {@link OAuthProvider} using a full-page redirect flow.
111+
* @remarks
112+
* To handle the results and errors for this operation, refer to {@link getRedirectResult}.
113+
* Follow the [best practices](https://firebase.google.com/docs/auth/web/redirect-best-practices) when using {@link reauthenticateWithRedirect}.
106114
*
107115
* @example
108116
* ```javascript
@@ -113,8 +121,8 @@ export async function _signInWithRedirect(
113121
*
114122
* // After returning from the redirect when your app initializes you can obtain the result
115123
* const result = await getRedirectResult(auth);
116-
* // Link using a redirect.
117-
* await linkWithRedirect(result.user, provider);
124+
* // Reauthenticate using a redirect.
125+
* await reauthenticateWithRedirect(result.user, provider);
118126
* // This will again trigger a full page redirect away from your app
119127
*
120128
* // After returning from the redirect when your app initializes you can obtain the result
@@ -147,6 +155,10 @@ export async function _reauthenticateWithRedirect(
147155
): Promise<void | never> {
148156
const userInternal = getModularInstance(user) as UserInternal;
149157
_assertInstanceOf(userInternal.auth, provider, FederatedAuthProvider);
158+
// Wait for auth initialization to complete, this will process pending redirects and clear the
159+
// PENDING_REDIRECT_KEY in persistence. This should be completed before starting a new
160+
// redirect and creating a PENDING_REDIRECT_KEY entry.
161+
await userInternal.auth._initializationPromise;
150162
// Allow the resolver to error before persisting the redirect user
151163
const resolverInternal = _withDefaultResolver(userInternal.auth, resolver);
152164
await _setPendingRedirectStatus(resolverInternal, userInternal.auth);
@@ -162,6 +174,9 @@ export async function _reauthenticateWithRedirect(
162174

163175
/**
164176
* Links the {@link OAuthProvider} to the user account using a full-page redirect flow.
177+
* @remarks
178+
* To handle the results and errors for this operation, refer to {@link getRedirectResult}.
179+
* Follow the [best practices](https://firebase.google.com/docs/auth/web/redirect-best-practices) when using {@link linkWithRedirect}.
165180
*
166181
* @example
167182
* ```javascript
@@ -199,6 +214,10 @@ export async function _linkWithRedirect(
199214
): Promise<void | never> {
200215
const userInternal = getModularInstance(user) as UserInternal;
201216
_assertInstanceOf(userInternal.auth, provider, FederatedAuthProvider);
217+
// Wait for auth initialization to complete, this will process pending redirects and clear the
218+
// PENDING_REDIRECT_KEY in persistence. This should be completed before starting a new
219+
// redirect and creating a PENDING_REDIRECT_KEY entry.
220+
await userInternal.auth._initializationPromise;
202221
// Allow the resolver to error before persisting the redirect user
203222
const resolverInternal = _withDefaultResolver(userInternal.auth, resolver);
204223
await _assertLinkedStatus(false, userInternal, provider.providerId);

packages/auth/test/helpers/mock_auth.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ export class MockPersistenceLayer extends InMemoryPersistence {
7171

7272
export async function testAuth(
7373
popupRedirectResolver?: PopupRedirectResolver,
74-
persistence = new MockPersistenceLayer()
74+
persistence = new MockPersistenceLayer(),
75+
skipAwaitOnInit?: boolean
7576
): Promise<TestAuth> {
7677
const auth: TestAuth = new AuthImpl(
7778
FAKE_APP,
@@ -88,7 +89,13 @@ export async function testAuth(
8889
) as TestAuth;
8990
auth._updateErrorMap(debugErrorMap);
9091

91-
await auth._initializeWithPersistence([persistence], popupRedirectResolver);
92+
if (skipAwaitOnInit) {
93+
// This is used to verify scenarios where auth flows (like signInWithRedirect) are invoked before auth is fully initialized.
94+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
95+
auth._initializeWithPersistence([persistence], popupRedirectResolver);
96+
} else {
97+
await auth._initializeWithPersistence([persistence], popupRedirectResolver);
98+
}
9299
auth.persistenceLayer = persistence;
93100
auth.settings.appVerificationDisabledForTesting = true;
94101
return auth;

packages/database/src/api/Database.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -320,9 +320,11 @@ export function getDatabase(
320320
const db = _getProvider(app, 'database').getImmediate({
321321
identifier: url
322322
}) as Database;
323-
const emulator = getDefaultEmulatorHostnameAndPort('database');
324-
if (emulator) {
325-
connectDatabaseEmulator(db, ...emulator);
323+
if (!db._instanceStarted) {
324+
const emulator = getDefaultEmulatorHostnameAndPort('database');
325+
if (emulator) {
326+
connectDatabaseEmulator(db, ...emulator);
327+
}
326328
}
327329
return db;
328330
}

0 commit comments

Comments
 (0)