cbor-x 1.0.0 → 1.2.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/encode.js CHANGED
@@ -38,12 +38,18 @@ export class Encoder extends Decoder {
38
38
  } : false
39
39
 
40
40
  let encoder = this
41
- let maxSharedStructures = options.maxSharedStructures || 128
41
+ let hasSharedStructures = options.structures || options.saveStructures
42
+ let maxSharedStructures = options.maxSharedStructures
43
+ if (maxSharedStructures == null)
44
+ maxSharedStructures = hasSharedStructures ? 128 : 0
45
+ if (maxSharedStructures > 8190)
46
+ throw new Error('Maximum maxSharedStructure is 8190')
42
47
  let isSequential = options.sequential
43
48
  if (isSequential) {
44
49
  maxSharedStructures = 0
45
- this.structures = []
46
50
  }
51
+ if (!this.structures)
52
+ this.structures = []
47
53
  if (this.saveStructures)
48
54
  this.saveShared = this.saveStructures
49
55
  let samplingPackedValues, packedObjectMap, sharedValues = options.sharedValues
@@ -91,6 +97,10 @@ export class Encoder extends Decoder {
91
97
  } else if (encodeOptions === REUSE_BUFFER_MODE)
92
98
  position = (position + 7) & 0x7ffffff8 // Word align to make any future copying of this buffer faster
93
99
  start = position
100
+ if (encoder.useSelfDescribedHeader) {
101
+ targetView.setUint32(position, 0xd9d9f700) // tag two byte, then self-descriptive tag
102
+ position += 3
103
+ }
94
104
  referenceMap = encoder.structuredClone ? new Map() : null
95
105
  if (encoder.bundleStrings && typeof value !== 'string') {
96
106
  bundledStrings = []
@@ -124,6 +134,8 @@ export class Encoder extends Decoder {
124
134
  continue
125
135
  let nextTransition, transition = sharedStructures.transitions
126
136
  for (let j = 0, l = keys.length; j < l; j++) {
137
+ if (transition[RECORD_SYMBOL] === undefined)
138
+ transition[RECORD_SYMBOL] = i
127
139
  let key = keys[j]
128
140
  nextTransition = transition[key]
129
141
  if (!nextTransition) {
@@ -131,7 +143,7 @@ export class Encoder extends Decoder {
131
143
  }
132
144
  transition = nextTransition
133
145
  }
134
- transition[RECORD_SYMBOL] = i
146
+ transition[RECORD_SYMBOL] = i | 0x100000
135
147
  }
136
148
  }
137
149
  if (!isSequential)
@@ -183,11 +195,13 @@ export class Encoder extends Decoder {
183
195
  target.end = position
184
196
  return target
185
197
  }
186
- return target.subarray(start, position) // position can change if we call pack again in saveShared, so we get the buffer now
198
+ return target.subarray(start, position) // position can change if we call encode again in saveShared, so we get the buffer now
187
199
  } finally {
188
200
  if (sharedStructures) {
189
201
  if (serializationsSinceTransitionRebuild < 10)
190
202
  serializationsSinceTransitionRebuild++
203
+ if (sharedStructures.length > maxSharedStructures)
204
+ sharedStructures.length = maxSharedStructures
191
205
  if (transitionsCount > 10000) {
192
206
  // force a rebuild occasionally after a lot of transitions so it can get cleaned up
193
207
  sharedStructures.transitions = null
@@ -200,6 +214,7 @@ export class Encoder extends Decoder {
200
214
  recordIdsToRemove[i][RECORD_SYMBOL] = undefined
201
215
  }
202
216
  recordIdsToRemove = []
217
+ //sharedStructures.nextId = maxSharedStructures
203
218
  }
204
219
  }
205
220
  if (hasSharedUpdate && encoder.saveShared) {
@@ -499,7 +514,9 @@ export class Encoder extends Decoder {
499
514
  let extensionClass = extensionClasses[i]
500
515
  if (value instanceof extensionClass) {
501
516
  let extension = extensions[i]
502
- let tag = extension.tag || extension.getTag && extension.getTag(value)
517
+ let tag = extension.tag
518
+ if (tag == undefined)
519
+ tag = extension.getTag && extension.getTag(value)
503
520
  if (tag < 0x18) {
504
521
  target[position++] = 0xc0 | tag
505
522
  } else if (tag < 0x100) {
@@ -611,88 +628,74 @@ export class Encoder extends Decoder {
611
628
  target[objectOffset++ + start] = size >> 8
612
629
  target[objectOffset + start] = size & 0xff
613
630
  } :
614
-
615
- /* sharedStructures ? // For highly stable structures, using for-in can a little bit faster
616
631
  (object, safePrototype) => {
617
632
  let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null))
618
- let objectOffset = position++ - start
619
- let wroteKeys
620
- for (let key in object) {
621
- if (safePrototype || object.hasOwnProperty(key)) {
633
+ let newTransitions = 0
634
+ let length = 0
635
+ let parentRecordId
636
+ let keys
637
+ if (this.keyMap) {
638
+ keys = Object.keys(object).map(k => this.encodeKey(k))
639
+ length = keys.length
640
+ for (let i = 0; i < length; i++) {
641
+ let key = keys[i]
622
642
  nextTransition = transition[key]
623
643
  if (!nextTransition) {
624
644
  nextTransition = transition[key] = Object.create(null)
625
- nextTransition.__keys__ = (transition.__keys__ || []).concat([key])
626
- /*let keys = Object.keys(object)
627
- if
628
- let size = 0
629
- let startBranch = transition.__keys__ ? transition.__keys__.length : 0
630
- for (let i = 0, l = keys.length; i++) {
631
- let key = keys[i]
632
- size += key.length << 2
633
- if (i >= startBranch) {
634
- nextTransition = nextTransition[key] = Object.create(null)
635
- nextTransition.__keys__ = keys.slice(0, i + 1)
636
- }
645
+ newTransitions++
646
+ }
647
+ transition = nextTransition
648
+ }
649
+ } else {
650
+ for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
651
+ nextTransition = transition[key]
652
+ if (!nextTransition) {
653
+ if (transition[RECORD_SYMBOL] & 0x100000) {// this indicates it is a brancheable/extendable terminal node, so we will use this record id and extend it
654
+ parentRecordId = transition[RECORD_SYMBOL] & 0xffff
637
655
  }
638
- makeRoom(position + size)
639
- nextTransition = transition[key]
640
- target.copy(target, )
641
- objectOffset
656
+ nextTransition = transition[key] = Object.create(null)
657
+ newTransitions++
642
658
  }
643
659
  transition = nextTransition
644
- encode(object[key])
645
- }
646
- }
647
- let id = transition.id
648
- if (!id) {
649
- id = transition.id = structures.push(transition.__keys__) + 63
650
- if (sharedStructures.onUpdate)
651
- sharedStructures.onUpdate(id, transition.__keys__)
652
- }
653
- target[objectOffset + start] = id
654
- }*/
655
- (object) => {
656
- let keys = Object.keys(object)
657
- let vals = Object.values(object)
658
- if (this.keyMap) keys = keys.map(k => this.encodeKey(k))
659
- let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null))
660
- let newTransitions = 0
661
- let length = keys.length
662
- //let parentRecordId
663
- for (let i = 0; i < length; i++) {
664
- //if (!parentRecordId)
665
- let key = keys[i]
666
- // parentRecordId = transition[RECORD_SYMBOL]
667
- nextTransition = transition[key]
668
- if (!nextTransition) {
669
- nextTransition = transition[key] = Object.create(null)
670
- newTransitions++
660
+ length++
671
661
  }
672
- transition = nextTransition
673
662
  }
674
663
  let recordId = transition[RECORD_SYMBOL]
675
664
  if (recordId !== undefined) {
665
+ recordId &= 0xffff
676
666
  target[position++] = 0xd9
677
667
  target[position++] = (recordId >> 8) | 0xe0
678
668
  target[position++] = recordId & 0xff
679
669
  } else {
680
- recordId = structures.nextId++
681
- if (!recordId) {
682
- recordId = 0
683
- structures.nextId = 1
684
- }
685
- if (recordId >= MAX_STRUCTURES) {// cycle back around
686
- structures.nextId = (recordId = maxSharedStructures) + 1
670
+ if (!keys)
671
+ keys = transition.__keys__ || (transition.__keys__ = Object.keys(object))
672
+ if (parentRecordId === undefined) {
673
+ recordId = structures.nextId++
674
+ if (!recordId) {
675
+ recordId = 0
676
+ structures.nextId = 1
677
+ }
678
+ if (recordId >= MAX_STRUCTURES) {// cycle back around
679
+ structures.nextId = (recordId = maxSharedStructures) + 1
680
+ }
681
+ } else {
682
+ recordId = parentRecordId
687
683
  }
688
- transition[RECORD_SYMBOL] = recordId
689
684
  structures[recordId] = keys
690
- if (sharedStructures && sharedStructures.length <= maxSharedStructures) {
685
+ if (recordId < maxSharedStructures) {
691
686
  target[position++] = 0xd9
692
687
  target[position++] = (recordId >> 8) | 0xe0
693
688
  target[position++] = recordId & 0xff
689
+ transition = structures.transitions
690
+ for (let i = 0; i < length; i++) {
691
+ if (transition[RECORD_SYMBOL] === undefined || (transition[RECORD_SYMBOL] & 0x100000))
692
+ transition[RECORD_SYMBOL] = recordId
693
+ transition = transition[keys[i]]
694
+ }
695
+ transition[RECORD_SYMBOL] = recordId | 0x100000 // indicates it is a extendable terminal
694
696
  hasSharedUpdate = true
695
697
  } else {
698
+ transition[RECORD_SYMBOL] = recordId
696
699
  targetView.setUint32(position, 0xd9dfff00) // tag two byte, then record definition id
697
700
  position += 3
698
701
  if (newTransitions)
@@ -713,7 +716,9 @@ export class Encoder extends Decoder {
713
716
  } else {
714
717
  writeArrayHeader(length)
715
718
  }
716
- for (let i =0; i < length; i++) encode(vals[i])
719
+ for (let key in object)
720
+ if (safePrototype || object.hasOwnProperty(key))
721
+ encode(object[key])
717
722
  }
718
723
  const makeRoom = (end) => {
719
724
  let newSize
@@ -752,15 +757,22 @@ export class Encoder extends Decoder {
752
757
  updateSharedData() {
753
758
  let lastVersion = this.sharedVersion || 0
754
759
  this.sharedVersion = lastVersion + 1
755
- let saveResults = this.saveShared(new SharedData(this.structures, this.sharedValues, this.sharedVersion),
760
+ let structuresCopy = this.structures.slice(0)
761
+ let sharedData = new SharedData(structuresCopy, this.sharedValues, this.sharedVersion)
762
+ let saveResults = this.saveShared(sharedData,
756
763
  existingShared => (existingShared && existingShared.version || 0) == lastVersion)
757
764
  if (saveResults === false) {
758
765
  // get updated structures and try again if the update failed
759
- let sharedData = this.getShared() || {}
766
+ sharedData = this.getShared() || {}
760
767
  this.structures = sharedData.structures || []
761
768
  this.sharedValues = sharedData.packedValues
762
769
  this.sharedVersion = sharedData.version
770
+ this.structures.nextId = this.structures.length
771
+ } else {
772
+ // restore structures
773
+ structuresCopy.forEach((structure, i) => this.structures[i] = structure)
763
774
  }
775
+ // 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
764
776
  return saveResults
765
777
  }
766
778
  }
@@ -838,7 +850,7 @@ function findRepetitiveStrings(value, packedValues) {
838
850
  case 'function': console.log(value)
839
851
  }
840
852
  }
841
-
853
+ const isLittleEndianMachine = new Uint8Array(new Uint16Array([1]).buffer)[0] == 1
842
854
  extensionClasses = [ Date, Set, Error, RegExp, Tag, ArrayBuffer, ByteArray,
843
855
  Uint8Array, Uint8ClampedArray, Uint16Array, Uint32Array,
844
856
  typeof BigUint64Array == 'undefined' ? function() {} : BigUint64Array, Int8Array, Int16Array, Int32Array,
@@ -893,17 +905,17 @@ extensions = [{
893
905
  encode(arrayBuffer, encode, makeRoom) {
894
906
  writeBuffer(arrayBuffer, makeRoom)
895
907
  }
896
- }, typedArrayEncoder(64),
897
- typedArrayEncoder(68),
898
- typedArrayEncoder(69),
899
- typedArrayEncoder(70),
900
- typedArrayEncoder(71),
901
- typedArrayEncoder(72),
902
- typedArrayEncoder(77),
903
- typedArrayEncoder(78),
904
- typedArrayEncoder(79),
905
- typedArrayEncoder(81),
906
- typedArrayEncoder(82),
908
+ }, typedArrayEncoder(64, 1),
909
+ typedArrayEncoder(68, 1),
910
+ typedArrayEncoder(69, 2),
911
+ typedArrayEncoder(70, 4),
912
+ typedArrayEncoder(71, 8),
913
+ typedArrayEncoder(72, 1),
914
+ typedArrayEncoder(77, 2),
915
+ typedArrayEncoder(78, 4),
916
+ typedArrayEncoder(79, 8),
917
+ typedArrayEncoder(85, 4),
918
+ typedArrayEncoder(86, 8),
907
919
  {
908
920
  encode(sharedData, encode) { // write SharedData
909
921
  let packedValues = sharedData.packedValues || []
@@ -932,8 +944,9 @@ extensions = [{
932
944
  encode(new Tag(sharedData.version, 0x53687264))
933
945
  }
934
946
  }]
935
-
936
- function typedArrayEncoder(tag) {
947
+ function typedArrayEncoder(tag, size) {
948
+ if (!isLittleEndianMachine && size > 1)
949
+ tag -= 4 // the big endian equivalents are 4 less
937
950
  return {
938
951
  tag: tag,
939
952
  encode: function writeExtBuffer(typedArray, encode) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cbor-x",
3
3
  "author": "Kris Zyp",
4
- "version": "1.0.0",
4
+ "version": "1.2.1",
5
5
  "description": "Ultra-fast and conformant CBOR (RFC 8949) implementation with support for numerous tag extensions including records and structured cloning",
6
6
  "license": "MIT",
7
7
  "types": "./index.d.ts",