ig-serialize 1.0.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.
@@ -0,0 +1,199 @@
1
+ /**********************************************************************
2
+ *
3
+ * XXX the structure of this will change!!
4
+ *
5
+ * XXX merge serialize(..) and stringify(..) -> pre-parse theinput string
6
+ * in deserialize(..) to replace undefined, NaN and <empty> with
7
+ * appropriate placeholders...
8
+ * There should be two formats:
9
+ * - pretty
10
+ * - fast -- w/o pre-processing...
11
+ * XXX should this be part of types.js???
12
+ * ...extend JSON or a separate object? (leaning towards the later)
13
+ *
14
+ **********************************************************************/
15
+ ((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define)
16
+ (function(require){ var module={} // make module AMD/node compatible...
17
+ /*********************************************************************/
18
+
19
+
20
+
21
+
22
+ /*********************************************************************/
23
+
24
+ //
25
+ // This extends JSON.stringify(..) adding suppoort for:
26
+ // - empty
27
+ // - NaN
28
+ // - undefined
29
+ //
30
+ var EMPTY = '<< EMPTY >>'
31
+ var UNDEFINED = '<< UNDEFINED >>'
32
+ var NAN = '<< NAN >>'
33
+ var INFINITY = '<< INFINITY >>'
34
+ var NEG_INFINITY = '<< NEG_INFINITY >>'
35
+
36
+ var FUNCTION = '<< FUNCTION >>'
37
+ var FUNC_SEP = '\n---\n'
38
+ var FUNCTION_PLACEHOLDER = '<< FUNCTION PLACEHOLDER >>'
39
+
40
+
41
+ // XXX unify the output format... (???)
42
+ // XXX handle formatting -- pass to JSON.stringify(..)...
43
+ // XXX this does not support functions...
44
+ var serialize =
45
+ module.serialize =
46
+ function(value, raw=true){
47
+ var replacer = function(k, v){
48
+ // undefined...
49
+ if(v === undefined){
50
+ return UNDEFINED
51
+ // Infinity...
52
+ } else if(typeof(v) == 'number'
53
+ && v === Infinity){
54
+ return INFINITY
55
+ // -Infinity...
56
+ } else if(typeof(v) == 'number'
57
+ && v === -Infinity){
58
+ return NEG_INFINITY
59
+ // NaN...
60
+ } else if(typeof(v) == 'number'
61
+ && isNaN(v)){
62
+ return NAN
63
+ // <empty>...
64
+ } else if(v instanceof Array){
65
+ copy = [...v]
66
+ for(var i=0; i < v.length; i++){
67
+ if(! (i in v)){
68
+ copy[i] = EMPTY } }
69
+ v = copy
70
+ // function...
71
+ } else if(typeof(v) == 'function'){
72
+ if(raw instanceof Array){
73
+ raw.push(v)
74
+ return FUNCTION_PLACEHOLDER }
75
+ return raw ?
76
+ FUNCTION
77
+ + '\n'
78
+ + v.toString()
79
+ + FUNC_SEP
80
+ + serialize(
81
+ Object.fromEntries(
82
+ Object.entries(v)),
83
+ raw)
84
+ : v.name != '' ?
85
+ FUNCTION
86
+ + v.name
87
+ + FUNCTION
88
+ : FUNCTION
89
+ + v.toString()
90
+ + FUNCTION }
91
+ return v }
92
+
93
+ return raw ?
94
+ JSON.stringify(value, replacer)
95
+ : JSON.stringify(value, replacer)
96
+ // cleanup placeholders...
97
+ .replace(new RegExp('"'+ FUNCTION +'(.*)'+ FUNCTION +'"', 'g'), '$1')
98
+ .replace(new RegExp('"'+ EMPTY +'"', 'g'), '<empty>')
99
+ .replace(new RegExp('"'+ EMPTY +'"', 'g'), '<empty>')
100
+ .replace(new RegExp('"'+ UNDEFINED +'"', 'g'), 'undefined')
101
+ .replace(new RegExp('"'+ INFINITY +'"', 'g'), 'Infinity')
102
+ .replace(new RegExp('"'+ NEG_INFINITY +'"', 'g'), '-Infinity')
103
+ .replace(new RegExp('"'+ NAN +'"', 'g'), 'NaN') }
104
+
105
+
106
+ var stringify =
107
+ module.stringify =
108
+ function(value){
109
+ return serialize(value, false) }
110
+
111
+
112
+ // XXX this should pre-parse te string -- need to handle strings correctly...
113
+ var deserialize =
114
+ module.deserialize =
115
+ function(str, funcs){
116
+ var PLACEHOLDER = {}
117
+ var parseFunction = function(code){
118
+ var [code, attrs] = code.split(FUNC_SEP)
119
+ // XXX this is not safe...
120
+ // ...need to parse function code into args and code...
121
+ var func = Function('return '+ code)()
122
+ attrs.trim() != '{}'
123
+ && Object.assign(func, deserialize(attrs))
124
+ return func }
125
+ var reviver = function(key, value, context){
126
+ if(value == UNDEFINED){
127
+ return PLACEHOLDER }
128
+ return typeof(value) == 'string'
129
+ && value.startsWith(FUNCTION) ?
130
+ parseFunction(value
131
+ .slice(FUNCTION.length)
132
+ .trim())
133
+ : (value == FUNCTION_PLACEHOLDER
134
+ && funcs) ?
135
+ funcs.shift()
136
+ : value == INFINITY ?
137
+ Infinity
138
+ : value == NEG_INFINITY ?
139
+ -Infinity
140
+ : value == NAN ?
141
+ NaN
142
+ : value === EMPTY ?
143
+ undefined
144
+ : value }
145
+ // NOTE: this is needed as we returning undefined from reviver(..)
146
+ // will leave the value empty.
147
+ var cleanup = function(obj){
148
+ if(typeof(obj) == 'object'){
149
+ for(var key in obj){
150
+ if(obj[key] === PLACEHOLDER){
151
+ obj[key] = undefined
152
+ } else {
153
+ cleanup(obj[key]) } } }
154
+ return obj }
155
+
156
+ var res = JSON.parse(str, reviver)
157
+
158
+ return cleanup(res) }
159
+
160
+
161
+
162
+ //---------------------------------------------------------------------
163
+ // copying/colning...
164
+
165
+ // Deep copy an object tree...
166
+ //
167
+ // This is similar to JSON.parse(JSON.stringify(..)) but uses deserialize
168
+ // and serialize.
169
+ //
170
+ // NOTE: this will try and reconstruct functions from the input tree,
171
+ // this will work fine for simple functions but more complex cases
172
+ // may yield unexpected results -- this is not done to full depth,
173
+ // as we only handle:
174
+ // - function code (as returned by .toString())
175
+ // - attributes set on the function directly
176
+ // if a function has a custom .__proto__ and/or data in its
177
+ // inheritance tree, such data is ignored.
178
+ var deepCopy =
179
+ module.deepCopy =
180
+ function(obj){
181
+ return deserialize(
182
+ serialize(obj)) }
183
+
184
+
185
+ // This is the same as semiDeepCopy(..) but instead of recreating
186
+ // functions, it will simply rereference them from the input...
187
+ var semiDeepCopy =
188
+ module.semiDeepCopy =
189
+ function(obj){
190
+ var funcs = []
191
+ return deserialize(
192
+ serialize(obji, funcs),
193
+ funcs) }
194
+
195
+
196
+
197
+
198
+ /**********************************************************************
199
+ * vim:set ts=4 sw=4 : */ return module })