Skip to content

Commit f5d984d

Browse files
authored
fix(NODE-3247): DBRef special handling (#443)
1 parent f170d44 commit f5d984d

File tree

6 files changed

+81
-17
lines changed

6 files changed

+81
-17
lines changed

src/db_ref.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@ export interface DBRefLike {
1212

1313
/** @internal */
1414
export function isDBRefLike(value: unknown): value is DBRefLike {
15-
return isObjectLike(value) && value['$id'] != null && value['$ref'] != null;
15+
return (
16+
isObjectLike(value) &&
17+
value.$id != null &&
18+
typeof value.$ref === 'string' &&
19+
(value.$db == null || typeof value.$db === 'string')
20+
);
1621
}
1722

1823
/**

src/extended_json.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Binary } from './binary';
22
import type { Document } from './bson';
33
import { Code } from './code';
4-
import { DBRef } from './db_ref';
4+
import { DBRef, isDBRefLike } from './db_ref';
55
import { Decimal128 } from './decimal128';
66
import { Double } from './double';
77
import { Int32 } from './int_32';
@@ -120,7 +120,7 @@ function deserializeValue(value: any, options: EJSON.Options = {}) {
120120
return Code.fromExtendedJSON(value);
121121
}
122122

123-
if (value.$ref != null || value.$dbPointer != null) {
123+
if (isDBRefLike(value) || value.$dbPointer) {
124124
const v = value.$ref ? value : value.$dbPointer;
125125

126126
// we run into this in a "degenerate EJSON" case (with $id and $ref order flipped)
@@ -310,10 +310,10 @@ function serializeDocument(doc: any, options: EJSONSerializeOptions) {
310310
outDoc = new Code(outDoc.code, serializeValue(outDoc.scope, options));
311311
} else if (bsontype === 'DBRef' && outDoc.oid) {
312312
outDoc = new DBRef(
313-
outDoc.collection,
313+
serializeValue(outDoc.collection, options),
314314
serializeValue(outDoc.oid, options),
315-
outDoc.db,
316-
outDoc.fields
315+
serializeValue(outDoc.db, options),
316+
serializeValue(outDoc.fields, options)
317317
);
318318
}
319319

test/node/specs/bson-corpus/binary.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,20 @@
9494
"string": "{\"x\" : { \"$uuid\" : { \"data\" : \"73ffd264-44b3-4c69-90e8-e7d1dfc035d4\"}}}"
9595
},
9696
{
97-
"description": "$uuid invalid value",
97+
"description": "$uuid invalid value--too short",
9898
"string": "{\"x\" : { \"$uuid\" : \"73ffd264-44b3-90e8-e7d1dfc035d4\"}}"
99+
},
100+
{
101+
"description": "$uuid invalid value--too long",
102+
"string": "{\"x\" : { \"$uuid\" : \"73ffd264-44b3-4c69-90e8-e7d1dfc035d4-789e4\"}}"
103+
},
104+
{
105+
"description": "$uuid invalid value--misplaced hyphens",
106+
"string": "{\"x\" : { \"$uuid\" : \"73ff-d26444b-34c6-990e8e-7d1dfc035d4\"}}"
107+
},
108+
{
109+
"description": "$uuid invalid value--too many hyphens",
110+
"string": "{\"x\" : { \"$uuid\" : \"----d264-44b3-4--9-90e8-e7d1dfc0----\"}}"
99111
}
100112
]
101113
}

test/node/specs/bson-corpus/dbref.json

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"description": "DBRef",
2+
"description": "Document type (DBRef sub-documents)",
33
"bson_type": "0x03",
44
"valid": [
55
{
@@ -26,6 +26,26 @@
2626
"description": "Document with key names similar to those of a DBRef",
2727
"canonical_bson": "3e0000000224726566000c0000006e6f742d612d646272656600072469640058921b3e6e32ab156a22b59e022462616e616e6100050000007065656c0000",
2828
"canonical_extjson": "{\"$ref\": \"not-a-dbref\", \"$id\": {\"$oid\": \"58921b3e6e32ab156a22b59e\"}, \"$banana\": \"peel\"}"
29+
},
30+
{
31+
"description": "DBRef with additional dollar-prefixed and dotted fields",
32+
"canonical_bson": "48000000036462726566003c0000000224726566000b000000636f6c6c656374696f6e00072469640058921b3e6e32ab156a22b59e10612e62000100000010246300010000000000",
33+
"canonical_extjson": "{\"dbref\": {\"$ref\": \"collection\", \"$id\": {\"$oid\": \"58921b3e6e32ab156a22b59e\"}, \"a.b\": {\"$numberInt\": \"1\"}, \"$c\": {\"$numberInt\": \"1\"}}}"
34+
},
35+
{
36+
"description": "Sub-document resembles DBRef but $id is missing",
37+
"canonical_bson": "26000000036462726566001a0000000224726566000b000000636f6c6c656374696f6e000000",
38+
"canonical_extjson": "{\"dbref\": {\"$ref\": \"collection\"}}"
39+
},
40+
{
41+
"description": "Sub-document resembles DBRef but $ref is not a string",
42+
"canonical_bson": "2c000000036462726566002000000010247265660001000000072469640058921b3e6e32ab156a22b59e0000",
43+
"canonical_extjson": "{\"dbref\": {\"$ref\": {\"$numberInt\": \"1\"}, \"$id\": {\"$oid\": \"58921b3e6e32ab156a22b59e\"}}}"
44+
},
45+
{
46+
"description": "Sub-document resembles DBRef but $db is not a string",
47+
"canonical_bson": "4000000003646272656600340000000224726566000b000000636f6c6c656374696f6e00072469640058921b3e6e32ab156a22b59e1024646200010000000000",
48+
"canonical_extjson": "{\"dbref\": {\"$ref\": \"collection\", \"$id\": {\"$oid\": \"58921b3e6e32ab156a22b59e\"}, \"$db\": {\"$numberInt\": \"1\"}}}"
2949
}
3050
]
3151
}

test/node/specs/bson-corpus/document.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,26 @@
1717
"description": "Single-character key subdoc",
1818
"canonical_bson": "160000000378000E0000000261000200000062000000",
1919
"canonical_extjson": "{\"x\" : {\"a\" : \"b\"}}"
20+
},
21+
{
22+
"description": "Dollar-prefixed key in sub-document",
23+
"canonical_bson": "170000000378000F000000022461000200000062000000",
24+
"canonical_extjson": "{\"x\" : {\"$a\" : \"b\"}}"
25+
},
26+
{
27+
"description": "Dollar as key in sub-document",
28+
"canonical_bson": "160000000378000E0000000224000200000061000000",
29+
"canonical_extjson": "{\"x\" : {\"$\" : \"a\"}}"
30+
},
31+
{
32+
"description": "Dotted key in sub-document",
33+
"canonical_bson": "180000000378001000000002612E62000200000063000000",
34+
"canonical_extjson": "{\"x\" : {\"a.b\" : \"c\"}}"
35+
},
36+
{
37+
"description": "Dot as key in sub-document",
38+
"canonical_bson": "160000000378000E000000022E000200000061000000",
39+
"canonical_extjson": "{\"x\" : {\".\" : \"a\"}}"
2040
}
2141
],
2242
"decodeErrors": [

test/node/specs/bson-corpus/top.json

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,24 @@
33
"bson_type": "0x00",
44
"valid": [
55
{
6-
"description": "Document with keys that start with $",
6+
"description": "Dollar-prefixed key in top-level document",
77
"canonical_bson": "0F00000010246B6579002A00000000",
88
"canonical_extjson": "{\"$key\": {\"$numberInt\": \"42\"}}"
9+
},
10+
{
11+
"description": "Dollar as key in top-level document",
12+
"canonical_bson": "0E00000002240002000000610000",
13+
"canonical_extjson": "{\"$\": \"a\"}"
14+
},
15+
{
16+
"description": "Dotted key in top-level document",
17+
"canonical_bson": "1000000002612E620002000000630000",
18+
"canonical_extjson": "{\"a.b\": \"c\"}"
19+
},
20+
{
21+
"description": "Dot as key in top-level document",
22+
"canonical_bson": "0E000000022E0002000000610000",
23+
"canonical_extjson": "{\".\": \"a\"}"
924
}
1025
],
1126
"decodeErrors": [
@@ -199,14 +214,6 @@
199214
"description": "Bad $date (extra field)",
200215
"string": "{\"a\" : {\"$date\" : {\"$numberLong\" : \"1356351330501\"}, \"unrelated\": true}}"
201216
},
202-
{
203-
"description": "Bad DBRef (ref is number, not string)",
204-
"string": "{\"x\" : {\"$ref\" : 42, \"$id\" : \"abc\"}}"
205-
},
206-
{
207-
"description": "Bad DBRef (db is number, not string)",
208-
"string": "{\"x\" : {\"$ref\" : \"a\", \"$id\" : \"abc\", \"$db\" : 42}}"
209-
},
210217
{
211218
"description": "Bad $minKey (boolean, not integer)",
212219
"string": "{\"a\" : {\"$minKey\" : true}}"

0 commit comments

Comments
 (0)