Expand file tree Collapse file tree 1 file changed +15
-0
lines changed Original file line number Diff line number Diff line change @@ -1205,6 +1205,21 @@ Spark.createLandmark = function (options, htmlFunc) {
1205
1205
1206
1206
landmark . _range = range ;
1207
1207
renderer . landmarkRanges . push ( range ) ;
1208
+ // Help GC avoid an actual memory leak (#1157) by nulling the
1209
+ // `renderer` local variable, which holds data structures about
1210
+ // the preservation and patching performed during this rendering
1211
+ // pass, including references to the old LiveRanges. If
1212
+ // `renderer` is retained by the LiveRange we initialize here,
1213
+ // it creates a chain linking the new LiveRanges to the
1214
+ // renderer, to the old LiveRanges, to the old renderer, etc.
1215
+ //
1216
+ // The reason the new LiveRange might retains `renderer` has to
1217
+ // do with how V8 implements closures. V8 considers
1218
+ // `range.finalize` to close over `renderer`, even though it
1219
+ // doesn't use it. Because `renderer` is used by *some* nested
1220
+ // closure, it apparently is retained by all nested closures as
1221
+ // part of `Spark.createLandmark`'s function context.
1222
+ renderer = null ;
1208
1223
} ) ;
1209
1224
} ;
1210
1225
0 commit comments