@@ -43,13 +43,12 @@ import { DocumentKey } from '../model/document_key';
4343import { DocumentSet } from '../model/document_set' ;
4444import { ResourcePath } from '../model/path' ;
4545import { newSerializer } from '../platform/serializer' ;
46+ import {
47+ buildQuerySnapshotJsonBundle ,
48+ buildDocumentSnapshotJsonBundle
49+ } from '../platform/snapshot_to_json' ;
4650import { fromDocument } from '../remote/serializer' ;
4751import { debugAssert , fail } from '../util/assert' ;
48- import {
49- BundleBuilder ,
50- DocumentSnapshotBundleData ,
51- QuerySnapshotBundleData
52- } from '../util/bundle_builder_impl' ;
5352import { Code , FirestoreError } from '../util/error' ;
5453// API extractor fails importing 'property' unless we also explicitly import 'Property'.
5554// eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-imports-ts
@@ -529,6 +528,13 @@ export class DocumentSnapshot<
529528 * @returns a JSON representation of this object.
530529 */
531530 toJSON ( ) : object {
531+ if ( this . metadata . hasPendingWrites ) {
532+ throw new FirestoreError (
533+ Code . FAILED_PRECONDITION ,
534+ 'DocumentSnapshot.toJSON() attempted to serialize a document with pending writes. ' +
535+ 'Await waitForPendingWrites() before invoking toJSON().'
536+ ) ;
537+ }
532538 const document = this . _document ;
533539 // eslint-disable-next-line @typescript-eslint/no-explicit-any
534540 const result : any = { } ;
@@ -544,29 +550,16 @@ export class DocumentSnapshot<
544550 ) {
545551 return result ;
546552 }
547- const builder : BundleBuilder = new BundleBuilder (
548- this . _firestore ,
549- AutoId . newId ( )
550- ) ;
551553 const documentData = this . _userDataWriter . convertObjectMap (
552554 document . data . value . mapValue . fields ,
553555 'previous'
554556 ) ;
555- if ( this . metadata . hasPendingWrites ) {
556- throw new FirestoreError (
557- Code . FAILED_PRECONDITION ,
558- 'DocumentSnapshot.toJSON() attempted to serialize a document with pending writes. ' +
559- 'Await waitForPendingWrites() before invoking toJSON().'
560- ) ;
561- }
562- builder . addBundleDocument (
563- documentToDocumentSnapshotBundleData (
564- this . ref . path ,
565- documentData ,
566- document
567- )
557+ result [ 'bundle' ] = buildDocumentSnapshotJsonBundle (
558+ this . _firestore ,
559+ document ,
560+ documentData ,
561+ this . ref . path
568562 ) ;
569- result [ 'bundle' ] = builder . build ( ) ;
570563 return result ;
571564 }
572565}
@@ -611,6 +604,12 @@ export function documentSnapshotFromJSON<
611604 converter ?: FirestoreDataConverter < AppModelType , DbModelType >
612605) : DocumentSnapshot < AppModelType , DbModelType > {
613606 if ( validateJSON ( json , DocumentSnapshot . _jsonSchema ) ) {
607+ if ( json . bundle === 'NOT SUPPORTED' ) {
608+ throw new FirestoreError (
609+ Code . INVALID_ARGUMENT ,
610+ 'The provided JSON object was created in a client environment, which is not supported.'
611+ ) ;
612+ }
614613 // Parse the bundle data.
615614 const serializer = newSerializer ( db . _databaseId ) ;
616615 const bundleReader = createBundleReaderSync ( json . bundle , serializer ) ;
@@ -825,52 +824,48 @@ export class QuerySnapshot<
825824 * @returns a JSON representation of this object.
826825 */
827826 toJSON ( ) : object {
827+ if ( this . metadata . hasPendingWrites ) {
828+ throw new FirestoreError (
829+ Code . FAILED_PRECONDITION ,
830+ 'QuerySnapshot.toJSON() attempted to serialize a document with pending writes. ' +
831+ 'Await waitForPendingWrites() before invoking toJSON().'
832+ ) ;
833+ }
828834 // eslint-disable-next-line @typescript-eslint/no-explicit-any
829835 const result : any = { } ;
830836 result [ 'type' ] = QuerySnapshot . _jsonSchemaVersion ;
831837 result [ 'bundleSource' ] = 'QuerySnapshot' ;
832838 result [ 'bundleName' ] = AutoId . newId ( ) ;
833839
834- const builder : BundleBuilder = new BundleBuilder (
835- this . _firestore ,
836- result [ 'bundleName' ]
837- ) ;
838840 const databaseId = this . _firestore . _databaseId . database ;
839841 const projectId = this . _firestore . _databaseId . projectId ;
840842 const parent = `projects/${ projectId } /databases/${ databaseId } /documents` ;
841- const docBundleDataArray : DocumentSnapshotBundleData [ ] = [ ] ;
842- const docArray = this . docs ;
843- docArray . forEach ( doc => {
843+ const documents : Document [ ] = [ ] ;
844+ const documentData : DocumentData [ ] = [ ] ;
845+ const paths : string [ ] = [ ] ;
846+
847+ this . docs . forEach ( doc => {
844848 if ( doc . _document === null ) {
845849 return ;
846850 }
847- const documentData = this . _userDataWriter . convertObjectMap (
848- doc . _document . data . value . mapValue . fields ,
849- 'previous'
850- ) ;
851- if ( this . metadata . hasPendingWrites ) {
852- throw new FirestoreError (
853- Code . FAILED_PRECONDITION ,
854- 'QuerySnapshot.toJSON() attempted to serialize a document with pending writes. ' +
855- 'Await waitForPendingWrites() before invoking toJSON().'
856- ) ;
857- }
858- docBundleDataArray . push (
859- documentToDocumentSnapshotBundleData (
860- doc . ref . path ,
861- documentData ,
862- doc . _document
851+ documents . push ( doc . _document ) ;
852+ documentData . push (
853+ this . _userDataWriter . convertObjectMap (
854+ doc . _document . data . value . mapValue . fields ,
855+ 'previous'
863856 )
864857 ) ;
858+ paths . push ( doc . ref . path ) ;
865859 } ) ;
866- const bundleData : QuerySnapshotBundleData = {
867- name : result [ 'bundleName' ] ,
868- query : this . query . _query ,
860+ result [ 'bundle' ] = buildQuerySnapshotJsonBundle (
861+ this . _firestore ,
862+ this . query . _query ,
863+ result [ 'bundleName' ] ,
869864 parent ,
870- docBundleDataArray
871- } ;
872- builder . addBundleQuery ( bundleData ) ;
873- result [ 'bundle' ] = builder . build ( ) ;
865+ paths ,
866+ documents ,
867+ documentData
868+ ) ;
874869 return result ;
875870 }
876871}
@@ -915,6 +910,12 @@ export function querySnapshotFromJSON<
915910 converter ?: FirestoreDataConverter < AppModelType , DbModelType >
916911) : QuerySnapshot < AppModelType , DbModelType > {
917912 if ( validateJSON ( json , QuerySnapshot . _jsonSchema ) ) {
913+ if ( json . bundle === 'NOT SUPPORTED' ) {
914+ throw new FirestoreError (
915+ Code . INVALID_ARGUMENT ,
916+ 'The provided JSON object was created in a client environment, which is not supported.'
917+ ) ;
918+ }
918919 // Parse the bundle data.
919920 const serializer = newSerializer ( db . _databaseId ) ;
920921 const bundleReader = createBundleReaderSync ( json . bundle , serializer ) ;
@@ -1111,20 +1112,3 @@ export function snapshotEqual<AppModelType, DbModelType extends DocumentData>(
11111112
11121113 return false ;
11131114}
1114-
1115- // Formats Document data for bundling a DocumentSnapshot.
1116- function documentToDocumentSnapshotBundleData (
1117- path : string ,
1118- documentData : DocumentData ,
1119- document : Document
1120- ) : DocumentSnapshotBundleData {
1121- return {
1122- documentData,
1123- documentKey : document . mutableCopy ( ) . key ,
1124- documentPath : path ,
1125- documentExists : true ,
1126- createdTime : document . createTime . toTimestamp ( ) ,
1127- readTime : document . readTime . toTimestamp ( ) ,
1128- versionTime : document . version . toTimestamp ( )
1129- } ;
1130- }
0 commit comments