@@ -10,14 +10,9 @@ function parse (text, reviver, options) {
10
10
if ( reviver !== null && typeof reviver === 'object' ) {
11
11
options = reviver
12
12
reviver = undefined
13
- } else {
14
- options = { }
15
13
}
16
14
}
17
15
18
- const protoAction = options . protoAction || 'error'
19
- const constructorAction = options . constructorAction || 'error'
20
-
21
16
if ( hasBuffer && Buffer . isBuffer ( text ) ) {
22
17
text = text . toString ( )
23
18
}
@@ -30,13 +25,16 @@ function parse (text, reviver, options) {
30
25
// Parse normally, allowing exceptions
31
26
const obj = JSON . parse ( text , reviver )
32
27
33
- // options: 'error' (default) / 'remove' / 'ignore'
34
- if ( protoAction === 'ignore' && constructorAction === 'ignore ') {
28
+ // Ignore null and non-objects
29
+ if ( obj === null || typeof obj !== 'object ') {
35
30
return obj
36
31
}
37
32
38
- // Ignore null and non-objects
39
- if ( obj === null || typeof obj !== 'object' ) {
33
+ const protoAction = ( options && options . protoAction ) || 'error'
34
+ const constructorAction = ( options && options . constructorAction ) || 'error'
35
+
36
+ // options: 'error' (default) / 'remove' / 'ignore'
37
+ if ( protoAction === 'ignore' && constructorAction === 'ignore' ) {
40
38
return obj
41
39
}
42
40
@@ -55,12 +53,10 @@ function parse (text, reviver, options) {
55
53
}
56
54
57
55
// Scan result for proto keys
58
- scan ( obj , { protoAction, constructorAction } )
59
-
60
- return obj
56
+ return filter ( obj , { protoAction, constructorAction, safe : options && options . safe } )
61
57
}
62
58
63
- function scan ( obj , { protoAction = 'error' , constructorAction = 'error' } = { } ) {
59
+ function filter ( obj , { protoAction = 'error' , constructorAction = 'error' , safe } = { } ) {
64
60
let next = [ obj ]
65
61
66
62
while ( next . length ) {
@@ -69,7 +65,9 @@ function scan (obj, { protoAction = 'error', constructorAction = 'error' } = {})
69
65
70
66
for ( const node of nodes ) {
71
67
if ( protoAction !== 'ignore' && Object . prototype . hasOwnProperty . call ( node , '__proto__' ) ) { // Avoid calling node.hasOwnProperty directly
72
- if ( protoAction === 'error' ) {
68
+ if ( safe === true ) {
69
+ return null
70
+ } else if ( protoAction === 'error' ) {
73
71
throw new SyntaxError ( 'Object contains forbidden prototype property' )
74
72
}
75
73
@@ -79,7 +77,9 @@ function scan (obj, { protoAction = 'error', constructorAction = 'error' } = {})
79
77
if ( constructorAction !== 'ignore' &&
80
78
Object . prototype . hasOwnProperty . call ( node , 'constructor' ) &&
81
79
Object . prototype . hasOwnProperty . call ( node . constructor , 'prototype' ) ) { // Avoid calling node.hasOwnProperty directly
82
- if ( constructorAction === 'error' ) {
80
+ if ( safe === true ) {
81
+ return null
82
+ } else if ( constructorAction === 'error' ) {
83
83
throw new SyntaxError ( 'Object contains forbidden prototype property' )
84
84
}
85
85
@@ -89,23 +89,24 @@ function scan (obj, { protoAction = 'error', constructorAction = 'error' } = {})
89
89
for ( const key in node ) {
90
90
const value = node [ key ]
91
91
if ( value && typeof value === 'object' ) {
92
- next . push ( node [ key ] )
92
+ next . push ( value )
93
93
}
94
94
}
95
95
}
96
96
}
97
+ return obj
97
98
}
98
99
99
100
function safeParse ( text , reviver ) {
100
101
try {
101
- return parse ( text , reviver )
102
+ return parse ( text , reviver , { safe : true } )
102
103
} catch ( ignoreError ) {
103
104
return null
104
105
}
105
106
}
106
107
107
108
module . exports = {
108
109
parse,
109
- scan,
110
+ scan : filter ,
110
111
safeParse
111
112
}
0 commit comments