@@ -138,7 +138,7 @@ import VAggregatorCell from './VAggregatorCell.vue'
138138import VDragAndDropCell from ' ./VDragAndDropCell.vue'
139139import VPivottable from ' ../pivottable/VPivottable.vue'
140140import TableRenderer from ' ../pivottable/renderer'
141- import { computed , watch , shallowRef , watchEffect , onUnmounted } from ' vue'
141+ import { computed , watch } from ' vue'
142142import {
143143 usePropsState ,
144144 useMaterializeInput ,
@@ -329,183 +329,9 @@ const unusedAttrs = computed(() => {
329329 .sort (sortAs (pivotUiState .unusedOrder ))
330330})
331331
332- // Use computed with proper memoization to prevent unnecessary PivotData recreations
333- // Include data reference to detect actual data changes, not just length
334- const pivotDataKey = computed (() =>
335- JSON .stringify ({
336- dataReference: state .data , // Include actual data reference to detect changes
337- rows: state .rows ,
338- cols: state .cols ,
339- vals: state .vals ,
340- aggregatorName: state .aggregatorName ,
341- valueFilter: state .valueFilter ,
342- rowOrder: state .rowOrder ,
343- colOrder: state .colOrder
344- })
345- )
346-
347- // Keep track of current PivotData instance
348- const pivotData = shallowRef <PivotData | null >(null )
349- let lastPivotDataKey = ' '
350-
351- // Only create new PivotData when structure actually changes
352- watchEffect (() => {
353- const currentKey = pivotDataKey .value
354-
355- // Only recreate if key has changed
356- if (currentKey !== lastPivotDataKey ) {
357- // Properly clean up old instance with enhanced cleanup
358- const oldPivotData = pivotData .value
359- if (oldPivotData ) {
360- // Deep cleanup to break all aggregator closures
361- if (oldPivotData .tree ) {
362- for (const rowKey in oldPivotData .tree ) {
363- for (const colKey in oldPivotData .tree [rowKey ]) {
364- const agg = oldPivotData .tree [rowKey ][colKey ]
365- if (agg && typeof agg === ' object' ) {
366- // Break closure references completely
367- Object .keys (agg ).forEach (key => {
368- if (typeof agg [key ] === ' function' ) {
369- agg [key ] = null // Break function closures
370- } else if (typeof agg [key ] === ' object' && agg [key ] !== null ) {
371- agg [key ] = null // Break object references
372- } else {
373- delete agg [key ] // Delete primitive values
374- }
375- })
376- }
377- }
378- delete oldPivotData .tree [rowKey ]
379- }
380- }
381-
382- // Clean up aggregator function references
383- if (oldPivotData .aggregator ) oldPivotData .aggregator = null
384-
385- // Clean up row/col totals aggregators
386- Object .keys (oldPivotData .rowTotals ).forEach (key => {
387- const agg = oldPivotData .rowTotals [key ]
388- if (agg && typeof agg === ' object' ) {
389- Object .keys (agg ).forEach (prop => {
390- if (typeof agg [prop ] === ' function' || (typeof agg [prop ] === ' object' && agg [prop ] !== null )) {
391- agg [prop ] = null
392- }
393- })
394- }
395- delete oldPivotData .rowTotals [key ]
396- })
397-
398- Object .keys (oldPivotData .colTotals ).forEach (key => {
399- const agg = oldPivotData .colTotals [key ]
400- if (agg && typeof agg === ' object' ) {
401- Object .keys (agg ).forEach (prop => {
402- if (typeof agg [prop ] === ' function' || (typeof agg [prop ] === ' object' && agg [prop ] !== null )) {
403- agg [prop ] = null
404- }
405- })
406- }
407- delete oldPivotData .colTotals [key ]
408- })
409-
410- // Clean up allTotal aggregator
411- if (oldPivotData .allTotal && typeof oldPivotData .allTotal === ' object' ) {
412- Object .keys (oldPivotData .allTotal ).forEach (prop => {
413- if (typeof oldPivotData .allTotal [prop ] === ' function' || (typeof oldPivotData .allTotal [prop ] === ' object' && oldPivotData .allTotal [prop ] !== null )) {
414- oldPivotData .allTotal [prop ] = null
415- }
416- })
417- }
418- oldPivotData .allTotal = null
419-
420- // Clear all remaining properties
421- oldPivotData .tree = {}
422- oldPivotData .rowKeys = []
423- oldPivotData .colKeys = []
424- oldPivotData .rowTotals = {}
425- oldPivotData .colTotals = {}
426- oldPivotData .filteredData = []
427- }
428-
429- // Create new instance
430- pivotData .value = new PivotData (state )
431- lastPivotDataKey = currentKey
432- }
433- })
434-
435- // Clean up on unmount
436- onUnmounted (() => {
437- const data = pivotData .value
438- if (data ) {
439- // Enhanced cleanup: Break aggregator closures completely
440- if (data .tree ) {
441- for (const rowKey in data .tree ) {
442- for (const colKey in data .tree [rowKey ]) {
443- const agg = data .tree [rowKey ][colKey ]
444- if (agg && typeof agg === ' object' ) {
445- // Break closure references completely
446- Object .keys (agg ).forEach (key => {
447- if (typeof agg [key ] === ' function' ) {
448- agg [key ] = null // Break function closures
449- } else if (typeof agg [key ] === ' object' && agg [key ] !== null ) {
450- agg [key ] = null // Break object references
451- } else {
452- delete agg [key ] // Delete primitive values
453- }
454- })
455- }
456- }
457- delete data .tree [rowKey ]
458- }
459- }
460-
461- // Clean up aggregator function references
462- if (data .aggregator ) data .aggregator = null
463-
464- // Clean up row/col totals aggregators
465- Object .keys (data .rowTotals ).forEach (key => {
466- const agg = data .rowTotals [key ]
467- if (agg && typeof agg === ' object' ) {
468- Object .keys (agg ).forEach (prop => {
469- if (typeof agg [prop ] === ' function' || (typeof agg [prop ] === ' object' && agg [prop ] !== null )) {
470- agg [prop ] = null
471- }
472- })
473- }
474- delete data .rowTotals [key ]
475- })
476-
477- Object .keys (data .colTotals ).forEach (key => {
478- const agg = data .colTotals [key ]
479- if (agg && typeof agg === ' object' ) {
480- Object .keys (agg ).forEach (prop => {
481- if (typeof agg [prop ] === ' function' || (typeof agg [prop ] === ' object' && agg [prop ] !== null )) {
482- agg [prop ] = null
483- }
484- })
485- }
486- delete data .colTotals [key ]
487- })
488-
489- // Clean up allTotal aggregator
490- if (data .allTotal && typeof data .allTotal === ' object' ) {
491- Object .keys (data .allTotal ).forEach (prop => {
492- if (typeof data .allTotal [prop ] === ' function' || (typeof data .allTotal [prop ] === ' object' && data .allTotal [prop ] !== null )) {
493- data .allTotal [prop ] = null
494- }
495- })
496- }
497- data .allTotal = null
498-
499- // Clear all remaining properties
500- data .tree = {}
501- data .rowKeys = []
502- data .colKeys = []
503- data .rowTotals = {}
504- data .colTotals = {}
505- data .filteredData = []
506- pivotData .value = null
507- }
508- })
332+ // Create new PivotData on every data change - no memoization
333+ // The real issue is that memoization prevents cleanup of old data
334+ const pivotData = computed (() => new PivotData (state ))
509335const pivotProps = computed (() => ({
510336 data: state .data ,
511337 aggregators: state .aggregators ,
0 commit comments