mirror of
https://github.com/nasa/openmct.git
synced 2025-06-25 02:29:24 +00:00
Compare commits
9 Commits
experiment
...
memory-lea
Author | SHA1 | Date | |
---|---|---|---|
7ac37a481c | |||
d6474045c3 | |||
23c10d40a8 | |||
cc37a5f899 | |||
177dbec0c5 | |||
38952b8eb3 | |||
f19c5699a6 | |||
cc017e879c | |||
93172eb180 |
10
app.js
10
app.js
@ -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) {
|
||||
|
@ -41,11 +41,6 @@ define([
|
||||
"$scope"
|
||||
]
|
||||
}
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"templateUrl": "templates/exampleForm.html"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
257
index.html
257
index.html
@ -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>
|
||||
|
@ -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?");
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
10
package.json
10
package.json
@ -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"
|
||||
},
|
||||
|
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -50,8 +50,6 @@ define([
|
||||
name: "platform/commonUI/browse",
|
||||
definition: {
|
||||
"extensions": {
|
||||
"routes": [
|
||||
],
|
||||
"constants": [
|
||||
{
|
||||
"key": "DEFAULT_PATH",
|
||||
|
@ -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);*/
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -89,7 +89,8 @@ define([
|
||||
"implementation": TickerService,
|
||||
"depends": [
|
||||
"$timeout",
|
||||
"now"
|
||||
"now",
|
||||
"$rootScope"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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(
|
||||
|
@ -28,8 +28,7 @@
|
||||
define(
|
||||
[
|
||||
'./FrameworkLayer',
|
||||
'angular',
|
||||
'angular-route'
|
||||
'angular'
|
||||
],
|
||||
function (
|
||||
FrameworkLayer,
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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")
|
||||
);
|
||||
};
|
||||
|
@ -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;
|
||||
|
34
src/MCT.js
34
src/MCT.js
@ -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;
|
||||
|
@ -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 + "/");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -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));
|
||||
|
@ -28,6 +28,10 @@ export default class Editor extends EventEmitter {
|
||||
super();
|
||||
this.editing = false;
|
||||
this.openmct = openmct;
|
||||
|
||||
openmct.once('destroy', () => {
|
||||
this.removeAllListeners();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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',
|
||||
|
@ -117,6 +117,10 @@ export default function NotebookPlugin() {
|
||||
key: 'notebook-snapshot-indicator'
|
||||
};
|
||||
|
||||
openmct.once('destroy', () => {
|
||||
snapshotContainer.destroy();
|
||||
});
|
||||
|
||||
openmct.indicators.add(indicator);
|
||||
|
||||
openmct.objectViews.addProvider({
|
||||
|
@ -80,4 +80,8 @@ export default class SnapshotContainer extends EventEmitter {
|
||||
|
||||
return this.saveSnapshots(updatedSnapshots);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
delete SnapshotContainer.instance;
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -38,6 +38,10 @@ define(
|
||||
|
||||
this.openmct = openmct;
|
||||
this.selected = [];
|
||||
|
||||
this.openmct.once('destroy', () => {
|
||||
this.removeAllListeners();
|
||||
});
|
||||
}
|
||||
|
||||
Selection.prototype = Object.create(EventEmitter.prototype);
|
||||
|
@ -253,7 +253,7 @@ export default {
|
||||
}
|
||||
|
||||
document.removeEventListener('click', this.closeViewAndSaveMenu);
|
||||
window.removeEventListener('click', this.promptUserbeforeNavigatingAway);
|
||||
window.removeEventListener('beforeunload', this.promptUserbeforeNavigatingAway);
|
||||
},
|
||||
methods: {
|
||||
toggleSaveMenu() {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
66
src/utils/testing/MemoryLeaksReporter.js
Normal file
66
src/utils/testing/MemoryLeaksReporter.js
Normal 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();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user