jaelis-node 1.3.1 → 1.4.1
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/README.md +72 -2
- package/lib/JAELIS-VM/lib/adapters/evm-adapter.js +454 -0
- package/lib/JAELIS-VM/lib/adapters/index.js +411 -0
- package/lib/JAELIS-VM/lib/adapters/svm-adapter.js +457 -0
- package/lib/JAELIS-VM/lib/compiler/jir-compiler.js +1097 -0
- package/lib/JAELIS-VM/lib/execution/engine.js +1183 -0
- package/lib/JAELIS-VM/lib/index.js +440 -0
- package/lib/JAELIS-VM/lib/integration/jaelis-integration.js +543 -0
- package/lib/JAELIS-VM/lib/serialization/serializer.js +819 -0
- package/lib/JAELIS-VM/lib/state/state-manager.js +1116 -0
- package/lib/JAELIS-VM/lib/translator/bytecode-translator.js +1222 -0
- package/lib/JAELIS-VM/lib/unified/cross-chain-state.js +836 -0
- package/lib/JAELIS-VM/lib/unified/dynamic-contracts.js +1127 -0
- package/lib/JAELIS-VM/lib/unified/index.js +378 -0
- package/lib/JAELIS-VM/lib/unified/jaelis-abi.js +1150 -0
- package/lib/JAELIS-VM/lib/unified/unified-compiler.js +1350 -0
- package/lib/JAELIS-VM/node_modules/.bin/download-cbor-prebuilds +12 -0
- package/lib/JAELIS-VM/node_modules/.bin/download-cbor-prebuilds.cmd +17 -0
- package/lib/JAELIS-VM/node_modules/.bin/download-cbor-prebuilds.ps1 +28 -0
- package/lib/JAELIS-VM/node_modules/.bin/download-msgpackr-prebuilds +12 -0
- package/lib/JAELIS-VM/node_modules/.bin/download-msgpackr-prebuilds.cmd +17 -0
- package/lib/JAELIS-VM/node_modules/.bin/download-msgpackr-prebuilds.ps1 +28 -0
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages +12 -0
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages-optional +12 -0
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages-optional.cmd +17 -0
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages-optional.ps1 +28 -0
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages-test +12 -0
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages-test.cmd +17 -0
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages-test.ps1 +28 -0
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages.cmd +17 -0
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages.ps1 +28 -0
- package/lib/JAELIS-VM/node_modules/.package-lock.json +127 -0
- package/lib/JAELIS-VM/node_modules/@cbor-extract/cbor-extract-win32-x64/README.md +1 -0
- package/lib/JAELIS-VM/node_modules/@cbor-extract/cbor-extract-win32-x64/index.js +0 -0
- package/lib/JAELIS-VM/node_modules/@cbor-extract/cbor-extract-win32-x64/node.abi115.node +0 -0
- package/lib/JAELIS-VM/node_modules/@cbor-extract/cbor-extract-win32-x64/node.napi.node +0 -0
- package/lib/JAELIS-VM/node_modules/@cbor-extract/cbor-extract-win32-x64/package.json +17 -0
- package/lib/JAELIS-VM/node_modules/@msgpackr-extract/msgpackr-extract-win32-x64/README.md +1 -0
- package/lib/JAELIS-VM/node_modules/@msgpackr-extract/msgpackr-extract-win32-x64/index.js +0 -0
- package/lib/JAELIS-VM/node_modules/@msgpackr-extract/msgpackr-extract-win32-x64/node.abi115.node +0 -0
- package/lib/JAELIS-VM/node_modules/@msgpackr-extract/msgpackr-extract-win32-x64/node.napi.node +0 -0
- package/lib/JAELIS-VM/node_modules/@msgpackr-extract/msgpackr-extract-win32-x64/package.json +17 -0
- package/lib/JAELIS-VM/node_modules/cbor-extract/LICENSE +21 -0
- package/lib/JAELIS-VM/node_modules/cbor-extract/README.md +5 -0
- package/lib/JAELIS-VM/node_modules/cbor-extract/bin/download-prebuilds.js +11 -0
- package/lib/JAELIS-VM/node_modules/cbor-extract/binding.gyp +60 -0
- package/lib/JAELIS-VM/node_modules/cbor-extract/index.js +1 -0
- package/lib/JAELIS-VM/node_modules/cbor-extract/package.json +50 -0
- package/lib/JAELIS-VM/node_modules/cbor-extract/src/extract.cpp +198 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/LICENSE +21 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/README.md +380 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/SECURITY.md +11 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/benchmark.md +73 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/browser.js +11 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/decode.d.ts +2 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/decode.js +1300 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/decode-no-eval.cjs +1244 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/decode-no-eval.cjs.map +1 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index-no-eval.cjs +2509 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index-no-eval.cjs.map +1 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index-no-eval.min.js +2 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index-no-eval.min.js.map +1 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index.js +2508 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index.js.map +1 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index.min.js +2 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index.min.js.map +1 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/node.cjs +2629 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/node.cjs.map +1 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/test.js +3343 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/test.js.map +1 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/encode.d.ts +1 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/encode.js +1231 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/index.d.ts +79 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/index.js +3 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/iterators.js +85 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/node-index.js +24 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/package.json +94 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/rollup.config.js +88 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/stream.js +61 -0
- package/lib/JAELIS-VM/node_modules/cbor-x/webpack.config.js +19 -0
- package/lib/JAELIS-VM/node_modules/detect-libc/LICENSE +201 -0
- package/lib/JAELIS-VM/node_modules/detect-libc/README.md +163 -0
- package/lib/JAELIS-VM/node_modules/detect-libc/index.d.ts +14 -0
- package/lib/JAELIS-VM/node_modules/detect-libc/lib/detect-libc.js +313 -0
- package/lib/JAELIS-VM/node_modules/detect-libc/lib/elf.js +39 -0
- package/lib/JAELIS-VM/node_modules/detect-libc/lib/filesystem.js +51 -0
- package/lib/JAELIS-VM/node_modules/detect-libc/lib/process.js +24 -0
- package/lib/JAELIS-VM/node_modules/detect-libc/package.json +44 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/LICENSE +21 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/README.md +372 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/SECURITY.md +11 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/benchmark.md +67 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index-no-eval.cjs +2407 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index-no-eval.cjs.map +1 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index-no-eval.min.js +2 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index-no-eval.min.js.map +1 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index.js +2406 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index.js.map +1 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index.min.js +2 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index.min.js.map +1 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/node.cjs +3320 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/node.cjs.map +1 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/test.js +4540 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/test.js.map +1 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/unpack-no-eval.cjs +1250 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/unpack-no-eval.cjs.map +1 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/index.d.cts +91 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/index.d.ts +91 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/index.js +5 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/iterators.js +87 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/node-index.js +25 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/pack.d.cts +1 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/pack.d.ts +1 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/pack.js +1141 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/package.json +104 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/rollup.config.js +88 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/stream.js +57 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/struct.js +815 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/test-worker.js +3 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/unpack.d.cts +2 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/unpack.d.ts +2 -0
- package/lib/JAELIS-VM/node_modules/msgpackr/unpack.js +1221 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/LICENSE +21 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/README.md +5 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/bin/download-prebuilds.js +13 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/binding.gyp +63 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/index.js +1 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages +12 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages-optional +12 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages-optional.cmd +17 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages-optional.ps1 +28 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages-test +12 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages-test.cmd +17 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages-test.ps1 +28 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages.cmd +17 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages.ps1 +28 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/LICENSE +21 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/README.md +58 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/bin.js +82 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/build-test.js +19 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/index.js +6 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/node-gyp-build.js +236 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/optional.js +7 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/package.json +32 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/package.json +50 -0
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/src/extract.cpp +274 -0
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/LICENSE +21 -0
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/README.md +58 -0
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/bin.js +77 -0
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/build-test.js +19 -0
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/index.js +224 -0
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/optional.js +7 -0
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/package.json +32 -0
- package/lib/JAELIS-VM/package-lock.json +284 -0
- package/lib/JAELIS-VM/package.json +38 -0
- package/lib/JAELIS-VM/test/comprehensive.test.js +267 -0
- package/lib/JAELIS-VM/test/cross-chain-test.js +470 -0
- package/lib/JAELIS-VM/test/unified-vm-test.js +459 -0
- package/lib/JAELIS-VM/test/unified.test.js +166 -0
- package/lib/JAELIS-VM/test/vm.test.js +599 -0
- package/lib/index.js +240 -4
- package/package.json +2 -2
|
@@ -0,0 +1,1231 @@
|
|
|
1
|
+
import { Decoder, mult10, Tag, typedArrays, addExtension as decodeAddExtension } from './decode.js'
|
|
2
|
+
let textEncoder
|
|
3
|
+
try {
|
|
4
|
+
textEncoder = new TextEncoder()
|
|
5
|
+
} catch (error) {}
|
|
6
|
+
let extensions, extensionClasses
|
|
7
|
+
const Buffer = typeof globalThis === 'object' && globalThis.Buffer;
|
|
8
|
+
const hasNodeBuffer = typeof Buffer !== 'undefined'
|
|
9
|
+
const ByteArrayAllocate = hasNodeBuffer ? Buffer.allocUnsafeSlow : Uint8Array
|
|
10
|
+
const ByteArray = hasNodeBuffer ? Buffer : Uint8Array
|
|
11
|
+
const MAX_STRUCTURES = 0x100
|
|
12
|
+
const MAX_BUFFER_SIZE = hasNodeBuffer ? 0x100000000 : 0x7fd00000
|
|
13
|
+
let serializationId = 1
|
|
14
|
+
let throwOnIterable
|
|
15
|
+
let target
|
|
16
|
+
let targetView
|
|
17
|
+
let position = 0
|
|
18
|
+
let safeEnd
|
|
19
|
+
let bundledStrings = null
|
|
20
|
+
const MAX_BUNDLE_SIZE = 0xf000
|
|
21
|
+
const hasNonLatin = /[\u0080-\uFFFF]/
|
|
22
|
+
const RECORD_SYMBOL = Symbol('record-id')
|
|
23
|
+
export class Encoder extends Decoder {
|
|
24
|
+
constructor(options) {
|
|
25
|
+
super(options)
|
|
26
|
+
this.offset = 0
|
|
27
|
+
let typeBuffer
|
|
28
|
+
let start
|
|
29
|
+
let sharedStructures
|
|
30
|
+
let hasSharedUpdate
|
|
31
|
+
let structures
|
|
32
|
+
let referenceMap
|
|
33
|
+
options = options || {}
|
|
34
|
+
let encodeUtf8 = ByteArray.prototype.utf8Write ? function(string, position, maxBytes) {
|
|
35
|
+
return target.utf8Write(string, position, maxBytes)
|
|
36
|
+
} : (textEncoder && textEncoder.encodeInto) ?
|
|
37
|
+
function(string, position) {
|
|
38
|
+
return textEncoder.encodeInto(string, target.subarray(position)).written
|
|
39
|
+
} : false
|
|
40
|
+
|
|
41
|
+
let encoder = this
|
|
42
|
+
let hasSharedStructures = options.structures || options.saveStructures
|
|
43
|
+
let maxSharedStructures = options.maxSharedStructures
|
|
44
|
+
if (maxSharedStructures == null)
|
|
45
|
+
maxSharedStructures = hasSharedStructures ? 128 : 0
|
|
46
|
+
if (maxSharedStructures > 8190)
|
|
47
|
+
throw new Error('Maximum maxSharedStructure is 8190')
|
|
48
|
+
let isSequential = options.sequential
|
|
49
|
+
if (isSequential) {
|
|
50
|
+
maxSharedStructures = 0
|
|
51
|
+
}
|
|
52
|
+
if (!this.structures)
|
|
53
|
+
this.structures = []
|
|
54
|
+
if (this.saveStructures)
|
|
55
|
+
this.saveShared = this.saveStructures
|
|
56
|
+
let samplingPackedValues, packedObjectMap, sharedValues = options.sharedValues
|
|
57
|
+
let sharedPackedObjectMap
|
|
58
|
+
if (sharedValues) {
|
|
59
|
+
sharedPackedObjectMap = Object.create(null)
|
|
60
|
+
for (let i = 0, l = sharedValues.length; i < l; i++) {
|
|
61
|
+
sharedPackedObjectMap[sharedValues[i]] = i
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
let recordIdsToRemove = []
|
|
65
|
+
let transitionsCount = 0
|
|
66
|
+
let serializationsSinceTransitionRebuild = 0
|
|
67
|
+
|
|
68
|
+
this.mapEncode = function(value, encodeOptions) {
|
|
69
|
+
// Experimental support for premapping keys using _keyMap instad of keyMap - not optiimised yet)
|
|
70
|
+
if (this._keyMap && !this._mapped) {
|
|
71
|
+
//console.log('encoding ', value)
|
|
72
|
+
switch (value.constructor.name) {
|
|
73
|
+
case 'Array':
|
|
74
|
+
value = value.map(r => this.encodeKeys(r))
|
|
75
|
+
break
|
|
76
|
+
//case 'Map':
|
|
77
|
+
// value = this.encodeKeys(value)
|
|
78
|
+
// break
|
|
79
|
+
}
|
|
80
|
+
//this._mapped = true
|
|
81
|
+
}
|
|
82
|
+
return this.encode(value, encodeOptions)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
this.encode = function(value, encodeOptions) {
|
|
86
|
+
if (!target) {
|
|
87
|
+
target = new ByteArrayAllocate(8192)
|
|
88
|
+
targetView = new DataView(target.buffer, 0, 8192)
|
|
89
|
+
position = 0
|
|
90
|
+
}
|
|
91
|
+
safeEnd = target.length - 10
|
|
92
|
+
if (safeEnd - position < 0x800) {
|
|
93
|
+
// don't start too close to the end,
|
|
94
|
+
target = new ByteArrayAllocate(target.length)
|
|
95
|
+
targetView = new DataView(target.buffer, 0, target.length)
|
|
96
|
+
safeEnd = target.length - 10
|
|
97
|
+
position = 0
|
|
98
|
+
} else if (encodeOptions === REUSE_BUFFER_MODE)
|
|
99
|
+
position = (position + 7) & 0x7ffffff8 // Word align to make any future copying of this buffer faster
|
|
100
|
+
start = position
|
|
101
|
+
if (encoder.useSelfDescribedHeader) {
|
|
102
|
+
targetView.setUint32(position, 0xd9d9f700) // tag two byte, then self-descriptive tag
|
|
103
|
+
position += 3
|
|
104
|
+
}
|
|
105
|
+
referenceMap = encoder.structuredClone ? new Map() : null
|
|
106
|
+
if (encoder.bundleStrings && typeof value !== 'string') {
|
|
107
|
+
bundledStrings = []
|
|
108
|
+
bundledStrings.size = Infinity // force a new bundle start on first string
|
|
109
|
+
} else
|
|
110
|
+
bundledStrings = null
|
|
111
|
+
|
|
112
|
+
sharedStructures = encoder.structures
|
|
113
|
+
if (sharedStructures) {
|
|
114
|
+
if (sharedStructures.uninitialized) {
|
|
115
|
+
let sharedData = encoder.getShared() || {}
|
|
116
|
+
encoder.structures = sharedStructures = sharedData.structures || []
|
|
117
|
+
encoder.sharedVersion = sharedData.version
|
|
118
|
+
let sharedValues = encoder.sharedValues = sharedData.packedValues
|
|
119
|
+
if (sharedValues) {
|
|
120
|
+
sharedPackedObjectMap = {}
|
|
121
|
+
for (let i = 0, l = sharedValues.length; i < l; i++)
|
|
122
|
+
sharedPackedObjectMap[sharedValues[i]] = i
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
let sharedStructuresLength = sharedStructures.length
|
|
126
|
+
if (sharedStructuresLength > maxSharedStructures && !isSequential)
|
|
127
|
+
sharedStructuresLength = maxSharedStructures
|
|
128
|
+
if (!sharedStructures.transitions) {
|
|
129
|
+
// rebuild our structure transitions
|
|
130
|
+
sharedStructures.transitions = Object.create(null)
|
|
131
|
+
for (let i = 0; i < sharedStructuresLength; i++) {
|
|
132
|
+
let keys = sharedStructures[i]
|
|
133
|
+
//console.log('shared struct keys:', keys)
|
|
134
|
+
if (!keys)
|
|
135
|
+
continue
|
|
136
|
+
let nextTransition, transition = sharedStructures.transitions
|
|
137
|
+
for (let j = 0, l = keys.length; j < l; j++) {
|
|
138
|
+
if (transition[RECORD_SYMBOL] === undefined)
|
|
139
|
+
transition[RECORD_SYMBOL] = i
|
|
140
|
+
let key = keys[j]
|
|
141
|
+
nextTransition = transition[key]
|
|
142
|
+
if (!nextTransition) {
|
|
143
|
+
nextTransition = transition[key] = Object.create(null)
|
|
144
|
+
}
|
|
145
|
+
transition = nextTransition
|
|
146
|
+
}
|
|
147
|
+
transition[RECORD_SYMBOL] = i | 0x100000
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (!isSequential)
|
|
151
|
+
sharedStructures.nextId = sharedStructuresLength
|
|
152
|
+
}
|
|
153
|
+
if (hasSharedUpdate)
|
|
154
|
+
hasSharedUpdate = false
|
|
155
|
+
structures = sharedStructures || []
|
|
156
|
+
packedObjectMap = sharedPackedObjectMap
|
|
157
|
+
if (options.pack) {
|
|
158
|
+
let packedValues = new Map()
|
|
159
|
+
packedValues.values = []
|
|
160
|
+
packedValues.encoder = encoder
|
|
161
|
+
packedValues.maxValues = options.maxPrivatePackedValues || (sharedPackedObjectMap ? 16 : Infinity)
|
|
162
|
+
packedValues.objectMap = sharedPackedObjectMap || false
|
|
163
|
+
packedValues.samplingPackedValues = samplingPackedValues
|
|
164
|
+
findRepetitiveStrings(value, packedValues)
|
|
165
|
+
if (packedValues.values.length > 0) {
|
|
166
|
+
target[position++] = 0xd8 // one-byte tag
|
|
167
|
+
target[position++] = 51 // tag 51 for packed shared structures https://www.potaroo.net/ietf/ids/draft-ietf-cbor-packed-03.txt
|
|
168
|
+
writeArrayHeader(4)
|
|
169
|
+
let valuesArray = packedValues.values
|
|
170
|
+
encode(valuesArray)
|
|
171
|
+
writeArrayHeader(0) // prefixes
|
|
172
|
+
writeArrayHeader(0) // suffixes
|
|
173
|
+
packedObjectMap = Object.create(sharedPackedObjectMap || null)
|
|
174
|
+
for (let i = 0, l = valuesArray.length; i < l; i++) {
|
|
175
|
+
packedObjectMap[valuesArray[i]] = i
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
throwOnIterable = encodeOptions & THROW_ON_ITERABLE;
|
|
180
|
+
try {
|
|
181
|
+
if (throwOnIterable)
|
|
182
|
+
return;
|
|
183
|
+
encode(value)
|
|
184
|
+
if (bundledStrings) {
|
|
185
|
+
writeBundles(start, encode)
|
|
186
|
+
}
|
|
187
|
+
encoder.offset = position // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
|
|
188
|
+
if (referenceMap && referenceMap.idsToInsert) {
|
|
189
|
+
position += referenceMap.idsToInsert.length * 2
|
|
190
|
+
if (position > safeEnd)
|
|
191
|
+
makeRoom(position)
|
|
192
|
+
encoder.offset = position
|
|
193
|
+
let serialized = insertIds(target.subarray(start, position), referenceMap.idsToInsert)
|
|
194
|
+
referenceMap = null
|
|
195
|
+
return serialized
|
|
196
|
+
}
|
|
197
|
+
if (encodeOptions & REUSE_BUFFER_MODE) {
|
|
198
|
+
target.start = start
|
|
199
|
+
target.end = position
|
|
200
|
+
return target
|
|
201
|
+
}
|
|
202
|
+
return target.subarray(start, position) // position can change if we call encode again in saveShared, so we get the buffer now
|
|
203
|
+
} finally {
|
|
204
|
+
if (sharedStructures) {
|
|
205
|
+
if (serializationsSinceTransitionRebuild < 10)
|
|
206
|
+
serializationsSinceTransitionRebuild++
|
|
207
|
+
if (sharedStructures.length > maxSharedStructures)
|
|
208
|
+
sharedStructures.length = maxSharedStructures
|
|
209
|
+
if (transitionsCount > 10000) {
|
|
210
|
+
// force a rebuild occasionally after a lot of transitions so it can get cleaned up
|
|
211
|
+
sharedStructures.transitions = null
|
|
212
|
+
serializationsSinceTransitionRebuild = 0
|
|
213
|
+
transitionsCount = 0
|
|
214
|
+
if (recordIdsToRemove.length > 0)
|
|
215
|
+
recordIdsToRemove = []
|
|
216
|
+
} else if (recordIdsToRemove.length > 0 && !isSequential) {
|
|
217
|
+
for (let i = 0, l = recordIdsToRemove.length; i < l; i++) {
|
|
218
|
+
recordIdsToRemove[i][RECORD_SYMBOL] = undefined
|
|
219
|
+
}
|
|
220
|
+
recordIdsToRemove = []
|
|
221
|
+
//sharedStructures.nextId = maxSharedStructures
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (hasSharedUpdate && encoder.saveShared) {
|
|
225
|
+
if (encoder.structures.length > maxSharedStructures) {
|
|
226
|
+
encoder.structures = encoder.structures.slice(0, maxSharedStructures)
|
|
227
|
+
}
|
|
228
|
+
// we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
|
|
229
|
+
let returnBuffer = target.subarray(start, position)
|
|
230
|
+
if (encoder.updateSharedData() === false)
|
|
231
|
+
return encoder.encode(value) // re-encode if it fails
|
|
232
|
+
return returnBuffer
|
|
233
|
+
}
|
|
234
|
+
if (encodeOptions & RESET_BUFFER_MODE)
|
|
235
|
+
position = start
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
this.findCommonStringsToPack = () => {
|
|
239
|
+
samplingPackedValues = new Map()
|
|
240
|
+
if (!sharedPackedObjectMap)
|
|
241
|
+
sharedPackedObjectMap = Object.create(null)
|
|
242
|
+
return (options) => {
|
|
243
|
+
let threshold = options && options.threshold || 4
|
|
244
|
+
let position = this.pack ? options.maxPrivatePackedValues || 16 : 0
|
|
245
|
+
if (!sharedValues)
|
|
246
|
+
sharedValues = this.sharedValues = []
|
|
247
|
+
for (let [ key, status ] of samplingPackedValues) {
|
|
248
|
+
if (status.count > threshold) {
|
|
249
|
+
sharedPackedObjectMap[key] = position++
|
|
250
|
+
sharedValues.push(key)
|
|
251
|
+
hasSharedUpdate = true
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
while (this.saveShared && this.updateSharedData() === false) {}
|
|
255
|
+
samplingPackedValues = null
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
const encode = (value) => {
|
|
259
|
+
if (position > safeEnd)
|
|
260
|
+
target = makeRoom(position)
|
|
261
|
+
|
|
262
|
+
var type = typeof value
|
|
263
|
+
var length
|
|
264
|
+
if (type === 'string') {
|
|
265
|
+
if (packedObjectMap) {
|
|
266
|
+
let packedPosition = packedObjectMap[value]
|
|
267
|
+
if (packedPosition >= 0) {
|
|
268
|
+
if (packedPosition < 16)
|
|
269
|
+
target[position++] = packedPosition + 0xe0 // simple values, defined in https://www.potaroo.net/ietf/ids/draft-ietf-cbor-packed-03.txt
|
|
270
|
+
else {
|
|
271
|
+
target[position++] = 0xc6 // tag 6 defined in https://www.potaroo.net/ietf/ids/draft-ietf-cbor-packed-03.txt
|
|
272
|
+
if (packedPosition & 1)
|
|
273
|
+
encode((15 - packedPosition) >> 1)
|
|
274
|
+
else
|
|
275
|
+
encode((packedPosition - 16) >> 1)
|
|
276
|
+
}
|
|
277
|
+
return
|
|
278
|
+
/* } else if (packedStatus.serializationId != serializationId) {
|
|
279
|
+
packedStatus.serializationId = serializationId
|
|
280
|
+
packedStatus.count = 1
|
|
281
|
+
if (options.sharedPack) {
|
|
282
|
+
let sharedCount = packedStatus.sharedCount = (packedStatus.sharedCount || 0) + 1
|
|
283
|
+
if (shareCount > (options.sharedPack.threshold || 5)) {
|
|
284
|
+
let sharedPosition = packedStatus.position = packedStatus.nextSharedPosition
|
|
285
|
+
hasSharedUpdate = true
|
|
286
|
+
if (sharedPosition < 16)
|
|
287
|
+
target[position++] = sharedPosition + 0xc0
|
|
288
|
+
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
} // else any in-doc incrementation?*/
|
|
292
|
+
} else if (samplingPackedValues && !options.pack) {
|
|
293
|
+
let status = samplingPackedValues.get(value)
|
|
294
|
+
if (status)
|
|
295
|
+
status.count++
|
|
296
|
+
else
|
|
297
|
+
samplingPackedValues.set(value, {
|
|
298
|
+
count: 1,
|
|
299
|
+
})
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
let strLength = value.length
|
|
303
|
+
if (bundledStrings && strLength >= 4 && strLength < 0x400) {
|
|
304
|
+
if ((bundledStrings.size += strLength) > MAX_BUNDLE_SIZE) {
|
|
305
|
+
let extStart
|
|
306
|
+
let maxBytes = (bundledStrings[0] ? bundledStrings[0].length * 3 + bundledStrings[1].length : 0) + 10
|
|
307
|
+
if (position + maxBytes > safeEnd)
|
|
308
|
+
target = makeRoom(position + maxBytes)
|
|
309
|
+
target[position++] = 0xd9 // tag 16-bit
|
|
310
|
+
target[position++] = 0xdf // tag 0xdff9
|
|
311
|
+
target[position++] = 0xf9
|
|
312
|
+
// TODO: If we only have one bundle with any string data, only write one string bundle
|
|
313
|
+
target[position++] = bundledStrings.position ? 0x84 : 0x82 // array of 4 or 2 elements depending on if we write bundles
|
|
314
|
+
target[position++] = 0x1a // 32-bit unsigned int
|
|
315
|
+
extStart = position - start
|
|
316
|
+
position += 4 // reserve for writing bundle reference
|
|
317
|
+
if (bundledStrings.position) {
|
|
318
|
+
writeBundles(start, encode) // write the last bundles
|
|
319
|
+
}
|
|
320
|
+
bundledStrings = ['', ''] // create new ones
|
|
321
|
+
bundledStrings.size = 0
|
|
322
|
+
bundledStrings.position = extStart
|
|
323
|
+
}
|
|
324
|
+
let twoByte = hasNonLatin.test(value)
|
|
325
|
+
bundledStrings[twoByte ? 0 : 1] += value
|
|
326
|
+
target[position++] = twoByte ? 0xce : 0xcf
|
|
327
|
+
encode(strLength);
|
|
328
|
+
return
|
|
329
|
+
}
|
|
330
|
+
let headerSize
|
|
331
|
+
// first we estimate the header size, so we can write to the correct location
|
|
332
|
+
if (strLength < 0x20) {
|
|
333
|
+
headerSize = 1
|
|
334
|
+
} else if (strLength < 0x100) {
|
|
335
|
+
headerSize = 2
|
|
336
|
+
} else if (strLength < 0x10000) {
|
|
337
|
+
headerSize = 3
|
|
338
|
+
} else {
|
|
339
|
+
headerSize = 5
|
|
340
|
+
}
|
|
341
|
+
let maxBytes = strLength * 3
|
|
342
|
+
if (position + maxBytes > safeEnd)
|
|
343
|
+
target = makeRoom(position + maxBytes)
|
|
344
|
+
|
|
345
|
+
if (strLength < 0x40 || !encodeUtf8) {
|
|
346
|
+
let i, c1, c2, strPosition = position + headerSize
|
|
347
|
+
for (i = 0; i < strLength; i++) {
|
|
348
|
+
c1 = value.charCodeAt(i)
|
|
349
|
+
if (c1 < 0x80) {
|
|
350
|
+
target[strPosition++] = c1
|
|
351
|
+
} else if (c1 < 0x800) {
|
|
352
|
+
target[strPosition++] = c1 >> 6 | 0xc0
|
|
353
|
+
target[strPosition++] = c1 & 0x3f | 0x80
|
|
354
|
+
} else if (
|
|
355
|
+
(c1 & 0xfc00) === 0xd800 &&
|
|
356
|
+
((c2 = value.charCodeAt(i + 1)) & 0xfc00) === 0xdc00
|
|
357
|
+
) {
|
|
358
|
+
c1 = 0x10000 + ((c1 & 0x03ff) << 10) + (c2 & 0x03ff)
|
|
359
|
+
i++
|
|
360
|
+
target[strPosition++] = c1 >> 18 | 0xf0
|
|
361
|
+
target[strPosition++] = c1 >> 12 & 0x3f | 0x80
|
|
362
|
+
target[strPosition++] = c1 >> 6 & 0x3f | 0x80
|
|
363
|
+
target[strPosition++] = c1 & 0x3f | 0x80
|
|
364
|
+
} else {
|
|
365
|
+
target[strPosition++] = c1 >> 12 | 0xe0
|
|
366
|
+
target[strPosition++] = c1 >> 6 & 0x3f | 0x80
|
|
367
|
+
target[strPosition++] = c1 & 0x3f | 0x80
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
length = strPosition - position - headerSize
|
|
371
|
+
} else {
|
|
372
|
+
length = encodeUtf8(value, position + headerSize, maxBytes)
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (length < 0x18) {
|
|
376
|
+
target[position++] = 0x60 | length
|
|
377
|
+
} else if (length < 0x100) {
|
|
378
|
+
if (headerSize < 2) {
|
|
379
|
+
target.copyWithin(position + 2, position + 1, position + 1 + length)
|
|
380
|
+
}
|
|
381
|
+
target[position++] = 0x78
|
|
382
|
+
target[position++] = length
|
|
383
|
+
} else if (length < 0x10000) {
|
|
384
|
+
if (headerSize < 3) {
|
|
385
|
+
target.copyWithin(position + 3, position + 2, position + 2 + length)
|
|
386
|
+
}
|
|
387
|
+
target[position++] = 0x79
|
|
388
|
+
target[position++] = length >> 8
|
|
389
|
+
target[position++] = length & 0xff
|
|
390
|
+
} else {
|
|
391
|
+
if (headerSize < 5) {
|
|
392
|
+
target.copyWithin(position + 5, position + 3, position + 3 + length)
|
|
393
|
+
}
|
|
394
|
+
target[position++] = 0x7a
|
|
395
|
+
targetView.setUint32(position, length)
|
|
396
|
+
position += 4
|
|
397
|
+
}
|
|
398
|
+
position += length
|
|
399
|
+
} else if (type === 'number') {
|
|
400
|
+
if (!this.alwaysUseFloat && value >>> 0 === value) {// positive integer, 32-bit or less
|
|
401
|
+
// positive uint
|
|
402
|
+
if (value < 0x18) {
|
|
403
|
+
target[position++] = value
|
|
404
|
+
} else if (value < 0x100) {
|
|
405
|
+
target[position++] = 0x18
|
|
406
|
+
target[position++] = value
|
|
407
|
+
} else if (value < 0x10000) {
|
|
408
|
+
target[position++] = 0x19
|
|
409
|
+
target[position++] = value >> 8
|
|
410
|
+
target[position++] = value & 0xff
|
|
411
|
+
} else {
|
|
412
|
+
target[position++] = 0x1a
|
|
413
|
+
targetView.setUint32(position, value)
|
|
414
|
+
position += 4
|
|
415
|
+
}
|
|
416
|
+
} else if (!this.alwaysUseFloat && value >> 0 === value) { // negative integer
|
|
417
|
+
if (value >= -0x18) {
|
|
418
|
+
target[position++] = 0x1f - value
|
|
419
|
+
} else if (value >= -0x100) {
|
|
420
|
+
target[position++] = 0x38
|
|
421
|
+
target[position++] = ~value
|
|
422
|
+
} else if (value >= -0x10000) {
|
|
423
|
+
target[position++] = 0x39
|
|
424
|
+
targetView.setUint16(position, ~value)
|
|
425
|
+
position += 2
|
|
426
|
+
} else {
|
|
427
|
+
target[position++] = 0x3a
|
|
428
|
+
targetView.setUint32(position, ~value)
|
|
429
|
+
position += 4
|
|
430
|
+
}
|
|
431
|
+
} else {
|
|
432
|
+
let useFloat32
|
|
433
|
+
if ((useFloat32 = this.useFloat32) > 0 && value < 0x100000000 && value >= -0x80000000) {
|
|
434
|
+
target[position++] = 0xfa
|
|
435
|
+
targetView.setFloat32(position, value)
|
|
436
|
+
let xShifted
|
|
437
|
+
if (useFloat32 < 4 ||
|
|
438
|
+
// this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
|
|
439
|
+
((xShifted = value * mult10[((target[position] & 0x7f) << 1) | (target[position + 1] >> 7)]) >> 0) === xShifted) {
|
|
440
|
+
position += 4
|
|
441
|
+
return
|
|
442
|
+
} else
|
|
443
|
+
position-- // move back into position for writing a double
|
|
444
|
+
}
|
|
445
|
+
target[position++] = 0xfb
|
|
446
|
+
targetView.setFloat64(position, value)
|
|
447
|
+
position += 8
|
|
448
|
+
}
|
|
449
|
+
} else if (type === 'object') {
|
|
450
|
+
if (!value)
|
|
451
|
+
target[position++] = 0xf6
|
|
452
|
+
else {
|
|
453
|
+
if (referenceMap) {
|
|
454
|
+
let referee = referenceMap.get(value)
|
|
455
|
+
if (referee) {
|
|
456
|
+
target[position++] = 0xd8
|
|
457
|
+
target[position++] = 29 // http://cbor.schmorp.de/value-sharing
|
|
458
|
+
target[position++] = 0x19 // 16-bit uint
|
|
459
|
+
if (!referee.references) {
|
|
460
|
+
let idsToInsert = referenceMap.idsToInsert || (referenceMap.idsToInsert = [])
|
|
461
|
+
referee.references = []
|
|
462
|
+
idsToInsert.push(referee)
|
|
463
|
+
}
|
|
464
|
+
referee.references.push(position - start)
|
|
465
|
+
position += 2 // TODO: also support 32-bit
|
|
466
|
+
return
|
|
467
|
+
} else
|
|
468
|
+
referenceMap.set(value, { offset: position - start })
|
|
469
|
+
}
|
|
470
|
+
let constructor = value.constructor
|
|
471
|
+
if (constructor === Object) {
|
|
472
|
+
writeObject(value)
|
|
473
|
+
} else if (constructor === Array) {
|
|
474
|
+
length = value.length
|
|
475
|
+
if (length < 0x18) {
|
|
476
|
+
target[position++] = 0x80 | length
|
|
477
|
+
} else {
|
|
478
|
+
writeArrayHeader(length)
|
|
479
|
+
}
|
|
480
|
+
for (let i = 0; i < length; i++) {
|
|
481
|
+
encode(value[i])
|
|
482
|
+
}
|
|
483
|
+
} else if (constructor === Map) {
|
|
484
|
+
if (this.mapsAsObjects ? this.useTag259ForMaps !== false : this.useTag259ForMaps) {
|
|
485
|
+
// use Tag 259 (https://github.com/shanewholloway/js-cbor-codec/blob/master/docs/CBOR-259-spec--explicit-maps.md) for maps if the user wants it that way
|
|
486
|
+
target[position++] = 0xd9
|
|
487
|
+
target[position++] = 1
|
|
488
|
+
target[position++] = 3
|
|
489
|
+
}
|
|
490
|
+
length = value.size
|
|
491
|
+
if (length < 0x18) {
|
|
492
|
+
target[position++] = 0xa0 | length
|
|
493
|
+
} else if (length < 0x100) {
|
|
494
|
+
target[position++] = 0xb8
|
|
495
|
+
target[position++] = length
|
|
496
|
+
} else if (length < 0x10000) {
|
|
497
|
+
target[position++] = 0xb9
|
|
498
|
+
target[position++] = length >> 8
|
|
499
|
+
target[position++] = length & 0xff
|
|
500
|
+
} else {
|
|
501
|
+
target[position++] = 0xba
|
|
502
|
+
targetView.setUint32(position, length)
|
|
503
|
+
position += 4
|
|
504
|
+
}
|
|
505
|
+
if (encoder.keyMap) {
|
|
506
|
+
for (let [ key, entryValue ] of value) {
|
|
507
|
+
encode(encoder.encodeKey(key))
|
|
508
|
+
encode(entryValue)
|
|
509
|
+
}
|
|
510
|
+
} else {
|
|
511
|
+
for (let [ key, entryValue ] of value) {
|
|
512
|
+
encode(key)
|
|
513
|
+
encode(entryValue)
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
} else {
|
|
517
|
+
for (let i = 0, l = extensions.length; i < l; i++) {
|
|
518
|
+
let extensionClass = extensionClasses[i]
|
|
519
|
+
if (value instanceof extensionClass) {
|
|
520
|
+
let extension = extensions[i]
|
|
521
|
+
let tag = extension.tag
|
|
522
|
+
if (tag == undefined)
|
|
523
|
+
tag = extension.getTag && extension.getTag.call(this, value)
|
|
524
|
+
if (tag < 0x18) {
|
|
525
|
+
target[position++] = 0xc0 | tag
|
|
526
|
+
} else if (tag < 0x100) {
|
|
527
|
+
target[position++] = 0xd8
|
|
528
|
+
target[position++] = tag
|
|
529
|
+
} else if (tag < 0x10000) {
|
|
530
|
+
target[position++] = 0xd9
|
|
531
|
+
target[position++] = tag >> 8
|
|
532
|
+
target[position++] = tag & 0xff
|
|
533
|
+
} else if (tag > -1) {
|
|
534
|
+
target[position++] = 0xda
|
|
535
|
+
targetView.setUint32(position, tag)
|
|
536
|
+
position += 4
|
|
537
|
+
} // else undefined, don't write tag
|
|
538
|
+
extension.encode.call(this, value, encode, makeRoom)
|
|
539
|
+
return
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
if (value[Symbol.iterator]) {
|
|
543
|
+
if (throwOnIterable) {
|
|
544
|
+
let error = new Error('Iterable should be serialized as iterator')
|
|
545
|
+
error.iteratorNotHandled = true;
|
|
546
|
+
throw error;
|
|
547
|
+
}
|
|
548
|
+
target[position++] = 0x9f // indefinite length array
|
|
549
|
+
for (let entry of value) {
|
|
550
|
+
encode(entry)
|
|
551
|
+
}
|
|
552
|
+
target[position++] = 0xff // stop-code
|
|
553
|
+
return
|
|
554
|
+
}
|
|
555
|
+
if (value[Symbol.asyncIterator] || isBlob(value)) {
|
|
556
|
+
let error = new Error('Iterable/blob should be serialized as iterator')
|
|
557
|
+
error.iteratorNotHandled = true;
|
|
558
|
+
throw error;
|
|
559
|
+
}
|
|
560
|
+
if (this.useToJSON && value.toJSON) {
|
|
561
|
+
const json = value.toJSON()
|
|
562
|
+
// if for some reason value.toJSON returns itself it'll loop forever
|
|
563
|
+
if (json !== value)
|
|
564
|
+
return encode(json)
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// no extension found, write as a plain object
|
|
568
|
+
writeObject(value)
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
} else if (type === 'boolean') {
|
|
572
|
+
target[position++] = value ? 0xf5 : 0xf4
|
|
573
|
+
} else if (type === 'bigint') {
|
|
574
|
+
if (value < (BigInt(1)<<BigInt(64)) && value >= 0) {
|
|
575
|
+
// use an unsigned int as long as it fits
|
|
576
|
+
target[position++] = 0x1b
|
|
577
|
+
targetView.setBigUint64(position, value)
|
|
578
|
+
} else if (value > -(BigInt(1)<<BigInt(64)) && value < 0) {
|
|
579
|
+
// if we can fit an unsigned int, use that
|
|
580
|
+
target[position++] = 0x3b
|
|
581
|
+
targetView.setBigUint64(position, -value - BigInt(1))
|
|
582
|
+
} else {
|
|
583
|
+
// overflow
|
|
584
|
+
if (this.largeBigIntToFloat) {
|
|
585
|
+
target[position++] = 0xfb
|
|
586
|
+
targetView.setFloat64(position, Number(value))
|
|
587
|
+
} else {
|
|
588
|
+
if (value >= BigInt(0))
|
|
589
|
+
target[position++] = 0xc2 // tag 2
|
|
590
|
+
else {
|
|
591
|
+
target[position++] = 0xc3 // tag 2
|
|
592
|
+
value = BigInt(-1) - value;
|
|
593
|
+
}
|
|
594
|
+
let bytes = [];
|
|
595
|
+
while (value) {
|
|
596
|
+
bytes.push(Number(value & BigInt(0xff)));
|
|
597
|
+
value >>= BigInt(8);
|
|
598
|
+
}
|
|
599
|
+
writeBuffer(new Uint8Array(bytes.reverse()), makeRoom);
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
position += 8
|
|
604
|
+
} else if (type === 'undefined') {
|
|
605
|
+
target[position++] = 0xf7
|
|
606
|
+
} else {
|
|
607
|
+
throw new Error('Unknown type: ' + type)
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
const writeObject = this.useRecords === false ? this.variableMapSize ? (object) => {
|
|
612
|
+
// this method is slightly slower, but generates "preferred serialization" (optimally small for smaller objects)
|
|
613
|
+
let keys = Object.keys(object)
|
|
614
|
+
let vals = Object.values(object)
|
|
615
|
+
let length = keys.length
|
|
616
|
+
if (length < 0x18) {
|
|
617
|
+
target[position++] = 0xa0 | length
|
|
618
|
+
} else if (length < 0x100) {
|
|
619
|
+
target[position++] = 0xb8
|
|
620
|
+
target[position++] = length
|
|
621
|
+
} else if (length < 0x10000) {
|
|
622
|
+
target[position++] = 0xb9
|
|
623
|
+
target[position++] = length >> 8
|
|
624
|
+
target[position++] = length & 0xff
|
|
625
|
+
} else {
|
|
626
|
+
target[position++] = 0xba
|
|
627
|
+
targetView.setUint32(position, length)
|
|
628
|
+
position += 4
|
|
629
|
+
}
|
|
630
|
+
let key
|
|
631
|
+
if (encoder.keyMap) {
|
|
632
|
+
for (let i = 0; i < length; i++) {
|
|
633
|
+
encode(encoder.encodeKey(keys[i]))
|
|
634
|
+
encode(vals[i])
|
|
635
|
+
}
|
|
636
|
+
} else {
|
|
637
|
+
for (let i = 0; i < length; i++) {
|
|
638
|
+
encode(keys[i])
|
|
639
|
+
encode(vals[i])
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
} :
|
|
643
|
+
(object) => {
|
|
644
|
+
target[position++] = 0xb9 // always use map 16, so we can preallocate and set the length afterwards
|
|
645
|
+
let objectOffset = position - start
|
|
646
|
+
position += 2
|
|
647
|
+
let size = 0
|
|
648
|
+
if (encoder.keyMap) {
|
|
649
|
+
for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
650
|
+
encode(encoder.encodeKey(key))
|
|
651
|
+
encode(object[key])
|
|
652
|
+
size++
|
|
653
|
+
}
|
|
654
|
+
} else {
|
|
655
|
+
for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
656
|
+
encode(key)
|
|
657
|
+
encode(object[key])
|
|
658
|
+
size++
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
target[objectOffset++ + start] = size >> 8
|
|
662
|
+
target[objectOffset + start] = size & 0xff
|
|
663
|
+
} :
|
|
664
|
+
(object, skipValues) => {
|
|
665
|
+
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null))
|
|
666
|
+
let newTransitions = 0
|
|
667
|
+
let length = 0
|
|
668
|
+
let parentRecordId
|
|
669
|
+
let keys
|
|
670
|
+
if (this.keyMap) {
|
|
671
|
+
keys = Object.keys(object).map(k => this.encodeKey(k))
|
|
672
|
+
length = keys.length
|
|
673
|
+
for (let i = 0; i < length; i++) {
|
|
674
|
+
let key = keys[i]
|
|
675
|
+
nextTransition = transition[key]
|
|
676
|
+
if (!nextTransition) {
|
|
677
|
+
nextTransition = transition[key] = Object.create(null)
|
|
678
|
+
newTransitions++
|
|
679
|
+
}
|
|
680
|
+
transition = nextTransition
|
|
681
|
+
}
|
|
682
|
+
} else {
|
|
683
|
+
for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
684
|
+
nextTransition = transition[key]
|
|
685
|
+
if (!nextTransition) {
|
|
686
|
+
if (transition[RECORD_SYMBOL] & 0x100000) {// this indicates it is a brancheable/extendable terminal node, so we will use this record id and extend it
|
|
687
|
+
parentRecordId = transition[RECORD_SYMBOL] & 0xffff
|
|
688
|
+
}
|
|
689
|
+
nextTransition = transition[key] = Object.create(null)
|
|
690
|
+
newTransitions++
|
|
691
|
+
}
|
|
692
|
+
transition = nextTransition
|
|
693
|
+
length++
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
let recordId = transition[RECORD_SYMBOL]
|
|
697
|
+
if (recordId !== undefined) {
|
|
698
|
+
recordId &= 0xffff
|
|
699
|
+
target[position++] = 0xd9
|
|
700
|
+
target[position++] = (recordId >> 8) | 0xe0
|
|
701
|
+
target[position++] = recordId & 0xff
|
|
702
|
+
} else {
|
|
703
|
+
if (!keys)
|
|
704
|
+
keys = transition.__keys__ || (transition.__keys__ = Object.keys(object))
|
|
705
|
+
if (parentRecordId === undefined) {
|
|
706
|
+
recordId = structures.nextId++
|
|
707
|
+
if (!recordId) {
|
|
708
|
+
recordId = 0
|
|
709
|
+
structures.nextId = 1
|
|
710
|
+
}
|
|
711
|
+
if (recordId >= MAX_STRUCTURES) {// cycle back around
|
|
712
|
+
structures.nextId = (recordId = maxSharedStructures) + 1
|
|
713
|
+
}
|
|
714
|
+
} else {
|
|
715
|
+
recordId = parentRecordId
|
|
716
|
+
}
|
|
717
|
+
structures[recordId] = keys
|
|
718
|
+
if (recordId < maxSharedStructures) {
|
|
719
|
+
target[position++] = 0xd9
|
|
720
|
+
target[position++] = (recordId >> 8) | 0xe0
|
|
721
|
+
target[position++] = recordId & 0xff
|
|
722
|
+
transition = structures.transitions
|
|
723
|
+
for (let i = 0; i < length; i++) {
|
|
724
|
+
if (transition[RECORD_SYMBOL] === undefined || (transition[RECORD_SYMBOL] & 0x100000))
|
|
725
|
+
transition[RECORD_SYMBOL] = recordId
|
|
726
|
+
transition = transition[keys[i]]
|
|
727
|
+
}
|
|
728
|
+
transition[RECORD_SYMBOL] = recordId | 0x100000 // indicates it is a extendable terminal
|
|
729
|
+
hasSharedUpdate = true
|
|
730
|
+
} else {
|
|
731
|
+
transition[RECORD_SYMBOL] = recordId
|
|
732
|
+
targetView.setUint32(position, 0xd9dfff00) // tag two byte, then record definition id
|
|
733
|
+
position += 3
|
|
734
|
+
if (newTransitions)
|
|
735
|
+
transitionsCount += serializationsSinceTransitionRebuild * newTransitions
|
|
736
|
+
// record the removal of the id, we can maintain our shared structure
|
|
737
|
+
if (recordIdsToRemove.length >= MAX_STRUCTURES - maxSharedStructures)
|
|
738
|
+
recordIdsToRemove.shift()[RECORD_SYMBOL] = undefined // we are cycling back through, and have to remove old ones
|
|
739
|
+
recordIdsToRemove.push(transition)
|
|
740
|
+
writeArrayHeader(length + 2)
|
|
741
|
+
encode(0xe000 + recordId)
|
|
742
|
+
encode(keys)
|
|
743
|
+
if (skipValues) return; // special exit for iterator
|
|
744
|
+
for (let key in object)
|
|
745
|
+
if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key))
|
|
746
|
+
encode(object[key])
|
|
747
|
+
return
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
if (length < 0x18) { // write the array header
|
|
751
|
+
target[position++] = 0x80 | length
|
|
752
|
+
} else {
|
|
753
|
+
writeArrayHeader(length)
|
|
754
|
+
}
|
|
755
|
+
if (skipValues) return; // special exit for iterator
|
|
756
|
+
for (let key in object)
|
|
757
|
+
if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key))
|
|
758
|
+
encode(object[key])
|
|
759
|
+
}
|
|
760
|
+
const makeRoom = (end) => {
|
|
761
|
+
let newSize
|
|
762
|
+
if (end > 0x1000000) {
|
|
763
|
+
// special handling for really large buffers
|
|
764
|
+
if ((end - start) > MAX_BUFFER_SIZE)
|
|
765
|
+
throw new Error('Encoded buffer would be larger than maximum buffer size')
|
|
766
|
+
newSize = Math.min(MAX_BUFFER_SIZE,
|
|
767
|
+
Math.round(Math.max((end - start) * (end > 0x4000000 ? 1.25 : 2), 0x400000) / 0x1000) * 0x1000)
|
|
768
|
+
} else // faster handling for smaller buffers
|
|
769
|
+
newSize = ((Math.max((end - start) << 2, target.length - 1) >> 12) + 1) << 12
|
|
770
|
+
let newBuffer = new ByteArrayAllocate(newSize)
|
|
771
|
+
targetView = new DataView(newBuffer.buffer, 0, newSize)
|
|
772
|
+
if (target.copy)
|
|
773
|
+
target.copy(newBuffer, 0, start, end)
|
|
774
|
+
else
|
|
775
|
+
newBuffer.set(target.slice(start, end))
|
|
776
|
+
position -= start
|
|
777
|
+
start = 0
|
|
778
|
+
safeEnd = newBuffer.length - 10
|
|
779
|
+
return target = newBuffer
|
|
780
|
+
}
|
|
781
|
+
let chunkThreshold = 100;
|
|
782
|
+
let continuedChunkThreshold = 1000;
|
|
783
|
+
this.encodeAsIterable = function(value, options) {
|
|
784
|
+
return startEncoding(value, options, encodeObjectAsIterable);
|
|
785
|
+
}
|
|
786
|
+
this.encodeAsAsyncIterable = function(value, options) {
|
|
787
|
+
return startEncoding(value, options, encodeObjectAsAsyncIterable);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
function* encodeObjectAsIterable(object, iterateProperties, finalIterable) {
|
|
791
|
+
let constructor = object.constructor;
|
|
792
|
+
if (constructor === Object) {
|
|
793
|
+
let useRecords = encoder.useRecords !== false;
|
|
794
|
+
if (useRecords)
|
|
795
|
+
writeObject(object, true); // write the record identifier
|
|
796
|
+
else
|
|
797
|
+
writeEntityLength(Object.keys(object).length, 0xa0);
|
|
798
|
+
for (let key in object) {
|
|
799
|
+
let value = object[key];
|
|
800
|
+
if (!useRecords) encode(key);
|
|
801
|
+
if (value && typeof value === 'object') {
|
|
802
|
+
if (iterateProperties[key])
|
|
803
|
+
yield* encodeObjectAsIterable(value, iterateProperties[key]);
|
|
804
|
+
else
|
|
805
|
+
yield* tryEncode(value, iterateProperties, key);
|
|
806
|
+
} else encode(value);
|
|
807
|
+
}
|
|
808
|
+
} else if (constructor === Array) {
|
|
809
|
+
let length = object.length;
|
|
810
|
+
writeArrayHeader(length);
|
|
811
|
+
for (let i = 0; i < length; i++) {
|
|
812
|
+
let value = object[i];
|
|
813
|
+
if (value && (typeof value === 'object' || position - start > chunkThreshold)) {
|
|
814
|
+
if (iterateProperties.element)
|
|
815
|
+
yield* encodeObjectAsIterable(value, iterateProperties.element);
|
|
816
|
+
else
|
|
817
|
+
yield* tryEncode(value, iterateProperties, 'element');
|
|
818
|
+
} else encode(value);
|
|
819
|
+
}
|
|
820
|
+
} else if (object[Symbol.iterator] && !object.buffer) { // iterator, but exclude typed arrays
|
|
821
|
+
target[position++] = 0x9f; // start indefinite array
|
|
822
|
+
for (let value of object) {
|
|
823
|
+
if (value && (typeof value === 'object' || position - start > chunkThreshold)) {
|
|
824
|
+
if (iterateProperties.element)
|
|
825
|
+
yield* encodeObjectAsIterable(value, iterateProperties.element);
|
|
826
|
+
else
|
|
827
|
+
yield* tryEncode(value, iterateProperties, 'element');
|
|
828
|
+
} else encode(value);
|
|
829
|
+
}
|
|
830
|
+
target[position++] = 0xff; // stop byte
|
|
831
|
+
} else if (isBlob(object)){
|
|
832
|
+
writeEntityLength(object.size, 0x40); // encode as binary data
|
|
833
|
+
yield target.subarray(start, position);
|
|
834
|
+
yield object; // directly return blobs, they have to be encoded asynchronously
|
|
835
|
+
restartEncoding();
|
|
836
|
+
} else if (object[Symbol.asyncIterator]) {
|
|
837
|
+
target[position++] = 0x9f; // start indefinite array
|
|
838
|
+
yield target.subarray(start, position);
|
|
839
|
+
yield object; // directly return async iterators, they have to be encoded asynchronously
|
|
840
|
+
restartEncoding();
|
|
841
|
+
target[position++] = 0xff; // stop byte
|
|
842
|
+
} else {
|
|
843
|
+
encode(object);
|
|
844
|
+
}
|
|
845
|
+
if (finalIterable && position > start) yield target.subarray(start, position);
|
|
846
|
+
else if (position - start > chunkThreshold) {
|
|
847
|
+
yield target.subarray(start, position);
|
|
848
|
+
restartEncoding();
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
function* tryEncode(value, iterateProperties, key) {
|
|
852
|
+
let restart = position - start;
|
|
853
|
+
try {
|
|
854
|
+
encode(value);
|
|
855
|
+
if (position - start > chunkThreshold) {
|
|
856
|
+
yield target.subarray(start, position);
|
|
857
|
+
restartEncoding();
|
|
858
|
+
}
|
|
859
|
+
} catch (error) {
|
|
860
|
+
if (error.iteratorNotHandled) {
|
|
861
|
+
iterateProperties[key] = {};
|
|
862
|
+
position = start + restart; // restart our position so we don't have partial data from last encode
|
|
863
|
+
yield* encodeObjectAsIterable.call(this, value, iterateProperties[key]);
|
|
864
|
+
} else throw error;
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
function restartEncoding() {
|
|
868
|
+
chunkThreshold = continuedChunkThreshold;
|
|
869
|
+
encoder.encode(null, THROW_ON_ITERABLE); // restart encoding
|
|
870
|
+
}
|
|
871
|
+
function startEncoding(value, options, encodeIterable) {
|
|
872
|
+
if (options && options.chunkThreshold) // explicitly specified chunk sizes
|
|
873
|
+
chunkThreshold = continuedChunkThreshold = options.chunkThreshold;
|
|
874
|
+
else // we start with a smaller threshold to get initial bytes sent quickly
|
|
875
|
+
chunkThreshold = 100;
|
|
876
|
+
if (value && typeof value === 'object') {
|
|
877
|
+
encoder.encode(null, THROW_ON_ITERABLE); // start encoding
|
|
878
|
+
return encodeIterable(value, encoder.iterateProperties || (encoder.iterateProperties = {}), true);
|
|
879
|
+
}
|
|
880
|
+
return [encoder.encode(value)];
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
async function* encodeObjectAsAsyncIterable(value, iterateProperties) {
|
|
884
|
+
for (let encodedValue of encodeObjectAsIterable(value, iterateProperties, true)) {
|
|
885
|
+
let constructor = encodedValue.constructor;
|
|
886
|
+
if (constructor === ByteArray || constructor === Uint8Array)
|
|
887
|
+
yield encodedValue;
|
|
888
|
+
else if (isBlob(encodedValue)) {
|
|
889
|
+
let reader = encodedValue.stream().getReader();
|
|
890
|
+
let next;
|
|
891
|
+
while (!(next = await reader.read()).done) {
|
|
892
|
+
yield next.value;
|
|
893
|
+
}
|
|
894
|
+
} else if (encodedValue[Symbol.asyncIterator]) {
|
|
895
|
+
for await (let asyncValue of encodedValue) {
|
|
896
|
+
restartEncoding();
|
|
897
|
+
if (asyncValue)
|
|
898
|
+
yield* encodeObjectAsAsyncIterable(asyncValue, iterateProperties.async || (iterateProperties.async = {}));
|
|
899
|
+
else yield encoder.encode(asyncValue);
|
|
900
|
+
}
|
|
901
|
+
} else {
|
|
902
|
+
yield encodedValue;
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
useBuffer(buffer) {
|
|
908
|
+
// this means we are finished using our own buffer and we can write over it safely
|
|
909
|
+
target = buffer
|
|
910
|
+
targetView = new DataView(target.buffer, target.byteOffset, target.byteLength)
|
|
911
|
+
position = 0
|
|
912
|
+
}
|
|
913
|
+
clearSharedData() {
|
|
914
|
+
if (this.structures)
|
|
915
|
+
this.structures = []
|
|
916
|
+
if (this.sharedValues)
|
|
917
|
+
this.sharedValues = undefined
|
|
918
|
+
}
|
|
919
|
+
updateSharedData() {
|
|
920
|
+
let lastVersion = this.sharedVersion || 0
|
|
921
|
+
this.sharedVersion = lastVersion + 1
|
|
922
|
+
let structuresCopy = this.structures.slice(0)
|
|
923
|
+
let sharedData = new SharedData(structuresCopy, this.sharedValues, this.sharedVersion)
|
|
924
|
+
let saveResults = this.saveShared(sharedData,
|
|
925
|
+
existingShared => (existingShared && existingShared.version || 0) == lastVersion)
|
|
926
|
+
if (saveResults === false) {
|
|
927
|
+
// get updated structures and try again if the update failed
|
|
928
|
+
sharedData = this.getShared() || {}
|
|
929
|
+
this.structures = sharedData.structures || []
|
|
930
|
+
this.sharedValues = sharedData.packedValues
|
|
931
|
+
this.sharedVersion = sharedData.version
|
|
932
|
+
this.structures.nextId = this.structures.length
|
|
933
|
+
} else {
|
|
934
|
+
// restore structures
|
|
935
|
+
structuresCopy.forEach((structure, i) => this.structures[i] = structure)
|
|
936
|
+
}
|
|
937
|
+
// saveShared may fail to write and reload, or may have reloaded to check compatibility and overwrite saved data, either way load the correct shared data
|
|
938
|
+
return saveResults
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
function writeEntityLength(length, majorValue) {
|
|
942
|
+
if (length < 0x18)
|
|
943
|
+
target[position++] = majorValue | length
|
|
944
|
+
else if (length < 0x100) {
|
|
945
|
+
target[position++] = majorValue | 0x18
|
|
946
|
+
target[position++] = length
|
|
947
|
+
} else if (length < 0x10000) {
|
|
948
|
+
target[position++] = majorValue | 0x19
|
|
949
|
+
target[position++] = length >> 8
|
|
950
|
+
target[position++] = length & 0xff
|
|
951
|
+
} else {
|
|
952
|
+
target[position++] = majorValue | 0x1a
|
|
953
|
+
targetView.setUint32(position, length)
|
|
954
|
+
position += 4
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
}
|
|
958
|
+
class SharedData {
|
|
959
|
+
constructor(structures, values, version) {
|
|
960
|
+
this.structures = structures
|
|
961
|
+
this.packedValues = values
|
|
962
|
+
this.version = version
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
function writeArrayHeader(length) {
|
|
967
|
+
if (length < 0x18)
|
|
968
|
+
target[position++] = 0x80 | length
|
|
969
|
+
else if (length < 0x100) {
|
|
970
|
+
target[position++] = 0x98
|
|
971
|
+
target[position++] = length
|
|
972
|
+
} else if (length < 0x10000) {
|
|
973
|
+
target[position++] = 0x99
|
|
974
|
+
target[position++] = length >> 8
|
|
975
|
+
target[position++] = length & 0xff
|
|
976
|
+
} else {
|
|
977
|
+
target[position++] = 0x9a
|
|
978
|
+
targetView.setUint32(position, length)
|
|
979
|
+
position += 4
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
const BlobConstructor = typeof Blob === 'undefined' ? function(){} : Blob;
|
|
984
|
+
function isBlob(object) {
|
|
985
|
+
if (object instanceof BlobConstructor)
|
|
986
|
+
return true;
|
|
987
|
+
let tag = object[Symbol.toStringTag];
|
|
988
|
+
return tag === 'Blob' || tag === 'File';
|
|
989
|
+
}
|
|
990
|
+
function findRepetitiveStrings(value, packedValues) {
|
|
991
|
+
switch(typeof value) {
|
|
992
|
+
case 'string':
|
|
993
|
+
if (value.length > 3) {
|
|
994
|
+
if (packedValues.objectMap[value] > -1 || packedValues.values.length >= packedValues.maxValues)
|
|
995
|
+
return
|
|
996
|
+
let packedStatus = packedValues.get(value)
|
|
997
|
+
if (packedStatus) {
|
|
998
|
+
if (++packedStatus.count == 2) {
|
|
999
|
+
packedValues.values.push(value)
|
|
1000
|
+
}
|
|
1001
|
+
} else {
|
|
1002
|
+
packedValues.set(value, {
|
|
1003
|
+
count: 1,
|
|
1004
|
+
})
|
|
1005
|
+
if (packedValues.samplingPackedValues) {
|
|
1006
|
+
let status = packedValues.samplingPackedValues.get(value)
|
|
1007
|
+
if (status)
|
|
1008
|
+
status.count++
|
|
1009
|
+
else
|
|
1010
|
+
packedValues.samplingPackedValues.set(value, {
|
|
1011
|
+
count: 1,
|
|
1012
|
+
})
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
break
|
|
1017
|
+
case 'object':
|
|
1018
|
+
if (value) {
|
|
1019
|
+
if (value instanceof Array) {
|
|
1020
|
+
for (let i = 0, l = value.length; i < l; i++) {
|
|
1021
|
+
findRepetitiveStrings(value[i], packedValues)
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
} else {
|
|
1025
|
+
let includeKeys = !packedValues.encoder.useRecords
|
|
1026
|
+
for (var key in value) {
|
|
1027
|
+
if (value.hasOwnProperty(key)) {
|
|
1028
|
+
if (includeKeys)
|
|
1029
|
+
findRepetitiveStrings(key, packedValues)
|
|
1030
|
+
findRepetitiveStrings(value[key], packedValues)
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
break
|
|
1036
|
+
case 'function': console.log(value)
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
const isLittleEndianMachine = new Uint8Array(new Uint16Array([1]).buffer)[0] == 1
|
|
1040
|
+
extensionClasses = [ Date, Set, Error, RegExp, Tag, ArrayBuffer,
|
|
1041
|
+
Uint8Array, Uint8ClampedArray, Uint16Array, Uint32Array,
|
|
1042
|
+
typeof BigUint64Array == 'undefined' ? function() {} : BigUint64Array, Int8Array, Int16Array, Int32Array,
|
|
1043
|
+
typeof BigInt64Array == 'undefined' ? function() {} : BigInt64Array,
|
|
1044
|
+
Float32Array, Float64Array, SharedData ]
|
|
1045
|
+
|
|
1046
|
+
//Object.getPrototypeOf(Uint8Array.prototype).constructor /*TypedArray*/
|
|
1047
|
+
extensions = [{ // Date
|
|
1048
|
+
tag: 1,
|
|
1049
|
+
encode(date, encode) {
|
|
1050
|
+
let seconds = date.getTime() / 1000
|
|
1051
|
+
if ((this.useTimestamp32 || date.getMilliseconds() === 0) && seconds >= 0 && seconds < 0x100000000) {
|
|
1052
|
+
// Timestamp 32
|
|
1053
|
+
target[position++] = 0x1a
|
|
1054
|
+
targetView.setUint32(position, seconds)
|
|
1055
|
+
position += 4
|
|
1056
|
+
} else {
|
|
1057
|
+
// Timestamp float64
|
|
1058
|
+
target[position++] = 0xfb
|
|
1059
|
+
targetView.setFloat64(position, seconds)
|
|
1060
|
+
position += 8
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
}, { // Set
|
|
1064
|
+
tag: 258, // https://github.com/input-output-hk/cbor-sets-spec/blob/master/CBOR_SETS.md
|
|
1065
|
+
encode(set, encode) {
|
|
1066
|
+
let array = Array.from(set)
|
|
1067
|
+
encode(array)
|
|
1068
|
+
}
|
|
1069
|
+
}, { // Error
|
|
1070
|
+
tag: 27, // http://cbor.schmorp.de/generic-object
|
|
1071
|
+
encode(error, encode) {
|
|
1072
|
+
encode([ error.name, error.message ])
|
|
1073
|
+
}
|
|
1074
|
+
}, { // RegExp
|
|
1075
|
+
tag: 27, // http://cbor.schmorp.de/generic-object
|
|
1076
|
+
encode(regex, encode) {
|
|
1077
|
+
encode([ 'RegExp', regex.source, regex.flags ])
|
|
1078
|
+
}
|
|
1079
|
+
}, { // Tag
|
|
1080
|
+
getTag(tag) {
|
|
1081
|
+
return tag.tag
|
|
1082
|
+
},
|
|
1083
|
+
encode(tag, encode) {
|
|
1084
|
+
encode(tag.value)
|
|
1085
|
+
}
|
|
1086
|
+
}, { // ArrayBuffer
|
|
1087
|
+
encode(arrayBuffer, encode, makeRoom) {
|
|
1088
|
+
writeBuffer(arrayBuffer, makeRoom)
|
|
1089
|
+
}
|
|
1090
|
+
}, { // Uint8Array
|
|
1091
|
+
getTag(typedArray) {
|
|
1092
|
+
if (typedArray.constructor === Uint8Array) {
|
|
1093
|
+
if (this.tagUint8Array || hasNodeBuffer && this.tagUint8Array !== false)
|
|
1094
|
+
return 64;
|
|
1095
|
+
} // else no tag
|
|
1096
|
+
},
|
|
1097
|
+
encode(typedArray, encode, makeRoom) {
|
|
1098
|
+
writeBuffer(typedArray, makeRoom)
|
|
1099
|
+
}
|
|
1100
|
+
},
|
|
1101
|
+
typedArrayEncoder(68, 1),
|
|
1102
|
+
typedArrayEncoder(69, 2),
|
|
1103
|
+
typedArrayEncoder(70, 4),
|
|
1104
|
+
typedArrayEncoder(71, 8),
|
|
1105
|
+
typedArrayEncoder(72, 1),
|
|
1106
|
+
typedArrayEncoder(77, 2),
|
|
1107
|
+
typedArrayEncoder(78, 4),
|
|
1108
|
+
typedArrayEncoder(79, 8),
|
|
1109
|
+
typedArrayEncoder(85, 4),
|
|
1110
|
+
typedArrayEncoder(86, 8),
|
|
1111
|
+
{
|
|
1112
|
+
encode(sharedData, encode) { // write SharedData
|
|
1113
|
+
let packedValues = sharedData.packedValues || []
|
|
1114
|
+
let sharedStructures = sharedData.structures || []
|
|
1115
|
+
if (packedValues.values.length > 0) {
|
|
1116
|
+
target[position++] = 0xd8 // one-byte tag
|
|
1117
|
+
target[position++] = 51 // tag 51 for packed shared structures https://www.potaroo.net/ietf/ids/draft-ietf-cbor-packed-03.txt
|
|
1118
|
+
writeArrayHeader(4)
|
|
1119
|
+
let valuesArray = packedValues.values
|
|
1120
|
+
encode(valuesArray)
|
|
1121
|
+
writeArrayHeader(0) // prefixes
|
|
1122
|
+
writeArrayHeader(0) // suffixes
|
|
1123
|
+
packedObjectMap = Object.create(sharedPackedObjectMap || null)
|
|
1124
|
+
for (let i = 0, l = valuesArray.length; i < l; i++) {
|
|
1125
|
+
packedObjectMap[valuesArray[i]] = i
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
if (sharedStructures) {
|
|
1129
|
+
targetView.setUint32(position, 0xd9dffe00)
|
|
1130
|
+
position += 3
|
|
1131
|
+
let definitions = sharedStructures.slice(0)
|
|
1132
|
+
definitions.unshift(0xe000)
|
|
1133
|
+
definitions.push(new Tag(sharedData.version, 0x53687264))
|
|
1134
|
+
encode(definitions)
|
|
1135
|
+
} else
|
|
1136
|
+
encode(new Tag(sharedData.version, 0x53687264))
|
|
1137
|
+
}
|
|
1138
|
+
}]
|
|
1139
|
+
function typedArrayEncoder(tag, size) {
|
|
1140
|
+
if (!isLittleEndianMachine && size > 1)
|
|
1141
|
+
tag -= 4 // the big endian equivalents are 4 less
|
|
1142
|
+
return {
|
|
1143
|
+
tag: tag,
|
|
1144
|
+
encode: function writeExtBuffer(typedArray, encode) {
|
|
1145
|
+
let length = typedArray.byteLength
|
|
1146
|
+
let offset = typedArray.byteOffset || 0
|
|
1147
|
+
let buffer = typedArray.buffer || typedArray
|
|
1148
|
+
encode(hasNodeBuffer ? Buffer.from(buffer, offset, length) :
|
|
1149
|
+
new Uint8Array(buffer, offset, length))
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
function writeBuffer(buffer, makeRoom) {
|
|
1154
|
+
let length = buffer.byteLength
|
|
1155
|
+
if (length < 0x18) {
|
|
1156
|
+
target[position++] = 0x40 + length
|
|
1157
|
+
} else if (length < 0x100) {
|
|
1158
|
+
target[position++] = 0x58
|
|
1159
|
+
target[position++] = length
|
|
1160
|
+
} else if (length < 0x10000) {
|
|
1161
|
+
target[position++] = 0x59
|
|
1162
|
+
target[position++] = length >> 8
|
|
1163
|
+
target[position++] = length & 0xff
|
|
1164
|
+
} else {
|
|
1165
|
+
target[position++] = 0x5a
|
|
1166
|
+
targetView.setUint32(position, length)
|
|
1167
|
+
position += 4
|
|
1168
|
+
}
|
|
1169
|
+
if (position + length >= target.length) {
|
|
1170
|
+
makeRoom(position + length)
|
|
1171
|
+
}
|
|
1172
|
+
// if it is already a typed array (has an ArrayBuffer), use that, but if it is an ArrayBuffer itself,
|
|
1173
|
+
// must wrap it to set it.
|
|
1174
|
+
target.set(buffer.buffer ? buffer : new Uint8Array(buffer), position)
|
|
1175
|
+
position += length
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
function insertIds(serialized, idsToInsert) {
|
|
1179
|
+
// insert the ids that need to be referenced for structured clones
|
|
1180
|
+
let nextId
|
|
1181
|
+
let distanceToMove = idsToInsert.length * 2
|
|
1182
|
+
let lastEnd = serialized.length - distanceToMove
|
|
1183
|
+
idsToInsert.sort((a, b) => a.offset > b.offset ? 1 : -1)
|
|
1184
|
+
for (let id = 0; id < idsToInsert.length; id++) {
|
|
1185
|
+
let referee = idsToInsert[id]
|
|
1186
|
+
referee.id = id
|
|
1187
|
+
for (let position of referee.references) {
|
|
1188
|
+
serialized[position++] = id >> 8
|
|
1189
|
+
serialized[position] = id & 0xff
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
while (nextId = idsToInsert.pop()) {
|
|
1193
|
+
let offset = nextId.offset
|
|
1194
|
+
serialized.copyWithin(offset + distanceToMove, offset, lastEnd)
|
|
1195
|
+
distanceToMove -= 2
|
|
1196
|
+
let position = offset + distanceToMove
|
|
1197
|
+
serialized[position++] = 0xd8
|
|
1198
|
+
serialized[position++] = 28 // http://cbor.schmorp.de/value-sharing
|
|
1199
|
+
lastEnd = offset
|
|
1200
|
+
}
|
|
1201
|
+
return serialized
|
|
1202
|
+
}
|
|
1203
|
+
function writeBundles(start, encode) {
|
|
1204
|
+
targetView.setUint32(bundledStrings.position + start, position - bundledStrings.position - start + 1) // the offset to bundle
|
|
1205
|
+
let writeStrings = bundledStrings
|
|
1206
|
+
bundledStrings = null
|
|
1207
|
+
encode(writeStrings[0])
|
|
1208
|
+
encode(writeStrings[1])
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
export function addExtension(extension) {
|
|
1212
|
+
if (extension.Class) {
|
|
1213
|
+
if (!extension.encode)
|
|
1214
|
+
throw new Error('Extension has no encode function')
|
|
1215
|
+
extensionClasses.unshift(extension.Class)
|
|
1216
|
+
extensions.unshift(extension)
|
|
1217
|
+
}
|
|
1218
|
+
decodeAddExtension(extension)
|
|
1219
|
+
}
|
|
1220
|
+
let defaultEncoder = new Encoder({ useRecords: false })
|
|
1221
|
+
export const encode = defaultEncoder.encode
|
|
1222
|
+
export const encodeAsIterable = defaultEncoder.encodeAsIterable
|
|
1223
|
+
export const encodeAsAsyncIterable = defaultEncoder.encodeAsAsyncIterable
|
|
1224
|
+
export { FLOAT32_OPTIONS } from './decode.js'
|
|
1225
|
+
import { FLOAT32_OPTIONS } from './decode.js'
|
|
1226
|
+
export const { NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } = FLOAT32_OPTIONS
|
|
1227
|
+
export const REUSE_BUFFER_MODE = 512
|
|
1228
|
+
export const RESET_BUFFER_MODE = 1024
|
|
1229
|
+
export const THROW_ON_ITERABLE = 2048
|
|
1230
|
+
|
|
1231
|
+
|