Compare commits

...

9 Commits

34 changed files with 387 additions and 298 deletions

10
app.js
View File

@ -42,11 +42,11 @@ app.use('/proxyUrl', function proxyRequest(req, res, next) {
const webpack = require('webpack');
const webpackConfig = require('./webpack.config.js');
webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
webpackConfig.plugins.push(function() { this.plugin('watch-run', function(watching, callback) { console.log('Begin compile at ' + new Date()); callback(); }) });
//webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
//webpackConfig.plugins.push(function() { this.plugin('watch-run', function(watching, callback) { console.log('Begin compile at ' + new Date()); callback(); }) });
webpackConfig.entry.openmct = [
'webpack-hot-middleware/client?reload=true',
// 'webpack-hot-middleware/client?reload=true',
webpackConfig.entry.openmct
];
@ -60,12 +60,12 @@ app.use(require('webpack-dev-middleware')(
}
));
app.use(require('webpack-hot-middleware')(
/*app.use(require('webpack-hot-middleware')(
compiler,
{
}
));
));*/
// Expose index.html for development users.
app.get('/', function (req, res) {

View File

@ -41,11 +41,6 @@ define([
"$scope"
]
}
],
"routes": [
{
"templateUrl": "templates/exampleForm.html"
}
]
}
}

View File

@ -66,134 +66,143 @@
<body>
</body>
<script>
const THIRTY_SECONDS = 30 * 1000;
const ONE_MINUTE = THIRTY_SECONDS * 2;
const FIVE_MINUTES = ONE_MINUTE * 5;
const FIFTEEN_MINUTES = FIVE_MINUTES * 3;
const THIRTY_MINUTES = FIFTEEN_MINUTES * 2;
const ONE_HOUR = THIRTY_MINUTES * 2;
const TWO_HOURS = ONE_HOUR * 2;
const ONE_DAY = ONE_HOUR * 24;
(function() {
const THIRTY_SECONDS = 30 * 1000;
const ONE_MINUTE = THIRTY_SECONDS * 2;
const FIVE_MINUTES = ONE_MINUTE * 5;
const FIFTEEN_MINUTES = FIVE_MINUTES * 3;
const THIRTY_MINUTES = FIFTEEN_MINUTES * 2;
const ONE_HOUR = THIRTY_MINUTES * 2;
const TWO_HOURS = ONE_HOUR * 2;
const ONE_DAY = ONE_HOUR * 24;
[
'example/eventGenerator'
].forEach(
openmct.legacyRegistry.enable.bind(openmct.legacyRegistry)
);
let app = new openmct();
openmct.install(openmct.plugins.LocalStorage());
openmct.install(openmct.plugins.Espresso());
openmct.install(openmct.plugins.MyItems());
openmct.install(openmct.plugins.Generator());
openmct.install(openmct.plugins.ExampleImagery());
openmct.install(openmct.plugins.PlanLayout());
openmct.install(openmct.plugins.Timeline());
openmct.install(openmct.plugins.UTCTimeSystem());
openmct.install(openmct.plugins.AutoflowView({
type: "telemetry.panel"
}));
openmct.install(openmct.plugins.DisplayLayout({
showAsView: ['summary-widget', 'example.imagery']
}));
openmct.install(openmct.plugins.Conductor({
menuOptions: [
{
name: "Fixed",
timeSystem: 'utc',
bounds: {
start: Date.now() - THIRTY_MINUTES,
end: Date.now()
[
'example/eventGenerator'
].forEach(
app.legacyRegistry.enable.bind(app.legacyRegistry)
);
app.install(app.plugins.LocalStorage());
app.install(app.plugins.Espresso());
app.install(app.plugins.MyItems());
//app.install(app.plugins.Generator());
app.install(app.plugins.ExampleImagery());
app.install(app.plugins.PlanLayout());
app.install(app.plugins.Timeline());
//app.install(app.plugins.Hyperlink());
app.install(app.plugins.UTCTimeSystem());
app.install(app.plugins.AutoflowView({
type: "telemetry.panel"
}));
app.install(app.plugins.DisplayLayout({
showAsView: ['summary-widget', 'example.imagery']
}));
app.install(app.plugins.Conductor({
menuOptions: [
{
name: "Fixed",
timeSystem: 'utc',
bounds: {
start: Date.now() - THIRTY_MINUTES,
end: Date.now()
},
// commonly used bounds can be stored in history
// bounds (start and end) can accept either a milliseconds number
// or a callback function returning a milliseconds number
// a function is useful for invoking Date.now() at exact moment of preset selection
presets: [
{
label: 'Last Day',
bounds: {
start: () => Date.now() - ONE_DAY,
end: () => Date.now()
}
},
{
label: 'Last 2 hours',
bounds: {
start: () => Date.now() - TWO_HOURS,
end: () => Date.now()
}
},
{
label: 'Last hour',
bounds: {
start: () => Date.now() - ONE_HOUR,
end: () => Date.now()
}
}
],
// maximum recent bounds to retain in conductor history
records: 10
// maximum duration between start and end bounds
// for utc-based time systems this is in milliseconds
// limit: ONE_DAY
},
// commonly used bounds can be stored in history
// bounds (start and end) can accept either a milliseconds number
// or a callback function returning a milliseconds number
// a function is useful for invoking Date.now() at exact moment of preset selection
presets: [
{
label: 'Last Day',
bounds: {
start: () => Date.now() - ONE_DAY,
end: () => Date.now()
}
{
name: "Realtime",
timeSystem: 'utc',
clock: 'local',
clockOffsets: {
start: - THIRTY_MINUTES,
end: THIRTY_SECONDS
},
{
label: 'Last 2 hours',
bounds: {
start: () => Date.now() - TWO_HOURS,
end: () => Date.now()
presets: [
{
label: '1 Hour',
bounds: {
start: - ONE_HOUR,
end: THIRTY_SECONDS
}
},
{
label: '30 Minutes',
bounds: {
start: - THIRTY_MINUTES,
end: THIRTY_SECONDS
}
},
{
label: '15 Minutes',
bounds: {
start: - FIFTEEN_MINUTES,
end: THIRTY_SECONDS
}
},
{
label: '5 Minutes',
bounds: {
start: - FIVE_MINUTES,
end: THIRTY_SECONDS
}
},
{
label: '1 Minute',
bounds: {
start: - ONE_MINUTE,
end: THIRTY_SECONDS
}
}
},
{
label: 'Last hour',
bounds: {
start: () => Date.now() - ONE_HOUR,
end: () => Date.now()
}
}
],
// maximum recent bounds to retain in conductor history
records: 10
// maximum duration between start and end bounds
// for utc-based time systems this is in milliseconds
// limit: ONE_DAY
},
{
name: "Realtime",
timeSystem: 'utc',
clock: 'local',
clockOffsets: {
start: - THIRTY_MINUTES,
end: THIRTY_SECONDS
},
presets: [
{
label: '1 Hour',
bounds: {
start: - ONE_HOUR,
end: THIRTY_SECONDS
}
},
{
label: '30 Minutes',
bounds: {
start: - THIRTY_MINUTES,
end: THIRTY_SECONDS
}
},
{
label: '15 Minutes',
bounds: {
start: - FIFTEEN_MINUTES,
end: THIRTY_SECONDS
}
},
{
label: '5 Minutes',
bounds: {
start: - FIVE_MINUTES,
end: THIRTY_SECONDS
}
},
{
label: '1 Minute',
bounds: {
start: - ONE_MINUTE,
end: THIRTY_SECONDS
}
}
]
}
]
}));
openmct.install(openmct.plugins.SummaryWidget());
openmct.install(openmct.plugins.Notebook());
openmct.install(openmct.plugins.LADTable());
openmct.install(openmct.plugins.Filters(['table', 'telemetry.plot.overlay']));
openmct.install(openmct.plugins.ObjectMigration());
openmct.install(openmct.plugins.ClearData(
['table', 'telemetry.plot.overlay', 'telemetry.plot.stacked'],
{indicator: true}
));
openmct.start();
]
}
]
}));
app.install(app.plugins.SummaryWidget());
app.install(app.plugins.Notebook());
app.install(app.plugins.LADTable());
app.install(app.plugins.Filters(['table', 'telemetry.plot.overlay']));
app.install(app.plugins.ObjectMigration());
app.install(app.plugins.ClearData(
['table', 'telemetry.plot.overlay', 'telemetry.plot.stacked'],
{indicator: true}
));
app.start();
setTimeout(() => {
app.destroy();
}, 5000)
})();
</script>
</html>

View File

@ -1,3 +1,7 @@
const testsContext = require.context('.', true, /\/(src|platform)\/.*Spec.js$/);
import MemoryLeaksReporter from "./src/utils/testing/MemoryLeaksReporter";
jasmine.getEnv().addReporter(new MemoryLeaksReporter());
const testsContext = require.context('.', true, /\/(src|platform)\/.*Spec.js$/);
testsContext.keys().forEach(testsContext);
console.error("Done running tests?");

View File

@ -23,7 +23,7 @@
/*global module,process*/
const devMode = process.env.NODE_ENV !== 'production';
const browsers = [process.env.NODE_ENV === 'debug' ? 'ChromeDebugging' : 'ChromeHeadless'];
const browsers = [process.env.NODE_ENV === 'debug' ? 'ChromeDebugging' : 'ChromeMemory'];
const coverageEnabled = process.env.COVERAGE === 'true';
const reporters = ['progress', 'html', 'junit'];
@ -64,7 +64,11 @@ module.exports = (config) => {
}
},
customLaunchers: {
ChromeDebugging: {
ChromeMemory: {
base: 'ChromeHeadless',
flags: ['--enable-precise-memory-info', '--js-flags="--expose-gc --nocrankshaft --noopt"']
}
/* ChromeDebugging: {
base: 'Chrome',
flags: ['--remote-debugging-port=9222'],
debug: true
@ -72,7 +76,7 @@ module.exports = (config) => {
FirefoxESR: {
base: 'FirefoxHeadless',
name: 'FirefoxESR'
}
}*/
},
colors: true,
logLevel: config.LOG_INFO,

View File

@ -32,6 +32,6 @@ if (document.currentScript) {
const MCT = require('./src/MCT');
const openmct = new MCT();
//const openmct = new MCT();
module.exports = openmct;
module.exports = MCT;

View File

@ -2,8 +2,11 @@
"name": "openmct",
"version": "1.7.6-SNAPSHOT",
"description": "The Open MCT core platform",
"dependencies": {},
"dependencies": {
"http-server": "^0.12.3"
},
"devDependencies": {
"@webpack-cli/serve": "^1.5.1",
"angular": ">=1.8.0",
"angular-route": "1.4.14",
"babel-eslint": "10.0.3",
@ -41,13 +44,13 @@
"jsdoc": "^3.3.2",
"karma": "6.3.4",
"karma-chrome-launcher": "3.1.0",
"karma-firefox-launcher": "2.1.0",
"karma-cli": "2.0.0",
"karma-coverage": "2.0.3",
"karma-coverage-istanbul-reporter": "3.0.3",
"karma-junit-reporter": "2.0.1",
"karma-firefox-launcher": "2.1.0",
"karma-html-reporter": "0.2.7",
"karma-jasmine": "4.0.1",
"karma-junit-reporter": "2.0.1",
"karma-sourcemap-loader": "0.3.8",
"karma-webpack": "4.0.2",
"location-bar": "^3.0.1",
@ -75,6 +78,7 @@
"webpack": "^4.16.2",
"webpack-cli": "^3.1.0",
"webpack-dev-middleware": "^3.1.3",
"webpack-dev-server": "^3.11.2",
"webpack-hot-middleware": "^2.22.3",
"zepto": "^1.2.0"
},

View File

@ -164,16 +164,6 @@ define([
"license": "license-apache",
"link": "http://logging.apache.org/log4net/license.html"
}
],
"routes": [
{
"when": "/licenses",
"template": licensesTemplate
},
{
"when": "/licenses-md",
"template": licensesExportMdTemplate
}
]
}
}

View File

@ -50,8 +50,6 @@ define([
name: "platform/commonUI/browse",
definition: {
"extensions": {
"routes": [
],
"constants": [
{
"key": "DEFAULT_PATH",

View File

@ -40,8 +40,8 @@ define(
this.checks = [];
this.$window = $window;
this.oldUnload = $window.onbeforeunload;
$window.onbeforeunload = this.onBeforeUnload.bind(this);
/* this.oldUnload = $window.onbeforeunload;
$window.onbeforeunload = this.onBeforeUnload.bind(this);*/
}
/**

View File

@ -89,7 +89,8 @@ define([
"implementation": TickerService,
"depends": [
"$timeout",
"now"
"now",
"$rootScope"
]
},
{

View File

@ -32,8 +32,13 @@ define(
* @param $timeout Angular's $timeout
* @param {Function} now function to provide the current time in ms
*/
function TickerService($timeout, now) {
function TickerService($timeout, now, $rootScope) {
var self = this;
var timeoutId;
$rootScope.$on('$destroy', function () {
$timeout.cancel(timeoutId);
});
function tick() {
var timestamp = now(),
@ -48,7 +53,7 @@ define(
}
// Try to update at exactly the next second
$timeout(tick, 1000 - millis, true);
timeoutId = $timeout(tick, 1000 - millis, true);
}
tick();

View File

@ -58,7 +58,7 @@ define([
) {
var $http = this.$http,
$log = this.$log,
app = angular.module(Constants.MODULE_NAME, ["ngRoute"]),
app = angular.module(Constants.MODULE_NAME, []),
loader = new BundleLoader($http, $log, openmct.legacyRegistry),
resolver = new BundleResolver(
new ExtensionResolver(

View File

@ -28,8 +28,7 @@
define(
[
'./FrameworkLayer',
'angular',
'angular-route'
'angular'
],
function (
FrameworkLayer,

View File

@ -57,7 +57,6 @@ define(
$log = this.$log;
return new Promise(function (resolve, reject) {
$log.info("Bootstrapping application " + (app || {}).name);
angular.element(document).ready(function () {
angular.bootstrap(document, [app.name], { strictDi: true });
resolve(angular);

View File

@ -138,34 +138,6 @@ define(
}
}
// Custom registration function for extensions of category "route"
function registerRoute(extension) {
var app = this.app,
$log = this.$log,
route = Object.create(extension);
// Adjust path for bundle
if (route.templateUrl) {
route.templateUrl = [
route.bundle.path,
route.bundle.resources,
route.templateUrl
].join(Constants.SEPARATOR);
}
// Log the registration
$log.info("Registering route: " + (route.key || route.when));
// Register the route with Angular
app.config(['$routeProvider', function ($routeProvider) {
if (route.when) {
$routeProvider.when(route.when, route);
} else {
$routeProvider.otherwise(route);
}
}]);
}
// Handle service compositing
function registerComponents(components) {
var app = this.app,
@ -194,13 +166,6 @@ define(
CustomRegistrars.prototype.constants =
mapUpon(registerConstant);
/**
* Register Angular routes.
* @param {Array} extensions the resolved extensions
*/
CustomRegistrars.prototype.routes =
mapUpon(registerRoute);
/**
* Register Angular directives.
* @param {Array} extensions the resolved extensions

View File

@ -57,7 +57,6 @@ define(
expect(customRegistrars.directives).toBeTruthy();
expect(customRegistrars.controllers).toBeTruthy();
expect(customRegistrars.services).toBeTruthy();
expect(customRegistrars.routes).toBeTruthy();
expect(customRegistrars.constants).toBeTruthy();
expect(customRegistrars.runs).toBeTruthy();
});
@ -139,47 +138,6 @@ define(
expect(mockLog.warn.calls.count()).toEqual(0);
});
it("allows routes to be registered", function () {
var mockRouteProvider = jasmine.createSpyObj(
"$routeProvider",
["when", "otherwise"]
),
bundle = {
path: "test/bundle",
resources: "res"
},
routes = [
{
when: "foo",
templateUrl: "templates/test.html",
bundle: bundle
},
{
templateUrl: "templates/default.html",
bundle: bundle
}
];
customRegistrars.routes(routes);
// Give it the route provider based on its config call
mockApp.config.calls.all().forEach(function (call) {
// Invoke the provided callback
call.args[0][1](mockRouteProvider);
});
// The "when" clause should have been mapped to the when method...
expect(mockRouteProvider.when).toHaveBeenCalled();
expect(mockRouteProvider.when.calls.mostRecent().args[0]).toEqual("foo");
expect(mockRouteProvider.when.calls.mostRecent().args[1].templateUrl)
.toEqual("test/bundle/res/templates/test.html");
// ...while the other should have been treated as a default route
expect(mockRouteProvider.otherwise).toHaveBeenCalled();
expect(mockRouteProvider.otherwise.calls.mostRecent().args[0].templateUrl)
.toEqual("test/bundle/res/templates/default.html");
});
it("accepts components for service compositing", function () {
// Most relevant code will be exercised in service compositor spec
expect(customRegistrars.components).toBeTruthy();

View File

@ -30,8 +30,8 @@ define([
return function ImportExportPlugin() {
return function (openmct) {
ExportAsJSONAction.appliesTo = function (context) {
return openmct.$injector.get('policyService')
ExportAsJSONAction.prototype.appliesTo = function (context) {
return this.openmct.$injector.get('policyService')
.allow("creation", context.domainObject.getCapability("type")
);
};

View File

@ -110,8 +110,15 @@ define([
worker = workerService.run('bareBonesSearchWorker');
}
worker.addEventListener('message', function (messageEvent) {
function handleWorkerMessage(messageEvent) {
provider.onWorkerMessage(messageEvent);
}
worker.addEventListener('message', handleWorkerMessage);
this.openmct.once('destroy', () => {
worker.removeEventListener('message', handleWorkerMessage);
worker.terminate();
});
return worker;

View File

@ -31,7 +31,6 @@ define([
'objectUtils',
'./plugins/plugins',
'./adapter/indicators/legacy-indicators-plugin',
'./plugins/buildInfo/plugin',
'./ui/registries/ViewRegistry',
'./plugins/imagery/plugin',
'./ui/registries/InspectorViewRegistry',
@ -40,6 +39,7 @@ define([
'./ui/router/Browse',
'../platform/framework/src/Main',
'./ui/layout/Layout.vue',
'./ui/inspector/styles/StylesManager',
'../platform/core/src/objects/DomainObjectImpl',
'../platform/core/src/capabilities/ContextualDomainObject',
'./ui/preview/plugin',
@ -60,7 +60,6 @@ define([
objectUtils,
plugins,
LegacyIndicatorsPlugin,
buildInfoPlugin,
ViewRegistry,
ImageryPlugin,
InspectorViewRegistry,
@ -69,6 +68,7 @@ define([
Browse,
Main,
Layout,
stylesManager,
DomainObjectImpl,
ContextualDomainObject,
PreviewPlugin,
@ -374,6 +374,7 @@ define([
* MCT; if undefined, MCT will be run in the body of the document
*/
MCT.prototype.start = function (domElement = document.body, isHeadlessMode = false) {
if (this.types.get('layout') === undefined) {
this.install(this.plugins.DisplayLayout({
showAsView: ['summary-widget']
@ -432,6 +433,9 @@ define([
domElement.appendChild(appLayout.$mount().$el);
this.layout = appLayout.$refs.layout;
this.once('destroy', () => {
this.layout.$destroy();
});
Browse(this);
}
@ -459,7 +463,31 @@ define([
MCT.prototype.destroy = function () {
this.emit('destroy');
this.router.destroy();
this.removeAllListeners();
if (this.$injector) {
this.$injector.get('$rootScope').$destroy();
this.$injector = null;
}
if (this.$angular) {
this.$angular.element(this.element).off().removeData();
this.$angular.element(this.element).empty();
this.$angular = null;
}
this.overlays.destroy();
if (this.element) {
this.element.remove();
}
stylesManager.default.removeAllListeners();
window.angular = null;
window.openmct = null;
Object.keys(require.cache).forEach(key => delete require.cache[key]);
};
MCT.prototype.plugins = plugins;

View File

@ -26,80 +26,93 @@ define([
'utils/testing'
], function (plugins, legacyRegistry, testUtils) {
describe("MCT", function () {
let openmct;
let mockPlugin;
let mockPlugin2;
let mockListener;
let oldBundles;
beforeEach(function () {
mockPlugin = jasmine.createSpy('plugin');
mockPlugin2 = jasmine.createSpy('plugin2');
mockListener = jasmine.createSpy('listener');
oldBundles = legacyRegistry.list();
this.mockPlugin = jasmine.createSpy('plugin');
this.mockPlugin2 = jasmine.createSpy('plugin2');
this.mockListener = jasmine.createSpy('listener');
this.oldBundles = legacyRegistry.list();
openmct = testUtils.createOpenMct();
this.openmct = testUtils.createOpenMct();
openmct.install(mockPlugin);
openmct.install(mockPlugin2);
openmct.on('start', mockListener);
this.openmct.install(this.mockPlugin);
this.openmct.install(this.mockPlugin2);
this.openmct.once('start', this.mockListener);
});
// Clean up the dirty singleton.
afterEach(function () {
legacyRegistry.list().forEach(function (bundle) {
if (oldBundles.indexOf(bundle) === -1) {
if (this.oldBundles.indexOf(bundle) === -1) {
legacyRegistry.delete(bundle);
}
});
return testUtils.resetApplicationState(openmct);
return testUtils.resetApplicationState(this.openmct)
.then(() => {
this.openmct = null;
this.mockPlugin = null;
this.mockPlugin2 = null;
this.mockListener = null;
this.oldBundles = null;
console.error('Done clearing test variables');
});
});
it("exposes plugins", function () {
expect(openmct.plugins).toEqual(plugins);
expect(this.openmct.plugins).toEqual(plugins);
});
it("does not issue a start event before started", function () {
expect(mockListener).not.toHaveBeenCalled();
expect(this.mockListener).not.toHaveBeenCalled();
});
describe("start", function () {
let appHolder;
beforeEach(function (done) {
appHolder = document.createElement("div");
openmct.on('start', done);
openmct.start(appHolder);
beforeEach(function () {
this.appHolder = document.createElement("div");
const startPromise = new Promise(resolve => {
this.openmct.once('start', resolve);
});
this.openmct.startHeadless();
return startPromise;
});
afterEach(() => {
//this.appHolder.remove();
this.appHolder = null;
});
it("calls plugins for configuration", function () {
expect(mockPlugin).toHaveBeenCalledWith(openmct);
expect(mockPlugin2).toHaveBeenCalledWith(openmct);
expect(this.mockPlugin).toHaveBeenCalledWith(this.openmct);
expect(this.mockPlugin2).toHaveBeenCalledWith(this.openmct);
});
it("emits a start event", function () {
expect(mockListener).toHaveBeenCalled();
expect(this.mockListener).toHaveBeenCalled();
});
it("Renders the application into the provided container element", function () {
let openMctShellElements = appHolder.querySelectorAll('div.l-shell');
let openMctShellElements = this.appHolder.querySelectorAll('div.l-shell');
expect(openMctShellElements.length).toBe(1);
});
});
describe("startHeadless", function () {
beforeEach(function (done) {
openmct.on('start', done);
openmct.startHeadless();
console.error('HERE');
this.openmct.on('start', done);
this.openmct.startHeadless();
});
it("calls plugins for configuration", function () {
expect(mockPlugin).toHaveBeenCalledWith(openmct);
expect(mockPlugin2).toHaveBeenCalledWith(openmct);
expect(this.mockPlugin).toHaveBeenCalledWith(this.openmct);
expect(this.mockPlugin2).toHaveBeenCalledWith(this.openmct);
});
it("emits a start event", function () {
expect(mockListener).toHaveBeenCalled();
expect(this.mockListener).toHaveBeenCalled();
});
it("Does not render Open MCT", function () {
@ -112,19 +125,19 @@ define([
let testAssetPath;
beforeEach(function () {
openmct.legacyExtension = jasmine.createSpy('legacyExtension');
this.openmct.legacyExtension = jasmine.createSpy('legacyExtension');
});
it("configures the path for assets", function () {
testAssetPath = "some/path/";
openmct.setAssetPath(testAssetPath);
expect(openmct.getAssetPath()).toBe(testAssetPath);
this.openmct.setAssetPath(testAssetPath);
expect(this.openmct.getAssetPath()).toBe(testAssetPath);
});
it("adds a trailing /", function () {
testAssetPath = "some/path";
openmct.setAssetPath(testAssetPath);
expect(openmct.getAssetPath()).toBe(testAssetPath + "/");
this.openmct.setAssetPath(testAssetPath);
expect(this.openmct.getAssetPath()).toBe(testAssetPath + "/");
});
});
});

View File

@ -32,6 +32,10 @@ define([
// cannot be injected.
function AlternateCompositionInitializer(openmct) {
AlternateCompositionCapability.appliesTo = function (model, id) {
openmct.once('destroy', () => {
delete AlternateCompositionCapability.appliesTo;
});
model = objectUtils.toNewFormat(model, id || '');
return Boolean(openmct.composition.get(model));

View File

@ -28,6 +28,10 @@ export default class Editor extends EventEmitter {
super();
this.editing = false;
this.openmct = openmct;
openmct.once('destroy', () => {
this.removeAllListeners();
});
}
/**

View File

@ -17,11 +17,7 @@ class OverlayAPI {
this.dismissLastOverlay = this.dismissLastOverlay.bind(this);
document.addEventListener('keyup', (event) => {
if (event.key === 'Escape') {
this.dismissLastOverlay();
}
});
document.addEventListener('keyup', this.dismissLastOverlay);
}
@ -49,10 +45,12 @@ class OverlayAPI {
/**
* private
*/
dismissLastOverlay() {
let lastOverlay = this.activeOverlays[this.activeOverlays.length - 1];
if (lastOverlay && lastOverlay.dismissable) {
lastOverlay.dismiss();
dismissLastOverlay(event) {
if (event.key === 'Escape') {
let lastOverlay = this.activeOverlays[this.activeOverlays.length - 1];
if (lastOverlay && lastOverlay.dismissable) {
lastOverlay.dismiss();
}
}
}
@ -129,6 +127,10 @@ class OverlayAPI {
return progressDialog;
}
destroy() {
document.removeEventListener('keyup', this.dismissLastOverlay);
}
}
export default OverlayAPI;

View File

@ -32,6 +32,10 @@ export default class StatusAPI extends EventEmitter {
this.get = this.get.bind(this);
this.set = this.set.bind(this);
this.observe = this.observe.bind(this);
openmct.once('destroy', () => {
this.removeAllListeners();
});
}
get(identifier) {

View File

@ -42,7 +42,7 @@ const DEFAULTS = [
'platform/forms',
'platform/identity',
'platform/persistence/aggregator',
'platform/persistence/queue',
//'platform/persistence/queue',
'platform/policy',
'platform/entanglement',
'platform/search',
@ -90,7 +90,7 @@ define([
'../platform/persistence/aggregator/bundle',
'../platform/persistence/elastic/bundle',
'../platform/persistence/local/bundle',
'../platform/persistence/queue/bundle',
//'../platform/persistence/queue/bundle',
'../platform/policy/bundle',
'../platform/representation/bundle',
'../platform/search/bundle',

View File

@ -117,6 +117,10 @@ export default function NotebookPlugin() {
key: 'notebook-snapshot-indicator'
};
openmct.once('destroy', () => {
snapshotContainer.destroy();
});
openmct.indicators.add(indicator);
openmct.objectViews.addProvider({

View File

@ -80,4 +80,8 @@ export default class SnapshotContainer extends EventEmitter {
return this.saveSnapshots(updatedSnapshots);
}
destroy() {
delete SnapshotContainer.instance;
}
}

View File

@ -98,7 +98,10 @@ export default {
//Respond to changes in conductor
this.openmct.time.on("timeSystem", this.setViewFromTimeSystem);
setInterval(this.resize, RESIZE_POLL_INTERVAL);
this.resizeTimer = setInterval(this.resize, RESIZE_POLL_INTERVAL);
},
destroyed() {
clearInterval(this.resizeTimer);
},
methods: {
setAxisDimensions() {

View File

@ -38,6 +38,10 @@ define(
this.openmct = openmct;
this.selected = [];
this.openmct.once('destroy', () => {
this.removeAllListeners();
});
}
Selection.prototype = Object.create(EventEmitter.prototype);

View File

@ -253,7 +253,7 @@ export default {
}
document.removeEventListener('click', this.closeViewAndSaveMenu);
window.removeEventListener('click', this.promptUserbeforeNavigatingAway);
window.removeEventListener('beforeunload', this.promptUserbeforeNavigatingAway);
},
methods: {
toggleSaveMenu() {

View File

@ -49,6 +49,10 @@ class ApplicationRouter extends EventEmitter {
this.routes = [];
this.started = false;
openmct.once('destroy', () => {
this.destroy();
});
this.setHash = _.debounce(this.setHash.bind(this), 300);
}

View File

@ -25,6 +25,12 @@ import MCT from 'MCT';
let nativeFunctions = [];
let mockObjects = setMockObjects();
const activeInstance = {
activeSpec: undefined,
specToInstanceMap: new WeakMap()
};
export {activeInstance};
export function createOpenMct() {
const openmct = new MCT();
openmct.install(openmct.plugins.LocalStorage());
@ -33,6 +39,7 @@ export function createOpenMct() {
start: 0,
end: 1
});
activeInstance.specToInstanceMap.set(activeInstance.activeSpec, openmct);
return openmct;
}
@ -88,7 +95,11 @@ export function resetApplicationState(openmct) {
promise = Promise.resolve();
}
return promise;
openmct = null;
return promise.then(() => {
window.gc();
});
}
// required: key

View File

@ -0,0 +1,66 @@
//'Possible memory leaks in 205 specs'
//'Possible memory leaks in 214 specs'
//'Possible memory leaks in 207 specs'
//'Possible memory leaks in 212 specs'
//'Possible memory leaks in 204 specs'
// Note: specDone will run when it THINKS the spec is done. It's possible that it's not actually done yet, the promise could have been resolved or the done function could have been invoked prematurely.
import {activeInstance} from '../testing.js';
function toMegabytes(bytes) {
return `${Math.round(bytes / 1024 / 1024)}MB`;
}
function toKilobytes(bytes) {
return `${Math.round(bytes / 1024)}KB`;
}
let count = 0;
const memoryLeaks = new Set();
const FR = new FinalizationRegistry((specName) => {
memoryLeaks.delete(specName);
console.error(`Spec cleaned up after itself: ${specName}. Good spec.`);
});
export default class MemoryLeaksReporter {
specStarted(spec) {
window.gc();
//this.usedJSHeapSizeStart = performance.memory.usedJSHeapSize;
activeInstance.activeSpec = spec;
}
specDone(spec) {
let instance = activeInstance.specToInstanceMap.get(activeInstance.activeSpec);
if (instance !== undefined) {
memoryLeaks.add(spec.fullName);
FR.register(instance, spec.fullName);
}
/*
const usedJSHeapSizeEnd = performance.memory.usedJSHeapSize;
const memoryDelta = usedJSHeapSizeEnd - this.usedJSHeapSizeStart;
if (memoryDelta > 0) {
count++;
}*/
}
async jasmineDone() {
window.gc();
await new Promise((resolve) => {
setTimeout(() => {
window.gc();
if (memoryLeaks.size > 0) {
console.error("\r\n");
console.error("##############################################");
console.error(`${memoryLeaks.size} test spec(s) contain memory leaks: `);
for (const specName of memoryLeaks) {
console.error(`- ${specName}`);
}
}
resolve();
});
});
}
}