Code Duplication    Length = 391-391 lines in 2 locations

formio/node_modules/bson/browser_build/bson.js 1 location

@@ 14305-14695 (lines=391) @@
14302
	  return deserializeObject(buffer, index, options, isArray);
14303
	};
14304
14305
	var deserializeObject = function (buffer, index, options, isArray) {
14306
	  var evalFunctions = options['evalFunctions'] == null ? false : options['evalFunctions'];
14307
	  var cacheFunctions = options['cacheFunctions'] == null ? false : options['cacheFunctions'];
14308
	  var cacheFunctionsCrc32 = options['cacheFunctionsCrc32'] == null ? false : options['cacheFunctionsCrc32'];
14309
	  var fieldsAsRaw = options['fieldsAsRaw'] == null ? null : options['fieldsAsRaw'];
14310
14311
	  // Return raw bson buffer instead of parsing it
14312
	  var raw = options['raw'] == null ? false : options['raw'];
14313
14314
	  // Return BSONRegExp objects instead of native regular expressions
14315
	  var bsonRegExp = typeof options['bsonRegExp'] == 'boolean' ? options['bsonRegExp'] : false;
14316
14317
	  // Controls the promotion of values vs wrapper classes
14318
	  var promoteBuffers = options['promoteBuffers'] == null ? false : options['promoteBuffers'];
14319
	  var promoteLongs = options['promoteLongs'] == null ? true : options['promoteLongs'];
14320
	  var promoteValues = options['promoteValues'] == null ? true : options['promoteValues'];
14321
14322
	  // Set the start index
14323
	  var startIndex = index;
14324
14325
	  // Validate that we have at least 4 bytes of buffer
14326
	  if (buffer.length < 5) throw new Error("corrupt bson message < 5 bytes long");
14327
14328
	  // Read the document size
14329
	  var size = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
14330
14331
	  // Ensure buffer is valid size
14332
	  if (size < 5 || size > buffer.length) throw new Error("corrupt bson message");
14333
14334
	  // Create holding object
14335
	  var object = isArray ? [] : {};
14336
	  // Used for arrays to skip having to perform utf8 decoding
14337
	  var arrayIndex = 0;
14338
14339
	  // While we have more left data left keep parsing
14340
	  while (true) {
14341
	    // Read the type
14342
	    var elementType = buffer[index++];
14343
	    // If we get a zero it's the last byte, exit
14344
	    if (elementType == 0) {
14345
	      break;
14346
	    }
14347
14348
	    // Get the start search index
14349
	    var i = index;
14350
	    // Locate the end of the c string
14351
	    while (buffer[i] !== 0x00 && i < buffer.length) {
14352
	      i++;
14353
	    }
14354
14355
	    // If are at the end of the buffer there is a problem with the document
14356
	    if (i >= buffer.length) throw new Error("Bad BSON Document: illegal CString");
14357
	    var name = isArray ? arrayIndex++ : buffer.toString('utf8', index, i);
14358
14359
	    index = i + 1;
14360
14361
	    if (elementType == BSON.BSON_DATA_STRING) {
14362
	      var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
14363
	      if (stringSize <= 0 || stringSize > buffer.length - index || buffer[index + stringSize - 1] != 0) throw new Error("bad string length in bson");
14364
	      object[name] = buffer.toString('utf8', index, index + stringSize - 1);
14365
	      index = index + stringSize;
14366
	    } else if (elementType == BSON.BSON_DATA_OID) {
14367
	      var oid = new Buffer(12);
14368
	      buffer.copy(oid, 0, index, index + 12);
14369
	      object[name] = new ObjectID(oid);
14370
	      index = index + 12;
14371
	    } else if (elementType == BSON.BSON_DATA_INT && promoteValues == false) {
14372
	      object[name] = new Int32(buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24);
14373
	    } else if (elementType == BSON.BSON_DATA_INT) {
14374
	      object[name] = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
14375
	    } else if (elementType == BSON.BSON_DATA_NUMBER && promoteValues == false) {
14376
	      object[name] = new Double(buffer.readDoubleLE(index));
14377
	      index = index + 8;
14378
	    } else if (elementType == BSON.BSON_DATA_NUMBER) {
14379
	      object[name] = buffer.readDoubleLE(index);
14380
	      index = index + 8;
14381
	    } else if (elementType == BSON.BSON_DATA_DATE) {
14382
	      var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
14383
	      var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
14384
	      object[name] = new Date(new Long(lowBits, highBits).toNumber());
14385
	    } else if (elementType == BSON.BSON_DATA_BOOLEAN) {
14386
	      if (buffer[index] != 0 && buffer[index] != 1) throw new Error('illegal boolean type value');
14387
	      object[name] = buffer[index++] == 1;
14388
	    } else if (elementType == BSON.BSON_DATA_OBJECT) {
14389
	      var _index = index;
14390
	      var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
14391
	      if (objectSize <= 0 || objectSize > buffer.length - index) throw new Error("bad embedded document length in bson");
14392
14393
	      // We have a raw value
14394
	      if (raw) {
14395
	        object[name] = buffer.slice(index, index + objectSize);
14396
	      } else {
14397
	        object[name] = deserializeObject(buffer, _index, options, false);
14398
	      }
14399
14400
	      index = index + objectSize;
14401
	    } else if (elementType == BSON.BSON_DATA_ARRAY) {
14402
	      var _index = index;
14403
	      var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
14404
	      var arrayOptions = options;
14405
14406
	      // Stop index
14407
	      var stopIndex = index + objectSize;
14408
14409
	      // All elements of array to be returned as raw bson
14410
	      if (fieldsAsRaw && fieldsAsRaw[name]) {
14411
	        arrayOptions = {};
14412
	        for (var n in options) arrayOptions[n] = options[n];
14413
	        arrayOptions['raw'] = true;
14414
	      }
14415
14416
	      object[name] = deserializeObject(buffer, _index, arrayOptions, true);
14417
	      index = index + objectSize;
14418
14419
	      if (buffer[index - 1] != 0) throw new Error('invalid array terminator byte');
14420
	      if (index != stopIndex) throw new Error('corrupted array bson');
14421
	    } else if (elementType == BSON.BSON_DATA_UNDEFINED) {
14422
	      object[name] = undefined;
14423
	    } else if (elementType == BSON.BSON_DATA_NULL) {
14424
	      object[name] = null;
14425
	    } else if (elementType == BSON.BSON_DATA_LONG) {
14426
	      // Unpack the low and high bits
14427
	      var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
14428
	      var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
14429
	      var long = new Long(lowBits, highBits);
14430
	      // Promote the long if possible
14431
	      if (promoteLongs && promoteValues == true) {
14432
	        object[name] = long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG) ? long.toNumber() : long;
14433
	      } else {
14434
	        object[name] = long;
14435
	      }
14436
	    } else if (elementType == BSON.BSON_DATA_DECIMAL128) {
14437
	      // Buffer to contain the decimal bytes
14438
	      var bytes = new Buffer(16);
14439
	      // Copy the next 16 bytes into the bytes buffer
14440
	      buffer.copy(bytes, 0, index, index + 16);
14441
	      // Update index
14442
	      index = index + 16;
14443
	      // Assign the new Decimal128 value
14444
	      var decimal128 = new Decimal128(bytes);
14445
	      // If we have an alternative mapper use that
14446
	      object[name] = decimal128.toObject ? decimal128.toObject() : decimal128;
14447
	    } else if (elementType == BSON.BSON_DATA_BINARY) {
14448
	      var binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
14449
	      var totalBinarySize = binarySize;
14450
	      var subType = buffer[index++];
14451
14452
	      // Did we have a negative binary size, throw
14453
	      if (binarySize < 0) throw new Error('Negative binary type element size found');
14454
14455
	      // Is the length longer than the document
14456
	      if (binarySize > buffer.length) throw new Error('Binary type size larger than document size');
14457
14458
	      // Decode as raw Buffer object if options specifies it
14459
	      if (buffer['slice'] != null) {
14460
	        // If we have subtype 2 skip the 4 bytes for the size
14461
	        if (subType == Binary.SUBTYPE_BYTE_ARRAY) {
14462
	          binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
14463
	          if (binarySize < 0) throw new Error('Negative binary type element size found for subtype 0x02');
14464
	          if (binarySize > totalBinarySize - 4) throw new Error('Binary type with subtype 0x02 contains to long binary size');
14465
	          if (binarySize < totalBinarySize - 4) throw new Error('Binary type with subtype 0x02 contains to short binary size');
14466
	        }
14467
14468
	        if (promoteBuffers && promoteValues) {
14469
	          object[name] = buffer.slice(index, index + binarySize);
14470
	        } else {
14471
	          object[name] = new Binary(buffer.slice(index, index + binarySize), subType);
14472
	        }
14473
	      } else {
14474
	        var _buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(binarySize)) : new Array(binarySize);
14475
	        // If we have subtype 2 skip the 4 bytes for the size
14476
	        if (subType == Binary.SUBTYPE_BYTE_ARRAY) {
14477
	          binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
14478
	          if (binarySize < 0) throw new Error('Negative binary type element size found for subtype 0x02');
14479
	          if (binarySize > totalBinarySize - 4) throw new Error('Binary type with subtype 0x02 contains to long binary size');
14480
	          if (binarySize < totalBinarySize - 4) throw new Error('Binary type with subtype 0x02 contains to short binary size');
14481
	        }
14482
14483
	        // Copy the data
14484
	        for (var i = 0; i < binarySize; i++) {
14485
	          _buffer[i] = buffer[index + i];
14486
	        }
14487
14488
	        if (promoteBuffers && promoteValues) {
14489
	          object[name] = _buffer;
14490
	        } else {
14491
	          object[name] = new Binary(_buffer, subType);
14492
	        }
14493
	      }
14494
14495
	      // Update the index
14496
	      index = index + binarySize;
14497
	    } else if (elementType == BSON.BSON_DATA_REGEXP && bsonRegExp == false) {
14498
	      // Get the start search index
14499
	      var i = index;
14500
	      // Locate the end of the c string
14501
	      while (buffer[i] !== 0x00 && i < buffer.length) {
14502
	        i++;
14503
	      }
14504
	      // If are at the end of the buffer there is a problem with the document
14505
	      if (i >= buffer.length) throw new Error("Bad BSON Document: illegal CString");
14506
	      // Return the C string
14507
	      var source = buffer.toString('utf8', index, i);
14508
	      // Create the regexp
14509
	      index = i + 1;
14510
14511
	      // Get the start search index
14512
	      var i = index;
14513
	      // Locate the end of the c string
14514
	      while (buffer[i] !== 0x00 && i < buffer.length) {
14515
	        i++;
14516
	      }
14517
	      // If are at the end of the buffer there is a problem with the document
14518
	      if (i >= buffer.length) throw new Error("Bad BSON Document: illegal CString");
14519
	      // Return the C string
14520
	      var regExpOptions = buffer.toString('utf8', index, i);
14521
	      index = i + 1;
14522
14523
	      // For each option add the corresponding one for javascript
14524
	      var optionsArray = new Array(regExpOptions.length);
14525
14526
	      // Parse options
14527
	      for (var i = 0; i < regExpOptions.length; i++) {
14528
	        switch (regExpOptions[i]) {
14529
	          case 'm':
14530
	            optionsArray[i] = 'm';
14531
	            break;
14532
	          case 's':
14533
	            optionsArray[i] = 'g';
14534
	            break;
14535
	          case 'i':
14536
	            optionsArray[i] = 'i';
14537
	            break;
14538
	        }
14539
	      }
14540
14541
	      object[name] = new RegExp(source, optionsArray.join(''));
14542
	    } else if (elementType == BSON.BSON_DATA_REGEXP && bsonRegExp == true) {
14543
	      // Get the start search index
14544
	      var i = index;
14545
	      // Locate the end of the c string
14546
	      while (buffer[i] !== 0x00 && i < buffer.length) {
14547
	        i++;
14548
	      }
14549
	      // If are at the end of the buffer there is a problem with the document
14550
	      if (i >= buffer.length) throw new Error("Bad BSON Document: illegal CString");
14551
	      // Return the C string
14552
	      var source = buffer.toString('utf8', index, i);
14553
	      index = i + 1;
14554
14555
	      // Get the start search index
14556
	      var i = index;
14557
	      // Locate the end of the c string
14558
	      while (buffer[i] !== 0x00 && i < buffer.length) {
14559
	        i++;
14560
	      }
14561
	      // If are at the end of the buffer there is a problem with the document
14562
	      if (i >= buffer.length) throw new Error("Bad BSON Document: illegal CString");
14563
	      // Return the C string
14564
	      var regExpOptions = buffer.toString('utf8', index, i);
14565
	      index = i + 1;
14566
14567
	      // Set the object
14568
	      object[name] = new BSONRegExp(source, regExpOptions);
14569
	    } else if (elementType == BSON.BSON_DATA_SYMBOL) {
14570
	      var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
14571
	      if (stringSize <= 0 || stringSize > buffer.length - index || buffer[index + stringSize - 1] != 0) throw new Error("bad string length in bson");
14572
	      object[name] = new Symbol(buffer.toString('utf8', index, index + stringSize - 1));
14573
	      index = index + stringSize;
14574
	    } else if (elementType == BSON.BSON_DATA_TIMESTAMP) {
14575
	      var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
14576
	      var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
14577
	      object[name] = new Timestamp(lowBits, highBits);
14578
	    } else if (elementType == BSON.BSON_DATA_MIN_KEY) {
14579
	      object[name] = new MinKey();
14580
	    } else if (elementType == BSON.BSON_DATA_MAX_KEY) {
14581
	      object[name] = new MaxKey();
14582
	    } else if (elementType == BSON.BSON_DATA_CODE) {
14583
	      var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
14584
	      if (stringSize <= 0 || stringSize > buffer.length - index || buffer[index + stringSize - 1] != 0) throw new Error("bad string length in bson");
14585
	      var functionString = buffer.toString('utf8', index, index + stringSize - 1);
14586
14587
	      // If we are evaluating the functions
14588
	      if (evalFunctions) {
14589
	        var value = null;
14590
	        // If we have cache enabled let's look for the md5 of the function in the cache
14591
	        if (cacheFunctions) {
14592
	          var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString;
14593
	          // Got to do this to avoid V8 deoptimizing the call due to finding eval
14594
	          object[name] = isolateEvalWithHash(functionCache, hash, functionString, object);
14595
	        } else {
14596
	          object[name] = isolateEval(functionString);
14597
	        }
14598
	      } else {
14599
	        object[name] = new Code(functionString);
14600
	      }
14601
14602
	      // Update parse index position
14603
	      index = index + stringSize;
14604
	    } else if (elementType == BSON.BSON_DATA_CODE_W_SCOPE) {
14605
	      var totalSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
14606
14607
	      // Element cannot be shorter than totalSize + stringSize + documentSize + terminator
14608
	      if (totalSize < 4 + 4 + 4 + 1) {
14609
	        throw new Error("code_w_scope total size shorter minimum expected length");
14610
	      }
14611
14612
	      // Get the code string size
14613
	      var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
14614
	      // Check if we have a valid string
14615
	      if (stringSize <= 0 || stringSize > buffer.length - index || buffer[index + stringSize - 1] != 0) throw new Error("bad string length in bson");
14616
14617
	      // Javascript function
14618
	      var functionString = buffer.toString('utf8', index, index + stringSize - 1);
14619
	      // Update parse index position
14620
	      index = index + stringSize;
14621
	      // Parse the element
14622
	      var _index = index;
14623
	      // Decode the size of the object document
14624
	      var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
14625
	      // Decode the scope object
14626
	      var scopeObject = deserializeObject(buffer, _index, options, false);
14627
	      // Adjust the index
14628
	      index = index + objectSize;
14629
14630
	      // Check if field length is to short
14631
	      if (totalSize < 4 + 4 + objectSize + stringSize) {
14632
	        throw new Error('code_w_scope total size is to short, truncating scope');
14633
	      }
14634
14635
	      // Check if totalSize field is to long
14636
	      if (totalSize > 4 + 4 + objectSize + stringSize) {
14637
	        throw new Error('code_w_scope total size is to long, clips outer document');
14638
	      }
14639
14640
	      // If we are evaluating the functions
14641
	      if (evalFunctions) {
14642
	        // Contains the value we are going to set
14643
	        var value = null;
14644
	        // If we have cache enabled let's look for the md5 of the function in the cache
14645
	        if (cacheFunctions) {
14646
	          var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString;
14647
	          // Got to do this to avoid V8 deoptimizing the call due to finding eval
14648
	          object[name] = isolateEvalWithHash(functionCache, hash, functionString, object);
14649
	        } else {
14650
	          object[name] = isolateEval(functionString);
14651
	        }
14652
14653
	        object[name].scope = scopeObject;
14654
	      } else {
14655
	        object[name] = new Code(functionString, scopeObject);
14656
	      }
14657
	    } else if (elementType == BSON.BSON_DATA_DBPOINTER) {
14658
	      // Get the code string size
14659
	      var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
14660
	      // Check if we have a valid string
14661
	      if (stringSize <= 0 || stringSize > buffer.length - index || buffer[index + stringSize - 1] != 0) throw new Error("bad string length in bson");
14662
	      // Namespace
14663
	      var namespace = buffer.toString('utf8', index, index + stringSize - 1);
14664
	      // Update parse index position
14665
	      index = index + stringSize;
14666
14667
	      // Read the oid
14668
	      var oidBuffer = new Buffer(12);
14669
	      buffer.copy(oidBuffer, 0, index, index + 12);
14670
	      var oid = new ObjectID(oidBuffer);
14671
14672
	      // Update the index
14673
	      index = index + 12;
14674
14675
	      // Split the namespace
14676
	      var parts = namespace.split('.');
14677
	      var db = parts.shift();
14678
	      var collection = parts.join('.');
14679
	      // Upgrade to DBRef type
14680
	      object[name] = new DBRef(collection, oid, db);
14681
	    } else {
14682
	      throw new Error("Detected unknown BSON type " + elementType.toString(16) + " for fieldname \"" + name + "\", are you using the latest BSON parser");
14683
	    }
14684
	  }
14685
14686
	  // Check if the deserialization was against a valid array/object
14687
	  if (size != index - startIndex) {
14688
	    if (isArray) throw new Error('corrupt array bson');
14689
	    throw new Error('corrupt object bson');
14690
	  }
14691
14692
	  // Check if we have a db ref object
14693
	  if (object['$id'] != null) object = new DBRef(object['$ref'], object['$id'], object['$db']);
14694
	  return object;
14695
	};
14696
14697
	/**
14698
	 * Ensure eval is isolated.

formio/node_modules/bson/lib/bson/parser/deserializer.js 1 location

@@ 39-429 (lines=391) @@
36
	return deserializeObject(buffer, index, options, isArray);
37
}
38
39
var deserializeObject = function(buffer, index, options, isArray) {
40
	var evalFunctions = options['evalFunctions'] == null ? false : options['evalFunctions'];
41
  var cacheFunctions = options['cacheFunctions'] == null ? false : options['cacheFunctions'];
42
  var cacheFunctionsCrc32 = options['cacheFunctionsCrc32'] == null ? false : options['cacheFunctionsCrc32'];
43
	var fieldsAsRaw = options['fieldsAsRaw'] == null ? null : options['fieldsAsRaw'];
44
45
	// Return raw bson buffer instead of parsing it
46
	var raw = options['raw'] == null ? false : options['raw'];
47
48
	// Return BSONRegExp objects instead of native regular expressions
49
  var bsonRegExp = typeof options['bsonRegExp'] == 'boolean' ? options['bsonRegExp'] : false;
50
51
	// Controls the promotion of values vs wrapper classes
52
	var promoteBuffers = options['promoteBuffers'] == null ? false : options['promoteBuffers'];
53
	var promoteLongs = options['promoteLongs'] == null ? true : options['promoteLongs'];
54
	var promoteValues = options['promoteValues'] == null ? true : options['promoteValues'];
55
56
	// Set the start index
57
	var startIndex = index;
58
59
  // Validate that we have at least 4 bytes of buffer
60
  if(buffer.length < 5) throw new Error("corrupt bson message < 5 bytes long");
61
62
	// Read the document size
63
  var size = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
64
65
	// Ensure buffer is valid size
66
  if(size < 5 || size > buffer.length) throw new Error("corrupt bson message");
67
68
  // Create holding object
69
  var object = isArray ? [] : {};
70
	// Used for arrays to skip having to perform utf8 decoding
71
	var arrayIndex = 0;
72
73
  // While we have more left data left keep parsing
74
  while(true) {
75
    // Read the type
76
    var elementType = buffer[index++];
77
    // If we get a zero it's the last byte, exit
78
    if(elementType == 0) {
79
			break;
80
		}
81
82
		// Get the start search index
83
		var i = index;
84
		// Locate the end of the c string
85
		while(buffer[i] !== 0x00 && i < buffer.length) {
86
			i++
87
		}
88
89
		// If are at the end of the buffer there is a problem with the document
90
		if(i >= buffer.length) throw new Error("Bad BSON Document: illegal CString")
91
		var name = isArray ? arrayIndex++ : buffer.toString('utf8', index, i);
92
93
		index = i + 1;
94
95
		if(elementType == BSON.BSON_DATA_STRING) {
96
      var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
97
			if(stringSize <= 0 || stringSize > (buffer.length - index) || buffer[index + stringSize - 1] != 0) throw new Error("bad string length in bson");
98
      object[name] = buffer.toString('utf8', index, index + stringSize - 1);
99
      index = index + stringSize;
100
		} else if(elementType == BSON.BSON_DATA_OID) {
101
			var oid = new Buffer(12);
102
			buffer.copy(oid, 0, index, index + 12);
103
      object[name] = new ObjectID(oid);
104
      index = index + 12;
105
		} else if(elementType == BSON.BSON_DATA_INT && promoteValues == false) {
106
			object[name] = new Int32(buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24);
107
		} else if(elementType == BSON.BSON_DATA_INT) {
108
      object[name] = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
109
		} else if(elementType == BSON.BSON_DATA_NUMBER && promoteValues == false) {
110
			object[name] = new Double(buffer.readDoubleLE(index));
111
			index = index + 8;
112
		} else if(elementType == BSON.BSON_DATA_NUMBER) {
113
			object[name] = buffer.readDoubleLE(index);
114
      index = index + 8;
115
		} else if(elementType == BSON.BSON_DATA_DATE) {
116
      var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
117
      var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
118
      object[name] = new Date(new Long(lowBits, highBits).toNumber());
119
		} else if(elementType == BSON.BSON_DATA_BOOLEAN) {
120
			if(buffer[index] != 0 && buffer[index] != 1) throw new Error('illegal boolean type value');
121
      object[name] = buffer[index++] == 1;
122
		} else if(elementType == BSON.BSON_DATA_OBJECT) {
123
			var _index = index;
124
      var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
125
			if(objectSize <= 0 || objectSize > (buffer.length - index)) throw new Error("bad embedded document length in bson");
126
127
			// We have a raw value
128
			if(raw) {
129
	      object[name] = buffer.slice(index, index + objectSize);
130
			} else {
131
	      object[name] = deserializeObject(buffer, _index, options, false);
132
			}
133
134
      index = index + objectSize;
135
		} else if(elementType == BSON.BSON_DATA_ARRAY) {
136
			var _index = index;
137
      var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
138
			var arrayOptions = options;
139
140
			// Stop index
141
			var stopIndex = index + objectSize;
142
143
			// All elements of array to be returned as raw bson
144
			if(fieldsAsRaw && fieldsAsRaw[name]) {
145
				arrayOptions = {};
146
				for(var n in options) arrayOptions[n] = options[n];
147
				arrayOptions['raw'] = true;
148
			}
149
150
      object[name] = deserializeObject(buffer, _index, arrayOptions, true);
151
      index = index + objectSize;
152
153
			if(buffer[index - 1] != 0) throw new Error('invalid array terminator byte');
154
			if(index != stopIndex) throw new Error('corrupted array bson');
155
		} else if(elementType == BSON.BSON_DATA_UNDEFINED) {
156
      object[name] = undefined;
157
		} else if(elementType == BSON.BSON_DATA_NULL) {
158
			object[name] = null;
159
		} else if(elementType == BSON.BSON_DATA_LONG) {
160
      // Unpack the low and high bits
161
      var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
162
      var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
163
      var long = new Long(lowBits, highBits);
164
      // Promote the long if possible
165
      if(promoteLongs && promoteValues == true) {
166
        object[name] = long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG) ? long.toNumber() : long;
167
      } else {
168
        object[name] = long;
169
      }
170
		} else if(elementType == BSON.BSON_DATA_DECIMAL128) {
171
			// Buffer to contain the decimal bytes
172
			var bytes = new Buffer(16);
173
			// Copy the next 16 bytes into the bytes buffer
174
			buffer.copy(bytes, 0, index, index + 16);
175
			// Update index
176
			index = index + 16;
177
			// Assign the new Decimal128 value
178
			var decimal128 = new Decimal128(bytes);
179
			// If we have an alternative mapper use that
180
			object[name] = decimal128.toObject ? decimal128.toObject() : decimal128;
181
		} else if(elementType == BSON.BSON_DATA_BINARY) {
182
      var binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
183
			var totalBinarySize = binarySize;
184
      var subType = buffer[index++];
185
186
			// Did we have a negative binary size, throw
187
			if(binarySize < 0) throw new Error('Negative binary type element size found');
188
189
			// Is the length longer than the document
190
			if(binarySize > buffer.length) throw new Error('Binary type size larger than document size');
191
192
			// Decode as raw Buffer object if options specifies it
193
      if(buffer['slice'] != null) {
194
        // If we have subtype 2 skip the 4 bytes for the size
195
        if(subType == Binary.SUBTYPE_BYTE_ARRAY) {
196
          binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
197
					if(binarySize < 0) throw new Error('Negative binary type element size found for subtype 0x02');
198
					if(binarySize > (totalBinarySize - 4)) throw new Error('Binary type with subtype 0x02 contains to long binary size');
199
					if(binarySize < (totalBinarySize - 4)) throw new Error('Binary type with subtype 0x02 contains to short binary size');
200
        }
201
202
        if(promoteBuffers && promoteValues) {
203
          object[name] = buffer.slice(index, index + binarySize);
204
        } else {
205
          object[name] = new Binary(buffer.slice(index, index + binarySize), subType);
206
        }
207
      } else {
208
        var _buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(binarySize)) : new Array(binarySize);
209
        // If we have subtype 2 skip the 4 bytes for the size
210
        if(subType == Binary.SUBTYPE_BYTE_ARRAY) {
211
          binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
212
					if(binarySize < 0) throw new Error('Negative binary type element size found for subtype 0x02');
213
					if(binarySize > (totalBinarySize - 4)) throw new Error('Binary type with subtype 0x02 contains to long binary size');
214
					if(binarySize < (totalBinarySize - 4)) throw new Error('Binary type with subtype 0x02 contains to short binary size');
215
        }
216
217
        // Copy the data
218
        for(var i = 0; i < binarySize; i++) {
219
          _buffer[i] = buffer[index + i];
220
        }
221
222
        if(promoteBuffers && promoteValues) {
223
          object[name] = _buffer;
224
        } else {
225
          object[name] = new Binary(_buffer, subType);
226
        }
227
      }
228
229
      // Update the index
230
      index = index + binarySize;
231
		} else if(elementType == BSON.BSON_DATA_REGEXP && bsonRegExp == false) {
232
			// Get the start search index
233
			var i = index;
234
			// Locate the end of the c string
235
			while(buffer[i] !== 0x00 && i < buffer.length) {
236
				i++
237
			}
238
			// If are at the end of the buffer there is a problem with the document
239
			if(i >= buffer.length) throw new Error("Bad BSON Document: illegal CString")
240
			// Return the C string
241
			var source = buffer.toString('utf8', index, i);
242
      // Create the regexp
243
			index = i + 1;
244
245
			// Get the start search index
246
			var i = index;
247
			// Locate the end of the c string
248
			while(buffer[i] !== 0x00 && i < buffer.length) {
249
				i++
250
			}
251
			// If are at the end of the buffer there is a problem with the document
252
			if(i >= buffer.length) throw new Error("Bad BSON Document: illegal CString")
253
			// Return the C string
254
			var regExpOptions = buffer.toString('utf8', index, i);
255
			index = i + 1;
256
257
      // For each option add the corresponding one for javascript
258
      var optionsArray = new Array(regExpOptions.length);
259
260
      // Parse options
261
      for(var i = 0; i < regExpOptions.length; i++) {
262
        switch(regExpOptions[i]) {
263
          case 'm':
264
            optionsArray[i] = 'm';
265
            break;
266
          case 's':
267
            optionsArray[i] = 'g';
268
            break;
269
          case 'i':
270
            optionsArray[i] = 'i';
271
            break;
272
        }
273
      }
274
275
      object[name] = new RegExp(source, optionsArray.join(''));
276
    } else if(elementType == BSON.BSON_DATA_REGEXP && bsonRegExp == true) {
277
			// Get the start search index
278
			var i = index;
279
			// Locate the end of the c string
280
			while(buffer[i] !== 0x00 && i < buffer.length) {
281
				i++
282
			}
283
			// If are at the end of the buffer there is a problem with the document
284
			if(i >= buffer.length) throw new Error("Bad BSON Document: illegal CString")
285
			// Return the C string
286
			var source = buffer.toString('utf8', index, i);
287
      index = i + 1;
288
289
			// Get the start search index
290
			var i = index;
291
			// Locate the end of the c string
292
			while(buffer[i] !== 0x00 && i < buffer.length) {
293
				i++
294
			}
295
			// If are at the end of the buffer there is a problem with the document
296
			if(i >= buffer.length) throw new Error("Bad BSON Document: illegal CString")
297
			// Return the C string
298
			var regExpOptions = buffer.toString('utf8', index, i);
299
      index = i + 1;
300
301
      // Set the object
302
      object[name] = new BSONRegExp(source, regExpOptions);
303
		} else if(elementType == BSON.BSON_DATA_SYMBOL) {
304
      var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
305
			if(stringSize <= 0 || stringSize > (buffer.length - index) || buffer[index + stringSize - 1] != 0) throw new Error("bad string length in bson");
306
      object[name] = new Symbol(buffer.toString('utf8', index, index + stringSize - 1));
307
      index = index + stringSize;
308
		} else if(elementType == BSON.BSON_DATA_TIMESTAMP) {
309
      var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
310
      var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
311
      object[name] = new Timestamp(lowBits, highBits);
312
		} else if(elementType == BSON.BSON_DATA_MIN_KEY) {
313
      object[name] = new MinKey();
314
		} else if(elementType == BSON.BSON_DATA_MAX_KEY) {
315
      object[name] = new MaxKey();
316
		} else if(elementType == BSON.BSON_DATA_CODE) {
317
      var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
318
			if(stringSize <= 0 || stringSize > (buffer.length - index) || buffer[index + stringSize - 1] != 0) throw new Error("bad string length in bson");
319
      var functionString = buffer.toString('utf8', index, index + stringSize - 1);
320
321
      // If we are evaluating the functions
322
      if(evalFunctions) {
323
        var value = null;
324
        // If we have cache enabled let's look for the md5 of the function in the cache
325
        if(cacheFunctions) {
326
          var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString;
327
          // Got to do this to avoid V8 deoptimizing the call due to finding eval
328
          object[name] = isolateEvalWithHash(functionCache, hash, functionString, object);
329
        } else {
330
          object[name] = isolateEval(functionString);
331
        }
332
      } else {
333
        object[name]  = new Code(functionString);
334
      }
335
336
      // Update parse index position
337
      index = index + stringSize;
338
		} else if(elementType == BSON.BSON_DATA_CODE_W_SCOPE) {
339
      var totalSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
340
341
			// Element cannot be shorter than totalSize + stringSize + documentSize + terminator
342
			if(totalSize < (4 + 4 + 4 + 1)) {
343
				throw new Error("code_w_scope total size shorter minimum expected length");
344
			}
345
346
			// Get the code string size
347
      var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
348
			// Check if we have a valid string
349
			if(stringSize <= 0 || stringSize > (buffer.length - index) || buffer[index + stringSize - 1] != 0) throw new Error("bad string length in bson");
350
351
      // Javascript function
352
      var functionString = buffer.toString('utf8', index, index + stringSize - 1);
353
      // Update parse index position
354
      index = index + stringSize;
355
      // Parse the element
356
			var _index = index;
357
      // Decode the size of the object document
358
      var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
359
      // Decode the scope object
360
      var scopeObject = deserializeObject(buffer, _index, options, false);
361
      // Adjust the index
362
      index = index + objectSize;
363
364
			// Check if field length is to short
365
			if(totalSize < (4 + 4 + objectSize + stringSize)) {
366
				throw new Error('code_w_scope total size is to short, truncating scope');
367
			}
368
369
			// Check if totalSize field is to long
370
			if(totalSize > (4 + 4 + objectSize + stringSize)) {
371
				throw new Error('code_w_scope total size is to long, clips outer document');
372
			}
373
374
      // If we are evaluating the functions
375
      if(evalFunctions) {
376
        // Contains the value we are going to set
377
        var value = null;
378
        // If we have cache enabled let's look for the md5 of the function in the cache
379
        if(cacheFunctions) {
380
          var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString;
381
          // Got to do this to avoid V8 deoptimizing the call due to finding eval
382
          object[name] = isolateEvalWithHash(functionCache, hash, functionString, object);
383
        } else {
384
          object[name] = isolateEval(functionString);
385
        }
386
387
        object[name].scope = scopeObject;
388
      } else {
389
        object[name]  = new Code(functionString, scopeObject);
390
      }
391
		} else if(elementType == BSON.BSON_DATA_DBPOINTER) {
392
			// Get the code string size
393
      var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
394
			// Check if we have a valid string
395
			if(stringSize <= 0 || stringSize > (buffer.length - index) || buffer[index + stringSize - 1] != 0) throw new Error("bad string length in bson");
396
			// Namespace
397
      var namespace = buffer.toString('utf8', index, index + stringSize - 1);
398
			// Update parse index position
399
      index = index + stringSize;
400
401
			// Read the oid
402
			var oidBuffer = new Buffer(12);
403
			buffer.copy(oidBuffer, 0, index, index + 12);
404
      var oid = new ObjectID(oidBuffer);
405
406
			// Update the index
407
			index = index + 12;
408
409
			// Split the namespace
410
			var parts = namespace.split('.');
411
			var db = parts.shift();
412
			var collection = parts.join('.');
413
			// Upgrade to DBRef type
414
			object[name] = new DBRef(collection, oid, db);
415
    } else {
416
			throw new Error("Detected unknown BSON type " + elementType.toString(16) + " for fieldname \"" + name + "\", are you using the latest BSON parser");
417
		}
418
  }
419
420
	// Check if the deserialization was against a valid array/object
421
	if(size != (index - startIndex)) {
422
		if(isArray) throw new Error('corrupt array bson');
423
		throw new Error('corrupt object bson');
424
	}
425
426
  // Check if we have a db ref object
427
  if(object['$id'] != null) object = new DBRef(object['$ref'], object['$id'], object['$db']);
428
  return object;
429
}
430
431
/**
432
 * Ensure eval is isolated.