Skip to content
This repository has been archived by the owner on Sep 23, 2024. It is now read-only.

Commit

Permalink
perf(NODE-3570): short circuit check for keys that start with $ (#78)
Browse files Browse the repository at this point in the history
  • Loading branch information
znewsham authored Sep 7, 2021
1 parent af3e7b1 commit f101dc8
Showing 1 changed file with 37 additions and 31 deletions.
68 changes: 37 additions & 31 deletions src/bson.cc
Original file line number Diff line number Diff line change
Expand Up @@ -769,9 +769,13 @@ Local<Value> BSONDeserializer::DeserializeDocumentInternal() {
Local<Object> returnObject = Unmaybe(Nan::New<Object>());
Local<String> propertyName;
bool raw = false;
bool hasDollar = false;

while (HasMoreData()) {
BsonType type = (BsonType)ReadByte();
if (*p == '$') {
hasDollar = true;
}
const Local<Value> &name = ReadCString();
if (name->IsNull())
ThrowAllocatedStringException(64, "Bad BSON Document: illegal CString");
Expand Down Expand Up @@ -806,43 +810,45 @@ Local<Value> BSONDeserializer::DeserializeDocumentInternal() {
64, "Bad BSON Document: Serialize consumed unexpected number of bytes");

// Determine if we need to return a DBRef or not
Local<Value> dbRefRefValue = NanGet(returnObject, DBREF_REF_PROPERTY_NAME);
Local<Value> dbRefIdValue = NanGet(returnObject, DBREF_ID_REF_PROPERTY_NAME);
Local<Value> dbRefDbValue = NanGet(returnObject, DBREF_DB_REF_PROPERTY_NAME);
if (!dbRefRefValue->IsUndefined() && !dbRefIdValue->IsUndefined()) {
Local<Object> fieldsObject = Unmaybe(Nan::New<Object>());
Local<Array> propertyNames = Unmaybe(Nan::GetPropertyNames(returnObject));
int propertyLength = propertyNames->Length();
for (int i = 0; i < propertyLength; ++i) {
propertyName = NanToString(NanGet(propertyNames, i));
if (hasDollar) {
Local<Value> dbRefRefValue = NanGet(returnObject, DBREF_REF_PROPERTY_NAME);
Local<Value> dbRefIdValue = NanGet(returnObject, DBREF_ID_REF_PROPERTY_NAME);
Local<Value> dbRefDbValue = NanGet(returnObject, DBREF_DB_REF_PROPERTY_NAME);
if (!dbRefRefValue->IsUndefined() && !dbRefIdValue->IsUndefined()) {
Local<Object> fieldsObject = Unmaybe(Nan::New<Object>());
Local<Array> propertyNames = Unmaybe(Nan::GetPropertyNames(returnObject));
int propertyLength = propertyNames->Length();
for (int i = 0; i < propertyLength; ++i) {
propertyName = NanToString(NanGet(propertyNames, i));

// First check if we have an invalid escaped key
std::string check(*Nan::Utf8String(propertyName));
// First check if we have an invalid escaped key
std::string check(*Nan::Utf8String(propertyName));

if (check[0] == '$' &&
(strcmp(check.c_str(), DBREF_REF_PROPERTY_NAME) != 0 &&
strcmp(check.c_str(), DBREF_ID_REF_PROPERTY_NAME) != 0 &&
strcmp(check.c_str(), DBREF_DB_REF_PROPERTY_NAME) != 0)) {
// this is not a proper DBRef, we're safe to just return the
// returnObject
return returnObject;
}
if (check[0] == '$' &&
(strcmp(check.c_str(), DBREF_REF_PROPERTY_NAME) != 0 &&
strcmp(check.c_str(), DBREF_ID_REF_PROPERTY_NAME) != 0 &&
strcmp(check.c_str(), DBREF_DB_REF_PROPERTY_NAME) != 0)) {
// this is not a proper DBRef, we're safe to just return the
// returnObject
return returnObject;
}

// Now build up the `fields` object
if (strcmp(check.c_str(), DBREF_REF_PROPERTY_NAME) == 0 ||
strcmp(check.c_str(), DBREF_ID_REF_PROPERTY_NAME) == 0 ||
strcmp(check.c_str(), DBREF_DB_REF_PROPERTY_NAME) == 0) {
continue;
// Now build up the `fields` object
if (strcmp(check.c_str(), DBREF_REF_PROPERTY_NAME) == 0 ||
strcmp(check.c_str(), DBREF_ID_REF_PROPERTY_NAME) == 0 ||
strcmp(check.c_str(), DBREF_DB_REF_PROPERTY_NAME) == 0) {
continue;
}

Nan::Set(fieldsObject, propertyName, NanGet(returnObject, propertyName));
}

Nan::Set(fieldsObject, propertyName, NanGet(returnObject, propertyName));
Local<Value> argv[] = {dbRefRefValue, dbRefIdValue, dbRefDbValue,
fieldsObject};
Nan::MaybeLocal<Object> obj =
Nan::NewInstance(Nan::New(bson->dbrefConstructor), 4, argv);
return obj.ToLocalChecked();
}

Local<Value> argv[] = {dbRefRefValue, dbRefIdValue, dbRefDbValue,
fieldsObject};
Nan::MaybeLocal<Object> obj =
Nan::NewInstance(Nan::New(bson->dbrefConstructor), 4, argv);
return obj.ToLocalChecked();
}

return returnObject;
Expand Down

0 comments on commit f101dc8

Please sign in to comment.