diff --git a/tensorboard/webapp/app_routing/location.ts b/tensorboard/webapp/app_routing/location.ts index 2111a4b972..ae5e717921 100644 --- a/tensorboard/webapp/app_routing/location.ts +++ b/tensorboard/webapp/app_routing/location.ts @@ -16,12 +16,7 @@ import {Injectable} from '@angular/core'; import {fromEvent, Observable} from 'rxjs'; import {map} from 'rxjs/operators'; import {createURLSearchParamsFromSerializableQueryParams} from './internal_utils'; -import { - Navigation, - NavigationFromHistory, - Route, - SerializableQueryParams, -} from './types'; +import {NavigationFromHistory, Route, SerializableQueryParams} from './types'; export interface LocationInterface { getHref(): string; diff --git a/tensorboard/webapp/widgets/line_chart_v2/lib/renderer/renderer_types.ts b/tensorboard/webapp/widgets/line_chart_v2/lib/renderer/renderer_types.ts index ea0dd7073a..e03acb6842 100644 --- a/tensorboard/webapp/widgets/line_chart_v2/lib/renderer/renderer_types.ts +++ b/tensorboard/webapp/widgets/line_chart_v2/lib/renderer/renderer_types.ts @@ -84,6 +84,12 @@ export interface ObjectRenderer { destroyObject(cachedValue: CacheValue): void; setUseDarkMode(useDarkMode: boolean): void; + + /** + * Disposes rendering context. After invocation, renderer should never be + * used. + */ + dispose(): void; } interface PaintOption { diff --git a/tensorboard/webapp/widgets/line_chart_v2/lib/renderer/svg_renderer.ts b/tensorboard/webapp/widgets/line_chart_v2/lib/renderer/svg_renderer.ts index d3648c10e5..96d8addc7a 100644 --- a/tensorboard/webapp/widgets/line_chart_v2/lib/renderer/svg_renderer.ts +++ b/tensorboard/webapp/widgets/line_chart_v2/lib/renderer/svg_renderer.ts @@ -270,4 +270,8 @@ export class SvgRenderer implements ObjectRenderer { data: vertices, }; } + + dispose() { + // noop. + } } diff --git a/tensorboard/webapp/widgets/line_chart_v2/lib/renderer/threejs_renderer.ts b/tensorboard/webapp/widgets/line_chart_v2/lib/renderer/threejs_renderer.ts index 99991b7115..ae76476a83 100644 --- a/tensorboard/webapp/widgets/line_chart_v2/lib/renderer/threejs_renderer.ts +++ b/tensorboard/webapp/widgets/line_chart_v2/lib/renderer/threejs_renderer.ts @@ -495,4 +495,8 @@ export class ThreeRenderer implements ObjectRenderer { flush() { this.renderer.render(this.scene, this.coordinator.getCamera()); } + + dispose() { + this.renderer.dispose(); + } } diff --git a/tensorboard/webapp/widgets/line_chart_v2/lib/utils.ts b/tensorboard/webapp/widgets/line_chart_v2/lib/utils.ts index cbda594d46..7e5fe819ad 100644 --- a/tensorboard/webapp/widgets/line_chart_v2/lib/utils.ts +++ b/tensorboard/webapp/widgets/line_chart_v2/lib/utils.ts @@ -22,10 +22,22 @@ export function convertRectToExtent(rect: Rect): Extent { }; } -const cachedIsWebGl2Supported = Boolean( - self.hasOwnProperty('document') && - document.createElement('canvas').getContext('webgl2') -); +let cachedIsWebGl2Supported = false; + +{ + if ( + self.hasOwnProperty('WebGL2RenderingContext') && + self.hasOwnProperty('document') + ) { + const canvas = document.createElement('canvas'); + + canvas.addEventListener('webglcontextcreationerror', () => { + cachedIsWebGl2Supported = false; + }); + const context = canvas.getContext('webgl2'); + cachedIsWebGl2Supported = Boolean(context); + } +} export function isWebGl2Supported(): boolean { return cachedIsWebGl2Supported; diff --git a/tensorboard/webapp/widgets/line_chart_v2/lib/worker/message_types.ts b/tensorboard/webapp/widgets/line_chart_v2/lib/worker/message_types.ts index f2037b774a..719ec0a25c 100644 --- a/tensorboard/webapp/widgets/line_chart_v2/lib/worker/message_types.ts +++ b/tensorboard/webapp/widgets/line_chart_v2/lib/worker/message_types.ts @@ -28,6 +28,7 @@ export enum HostToGuestEvent { INIT, DOM_RESIZED, DARK_MODE_UPDATED, + DISPOSED, } export interface InitMessage { @@ -73,8 +74,13 @@ export interface DarkModeUpdatedMessage { useDarkMode: boolean; } +export interface DisposeMessage { + type: HostToGuestEvent.DISPOSED; +} + export type HostToGuestMessage = | DarkModeUpdatedMessage + | DisposeMessage | ResizeMessage | ScaleUpdateMessage | SeriesMetadataChangedMessage diff --git a/tensorboard/webapp/widgets/line_chart_v2/lib/worker/worker_chart.ts b/tensorboard/webapp/widgets/line_chart_v2/lib/worker/worker_chart.ts index 6b34b35f84..f5898405bd 100644 --- a/tensorboard/webapp/widgets/line_chart_v2/lib/worker/worker_chart.ts +++ b/tensorboard/webapp/widgets/line_chart_v2/lib/worker/worker_chart.ts @@ -80,6 +80,7 @@ export class WorkerChart implements Chart { } dispose() { + this.sendMessage({type: HostToGuestEvent.DISPOSED}); this.workerInstance.free(); this.txMessagePort.close(); } diff --git a/tensorboard/webapp/widgets/line_chart_v2/lib/worker/worker_chart_bridge.ts b/tensorboard/webapp/widgets/line_chart_v2/lib/worker/worker_chart_bridge.ts index 0b00b93fe2..70788e0e5d 100644 --- a/tensorboard/webapp/widgets/line_chart_v2/lib/worker/worker_chart_bridge.ts +++ b/tensorboard/webapp/widgets/line_chart_v2/lib/worker/worker_chart_bridge.ts @@ -104,6 +104,10 @@ function createPortHandler(port: MessagePort, initMessage: InitMessage) { } break; } + case HostToGuestEvent.DISPOSED: { + lineChart.dispose(); + break; + } } }; }