@@ -5,7 +5,8 @@ import parameters from './lib/parameters.js';
5
5
import properties from './lib/properties.js' ;
6
6
import ContextTree from './lib/context-tree.js' ;
7
7
8
- const HARD_LIMIT = 100 ;
8
+ const PLUGIN_DISPATCH_LIMIT = 100 ;
9
+ const TRAVERSE_LIMIT = 1000 ;
9
10
const noop = ( ) => { } ;
10
11
11
12
class SpecMap {
@@ -39,6 +40,7 @@ class SpecMap {
39
40
getInstance : ( ) => this ,
40
41
} ) ,
41
42
allowMetaPatches : false ,
43
+ currentTraverseCount : 0 ,
42
44
} ,
43
45
opts
44
46
) ;
@@ -70,6 +72,7 @@ class SpecMap {
70
72
71
73
wrapPlugin ( plugin , name ) {
72
74
const { pathDiscriminator } = this ;
75
+ const that = this ;
73
76
let ctx = null ;
74
77
let fn ;
75
78
@@ -105,10 +108,15 @@ class SpecMap {
105
108
106
109
// eslint-disable-next-line no-restricted-syntax
107
110
for ( const patch of patches . filter ( lib . isAdditiveMutation ) ) {
108
- yield * traverse ( patch . value , patch . path , patch ) ;
111
+ if ( that . currentTraverseCount < TRAVERSE_LIMIT ) {
112
+ yield * traverse ( patch . value , patch . path , patch ) ;
113
+ } else {
114
+ return ;
115
+ }
109
116
}
110
117
111
118
function * traverse ( obj , path , patch ) {
119
+ that . currentTraverseCount += 1 ;
112
120
if ( ! lib . isObject ( obj ) ) {
113
121
if ( pluginObj . key === path [ path . length - 1 ] ) {
114
122
yield pluginObj . plugin ( obj , pluginObj . key , path , specmap ) ;
@@ -134,7 +142,11 @@ class SpecMap {
134
142
if ( specmap . allowMetaPatches && objRef ) {
135
143
refCache [ objRef ] = true ;
136
144
}
137
- yield * traverse ( val , updatedPath , patch ) ;
145
+ if ( that . currentTraverseCount < TRAVERSE_LIMIT ) {
146
+ yield * traverse ( val , updatedPath , patch ) ;
147
+ } else {
148
+ return ;
149
+ }
138
150
}
139
151
}
140
152
@@ -313,6 +325,8 @@ class SpecMap {
313
325
const that = this ;
314
326
const plugin = this . nextPlugin ( ) ;
315
327
328
+ that . currentTraverseCount = 0 ;
329
+
316
330
if ( ! plugin ) {
317
331
const nextPromise = this . nextPromisedPatch ( ) ;
318
332
if ( nextPromise ) {
@@ -328,13 +342,13 @@ class SpecMap {
328
342
}
329
343
330
344
// Makes sure plugin isn't running an endless loop
331
- that . pluginCount = that . pluginCount || { } ;
332
- that . pluginCount [ plugin ] = ( that . pluginCount [ plugin ] || 0 ) + 1 ;
333
- if ( that . pluginCount [ plugin ] > HARD_LIMIT ) {
345
+ that . pluginCount = that . pluginCount || new WeakMap ( ) ;
346
+ that . pluginCount . set ( plugin , ( that . pluginCount . get ( plugin ) || 0 ) + 1 ) ;
347
+ if ( that . pluginCount [ plugin ] > PLUGIN_DISPATCH_LIMIT ) {
334
348
return Promise . resolve ( {
335
349
spec : that . state ,
336
350
errors : that . errors . concat (
337
- new Error ( `We've reached a hard limit of ${ HARD_LIMIT } plugin runs` )
351
+ new Error ( `We've reached a hard limit of ${ PLUGIN_DISPATCH_LIMIT } plugin runs` )
338
352
) ,
339
353
} ) ;
340
354
}
0 commit comments