← 返回首页
feat(firestore): BSON types by dlarocque · Pull Request #10099 · firebase/firebase-js-sdk · GitHub
Skip to content

Navigation Menu

Toggle navigation
Sign in
Appearance settings
Search or jump to...

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Resetting focus

feat(firestore): BSON types#10099

Draft
dlarocque wants to merge 19 commits into
mainfrom
dl/bson-types
Draft

feat(firestore): BSON types#10099
dlarocque wants to merge 19 commits into
mainfrom
dl/bson-types

Conversation

Copy link
Copy Markdown
Contributor

Draft

changeset-bot Bot commented Jun 17, 2026
edited
Loading

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a643098

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

This PR includes changesets to release 3 packages Name Type
firebase Minor
@firebase/firestore Minor
@firebase/firestore-compat 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

gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality Hide comment

Code Review

This pull request introduces comprehensive support for BSON types (including BsonBinaryData, BsonObjectId, BsonTimestamp, Decimal128Value, Int32Value, MaxKey, MinKey, and RegexValue) across both the standard and Lite Firestore SDKs. The changes span API definitions, serialization, indexing, query validation, and local store comparisons, supported by new utility classes for 128-bit decimal operations and extensive integration tests. Feedback on the implementation highlights opportunities to improve safety and compatibility, such as using optional chaining to prevent runtime errors when writing BSON timestamp index maps, validating integer inputs for BSON types, using SDK-consistent FirestoreError classes, and replacing ES2022 Uint8Array.prototype.at() with standard index access for broader environment compatibility.

Comment on lines +310 to +318
const fields = mapValue.fields || {};
if (fields) {
// The JS SDK encodes BSON timestamps differently than the backend.
// This is due to the limitation of `number` in JS which handles up to 53-bit precision.
this.writeIndexMap(
fields[RESERVED_BSON_TIMESTAMP_KEY].mapValue!,
encoder
);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality Hide comment

The if (fields) check is redundant because fields is initialized to mapValue.fields || {} which is always truthy. More importantly, accessing fields[RESERVED_BSON_TIMESTAMP_KEY].mapValue! directly can cause a runtime TypeError if the key is missing. Using optional chaining and checking if the map exists before writing is much safer.

const fields = mapValue.fields || {}; const timestampMap = fields[RESERVED_BSON_TIMESTAMP_KEY]?.mapValue; if (timestampMap) { // The JS SDK encodes BSON timestamps differently than the backend. // This is due to the limitation of `number` in JS which handles up to 53-bit precision. this.writeIndexMap(timestampMap, encoder); }

Comment on lines +29 to +36
constructor(readonly subtype: number, data: Uint8Array) {
if (subtype < 0 || subtype > 255) {
throw new FirestoreError(
Code.INVALID_ARGUMENT,
'The subtype for BsonBinaryData must be a value in the inclusive [0, 255] range.'
);
}
this.subtype = subtype;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality Hide comment

The assignment this.subtype = subtype; is redundant because readonly subtype: number in the constructor parameter list automatically declares and initializes it as a class property. Additionally, we should validate that subtype is an integer to prevent floating-point values or NaN from being silently accepted.

Suggested change
constructor(readonly subtype: number, data: Uint8Array) {
if (subtype < 0 || subtype > 255) {
throw new FirestoreError(
Code.INVALID_ARGUMENT,
'The subtype for BsonBinaryData must be a value in the inclusive [0, 255] range.'
);
}
this.subtype = subtype;
constructor(readonly subtype: number, data: Uint8Array) {
if (subtype < 0 || subtype > 255 || !Number.isInteger(subtype)) {
throw new FirestoreError(
Code.INVALID_ARGUMENT,
'The subtype for BsonBinaryData must be a value in the inclusive [0, 255] range.'
);
}

Comment on lines +24 to +35
constructor(readonly seconds: number, readonly increment: number) {
// Make sure 'seconds' and 'increment' are in the range of a 32-bit unsigned integer.
if (seconds < 0 || seconds > 4294967295) {
throw new Error(
"BsonTimestamp 'seconds' must be in the range of a 32-bit unsigned integer."
);
}
if (increment < 0 || increment > 4294967295) {
throw new Error(
"BsonTimestamp 'increment' must be in the range of a 32-bit unsigned integer."
);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality Hide comment

We should validate that seconds and increment are integers to prevent floating-point values or NaN from being silently accepted. Also, using FirestoreError with Code.INVALID_ARGUMENT is much more consistent with the rest of the Firestore SDK API than a generic Error. Note: You will need to import Code and FirestoreError from ../util/error at the top of the file.

constructor(readonly seconds: number, readonly increment: number) { // Make sure 'seconds' and 'increment' are in the range of a 32-bit unsigned integer. if (seconds < 0 || seconds > 4294967295 || !Number.isInteger(seconds)) { throw new FirestoreError( Code.INVALID_ARGUMENT, "BsonTimestamp 'seconds' must be in the range of a 32-bit unsigned integer." ); } if (increment < 0 || increment > 4294967295 || !Number.isInteger(increment)) { throw new FirestoreError( Code.INVALID_ARGUMENT, "BsonTimestamp 'increment' must be in the range of a 32-bit unsigned integer." ); }

if (bytes.length === 0) {
throw new Error('Received empty bytesValue for BsonBinaryData');
}
const subtype = bytes.at(0);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality Hide comment

Uint8Array.prototype.at() is an ES2022 feature and may not be supported in all target environments (older browsers or Node.js versions) without a polyfill. Using standard index access bytes[0] is fully compatible, safer, and more performant.

Suggested change
const subtype = bytes.at(0);
const subtype = bytes[0];

dlarocque and others added 6 commits June 23, 2026 13:49
* feat(firestore): Merge `BsonBinaryData` into `Bytes` - Removed the BsonBinaryData class and merged its functionality into the Bytes class. - The Bytes class now supports an optional subtype parameter (defaults to 0, range 0 to 255). - Added a readonly subtype property and a data getter on the Bytes class. - Updated Bytes serialization (toJSON and fromJSON) to support subtypes, omitting it when subtype is 0. - Updated the local index writer to encode Bytes with subtype 0 identically to standard blobs to ensure consistent sorting. - Updated internal readers, writers, and enums to map BSON binary data to Bytes. * formatting * lint and format * fix lint * chore(firestore): remove unrelated BSON Int32Value numeric increment test case from dl/bsonbinary * fix format
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Footer

© 2026 GitHub, Inc.