bson 4.0.4 → 4.2.2

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.
Files changed (90) hide show
  1. package/HISTORY.md +56 -1
  2. package/README.md +7 -9
  3. package/bower.json +1 -1
  4. package/bson.d.ts +983 -0
  5. package/dist/bson.browser.esm.js +7261 -5004
  6. package/dist/bson.browser.esm.js.map +1 -0
  7. package/dist/bson.browser.umd.js +7319 -5099
  8. package/dist/bson.browser.umd.js.map +1 -0
  9. package/dist/bson.bundle.js +8168 -9216
  10. package/dist/bson.bundle.js.map +1 -0
  11. package/dist/bson.esm.js +5643 -5409
  12. package/dist/bson.esm.js.map +1 -0
  13. package/etc/prepare.js +19 -0
  14. package/lib/binary.js +194 -377
  15. package/lib/binary.js.map +1 -0
  16. package/lib/bson.js +200 -243
  17. package/lib/bson.js.map +1 -0
  18. package/lib/code.js +36 -39
  19. package/lib/code.js.map +1 -0
  20. package/lib/constants.js +78 -203
  21. package/lib/constants.js.map +1 -0
  22. package/lib/db_ref.js +79 -79
  23. package/lib/db_ref.js.map +1 -0
  24. package/lib/decimal128.js +647 -760
  25. package/lib/decimal128.js.map +1 -0
  26. package/lib/double.js +61 -58
  27. package/lib/double.js.map +1 -0
  28. package/lib/ensure_buffer.js +22 -18
  29. package/lib/ensure_buffer.js.map +1 -0
  30. package/lib/extended_json.js +305 -322
  31. package/lib/extended_json.js.map +1 -0
  32. package/lib/float_parser.js +98 -104
  33. package/lib/float_parser.js.map +1 -0
  34. package/lib/int_32.js +45 -47
  35. package/lib/int_32.js.map +1 -0
  36. package/lib/long.js +876 -16
  37. package/lib/long.js.map +1 -0
  38. package/lib/map.js +123 -124
  39. package/lib/map.js.map +1 -0
  40. package/lib/max_key.js +21 -23
  41. package/lib/max_key.js.map +1 -0
  42. package/lib/min_key.js +21 -23
  43. package/lib/min_key.js.map +1 -0
  44. package/lib/objectid.js +264 -382
  45. package/lib/objectid.js.map +1 -0
  46. package/lib/parser/calculate_size.js +185 -224
  47. package/lib/parser/calculate_size.js.map +1 -0
  48. package/lib/parser/deserializer.js +543 -620
  49. package/lib/parser/deserializer.js.map +1 -0
  50. package/lib/parser/serializer.js +774 -918
  51. package/lib/parser/serializer.js.map +1 -0
  52. package/lib/parser/utils.js +81 -30
  53. package/lib/parser/utils.js.map +1 -0
  54. package/lib/regexp.js +54 -70
  55. package/lib/regexp.js.map +1 -0
  56. package/lib/symbol.js +40 -56
  57. package/lib/symbol.js.map +1 -0
  58. package/lib/timestamp.js +70 -95
  59. package/lib/timestamp.js.map +1 -0
  60. package/lib/uuid.js +48 -0
  61. package/lib/uuid.js.map +1 -0
  62. package/lib/validate_utf8.js +32 -33
  63. package/lib/validate_utf8.js.map +1 -0
  64. package/package.json +53 -31
  65. package/src/binary.ts +270 -0
  66. package/src/bson.ts +326 -0
  67. package/src/code.ts +57 -0
  68. package/src/constants.ts +104 -0
  69. package/src/db_ref.ts +115 -0
  70. package/src/decimal128.ts +801 -0
  71. package/src/double.ts +85 -0
  72. package/src/ensure_buffer.ts +26 -0
  73. package/src/extended_json.ts +395 -0
  74. package/src/float_parser.ts +152 -0
  75. package/src/int_32.ts +64 -0
  76. package/src/long.ts +1000 -0
  77. package/src/map.ts +139 -0
  78. package/src/max_key.ts +33 -0
  79. package/src/min_key.ts +33 -0
  80. package/src/objectid.ts +377 -0
  81. package/src/parser/calculate_size.ts +230 -0
  82. package/src/parser/deserializer.ts +655 -0
  83. package/src/parser/serializer.ts +1069 -0
  84. package/src/parser/utils.ts +93 -0
  85. package/src/regexp.ts +92 -0
  86. package/src/symbol.ts +57 -0
  87. package/src/timestamp.ts +103 -0
  88. package/src/uuid.ts +57 -0
  89. package/src/validate_utf8.ts +47 -0
  90. package/lib/fnv1a.js +0 -48
@@ -1,640 +1,563 @@
1
- 'use strict';
2
-
3
- const Buffer = require('buffer').Buffer;
4
- const Long = require('../long');
5
- const Double = require('../double');
6
- const Timestamp = require('../timestamp');
7
- const ObjectId = require('../objectid');
8
- const Code = require('../code');
9
- const MinKey = require('../min_key');
10
- const MaxKey = require('../max_key');
11
- const Decimal128 = require('../decimal128');
12
- const Int32 = require('../int_32');
13
- const DBRef = require('../db_ref');
14
- const BSONRegExp = require('../regexp');
15
- const BSONSymbol = require('../symbol');
16
- const Binary = require('../binary');
17
- const constants = require('../constants');
18
- const validateUtf8 = require('../validate_utf8').validateUtf8;
19
-
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deserialize = void 0;
4
+ const buffer_1 = require("buffer");
5
+ const binary_1 = require("../binary");
6
+ const code_1 = require("../code");
7
+ const constants = require("../constants");
8
+ const db_ref_1 = require("../db_ref");
9
+ const decimal128_1 = require("../decimal128");
10
+ const double_1 = require("../double");
11
+ const int_32_1 = require("../int_32");
12
+ const long_1 = require("../long");
13
+ const max_key_1 = require("../max_key");
14
+ const min_key_1 = require("../min_key");
15
+ const objectid_1 = require("../objectid");
16
+ const regexp_1 = require("../regexp");
17
+ const symbol_1 = require("../symbol");
18
+ const timestamp_1 = require("../timestamp");
19
+ const validate_utf8_1 = require("../validate_utf8");
20
20
  // Internal long versions
21
- const JS_INT_MAX_LONG = Long.fromNumber(constants.JS_INT_MAX);
22
- const JS_INT_MIN_LONG = Long.fromNumber(constants.JS_INT_MIN);
23
-
21
+ const JS_INT_MAX_LONG = long_1.Long.fromNumber(constants.JS_INT_MAX);
22
+ const JS_INT_MIN_LONG = long_1.Long.fromNumber(constants.JS_INT_MIN);
24
23
  const functionCache = {};
25
-
26
24
  function deserialize(buffer, options, isArray) {
27
- options = options == null ? {} : options;
28
- const index = options && options.index ? options.index : 0;
29
- // Read the document size
30
- const size =
31
- buffer[index] |
32
- (buffer[index + 1] << 8) |
33
- (buffer[index + 2] << 16) |
34
- (buffer[index + 3] << 24);
35
-
36
- if (size < 5) {
37
- throw new Error(`bson size must be >= 5, is ${size}`);
38
- }
39
-
40
- if (options.allowObjectSmallerThanBufferSize && buffer.length < size) {
41
- throw new Error(`buffer length ${buffer.length} must be >= bson size ${size}`);
42
- }
43
-
44
- if (!options.allowObjectSmallerThanBufferSize && buffer.length !== size) {
45
- throw new Error(`buffer length ${buffer.length} must === bson size ${size}`);
46
- }
47
-
48
- if (size + index > buffer.length) {
49
- throw new Error(
50
- `(bson size ${size} + options.index ${index} must be <= buffer length ${Buffer.byteLength(
51
- buffer
52
- )})`
53
- );
54
- }
55
-
56
- // Illegal end value
57
- if (buffer[index + size - 1] !== 0) {
58
- throw new Error("One object, sized correctly, with a spot for an EOO, but the EOO isn't 0x00");
59
- }
60
-
61
- // Start deserializtion
62
- return deserializeObject(buffer, index, options, isArray);
63
- }
64
-
65
- function deserializeObject(buffer, index, options, isArray) {
66
- const evalFunctions = options['evalFunctions'] == null ? false : options['evalFunctions'];
67
- const cacheFunctions = options['cacheFunctions'] == null ? false : options['cacheFunctions'];
68
- const cacheFunctionsCrc32 =
69
- options['cacheFunctionsCrc32'] == null ? false : options['cacheFunctionsCrc32'];
70
-
71
- if (!cacheFunctionsCrc32) var crc32 = null;
72
-
73
- const fieldsAsRaw = options['fieldsAsRaw'] == null ? null : options['fieldsAsRaw'];
74
-
75
- // Return raw bson buffer instead of parsing it
76
- const raw = options['raw'] == null ? false : options['raw'];
77
-
78
- // Return BSONRegExp objects instead of native regular expressions
79
- const bsonRegExp = typeof options['bsonRegExp'] === 'boolean' ? options['bsonRegExp'] : false;
80
-
81
- // Controls the promotion of values vs wrapper classes
82
- const promoteBuffers = options['promoteBuffers'] == null ? false : options['promoteBuffers'];
83
- const promoteLongs = options['promoteLongs'] == null ? true : options['promoteLongs'];
84
- const promoteValues = options['promoteValues'] == null ? true : options['promoteValues'];
85
-
86
- // Set the start index
87
- let startIndex = index;
88
-
89
- // Validate that we have at least 4 bytes of buffer
90
- if (buffer.length < 5) throw new Error('corrupt bson message < 5 bytes long');
91
-
92
- // Read the document size
93
- const size =
94
- buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
95
-
96
- // Ensure buffer is valid size
97
- if (size < 5 || size > buffer.length) throw new Error('corrupt bson message');
98
-
99
- // Create holding object
100
- const object = isArray ? [] : {};
101
- // Used for arrays to skip having to perform utf8 decoding
102
- let arrayIndex = 0;
103
- let done = false;
104
-
105
- // While we have more left data left keep parsing
106
- while (!done) {
107
- // Read the type
108
- const elementType = buffer[index++];
109
-
110
- // If we get a zero it's the last byte, exit
111
- if (elementType === 0) break;
112
-
113
- // Get the start search index
114
- let i = index;
115
- // Locate the end of the c string
116
- while (buffer[i] !== 0x00 && i < buffer.length) {
117
- i++;
118
- }
119
-
120
- // If are at the end of the buffer there is a problem with the document
121
- if (i >= Buffer.byteLength(buffer)) throw new Error('Bad BSON Document: illegal CString');
122
- const name = isArray ? arrayIndex++ : buffer.toString('utf8', index, i);
123
-
124
- index = i + 1;
125
-
126
- if (elementType === constants.BSON_DATA_STRING) {
127
- const stringSize =
128
- buffer[index++] |
129
- (buffer[index++] << 8) |
130
- (buffer[index++] << 16) |
131
- (buffer[index++] << 24);
132
- if (
133
- stringSize <= 0 ||
134
- stringSize > buffer.length - index ||
135
- buffer[index + stringSize - 1] !== 0
136
- )
137
- throw new Error('bad string length in bson');
138
-
139
- if (!validateUtf8(buffer, index, index + stringSize - 1)) {
140
- throw new Error('Invalid UTF-8 string in BSON document');
141
- }
142
-
143
- const s = buffer.toString('utf8', index, index + stringSize - 1);
144
-
145
- object[name] = s;
146
- index = index + stringSize;
147
- } else if (elementType === constants.BSON_DATA_OID) {
148
- const oid = Buffer.alloc(12);
149
- buffer.copy(oid, 0, index, index + 12);
150
- object[name] = new ObjectId(oid);
151
- index = index + 12;
152
- } else if (elementType === constants.BSON_DATA_INT && promoteValues === false) {
153
- object[name] = new Int32(
154
- buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24)
155
- );
156
- } else if (elementType === constants.BSON_DATA_INT) {
157
- object[name] =
158
- buffer[index++] |
159
- (buffer[index++] << 8) |
160
- (buffer[index++] << 16) |
161
- (buffer[index++] << 24);
162
- } else if (elementType === constants.BSON_DATA_NUMBER && promoteValues === false) {
163
- object[name] = new Double(buffer.readDoubleLE(index));
164
- index = index + 8;
165
- } else if (elementType === constants.BSON_DATA_NUMBER) {
166
- object[name] = buffer.readDoubleLE(index);
167
- index = index + 8;
168
- } else if (elementType === constants.BSON_DATA_DATE) {
169
- const lowBits =
170
- buffer[index++] |
171
- (buffer[index++] << 8) |
172
- (buffer[index++] << 16) |
173
- (buffer[index++] << 24);
174
- const highBits =
175
- buffer[index++] |
176
- (buffer[index++] << 8) |
177
- (buffer[index++] << 16) |
178
- (buffer[index++] << 24);
179
- object[name] = new Date(new Long(lowBits, highBits).toNumber());
180
- } else if (elementType === constants.BSON_DATA_BOOLEAN) {
181
- if (buffer[index] !== 0 && buffer[index] !== 1) throw new Error('illegal boolean type value');
182
- object[name] = buffer[index++] === 1;
183
- } else if (elementType === constants.BSON_DATA_OBJECT) {
184
- const _index = index;
185
- const objectSize =
186
- buffer[index] |
187
- (buffer[index + 1] << 8) |
188
- (buffer[index + 2] << 16) |
189
- (buffer[index + 3] << 24);
190
- if (objectSize <= 0 || objectSize > buffer.length - index)
191
- throw new Error('bad embedded document length in bson');
192
-
193
- // We have a raw value
194
- if (raw) {
195
- object[name] = buffer.slice(index, index + objectSize);
196
- } else {
197
- object[name] = deserializeObject(buffer, _index, options, false);
198
- }
199
-
200
- index = index + objectSize;
201
- } else if (elementType === constants.BSON_DATA_ARRAY) {
202
- const _index = index;
203
- const objectSize =
204
- buffer[index] |
25
+ options = options == null ? {} : options;
26
+ const index = options && options.index ? options.index : 0;
27
+ // Read the document size
28
+ const size = buffer[index] |
205
29
  (buffer[index + 1] << 8) |
206
30
  (buffer[index + 2] << 16) |
207
31
  (buffer[index + 3] << 24);
208
- let arrayOptions = options;
209
-
210
- // Stop index
211
- const stopIndex = index + objectSize;
212
-
213
- // All elements of array to be returned as raw bson
214
- if (fieldsAsRaw && fieldsAsRaw[name]) {
215
- arrayOptions = {};
216
- for (let n in options) arrayOptions[n] = options[n];
217
- arrayOptions['raw'] = true;
218
- }
219
-
220
- object[name] = deserializeObject(buffer, _index, arrayOptions, true);
221
- index = index + objectSize;
222
-
223
- if (buffer[index - 1] !== 0) throw new Error('invalid array terminator byte');
224
- if (index !== stopIndex) throw new Error('corrupted array bson');
225
- } else if (elementType === constants.BSON_DATA_UNDEFINED) {
226
- object[name] = undefined;
227
- } else if (elementType === constants.BSON_DATA_NULL) {
228
- object[name] = null;
229
- } else if (elementType === constants.BSON_DATA_LONG) {
230
- // Unpack the low and high bits
231
- const lowBits =
232
- buffer[index++] |
233
- (buffer[index++] << 8) |
234
- (buffer[index++] << 16) |
235
- (buffer[index++] << 24);
236
- const highBits =
237
- buffer[index++] |
238
- (buffer[index++] << 8) |
239
- (buffer[index++] << 16) |
240
- (buffer[index++] << 24);
241
- const long = new Long(lowBits, highBits);
242
- // Promote the long if possible
243
- if (promoteLongs && promoteValues === true) {
244
- object[name] =
245
- long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG)
246
- ? long.toNumber()
247
- : long;
248
- } else {
249
- object[name] = long;
250
- }
251
- } else if (elementType === constants.BSON_DATA_DECIMAL128) {
252
- // Buffer to contain the decimal bytes
253
- const bytes = Buffer.alloc(16);
254
- // Copy the next 16 bytes into the bytes buffer
255
- buffer.copy(bytes, 0, index, index + 16);
256
- // Update index
257
- index = index + 16;
258
- // Assign the new Decimal128 value
259
- const decimal128 = new Decimal128(bytes);
260
- // If we have an alternative mapper use that
261
- object[name] = decimal128.toObject ? decimal128.toObject() : decimal128;
262
- } else if (elementType === constants.BSON_DATA_BINARY) {
263
- let binarySize =
264
- buffer[index++] |
265
- (buffer[index++] << 8) |
266
- (buffer[index++] << 16) |
267
- (buffer[index++] << 24);
268
- const totalBinarySize = binarySize;
269
- const subType = buffer[index++];
270
-
271
- // Did we have a negative binary size, throw
272
- if (binarySize < 0) throw new Error('Negative binary type element size found');
273
-
274
- // Is the length longer than the document
275
- if (binarySize > Buffer.byteLength(buffer))
276
- throw new Error('Binary type size larger than document size');
277
-
278
- // Decode as raw Buffer object if options specifies it
279
- if (buffer['slice'] != null) {
280
- // If we have subtype 2 skip the 4 bytes for the size
281
- if (subType === Binary.SUBTYPE_BYTE_ARRAY) {
282
- binarySize =
283
- buffer[index++] |
284
- (buffer[index++] << 8) |
285
- (buffer[index++] << 16) |
286
- (buffer[index++] << 24);
287
- if (binarySize < 0)
288
- throw new Error('Negative binary type element size found for subtype 0x02');
289
- if (binarySize > totalBinarySize - 4)
290
- throw new Error('Binary type with subtype 0x02 contains to long binary size');
291
- if (binarySize < totalBinarySize - 4)
292
- throw new Error('Binary type with subtype 0x02 contains to short binary size');
32
+ if (size < 5) {
33
+ throw new Error(`bson size must be >= 5, is ${size}`);
34
+ }
35
+ if (options.allowObjectSmallerThanBufferSize && buffer.length < size) {
36
+ throw new Error(`buffer length ${buffer.length} must be >= bson size ${size}`);
37
+ }
38
+ if (!options.allowObjectSmallerThanBufferSize && buffer.length !== size) {
39
+ throw new Error(`buffer length ${buffer.length} must === bson size ${size}`);
40
+ }
41
+ if (size + index > buffer.byteLength) {
42
+ throw new Error(`(bson size ${size} + options.index ${index} must be <= buffer length ${buffer.byteLength})`);
43
+ }
44
+ // Illegal end value
45
+ if (buffer[index + size - 1] !== 0) {
46
+ throw new Error("One object, sized correctly, with a spot for an EOO, but the EOO isn't 0x00");
47
+ }
48
+ // Start deserializtion
49
+ return deserializeObject(buffer, index, options, isArray);
50
+ }
51
+ exports.deserialize = deserialize;
52
+ function deserializeObject(buffer, index, options, isArray = false) {
53
+ const evalFunctions = options['evalFunctions'] == null ? false : options['evalFunctions'];
54
+ const cacheFunctions = options['cacheFunctions'] == null ? false : options['cacheFunctions'];
55
+ const fieldsAsRaw = options['fieldsAsRaw'] == null ? null : options['fieldsAsRaw'];
56
+ // Return raw bson buffer instead of parsing it
57
+ const raw = options['raw'] == null ? false : options['raw'];
58
+ // Return BSONRegExp objects instead of native regular expressions
59
+ const bsonRegExp = typeof options['bsonRegExp'] === 'boolean' ? options['bsonRegExp'] : false;
60
+ // Controls the promotion of values vs wrapper classes
61
+ const promoteBuffers = options['promoteBuffers'] == null ? false : options['promoteBuffers'];
62
+ const promoteLongs = options['promoteLongs'] == null ? true : options['promoteLongs'];
63
+ const promoteValues = options['promoteValues'] == null ? true : options['promoteValues'];
64
+ // Set the start index
65
+ const startIndex = index;
66
+ // Validate that we have at least 4 bytes of buffer
67
+ if (buffer.length < 5)
68
+ throw new Error('corrupt bson message < 5 bytes long');
69
+ // Read the document size
70
+ const size = buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
71
+ // Ensure buffer is valid size
72
+ if (size < 5 || size > buffer.length)
73
+ throw new Error('corrupt bson message');
74
+ // Create holding object
75
+ const object = isArray ? [] : {};
76
+ // Used for arrays to skip having to perform utf8 decoding
77
+ let arrayIndex = 0;
78
+ const done = false;
79
+ // While we have more left data left keep parsing
80
+ while (!done) {
81
+ // Read the type
82
+ const elementType = buffer[index++];
83
+ // If we get a zero it's the last byte, exit
84
+ if (elementType === 0)
85
+ break;
86
+ // Get the start search index
87
+ let i = index;
88
+ // Locate the end of the c string
89
+ while (buffer[i] !== 0x00 && i < buffer.length) {
90
+ i++;
293
91
  }
294
-
295
- if (promoteBuffers && promoteValues) {
296
- object[name] = buffer.slice(index, index + binarySize);
297
- } else {
298
- object[name] = new Binary(buffer.slice(index, index + binarySize), subType);
92
+ // If are at the end of the buffer there is a problem with the document
93
+ if (i >= buffer.byteLength)
94
+ throw new Error('Bad BSON Document: illegal CString');
95
+ const name = isArray ? arrayIndex++ : buffer.toString('utf8', index, i);
96
+ index = i + 1;
97
+ if (elementType === constants.BSON_DATA_STRING) {
98
+ const stringSize = buffer[index++] |
99
+ (buffer[index++] << 8) |
100
+ (buffer[index++] << 16) |
101
+ (buffer[index++] << 24);
102
+ if (stringSize <= 0 ||
103
+ stringSize > buffer.length - index ||
104
+ buffer[index + stringSize - 1] !== 0)
105
+ throw new Error('bad string length in bson');
106
+ if (!validate_utf8_1.validateUtf8(buffer, index, index + stringSize - 1)) {
107
+ throw new Error('Invalid UTF-8 string in BSON document');
108
+ }
109
+ const s = buffer.toString('utf8', index, index + stringSize - 1);
110
+ object[name] = s;
111
+ index = index + stringSize;
299
112
  }
300
- } else {
301
- const _buffer =
302
- typeof Uint8Array !== 'undefined'
303
- ? new Uint8Array(new ArrayBuffer(binarySize))
304
- : new Array(binarySize);
305
- // If we have subtype 2 skip the 4 bytes for the size
306
- if (subType === Binary.SUBTYPE_BYTE_ARRAY) {
307
- binarySize =
308
- buffer[index++] |
309
- (buffer[index++] << 8) |
310
- (buffer[index++] << 16) |
311
- (buffer[index++] << 24);
312
- if (binarySize < 0)
313
- throw new Error('Negative binary type element size found for subtype 0x02');
314
- if (binarySize > totalBinarySize - 4)
315
- throw new Error('Binary type with subtype 0x02 contains to long binary size');
316
- if (binarySize < totalBinarySize - 4)
317
- throw new Error('Binary type with subtype 0x02 contains to short binary size');
113
+ else if (elementType === constants.BSON_DATA_OID) {
114
+ const oid = buffer_1.Buffer.alloc(12);
115
+ buffer.copy(oid, 0, index, index + 12);
116
+ object[name] = new objectid_1.ObjectId(oid);
117
+ index = index + 12;
318
118
  }
319
-
320
- // Copy the data
321
- for (i = 0; i < binarySize; i++) {
322
- _buffer[i] = buffer[index + i];
119
+ else if (elementType === constants.BSON_DATA_INT && promoteValues === false) {
120
+ object[name] = new int_32_1.Int32(buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24));
323
121
  }
324
-
325
- if (promoteBuffers && promoteValues) {
326
- object[name] = _buffer;
327
- } else {
328
- object[name] = new Binary(_buffer, subType);
122
+ else if (elementType === constants.BSON_DATA_INT) {
123
+ object[name] =
124
+ buffer[index++] |
125
+ (buffer[index++] << 8) |
126
+ (buffer[index++] << 16) |
127
+ (buffer[index++] << 24);
329
128
  }
330
- }
331
-
332
- // Update the index
333
- index = index + binarySize;
334
- } else if (elementType === constants.BSON_DATA_REGEXP && bsonRegExp === false) {
335
- // Get the start search index
336
- i = index;
337
- // Locate the end of the c string
338
- while (buffer[i] !== 0x00 && i < buffer.length) {
339
- i++;
340
- }
341
- // If are at the end of the buffer there is a problem with the document
342
- if (i >= buffer.length) throw new Error('Bad BSON Document: illegal CString');
343
- // Return the C string
344
- const source = buffer.toString('utf8', index, i);
345
- // Create the regexp
346
- index = i + 1;
347
-
348
- // Get the start search index
349
- i = index;
350
- // Locate the end of the c string
351
- while (buffer[i] !== 0x00 && i < buffer.length) {
352
- i++;
353
- }
354
- // If are at the end of the buffer there is a problem with the document
355
- if (i >= buffer.length) throw new Error('Bad BSON Document: illegal CString');
356
- // Return the C string
357
- const regExpOptions = buffer.toString('utf8', index, i);
358
- index = i + 1;
359
-
360
- // For each option add the corresponding one for javascript
361
- const optionsArray = new Array(regExpOptions.length);
362
-
363
- // Parse options
364
- for (i = 0; i < regExpOptions.length; i++) {
365
- switch (regExpOptions[i]) {
366
- case 'm':
367
- optionsArray[i] = 'm';
368
- break;
369
- case 's':
370
- optionsArray[i] = 'g';
371
- break;
372
- case 'i':
373
- optionsArray[i] = 'i';
374
- break;
129
+ else if (elementType === constants.BSON_DATA_NUMBER && promoteValues === false) {
130
+ object[name] = new double_1.Double(buffer.readDoubleLE(index));
131
+ index = index + 8;
375
132
  }
376
- }
377
-
378
- object[name] = new RegExp(source, optionsArray.join(''));
379
- } else if (elementType === constants.BSON_DATA_REGEXP && bsonRegExp === true) {
380
- // Get the start search index
381
- i = index;
382
- // Locate the end of the c string
383
- while (buffer[i] !== 0x00 && i < buffer.length) {
384
- i++;
385
- }
386
- // If are at the end of the buffer there is a problem with the document
387
- if (i >= buffer.length) throw new Error('Bad BSON Document: illegal CString');
388
- // Return the C string
389
- const source = buffer.toString('utf8', index, i);
390
- index = i + 1;
391
-
392
- // Get the start search index
393
- i = index;
394
- // Locate the end of the c string
395
- while (buffer[i] !== 0x00 && i < buffer.length) {
396
- i++;
397
- }
398
- // If are at the end of the buffer there is a problem with the document
399
- if (i >= buffer.length) throw new Error('Bad BSON Document: illegal CString');
400
- // Return the C string
401
- const regExpOptions = buffer.toString('utf8', index, i);
402
- index = i + 1;
403
-
404
- // Set the object
405
- object[name] = new BSONRegExp(source, regExpOptions);
406
- } else if (elementType === constants.BSON_DATA_SYMBOL) {
407
- const stringSize =
408
- buffer[index++] |
409
- (buffer[index++] << 8) |
410
- (buffer[index++] << 16) |
411
- (buffer[index++] << 24);
412
- if (
413
- stringSize <= 0 ||
414
- stringSize > buffer.length - index ||
415
- buffer[index + stringSize - 1] !== 0
416
- )
417
- throw new Error('bad string length in bson');
418
- const symbol = buffer.toString('utf8', index, index + stringSize - 1);
419
- object[name] = promoteValues ? symbol : new BSONSymbol(symbol);
420
- index = index + stringSize;
421
- } else if (elementType === constants.BSON_DATA_TIMESTAMP) {
422
- const lowBits =
423
- buffer[index++] |
424
- (buffer[index++] << 8) |
425
- (buffer[index++] << 16) |
426
- (buffer[index++] << 24);
427
- const highBits =
428
- buffer[index++] |
429
- (buffer[index++] << 8) |
430
- (buffer[index++] << 16) |
431
- (buffer[index++] << 24);
432
-
433
- object[name] = new Timestamp(lowBits, highBits);
434
- } else if (elementType === constants.BSON_DATA_MIN_KEY) {
435
- object[name] = new MinKey();
436
- } else if (elementType === constants.BSON_DATA_MAX_KEY) {
437
- object[name] = new MaxKey();
438
- } else if (elementType === constants.BSON_DATA_CODE) {
439
- const stringSize =
440
- buffer[index++] |
441
- (buffer[index++] << 8) |
442
- (buffer[index++] << 16) |
443
- (buffer[index++] << 24);
444
- if (
445
- stringSize <= 0 ||
446
- stringSize > buffer.length - index ||
447
- buffer[index + stringSize - 1] !== 0
448
- )
449
- throw new Error('bad string length in bson');
450
- const functionString = buffer.toString('utf8', index, index + stringSize - 1);
451
-
452
- // If we are evaluating the functions
453
- if (evalFunctions) {
454
- // If we have cache enabled let's look for the md5 of the function in the cache
455
- if (cacheFunctions) {
456
- const hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString;
457
- // Got to do this to avoid V8 deoptimizing the call due to finding eval
458
- object[name] = isolateEvalWithHash(functionCache, hash, functionString, object);
459
- } else {
460
- object[name] = isolateEval(functionString);
133
+ else if (elementType === constants.BSON_DATA_NUMBER) {
134
+ object[name] = buffer.readDoubleLE(index);
135
+ index = index + 8;
461
136
  }
462
- } else {
463
- object[name] = new Code(functionString);
464
- }
465
-
466
- // Update parse index position
467
- index = index + stringSize;
468
- } else if (elementType === constants.BSON_DATA_CODE_W_SCOPE) {
469
- const totalSize =
470
- buffer[index++] |
471
- (buffer[index++] << 8) |
472
- (buffer[index++] << 16) |
473
- (buffer[index++] << 24);
474
-
475
- // Element cannot be shorter than totalSize + stringSize + documentSize + terminator
476
- if (totalSize < 4 + 4 + 4 + 1) {
477
- throw new Error('code_w_scope total size shorter minimum expected length');
478
- }
479
-
480
- // Get the code string size
481
- const stringSize =
482
- buffer[index++] |
483
- (buffer[index++] << 8) |
484
- (buffer[index++] << 16) |
485
- (buffer[index++] << 24);
486
- // Check if we have a valid string
487
- if (
488
- stringSize <= 0 ||
489
- stringSize > buffer.length - index ||
490
- buffer[index + stringSize - 1] !== 0
491
- )
492
- throw new Error('bad string length in bson');
493
-
494
- // Javascript function
495
- const functionString = buffer.toString('utf8', index, index + stringSize - 1);
496
- // Update parse index position
497
- index = index + stringSize;
498
- // Parse the element
499
- const _index = index;
500
- // Decode the size of the object document
501
- const objectSize =
502
- buffer[index] |
503
- (buffer[index + 1] << 8) |
504
- (buffer[index + 2] << 16) |
505
- (buffer[index + 3] << 24);
506
- // Decode the scope object
507
- const scopeObject = deserializeObject(buffer, _index, options, false);
508
- // Adjust the index
509
- index = index + objectSize;
510
-
511
- // Check if field length is to short
512
- if (totalSize < 4 + 4 + objectSize + stringSize) {
513
- throw new Error('code_w_scope total size is to short, truncating scope');
514
- }
515
-
516
- // Check if totalSize field is to long
517
- if (totalSize > 4 + 4 + objectSize + stringSize) {
518
- throw new Error('code_w_scope total size is to long, clips outer document');
519
- }
520
-
521
- // If we are evaluating the functions
522
- if (evalFunctions) {
523
- // If we have cache enabled let's look for the md5 of the function in the cache
524
- if (cacheFunctions) {
525
- const hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString;
526
- // Got to do this to avoid V8 deoptimizing the call due to finding eval
527
- object[name] = isolateEvalWithHash(functionCache, hash, functionString, object);
528
- } else {
529
- object[name] = isolateEval(functionString);
137
+ else if (elementType === constants.BSON_DATA_DATE) {
138
+ const lowBits = buffer[index++] |
139
+ (buffer[index++] << 8) |
140
+ (buffer[index++] << 16) |
141
+ (buffer[index++] << 24);
142
+ const highBits = buffer[index++] |
143
+ (buffer[index++] << 8) |
144
+ (buffer[index++] << 16) |
145
+ (buffer[index++] << 24);
146
+ object[name] = new Date(new long_1.Long(lowBits, highBits).toNumber());
147
+ }
148
+ else if (elementType === constants.BSON_DATA_BOOLEAN) {
149
+ if (buffer[index] !== 0 && buffer[index] !== 1)
150
+ throw new Error('illegal boolean type value');
151
+ object[name] = buffer[index++] === 1;
152
+ }
153
+ else if (elementType === constants.BSON_DATA_OBJECT) {
154
+ const _index = index;
155
+ const objectSize = buffer[index] |
156
+ (buffer[index + 1] << 8) |
157
+ (buffer[index + 2] << 16) |
158
+ (buffer[index + 3] << 24);
159
+ if (objectSize <= 0 || objectSize > buffer.length - index)
160
+ throw new Error('bad embedded document length in bson');
161
+ // We have a raw value
162
+ if (raw) {
163
+ object[name] = buffer.slice(index, index + objectSize);
164
+ }
165
+ else {
166
+ object[name] = deserializeObject(buffer, _index, options, false);
167
+ }
168
+ index = index + objectSize;
169
+ }
170
+ else if (elementType === constants.BSON_DATA_ARRAY) {
171
+ const _index = index;
172
+ const objectSize = buffer[index] |
173
+ (buffer[index + 1] << 8) |
174
+ (buffer[index + 2] << 16) |
175
+ (buffer[index + 3] << 24);
176
+ let arrayOptions = options;
177
+ // Stop index
178
+ const stopIndex = index + objectSize;
179
+ // All elements of array to be returned as raw bson
180
+ if (fieldsAsRaw && fieldsAsRaw[name]) {
181
+ arrayOptions = {};
182
+ for (const n in options) {
183
+ arrayOptions[n] = options[n];
184
+ }
185
+ arrayOptions['raw'] = true;
186
+ }
187
+ object[name] = deserializeObject(buffer, _index, arrayOptions, true);
188
+ index = index + objectSize;
189
+ if (buffer[index - 1] !== 0)
190
+ throw new Error('invalid array terminator byte');
191
+ if (index !== stopIndex)
192
+ throw new Error('corrupted array bson');
193
+ }
194
+ else if (elementType === constants.BSON_DATA_UNDEFINED) {
195
+ object[name] = undefined;
196
+ }
197
+ else if (elementType === constants.BSON_DATA_NULL) {
198
+ object[name] = null;
199
+ }
200
+ else if (elementType === constants.BSON_DATA_LONG) {
201
+ // Unpack the low and high bits
202
+ const lowBits = buffer[index++] |
203
+ (buffer[index++] << 8) |
204
+ (buffer[index++] << 16) |
205
+ (buffer[index++] << 24);
206
+ const highBits = buffer[index++] |
207
+ (buffer[index++] << 8) |
208
+ (buffer[index++] << 16) |
209
+ (buffer[index++] << 24);
210
+ const long = new long_1.Long(lowBits, highBits);
211
+ // Promote the long if possible
212
+ if (promoteLongs && promoteValues === true) {
213
+ object[name] =
214
+ long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG)
215
+ ? long.toNumber()
216
+ : long;
217
+ }
218
+ else {
219
+ object[name] = long;
220
+ }
221
+ }
222
+ else if (elementType === constants.BSON_DATA_DECIMAL128) {
223
+ // Buffer to contain the decimal bytes
224
+ const bytes = buffer_1.Buffer.alloc(16);
225
+ // Copy the next 16 bytes into the bytes buffer
226
+ buffer.copy(bytes, 0, index, index + 16);
227
+ // Update index
228
+ index = index + 16;
229
+ // Assign the new Decimal128 value
230
+ const decimal128 = new decimal128_1.Decimal128(bytes);
231
+ // If we have an alternative mapper use that
232
+ if ('toObject' in decimal128 && typeof decimal128.toObject === 'function') {
233
+ object[name] = decimal128.toObject();
234
+ }
235
+ else {
236
+ object[name] = decimal128;
237
+ }
238
+ }
239
+ else if (elementType === constants.BSON_DATA_BINARY) {
240
+ let binarySize = buffer[index++] |
241
+ (buffer[index++] << 8) |
242
+ (buffer[index++] << 16) |
243
+ (buffer[index++] << 24);
244
+ const totalBinarySize = binarySize;
245
+ const subType = buffer[index++];
246
+ // Did we have a negative binary size, throw
247
+ if (binarySize < 0)
248
+ throw new Error('Negative binary type element size found');
249
+ // Is the length longer than the document
250
+ if (binarySize > buffer.byteLength)
251
+ throw new Error('Binary type size larger than document size');
252
+ // Decode as raw Buffer object if options specifies it
253
+ if (buffer['slice'] != null) {
254
+ // If we have subtype 2 skip the 4 bytes for the size
255
+ if (subType === binary_1.Binary.SUBTYPE_BYTE_ARRAY) {
256
+ binarySize =
257
+ buffer[index++] |
258
+ (buffer[index++] << 8) |
259
+ (buffer[index++] << 16) |
260
+ (buffer[index++] << 24);
261
+ if (binarySize < 0)
262
+ throw new Error('Negative binary type element size found for subtype 0x02');
263
+ if (binarySize > totalBinarySize - 4)
264
+ throw new Error('Binary type with subtype 0x02 contains too long binary size');
265
+ if (binarySize < totalBinarySize - 4)
266
+ throw new Error('Binary type with subtype 0x02 contains too short binary size');
267
+ }
268
+ if (promoteBuffers && promoteValues) {
269
+ object[name] = buffer.slice(index, index + binarySize);
270
+ }
271
+ else {
272
+ object[name] = new binary_1.Binary(buffer.slice(index, index + binarySize), subType);
273
+ }
274
+ }
275
+ else {
276
+ const _buffer = buffer_1.Buffer.alloc(binarySize);
277
+ // If we have subtype 2 skip the 4 bytes for the size
278
+ if (subType === binary_1.Binary.SUBTYPE_BYTE_ARRAY) {
279
+ binarySize =
280
+ buffer[index++] |
281
+ (buffer[index++] << 8) |
282
+ (buffer[index++] << 16) |
283
+ (buffer[index++] << 24);
284
+ if (binarySize < 0)
285
+ throw new Error('Negative binary type element size found for subtype 0x02');
286
+ if (binarySize > totalBinarySize - 4)
287
+ throw new Error('Binary type with subtype 0x02 contains too long binary size');
288
+ if (binarySize < totalBinarySize - 4)
289
+ throw new Error('Binary type with subtype 0x02 contains too short binary size');
290
+ }
291
+ // Copy the data
292
+ for (i = 0; i < binarySize; i++) {
293
+ _buffer[i] = buffer[index + i];
294
+ }
295
+ if (promoteBuffers && promoteValues) {
296
+ object[name] = _buffer;
297
+ }
298
+ else {
299
+ object[name] = new binary_1.Binary(_buffer, subType);
300
+ }
301
+ }
302
+ // Update the index
303
+ index = index + binarySize;
304
+ }
305
+ else if (elementType === constants.BSON_DATA_REGEXP && bsonRegExp === false) {
306
+ // Get the start search index
307
+ i = index;
308
+ // Locate the end of the c string
309
+ while (buffer[i] !== 0x00 && i < buffer.length) {
310
+ i++;
311
+ }
312
+ // If are at the end of the buffer there is a problem with the document
313
+ if (i >= buffer.length)
314
+ throw new Error('Bad BSON Document: illegal CString');
315
+ // Return the C string
316
+ const source = buffer.toString('utf8', index, i);
317
+ // Create the regexp
318
+ index = i + 1;
319
+ // Get the start search index
320
+ i = index;
321
+ // Locate the end of the c string
322
+ while (buffer[i] !== 0x00 && i < buffer.length) {
323
+ i++;
324
+ }
325
+ // If are at the end of the buffer there is a problem with the document
326
+ if (i >= buffer.length)
327
+ throw new Error('Bad BSON Document: illegal CString');
328
+ // Return the C string
329
+ const regExpOptions = buffer.toString('utf8', index, i);
330
+ index = i + 1;
331
+ // For each option add the corresponding one for javascript
332
+ const optionsArray = new Array(regExpOptions.length);
333
+ // Parse options
334
+ for (i = 0; i < regExpOptions.length; i++) {
335
+ switch (regExpOptions[i]) {
336
+ case 'm':
337
+ optionsArray[i] = 'm';
338
+ break;
339
+ case 's':
340
+ optionsArray[i] = 'g';
341
+ break;
342
+ case 'i':
343
+ optionsArray[i] = 'i';
344
+ break;
345
+ }
346
+ }
347
+ object[name] = new RegExp(source, optionsArray.join(''));
348
+ }
349
+ else if (elementType === constants.BSON_DATA_REGEXP && bsonRegExp === true) {
350
+ // Get the start search index
351
+ i = index;
352
+ // Locate the end of the c string
353
+ while (buffer[i] !== 0x00 && i < buffer.length) {
354
+ i++;
355
+ }
356
+ // If are at the end of the buffer there is a problem with the document
357
+ if (i >= buffer.length)
358
+ throw new Error('Bad BSON Document: illegal CString');
359
+ // Return the C string
360
+ const source = buffer.toString('utf8', index, i);
361
+ index = i + 1;
362
+ // Get the start search index
363
+ i = index;
364
+ // Locate the end of the c string
365
+ while (buffer[i] !== 0x00 && i < buffer.length) {
366
+ i++;
367
+ }
368
+ // If are at the end of the buffer there is a problem with the document
369
+ if (i >= buffer.length)
370
+ throw new Error('Bad BSON Document: illegal CString');
371
+ // Return the C string
372
+ const regExpOptions = buffer.toString('utf8', index, i);
373
+ index = i + 1;
374
+ // Set the object
375
+ object[name] = new regexp_1.BSONRegExp(source, regExpOptions);
376
+ }
377
+ else if (elementType === constants.BSON_DATA_SYMBOL) {
378
+ const stringSize = buffer[index++] |
379
+ (buffer[index++] << 8) |
380
+ (buffer[index++] << 16) |
381
+ (buffer[index++] << 24);
382
+ if (stringSize <= 0 ||
383
+ stringSize > buffer.length - index ||
384
+ buffer[index + stringSize - 1] !== 0)
385
+ throw new Error('bad string length in bson');
386
+ const symbol = buffer.toString('utf8', index, index + stringSize - 1);
387
+ object[name] = promoteValues ? symbol : new symbol_1.BSONSymbol(symbol);
388
+ index = index + stringSize;
389
+ }
390
+ else if (elementType === constants.BSON_DATA_TIMESTAMP) {
391
+ const lowBits = buffer[index++] |
392
+ (buffer[index++] << 8) |
393
+ (buffer[index++] << 16) |
394
+ (buffer[index++] << 24);
395
+ const highBits = buffer[index++] |
396
+ (buffer[index++] << 8) |
397
+ (buffer[index++] << 16) |
398
+ (buffer[index++] << 24);
399
+ object[name] = new timestamp_1.Timestamp(lowBits, highBits);
400
+ }
401
+ else if (elementType === constants.BSON_DATA_MIN_KEY) {
402
+ object[name] = new min_key_1.MinKey();
403
+ }
404
+ else if (elementType === constants.BSON_DATA_MAX_KEY) {
405
+ object[name] = new max_key_1.MaxKey();
406
+ }
407
+ else if (elementType === constants.BSON_DATA_CODE) {
408
+ const stringSize = buffer[index++] |
409
+ (buffer[index++] << 8) |
410
+ (buffer[index++] << 16) |
411
+ (buffer[index++] << 24);
412
+ if (stringSize <= 0 ||
413
+ stringSize > buffer.length - index ||
414
+ buffer[index + stringSize - 1] !== 0)
415
+ throw new Error('bad string length in bson');
416
+ const functionString = buffer.toString('utf8', index, index + stringSize - 1);
417
+ // If we are evaluating the functions
418
+ if (evalFunctions) {
419
+ // If we have cache enabled let's look for the md5 of the function in the cache
420
+ if (cacheFunctions) {
421
+ // Got to do this to avoid V8 deoptimizing the call due to finding eval
422
+ object[name] = isolateEval(functionString, functionCache, object);
423
+ }
424
+ else {
425
+ object[name] = isolateEval(functionString);
426
+ }
427
+ }
428
+ else {
429
+ object[name] = new code_1.Code(functionString);
430
+ }
431
+ // Update parse index position
432
+ index = index + stringSize;
433
+ }
434
+ else if (elementType === constants.BSON_DATA_CODE_W_SCOPE) {
435
+ const totalSize = buffer[index++] |
436
+ (buffer[index++] << 8) |
437
+ (buffer[index++] << 16) |
438
+ (buffer[index++] << 24);
439
+ // Element cannot be shorter than totalSize + stringSize + documentSize + terminator
440
+ if (totalSize < 4 + 4 + 4 + 1) {
441
+ throw new Error('code_w_scope total size shorter minimum expected length');
442
+ }
443
+ // Get the code string size
444
+ const stringSize = buffer[index++] |
445
+ (buffer[index++] << 8) |
446
+ (buffer[index++] << 16) |
447
+ (buffer[index++] << 24);
448
+ // Check if we have a valid string
449
+ if (stringSize <= 0 ||
450
+ stringSize > buffer.length - index ||
451
+ buffer[index + stringSize - 1] !== 0)
452
+ throw new Error('bad string length in bson');
453
+ // Javascript function
454
+ const functionString = buffer.toString('utf8', index, index + stringSize - 1);
455
+ // Update parse index position
456
+ index = index + stringSize;
457
+ // Parse the element
458
+ const _index = index;
459
+ // Decode the size of the object document
460
+ const objectSize = buffer[index] |
461
+ (buffer[index + 1] << 8) |
462
+ (buffer[index + 2] << 16) |
463
+ (buffer[index + 3] << 24);
464
+ // Decode the scope object
465
+ const scopeObject = deserializeObject(buffer, _index, options, false);
466
+ // Adjust the index
467
+ index = index + objectSize;
468
+ // Check if field length is too short
469
+ if (totalSize < 4 + 4 + objectSize + stringSize) {
470
+ throw new Error('code_w_scope total size is too short, truncating scope');
471
+ }
472
+ // Check if totalSize field is too long
473
+ if (totalSize > 4 + 4 + objectSize + stringSize) {
474
+ throw new Error('code_w_scope total size is too long, clips outer document');
475
+ }
476
+ // If we are evaluating the functions
477
+ if (evalFunctions) {
478
+ // If we have cache enabled let's look for the md5 of the function in the cache
479
+ if (cacheFunctions) {
480
+ // Got to do this to avoid V8 deoptimizing the call due to finding eval
481
+ object[name] = isolateEval(functionString, functionCache, object);
482
+ }
483
+ else {
484
+ object[name] = isolateEval(functionString);
485
+ }
486
+ object[name].scope = scopeObject;
487
+ }
488
+ else {
489
+ object[name] = new code_1.Code(functionString, scopeObject);
490
+ }
491
+ }
492
+ else if (elementType === constants.BSON_DATA_DBPOINTER) {
493
+ // Get the code string size
494
+ const stringSize = buffer[index++] |
495
+ (buffer[index++] << 8) |
496
+ (buffer[index++] << 16) |
497
+ (buffer[index++] << 24);
498
+ // Check if we have a valid string
499
+ if (stringSize <= 0 ||
500
+ stringSize > buffer.length - index ||
501
+ buffer[index + stringSize - 1] !== 0)
502
+ throw new Error('bad string length in bson');
503
+ // Namespace
504
+ if (!validate_utf8_1.validateUtf8(buffer, index, index + stringSize - 1)) {
505
+ throw new Error('Invalid UTF-8 string in BSON document');
506
+ }
507
+ const namespace = buffer.toString('utf8', index, index + stringSize - 1);
508
+ // Update parse index position
509
+ index = index + stringSize;
510
+ // Read the oid
511
+ const oidBuffer = buffer_1.Buffer.alloc(12);
512
+ buffer.copy(oidBuffer, 0, index, index + 12);
513
+ const oid = new objectid_1.ObjectId(oidBuffer);
514
+ // Update the index
515
+ index = index + 12;
516
+ // Upgrade to DBRef type
517
+ object[name] = new db_ref_1.DBRef(namespace, oid);
518
+ }
519
+ else {
520
+ throw new Error('Detected unknown BSON type ' + elementType.toString(16) + ' for fieldname "' + name + '"');
530
521
  }
531
-
532
- object[name].scope = scopeObject;
533
- } else {
534
- object[name] = new Code(functionString, scopeObject);
535
- }
536
- } else if (elementType === constants.BSON_DATA_DBPOINTER) {
537
- // Get the code string size
538
- const stringSize =
539
- buffer[index++] |
540
- (buffer[index++] << 8) |
541
- (buffer[index++] << 16) |
542
- (buffer[index++] << 24);
543
- // Check if we have a valid string
544
- if (
545
- stringSize <= 0 ||
546
- stringSize > buffer.length - index ||
547
- buffer[index + stringSize - 1] !== 0
548
- )
549
- throw new Error('bad string length in bson');
550
- // Namespace
551
- if (!validateUtf8(buffer, index, index + stringSize - 1)) {
552
- throw new Error('Invalid UTF-8 string in BSON document');
553
- }
554
- const namespace = buffer.toString('utf8', index, index + stringSize - 1);
555
- // Update parse index position
556
- index = index + stringSize;
557
-
558
- // Read the oid
559
- const oidBuffer = Buffer.alloc(12);
560
- buffer.copy(oidBuffer, 0, index, index + 12);
561
- const oid = new ObjectId(oidBuffer);
562
-
563
- // Update the index
564
- index = index + 12;
565
-
566
- // Upgrade to DBRef type
567
- object[name] = new DBRef(namespace, oid);
568
- } else {
569
- throw new Error(
570
- 'Detected unknown BSON type ' +
571
- elementType.toString(16) +
572
- ' for fieldname "' +
573
- name +
574
- '", are you using the latest BSON parser?'
575
- );
576
522
  }
577
- }
578
-
579
- // Check if the deserialization was against a valid array/object
580
- if (size !== index - startIndex) {
581
- if (isArray) throw new Error('corrupt array bson');
582
- throw new Error('corrupt object bson');
583
- }
584
-
585
- // check if object's $ keys are those of a DBRef
586
- const dollarKeys = Object.keys(object).filter(k => k.startsWith('$'));
587
- let valid = true;
588
- dollarKeys.forEach(k => {
589
- if (['$ref', '$id', '$db'].indexOf(k) === -1) valid = false;
590
- });
591
-
592
- // if a $key not in "$ref", "$id", "$db", don't make a DBRef
593
- if (!valid) return object;
594
-
595
- if (object['$id'] != null && object['$ref'] != null) {
596
- let copy = Object.assign({}, object);
597
- delete copy.$ref;
598
- delete copy.$id;
599
- delete copy.$db;
600
- return new DBRef(object.$ref, object.$id, object.$db || null, copy);
601
- }
602
-
603
- return object;
604
- }
605
-
606
- /**
607
- * Ensure eval is isolated.
608
- *
609
- * @ignore
610
- * @api private
611
- */
612
- function isolateEvalWithHash(functionCache, hash, functionString, object) {
613
- // Contains the value we are going to set
614
- let value = null;
615
-
616
- // Check for cache hit, eval if missing and return cached function
617
- if (functionCache[hash] == null) {
618
- eval('value = ' + functionString);
619
- functionCache[hash] = value;
620
- }
621
-
622
- // Set the object
623
- return functionCache[hash].bind(object);
523
+ // Check if the deserialization was against a valid array/object
524
+ if (size !== index - startIndex) {
525
+ if (isArray)
526
+ throw new Error('corrupt array bson');
527
+ throw new Error('corrupt object bson');
528
+ }
529
+ // check if object's $ keys are those of a DBRef
530
+ const dollarKeys = Object.keys(object).filter(k => k.startsWith('$'));
531
+ let valid = true;
532
+ dollarKeys.forEach(k => {
533
+ if (['$ref', '$id', '$db'].indexOf(k) === -1)
534
+ valid = false;
535
+ });
536
+ // if a $key not in "$ref", "$id", "$db", don't make a DBRef
537
+ if (!valid)
538
+ return object;
539
+ if (db_ref_1.isDBRefLike(object)) {
540
+ const copy = Object.assign({}, object);
541
+ delete copy.$ref;
542
+ delete copy.$id;
543
+ delete copy.$db;
544
+ return new db_ref_1.DBRef(object.$ref, object.$id, object.$db, copy);
545
+ }
546
+ return object;
624
547
  }
625
-
626
548
  /**
627
- * Ensure eval is isolated.
549
+ * Ensure eval is isolated, store the result in functionCache.
628
550
  *
629
- * @ignore
630
- * @api private
551
+ * @internal
631
552
  */
632
- function isolateEval(functionString) {
633
- // Contains the value we are going to set
634
- let value = null;
635
- // Eval the function
636
- eval('value = ' + functionString);
637
- return value;
553
+ function isolateEval(functionString, functionCache, object) {
554
+ if (!functionCache)
555
+ return new Function(functionString);
556
+ // Check for cache hit, eval if missing and return cached function
557
+ if (functionCache[functionString] == null) {
558
+ functionCache[functionString] = new Function(functionString);
559
+ }
560
+ // Set the object
561
+ return functionCache[functionString].bind(object);
638
562
  }
639
-
640
- module.exports = deserialize;
563
+ //# sourceMappingURL=deserializer.js.map