sproutboat 0.28.0 → 0.30.0

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 (36) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/SURFACE.md +3 -3
  3. package/THIRD_PARTY_NOTICES.md +9 -0
  4. package/package.json +8 -8
  5. package/src/build.ts +12 -2
  6. package/src/compile.ts +23 -1
  7. package/src/main.ts +13 -2
  8. package/src/native-restore-sources.ts +48 -0
  9. package/src/native-restore.ts +155 -0
  10. package/src/surface.ts +2 -2
  11. package/vendor/ltx-restore/LICENSE +202 -0
  12. package/vendor/ltx-restore/NOTICE +32 -0
  13. package/vendor/ltx-restore/crc64-native.ts.txt +7 -0
  14. package/vendor/ltx-restore/errors.ts.txt +74 -0
  15. package/vendor/ltx-restore/file-io.ts.txt +54 -0
  16. package/vendor/ltx-restore/ltx/byte-reader.ts.txt +46 -0
  17. package/vendor/ltx-restore/ltx/bytes.ts.txt +87 -0
  18. package/vendor/ltx-restore/ltx/checksum.ts.txt +46 -0
  19. package/vendor/ltx-restore/ltx/constants.ts.txt +71 -0
  20. package/vendor/ltx-restore/ltx/crc64.ts.txt +73 -0
  21. package/vendor/ltx-restore/ltx/decoder.ts.txt +285 -0
  22. package/vendor/ltx-restore/ltx/header.ts.txt +126 -0
  23. package/vendor/ltx-restore/ltx/lz4.ts.txt +260 -0
  24. package/vendor/ltx-restore/ltx/page-index.ts.txt +140 -0
  25. package/vendor/ltx-restore/ltx/page.ts.txt +80 -0
  26. package/vendor/ltx-restore/ltx/sink.ts.txt +33 -0
  27. package/vendor/ltx-restore/ltx/trailer.ts.txt +58 -0
  28. package/vendor/ltx-restore/ltx/types.ts.txt +152 -0
  29. package/vendor/ltx-restore/lz4js/README.md +39 -0
  30. package/vendor/ltx-restore/lz4js/lz4.js.txt +560 -0
  31. package/vendor/ltx-restore/lz4js/package.json +36 -0
  32. package/vendor/ltx-restore/lz4js/util.js.txt +54 -0
  33. package/vendor/ltx-restore/lz4js/xxh32.js.txt +102 -0
  34. package/vendor/ltx-restore/program.ts.txt +3 -0
  35. package/vendor/ltx-restore/restore-native.ts.txt +120 -0
  36. package/vendor/ltx-restore/restore.ts.txt +96 -0
@@ -0,0 +1,560 @@
1
+ // lz4.js - An implementation of Lz4 in plain JavaScript.
2
+ //
3
+ // TODO:
4
+ // - Unify header parsing/writing.
5
+ // - Support options (block size, checksums)
6
+ // - Support streams
7
+ // - Better error handling (handle bad offset, etc.)
8
+ // - HC support (better search algorithm)
9
+ // - Tests/benchmarking
10
+
11
+ var xxhash = require('./xxh32.js');
12
+ var util = require('./util.js');
13
+
14
+ // Constants
15
+ // --
16
+
17
+ // Compression format parameters/constants.
18
+ var minMatch = 4;
19
+ var minLength = 13;
20
+ var searchLimit = 5;
21
+ var skipTrigger = 6;
22
+ var hashSize = 1 << 16;
23
+
24
+ // Token constants.
25
+ var mlBits = 4;
26
+ var mlMask = (1 << mlBits) - 1;
27
+ var runBits = 4;
28
+ var runMask = (1 << runBits) - 1;
29
+
30
+ // Shared buffers
31
+ var blockBuf = makeBuffer(5 << 20);
32
+ var hashTable = makeHashTable();
33
+
34
+ // Frame constants.
35
+ var magicNum = 0x184D2204;
36
+
37
+ // Frame descriptor flags.
38
+ var fdContentChksum = 0x4;
39
+ var fdContentSize = 0x8;
40
+ var fdBlockChksum = 0x10;
41
+ // var fdBlockIndep = 0x20;
42
+ var fdVersion = 0x40;
43
+ var fdVersionMask = 0xC0;
44
+
45
+ // Block sizes.
46
+ var bsUncompressed = 0x80000000;
47
+ var bsDefault = 7;
48
+ var bsShift = 4;
49
+ var bsMask = 7;
50
+ var bsMap = {
51
+ 4: 0x10000,
52
+ 5: 0x40000,
53
+ 6: 0x100000,
54
+ 7: 0x400000
55
+ };
56
+
57
+ // Utility functions/primitives
58
+ // --
59
+
60
+ // Makes our hashtable. On older browsers, may return a plain array.
61
+ function makeHashTable () {
62
+ try {
63
+ return new Uint32Array(hashSize);
64
+ } catch (error) {
65
+ var hashTable = new Array(hashSize);
66
+
67
+ for (var i = 0; i < hashSize; i++) {
68
+ hashTable[i] = 0;
69
+ }
70
+
71
+ return hashTable;
72
+ }
73
+ }
74
+
75
+ // Clear hashtable.
76
+ function clearHashTable (table) {
77
+ for (var i = 0; i < hashSize; i++) {
78
+ hashTable[i] = 0;
79
+ }
80
+ }
81
+
82
+ // Makes a byte buffer. On older browsers, may return a plain array.
83
+ function makeBuffer (size) {
84
+ try {
85
+ return new Uint8Array(size);
86
+ } catch (error) {
87
+ var buf = new Array(size);
88
+
89
+ for (var i = 0; i < size; i++) {
90
+ buf[i] = 0;
91
+ }
92
+
93
+ return buf;
94
+ }
95
+ }
96
+
97
+ function sliceArray (array, start, end) {
98
+ if (typeof array.buffer !== undefined) {
99
+ if (Uint8Array.prototype.slice) {
100
+ return array.slice(start, end);
101
+ } else {
102
+ // Uint8Array#slice polyfill.
103
+ var len = array.length;
104
+
105
+ // Calculate start.
106
+ start = start | 0;
107
+ start = (start < 0) ? Math.max(len + start, 0) : Math.min(start, len);
108
+
109
+ // Calculate end.
110
+ end = (end === undefined) ? len : end | 0;
111
+ end = (end < 0) ? Math.max(len + end, 0) : Math.min(end, len);
112
+
113
+ // Copy into new array.
114
+ var arraySlice = new Uint8Array(end - start);
115
+ for (var i = start, n = 0; i < end;) {
116
+ arraySlice[n++] = array[i++];
117
+ }
118
+
119
+ return arraySlice;
120
+ }
121
+ } else {
122
+ // Assume normal array.
123
+ return array.slice(start, end);
124
+ }
125
+ }
126
+
127
+ // Implementation
128
+ // --
129
+
130
+ // Calculates an upper bound for lz4 compression.
131
+ exports.compressBound = function compressBound (n) {
132
+ return (n + (n / 255) + 16) | 0;
133
+ };
134
+
135
+ // Calculates an upper bound for lz4 decompression, by reading the data.
136
+ exports.decompressBound = function decompressBound (src) {
137
+ var sIndex = 0;
138
+
139
+ // Read magic number
140
+ if (util.readU32(src, sIndex) !== magicNum) {
141
+ throw new Error('invalid magic number');
142
+ }
143
+
144
+ sIndex += 4;
145
+
146
+ // Read descriptor
147
+ var descriptor = src[sIndex++];
148
+
149
+ // Check version
150
+ if ((descriptor & fdVersionMask) !== fdVersion) {
151
+ throw new Error('incompatible descriptor version ' + (descriptor & fdVersionMask));
152
+ }
153
+
154
+ // Read flags
155
+ var useBlockSum = (descriptor & fdBlockChksum) !== 0;
156
+ var useContentSize = (descriptor & fdContentSize) !== 0;
157
+
158
+ // Read block size
159
+ var bsIdx = (src[sIndex++] >> bsShift) & bsMask;
160
+
161
+ if (bsMap[bsIdx] === undefined) {
162
+ throw new Error('invalid block size ' + bsIdx);
163
+ }
164
+
165
+ var maxBlockSize = bsMap[bsIdx];
166
+
167
+ // Get content size
168
+ if (useContentSize) {
169
+ return util.readU64(src, sIndex);
170
+ }
171
+
172
+ // Checksum
173
+ sIndex++;
174
+
175
+ // Read blocks.
176
+ var maxSize = 0;
177
+ while (true) {
178
+ var blockSize = util.readU32(src, sIndex);
179
+ sIndex += 4;
180
+
181
+ if (blockSize & bsUncompressed) {
182
+ blockSize &= ~bsUncompressed;
183
+ maxSize += blockSize;
184
+ } else {
185
+ maxSize += maxBlockSize;
186
+ }
187
+
188
+ if (blockSize === 0) {
189
+ return maxSize;
190
+ }
191
+
192
+ if (useBlockSum) {
193
+ sIndex += 4;
194
+ }
195
+
196
+ sIndex += blockSize;
197
+ }
198
+ };
199
+
200
+ // Creates a buffer of a given byte-size, falling back to plain arrays.
201
+ exports.makeBuffer = makeBuffer;
202
+
203
+ // Decompresses a block of Lz4.
204
+ exports.decompressBlock = function decompressBlock (src, dst, sIndex, sLength, dIndex) {
205
+ var mLength, mOffset, sEnd, n, i;
206
+
207
+ // Setup initial state.
208
+ sEnd = sIndex + sLength;
209
+
210
+ // Consume entire input block.
211
+ while (sIndex < sEnd) {
212
+ var token = src[sIndex++];
213
+
214
+ // Copy literals.
215
+ var literalCount = (token >> 4);
216
+ if (literalCount > 0) {
217
+ // Parse length.
218
+ if (literalCount === 0xf) {
219
+ while (true) {
220
+ literalCount += src[sIndex];
221
+ if (src[sIndex++] !== 0xff) {
222
+ break;
223
+ }
224
+ }
225
+ }
226
+
227
+ // Copy literals
228
+ for (n = sIndex + literalCount; sIndex < n;) {
229
+ dst[dIndex++] = src[sIndex++];
230
+ }
231
+ }
232
+
233
+ if (sIndex >= sEnd) {
234
+ break;
235
+ }
236
+
237
+ // Copy match.
238
+ mLength = (token & 0xf);
239
+
240
+ // Parse offset.
241
+ mOffset = src[sIndex++] | (src[sIndex++] << 8);
242
+
243
+ // Parse length.
244
+ if (mLength === 0xf) {
245
+ while (true) {
246
+ mLength += src[sIndex];
247
+ if (src[sIndex++] !== 0xff) {
248
+ break;
249
+ }
250
+ }
251
+ }
252
+
253
+ mLength += minMatch;
254
+
255
+ // Copy match.
256
+ for (i = dIndex - mOffset, n = i + mLength; i < n;) {
257
+ dst[dIndex++] = dst[i++] | 0;
258
+ }
259
+ }
260
+
261
+ return dIndex;
262
+ };
263
+
264
+ // Compresses a block with Lz4.
265
+ exports.compressBlock = function compressBlock (src, dst, sIndex, sLength, hashTable) {
266
+ var mIndex, mAnchor, mLength, mOffset, mStep;
267
+ var literalCount, dIndex, sEnd, n;
268
+
269
+ // Setup initial state.
270
+ dIndex = 0;
271
+ sEnd = sLength + sIndex;
272
+ mAnchor = sIndex;
273
+
274
+ // Process only if block is large enough.
275
+ if (sLength >= minLength) {
276
+ var searchMatchCount = (1 << skipTrigger) + 3;
277
+
278
+ // Consume until last n literals (Lz4 spec limitation.)
279
+ while (sIndex + minMatch < sEnd - searchLimit) {
280
+ var seq = util.readU32(src, sIndex);
281
+ var hash = util.hashU32(seq) >>> 0;
282
+
283
+ // Crush hash to 16 bits.
284
+ hash = ((hash >> 16) ^ hash) >>> 0 & 0xffff;
285
+
286
+ // Look for a match in the hashtable. NOTE: remove one; see below.
287
+ mIndex = hashTable[hash] - 1;
288
+
289
+ // Put pos in hash table. NOTE: add one so that zero = invalid.
290
+ hashTable[hash] = sIndex + 1;
291
+
292
+ // Determine if there is a match (within range.)
293
+ if (mIndex < 0 || ((sIndex - mIndex) >>> 16) > 0 || util.readU32(src, mIndex) !== seq) {
294
+ mStep = searchMatchCount++ >> skipTrigger;
295
+ sIndex += mStep;
296
+ continue;
297
+ }
298
+
299
+ searchMatchCount = (1 << skipTrigger) + 3;
300
+
301
+ // Calculate literal count and offset.
302
+ literalCount = sIndex - mAnchor;
303
+ mOffset = sIndex - mIndex;
304
+
305
+ // We've already matched one word, so get that out of the way.
306
+ sIndex += minMatch;
307
+ mIndex += minMatch;
308
+
309
+ // Determine match length.
310
+ // N.B.: mLength does not include minMatch, Lz4 adds it back
311
+ // in decoding.
312
+ mLength = sIndex;
313
+ while (sIndex < sEnd - searchLimit && src[sIndex] === src[mIndex]) {
314
+ sIndex++;
315
+ mIndex++;
316
+ }
317
+ mLength = sIndex - mLength;
318
+
319
+ // Write token + literal count.
320
+ var token = mLength < mlMask ? mLength : mlMask;
321
+ if (literalCount >= runMask) {
322
+ dst[dIndex++] = (runMask << mlBits) + token;
323
+ for (n = literalCount - runMask; n >= 0xff; n -= 0xff) {
324
+ dst[dIndex++] = 0xff;
325
+ }
326
+ dst[dIndex++] = n;
327
+ } else {
328
+ dst[dIndex++] = (literalCount << mlBits) + token;
329
+ }
330
+
331
+ // Write literals.
332
+ for (var i = 0; i < literalCount; i++) {
333
+ dst[dIndex++] = src[mAnchor + i];
334
+ }
335
+
336
+ // Write offset.
337
+ dst[dIndex++] = mOffset;
338
+ dst[dIndex++] = (mOffset >> 8);
339
+
340
+ // Write match length.
341
+ if (mLength >= mlMask) {
342
+ for (n = mLength - mlMask; n >= 0xff; n -= 0xff) {
343
+ dst[dIndex++] = 0xff;
344
+ }
345
+ dst[dIndex++] = n;
346
+ }
347
+
348
+ // Move the anchor.
349
+ mAnchor = sIndex;
350
+ }
351
+ }
352
+
353
+ // Nothing was encoded.
354
+ if (mAnchor === 0) {
355
+ return 0;
356
+ }
357
+
358
+ // Write remaining literals.
359
+ // Write literal token+count.
360
+ literalCount = sEnd - mAnchor;
361
+ if (literalCount >= runMask) {
362
+ dst[dIndex++] = (runMask << mlBits);
363
+ for (n = literalCount - runMask; n >= 0xff; n -= 0xff) {
364
+ dst[dIndex++] = 0xff;
365
+ }
366
+ dst[dIndex++] = n;
367
+ } else {
368
+ dst[dIndex++] = (literalCount << mlBits);
369
+ }
370
+
371
+ // Write literals.
372
+ sIndex = mAnchor;
373
+ while (sIndex < sEnd) {
374
+ dst[dIndex++] = src[sIndex++];
375
+ }
376
+
377
+ return dIndex;
378
+ };
379
+
380
+ // Decompresses a frame of Lz4 data.
381
+ exports.decompressFrame = function decompressFrame (src, dst) {
382
+ var useBlockSum, useContentSum, useContentSize, descriptor;
383
+ var sIndex = 0;
384
+ var dIndex = 0;
385
+
386
+ // Read magic number
387
+ if (util.readU32(src, sIndex) !== magicNum) {
388
+ throw new Error('invalid magic number');
389
+ }
390
+
391
+ sIndex += 4;
392
+
393
+ // Read descriptor
394
+ descriptor = src[sIndex++];
395
+
396
+ // Check version
397
+ if ((descriptor & fdVersionMask) !== fdVersion) {
398
+ throw new Error('incompatible descriptor version');
399
+ }
400
+
401
+ // Read flags
402
+ useBlockSum = (descriptor & fdBlockChksum) !== 0;
403
+ useContentSum = (descriptor & fdContentChksum) !== 0;
404
+ useContentSize = (descriptor & fdContentSize) !== 0;
405
+
406
+ // Read block size
407
+ var bsIdx = (src[sIndex++] >> bsShift) & bsMask;
408
+
409
+ if (bsMap[bsIdx] === undefined) {
410
+ throw new Error('invalid block size');
411
+ }
412
+
413
+ if (useContentSize) {
414
+ // TODO: read content size
415
+ sIndex += 8;
416
+ }
417
+
418
+ sIndex++;
419
+
420
+ // Read blocks.
421
+ while (true) {
422
+ var compSize;
423
+
424
+ compSize = util.readU32(src, sIndex);
425
+ sIndex += 4;
426
+
427
+ if (compSize === 0) {
428
+ break;
429
+ }
430
+
431
+ if (useBlockSum) {
432
+ // TODO: read block checksum
433
+ sIndex += 4;
434
+ }
435
+
436
+ // Check if block is compressed
437
+ if ((compSize & bsUncompressed) !== 0) {
438
+ // Mask off the 'uncompressed' bit
439
+ compSize &= ~bsUncompressed;
440
+
441
+ // Copy uncompressed data into destination buffer.
442
+ for (var j = 0; j < compSize; j++) {
443
+ dst[dIndex++] = src[sIndex++];
444
+ }
445
+ } else {
446
+ // Decompress into blockBuf
447
+ dIndex = exports.decompressBlock(src, dst, sIndex, compSize, dIndex);
448
+ sIndex += compSize;
449
+ }
450
+ }
451
+
452
+ if (useContentSum) {
453
+ // TODO: read content checksum
454
+ sIndex += 4;
455
+ }
456
+
457
+ return dIndex;
458
+ };
459
+
460
+ // Compresses data to an Lz4 frame.
461
+ exports.compressFrame = function compressFrame (src, dst) {
462
+ var dIndex = 0;
463
+
464
+ // Write magic number.
465
+ util.writeU32(dst, dIndex, magicNum);
466
+ dIndex += 4;
467
+
468
+ // Descriptor flags.
469
+ dst[dIndex++] = fdVersion;
470
+ dst[dIndex++] = bsDefault << bsShift;
471
+
472
+ // Descriptor checksum.
473
+ dst[dIndex] = xxhash.hash(0, dst, 4, dIndex - 4) >> 8;
474
+ dIndex++;
475
+
476
+ // Write blocks.
477
+ var maxBlockSize = bsMap[bsDefault];
478
+ var remaining = src.length;
479
+ var sIndex = 0;
480
+
481
+ // Clear the hashtable.
482
+ clearHashTable(hashTable);
483
+
484
+ // Split input into blocks and write.
485
+ while (remaining > 0) {
486
+ var compSize = 0;
487
+ var blockSize = remaining > maxBlockSize ? maxBlockSize : remaining;
488
+
489
+ compSize = exports.compressBlock(src, blockBuf, sIndex, blockSize, hashTable);
490
+
491
+ if (compSize > blockSize || compSize === 0) {
492
+ // Output uncompressed.
493
+ util.writeU32(dst, dIndex, 0x80000000 | blockSize);
494
+ dIndex += 4;
495
+
496
+ for (var z = sIndex + blockSize; sIndex < z;) {
497
+ dst[dIndex++] = src[sIndex++];
498
+ }
499
+
500
+ remaining -= blockSize;
501
+ } else {
502
+ // Output compressed.
503
+ util.writeU32(dst, dIndex, compSize);
504
+ dIndex += 4;
505
+
506
+ for (var j = 0; j < compSize;) {
507
+ dst[dIndex++] = blockBuf[j++];
508
+ }
509
+
510
+ sIndex += blockSize;
511
+ remaining -= blockSize;
512
+ }
513
+ }
514
+
515
+ // Write blank end block.
516
+ util.writeU32(dst, dIndex, 0);
517
+ dIndex += 4;
518
+
519
+ return dIndex;
520
+ };
521
+
522
+ // Decompresses a buffer containing an Lz4 frame. maxSize is optional; if not
523
+ // provided, a maximum size will be determined by examining the data. The
524
+ // buffer returned will always be perfectly-sized.
525
+ exports.decompress = function decompress (src, maxSize) {
526
+ var dst, size;
527
+
528
+ if (maxSize === undefined) {
529
+ maxSize = exports.decompressBound(src);
530
+ }
531
+
532
+ dst = exports.makeBuffer(maxSize);
533
+ size = exports.decompressFrame(src, dst);
534
+
535
+ if (size !== maxSize) {
536
+ dst = sliceArray(dst, 0, size);
537
+ }
538
+
539
+ return dst;
540
+ };
541
+
542
+ // Compresses a buffer to an Lz4 frame. maxSize is optional; if not provided,
543
+ // a buffer will be created based on the theoretical worst output size for a
544
+ // given input size. The buffer returned will always be perfectly-sized.
545
+ exports.compress = function compress (src, maxSize) {
546
+ var dst, size;
547
+
548
+ if (maxSize === undefined) {
549
+ maxSize = exports.compressBound(src.length);
550
+ }
551
+
552
+ dst = exports.makeBuffer(maxSize);
553
+ size = exports.compressFrame(src, dst);
554
+
555
+ if (size !== maxSize) {
556
+ dst = sliceArray(dst, 0, size);
557
+ }
558
+
559
+ return dst;
560
+ };
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "lz4js",
3
+ "version": "0.2.0",
4
+ "description": "An Lz4 implementation for the browser.",
5
+ "main": "lz4.js",
6
+ "scripts": {
7
+ "test": "mocha -R spec test/cases"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+ssh://git@github.com/Benzinga/lz4js.git"
12
+ },
13
+ "keywords": [
14
+ "lz4",
15
+ "compression",
16
+ "decompression",
17
+ "browser",
18
+ "commonjs"
19
+ ],
20
+ "author": "John Chadwick",
21
+ "license": "ISC",
22
+ "bugs": {
23
+ "url": "https://github.com/Benzinga/lz4js/issues"
24
+ },
25
+ "homepage": "https://github.com/Benzinga/lz4js#readme",
26
+ "devDependencies": {
27
+ "chai": "^3.5.0",
28
+ "eslint": "^3.0.1",
29
+ "eslint-config-semistandard": "^6.0.2",
30
+ "eslint-config-standard": "^5.3.5",
31
+ "eslint-plugin-promise": "^2.0.0",
32
+ "eslint-plugin-react": "^5.2.2",
33
+ "eslint-plugin-standard": "^2.0.0",
34
+ "mocha": "^2.5.3"
35
+ }
36
+ }
@@ -0,0 +1,54 @@
1
+ // Simple hash function, from: http://burtleburtle.net/bob/hash/integer.html.
2
+ // Chosen because it doesn't use multiply and achieves full avalanche.
3
+ exports.hashU32 = function hashU32 (a) {
4
+ a = a | 0;
5
+ a = a + 2127912214 + (a << 12) | 0;
6
+ a = a ^ -949894596 ^ a >>> 19;
7
+ a = a + 374761393 + (a << 5) | 0;
8
+ a = a + -744332180 ^ a << 9;
9
+ a = a + -42973499 + (a << 3) | 0;
10
+ return a ^ -1252372727 ^ a >>> 16 | 0;
11
+ };
12
+
13
+ // Reads a 64-bit little-endian integer from an array.
14
+ exports.readU64 = function readU64 (b, n) {
15
+ var x = 0;
16
+ x |= b[n++] << 0;
17
+ x |= b[n++] << 8;
18
+ x |= b[n++] << 16;
19
+ x |= b[n++] << 24;
20
+ x |= b[n++] << 32;
21
+ x |= b[n++] << 40;
22
+ x |= b[n++] << 48;
23
+ x |= b[n++] << 56;
24
+ return x;
25
+ };
26
+
27
+ // Reads a 32-bit little-endian integer from an array.
28
+ exports.readU32 = function readU32 (b, n) {
29
+ var x = 0;
30
+ x |= b[n++] << 0;
31
+ x |= b[n++] << 8;
32
+ x |= b[n++] << 16;
33
+ x |= b[n++] << 24;
34
+ return x;
35
+ };
36
+
37
+ // Writes a 32-bit little-endian integer from an array.
38
+ exports.writeU32 = function writeU32 (b, n, x) {
39
+ b[n++] = (x >> 0) & 0xff;
40
+ b[n++] = (x >> 8) & 0xff;
41
+ b[n++] = (x >> 16) & 0xff;
42
+ b[n++] = (x >> 24) & 0xff;
43
+ };
44
+
45
+ // Multiplies two numbers using 32-bit integer multiplication.
46
+ // Algorithm from Emscripten.
47
+ exports.imul = function imul (a, b) {
48
+ var ah = a >>> 16;
49
+ var al = a & 65535;
50
+ var bh = b >>> 16;
51
+ var bl = b & 65535;
52
+
53
+ return al * bl + (ah * bl + al * bh << 16) | 0;
54
+ };