@@ -6,11 +6,13 @@ See the accompanying LICENSE file for terms.
6
6
7
7
'use strict' ;
8
8
9
- var isRegExp = require ( 'util' ) . isRegExp ;
9
+ var isRegExp = require ( 'util' ) . isRegExp ;
10
+ var randomBytes = require ( 'randombytes' ) ;
10
11
11
12
// Generate an internal UID to make the regexp pattern harder to guess.
12
- var UID = Math . floor ( Math . random ( ) * 0x10000000000 ) . toString ( 16 ) ;
13
- var PLACE_HOLDER_REGEXP = new RegExp ( '(\\\\)?"@__(F|R)-' + UID + '-(\\d+)__@"' , 'g' ) ;
13
+ var UID_LENGTH = 16 ;
14
+ var UID = generateUID ( ) ;
15
+ var PLACE_HOLDER_REGEXP = buildPlaceHolderRegExp ( UID ) ;
14
16
15
17
var IS_NATIVE_CODE_REGEXP = / \{ \s * \[ n a t i v e c o d e \] \s * \} / g;
16
18
var UNSAFE_CHARS_REGEXP = / [ < > \/ \u2028 \u2029 ] / g;
@@ -29,6 +31,19 @@ function escapeUnsafeChars(unsafeChar) {
29
31
return ESCAPED_CHARS [ unsafeChar ] ;
30
32
}
31
33
34
+ function generateUID ( ) {
35
+ var bytes = randomBytes ( UID_LENGTH ) ;
36
+ var result = '' ;
37
+ for ( var i = 0 ; i < UID_LENGTH ; ++ i ) {
38
+ result += bytes [ i ] . toString ( 16 ) ;
39
+ }
40
+ return result ;
41
+ }
42
+
43
+ function buildPlaceHolderRegExp ( uid ) {
44
+ return new RegExp ( '(\\\\)?"@__(F|R)-' + uid + '-(\\d+)__@"' , 'g' ) ;
45
+ }
46
+
32
47
module . exports = function serialize ( obj , options ) {
33
48
options || ( options = { } ) ;
34
49
@@ -37,6 +52,7 @@ module.exports = function serialize(obj, options) {
37
52
options = { space : options } ;
38
53
}
39
54
55
+ var uid = options . uid || UID ;
40
56
var functions = [ ] ;
41
57
var regexps = [ ] ;
42
58
@@ -51,14 +67,14 @@ module.exports = function serialize(obj, options) {
51
67
52
68
if ( type === 'object' ) {
53
69
if ( isRegExp ( value ) ) {
54
- return '@__R-' + UID + '-' + ( regexps . push ( value ) - 1 ) + '__@' ;
70
+ return '@__R-' + uid + '-' + ( regexps . push ( value ) - 1 ) + '__@' ;
55
71
}
56
72
57
73
return value ;
58
74
}
59
75
60
76
if ( type === 'function' ) {
61
- return '@__F-' + UID + '-' + ( functions . push ( value ) - 1 ) + '__@' ;
77
+ return '@__F-' + uid + '-' + ( functions . push ( value ) - 1 ) + '__@' ;
62
78
}
63
79
64
80
return value ;
@@ -89,10 +105,20 @@ module.exports = function serialize(obj, options) {
89
105
return str ;
90
106
}
91
107
108
+ var placeHolderRegExp ;
109
+ if ( options . uid ) {
110
+ placeHolderRegExp = buildPlaceHolderRegExp ( uid ) ;
111
+ } else {
112
+ placeHolderRegExp = PLACE_HOLDER_REGEXP ;
113
+ }
114
+
92
115
// Replaces all occurrences of function and regexp placeholders in the JSON
93
116
// string with their string representations. If the original value can not
94
117
// be found, then `undefined` is used.
95
- return str . replace ( PLACE_HOLDER_REGEXP , function ( match , backSlash , type , valueIndex ) {
118
+ return str . replace ( placeHolderRegExp , function ( match , backSlash , type , valueIndex ) {
119
+ // The placeholder may not be preceded by a backslash. This is to prevent
120
+ // replacing things like `"a\"@__R-<UID>-0__@"` and thus outputting
121
+ // invalid JS.
96
122
if ( backSlash ) {
97
123
return match ;
98
124
}
0 commit comments