ig-serialize 1.0.4 → 1.0.5

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 CHANGED
@@ -49,6 +49,33 @@ Thus, care must be taken when serializing structures containing function.
49
49
  ### `partialDeepCopy(..)`
50
50
 
51
51
 
52
+ ## Format
53
+
54
+ The output of `.serialize(..)` is a strict superset of [standard JSON](https://www.json.org/json-en.html),
55
+ while the input format is a bit more relaxed than in several details.
56
+
57
+ Extensions to JSON:
58
+ - Recursion
59
+ - undefined / NaN
60
+ - BigInt
61
+ - Map / Set
62
+ - Function
63
+
64
+ ### Structural paths
65
+
66
+ ### Recursion
67
+
68
+ ### null types
69
+
70
+ ### BigInt
71
+
72
+ ### Map / Set
73
+
74
+ ### Functions
75
+
76
+
77
+
78
+
52
79
 
53
80
 
54
81
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ig-serialize",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "experimental extended json serializaion...",
5
5
  "main": "serialize.js",
6
6
  "scripts": {
package/serialize.js CHANGED
@@ -1,5 +1,41 @@
1
1
  /**********************************************************************
2
2
  *
3
+ * TODO would be useful to split this into:
4
+ * - object traversal using object path
5
+ * Object.walk(..) -- a-la Python's walk(..)
6
+ * Object.graph(..)
7
+ * like .map(..) but deep and paths instead of indexes...
8
+ * - get/set object by path
9
+ * Object.get(..) / Object.set(..)
10
+ *
11
+ * XXX the current path implementation is fully complient to the task at
12
+ * hand but it will not suite the diff task as there is no way to know
13
+ * the meaning of the path element without seeing the object (map/set
14
+ * indexes)...
15
+ * a different path format would suit both tasks and make things more
16
+ * universal:
17
+ * Current:
18
+ * [1, 'a', 5, 0, 3]
19
+ * \ \ +-++ +---------------- Set index (from context)
20
+ * \ \ +------------------- Map index (from context)
21
+ * \ +------------------------ Object key (string)
22
+ * +--------------------------- Array index (from context)
23
+ * Proposed:
24
+ * [1, 'a', ['map', 5, 0], ['set', 3]]
25
+ * \ \ +---------+-+ +------+-+
26
+ * \ \ \ +--- Set index
27
+ * \ \ +-------------- Map index
28
+ * \ +--------------------------- Object key (string)
29
+ * +------------------------------ Array index (number)
30
+ * And/or:
31
+ * [1, ['object', 3], ['map', 5, 0], ['set', 3]]
32
+ * +---------+-+
33
+ * +----- Object attr index
34
+ * The questions is which to use as default for objects, the key or
35
+ * position?
36
+ * (XXX move this note to diff.jx)
37
+ *
38
+ * XXX do a revision of the JSON standard for things I could have forgotten...
3
39
  *
4
40
  *
5
41
  **********************************************************************/
@@ -41,7 +77,8 @@ var debug = {
41
77
 
42
78
  //---------------------------------------------------------------------
43
79
 
44
- module.STRING_LENGTH_REF = 64
80
+ module.STRING_LENGTH_REF = RECURSIVE.length * 8
81
+
45
82
 
46
83
  //
47
84
  // serialize(obj[, options])
@@ -101,7 +138,7 @@ module.STRING_LENGTH_REF = 64
101
138
  // ]
102
139
  //
103
140
  //
104
- // XXX BUG: using non-whitespace as indent breaks the depth of the first
141
+ // XXX BUG?: using non-whitespace as indent breaks the depth of the first
105
142
  // or last elements in sequences
106
143
  // ...breaks .trim*() in Map/Set/Object...
107
144
  var _serialize =
@@ -131,7 +168,8 @@ function(obj, path=[], seen=new Map(), indent, depth=0, options={}){
131
168
  return FUNCTION
132
169
  .replace('%', s.length +','+ s) }
133
170
 
134
- // special case: long strings...
171
+ // long strings...
172
+ // NOTE: this saves on output size...
135
173
  if(typeof(obj) == 'string'
136
174
  && obj.length > string_length_ref){
137
175
  seen.set(obj, path) }
@@ -230,7 +268,7 @@ module.eJSON = {
230
268
 
231
269
  0: 'number', 1: 'number', 2: 'number', 3: 'number', 4: 'number',
232
270
  5: 'number', 6: 'number', 7: 'number', 8: 'number', 9: 'number',
233
- '.': 'number', '-': 'number',
271
+ '.': 'number', '-': 'number', '+': 'number',
234
272
 
235
273
  '[': 'array',
236
274
  '{': 'object',
@@ -370,11 +408,33 @@ module.eJSON = {
370
408
  && str.slice(i, i+'-Infinity'.length) == '-Infinity'){
371
409
  return [-Infinity, i+'-Infinity'.length, line] }
372
410
  // numbers...
373
- var j = i+1
411
+ // XXX do we need to handle the odd case of 077 vs 088???
412
+ var j = i
413
+ var mode = 'dec'
414
+ if(str[j] == '0'
415
+ && 'xXbBoO'.includes(str[j+1])){
416
+ mode = str[j+1]
417
+ j++ }
418
+ j++
374
419
  while(j < str.length
375
420
  && (str[j] == '.'
421
+ // dec/oct/bin...
422
+ // XXX do we need to be pedantic and check the rest
423
+ // of the modes explicitly???
376
424
  || (str[j] >= '0'
377
- && str[j] <= '9'))){
425
+ && str[j] <= '9')
426
+ // hex...
427
+ || (mode == 'x'
428
+ && ((str[j] >= 'a'
429
+ && str[j] <= 'f')
430
+ || (str[j] >= 'A'
431
+ && str[j] <= 'F')))
432
+ // exponent...
433
+ || str[j] == 'e'
434
+ || str[j] == 'E')){
435
+ if('eE'.includes(str[j])
436
+ && '+-'.includes(str[j+1])){
437
+ j++ }
378
438
  j++ }
379
439
  // BigInt...
380
440
  if(str[j] == 'n'){
package/test.js CHANGED
@@ -45,6 +45,10 @@ var setups = test.Setups({
45
45
  return ['123', json] },
46
46
  'number-neg': function(assert){
47
47
  return ['-123', json] },
48
+ //'number-pos': function(assert){
49
+ // return ['+123', json] },
50
+ 'number-exp': function(assert){
51
+ return ['1e+100', json] },
48
52
  'number-zero': function(assert){
49
53
  return ['0', json] },
50
54
  'float-a': function(assert){
@@ -68,7 +72,8 @@ var setups = test.Setups({
68
72
  // XXX also test diffrerent quotations...
69
73
  string: function(assert){
70
74
  return ['"string"', json] },
71
- // XXX ERR this breaks...
75
+ 'string-empty': function(assert){
76
+ return ['""', json] },
72
77
  'string-multiline': function(assert){
73
78
  return ['"string\\nstring\\nstring"', json] },
74
79
 
@@ -106,7 +111,6 @@ var setups = test.Setups({
106
111
  return ['Map([[<RECURSIVE[]>,"value"]])'] },
107
112
  'map-recursive-value': function(assert){
108
113
  return ['Map([["key",<RECURSIVE[]>]])'] },
109
-
110
114
  })
111
115
 
112
116
  test.Modifiers({
@@ -170,7 +174,6 @@ test.Tests({
170
174
  // XXX
171
175
  },
172
176
 
173
- //* XXX ERR
174
177
  'partial-deep-copy': function(assert, [setup]){
175
178
  var obj = eJSON.deserialize(setup, true)
176
179
  var funcs = []
@@ -185,12 +188,13 @@ test.Tests({
185
188
  })
186
189
 
187
190
  test.Cases({
188
- /* XXX for some magical reason hese break as soon as we add [setup] to arguments...
189
- 'deep-copy-function': function(assert, [setup]){
190
- // XXX check function isolation...
191
- },
192
- //*/
193
-
191
+ //
192
+ // Format:
193
+ // [
194
+ // [ "<extended-syntax>", "<JSON-syntax>" ],
195
+ // ...
196
+ // ]
197
+ //
194
198
  // NOTE: these syntax variants are not output by .serialize(..) this it
195
199
  // is less critical to test them in the main loop.
196
200
  // XXX though it would be nice to do so...
@@ -198,10 +202,13 @@ test.Cases({
198
202
  // numbers/floats...
199
203
  ['.123', '0.123'],
200
204
  ['123.', '123'],
205
+ ['+123', '123'],
206
+ ['123e100', '123e+100'],
207
+ ['0xff', '255'],
201
208
 
202
209
  // string quotes...
203
- ['"abc"', "'abc'"],
204
- ['"abc"', '`abc`'],
210
+ ["'abc'", '"abc"'],
211
+ ['`abc`', '"abc"'],
205
212
 
206
213
  // arrays...
207
214
  ['[1,2,]', '[1,2]'],
@@ -218,12 +225,46 @@ test.Cases({
218
225
  `"${ a }" and "${ b }" should deserialize to the samve value.`,
219
226
  'got:', aa, 'and', bb, 'resp.') } },
220
227
 
228
+ _make_object_with_methods: function(){
229
+ var in_closure = 123
230
+ return {
231
+ stateful: function(){
232
+ return typeof(in_closure) != 'undefined' ?
233
+ 'state_retained'
234
+ : 'state_lost' },
235
+ stateless: function(){
236
+ return 'stateless' },
237
+ } },
221
238
  'deep-copy-function': function(assert){
222
- // XXX check function isolation...
223
- },
239
+ var obj = this._make_object_with_methods()
240
+ var obj_copy = eJSON.deepCopy(obj, true)
241
+
242
+ // sanity checks...
243
+ assert(obj.stateless() == 'stateless')
244
+ assert(obj.stateful() == 'state_retained')
245
+ assert(obj_copy.stateless() == 'stateless')
246
+
247
+ // context should be lost...
248
+ assert(
249
+ obj_copy.stateful() == 'state_lost',
250
+ 'Function closure not lost.')
251
+ assert(obj.stateful !== obj_copy.stateful,
252
+ 'Function objects retained.') },
224
253
  'partial-deep-copy-function': function(assert){
225
- // XXX check function isolation...
226
- },
254
+ var obj = this._make_object_with_methods()
255
+ var obj_copy = eJSON.partialDeepCopy(obj)
256
+
257
+ // sanity checks...
258
+ assert(obj.stateless() == 'stateless')
259
+ assert(obj.stateful() == 'state_retained')
260
+ assert(obj_copy.stateless() == 'stateless')
261
+
262
+ // context should be retained...
263
+ assert(
264
+ obj_copy.stateful() == 'state_retained',
265
+ 'Function closure lost.')
266
+ assert(obj.stateful === obj_copy.stateful,
267
+ 'Function objects not retained.') },
227
268
  })
228
269
 
229
270