@hydranium/glsp-client-theia 1.0.0-next.32 → 1.0.0-next.321
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -98
- package/lib/browser/client-contribution.d.ts +87 -25
- package/lib/browser/client-contribution.d.ts.map +1 -1
- package/lib/browser/client-contribution.js +233 -53
- package/lib/browser/client-contribution.js.map +1 -1
- package/lib/browser/diagram-only-marker-manager.d.ts.map +1 -1
- package/lib/browser/diagram-only-marker-manager.js.map +1 -1
- package/lib/browser/diagram-widget.d.ts +43 -25
- package/lib/browser/diagram-widget.d.ts.map +1 -1
- package/lib/browser/diagram-widget.js +76 -26
- package/lib/browser/diagram-widget.js.map +1 -1
- package/lib/browser/glsp-client-theia-module.d.ts +12 -5
- package/lib/browser/glsp-client-theia-module.d.ts.map +1 -1
- package/lib/browser/glsp-client-theia-module.js +27 -12
- package/lib/browser/glsp-client-theia-module.js.map +1 -1
- package/lib/browser/glsp-diagram-manager.d.ts +40 -1
- package/lib/browser/glsp-diagram-manager.d.ts.map +1 -1
- package/lib/browser/glsp-diagram-manager.js +100 -0
- package/lib/browser/glsp-diagram-manager.js.map +1 -1
- package/lib/browser/glsp-message-service.d.ts.map +1 -1
- package/lib/browser/glsp-message-service.js.map +1 -1
- package/lib/browser/glsp-saveable.d.ts +67 -0
- package/lib/browser/glsp-saveable.d.ts.map +1 -0
- package/lib/browser/glsp-saveable.js +110 -0
- package/lib/browser/glsp-saveable.js.map +1 -0
- package/lib/browser/glsp-theia-frontend-module.d.ts.map +1 -1
- package/lib/browser/glsp-theia-frontend-module.js +4 -1
- package/lib/browser/glsp-theia-frontend-module.js.map +1 -1
- package/lib/browser/hydranium-glsp-diagram-configuration.d.ts +3 -1
- package/lib/browser/hydranium-glsp-diagram-configuration.d.ts.map +1 -1
- package/lib/browser/hydranium-glsp-diagram-configuration.js +3 -1
- package/lib/browser/hydranium-glsp-diagram-configuration.js.map +1 -1
- package/lib/browser/index.d.ts +4 -3
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +7 -5
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/theia-diagram-loader.d.ts +25 -0
- package/lib/browser/theia-diagram-loader.d.ts.map +1 -0
- package/lib/browser/theia-diagram-loader.js +42 -0
- package/lib/browser/theia-diagram-loader.js.map +1 -0
- package/lib/browser/window-session.d.ts +57 -0
- package/lib/browser/window-session.d.ts.map +1 -0
- package/lib/browser/window-session.js +102 -0
- package/lib/browser/window-session.js.map +1 -0
- package/lib/node/connection-container-module.js.map +1 -1
- package/lib/node/glsp-server-connection-handler.d.ts +11 -20
- package/lib/node/glsp-server-connection-handler.d.ts.map +1 -1
- package/lib/node/glsp-server-connection-handler.js +12 -15
- package/lib/node/glsp-server-connection-handler.js.map +1 -1
- package/package.json +37 -46
- package/src/browser/client-contribution.ts +254 -55
- package/src/browser/diagram-widget.ts +80 -28
- package/src/browser/glsp-client-theia-module.ts +34 -13
- package/src/browser/glsp-diagram-manager.ts +112 -3
- package/src/browser/glsp-saveable.ts +111 -0
- package/src/browser/glsp-theia-frontend-module.ts +4 -1
- package/src/browser/hydranium-glsp-diagram-configuration.ts +3 -1
- package/src/browser/index.ts +12 -5
- package/src/browser/theia-diagram-loader.ts +31 -0
- package/src/browser/window-session.ts +114 -0
- package/src/node/glsp-server-connection-handler.ts +12 -24
- package/style/diagram-loading.css +2 -5
- package/lib/browser/action-dispatcher.d.ts +0 -85
- package/lib/browser/action-dispatcher.d.ts.map +0 -1
- package/lib/browser/action-dispatcher.js +0 -238
- package/lib/browser/action-dispatcher.js.map +0 -1
- package/lib/browser/diagram-loader.d.ts +0 -123
- package/lib/browser/diagram-loader.d.ts.map +0 -1
- package/lib/browser/diagram-loader.js +0 -153
- package/lib/browser/diagram-loader.js.map +0 -1
- package/lib/browser/hidden-bounds-updater.d.ts +0 -122
- package/lib/browser/hidden-bounds-updater.d.ts.map +0 -1
- package/lib/browser/hidden-bounds-updater.js +0 -207
- package/lib/browser/hidden-bounds-updater.js.map +0 -1
- package/lib/testing/bind-recorder.d.ts +0 -67
- package/lib/testing/bind-recorder.d.ts.map +0 -1
- package/lib/testing/bind-recorder.js +0 -72
- package/lib/testing/bind-recorder.js.map +0 -1
- package/lib/testing/index.d.ts +0 -10
- package/lib/testing/index.d.ts.map +0 -1
- package/lib/testing/index.js +0 -30
- package/lib/testing/index.js.map +0 -1
- package/src/browser/action-dispatcher.ts +0 -257
- package/src/browser/diagram-loader.ts +0 -173
- package/src/browser/hidden-bounds-updater.ts +0 -212
- package/src/testing/bind-recorder.ts +0 -126
- package/src/testing/index.ts +0 -15
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
/********************************************************************************
|
|
2
|
-
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
-
*
|
|
4
|
-
* This program and the accompanying materials are made available under the
|
|
5
|
-
* terms of the MIT License which is available in the project root.
|
|
6
|
-
*
|
|
7
|
-
* SPDX-License-Identifier: MIT
|
|
8
|
-
********************************************************************************/
|
|
9
|
-
import { DiagramLoader, type DiagramLoadingOptions } from '@eclipse-glsp/client';
|
|
10
|
-
import { ChannelLogger } from '@hydranium/client-theia/lib/browser';
|
|
11
|
-
import { Deferred } from '@hydranium/protocol';
|
|
12
|
-
/**
|
|
13
|
-
* How a diagram load ended. A discriminated union rather than a boolean or a
|
|
14
|
-
* string: a consumer showing a pending indicator has to distinguish "not settled
|
|
15
|
-
* yet" (`undefined`) from either terminal state, and the failed arm has to carry
|
|
16
|
-
* enough for that consumer to decide whether *it* is now the only thing that can
|
|
17
|
-
* report the failure — see {@link DiagramLoadFailure.surfaced}.
|
|
18
|
-
*/
|
|
19
|
-
export type DiagramLoadOutcome = DiagramLoadSuccess | DiagramLoadFailure;
|
|
20
|
-
export interface DiagramLoadSuccess {
|
|
21
|
-
readonly status: 'loaded';
|
|
22
|
-
}
|
|
23
|
-
export interface DiagramLoadFailure {
|
|
24
|
-
readonly status: 'failed';
|
|
25
|
-
/** The thrown value, verbatim. `unknown` because a rejection can be anything. */
|
|
26
|
-
readonly error: unknown;
|
|
27
|
-
/**
|
|
28
|
-
* Whether the `severity: 'ERROR'` {@link StatusAction} reached the action
|
|
29
|
-
* dispatcher — i.e. whether GLSP's `StatusOverlay` is now displaying this
|
|
30
|
-
* failure.
|
|
31
|
-
*
|
|
32
|
-
* `false` means the report itself failed, which happens when the action
|
|
33
|
-
* dispatcher is the thing that could not initialize. A consumer that covers
|
|
34
|
-
* the canvas must then render the failure itself: it is the only surface
|
|
35
|
-
* left, and removing its overlay would leave a blank diagram whose only
|
|
36
|
-
* explanation is a line in the Output channel — the exact failure mode this
|
|
37
|
-
* loader exists to prevent.
|
|
38
|
-
*/
|
|
39
|
-
readonly surfaced: boolean;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Diagram loader that never lets a load failure vanish.
|
|
43
|
-
*
|
|
44
|
-
* `DiagramLoader.load()` orchestrates the full diagram-init path — action
|
|
45
|
-
* dispatcher init, GLSP-client connect + server `initialize`, the first
|
|
46
|
-
* `RequestModelAction`, and the model-initialization constraint. Of these only
|
|
47
|
-
* the `IDiagramStartup` hooks are wrapped by the base loader (it logs them to
|
|
48
|
-
* `console.error`); the dispatcher-init / connection / request-model steps are
|
|
49
|
-
* not. The widget that drives loading
|
|
50
|
-
* (`@eclipse-glsp/theia-integration`'s `GLSPDiagramWidget.onAfterAttach`)
|
|
51
|
-
* calls `load()` *without awaiting or catching it*, so any rejection becomes an
|
|
52
|
-
* uncaught promise rejection visible only in the browser devtools console —
|
|
53
|
-
* nothing reaches the e2e output, the server log, or a Theia log sink, and the
|
|
54
|
-
* diagram just stays blank.
|
|
55
|
-
*
|
|
56
|
-
* This subclass closes that gap: it catches every load failure, routes it to
|
|
57
|
-
* the framework Output channel (the same {@link ChannelLogger} sink the server
|
|
58
|
-
* log and action traffic share, so it is discoverable where a developer already
|
|
59
|
-
* looks), and surfaces a persistent error to the user via a `severity: 'ERROR'`
|
|
60
|
-
* {@link StatusAction} on the diagram's status overlay. It deliberately does
|
|
61
|
-
* **not** rethrow — the caller drops the promise, so rethrowing would only
|
|
62
|
-
* reproduce the uncaught rejection this exists to prevent.
|
|
63
|
-
*
|
|
64
|
-
* It also publishes the load's terminal state ({@link loadOutcome} /
|
|
65
|
-
* {@link onceLoadSettled}) so a pending indicator has one authority to key on.
|
|
66
|
-
* `HydraniumGlspDiagramWidget` uses it to cover the canvas while loading; see
|
|
67
|
-
* {@link settle} for why the signal cannot be derived from the error
|
|
68
|
-
* `StatusAction` instead.
|
|
69
|
-
*
|
|
70
|
-
* Bound by `createGlspClientTheiaModule` via `rebind(DiagramLoader)`.
|
|
71
|
-
*/
|
|
72
|
-
export declare class HydraniumDiagramLoader extends DiagramLoader {
|
|
73
|
-
protected readonly channel: ChannelLogger;
|
|
74
|
-
protected readonly settled: Deferred<DiagramLoadOutcome>;
|
|
75
|
-
protected outcome?: DiagramLoadOutcome;
|
|
76
|
-
/** Terminal state of the load, or `undefined` while it is still in flight.
|
|
77
|
-
* The synchronous companion of {@link onceLoadSettled}, for a consumer that
|
|
78
|
-
* must decide something in the same tick (e.g. whether to show an indicator
|
|
79
|
-
* at all when re-attaching an already-loaded diagram). */
|
|
80
|
-
get loadOutcome(): DiagramLoadOutcome | undefined;
|
|
81
|
-
/** Resolves once the load reaches a terminal state — on success **and** on
|
|
82
|
-
* failure, so a caller awaiting it cannot hang. Never rejects. */
|
|
83
|
-
onceLoadSettled(): Promise<DiagramLoadOutcome>;
|
|
84
|
-
load(options?: DiagramLoadingOptions): Promise<void>;
|
|
85
|
-
/**
|
|
86
|
-
* Record the terminal state and release {@link onceLoadSettled}. Idempotent —
|
|
87
|
-
* the first outcome wins, so a reload cannot flip a settled indicator.
|
|
88
|
-
*
|
|
89
|
-
* This runs unconditionally after {@link reportLoadFailure}, *including* when
|
|
90
|
-
* the status dispatch inside it threw. That is the load-bearing property: when
|
|
91
|
-
* the action dispatcher is itself the thing that failed to initialize — the
|
|
92
|
-
* exact failure this class exists for — no `StatusAction` ever lands, so a
|
|
93
|
-
* consumer observing actions would wait forever. Settling here means a pending
|
|
94
|
-
* indicator always comes down, and `surfaced: false` tells that consumer it is
|
|
95
|
-
* now the only thing that can report the failure.
|
|
96
|
-
*/
|
|
97
|
-
protected settle(outcome: DiagramLoadOutcome): void;
|
|
98
|
-
/**
|
|
99
|
-
* Route a diagram-load failure to the Output channel and the status overlay.
|
|
100
|
-
* The status dispatch is itself guarded: when the action dispatcher is the
|
|
101
|
-
* thing that failed to initialize, dispatching may throw too, and a failure
|
|
102
|
-
* to *report* the failure must not re-escape as an uncaught rejection.
|
|
103
|
-
*
|
|
104
|
-
* @returns whether the `StatusAction` reached the dispatcher — i.e. whether the
|
|
105
|
-
* user can see this failure on the diagram. The channel line always happens, so
|
|
106
|
-
* the return value is specifically about the *user-visible* report; a `false`
|
|
107
|
-
* makes {@link DiagramLoadFailure.surfaced} false and hands the job to whoever
|
|
108
|
-
* is covering the canvas.
|
|
109
|
-
*/
|
|
110
|
-
protected reportLoadFailure(err: unknown): Promise<boolean>;
|
|
111
|
-
/**
|
|
112
|
-
* The sentence a failed load is reported with, on every surface that reports
|
|
113
|
-
* it, and the only seam an adopter rewords or localizes it at. Public
|
|
114
|
-
* because the canvas overlay is one of those surfaces and lives in another
|
|
115
|
-
* class: it renders this failure exactly when the `StatusAction` did not
|
|
116
|
-
* land, so a second copy of the sentence there could only ever drift unseen.
|
|
117
|
-
*/
|
|
118
|
-
loadFailureLabel(err: unknown): string;
|
|
119
|
-
/** Render a thrown value as a message. Shared so the channel line, the status
|
|
120
|
-
* overlay and any consumer rendering {@link DiagramLoadFailure.error} agree. */
|
|
121
|
-
protected formatError(err: unknown): string;
|
|
122
|
-
}
|
|
123
|
-
//# sourceMappingURL=diagram-loader.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"diagram-loader.d.ts","sourceRoot":"","sources":["../../src/browser/diagram-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,aAAa,EAAE,KAAK,qBAAqB,EAAgB,MAAM,sBAAsB,CAAC;AAC/F,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAG/C;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,kBAAkB,GAAG,kBAAkB,CAAC;AAEzE,MAAM,WAAW,kBAAkB;IAChC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IAChC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBACa,sBAAuB,SAAQ,aAAa;IAC/B,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAG,aAAa,CAAC;IAElE,SAAS,CAAC,QAAQ,CAAC,OAAO,+BAAsC;IAChE,SAAS,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAEvC;;;+DAG2D;IAC3D,IAAI,WAAW,IAAI,kBAAkB,GAAG,SAAS,CAEhD;IAED;uEACmE;IACnE,eAAe,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAI/B,IAAI,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAcnE;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAQnD;;;;;;;;;;;OAWG;cACa,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAYjE;;;;;;OAMG;IACH,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM;IAItC;qFACiF;IACjF,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM;CAG7C"}
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/********************************************************************************
|
|
3
|
-
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
-
*
|
|
5
|
-
* This program and the accompanying materials are made available under the
|
|
6
|
-
* terms of the MIT License which is available in the project root.
|
|
7
|
-
*
|
|
8
|
-
* SPDX-License-Identifier: MIT
|
|
9
|
-
********************************************************************************/
|
|
10
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
11
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
12
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
13
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
14
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
15
|
-
};
|
|
16
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
17
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
18
|
-
};
|
|
19
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.HydraniumDiagramLoader = void 0;
|
|
21
|
-
const client_1 = require("@eclipse-glsp/client");
|
|
22
|
-
const browser_1 = require("@hydranium/client-theia/lib/browser");
|
|
23
|
-
const protocol_1 = require("@hydranium/protocol");
|
|
24
|
-
const inversify_1 = require("@theia/core/shared/inversify");
|
|
25
|
-
/**
|
|
26
|
-
* Diagram loader that never lets a load failure vanish.
|
|
27
|
-
*
|
|
28
|
-
* `DiagramLoader.load()` orchestrates the full diagram-init path — action
|
|
29
|
-
* dispatcher init, GLSP-client connect + server `initialize`, the first
|
|
30
|
-
* `RequestModelAction`, and the model-initialization constraint. Of these only
|
|
31
|
-
* the `IDiagramStartup` hooks are wrapped by the base loader (it logs them to
|
|
32
|
-
* `console.error`); the dispatcher-init / connection / request-model steps are
|
|
33
|
-
* not. The widget that drives loading
|
|
34
|
-
* (`@eclipse-glsp/theia-integration`'s `GLSPDiagramWidget.onAfterAttach`)
|
|
35
|
-
* calls `load()` *without awaiting or catching it*, so any rejection becomes an
|
|
36
|
-
* uncaught promise rejection visible only in the browser devtools console —
|
|
37
|
-
* nothing reaches the e2e output, the server log, or a Theia log sink, and the
|
|
38
|
-
* diagram just stays blank.
|
|
39
|
-
*
|
|
40
|
-
* This subclass closes that gap: it catches every load failure, routes it to
|
|
41
|
-
* the framework Output channel (the same {@link ChannelLogger} sink the server
|
|
42
|
-
* log and action traffic share, so it is discoverable where a developer already
|
|
43
|
-
* looks), and surfaces a persistent error to the user via a `severity: 'ERROR'`
|
|
44
|
-
* {@link StatusAction} on the diagram's status overlay. It deliberately does
|
|
45
|
-
* **not** rethrow — the caller drops the promise, so rethrowing would only
|
|
46
|
-
* reproduce the uncaught rejection this exists to prevent.
|
|
47
|
-
*
|
|
48
|
-
* It also publishes the load's terminal state ({@link loadOutcome} /
|
|
49
|
-
* {@link onceLoadSettled}) so a pending indicator has one authority to key on.
|
|
50
|
-
* `HydraniumGlspDiagramWidget` uses it to cover the canvas while loading; see
|
|
51
|
-
* {@link settle} for why the signal cannot be derived from the error
|
|
52
|
-
* `StatusAction` instead.
|
|
53
|
-
*
|
|
54
|
-
* Bound by `createGlspClientTheiaModule` via `rebind(DiagramLoader)`.
|
|
55
|
-
*/
|
|
56
|
-
let HydraniumDiagramLoader = class HydraniumDiagramLoader extends client_1.DiagramLoader {
|
|
57
|
-
channel;
|
|
58
|
-
settled = new protocol_1.Deferred();
|
|
59
|
-
outcome;
|
|
60
|
-
/** Terminal state of the load, or `undefined` while it is still in flight.
|
|
61
|
-
* The synchronous companion of {@link onceLoadSettled}, for a consumer that
|
|
62
|
-
* must decide something in the same tick (e.g. whether to show an indicator
|
|
63
|
-
* at all when re-attaching an already-loaded diagram). */
|
|
64
|
-
get loadOutcome() {
|
|
65
|
-
return this.outcome;
|
|
66
|
-
}
|
|
67
|
-
/** Resolves once the load reaches a terminal state — on success **and** on
|
|
68
|
-
* failure, so a caller awaiting it cannot hang. Never rejects. */
|
|
69
|
-
onceLoadSettled() {
|
|
70
|
-
return this.settled.promise;
|
|
71
|
-
}
|
|
72
|
-
async load(options) {
|
|
73
|
-
try {
|
|
74
|
-
await super.load(options);
|
|
75
|
-
this.settle({ status: 'loaded' });
|
|
76
|
-
}
|
|
77
|
-
catch (err) {
|
|
78
|
-
// Report first, settle second, and carry whether the report landed: a
|
|
79
|
-
// consumer that uncovers the canvas on settle then finds the error
|
|
80
|
-
// already on the status overlay — or learns that it has to render the
|
|
81
|
-
// failure itself because nothing else can.
|
|
82
|
-
const surfaced = await this.reportLoadFailure(err);
|
|
83
|
-
this.settle({ status: 'failed', error: err, surfaced });
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Record the terminal state and release {@link onceLoadSettled}. Idempotent —
|
|
88
|
-
* the first outcome wins, so a reload cannot flip a settled indicator.
|
|
89
|
-
*
|
|
90
|
-
* This runs unconditionally after {@link reportLoadFailure}, *including* when
|
|
91
|
-
* the status dispatch inside it threw. That is the load-bearing property: when
|
|
92
|
-
* the action dispatcher is itself the thing that failed to initialize — the
|
|
93
|
-
* exact failure this class exists for — no `StatusAction` ever lands, so a
|
|
94
|
-
* consumer observing actions would wait forever. Settling here means a pending
|
|
95
|
-
* indicator always comes down, and `surfaced: false` tells that consumer it is
|
|
96
|
-
* now the only thing that can report the failure.
|
|
97
|
-
*/
|
|
98
|
-
settle(outcome) {
|
|
99
|
-
if (this.outcome !== undefined) {
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
this.outcome = outcome;
|
|
103
|
-
this.settled.resolve(outcome);
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Route a diagram-load failure to the Output channel and the status overlay.
|
|
107
|
-
* The status dispatch is itself guarded: when the action dispatcher is the
|
|
108
|
-
* thing that failed to initialize, dispatching may throw too, and a failure
|
|
109
|
-
* to *report* the failure must not re-escape as an uncaught rejection.
|
|
110
|
-
*
|
|
111
|
-
* @returns whether the `StatusAction` reached the dispatcher — i.e. whether the
|
|
112
|
-
* user can see this failure on the diagram. The channel line always happens, so
|
|
113
|
-
* the return value is specifically about the *user-visible* report; a `false`
|
|
114
|
-
* makes {@link DiagramLoadFailure.surfaced} false and hands the job to whoever
|
|
115
|
-
* is covering the canvas.
|
|
116
|
-
*/
|
|
117
|
-
async reportLoadFailure(err) {
|
|
118
|
-
const label = this.loadFailureLabel(err);
|
|
119
|
-
this.channel.error(label, err);
|
|
120
|
-
try {
|
|
121
|
-
await this.actionDispatcher.dispatch(client_1.StatusAction.create(label, { severity: 'ERROR' }));
|
|
122
|
-
return true;
|
|
123
|
-
}
|
|
124
|
-
catch (statusErr) {
|
|
125
|
-
this.channel.error('Failed to surface the diagram-load failure on the status overlay', statusErr);
|
|
126
|
-
return false;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* The sentence a failed load is reported with, on every surface that reports
|
|
131
|
-
* it, and the only seam an adopter rewords or localizes it at. Public
|
|
132
|
-
* because the canvas overlay is one of those surfaces and lives in another
|
|
133
|
-
* class: it renders this failure exactly when the `StatusAction` did not
|
|
134
|
-
* land, so a second copy of the sentence there could only ever drift unseen.
|
|
135
|
-
*/
|
|
136
|
-
loadFailureLabel(err) {
|
|
137
|
-
return `Diagram failed to load: ${this.formatError(err)}`;
|
|
138
|
-
}
|
|
139
|
-
/** Render a thrown value as a message. Shared so the channel line, the status
|
|
140
|
-
* overlay and any consumer rendering {@link DiagramLoadFailure.error} agree. */
|
|
141
|
-
formatError(err) {
|
|
142
|
-
return err instanceof Error ? err.message : String(err);
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
exports.HydraniumDiagramLoader = HydraniumDiagramLoader;
|
|
146
|
-
__decorate([
|
|
147
|
-
(0, inversify_1.inject)(browser_1.ChannelLogger),
|
|
148
|
-
__metadata("design:type", browser_1.ChannelLogger)
|
|
149
|
-
], HydraniumDiagramLoader.prototype, "channel", void 0);
|
|
150
|
-
exports.HydraniumDiagramLoader = HydraniumDiagramLoader = __decorate([
|
|
151
|
-
(0, inversify_1.injectable)()
|
|
152
|
-
], HydraniumDiagramLoader);
|
|
153
|
-
//# sourceMappingURL=diagram-loader.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"diagram-loader.js","sourceRoot":"","sources":["../../src/browser/diagram-loader.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;AAElF,iDAA+F;AAC/F,iEAAoE;AACpE,kDAA+C;AAC/C,4DAAkE;AAkClE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEI,IAAM,sBAAsB,GAA5B,MAAM,sBAAuB,SAAQ,sBAAa;IACZ,OAAO,CAAiB;IAE/C,OAAO,GAAG,IAAI,mBAAQ,EAAsB,CAAC;IACtD,OAAO,CAAsB;IAEvC;;;+DAG2D;IAC3D,IAAI,WAAW;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC;IACvB,CAAC;IAED;uEACmE;IACnE,eAAe;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;IAC/B,CAAC;IAEQ,KAAK,CAAC,IAAI,CAAC,OAA+B;QAChD,IAAI,CAAC;YACF,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC1B,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACZ,sEAAsE;YACtE,mEAAmE;YACnE,sEAAsE;YACtE,2CAA2C;YAC3C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;YACnD,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3D,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;OAWG;IACO,MAAM,CAAC,OAA2B;QACzC,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO;QACV,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;IAED;;;;;;;;;;;OAWG;IACO,KAAK,CAAC,iBAAiB,CAAC,GAAY;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC/B,IAAI,CAAC;YACF,MAAM,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,qBAAY,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;YACxF,OAAO,IAAI,CAAC;QACf,CAAC;QAAC,OAAO,SAAS,EAAE,CAAC;YAClB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,kEAAkE,EAAE,SAAS,CAAC,CAAC;YAClG,OAAO,KAAK,CAAC;QAChB,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,gBAAgB,CAAC,GAAY;QAC1B,OAAO,2BAA2B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;IAC7D,CAAC;IAED;qFACiF;IACvE,WAAW,CAAC,GAAY;QAC/B,OAAO,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3D,CAAC;CACH,CAAA;AA9FY,wDAAsB;AACU;IAAzC,IAAA,kBAAM,EAAC,uBAAa,CAAC;8BAA8B,uBAAa;uDAAC;iCADxD,sBAAsB;IADlC,IAAA,sBAAU,GAAE;GACA,sBAAsB,CA8FlC"}
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
/********************************************************************************
|
|
2
|
-
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
-
*
|
|
4
|
-
* This program and the accompanying materials are made available under the
|
|
5
|
-
* terms of the MIT License which is available in the project root.
|
|
6
|
-
*
|
|
7
|
-
* SPDX-License-Identifier: MIT
|
|
8
|
-
********************************************************************************/
|
|
9
|
-
import { type Action, type ElementAndRoutingPoints, type GModelElement, type GRoutableElement, GLSPHiddenBoundsUpdater, RequestBoundsAction } from '@eclipse-glsp/client';
|
|
10
|
-
import { ChannelLogger } from '@hydranium/client-theia/lib/browser';
|
|
11
|
-
import { type Clock } from '@hydranium/protocol';
|
|
12
|
-
import { type VNode } from 'snabbdom';
|
|
13
|
-
/**
|
|
14
|
-
* Instruments sprotty's hidden-bounds pass and repairs degenerate routes before
|
|
15
|
-
* they go on the wire.
|
|
16
|
-
*
|
|
17
|
-
* **Why the framework owns this.** Every GLSP head runs the hidden-bounds pass on
|
|
18
|
-
* every model update, and it is the one client-side phase that scales with the
|
|
19
|
-
* *rendered element count* rather than the model size — labels, compartments and
|
|
20
|
-
* edge decorations expand a modest node count into orders of magnitude more DOM
|
|
21
|
-
* elements. Without a timing line there is no way to tell a slow measurement pass
|
|
22
|
-
* apart from slow edge routing or a slow server round trip; with one,
|
|
23
|
-
* `bounds-request` either exonerates the client in a sentence or names the
|
|
24
|
-
* dominant cost.
|
|
25
|
-
*
|
|
26
|
-
* Emits exactly one `trace` line per bounds request — `trace` because the
|
|
27
|
-
* frequency matches the per-action traffic `HydraniumGlspActionDispatcher` logs
|
|
28
|
-
* there (a bounds request is driven by those actions), so it belongs with them
|
|
29
|
-
* rather than above them. The line carries:
|
|
30
|
-
*
|
|
31
|
-
* - `server` / `local` — whether the request came from the server or from a
|
|
32
|
-
* client-local {@link LocalRequestBoundsAction}
|
|
33
|
-
* - `scope=<ids>` — the elements a scoped request named; absent when the request
|
|
34
|
-
* covers the whole diagram
|
|
35
|
-
* - `measured=N` — DOM elements whose bounds were read. Exceeds the scoped id
|
|
36
|
-
* count because the base class expands each requested element to its
|
|
37
|
-
* descendants
|
|
38
|
-
* - `getBBox=Nms` — {@link getBoundsFromDOM} **only**: the layout pass and the
|
|
39
|
-
* `ComputedBoundsAction` assembly stay outside it, so the number isolates raw
|
|
40
|
-
* measurement cost
|
|
41
|
-
*
|
|
42
|
-
* Composed from {@link Clock.measure} rather than `Tracer.time`, matching
|
|
43
|
-
* `HydraniumDocumentBuilder`'s phase instrumentation. `Tracer.time` is for "tell
|
|
44
|
-
* me when this is slow" and is deliberately silent on a fast success, which would
|
|
45
|
-
* drop the element count on every normal pass — and forcing it to emit costs a
|
|
46
|
-
* paired `[#N start]` line per request. This is a per-occurrence record, so it
|
|
47
|
-
* measures and composes its own line.
|
|
48
|
-
*
|
|
49
|
-
* Bound by `createGlspClientTheiaModule` via `rebind(GLSPHiddenBoundsUpdater)`.
|
|
50
|
-
*/
|
|
51
|
-
export declare class HydraniumHiddenBoundsUpdater extends GLSPHiddenBoundsUpdater {
|
|
52
|
-
protected readonly channel: ChannelLogger;
|
|
53
|
-
/** Not injected: the browser container binds no {@link Clock}, and this only
|
|
54
|
-
* measures — no logic is gated on time, so there is nothing to fake in
|
|
55
|
-
* production. Overridden in tests for a deterministic elapsed value. */
|
|
56
|
-
protected readonly clock: Clock;
|
|
57
|
-
/**
|
|
58
|
-
* Scope description for the in-flight request, read from the `cause` in
|
|
59
|
-
* {@link postUpdate} and consumed by {@link getBoundsFromDOM} — which the base
|
|
60
|
-
* class calls with no arguments, so the cause cannot be threaded through.
|
|
61
|
-
*/
|
|
62
|
-
protected currentScope?: string;
|
|
63
|
-
decorate(vnode: VNode, element: GModelElement): VNode;
|
|
64
|
-
/**
|
|
65
|
-
* Replace the routing entry the base class just pushed when it carries fewer
|
|
66
|
-
* than two points, which is not a valid route for any edge.
|
|
67
|
-
*
|
|
68
|
-
* `calcElementAndRoute` already guards the case where the registered router
|
|
69
|
-
* returns *nothing* — it falls back to source + own routing points + target.
|
|
70
|
-
* The hole is one step further in: `calcRoute` filters duplicate points at
|
|
71
|
-
* `Number.EPSILON`, so while obstacles still carry sprotty's unmeasured-bounds
|
|
72
|
-
* sentinel `(100, 100, -1, -1)` the source and target coincide and a valid
|
|
73
|
-
* two-point route collapses to a single point. That result is defined, so the
|
|
74
|
-
* upstream truthiness guard never fires and the single point ships.
|
|
75
|
-
*
|
|
76
|
-
* The substitute is deliberately upstream's own fallback shape rather than a
|
|
77
|
-
* new invention, so a repaired route is indistinguishable from a route the
|
|
78
|
-
* base class would have produced had it noticed. Only already-invalid payloads
|
|
79
|
-
* are touched, so a head with a working router is unaffected.
|
|
80
|
-
*/
|
|
81
|
-
protected repairLastRoute(element: GRoutableElement): void;
|
|
82
|
-
/** A route needs at least a start and an end point to describe an edge. */
|
|
83
|
-
protected hasValidRoute(route: ElementAndRoutingPoints): boolean;
|
|
84
|
-
/** Upstream's `calcElementAndRoute` no-router fallback: the element's own
|
|
85
|
-
* bendpoints framed by its source and target anchor positions. */
|
|
86
|
-
protected toSourceTargetRoute(element: GRoutableElement): ElementAndRoutingPoints;
|
|
87
|
-
protected getBoundsFromDOM(): void;
|
|
88
|
-
/** Format the per-request line. Override to change the wording. */
|
|
89
|
-
protected formatBoundsRequest(scope: string, measured: number, elapsedMs: number): string;
|
|
90
|
-
postUpdate(cause?: Action): void;
|
|
91
|
-
/**
|
|
92
|
-
* Scope facts for the log line: where the request came from, and which
|
|
93
|
-
* elements it asked for.
|
|
94
|
-
*
|
|
95
|
-
* Origin is read from {@link ServerAction}, the `__receivedFromServer` marker
|
|
96
|
-
* `GLSPModelSource` stamps on inbound actions, rather than from
|
|
97
|
-
* `LocalRequestBoundsAction.is`. The latter would answer the same today, but
|
|
98
|
-
* only incidentally: its `elementIDs` check is declared optional, so it is
|
|
99
|
-
* really just "a bounds request that did not come from the server". Keying on
|
|
100
|
-
* the marker states that directly, and keeps an *unscoped* local request from
|
|
101
|
-
* being mislabelled `server` if GLSP ever tightens that guard.
|
|
102
|
-
*/
|
|
103
|
-
protected formatCause(cause: Action): string;
|
|
104
|
-
/**
|
|
105
|
-
* Name the elements a scoped request asked for, or `undefined` when it covers
|
|
106
|
-
* the whole diagram.
|
|
107
|
-
*
|
|
108
|
-
* Deliberately the ids and not their count. A scoped request in practice names
|
|
109
|
-
* a single element, so a count is always `1` and says nothing, while the id
|
|
110
|
-
* says *which* element was re-measured — and it is the only part of the line
|
|
111
|
-
* that distinguishes one such request from the next. It also stops the line
|
|
112
|
-
* reading as a contradiction: `scope=node0, measured=6` is coherent (the base
|
|
113
|
-
* class expands a requested element to its descendants, so one id measures six
|
|
114
|
-
* DOM elements), where `scoped=1, measured=6` invites the reader to wonder
|
|
115
|
-
* which number is wrong.
|
|
116
|
-
*
|
|
117
|
-
* A request naming only the root is treated as unscoped: it measures
|
|
118
|
-
* everything, so the id adds nothing over the absence of a `scope` tag.
|
|
119
|
-
*/
|
|
120
|
-
protected formatScope(cause: RequestBoundsAction): string | undefined;
|
|
121
|
-
}
|
|
122
|
-
//# sourceMappingURL=hidden-bounds-updater.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hidden-bounds-updater.d.ts","sourceRoot":"","sources":["../../src/browser/hidden-bounds-updater.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EACJ,KAAK,MAAM,EACX,KAAK,uBAAuB,EAC5B,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,uBAAuB,EAGvB,mBAAmB,EAGrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,KAAK,KAAK,EAAe,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,UAAU,CAAC;AAOtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,qBACa,4BAA6B,SAAQ,uBAAuB;IAC/C,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAG,aAAa,CAAC;IAElE;;6EAEyE;IACzE,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAqB;IAEpD;;;;OAIG;IACH,SAAS,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAEvB,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,GAAG,KAAK;IAQ9D;;;;;;;;;;;;;;;;OAgBG;IACH,SAAS,CAAC,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAQ1D,2EAA2E;IAC3E,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO;IAIhE;uEACmE;IACnE,SAAS,CAAC,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,GAAG,uBAAuB;cAO9D,gBAAgB,IAAI,IAAI;IAa3C,mEAAmE;IACnE,SAAS,CAAC,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;IAIhF,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAazC;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAM5C;;;;;;;;;;;;;;;OAeG;IACH,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,mBAAmB,GAAG,MAAM,GAAG,SAAS;CAcvE"}
|
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/********************************************************************************
|
|
3
|
-
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
-
*
|
|
5
|
-
* This program and the accompanying materials are made available under the
|
|
6
|
-
* terms of the MIT License which is available in the project root.
|
|
7
|
-
*
|
|
8
|
-
* SPDX-License-Identifier: MIT
|
|
9
|
-
********************************************************************************/
|
|
10
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
11
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
12
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
13
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
14
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
15
|
-
};
|
|
16
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
17
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
18
|
-
};
|
|
19
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.HydraniumHiddenBoundsUpdater = void 0;
|
|
21
|
-
const client_1 = require("@eclipse-glsp/client");
|
|
22
|
-
const browser_1 = require("@hydranium/client-theia/lib/browser");
|
|
23
|
-
const protocol_1 = require("@hydranium/protocol");
|
|
24
|
-
const inversify_1 = require("@theia/core/shared/inversify");
|
|
25
|
-
/** How many scoped element ids the log line names before summarising the rest.
|
|
26
|
-
* A scoped request names one element in practice; the cap only stops a
|
|
27
|
-
* pathological caller from writing a thousand ids into the channel. */
|
|
28
|
-
const SCOPE_ID_CAP = 3;
|
|
29
|
-
/**
|
|
30
|
-
* Instruments sprotty's hidden-bounds pass and repairs degenerate routes before
|
|
31
|
-
* they go on the wire.
|
|
32
|
-
*
|
|
33
|
-
* **Why the framework owns this.** Every GLSP head runs the hidden-bounds pass on
|
|
34
|
-
* every model update, and it is the one client-side phase that scales with the
|
|
35
|
-
* *rendered element count* rather than the model size — labels, compartments and
|
|
36
|
-
* edge decorations expand a modest node count into orders of magnitude more DOM
|
|
37
|
-
* elements. Without a timing line there is no way to tell a slow measurement pass
|
|
38
|
-
* apart from slow edge routing or a slow server round trip; with one,
|
|
39
|
-
* `bounds-request` either exonerates the client in a sentence or names the
|
|
40
|
-
* dominant cost.
|
|
41
|
-
*
|
|
42
|
-
* Emits exactly one `trace` line per bounds request — `trace` because the
|
|
43
|
-
* frequency matches the per-action traffic `HydraniumGlspActionDispatcher` logs
|
|
44
|
-
* there (a bounds request is driven by those actions), so it belongs with them
|
|
45
|
-
* rather than above them. The line carries:
|
|
46
|
-
*
|
|
47
|
-
* - `server` / `local` — whether the request came from the server or from a
|
|
48
|
-
* client-local {@link LocalRequestBoundsAction}
|
|
49
|
-
* - `scope=<ids>` — the elements a scoped request named; absent when the request
|
|
50
|
-
* covers the whole diagram
|
|
51
|
-
* - `measured=N` — DOM elements whose bounds were read. Exceeds the scoped id
|
|
52
|
-
* count because the base class expands each requested element to its
|
|
53
|
-
* descendants
|
|
54
|
-
* - `getBBox=Nms` — {@link getBoundsFromDOM} **only**: the layout pass and the
|
|
55
|
-
* `ComputedBoundsAction` assembly stay outside it, so the number isolates raw
|
|
56
|
-
* measurement cost
|
|
57
|
-
*
|
|
58
|
-
* Composed from {@link Clock.measure} rather than `Tracer.time`, matching
|
|
59
|
-
* `HydraniumDocumentBuilder`'s phase instrumentation. `Tracer.time` is for "tell
|
|
60
|
-
* me when this is slow" and is deliberately silent on a fast success, which would
|
|
61
|
-
* drop the element count on every normal pass — and forcing it to emit costs a
|
|
62
|
-
* paired `[#N start]` line per request. This is a per-occurrence record, so it
|
|
63
|
-
* measures and composes its own line.
|
|
64
|
-
*
|
|
65
|
-
* Bound by `createGlspClientTheiaModule` via `rebind(GLSPHiddenBoundsUpdater)`.
|
|
66
|
-
*/
|
|
67
|
-
let HydraniumHiddenBoundsUpdater = class HydraniumHiddenBoundsUpdater extends client_1.GLSPHiddenBoundsUpdater {
|
|
68
|
-
channel;
|
|
69
|
-
/** Not injected: the browser container binds no {@link Clock}, and this only
|
|
70
|
-
* measures — no logic is gated on time, so there is nothing to fake in
|
|
71
|
-
* production. Overridden in tests for a deterministic elapsed value. */
|
|
72
|
-
clock = new protocol_1.SystemClock();
|
|
73
|
-
/**
|
|
74
|
-
* Scope description for the in-flight request, read from the `cause` in
|
|
75
|
-
* {@link postUpdate} and consumed by {@link getBoundsFromDOM} — which the base
|
|
76
|
-
* class calls with no arguments, so the cause cannot be threaded through.
|
|
77
|
-
*/
|
|
78
|
-
currentScope;
|
|
79
|
-
decorate(vnode, element) {
|
|
80
|
-
super.decorate(vnode, element);
|
|
81
|
-
if ((0, client_1.isRoutable)(element)) {
|
|
82
|
-
this.repairLastRoute(element);
|
|
83
|
-
}
|
|
84
|
-
return vnode;
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Replace the routing entry the base class just pushed when it carries fewer
|
|
88
|
-
* than two points, which is not a valid route for any edge.
|
|
89
|
-
*
|
|
90
|
-
* `calcElementAndRoute` already guards the case where the registered router
|
|
91
|
-
* returns *nothing* — it falls back to source + own routing points + target.
|
|
92
|
-
* The hole is one step further in: `calcRoute` filters duplicate points at
|
|
93
|
-
* `Number.EPSILON`, so while obstacles still carry sprotty's unmeasured-bounds
|
|
94
|
-
* sentinel `(100, 100, -1, -1)` the source and target coincide and a valid
|
|
95
|
-
* two-point route collapses to a single point. That result is defined, so the
|
|
96
|
-
* upstream truthiness guard never fires and the single point ships.
|
|
97
|
-
*
|
|
98
|
-
* The substitute is deliberately upstream's own fallback shape rather than a
|
|
99
|
-
* new invention, so a repaired route is indistinguishable from a route the
|
|
100
|
-
* base class would have produced had it noticed. Only already-invalid payloads
|
|
101
|
-
* are touched, so a head with a working router is unaffected.
|
|
102
|
-
*/
|
|
103
|
-
repairLastRoute(element) {
|
|
104
|
-
const addedRoute = this.element2route.pop();
|
|
105
|
-
if (addedRoute === undefined) {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
this.element2route.push(this.hasValidRoute(addedRoute) ? addedRoute : this.toSourceTargetRoute(element));
|
|
109
|
-
}
|
|
110
|
-
/** A route needs at least a start and an end point to describe an edge. */
|
|
111
|
-
hasValidRoute(route) {
|
|
112
|
-
return route.newRoutingPoints !== undefined && route.newRoutingPoints.length >= 2;
|
|
113
|
-
}
|
|
114
|
-
/** Upstream's `calcElementAndRoute` no-router fallback: the element's own
|
|
115
|
-
* bendpoints framed by its source and target anchor positions. */
|
|
116
|
-
toSourceTargetRoute(element) {
|
|
117
|
-
return {
|
|
118
|
-
elementId: element.id,
|
|
119
|
-
newRoutingPoints: [element.source?.position ?? client_1.Point.ORIGIN, ...element.routingPoints, element.target?.position ?? client_1.Point.ORIGIN]
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
getBoundsFromDOM() {
|
|
123
|
-
if (this.currentScope === undefined) {
|
|
124
|
-
// Not inside an instrumented `postUpdate` (a subclass calling directly);
|
|
125
|
-
// with no cause there is nothing to attribute a measurement to.
|
|
126
|
-
super.getBoundsFromDOM();
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
// Read before the pass: the base class clears the map on its way out.
|
|
130
|
-
const measured = this.getElement2BoundsData().size;
|
|
131
|
-
const { elapsedMs } = this.clock.measure(() => super.getBoundsFromDOM());
|
|
132
|
-
this.channel.trace(this.formatBoundsRequest(this.currentScope, measured, elapsedMs));
|
|
133
|
-
}
|
|
134
|
-
/** Format the per-request line. Override to change the wording. */
|
|
135
|
-
formatBoundsRequest(scope, measured, elapsedMs) {
|
|
136
|
-
return `bounds-request[${scope}] measured=${measured} getBBox=${elapsedMs.toFixed(0)}ms`;
|
|
137
|
-
}
|
|
138
|
-
postUpdate(cause) {
|
|
139
|
-
if (cause?.kind !== client_1.RequestBoundsAction.KIND) {
|
|
140
|
-
super.postUpdate(cause);
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
this.currentScope = this.formatCause(cause);
|
|
144
|
-
try {
|
|
145
|
-
super.postUpdate(cause);
|
|
146
|
-
}
|
|
147
|
-
finally {
|
|
148
|
-
this.currentScope = undefined;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Scope facts for the log line: where the request came from, and which
|
|
153
|
-
* elements it asked for.
|
|
154
|
-
*
|
|
155
|
-
* Origin is read from {@link ServerAction}, the `__receivedFromServer` marker
|
|
156
|
-
* `GLSPModelSource` stamps on inbound actions, rather than from
|
|
157
|
-
* `LocalRequestBoundsAction.is`. The latter would answer the same today, but
|
|
158
|
-
* only incidentally: its `elementIDs` check is declared optional, so it is
|
|
159
|
-
* really just "a bounds request that did not come from the server". Keying on
|
|
160
|
-
* the marker states that directly, and keeps an *unscoped* local request from
|
|
161
|
-
* being mislabelled `server` if GLSP ever tightens that guard.
|
|
162
|
-
*/
|
|
163
|
-
formatCause(cause) {
|
|
164
|
-
const origin = client_1.ServerAction.is(cause) ? 'server' : 'local';
|
|
165
|
-
const scope = this.formatScope(cause);
|
|
166
|
-
return scope ? `${origin} scope=${scope}` : origin;
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Name the elements a scoped request asked for, or `undefined` when it covers
|
|
170
|
-
* the whole diagram.
|
|
171
|
-
*
|
|
172
|
-
* Deliberately the ids and not their count. A scoped request in practice names
|
|
173
|
-
* a single element, so a count is always `1` and says nothing, while the id
|
|
174
|
-
* says *which* element was re-measured — and it is the only part of the line
|
|
175
|
-
* that distinguishes one such request from the next. It also stops the line
|
|
176
|
-
* reading as a contradiction: `scope=node0, measured=6` is coherent (the base
|
|
177
|
-
* class expands a requested element to its descendants, so one id measures six
|
|
178
|
-
* DOM elements), where `scoped=1, measured=6` invites the reader to wonder
|
|
179
|
-
* which number is wrong.
|
|
180
|
-
*
|
|
181
|
-
* A request naming only the root is treated as unscoped: it measures
|
|
182
|
-
* everything, so the id adds nothing over the absence of a `scope` tag.
|
|
183
|
-
*/
|
|
184
|
-
formatScope(cause) {
|
|
185
|
-
const scopedIds = cause.elementIDs;
|
|
186
|
-
if (!scopedIds || scopedIds.length === 0) {
|
|
187
|
-
return undefined;
|
|
188
|
-
}
|
|
189
|
-
const named = scopedIds.filter(id => id !== cause.newRoot?.id);
|
|
190
|
-
if (named.length === 0) {
|
|
191
|
-
return undefined;
|
|
192
|
-
}
|
|
193
|
-
if (named.length > SCOPE_ID_CAP) {
|
|
194
|
-
return `${named.slice(0, SCOPE_ID_CAP).join(',')},+${named.length - SCOPE_ID_CAP} more`;
|
|
195
|
-
}
|
|
196
|
-
return named.join(',');
|
|
197
|
-
}
|
|
198
|
-
};
|
|
199
|
-
exports.HydraniumHiddenBoundsUpdater = HydraniumHiddenBoundsUpdater;
|
|
200
|
-
__decorate([
|
|
201
|
-
(0, inversify_1.inject)(browser_1.ChannelLogger),
|
|
202
|
-
__metadata("design:type", browser_1.ChannelLogger)
|
|
203
|
-
], HydraniumHiddenBoundsUpdater.prototype, "channel", void 0);
|
|
204
|
-
exports.HydraniumHiddenBoundsUpdater = HydraniumHiddenBoundsUpdater = __decorate([
|
|
205
|
-
(0, inversify_1.injectable)()
|
|
206
|
-
], HydraniumHiddenBoundsUpdater);
|
|
207
|
-
//# sourceMappingURL=hidden-bounds-updater.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hidden-bounds-updater.js","sourceRoot":"","sources":["../../src/browser/hidden-bounds-updater.ts"],"names":[],"mappings":"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"}
|