Skip to content

Commit

Permalink
fix(NODE-3247): DBRef special handling (#443)
Browse files Browse the repository at this point in the history
  • Loading branch information
addaleax authored Jun 25, 2021
1 parent f170d44 commit f5d984d
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 17 deletions.
7 changes: 6 additions & 1 deletion src/db_ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ export interface DBRefLike {

/** @internal */
export function isDBRefLike(value: unknown): value is DBRefLike {
return isObjectLike(value) && value['$id'] != null && value['$ref'] != null;
return (
isObjectLike(value) &&
value.$id != null &&
typeof value.$ref === 'string' &&
(value.$db == null || typeof value.$db === 'string')
);
}

/**
Expand Down
10 changes: 5 additions & 5 deletions src/extended_json.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Binary } from './binary';
import type { Document } from './bson';
import { Code } from './code';
import { DBRef } from './db_ref';
import { DBRef, isDBRefLike } from './db_ref';
import { Decimal128 } from './decimal128';
import { Double } from './double';
import { Int32 } from './int_32';
Expand Down Expand Up @@ -120,7 +120,7 @@ function deserializeValue(value: any, options: EJSON.Options = {}) {
return Code.fromExtendedJSON(value);
}

if (value.$ref != null || value.$dbPointer != null) {
if (isDBRefLike(value) || value.$dbPointer) {
const v = value.$ref ? value : value.$dbPointer;

// we run into this in a "degenerate EJSON" case (with $id and $ref order flipped)
Expand Down Expand Up @@ -310,10 +310,10 @@ function serializeDocument(doc: any, options: EJSONSerializeOptions) {
outDoc = new Code(outDoc.code, serializeValue(outDoc.scope, options));
} else if (bsontype === 'DBRef' && outDoc.oid) {
outDoc = new DBRef(
outDoc.collection,
serializeValue(outDoc.collection, options),
serializeValue(outDoc.oid, options),
outDoc.db,
outDoc.fields
serializeValue(outDoc.db, options),
serializeValue(outDoc.fields, options)
);
}

Expand Down
14 changes: 13 additions & 1 deletion test/node/specs/bson-corpus/binary.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,20 @@
"string": "{\"x\" : { \"$uuid\" : { \"data\" : \"73ffd264-44b3-4c69-90e8-e7d1dfc035d4\"}}}"
},
{
"description": "$uuid invalid value",
"description": "$uuid invalid value--too short",
"string": "{\"x\" : { \"$uuid\" : \"73ffd264-44b3-90e8-e7d1dfc035d4\"}}"
},
{
"description": "$uuid invalid value--too long",
"string": "{\"x\" : { \"$uuid\" : \"73ffd264-44b3-4c69-90e8-e7d1dfc035d4-789e4\"}}"
},
{
"description": "$uuid invalid value--misplaced hyphens",
"string": "{\"x\" : { \"$uuid\" : \"73ff-d26444b-34c6-990e8e-7d1dfc035d4\"}}"
},
{
"description": "$uuid invalid value--too many hyphens",
"string": "{\"x\" : { \"$uuid\" : \"----d264-44b3-4--9-90e8-e7d1dfc0----\"}}"
}
]
}
22 changes: 21 additions & 1 deletion test/node/specs/bson-corpus/dbref.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"description": "DBRef",
"description": "Document type (DBRef sub-documents)",
"bson_type": "0x03",
"valid": [
{
Expand All @@ -26,6 +26,26 @@
"description": "Document with key names similar to those of a DBRef",
"canonical_bson": "3e0000000224726566000c0000006e6f742d612d646272656600072469640058921b3e6e32ab156a22b59e022462616e616e6100050000007065656c0000",
"canonical_extjson": "{\"$ref\": \"not-a-dbref\", \"$id\": {\"$oid\": \"58921b3e6e32ab156a22b59e\"}, \"$banana\": \"peel\"}"
},
{
"description": "DBRef with additional dollar-prefixed and dotted fields",
"canonical_bson": "48000000036462726566003c0000000224726566000b000000636f6c6c656374696f6e00072469640058921b3e6e32ab156a22b59e10612e62000100000010246300010000000000",
"canonical_extjson": "{\"dbref\": {\"$ref\": \"collection\", \"$id\": {\"$oid\": \"58921b3e6e32ab156a22b59e\"}, \"a.b\": {\"$numberInt\": \"1\"}, \"$c\": {\"$numberInt\": \"1\"}}}"
},
{
"description": "Sub-document resembles DBRef but $id is missing",
"canonical_bson": "26000000036462726566001a0000000224726566000b000000636f6c6c656374696f6e000000",
"canonical_extjson": "{\"dbref\": {\"$ref\": \"collection\"}}"
},
{
"description": "Sub-document resembles DBRef but $ref is not a string",
"canonical_bson": "2c000000036462726566002000000010247265660001000000072469640058921b3e6e32ab156a22b59e0000",
"canonical_extjson": "{\"dbref\": {\"$ref\": {\"$numberInt\": \"1\"}, \"$id\": {\"$oid\": \"58921b3e6e32ab156a22b59e\"}}}"
},
{
"description": "Sub-document resembles DBRef but $db is not a string",
"canonical_bson": "4000000003646272656600340000000224726566000b000000636f6c6c656374696f6e00072469640058921b3e6e32ab156a22b59e1024646200010000000000",
"canonical_extjson": "{\"dbref\": {\"$ref\": \"collection\", \"$id\": {\"$oid\": \"58921b3e6e32ab156a22b59e\"}, \"$db\": {\"$numberInt\": \"1\"}}}"
}
]
}
20 changes: 20 additions & 0 deletions test/node/specs/bson-corpus/document.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,26 @@
"description": "Single-character key subdoc",
"canonical_bson": "160000000378000E0000000261000200000062000000",
"canonical_extjson": "{\"x\" : {\"a\" : \"b\"}}"
},
{
"description": "Dollar-prefixed key in sub-document",
"canonical_bson": "170000000378000F000000022461000200000062000000",
"canonical_extjson": "{\"x\" : {\"$a\" : \"b\"}}"
},
{
"description": "Dollar as key in sub-document",
"canonical_bson": "160000000378000E0000000224000200000061000000",
"canonical_extjson": "{\"x\" : {\"$\" : \"a\"}}"
},
{
"description": "Dotted key in sub-document",
"canonical_bson": "180000000378001000000002612E62000200000063000000",
"canonical_extjson": "{\"x\" : {\"a.b\" : \"c\"}}"
},
{
"description": "Dot as key in sub-document",
"canonical_bson": "160000000378000E000000022E000200000061000000",
"canonical_extjson": "{\"x\" : {\".\" : \"a\"}}"
}
],
"decodeErrors": [
Expand Down
25 changes: 16 additions & 9 deletions test/node/specs/bson-corpus/top.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,24 @@
"bson_type": "0x00",
"valid": [
{
"description": "Document with keys that start with $",
"description": "Dollar-prefixed key in top-level document",
"canonical_bson": "0F00000010246B6579002A00000000",
"canonical_extjson": "{\"$key\": {\"$numberInt\": \"42\"}}"
},
{
"description": "Dollar as key in top-level document",
"canonical_bson": "0E00000002240002000000610000",
"canonical_extjson": "{\"$\": \"a\"}"
},
{
"description": "Dotted key in top-level document",
"canonical_bson": "1000000002612E620002000000630000",
"canonical_extjson": "{\"a.b\": \"c\"}"
},
{
"description": "Dot as key in top-level document",
"canonical_bson": "0E000000022E0002000000610000",
"canonical_extjson": "{\".\": \"a\"}"
}
],
"decodeErrors": [
Expand Down Expand Up @@ -199,14 +214,6 @@
"description": "Bad $date (extra field)",
"string": "{\"a\" : {\"$date\" : {\"$numberLong\" : \"1356351330501\"}, \"unrelated\": true}}"
},
{
"description": "Bad DBRef (ref is number, not string)",
"string": "{\"x\" : {\"$ref\" : 42, \"$id\" : \"abc\"}}"
},
{
"description": "Bad DBRef (db is number, not string)",
"string": "{\"x\" : {\"$ref\" : \"a\", \"$id\" : \"abc\", \"$db\" : 42}}"
},
{
"description": "Bad $minKey (boolean, not integer)",
"string": "{\"a\" : {\"$minKey\" : true}}"
Expand Down

0 comments on commit f5d984d

Please sign in to comment.