-
Notifications
You must be signed in to change notification settings - Fork 934
Protobuf-backed FieldValues #2682
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
Protobuf-backed FieldValues #2682
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry about the long delay.
} | ||
|
||
private convertValue(value: api.Value): FieldType { | ||
if ('nullValue' in value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: this seems to involve string comparison. Is there any way to use some sort of an enum instead? (based on the assumption that it might have some, even if minor, effect on performance when converting many values)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are key lookups in a ProtobufJS-generated JavaScript object. Unfortunately, we don't control how these are generated. FWIW, back in the days (with an older version of ProtobufJs), we were able to use an enum-based approach.
} | ||
|
||
private convertReference(value: string): DocumentKey { | ||
// TODO(mrschmidt): Move `value()` and `convertValue()` to DocumentSnapshot, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this comment be moved somewhere else? (it refers to value
and convertValue
, not convertReference
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will allow us to fix convertReference
. I think this is not the best comment, but it will get removed before we merge.
if (other instanceof PrimitiveValue) { | ||
return equals(this.proto, other.proto); | ||
} | ||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to clarify -- why aren't two maps with the same keys and values ever considered equal?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A map would pass the instanceof PrimitiveValue
check and trigger this code: https://github.com/firebase/firebase-js-sdk/blob/mrschmidt/rewritefieldvalue/packages/firestore/src/model/proto_values.ts#L162 (which enforces key/value based equality).
|
||
/** | ||
* An ObjectValue represents a MapValue in the Firestore Proto and offers the | ||
* ability to add an remove fields (via the ObjectValueBuilder). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: s/an/and/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
/** | ||
* An ObjectValue represents a MapValue in the Firestore Proto and offers the | ||
* ability to add an remove fields (via the ObjectValueBuilder). | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional: consider extending the comment to compare and contrast ObjectValue
and PrimitiveValue
that is a map.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good suggestion, but PrimitiveValue is actually just a stepping stone to allow us to gradually remove field values. In the final PR, PrimitiveValue will disappear.
const timestamp = Timestamp.fromDate(input); | ||
return { | ||
timestampValue: { | ||
seconds: String(timestamp.seconds), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: why is String
necessary here, but not for integerValue
above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
integerValue
is defined as string | number
, which this should be too. Fixed.
expectedTypeOrder: TypeOrder | ||
): boolean { | ||
return value !== undefined && typeOrder(value) === expectedTypeOrder; | ||
): value is api.Value { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: how does value is api.Value
work as a return type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It tells the transpiler that it can assume that value is api.Value
if the function returns true. This allows the following:
let valueOrUnknown : api.Value | null | undefined = ...;
if (isType(valueOrUnknown, ...)) {
// valueOrUnknown is api.Value
}
This is all based on the honor system and we could easily fool the transpiler by providing the wrong guarantees.
|
||
/** | ||
* An Overlay, which contains an update to apply. Can either be Value proto, a | ||
* ma of Overlay values (to represent additional nesting at the given key) or |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: s/ma/map/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
|
||
/** | ||
* Removes the field at the specified path. If there is no field at the | ||
* specified path nothing is changed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ultranit: I think there should be a comma after path
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added
* Removes the field at the specified path. If there is no field at the | ||
* specified path nothing is changed. | ||
* | ||
* @param path The field path to remove |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ultranit: missing full stop at the end of the sentence.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added
Port of firebase/firebase-android-sdk#1156