4
4
5
5
"use strict" ;
6
6
7
+ const ErrorObjectSerializer = require ( "./ErrorObjectSerializer" ) ;
7
8
const MapObjectSerializer = require ( "./MapObjectSerializer" ) ;
8
9
const PlainObjectSerializer = require ( "./PlainObjectSerializer" ) ;
9
10
const RegExpObjectSerializer = require ( "./RegExpObjectSerializer" ) ;
@@ -57,6 +58,7 @@ const ESCAPE_UNDEFINED = false;
57
58
58
59
const CURRENT_VERSION = 1 ;
59
60
61
+ const errorObjectSerializer = new ErrorObjectSerializer ( ) ;
60
62
const plainObjectSerializer = new PlainObjectSerializer ( ) ;
61
63
const mapObjectSerializer = new MapObjectSerializer ( ) ;
62
64
const setObjectSerializer = new SetObjectSerializer ( ) ;
@@ -74,26 +76,37 @@ serializers.set(Object, {
74
76
name : null ,
75
77
serializer : plainObjectSerializer
76
78
} ) ;
79
+
77
80
serializers . set ( Array , {
78
81
request : "" ,
79
82
name : null ,
80
83
serializer : plainObjectSerializer
81
84
} ) ;
85
+
82
86
serializers . set ( Map , {
83
87
request : "" ,
84
88
name : 1 ,
85
89
serializer : mapObjectSerializer
86
90
} ) ;
91
+
87
92
serializers . set ( Set , {
88
93
request : "" ,
89
94
name : 2 ,
90
95
serializer : setObjectSerializer
91
96
} ) ;
97
+
92
98
serializers . set ( RegExp , {
93
99
request : "" ,
94
100
name : 3 ,
95
101
serializer : regExpObjectSerializer
96
102
} ) ;
103
+
104
+ serializers . set ( Error , {
105
+ request : "" ,
106
+ name : 4 ,
107
+ serializer : errorObjectSerializer
108
+ } ) ;
109
+
97
110
for ( const { request, name, serializer } of serializers . values ( ) ) {
98
111
serializerInversed . set ( `${ request } /${ name } ` , serializer ) ;
99
112
}
@@ -108,23 +121,27 @@ class ObjectMiddleware extends SerializerMiddleware {
108
121
*/
109
122
static register ( Constructor , request , name , serializer ) {
110
123
const key = request + "/" + name ;
124
+
111
125
if ( serializers . has ( Constructor ) ) {
112
126
throw new Error (
113
127
`ObjectMiddleware.register: serializer for ${
114
128
Constructor . name
115
129
} is already registered`
116
130
) ;
117
131
}
132
+
118
133
if ( serializerInversed . has ( key ) ) {
119
134
throw new Error (
120
135
`ObjectMiddleware.register: serializer for ${ key } is already registered`
121
136
) ;
122
137
}
138
+
123
139
serializers . set ( Constructor , {
124
140
request,
125
141
name,
126
142
serializer
127
143
} ) ;
144
+
128
145
serializerInversed . set ( key , serializer ) ;
129
146
}
130
147
@@ -140,40 +157,49 @@ class ObjectMiddleware extends SerializerMiddleware {
140
157
} is already registered`
141
158
) ;
142
159
}
160
+
143
161
serializers . set ( Constructor , NOT_SERIALIZABLE ) ;
144
162
}
145
163
146
164
static getSerializerFor ( object ) {
147
165
const c = object . constructor ;
148
166
const config = serializers . get ( c ) ;
167
+
149
168
if ( ! config ) throw new Error ( `No serializer registered for ${ c . name } ` ) ;
150
169
if ( config === NOT_SERIALIZABLE ) throw NOT_SERIALIZABLE ;
170
+
151
171
return config ;
152
172
}
153
173
154
174
static getDeserializerFor ( request , name ) {
155
175
const key = request + "/" + name ;
156
176
const serializer = serializerInversed . get ( key ) ;
177
+
157
178
if ( serializer === undefined ) {
158
179
throw new Error ( `No deserializer registered for ${ key } ` ) ;
159
180
}
181
+
160
182
return serializer ;
161
183
}
162
184
163
185
_handleFunctionSerialization ( fn , context ) {
164
186
return ( ) => {
165
187
const r = fn ( ) ;
188
+
166
189
if ( r instanceof Promise )
167
190
return r . then ( data => this . serialize ( [ data ] , context ) ) ;
191
+
168
192
return this . serialize ( [ r ] , context ) ;
169
193
} ;
170
194
}
171
195
172
196
_handleFunctionDeserialization ( fn , context ) {
173
197
return ( ) => {
174
198
const r = fn ( ) ;
199
+
175
200
if ( r instanceof Promise )
176
201
return r . then ( data => this . deserialize ( data , context ) [ 0 ] ) ;
202
+
177
203
return this . deserialize ( r , context ) [ 0 ] ;
178
204
} ;
179
205
}
@@ -197,12 +223,16 @@ class ObjectMiddleware extends SerializerMiddleware {
197
223
const process = item => {
198
224
// check if we can emit a reference
199
225
const ref = referenceable . get ( item ) ;
226
+
200
227
if ( ref !== undefined ) {
201
228
result . push ( ESCAPE , ref - currentPos ) ;
229
+
202
230
return ;
203
231
}
232
+
204
233
if ( Buffer . isBuffer ( item ) ) {
205
234
addReferenceable ( item ) ;
235
+
206
236
result . push ( item ) ;
207
237
} else if ( typeof item === "object" && item !== null ) {
208
238
if ( cycleStack . has ( item ) ) {
@@ -213,32 +243,40 @@ class ObjectMiddleware extends SerializerMiddleware {
213
243
. join ( " -> " ) } )`
214
244
) ;
215
245
}
246
+
216
247
const { request, name, serializer } = ObjectMiddleware . getSerializerFor (
217
248
item
218
249
) ;
219
-
220
250
const key = `${ request } /${ name } ` ;
221
251
const lastIndex = objectTypeLookup . get ( key ) ;
252
+
222
253
if ( lastIndex === undefined ) {
223
254
objectTypeLookup . set ( key , currentPosTypeLookup ++ ) ;
255
+
224
256
result . push ( ESCAPE , request , name ) ;
225
257
} else {
226
258
result . push ( ESCAPE , currentPosTypeLookup - lastIndex ) ;
227
259
}
260
+
228
261
cycleStack . add ( item ) ;
262
+
229
263
serializer . serialize ( item , {
230
264
write ( value ) {
231
265
process ( value ) ;
232
266
}
233
267
} ) ;
268
+
234
269
cycleStack . delete ( item ) ;
270
+
235
271
result . push ( ESCAPE , ESCAPE_END_OBJECT ) ;
272
+
236
273
addReferenceable ( item ) ;
237
274
} else if ( typeof item === "string" ) {
238
275
if ( item !== "" ) {
239
276
// empty strings are shorter when not emitting a reference (this saves 1 byte per empty string)
240
277
addReferenceable ( item ) ;
241
278
}
279
+
242
280
result . push ( item ) ;
243
281
} else if ( item === ESCAPE ) {
244
282
result . push ( ESCAPE , ESCAPE_ESCAPE_VALUE ) ;
@@ -250,14 +288,17 @@ class ObjectMiddleware extends SerializerMiddleware {
250
288
result . push ( item ) ;
251
289
}
252
290
} ;
291
+
253
292
try {
254
293
for ( const item of data ) {
255
294
process ( item ) ;
256
295
}
257
296
} catch ( e ) {
258
297
if ( e === NOT_SERIALIZABLE ) return null ;
298
+
259
299
throw e ;
260
300
}
301
+
261
302
return result ;
262
303
}
263
304
@@ -271,10 +312,13 @@ class ObjectMiddleware extends SerializerMiddleware {
271
312
const read = ( ) => {
272
313
if ( currentDataPos >= data . length )
273
314
throw new Error ( "Unexpected end of stream" ) ;
315
+
274
316
return data [ currentDataPos ++ ] ;
275
317
} ;
318
+
276
319
if ( read ( ) !== CURRENT_VERSION )
277
320
throw new Error ( "Version missmatch, serializer changed" ) ;
321
+
278
322
let currentPos = 0 ;
279
323
const referenceable = new Map ( ) ;
280
324
const addReferenceable = item => {
@@ -285,8 +329,10 @@ class ObjectMiddleware extends SerializerMiddleware {
285
329
const result = [ ] ;
286
330
const decodeValue = ( ) => {
287
331
const item = read ( ) ;
332
+
288
333
if ( item === ESCAPE ) {
289
334
const nextItem = read ( ) ;
335
+
290
336
if ( nextItem === ESCAPE_ESCAPE_VALUE ) {
291
337
return ESCAPE ;
292
338
} else if ( nextItem === ESCAPE_UNDEFINED ) {
@@ -301,51 +347,66 @@ class ObjectMiddleware extends SerializerMiddleware {
301
347
} else {
302
348
const request = nextItem ;
303
349
let serializer ;
350
+
304
351
if ( typeof request === "number" ) {
305
352
serializer = objectTypeLookup . get ( currentPosTypeLookup - request ) ;
306
353
} else {
307
354
const name = read ( ) ;
355
+
308
356
if ( request && ! loadedRequests . has ( request ) ) {
309
357
require ( request ) ;
358
+
310
359
loadedRequests . add ( request ) ;
311
360
}
361
+
312
362
serializer = ObjectMiddleware . getDeserializerFor ( request , name ) ;
363
+
313
364
objectTypeLookup . set ( currentPosTypeLookup ++ , serializer ) ;
314
365
}
315
366
const item = serializer . deserialize ( {
316
367
read ( ) {
317
368
const item = decodeValue ( ) ;
369
+
318
370
return item ;
319
371
}
320
372
} ) ;
321
373
const end1 = read ( ) ;
374
+
322
375
if ( end1 !== ESCAPE ) {
323
376
throw new Error ( "Expected end of object" ) ;
324
377
}
378
+
325
379
const end2 = read ( ) ;
380
+
326
381
if ( end2 !== ESCAPE_END_OBJECT ) {
327
382
throw new Error ( "Expected end of object" ) ;
328
383
}
384
+
329
385
addReferenceable ( item ) ;
386
+
330
387
return item ;
331
388
}
332
389
} else if ( typeof item === "string" ) {
333
390
if ( item !== "" ) {
334
391
addReferenceable ( item ) ;
335
392
}
393
+
336
394
return item ;
337
395
} else if ( Buffer . isBuffer ( item ) ) {
338
396
addReferenceable ( item ) ;
397
+
339
398
return item ;
340
399
} else if ( typeof item === "function" ) {
341
400
return this . _handleFunctionDeserialization ( item , context ) ;
342
401
} else {
343
402
return item ;
344
403
}
345
404
} ;
405
+
346
406
while ( currentDataPos < data . length ) {
347
407
result . push ( decodeValue ( ) ) ;
348
408
}
409
+
349
410
return result ;
350
411
}
351
412
}
0 commit comments