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.
- package/LICENSE +29 -0
- package/README.md +2 -0
- package/package.json +29 -0
- package/serialize.js +645 -0
- package/serialize.js.bak +199 -0
- package/serialize2.js +645 -0
- package/test.js +168 -0
package/serialize.js.bak
ADDED
|
@@ -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 })
|