mirror of
https://github.com/nasa/openmct.git
synced 2025-06-15 13:48:12 +00:00
Memory leak fixes for several views (#7057)
* Change the mount utility to use Vue's createApp and defineComponent methods * Fix display layout memory leaks caused by `getSelectionContext` * fix some display layout leaks due to use of slots * Fix imagery memory leak (removed span tag). NOTE: CompassRose svg leaks memory - must test on firefox to see if this is a Chrome leak. * Fix ActionsAPI action collection and applicable actions leak. * Fix flexible layout memory leaks - remove listeners on unmount. NOTE: One type of overlay plot (Rover Yaw) is still leaking. * pass in the el on mount * e2e test config and spec changes * Remove mounting of limit lines. Use components directly * test: remove `.only()` * Fix display layout memory leaks * Enable passing tests * e2e README and appActions should be what master has. * lint: add word to cspell list * lint: fixes * lint:fix * fix: revert `el` change * fix: remove empty span * fix: creating shapes in displayLayout * fix: avoid `splice` as it loses reactivity * test: reduce timeout time * quick fixes * add prod mode and convert the test config to select the correct mode * Fix webpack prod config * Add launch flag for exposing window.gc * never worked * explicit naming * rename * We don't need to destroy view providers * test: increase timeout time * test: unskip all mem tests * fix(vue-loader): disable static hoisting * chore: run `test:perf:memory` * Don't destroy view providers * Move context menu once listener to beforeUnmount instead. * Disconnect all resize observers on unmount * Delete Test vue component * Use beforeUnmount and remove splice(0) in favor of [] for emptying arrays * re-structure * fix: unregister listener in pane.vue * test: tweak timeouts * chore: lint:fix * test: unskip perf tests * fix: unregister events properly * fix: unregister listener * fix: unregister listener * fix: unregister listener * fix: use `unmounted()` * fix: unregister listeners * fix: unregister listener properly * chore: lint:fix * test: fix imagery layer toggle test * test: increase timeout * Don't use anonymous functions for listeners * Destroy objects and event listeners properly * Delete config stores that are created by components * Use the right unmount hook. Destroy mounted view on unmount. * Use unmounted, not beforeUnmounted * Lint fixes * Fix time strip memory leak * Undo unneeded change for memory leaks. * chore: combine common webpack configs --------- Co-authored-by: Jesse Mazzella <jesse.d.mazzella@nasa.gov> Co-authored-by: John Hill <john.c.hill@nasa.gov>
This commit is contained in:
@ -25,14 +25,16 @@
|
||||
:item="item"
|
||||
:grid-size="gridSize"
|
||||
:is-editing="isEditing"
|
||||
@move="(gridDelta) => $emit('move', gridDelta)"
|
||||
@endMove="() => $emit('endMove')"
|
||||
@move="move"
|
||||
@endMove="endMove"
|
||||
>
|
||||
<div
|
||||
class="c-box-view u-style-receiver js-style-receiver"
|
||||
:class="[styleClass]"
|
||||
:style="style"
|
||||
></div>
|
||||
<template #content>
|
||||
<div
|
||||
class="c-box-view u-style-receiver js-style-receiver"
|
||||
:class="[styleClass]"
|
||||
:style="style"
|
||||
></div>
|
||||
</template>
|
||||
</layout-frame>
|
||||
</template>
|
||||
|
||||
@ -115,10 +117,18 @@ export default {
|
||||
this.initSelect
|
||||
);
|
||||
},
|
||||
unmounted() {
|
||||
beforeUnmount() {
|
||||
if (this.removeSelectable) {
|
||||
this.removeSelectable();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
move(gridDelta) {
|
||||
this.$emit('move', gridDelta);
|
||||
},
|
||||
endMove() {
|
||||
this.$emit('endMove');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@ -145,7 +145,7 @@ function getItemDefinition(itemType, ...options) {
|
||||
|
||||
export default {
|
||||
components: components,
|
||||
inject: ['openmct', 'objectPath', 'options', 'objectUtils', 'currentView'],
|
||||
inject: ['openmct', 'objectPath', 'options', 'currentView'],
|
||||
props: {
|
||||
domainObject: {
|
||||
type: Object,
|
||||
@ -222,13 +222,21 @@ export default {
|
||||
this.composition.load();
|
||||
this.gridDimensions = [this.$el.offsetWidth, this.$el.scrollHeight];
|
||||
|
||||
this.openmct.objects.observe(this.domainObject, 'configuration.items', (items) => {
|
||||
this.layoutItems = items;
|
||||
});
|
||||
this.unObserveItems = this.openmct.objects.observe(
|
||||
this.domainObject,
|
||||
'configuration.items',
|
||||
(items) => {
|
||||
this.layoutItems = [...items];
|
||||
}
|
||||
);
|
||||
|
||||
this.watchDisplayResize();
|
||||
},
|
||||
unmounted() {
|
||||
beforeUnmount() {
|
||||
if (this.unObserveItems) {
|
||||
this.unObserveItems();
|
||||
}
|
||||
this.unwatchDisplayResize();
|
||||
this.openmct.selection.off('change', this.setSelection);
|
||||
this.composition.off('add', this.addChild);
|
||||
this.composition.off('remove', this.removeChild);
|
||||
@ -252,9 +260,15 @@ export default {
|
||||
this.$el.click();
|
||||
},
|
||||
watchDisplayResize() {
|
||||
const resizeObserver = new ResizeObserver(() => this.updateGrid());
|
||||
this.unwatchDisplayResize();
|
||||
this.resizeObserver = new ResizeObserver(this.updateGrid);
|
||||
|
||||
resizeObserver.observe(this.$el);
|
||||
this.resizeObserver.observe(this.$el);
|
||||
},
|
||||
unwatchDisplayResize() {
|
||||
if (this.resizeObserver) {
|
||||
this.resizeObserver.disconnect();
|
||||
}
|
||||
},
|
||||
addElement(itemType, element) {
|
||||
this.addItem(itemType + '-view', element);
|
||||
@ -624,7 +638,7 @@ export default {
|
||||
return this.openmct.objects.makeKeyString(item.identifier) !== keyString;
|
||||
}
|
||||
});
|
||||
this.layoutItems = layoutItems;
|
||||
this.layoutItems = [...layoutItems];
|
||||
this.mutate('configuration.items', layoutItems);
|
||||
this.clearSelection();
|
||||
},
|
||||
|
@ -25,14 +25,16 @@
|
||||
:item="item"
|
||||
:grid-size="gridSize"
|
||||
:is-editing="isEditing"
|
||||
@move="(gridDelta) => $emit('move', gridDelta)"
|
||||
@endMove="() => $emit('endMove')"
|
||||
@move="move"
|
||||
@endMove="endMove"
|
||||
>
|
||||
<div
|
||||
class="c-ellipse-view u-style-receiver js-style-receiver"
|
||||
:class="[styleClass]"
|
||||
:style="style"
|
||||
></div>
|
||||
<template #content>
|
||||
<div
|
||||
class="c-ellipse-view u-style-receiver js-style-receiver"
|
||||
:class="[styleClass]"
|
||||
:style="style"
|
||||
></div>
|
||||
</template>
|
||||
</layout-frame>
|
||||
</template>
|
||||
|
||||
@ -115,10 +117,18 @@ export default {
|
||||
this.initSelect
|
||||
);
|
||||
},
|
||||
unmounted() {
|
||||
beforeUnmount() {
|
||||
if (this.removeSelectable) {
|
||||
this.removeSelectable();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
move(gridDelta) {
|
||||
this.$emit('move', gridDelta);
|
||||
},
|
||||
endMove() {
|
||||
this.$emit('endMove');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@ -25,10 +25,12 @@
|
||||
:item="item"
|
||||
:grid-size="gridSize"
|
||||
:is-editing="isEditing"
|
||||
@move="(gridDelta) => $emit('move', gridDelta)"
|
||||
@endMove="() => $emit('endMove')"
|
||||
@move="move"
|
||||
@endMove="endMove"
|
||||
>
|
||||
<div class="c-image-view" :class="[styleClass]" :style="style"></div>
|
||||
<template #content>
|
||||
<div class="c-image-view" :style="style"></div>
|
||||
</template>
|
||||
</layout-frame>
|
||||
</template>
|
||||
|
||||
@ -118,10 +120,18 @@ export default {
|
||||
this.initSelect
|
||||
);
|
||||
},
|
||||
unmounted() {
|
||||
beforeUnmount() {
|
||||
if (this.removeSelectable) {
|
||||
this.removeSelectable();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
move(gridDelta) {
|
||||
this.$emit('move', gridDelta);
|
||||
},
|
||||
endMove() {
|
||||
this.$emit('endMove');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@ -29,7 +29,7 @@
|
||||
}"
|
||||
:style="style"
|
||||
>
|
||||
<slot></slot>
|
||||
<slot name="content"></slot>
|
||||
<div class="c-frame__move-bar" @mousedown.left="startMove($event)"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -20,24 +20,26 @@
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<template>
|
||||
<LayoutFrame
|
||||
<layout-frame
|
||||
:item="item"
|
||||
:grid-size="gridSize"
|
||||
:is-editing="isEditing"
|
||||
@move="(gridDelta) => $emit('move', gridDelta)"
|
||||
@endMove="() => $emit('endMove')"
|
||||
@move="move"
|
||||
@endMove="endMove"
|
||||
>
|
||||
<ObjectFrame
|
||||
v-if="domainObject"
|
||||
ref="objectFrame"
|
||||
:domain-object="domainObject"
|
||||
:object-path="currentObjectPath"
|
||||
:has-frame="item.hasFrame"
|
||||
:show-edit-view="false"
|
||||
:layout-font-size="item.fontSize"
|
||||
:layout-font="item.font"
|
||||
/>
|
||||
</LayoutFrame>
|
||||
<template #content>
|
||||
<ObjectFrame
|
||||
v-if="domainObject"
|
||||
ref="objectFrame"
|
||||
:domain-object="domainObject"
|
||||
:object-path="currentObjectPath"
|
||||
:has-frame="item.hasFrame"
|
||||
:show-edit-view="false"
|
||||
:layout-font-size="item.fontSize"
|
||||
:layout-font="item.font"
|
||||
/>
|
||||
</template>
|
||||
</layout-frame>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -104,8 +106,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
domainObject: undefined,
|
||||
currentObjectPath: [],
|
||||
mutablePromise: undefined
|
||||
currentObjectPath: []
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
@ -168,6 +169,12 @@ export default {
|
||||
delete this.immediatelySelect;
|
||||
}
|
||||
});
|
||||
},
|
||||
move(gridDelta) {
|
||||
this.$emit('move', gridDelta);
|
||||
},
|
||||
endMove() {
|
||||
this.$emit('endMove');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -25,42 +25,44 @@
|
||||
:item="item"
|
||||
:grid-size="gridSize"
|
||||
:is-editing="isEditing"
|
||||
@move="(gridDelta) => $emit('move', gridDelta)"
|
||||
@endMove="() => $emit('endMove')"
|
||||
@move="move"
|
||||
@endMove="endMove"
|
||||
>
|
||||
<div
|
||||
v-if="domainObject"
|
||||
ref="telemetryViewWrapper"
|
||||
class="c-telemetry-view u-style-receiver"
|
||||
:class="[itemClasses]"
|
||||
:style="styleObject"
|
||||
:data-font-size="item.fontSize"
|
||||
:data-font="item.font"
|
||||
@contextmenu.prevent="showContextMenu"
|
||||
@mouseover.ctrl="showToolTip"
|
||||
@mouseleave="hideToolTip"
|
||||
>
|
||||
<div class="is-status__indicator" :title="`This item is ${status}`"></div>
|
||||
<div v-if="showLabel" class="c-telemetry-view__label">
|
||||
<div class="c-telemetry-view__label-text">
|
||||
{{ domainObject.name }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #content>
|
||||
<div
|
||||
v-if="showValue"
|
||||
:title="fieldName"
|
||||
class="c-telemetry-view__value"
|
||||
:class="[telemetryClass]"
|
||||
v-if="domainObject"
|
||||
ref="telemetryViewWrapper"
|
||||
class="c-telemetry-view u-style-receiver"
|
||||
:class="[itemClasses]"
|
||||
:style="styleObject"
|
||||
:data-font-size="item.fontSize"
|
||||
:data-font="item.font"
|
||||
@contextmenu.prevent="showContextMenu"
|
||||
@mouseover.ctrl="showToolTip"
|
||||
@mouseleave="hideToolTip"
|
||||
>
|
||||
<div class="c-telemetry-view__value-text">
|
||||
{{ telemetryValue }}
|
||||
<span v-if="unit && item.showUnits" class="c-telemetry-view__value-text__unit">
|
||||
{{ unit }}
|
||||
</span>
|
||||
<div class="is-status__indicator" :title="`This item is ${status}`"></div>
|
||||
<div v-if="showLabel" class="c-telemetry-view__label">
|
||||
<div class="c-telemetry-view__label-text">
|
||||
{{ domainObject.name }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="showValue"
|
||||
:title="fieldName"
|
||||
class="c-telemetry-view__value"
|
||||
:class="[telemetryClass]"
|
||||
>
|
||||
<div class="c-telemetry-view__value-text">
|
||||
{{ telemetryValue }}
|
||||
<span v-if="unit && item.showUnits" class="c-telemetry-view__value-text__unit">
|
||||
{{ unit }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</layout-frame>
|
||||
</template>
|
||||
|
||||
@ -388,6 +390,12 @@ export default {
|
||||
async showToolTip() {
|
||||
const { BELOW } = this.openmct.tooltips.TOOLTIP_LOCATIONS;
|
||||
this.buildToolTip(await this.getObjectPath(), BELOW, 'telemetryViewWrapper');
|
||||
},
|
||||
move(gridDelta) {
|
||||
this.$emit('move', gridDelta);
|
||||
},
|
||||
endMove() {
|
||||
this.$emit('endMove');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -25,18 +25,20 @@
|
||||
:item="item"
|
||||
:grid-size="gridSize"
|
||||
:is-editing="isEditing"
|
||||
@move="(gridDelta) => $emit('move', gridDelta)"
|
||||
@endMove="() => $emit('endMove')"
|
||||
@move="move"
|
||||
@endMove="endMove"
|
||||
>
|
||||
<div
|
||||
class="c-text-view u-style-receiver js-style-receiver"
|
||||
:data-font-size="item.fontSize"
|
||||
:data-font="item.font"
|
||||
:class="[styleClass]"
|
||||
:style="style"
|
||||
>
|
||||
<div class="c-text-view__text">{{ item.text }}</div>
|
||||
</div>
|
||||
<template #content>
|
||||
<div
|
||||
class="c-text-view u-style-receiver js-style-receiver"
|
||||
:data-font-size="item.fontSize"
|
||||
:data-font="item.font"
|
||||
:class="[styleClass]"
|
||||
:style="style"
|
||||
>
|
||||
<div class="c-text-view__text">{{ item.text }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</layout-frame>
|
||||
</template>
|
||||
|
||||
@ -127,10 +129,18 @@ export default {
|
||||
this.initSelect
|
||||
);
|
||||
},
|
||||
unmounted() {
|
||||
beforeUnmount() {
|
||||
if (this.removeSelectable) {
|
||||
this.removeSelectable();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
move(gridDelta) {
|
||||
this.$emit('move', gridDelta);
|
||||
},
|
||||
endMove() {
|
||||
this.$emit('endMove');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
Reference in New Issue
Block a user