bson 0.4.19 → 0.4.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/HISTORY CHANGED
@@ -1,3 +1,22 @@
1
+ 0.4.23 2016-04-08
2
+ -----------------
3
+ - Allow for proper detection of ObjectId or objects that look like ObjectId, improving compatibility across third party libraries.
4
+ - Remove one package from dependency due to having been pulled from NPM.
5
+
6
+ 0.4.22 2016-03-04
7
+ -----------------
8
+ - Fix "TypeError: data.copy is not a function" in Electron (Issue #170, https://github.com/kangas).
9
+ - Fixed issue with undefined type on deserializing.
10
+
11
+ 0.4.21 2016-01-12
12
+ -----------------
13
+ - Minor optimizations to avoid non needed object creation.
14
+
15
+ 0.4.20 2015-10-15
16
+ -----------------
17
+ - Added bower file to repository.
18
+ - Fixed browser pid sometimes set greater than 0xFFFF on browsers (Issue #155, https://github.com/rahatarmanahmed)
19
+
1
20
  0.4.19 2015-10-15
2
21
  -----------------
3
22
  - Remove all support for bson-ext.
package/bower.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "bson",
3
+ "description": "A bson parser for node.js and the browser",
4
+ "keywords": [
5
+ "mongodb",
6
+ "bson",
7
+ "parser"
8
+ ],
9
+ "author": "Christian Amor Kvalheim <christkv@gmail.com>",
10
+ "main": "./browser_build/bson.js",
11
+ "license": "Apache-2.0",
12
+ "moduleType": [
13
+ "globals",
14
+ "node"
15
+ ],
16
+ "ignore": [
17
+ "**/.*",
18
+ "alternate_parsers",
19
+ "benchmarks",
20
+ "bower_components",
21
+ "node_modules",
22
+ "test",
23
+ "tools"
24
+ ]
25
+ }
@@ -0,0 +1,357 @@
1
+ "use strict"
2
+
3
+ var writeIEEE754 = require('../float_parser').writeIEEE754,
4
+ readIEEE754 = require('../float_parser').readIEEE754,
5
+ f = require('util').format,
6
+ Long = require('../long').Long,
7
+ Double = require('../double').Double,
8
+ Timestamp = require('../timestamp').Timestamp,
9
+ ObjectID = require('../objectid').ObjectID,
10
+ Symbol = require('../symbol').Symbol,
11
+ Code = require('../code').Code,
12
+ MinKey = require('../min_key').MinKey,
13
+ MaxKey = require('../max_key').MaxKey,
14
+ DBRef = require('../db_ref').DBRef,
15
+ BSONRegExp = require('../regexp').BSONRegExp,
16
+ Binary = require('../binary').Binary;
17
+
18
+ var BSON = {};
19
+
20
+ /**
21
+ * Contains the function cache if we have that enable to allow for avoiding the eval step on each deserialization, comparison is by md5
22
+ *
23
+ * @ignore
24
+ * @api private
25
+ */
26
+ var functionCache = BSON.functionCache = {};
27
+
28
+ /**
29
+ * Number BSON Type
30
+ *
31
+ * @classconstant BSON_DATA_NUMBER
32
+ **/
33
+ BSON.BSON_DATA_NUMBER = 1;
34
+ /**
35
+ * String BSON Type
36
+ *
37
+ * @classconstant BSON_DATA_STRING
38
+ **/
39
+ BSON.BSON_DATA_STRING = 2;
40
+ /**
41
+ * Object BSON Type
42
+ *
43
+ * @classconstant BSON_DATA_OBJECT
44
+ **/
45
+ BSON.BSON_DATA_OBJECT = 3;
46
+ /**
47
+ * Array BSON Type
48
+ *
49
+ * @classconstant BSON_DATA_ARRAY
50
+ **/
51
+ BSON.BSON_DATA_ARRAY = 4;
52
+ /**
53
+ * Binary BSON Type
54
+ *
55
+ * @classconstant BSON_DATA_BINARY
56
+ **/
57
+ BSON.BSON_DATA_BINARY = 5;
58
+ /**
59
+ * ObjectID BSON Type
60
+ *
61
+ * @classconstant BSON_DATA_OID
62
+ **/
63
+ BSON.BSON_DATA_OID = 7;
64
+ /**
65
+ * Boolean BSON Type
66
+ *
67
+ * @classconstant BSON_DATA_BOOLEAN
68
+ **/
69
+ BSON.BSON_DATA_BOOLEAN = 8;
70
+ /**
71
+ * Date BSON Type
72
+ *
73
+ * @classconstant BSON_DATA_DATE
74
+ **/
75
+ BSON.BSON_DATA_DATE = 9;
76
+ /**
77
+ * null BSON Type
78
+ *
79
+ * @classconstant BSON_DATA_NULL
80
+ **/
81
+ BSON.BSON_DATA_NULL = 10;
82
+ /**
83
+ * RegExp BSON Type
84
+ *
85
+ * @classconstant BSON_DATA_REGEXP
86
+ **/
87
+ BSON.BSON_DATA_REGEXP = 11;
88
+ /**
89
+ * Code BSON Type
90
+ *
91
+ * @classconstant BSON_DATA_CODE
92
+ **/
93
+ BSON.BSON_DATA_CODE = 13;
94
+ /**
95
+ * Symbol BSON Type
96
+ *
97
+ * @classconstant BSON_DATA_SYMBOL
98
+ **/
99
+ BSON.BSON_DATA_SYMBOL = 14;
100
+ /**
101
+ * Code with Scope BSON Type
102
+ *
103
+ * @classconstant BSON_DATA_CODE_W_SCOPE
104
+ **/
105
+ BSON.BSON_DATA_CODE_W_SCOPE = 15;
106
+ /**
107
+ * 32 bit Integer BSON Type
108
+ *
109
+ * @classconstant BSON_DATA_INT
110
+ **/
111
+ BSON.BSON_DATA_INT = 16;
112
+ /**
113
+ * Timestamp BSON Type
114
+ *
115
+ * @classconstant BSON_DATA_TIMESTAMP
116
+ **/
117
+ BSON.BSON_DATA_TIMESTAMP = 17;
118
+ /**
119
+ * Long BSON Type
120
+ *
121
+ * @classconstant BSON_DATA_LONG
122
+ **/
123
+ BSON.BSON_DATA_LONG = 18;
124
+ /**
125
+ * MinKey BSON Type
126
+ *
127
+ * @classconstant BSON_DATA_MIN_KEY
128
+ **/
129
+ BSON.BSON_DATA_MIN_KEY = 0xff;
130
+ /**
131
+ * MaxKey BSON Type
132
+ *
133
+ * @classconstant BSON_DATA_MAX_KEY
134
+ **/
135
+ BSON.BSON_DATA_MAX_KEY = 0x7f;
136
+
137
+ /**
138
+ * Binary Default Type
139
+ *
140
+ * @classconstant BSON_BINARY_SUBTYPE_DEFAULT
141
+ **/
142
+ BSON.BSON_BINARY_SUBTYPE_DEFAULT = 0;
143
+ /**
144
+ * Binary Function Type
145
+ *
146
+ * @classconstant BSON_BINARY_SUBTYPE_FUNCTION
147
+ **/
148
+ BSON.BSON_BINARY_SUBTYPE_FUNCTION = 1;
149
+ /**
150
+ * Binary Byte Array Type
151
+ *
152
+ * @classconstant BSON_BINARY_SUBTYPE_BYTE_ARRAY
153
+ **/
154
+ BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY = 2;
155
+ /**
156
+ * Binary UUID Type
157
+ *
158
+ * @classconstant BSON_BINARY_SUBTYPE_UUID
159
+ **/
160
+ BSON.BSON_BINARY_SUBTYPE_UUID = 3;
161
+ /**
162
+ * Binary MD5 Type
163
+ *
164
+ * @classconstant BSON_BINARY_SUBTYPE_MD5
165
+ **/
166
+ BSON.BSON_BINARY_SUBTYPE_MD5 = 4;
167
+ /**
168
+ * Binary User Defined Type
169
+ *
170
+ * @classconstant BSON_BINARY_SUBTYPE_USER_DEFINED
171
+ **/
172
+ BSON.BSON_BINARY_SUBTYPE_USER_DEFINED = 128;
173
+
174
+ // BSON MAX VALUES
175
+ BSON.BSON_INT32_MAX = 0x7FFFFFFF;
176
+ BSON.BSON_INT32_MIN = -0x80000000;
177
+
178
+ BSON.BSON_INT64_MAX = Math.pow(2, 63) - 1;
179
+ BSON.BSON_INT64_MIN = -Math.pow(2, 63);
180
+
181
+ // JS MAX PRECISE VALUES
182
+ BSON.JS_INT_MAX = 0x20000000000000; // Any integer up to 2^53 can be precisely represented by a double.
183
+ BSON.JS_INT_MIN = -0x20000000000000; // Any integer down to -2^53 can be precisely represented by a double.
184
+
185
+ // Internal long versions
186
+ var JS_INT_MAX_LONG = Long.fromNumber(0x20000000000000); // Any integer up to 2^53 can be precisely represented by a double.
187
+ var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down to -2^53 can be precisely represented by a double.
188
+
189
+ var deserialize = function(buffer, options, isArray) {
190
+ var index = 0;
191
+ // Read the document size
192
+ var size = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
193
+
194
+ // Ensure buffer is valid size
195
+ if(size < 5 || buffer.length < size) {
196
+ throw new Error("corrupt bson message");
197
+ }
198
+
199
+ // Illegal end value
200
+ if(buffer[size - 1] != 0) {
201
+ throw new Error("One object, sized correctly, with a spot for an EOO, but the EOO isn't 0x00");
202
+ }
203
+
204
+ // Start deserializtion
205
+ return deserializeObject(buffer, options, isArray);
206
+ }
207
+
208
+ // // Reads in a C style string
209
+ // var readCStyleStringSpecial = function(buffer, index) {
210
+ // // Get the start search index
211
+ // var i = index;
212
+ // // Locate the end of the c string
213
+ // while(buffer[i] !== 0x00 && i < buffer.length) {
214
+ // i++
215
+ // }
216
+ // // If are at the end of the buffer there is a problem with the document
217
+ // if(i >= buffer.length) throw new Error("Bad BSON Document: illegal CString")
218
+ // // Grab utf8 encoded string
219
+ // var string = buffer.toString('utf8', index, i);
220
+ // // Update index position
221
+ // index = i + 1;
222
+ // // Return string
223
+ // return {s: string, i: index};
224
+ // }
225
+
226
+ // Reads in a C style string
227
+ var readCStyleStringSpecial = function(buffer, index) {
228
+ // Get the start search index
229
+ var i = index;
230
+ // Locate the end of the c string
231
+ while(buffer[i] !== 0x00 && i < buffer.length) {
232
+ i++
233
+ }
234
+ // If are at the end of the buffer there is a problem with the document
235
+ if(i >= buffer.length) throw new Error("Bad BSON Document: illegal CString")
236
+ // Grab utf8 encoded string
237
+ return buffer.toString('utf8', index, i);
238
+ }
239
+
240
+ var DeserializationMethods = {}
241
+ DeserializationMethods[BSON.BSON_DATA_OID] = function(name, object, buffer, index) {
242
+ var string = buffer.toString('binary', index, index + 12);
243
+ object[name] = new ObjectID(string);
244
+ return index + 12;
245
+ }
246
+
247
+ DeserializationMethods[BSON.BSON_DATA_NUMBER] = function(name, object, buffer, index) {
248
+ object[name] = buffer.readDoubleLE(index);
249
+ return index + 8;
250
+ }
251
+
252
+ DeserializationMethods[BSON.BSON_DATA_INT] = function(name, object, buffer, index) {
253
+ object[name] = buffer.readInt32LE(index);
254
+ return index + 4;
255
+ }
256
+
257
+ DeserializationMethods[BSON.BSON_DATA_TIMESTAMP] = function(name, object, buffer, index) {
258
+ var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
259
+ var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
260
+ object[name] = new Timestamp(lowBits, highBits);
261
+ return index;
262
+ }
263
+
264
+ DeserializationMethods[BSON.BSON_DATA_STRING] = function(name, object, buffer, index) {
265
+ var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
266
+ if(stringSize <= 0 || stringSize > (buffer.length - index) || buffer[index + stringSize - 1] != 0) throw new Error("bad string length in bson");
267
+ object[name] = buffer.toString('utf8', index, index + stringSize - 1);
268
+ return index + stringSize;
269
+ }
270
+
271
+ DeserializationMethods[BSON.BSON_DATA_BOOLEAN] = function(name, object, buffer, index) {
272
+ object[name] = buffer[index++] == 1;
273
+ return index;
274
+ }
275
+
276
+ var deserializeObject = function(buffer, options, isArray) {
277
+ // Options
278
+ options = options == null ? {} : options;
279
+ var evalFunctions = options['evalFunctions'] == null ? false : options['evalFunctions'];
280
+ var cacheFunctions = options['cacheFunctions'] == null ? false : options['cacheFunctions'];
281
+ var cacheFunctionsCrc32 = options['cacheFunctionsCrc32'] == null ? false : options['cacheFunctionsCrc32'];
282
+ var promoteLongs = options['promoteLongs'] == null ? true : options['promoteLongs'];
283
+ var fieldsAsRaw = options['fieldsAsRaw'] == null ? {} : options['fieldsAsRaw'];
284
+ // Return BSONRegExp objects instead of native regular expressions
285
+ var bsonRegExp = typeof options['bsonRegExp'] == 'boolean' ? options['bsonRegExp'] : false;
286
+ var promoteBuffers = options['promoteBuffers'] == null ? false : options['promoteBuffers'];
287
+
288
+ // Validate that we have at least 4 bytes of buffer
289
+ if(buffer.length < 5) throw new Error("corrupt bson message < 5 bytes long");
290
+
291
+ // Set up index
292
+ var index = typeof options['index'] == 'number' ? options['index'] : 0;
293
+
294
+ // Read the document size
295
+ var size = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
296
+
297
+ // Ensure buffer is valid size
298
+ if(size < 5 || size > buffer.length) throw new Error("corrupt bson message");
299
+
300
+ // Create holding object
301
+ var object = isArray ? [] : {};
302
+
303
+ // While we have more left data left keep parsing
304
+ while(true) {
305
+ // Read the type
306
+ var elementType = buffer[index++];
307
+ // If we get a zero it's the last byte, exit
308
+ if(elementType == 0) break;
309
+ var name = readCStyleStringSpecial(buffer, index);
310
+ index = index + name.length + 1;
311
+
312
+ // console.log("----------- 0 " + elementType + " :: " + name)
313
+ index = DeserializationMethods[elementType](name, object, buffer, index);
314
+ // console.log('--------------- 1')
315
+ }
316
+
317
+ // Check if we have a db ref object
318
+ if(object['$id'] != null) object = new DBRef(object['$ref'], object['$id'], object['$db']);
319
+
320
+ // Return the final objects
321
+ return object;
322
+ }
323
+
324
+ /**
325
+ * Ensure eval is isolated.
326
+ *
327
+ * @ignore
328
+ * @api private
329
+ */
330
+ var isolateEvalWithHash = function(functionCache, hash, functionString, object) {
331
+ // Contains the value we are going to set
332
+ var value = null;
333
+
334
+ // Check for cache hit, eval if missing and return cached function
335
+ if(functionCache[hash] == null) {
336
+ eval("value = " + functionString);
337
+ functionCache[hash] = value;
338
+ }
339
+ // Set the object
340
+ return functionCache[hash].bind(object);
341
+ }
342
+
343
+ /**
344
+ * Ensure eval is isolated.
345
+ *
346
+ * @ignore
347
+ * @api private
348
+ */
349
+ var isolateEval = function(functionString) {
350
+ // Contains the value we are going to set
351
+ var value = null;
352
+ // Eval the function
353
+ eval("value = " + functionString);
354
+ return value;
355
+ }
356
+
357
+ module.exports = deserialize
@@ -2,7 +2,10 @@
2
2
  * Module dependencies.
3
3
  * @ignore
4
4
  */
5
- if(typeof window === 'undefined') {
5
+
6
+ // Test if we're in Node via presence of "global" not absence of "window"
7
+ // to support hybrid environments like Electron
8
+ if(typeof global !== 'undefined') {
6
9
  var Buffer = require('buffer').Buffer; // TODO just use global Buffer
7
10
  }
8
11
 
package/lib/bson/index.js CHANGED
@@ -17,7 +17,7 @@ try {
17
17
  , './symbol'
18
18
  , './timestamp'
19
19
  , './long'].forEach(function (path) {
20
- var module = require('./' + path);
20
+ var module = require(path);
21
21
  for (var i in module) {
22
22
  exports[i] = module[i];
23
23
  }
@@ -40,8 +40,8 @@ exports.pure = function() {
40
40
  , './symbol'
41
41
  , './timestamp'
42
42
  , './long'
43
- , '././bson'].forEach(function (path) {
44
- var module = require('./' + path);
43
+ , './bson'].forEach(function (path) {
44
+ var module = require(path);
45
45
  for (var i in module) {
46
46
  classes[i] = module[i];
47
47
  }
@@ -68,7 +68,7 @@ exports.native = function() {
68
68
  , './timestamp'
69
69
  , './long'
70
70
  ].forEach(function (path) {
71
- var module = require('./' + path);
71
+ var module = require(path);
72
72
  for (var i in module) {
73
73
  classes[i] = module[i];
74
74
  }
@@ -27,7 +27,8 @@ var checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$");
27
27
  */
28
28
  var ObjectID = function ObjectID(id) {
29
29
  if(!(this instanceof ObjectID)) return new ObjectID(id);
30
- if((id instanceof ObjectID)) return id;
30
+ // Duck-typing to support ObjectId from different npm packages
31
+ if((id instanceof ObjectID) || (id && id.toHexString)) return id;
31
32
 
32
33
  this._bsontype = 'ObjectID';
33
34
  var __id = null;
@@ -114,7 +115,7 @@ ObjectID.prototype.generate = function(time) {
114
115
  var time4Bytes = BinaryParser.encodeInt(time, 32, true, true);
115
116
  /* for time-based ObjectID the bytes following the time will be zeroed */
116
117
  var machine3Bytes = BinaryParser.encodeInt(MACHINE_ID, 24, false);
117
- var pid2Bytes = BinaryParser.fromShort(typeof process === 'undefined' ? Math.floor(Math.random() * 100000) : process.pid % 0xFFFF);
118
+ var pid2Bytes = BinaryParser.fromShort((typeof process === 'undefined' ? Math.floor(Math.random() * 100000) : process.pid) % 0xFFFF);
118
119
  var index3Bytes = BinaryParser.encodeInt(this.get_inc(), 24, false, true);
119
120
 
120
121
  return time4Bytes + machine3Bytes + pid2Bytes + index3Bytes;
@@ -251,6 +252,13 @@ ObjectID.isValid = function isValid(id) {
251
252
  if(typeof id == 'string') {
252
253
  return id.length == 12 || (id.length == 24 && checkForHexRegExp.test(id));
253
254
  }
255
+ if(id instanceof ObjectID) {
256
+ return true;
257
+ }
258
+ // Duck-Typing detection of ObjectId like objects
259
+ if(id.toHexString) {
260
+ return id.id.length == 12 || (id.id.length == 24 && checkForHexRegExp.test(id.id));
261
+ }
254
262
  return false;
255
263
  };
256
264
 
@@ -1,7 +1,6 @@
1
1
  "use strict"
2
2
 
3
- var writeIEEE754 = require('../float_parser').writeIEEE754,
4
- readIEEE754 = require('../float_parser').readIEEE754,
3
+ var readIEEE754 = require('../float_parser').readIEEE754,
5
4
  f = require('util').format,
6
5
  Long = require('../long').Long,
7
6
  Double = require('../double').Double,
@@ -16,9 +15,10 @@ var writeIEEE754 = require('../float_parser').writeIEEE754,
16
15
  Binary = require('../binary').Binary;
17
16
 
18
17
  var deserialize = function(buffer, options, isArray) {
19
- var index = 0;
18
+ options = options == null ? {} : options;
19
+ var index = options && options.index ? options.index : 0;
20
20
  // Read the document size
21
- var size = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
21
+ var size = buffer[index] | buffer[index+1] << 8 | buffer[index+2] << 16 | buffer[index+3] << 24;
22
22
 
23
23
  // Ensure buffer is valid size
24
24
  if(size < 5 || buffer.length < size) {
@@ -26,40 +26,21 @@ var deserialize = function(buffer, options, isArray) {
26
26
  }
27
27
 
28
28
  // Illegal end value
29
- if(buffer[size - 1] != 0) {
29
+ if(buffer[index + size - 1] != 0) {
30
30
  throw new Error("One object, sized correctly, with a spot for an EOO, but the EOO isn't 0x00");
31
31
  }
32
32
 
33
33
  // Start deserializtion
34
- return deserializeObject(buffer, options, isArray);
35
- }
36
-
37
- // Reads in a C style string
38
- var readCStyleStringSpecial = function(buffer, index) {
39
- // Get the start search index
40
- var i = index;
41
- // Locate the end of the c string
42
- while(buffer[i] !== 0x00 && i < buffer.length) {
43
- i++
44
- }
45
- // If are at the end of the buffer there is a problem with the document
46
- if(i >= buffer.length) throw new Error("Bad BSON Document: illegal CString")
47
- // Grab utf8 encoded string
48
- var string = buffer.toString('utf8', index, i);
49
- // Update index position
50
- index = i + 1;
51
- // Return string
52
- return {s: string, i: index};
34
+ return deserializeObject(buffer, index, options, isArray);
53
35
  }
54
36
 
55
- var deserializeObject = function(buffer, options, isArray) {
56
- // Options
57
- options = options == null ? {} : options;
58
- var evalFunctions = options['evalFunctions'] == null ? false : options['evalFunctions'];
37
+ var deserializeObject = function(buffer, index, options, isArray) {
38
+ var evalFunctions = options['evalFunctions'] == null ? false : options['evalFunctions'];
59
39
  var cacheFunctions = options['cacheFunctions'] == null ? false : options['cacheFunctions'];
60
40
  var cacheFunctionsCrc32 = options['cacheFunctionsCrc32'] == null ? false : options['cacheFunctionsCrc32'];
61
41
  var promoteLongs = options['promoteLongs'] == null ? true : options['promoteLongs'];
62
- var fieldsAsRaw = options['fieldsAsRaw'] == null ? {} : options['fieldsAsRaw'];
42
+ var fieldsAsRaw = options['fieldsAsRaw'] == null ? null : options['fieldsAsRaw'];
43
+ var raw = options['raw'] == null ? false : options['raw'];
63
44
  // Return BSONRegExp objects instead of native regular expressions
64
45
  var bsonRegExp = typeof options['bsonRegExp'] == 'boolean' ? options['bsonRegExp'] : false;
65
46
  var promoteBuffers = options['promoteBuffers'] == null ? false : options['promoteBuffers'];
@@ -67,9 +48,6 @@ var deserializeObject = function(buffer, options, isArray) {
67
48
  // Validate that we have at least 4 bytes of buffer
68
49
  if(buffer.length < 5) throw new Error("corrupt bson message < 5 bytes long");
69
50
 
70
- // Set up index
71
- var index = typeof options['index'] == 'number' ? options['index'] : 0;
72
-
73
51
  // Read the document size
74
52
  var size = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
75
53
 
@@ -85,51 +63,82 @@ var deserializeObject = function(buffer, options, isArray) {
85
63
  var elementType = buffer[index++];
86
64
  // If we get a zero it's the last byte, exit
87
65
  if(elementType == 0) break;
88
- // Read the name of the field
89
- var r = readCStyleStringSpecial(buffer, index);
90
- var name = r.s;
91
- index = r.i;
92
66
 
93
- // Switch on the type
94
- if(elementType == BSON.BSON_DATA_OID) {
95
- var string = buffer.toString('binary', index, index + 12);
96
- // Decode the oid
97
- object[name] = new ObjectID(string);
98
- // Update index
99
- index = index + 12;
100
- } else if(elementType == BSON.BSON_DATA_STRING) {
101
- // Read the content of the field
67
+ // Get the start search index
68
+ var i = index;
69
+ // Locate the end of the c string
70
+ while(buffer[i] !== 0x00 && i < buffer.length) {
71
+ i++
72
+ }
73
+
74
+ // If are at the end of the buffer there is a problem with the document
75
+ if(i >= buffer.length) throw new Error("Bad BSON Document: illegal CString")
76
+ var name = buffer.toString('utf8', index, i);
77
+
78
+ index = i + 1;
79
+
80
+ if(elementType == BSON.BSON_DATA_STRING) {
102
81
  var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
103
- // Validate if string Size is larger than the actual provided buffer
104
82
  if(stringSize <= 0 || stringSize > (buffer.length - index) || buffer[index + stringSize - 1] != 0) throw new Error("bad string length in bson");
105
- // Add string to object
106
83
  object[name] = buffer.toString('utf8', index, index + stringSize - 1);
107
- // Update parse index position
108
84
  index = index + stringSize;
85
+ } else if(elementType == BSON.BSON_DATA_OID) {
86
+ var string = buffer.toString('binary', index, index + 12);
87
+ object[name] = new ObjectID(string);
88
+ index = index + 12;
109
89
  } else if(elementType == BSON.BSON_DATA_INT) {
110
- // Decode the 32bit value
111
90
  object[name] = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
112
91
  } else if(elementType == BSON.BSON_DATA_NUMBER) {
113
- // Decode the double value
114
- object[name] = readIEEE754(buffer, index, 'little', 52, 8);
115
- // Update the index
92
+ object[name] = buffer.readDoubleLE(index);
116
93
  index = index + 8;
117
94
  } else if(elementType == BSON.BSON_DATA_DATE) {
118
- // Unpack the low and high bits
119
95
  var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
120
96
  var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
121
- // Set date object
122
97
  object[name] = new Date(new Long(lowBits, highBits).toNumber());
123
98
  } else if(elementType == BSON.BSON_DATA_BOOLEAN) {
124
- // Parse the boolean value
125
99
  object[name] = buffer[index++] == 1;
100
+ } else if(elementType == BSON.BSON_DATA_OBJECT) {
101
+ var _index = index;
102
+ var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
103
+ if(objectSize <= 0 || objectSize > (buffer.length - index)) throw new Error("bad embedded document length in bson");
104
+
105
+ // We have a raw value
106
+ if(raw) {
107
+ object[name] = buffer.slice(index, index + objectSize);
108
+ } else {
109
+ object[name] = deserializeObject(buffer, _index, options, false);
110
+ }
111
+
112
+ index = index + objectSize;
113
+ } else if(elementType == BSON.BSON_DATA_ARRAY) {
114
+ var _index = index;
115
+ var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
116
+ var arrayOptions = options;
117
+
118
+ // All elements of array to be returned as raw bson
119
+ if(fieldsAsRaw && fieldsAsRaw[name]) {
120
+ arrayOptions = {};
121
+ for(var n in options) arrayOptions[n] = options[n];
122
+ arrayOptions['raw'] = true;
123
+ }
124
+
125
+ object[name] = deserializeObject(buffer, _index, arrayOptions, true);
126
+ index = index + objectSize;
126
127
  } else if(elementType == BSON.BSON_DATA_UNDEFINED || elementType == BSON.BSON_DATA_NULL) {
127
- // Parse the boolean value
128
128
  object[name] = null;
129
+ } else if(elementType == BSON.BSON_DATA_LONG) {
130
+ // Unpack the low and high bits
131
+ var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
132
+ var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
133
+ var long = new Long(lowBits, highBits);
134
+ // Promote the long if possible
135
+ if(promoteLongs) {
136
+ object[name] = long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG) ? long.toNumber() : long;
137
+ } else {
138
+ object[name] = long;
139
+ }
129
140
  } else if(elementType == BSON.BSON_DATA_BINARY) {
130
- // Decode the size of the binary blob
131
141
  var binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
132
- // Decode the subtype
133
142
  var subType = buffer[index++];
134
143
  // Decode as raw Buffer object if options specifies it
135
144
  if(buffer['slice'] != null) {
@@ -138,10 +147,8 @@ var deserializeObject = function(buffer, options, isArray) {
138
147
  binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
139
148
  }
140
149
  if(promoteBuffers) {
141
- // assign reference to sliced Buffer object
142
150
  object[name] = buffer.slice(index, index + binarySize);
143
151
  } else {
144
- // Slice the data
145
152
  object[name] = new Binary(buffer.slice(index, index + binarySize), subType);
146
153
  }
147
154
  } else {
@@ -155,59 +162,38 @@ var deserializeObject = function(buffer, options, isArray) {
155
162
  _buffer[i] = buffer[index + i];
156
163
  }
157
164
  if(promoteBuffers) {
158
- // assign reference to Buffer object
159
165
  object[name] = _buffer;
160
166
  } else {
161
- // Create the binary object
162
167
  object[name] = new Binary(_buffer, subType);
163
168
  }
164
169
  }
165
170
  // Update the index
166
171
  index = index + binarySize;
167
- } else if(elementType == BSON.BSON_DATA_ARRAY) {
168
- options['index'] = index;
169
- // Decode the size of the array document
170
- var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
171
- var arrayOptions = options;
172
-
173
- // All elements of array to be returned as raw bson
174
- if(fieldsAsRaw[name]) {
175
- arrayOptions = {};
176
- for(var n in options) arrayOptions[n] = options[n];
177
- arrayOptions['raw'] = true;
178
- }
179
-
180
- // Set the array to the object
181
- object[name] = deserializeObject(buffer, arrayOptions, true);
182
- // Adjust the index
183
- index = index + objectSize;
184
- } else if(elementType == BSON.BSON_DATA_OBJECT) {
185
- options['index'] = index;
186
- // Decode the size of the object document
187
- var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
188
- // Validate if string Size is larger than the actual provided buffer
189
- if(objectSize <= 0 || objectSize > (buffer.length - index)) throw new Error("bad embedded document length in bson");
190
-
191
- // We have a raw value
192
- if(options['raw']) {
193
- // Set the array to the object
194
- object[name] = buffer.slice(index, index + objectSize);
195
- } else {
196
- // Set the array to the object
197
- object[name] = deserializeObject(buffer, options, false);
198
- }
199
-
200
- // Adjust the index
201
- index = index + objectSize;
202
172
  } else if(elementType == BSON.BSON_DATA_REGEXP && bsonRegExp == false) {
173
+ // Get the start search index
174
+ var i = index;
175
+ // Locate the end of the c string
176
+ while(buffer[i] !== 0x00 && i < buffer.length) {
177
+ i++
178
+ }
179
+ // If are at the end of the buffer there is a problem with the document
180
+ if(i >= buffer.length) throw new Error("Bad BSON Document: illegal CString")
181
+ // Return the C string
182
+ var source = buffer.toString('utf8', index, i);
203
183
  // Create the regexp
204
- var r = readCStyleStringSpecial(buffer, index);
205
- var source = r.s;
206
- index = r.i;
184
+ index = i + 1;
207
185
 
208
- var r = readCStyleStringSpecial(buffer, index);
209
- var regExpOptions = r.s;
210
- index = r.i;
186
+ // Get the start search index
187
+ var i = index;
188
+ // Locate the end of the c string
189
+ while(buffer[i] !== 0x00 && i < buffer.length) {
190
+ i++
191
+ }
192
+ // If are at the end of the buffer there is a problem with the document
193
+ if(i >= buffer.length) throw new Error("Bad BSON Document: illegal CString")
194
+ // Return the C string
195
+ var regExpOptions = buffer.toString('utf8', index, i);
196
+ index = i + 1;
211
197
 
212
198
  // For each option add the corresponding one for javascript
213
199
  var optionsArray = new Array(regExpOptions.length);
@@ -229,61 +215,52 @@ var deserializeObject = function(buffer, options, isArray) {
229
215
 
230
216
  object[name] = new RegExp(source, optionsArray.join(''));
231
217
  } else if(elementType == BSON.BSON_DATA_REGEXP && bsonRegExp == true) {
232
- // Create the regexp
233
- var r = readCStyleStringSpecial(buffer, index);
234
- var source = r.s;
235
- index = r.i;
236
-
237
- var r = readCStyleStringSpecial(buffer, index);
238
- var regExpOptions = r.s;
239
- index = r.i;
218
+ // Get the start search index
219
+ var i = index;
220
+ // Locate the end of the c string
221
+ while(buffer[i] !== 0x00 && i < buffer.length) {
222
+ i++
223
+ }
224
+ // If are at the end of the buffer there is a problem with the document
225
+ if(i >= buffer.length) throw new Error("Bad BSON Document: illegal CString")
226
+ // Return the C string
227
+ var source = buffer.toString('utf8', index, i);
228
+ index = i + 1;
229
+
230
+ // Get the start search index
231
+ var i = index;
232
+ // Locate the end of the c string
233
+ while(buffer[i] !== 0x00 && i < buffer.length) {
234
+ i++
235
+ }
236
+ // If are at the end of the buffer there is a problem with the document
237
+ if(i >= buffer.length) throw new Error("Bad BSON Document: illegal CString")
238
+ // Return the C string
239
+ var regExpOptions = buffer.toString('utf8', index, i);
240
+ index = i + 1;
240
241
 
241
242
  // Set the object
242
- object[name] = new BSONRegExp(source, regExpOptions);
243
- } else if(elementType == BSON.BSON_DATA_LONG) {
244
- // Unpack the low and high bits
245
- var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
246
- var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
247
- // Create long object
248
- var long = new Long(lowBits, highBits);
249
- // Promote the long if possible
250
- if(promoteLongs) {
251
- object[name] = long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG) ? long.toNumber() : long;
252
- } else {
253
- object[name] = long;
254
- }
243
+ object[name] = new BSONRegExp(source, regExpOptions);
255
244
  } else if(elementType == BSON.BSON_DATA_SYMBOL) {
256
- // Read the content of the field
257
245
  var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
258
- // Validate if string Size is larger than the actual provided buffer
259
246
  if(stringSize <= 0 || stringSize > (buffer.length - index) || buffer[index + stringSize - 1] != 0) throw new Error("bad string length in bson");
260
- // Add string to object
261
247
  object[name] = new Symbol(buffer.toString('utf8', index, index + stringSize - 1));
262
- // Update parse index position
263
248
  index = index + stringSize;
264
249
  } else if(elementType == BSON.BSON_DATA_TIMESTAMP) {
265
- // Unpack the low and high bits
266
250
  var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
267
251
  var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
268
- // Set the object
269
252
  object[name] = new Timestamp(lowBits, highBits);
270
253
  } else if(elementType == BSON.BSON_DATA_MIN_KEY) {
271
- // Parse the object
272
254
  object[name] = new MinKey();
273
255
  } else if(elementType == BSON.BSON_DATA_MAX_KEY) {
274
- // Parse the object
275
256
  object[name] = new MaxKey();
276
257
  } else if(elementType == BSON.BSON_DATA_CODE) {
277
- // Read the content of the field
278
258
  var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
279
- // Validate if string Size is larger than the actual provided buffer
280
259
  if(stringSize <= 0 || stringSize > (buffer.length - index) || buffer[index + stringSize - 1] != 0) throw new Error("bad string length in bson");
281
- // Function string
282
260
  var functionString = buffer.toString('utf8', index, index + stringSize - 1);
283
261
 
284
262
  // If we are evaluating the functions
285
263
  if(evalFunctions) {
286
- // Contains the value we are going to set
287
264
  var value = null;
288
265
  // If we have cache enabled let's look for the md5 of the function in the cache
289
266
  if(cacheFunctions) {
@@ -291,7 +268,6 @@ var deserializeObject = function(buffer, options, isArray) {
291
268
  // Got to do this to avoid V8 deoptimizing the call due to finding eval
292
269
  object[name] = isolateEvalWithHash(functionCache, hash, functionString, object);
293
270
  } else {
294
- // Set directly
295
271
  object[name] = isolateEval(functionString);
296
272
  }
297
273
  } else {
@@ -301,21 +277,19 @@ var deserializeObject = function(buffer, options, isArray) {
301
277
  // Update parse index position
302
278
  index = index + stringSize;
303
279
  } else if(elementType == BSON.BSON_DATA_CODE_W_SCOPE) {
304
- // Read the content of the field
305
280
  var totalSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
306
281
  var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24;
307
- // Validate if string Size is larger than the actual provided buffer
308
282
  if(stringSize <= 0 || stringSize > (buffer.length - index) || buffer[index + stringSize - 1] != 0) throw new Error("bad string length in bson");
309
283
  // Javascript function
310
284
  var functionString = buffer.toString('utf8', index, index + stringSize - 1);
311
285
  // Update parse index position
312
286
  index = index + stringSize;
313
287
  // Parse the element
314
- options['index'] = index;
288
+ var _index = index;
315
289
  // Decode the size of the object document
316
290
  var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
317
291
  // Decode the scope object
318
- var scopeObject = deserializeObject(buffer, options, false);
292
+ var scopeObject = deserializeObject(buffer, _index, options, false);
319
293
  // Adjust the index
320
294
  index = index + objectSize;
321
295
 
@@ -329,11 +303,9 @@ var deserializeObject = function(buffer, options, isArray) {
329
303
  // Got to do this to avoid V8 deoptimizing the call due to finding eval
330
304
  object[name] = isolateEvalWithHash(functionCache, hash, functionString, object);
331
305
  } else {
332
- // Set directly
333
306
  object[name] = isolateEval(functionString);
334
307
  }
335
308
 
336
- // Set the scope on the object
337
309
  object[name].scope = scopeObject;
338
310
  } else {
339
311
  object[name] = new Code(functionString, scopeObject);
@@ -343,8 +315,6 @@ var deserializeObject = function(buffer, options, isArray) {
343
315
 
344
316
  // Check if we have a db ref object
345
317
  if(object['$id'] != null) object = new DBRef(object['$ref'], object['$id'], object['$db']);
346
-
347
- // Return the final objects
348
318
  return object;
349
319
  }
350
320
 
@@ -421,6 +391,12 @@ BSON.BSON_DATA_ARRAY = 4;
421
391
  * @classconstant BSON_DATA_BINARY
422
392
  **/
423
393
  BSON.BSON_DATA_BINARY = 5;
394
+ /**
395
+ * Binary BSON Type
396
+ *
397
+ * @classconstant BSON_DATA_UNDEFINED
398
+ **/
399
+ BSON.BSON_DATA_UNDEFINED = 7;
424
400
  /**
425
401
  * ObjectID BSON Type
426
402
  *
@@ -285,7 +285,7 @@ var serializeObject = function(buffer, key, value, index, checkKeys, depth, seri
285
285
 
286
286
  var serializeLong = function(buffer, key, value, index) {
287
287
  // Write the type
288
- buffer[index++] = value instanceof Long ? BSON.BSON_DATA_LONG : BSON.BSON_DATA_TIMESTAMP;
288
+ buffer[index++] = value._bsontype == 'Long' ? BSON.BSON_DATA_LONG : BSON.BSON_DATA_TIMESTAMP;
289
289
  // Number of written bytes
290
290
  var numberOfWrittenBytes = buffer.write(key, index, 'utf8');
291
291
  // Encode the name
@@ -564,7 +564,7 @@ var serializeInto = function serializeInto(buffer, object, checkKeys, startingIn
564
564
  } else if(value['_bsontype'] == 'DBRef') {
565
565
  index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions);
566
566
  } else if(value['_bsontype'] == 'BSONRegExp') {
567
- index = serializeBSONRegExp(buffer, key, value, index);
567
+ index = serializeBSONRegExp(buffer, key, value, index);
568
568
  } else if(value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') {
569
569
  index = serializeMinMax(buffer, key, value, index);
570
570
  }
@@ -603,7 +603,7 @@ var serializeInto = function serializeInto(buffer, object, checkKeys, startingIn
603
603
  }
604
604
  }
605
605
  }
606
-
606
+
607
607
  // console.log("---------------------------------------------------")
608
608
  // console.dir("key = " + key)
609
609
  // console.dir("value = " + value)
@@ -642,7 +642,7 @@ var serializeInto = function serializeInto(buffer, object, checkKeys, startingIn
642
642
  } else if(value['_bsontype'] == 'DBRef') {
643
643
  index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions);
644
644
  } else if(value['_bsontype'] == 'BSONRegExp') {
645
- index = serializeBSONRegExp(buffer, key, value, index);
645
+ index = serializeBSONRegExp(buffer, key, value, index);
646
646
  } else if(value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') {
647
647
  index = serializeMinMax(buffer, key, value, index);
648
648
  }
@@ -718,7 +718,7 @@ var serializeInto = function serializeInto(buffer, object, checkKeys, startingIn
718
718
  } else if(value['_bsontype'] == 'DBRef') {
719
719
  index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions);
720
720
  } else if(value['_bsontype'] == 'BSONRegExp') {
721
- index = serializeBSONRegExp(buffer, key, value, index);
721
+ index = serializeBSONRegExp(buffer, key, value, index);
722
722
  } else if(value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') {
723
723
  index = serializeMinMax(buffer, key, value, index);
724
724
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  { "name" : "bson"
2
2
  , "description" : "A bson parser for node.js and the browser"
3
3
  , "keywords" : ["mongodb", "bson", "parser"]
4
- , "version" : "0.4.19"
4
+ , "version" : "0.4.23"
5
5
  , "author" : "Christian Amor Kvalheim <christkv@gmail.com>"
6
6
  , "contributors" : []
7
7
 
@@ -12,7 +12,6 @@
12
12
  , "devDependencies": {
13
13
  "nodeunit": "0.9.0"
14
14
  , "gleak": "0.2.3"
15
- , "one": "2.X.X"
16
15
  , "benchmark": "1.0.0"
17
16
  , "colors": "1.1.0"
18
17
  }