Skip to content

Commit 4b1b784

Browse files
authored
Merge branch 'firebase:master' into testing-doc
2 parents 58ddf45 + bf4959b commit 4b1b784

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

+545
-209
lines changed

.changeset/rotten-tables-brush.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@firebase/database": patch
3+
---
4+
5+
Fixed issue where `get()` saved results incorrectly for non-default queries.

.changeset/tame-rice-peel.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@firebase/app-check": patch
3+
"@firebase/database": patch
4+
"@firebase/util": patch
5+
---
6+
7+
Extract uuid function into @firebase/util

.changeset/tiny-donuts-draw.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@firebase/functions': patch
3+
---
4+
5+
Update public `FunctionsErrorCode` type to include "functions/" prefix.

.changeset/witty-windows-unite.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@firebase/auth": patch
3+
---
4+
5+
Update user agent detection to better detect iPad; fixes bug for some iPad devices running Cordova apps

.github/workflows/health-metrics-pull-request.yml

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
name: Health Metrics
22

3-
on: [push, pull_request]
3+
on:
4+
push:
5+
branches: ['**']
6+
pull_request:
47

58
env:
69
GITHUB_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}

.github/workflows/release-prod.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ jobs:
2121
# Release script requires git history and tags.
2222
fetch-depth: 0
2323
ref: release
24+
token: ${{ secrets.OSS_BOT_GITHUB_TOKEN }}
2425
- name: Yarn install
2526
run: yarn
2627
- name: Publish to NPM
@@ -31,7 +32,6 @@ jobs:
3132
# TODO: Make these flags defaults in the release script.
3233
run: yarn release --releaseType Production --ci --skipTests --skipReinstall --ignoreUnstaged
3334
env:
34-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3535
NPM_TOKEN_ANALYTICS: ${{secrets.NPM_TOKEN_ANALYTICS}}
3636
NPM_TOKEN_ANALYTICS_INTEROP_TYPES: ${{secrets.NPM_TOKEN_ANALYTICS_INTEROP_TYPES}}
3737
NPM_TOKEN_ANALYTICS_TYPES: ${{secrets.NPM_TOKEN_ANALYTICS_TYPES}}

.github/workflows/test-all.yml

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
name: Test All Packages
22

3-
on: push
3+
on:
4+
push:
5+
branches: ['**']
6+
47
env:
58
# make chromedriver detect installed Chrome version and download the corresponding driver
69
DETECT_CHROMEDRIVER_VERSION: true

.vscode/launch.json

+5-4
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@
88
"type": "node",
99
"request": "launch",
1010
"name": "RTDB Unit Tests (Node)",
11-
"program": "${workspaceRoot}/packages/firebase/node_modules/.bin/_mocha",
11+
"program": "${workspaceRoot}/node_modules/.bin/_mocha",
1212
"cwd": "${workspaceRoot}/packages/database",
1313
"args": [
1414
"test/{,!(browser)/**/}*.test.ts",
15-
"--file", "index.node.ts",
16-
"--config", "../../config/mocharc.node.js"
15+
"--file", "src/index.node.ts",
16+
"--config", "../../config/mocharc.node.js",
1717
],
1818
"env": {
19+
"TS_NODE_FILES":true,
1920
"TS_NODE_CACHE": "NO",
2021
"TS_NODE_COMPILER_OPTIONS" : "{\"module\":\"commonjs\"}"
2122
},
@@ -30,7 +31,7 @@
3031
"cwd": "${workspaceRoot}/packages/firestore",
3132
"args": [
3233
"--require", "babel-register.js",
33-
"--require", "index.node.ts",
34+
"--require", "src/index.node.ts",
3435
"--timeout", "5000",
3536
"test/{,!(browser|integration)/**/}*.test.ts",
3637
"--exit"

common/api-review/functions.api.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ export interface FunctionsError extends FirebaseError {
2424
}
2525

2626
// @public
27-
export type FunctionsErrorCode = 'ok' | 'cancelled' | 'unknown' | 'invalid-argument' | 'deadline-exceeded' | 'not-found' | 'already-exists' | 'permission-denied' | 'resource-exhausted' | 'failed-precondition' | 'aborted' | 'out-of-range' | 'unimplemented' | 'internal' | 'unavailable' | 'data-loss' | 'unauthenticated';
27+
export type FunctionsErrorCode = `functions/${FunctionsErrorCodeCore}`;
28+
29+
// @public
30+
export type FunctionsErrorCodeCore = 'ok' | 'cancelled' | 'unknown' | 'invalid-argument' | 'deadline-exceeded' | 'not-found' | 'already-exists' | 'permission-denied' | 'resource-exhausted' | 'failed-precondition' | 'aborted' | 'out-of-range' | 'unimplemented' | 'internal' | 'unavailable' | 'data-loss' | 'unauthenticated';
2831

2932
// @public
3033
export function getFunctions(app?: FirebaseApp, regionOrCustomDomain?: string): Functions;

common/api-review/util.api.md

+3
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,9 @@ export interface Subscribe<T> {
422422
// @public (undocumented)
423423
export type Unsubscribe = () => void;
424424

425+
// @public
426+
export const uuidv4: () => string;
427+
425428
// Warning: (ae-missing-release-tag) "validateArgCount" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
426429
//
427430
// @public

packages/analytics/src/get-config.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,9 @@ async function attemptFetchDynamicConfigWithRetry(
188188
logger.warn(
189189
`Timed out fetching this Firebase app's measurement ID from the server.` +
190190
` Falling back to the measurement ID ${measurementId}` +
191-
` provided in the "measurementId" field in the local Firebase config. [${e.message}]`
191+
` provided in the "measurementId" field in the local Firebase config. [${
192+
(e as Error)?.message
193+
}]`
192194
);
193195
return { appId, measurementId };
194196
}
@@ -203,13 +205,14 @@ async function attemptFetchDynamicConfigWithRetry(
203205

204206
return response;
205207
} catch (e) {
206-
if (!isRetriableError(e)) {
208+
const error = e as Error;
209+
if (!isRetriableError(error)) {
207210
retryData.deleteThrottleMetadata(appId);
208211
if (measurementId) {
209212
logger.warn(
210213
`Failed to fetch this Firebase app's measurement ID from the server.` +
211214
` Falling back to the measurement ID ${measurementId}` +
212-
` provided in the "measurementId" field in the local Firebase config. [${e.message}]`
215+
` provided in the "measurementId" field in the local Firebase config. [${error?.message}]`
213216
);
214217
return { appId, measurementId };
215218
} else {
@@ -218,7 +221,7 @@ async function attemptFetchDynamicConfigWithRetry(
218221
}
219222

220223
const backoffMillis =
221-
Number(e.customData.httpStatus) === 503
224+
Number(error?.customData?.httpStatus) === 503
222225
? calculateBackoffMillis(
223226
backoffCount,
224227
retryData.intervalMillis,

packages/app-check/src/storage.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@
1515
* limitations under the License.
1616
*/
1717

18-
import { uuidv4 } from './util';
1918
import { FirebaseApp } from '@firebase/app';
20-
import { isIndexedDBAvailable } from '@firebase/util';
19+
import { isIndexedDBAvailable, uuidv4 } from '@firebase/util';
2120
import {
2221
readDebugTokenFromIndexedDB,
2322
readTokenFromIndexedDB,

packages/app-check/src/util.ts

-11
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,6 @@ export function ensureActivated(app: FirebaseApp): void {
3737
}
3838
}
3939

40-
/**
41-
* Copied from https://stackoverflow.com/a/2117523
42-
*/
43-
export function uuidv4(): string {
44-
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
45-
const r = (Math.random() * 16) | 0,
46-
v = c === 'x' ? r : (r & 0x3) | 0x8;
47-
return v.toString(16);
48-
});
49-
}
50-
5140
export function getDurationString(durationInMillis: number): string {
5241
const totalSeconds = Math.round(durationInMillis / 1000);
5342
const days = Math.floor(totalSeconds / (3600 * 24));

packages/auth/src/core/util/browser.test.ts

+87-65
Original file line numberDiff line numberDiff line change
@@ -16,84 +16,106 @@
1616
*/
1717

1818
import { expect } from 'chai';
19-
import { _getBrowserName, BrowserName } from './browser';
19+
import { _getBrowserName, BrowserName, _isIOS } from './browser';
2020

21-
describe('core/util/_getBrowserName', () => {
22-
it('should recognize Opera', () => {
23-
const userAgent =
24-
'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36 OPR/36.0.2130.74';
25-
expect(_getBrowserName(userAgent)).to.eq(BrowserName.OPERA);
26-
});
21+
describe('core/util/browser', () => {
22+
context('_getBrowserName', () => {
23+
it('should recognize Opera', () => {
24+
const userAgent =
25+
'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36 OPR/36.0.2130.74';
26+
expect(_getBrowserName(userAgent)).to.eq(BrowserName.OPERA);
27+
});
2728

28-
it('should recognize IE', () => {
29-
const userAgent =
30-
'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C)';
31-
expect(_getBrowserName(userAgent)).to.eq(BrowserName.IE);
32-
});
29+
it('should recognize IE', () => {
30+
const userAgent =
31+
'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C)';
32+
expect(_getBrowserName(userAgent)).to.eq(BrowserName.IE);
33+
});
3334

34-
it('should recognize Edge', () => {
35-
const userAgent =
36-
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240';
37-
expect(_getBrowserName(userAgent)).to.eq(BrowserName.EDGE);
38-
});
35+
it('should recognize Edge', () => {
36+
const userAgent =
37+
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240';
38+
expect(_getBrowserName(userAgent)).to.eq(BrowserName.EDGE);
39+
});
3940

40-
it('should recognize Firefox', () => {
41-
const userAgent =
42-
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:46.0) Gecko/20100101 Firefox/46.0';
43-
expect(_getBrowserName(userAgent)).to.eq(BrowserName.FIREFOX);
44-
});
41+
it('should recognize Firefox', () => {
42+
const userAgent =
43+
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:46.0) Gecko/20100101 Firefox/46.0';
44+
expect(_getBrowserName(userAgent)).to.eq(BrowserName.FIREFOX);
45+
});
4546

46-
it('should recognize Silk', () => {
47-
const userAgent =
48-
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Silk/44.1.54 like Chrome/44.0.2403.63 Safari/537.36';
49-
expect(_getBrowserName(userAgent)).to.eq(BrowserName.SILK);
50-
});
47+
it('should recognize Silk', () => {
48+
const userAgent =
49+
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Silk/44.1.54 like Chrome/44.0.2403.63 Safari/537.36';
50+
expect(_getBrowserName(userAgent)).to.eq(BrowserName.SILK);
51+
});
5152

52-
it('should recognize Safari', () => {
53-
const userAgent =
54-
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11-4) AppleWebKit/601.5.17 (KHTML, like Gecko) Version/9.1 Safari/601.5.17';
55-
expect(_getBrowserName(userAgent)).to.eq(BrowserName.SAFARI);
56-
});
53+
it('should recognize Safari', () => {
54+
const userAgent =
55+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11-4) AppleWebKit/601.5.17 (KHTML, like Gecko) Version/9.1 Safari/601.5.17';
56+
expect(_getBrowserName(userAgent)).to.eq(BrowserName.SAFARI);
57+
});
5758

58-
it('should recognize Chrome', () => {
59-
const userAgent =
60-
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36';
61-
expect(_getBrowserName(userAgent)).to.eq(BrowserName.CHROME);
62-
});
59+
it('should recognize Chrome', () => {
60+
const userAgent =
61+
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36';
62+
expect(_getBrowserName(userAgent)).to.eq(BrowserName.CHROME);
63+
});
6364

64-
it('should recognize Android', () => {
65-
const userAgent =
66-
'Mozilla/5.0 (Linux; U; Android 4.0.3; ko-kr; LG-L160L Build/IML74K) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30';
67-
expect(_getBrowserName(userAgent)).to.eq(BrowserName.ANDROID);
68-
});
65+
it('should recognize Android', () => {
66+
const userAgent =
67+
'Mozilla/5.0 (Linux; U; Android 4.0.3; ko-kr; LG-L160L Build/IML74K) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30';
68+
expect(_getBrowserName(userAgent)).to.eq(BrowserName.ANDROID);
69+
});
6970

70-
it('should recognize Blackberry', () => {
71-
const userAgent =
72-
'Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.1.0.346 Mobile Safari/534.11+';
73-
expect(_getBrowserName(userAgent)).to.eq(BrowserName.BLACKBERRY);
74-
});
71+
it('should recognize Blackberry', () => {
72+
const userAgent =
73+
'Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.1.0.346 Mobile Safari/534.11+';
74+
expect(_getBrowserName(userAgent)).to.eq(BrowserName.BLACKBERRY);
75+
});
7576

76-
it('should recognize IE Mobile', () => {
77-
const userAgent =
78-
'Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0;Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920)';
79-
expect(_getBrowserName(userAgent)).to.eq(BrowserName.IEMOBILE);
80-
});
77+
it('should recognize IE Mobile', () => {
78+
const userAgent =
79+
'Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0;Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920)';
80+
expect(_getBrowserName(userAgent)).to.eq(BrowserName.IEMOBILE);
81+
});
8182

82-
it('should recognize WebOS', () => {
83-
const userAgent =
84-
'Mozilla/5.0 (webOS/1.3; U; en-US) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/1.0 Safari/525.27.1 Desktop/1.0';
85-
expect(_getBrowserName(userAgent)).to.eq(BrowserName.WEBOS);
86-
});
83+
it('should recognize WebOS', () => {
84+
const userAgent =
85+
'Mozilla/5.0 (webOS/1.3; U; en-US) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/1.0 Safari/525.27.1 Desktop/1.0';
86+
expect(_getBrowserName(userAgent)).to.eq(BrowserName.WEBOS);
87+
});
8788

88-
it('should recognize an unlisted browser', () => {
89-
const userAgent =
90-
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Awesome/2.0.012';
91-
expect(_getBrowserName(userAgent)).to.eq('Awesome');
89+
it('should recognize an unlisted browser', () => {
90+
const userAgent =
91+
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Awesome/2.0.012';
92+
expect(_getBrowserName(userAgent)).to.eq('Awesome');
93+
});
94+
95+
it('should default to Other', () => {
96+
const userAgent =
97+
'Mozilla/5.0 (iPhone; CPU iPhone OS 8_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12D508 [FBAN/FBIOS;FBAV/27.0.0.10.12;FBBV/8291884;FBDV/iPhone7,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/8.2;FBSS/3; FBCR/vodafoneIE;FBID/phone;FBLC/en_US;FBOP/5]';
98+
expect(_getBrowserName(userAgent)).to.eq(BrowserName.OTHER);
99+
});
92100
});
93101

94-
it('should default to Other', () => {
95-
const userAgent =
96-
'Mozilla/5.0 (iPhone; CPU iPhone OS 8_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12D508 [FBAN/FBIOS;FBAV/27.0.0.10.12;FBBV/8291884;FBDV/iPhone7,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/8.2;FBSS/3; FBCR/vodafoneIE;FBID/phone;FBLC/en_US;FBOP/5]';
97-
expect(_getBrowserName(userAgent)).to.eq(BrowserName.OTHER);
102+
context('_isIOS', () => {
103+
it('should recognize iPhone', () => {
104+
const userAgent =
105+
'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/1234';
106+
expect(_isIOS(userAgent)).to.be.true;
107+
});
108+
109+
it('should recognize iPad without iPad string', () => {
110+
const userAgent =
111+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/1234';
112+
expect(_isIOS(userAgent)).to.be.true;
113+
});
114+
115+
it('should respond false for other mobile', () => {
116+
const userAgent =
117+
'Mozilla/5.0 (Linux; U; Android 4.0.3; ko-kr; LG-L160L Build/IML74K) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Chrome/534.30';
118+
expect(_isIOS(userAgent)).to.be.false;
119+
});
98120
});
99121
});

packages/auth/src/core/util/browser.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ export function _isWebOS(ua = getUA()): boolean {
123123
}
124124

125125
export function _isIOS(ua = getUA()): boolean {
126-
return /iphone|ipad|ipod/i.test(ua);
126+
return /iphone|ipad|ipod/i.test(ua) ||
127+
(/macintosh/i.test(ua) && /mobile/i.test(ua));
127128
}
128129

129130
export function _isIOS7Or8(ua = getUA()): boolean {

packages/database/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@
5656
"@firebase/app": "0.7.26",
5757
"rollup": "2.72.1",
5858
"rollup-plugin-typescript2": "0.31.2",
59-
"typescript": "4.2.2"
59+
"typescript": "4.2.2",
60+
"uuid": "^8.3.2"
6061
},
6162
"repository": {
6263
"directory": "packages/database",

packages/database/src/core/PersistentConnection.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -206,12 +206,6 @@ export class PersistentConnection extends ServerActions {
206206
onComplete: (message: { [k: string]: unknown }) => {
207207
const payload = message['d'] as string;
208208
if (message['s'] === 'ok') {
209-
this.onDataUpdate_(
210-
request['p'],
211-
payload,
212-
/*isMerge*/ false,
213-
/*tag*/ null
214-
);
215209
deferred.resolve(payload);
216210
} else {
217211
deferred.reject(payload);
@@ -265,7 +259,7 @@ export class PersistentConnection extends ServerActions {
265259
);
266260
assert(
267261
!this.listens.get(pathString)!.has(queryId),
268-
'listen() called twice for same path/queryId.'
262+
`listen() called twice for same path/queryId.`
269263
);
270264
const listenSpec: ListenSpec = {
271265
onComplete,

0 commit comments

Comments
 (0)