@@ -10,14 +10,9 @@ function parse (text, reviver, options) {
1010 if ( reviver !== null && typeof reviver === 'object' ) {
1111 options = reviver
1212 reviver = undefined
13- } else {
14- options = { }
1513 }
1614 }
1715
18- const protoAction = options . protoAction || 'error'
19- const constructorAction = options . constructorAction || 'error'
20-
2116 if ( hasBuffer && Buffer . isBuffer ( text ) ) {
2217 text = text . toString ( )
2318 }
@@ -30,13 +25,16 @@ function parse (text, reviver, options) {
3025 // Parse normally, allowing exceptions
3126 const obj = JSON . parse ( text , reviver )
3227
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 ') {
3530 return obj
3631 }
3732
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' ) {
4038 return obj
4139 }
4240
@@ -55,12 +53,10 @@ function parse (text, reviver, options) {
5553 }
5654
5755 // Scan result for proto keys
58- scan ( obj , { protoAction, constructorAction } )
59-
60- return obj
56+ return filter ( obj , { protoAction, constructorAction, safe : options && options . safe } )
6157}
6258
63- function scan ( obj , { protoAction = 'error' , constructorAction = 'error' } = { } ) {
59+ function filter ( obj , { protoAction = 'error' , constructorAction = 'error' , safe } = { } ) {
6460 let next = [ obj ]
6561
6662 while ( next . length ) {
@@ -69,7 +65,9 @@ function scan (obj, { protoAction = 'error', constructorAction = 'error' } = {})
6965
7066 for ( const node of nodes ) {
7167 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' ) {
7371 throw new SyntaxError ( 'Object contains forbidden prototype property' )
7472 }
7573
@@ -79,7 +77,9 @@ function scan (obj, { protoAction = 'error', constructorAction = 'error' } = {})
7977 if ( constructorAction !== 'ignore' &&
8078 Object . prototype . hasOwnProperty . call ( node , 'constructor' ) &&
8179 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' ) {
8383 throw new SyntaxError ( 'Object contains forbidden prototype property' )
8484 }
8585
@@ -89,23 +89,24 @@ function scan (obj, { protoAction = 'error', constructorAction = 'error' } = {})
8989 for ( const key in node ) {
9090 const value = node [ key ]
9191 if ( value && typeof value === 'object' ) {
92- next . push ( node [ key ] )
92+ next . push ( value )
9393 }
9494 }
9595 }
9696 }
97+ return obj
9798}
9899
99100function safeParse ( text , reviver ) {
100101 try {
101- return parse ( text , reviver )
102+ return parse ( text , reviver , { safe : true } )
102103 } catch ( ignoreError ) {
103104 return null
104105 }
105106}
106107
107108module . exports = {
108109 parse,
109- scan,
110+ scan : filter ,
110111 safeParse
111112}
0 commit comments