From 4a9bc759098aa04bc9038a33277c69cfc991962b Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Thu, 24 Jun 2021 18:33:29 +0200 Subject: [PATCH] fix(NODE-3247): bump spec tests and fix up DBRef handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I wanted to bump the spec tests for NODE-3094, turns out there’s nothing to do there, but NODE-3247 breaks the tests, so I’ve made changes that align the handling with the spec here. --- src/db_ref.ts | 7 ++++++- src/extended_json.ts | 10 ++++----- test/node/specs/bson-corpus/binary.json | 14 ++++++++++++- test/node/specs/bson-corpus/dbref.json | 22 +++++++++++++++++++- test/node/specs/bson-corpus/document.json | 20 ++++++++++++++++++ test/node/specs/bson-corpus/top.json | 25 +++++++++++++++-------- 6 files changed, 81 insertions(+), 17 deletions(-) diff --git a/src/db_ref.ts b/src/db_ref.ts index a4a0e51e..53b649ff 100644 --- a/src/db_ref.ts +++ b/src/db_ref.ts @@ -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') + ); } /** diff --git a/src/extended_json.ts b/src/extended_json.ts index 07adfbba..e38cb06e 100644 --- a/src/extended_json.ts +++ b/src/extended_json.ts @@ -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'; @@ -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) @@ -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) ); } diff --git a/test/node/specs/bson-corpus/binary.json b/test/node/specs/bson-corpus/binary.json index 324c56ab..dd1ebfa1 100644 --- a/test/node/specs/bson-corpus/binary.json +++ b/test/node/specs/bson-corpus/binary.json @@ -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----\"}}" } ] } diff --git a/test/node/specs/bson-corpus/dbref.json b/test/node/specs/bson-corpus/dbref.json index 1fe12c6f..41c0b09d 100644 --- a/test/node/specs/bson-corpus/dbref.json +++ b/test/node/specs/bson-corpus/dbref.json @@ -1,5 +1,5 @@ { - "description": "DBRef", + "description": "Document type (DBRef sub-documents)", "bson_type": "0x03", "valid": [ { @@ -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\"}}}" } ] } diff --git a/test/node/specs/bson-corpus/document.json b/test/node/specs/bson-corpus/document.json index 3ec91870..10bf637d 100644 --- a/test/node/specs/bson-corpus/document.json +++ b/test/node/specs/bson-corpus/document.json @@ -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": [ diff --git a/test/node/specs/bson-corpus/top.json b/test/node/specs/bson-corpus/top.json index 5352a3fa..ce7d4cdf 100644 --- a/test/node/specs/bson-corpus/top.json +++ b/test/node/specs/bson-corpus/top.json @@ -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": [ @@ -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}}"