@theia/debug 1.70.0-next.81 → 1.71.0-next.0
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/lib/browser/breakpoint/breakpoint-manager.d.ts +80 -45
- package/lib/browser/breakpoint/breakpoint-manager.d.ts.map +1 -1
- package/lib/browser/breakpoint/breakpoint-manager.js +553 -170
- package/lib/browser/breakpoint/breakpoint-manager.js.map +1 -1
- package/lib/browser/breakpoint/breakpoint-manager.spec.d.ts +2 -0
- package/lib/browser/breakpoint/breakpoint-manager.spec.d.ts.map +1 -0
- package/lib/browser/breakpoint/breakpoint-manager.spec.js +861 -0
- package/lib/browser/breakpoint/breakpoint-manager.spec.js.map +1 -0
- package/lib/browser/breakpoint/breakpoint-marker.d.ts +7 -10
- package/lib/browser/breakpoint/breakpoint-marker.d.ts.map +1 -1
- package/lib/browser/breakpoint/breakpoint-marker.js +14 -11
- package/lib/browser/breakpoint/breakpoint-marker.js.map +1 -1
- package/lib/browser/breakpoint/debug-data-breakpoint-actions.js +1 -1
- package/lib/browser/breakpoint/debug-data-breakpoint-actions.js.map +1 -1
- package/lib/browser/debug-frontend-application-contribution.d.ts +1 -2
- package/lib/browser/debug-frontend-application-contribution.d.ts.map +1 -1
- package/lib/browser/debug-frontend-application-contribution.js +13 -21
- package/lib/browser/debug-frontend-application-contribution.js.map +1 -1
- package/lib/browser/debug-frontend-module.d.ts.map +1 -1
- package/lib/browser/debug-frontend-module.js +3 -0
- package/lib/browser/debug-frontend-module.js.map +1 -1
- package/lib/browser/debug-session-manager.d.ts +8 -27
- package/lib/browser/debug-session-manager.d.ts.map +1 -1
- package/lib/browser/debug-session-manager.js +14 -132
- package/lib/browser/debug-session-manager.js.map +1 -1
- package/lib/browser/debug-session.d.ts +1 -21
- package/lib/browser/debug-session.d.ts.map +1 -1
- package/lib/browser/debug-session.js +72 -203
- package/lib/browser/debug-session.js.map +1 -1
- package/lib/browser/disassembly-view/disassembly-view-breakpoint-renderer.js +1 -1
- package/lib/browser/disassembly-view/disassembly-view-breakpoint-renderer.js.map +1 -1
- package/lib/browser/disassembly-view/disassembly-view-widget.d.ts.map +1 -1
- package/lib/browser/disassembly-view/disassembly-view-widget.js +17 -24
- package/lib/browser/disassembly-view/disassembly-view-widget.js.map +1 -1
- package/lib/browser/editor/debug-editor-model.d.ts +15 -5
- package/lib/browser/editor/debug-editor-model.d.ts.map +1 -1
- package/lib/browser/editor/debug-editor-model.js +56 -32
- package/lib/browser/editor/debug-editor-model.js.map +1 -1
- package/lib/browser/model/debug-breakpoint-opener.d.ts +14 -0
- package/lib/browser/model/debug-breakpoint-opener.d.ts.map +1 -0
- package/lib/browser/model/debug-breakpoint-opener.js +67 -0
- package/lib/browser/model/debug-breakpoint-opener.js.map +1 -0
- package/lib/browser/model/debug-breakpoint.d.ts +32 -13
- package/lib/browser/model/debug-breakpoint.d.ts.map +1 -1
- package/lib/browser/model/debug-breakpoint.js +76 -16
- package/lib/browser/model/debug-breakpoint.js.map +1 -1
- package/lib/browser/model/debug-data-breakpoint.d.ts +1 -0
- package/lib/browser/model/debug-data-breakpoint.d.ts.map +1 -1
- package/lib/browser/model/debug-data-breakpoint.js +6 -5
- package/lib/browser/model/debug-data-breakpoint.js.map +1 -1
- package/lib/browser/model/debug-function-breakpoint.d.ts +4 -1
- package/lib/browser/model/debug-function-breakpoint.d.ts.map +1 -1
- package/lib/browser/model/debug-function-breakpoint.js +20 -29
- package/lib/browser/model/debug-function-breakpoint.js.map +1 -1
- package/lib/browser/model/debug-instruction-breakpoint.d.ts +2 -1
- package/lib/browser/model/debug-instruction-breakpoint.d.ts.map +1 -1
- package/lib/browser/model/debug-instruction-breakpoint.js +8 -8
- package/lib/browser/model/debug-instruction-breakpoint.js.map +1 -1
- package/lib/browser/model/debug-source-breakpoint.d.ts +6 -15
- package/lib/browser/model/debug-source-breakpoint.d.ts.map +1 -1
- package/lib/browser/model/debug-source-breakpoint.js +16 -90
- package/lib/browser/model/debug-source-breakpoint.js.map +1 -1
- package/lib/browser/view/debug-breakpoints-source.d.ts +0 -2
- package/lib/browser/view/debug-breakpoints-source.d.ts.map +1 -1
- package/lib/browser/view/debug-breakpoints-source.js +2 -10
- package/lib/browser/view/debug-breakpoints-source.js.map +1 -1
- package/lib/browser/view/debug-breakpoints-widget.d.ts +2 -0
- package/lib/browser/view/debug-breakpoints-widget.d.ts.map +1 -1
- package/lib/browser/view/debug-breakpoints-widget.js +3 -0
- package/lib/browser/view/debug-breakpoints-widget.js.map +1 -1
- package/lib/browser/view/debug-exception-breakpoint.d.ts +18 -11
- package/lib/browser/view/debug-exception-breakpoint.d.ts.map +1 -1
- package/lib/browser/view/debug-exception-breakpoint.js +58 -24
- package/lib/browser/view/debug-exception-breakpoint.js.map +1 -1
- package/lib/browser/view/debug-view-model.d.ts +8 -4
- package/lib/browser/view/debug-view-model.d.ts.map +1 -1
- package/lib/browser/view/debug-view-model.js +16 -9
- package/lib/browser/view/debug-view-model.js.map +1 -1
- package/package.json +16 -16
- package/src/browser/breakpoint/breakpoint-manager.spec.ts +1106 -0
- package/src/browser/breakpoint/breakpoint-manager.ts +583 -194
- package/src/browser/breakpoint/breakpoint-marker.ts +21 -15
- package/src/browser/breakpoint/debug-data-breakpoint-actions.ts +1 -1
- package/src/browser/debug-frontend-application-contribution.ts +18 -23
- package/src/browser/debug-frontend-module.ts +5 -1
- package/src/browser/debug-session-manager.ts +15 -147
- package/src/browser/debug-session.tsx +71 -221
- package/src/browser/disassembly-view/disassembly-view-breakpoint-renderer.ts +1 -1
- package/src/browser/disassembly-view/disassembly-view-widget.ts +17 -23
- package/src/browser/editor/debug-editor-model.ts +58 -35
- package/src/browser/model/debug-breakpoint-opener.ts +51 -0
- package/src/browser/model/debug-breakpoint.tsx +101 -20
- package/src/browser/model/debug-data-breakpoint.tsx +8 -5
- package/src/browser/model/debug-function-breakpoint.tsx +18 -29
- package/src/browser/model/debug-instruction-breakpoint.tsx +10 -8
- package/src/browser/model/debug-source-breakpoint.tsx +23 -101
- package/src/browser/view/debug-breakpoints-source.tsx +2 -9
- package/src/browser/view/debug-breakpoints-widget.ts +6 -0
- package/src/browser/view/debug-exception-breakpoint.tsx +66 -27
- package/src/browser/view/debug-view-model.ts +21 -13
|
@@ -0,0 +1,861 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// *****************************************************************************
|
|
3
|
+
// Copyright (C) 2026 EclipseSource GmbH and others.
|
|
4
|
+
//
|
|
5
|
+
// This program and the accompanying materials are made available under the
|
|
6
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
7
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
8
|
+
//
|
|
9
|
+
// This Source Code may also be made available under the following Secondary
|
|
10
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
11
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
12
|
+
// with the GNU Classpath Exception which is available at
|
|
13
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
14
|
+
//
|
|
15
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
16
|
+
// *****************************************************************************
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
const frontend_application_config_provider_1 = require("@theia/core/lib/browser/frontend-application-config-provider");
|
|
19
|
+
const jsdom_1 = require("@theia/core/lib/browser/test/jsdom");
|
|
20
|
+
const disableJSDOM = (0, jsdom_1.enableJSDOM)();
|
|
21
|
+
frontend_application_config_provider_1.FrontendApplicationConfigProvider.set({});
|
|
22
|
+
const inversify_1 = require("@theia/core/shared/inversify");
|
|
23
|
+
const common_1 = require("@theia/core/lib/common");
|
|
24
|
+
const browser_1 = require("@theia/core/lib/browser");
|
|
25
|
+
const storage_service_1 = require("@theia/core/lib/browser/storage-service");
|
|
26
|
+
const uri_1 = require("@theia/core/lib/common/uri");
|
|
27
|
+
const file_service_1 = require("@theia/filesystem/lib/browser/file-service");
|
|
28
|
+
const files_1 = require("@theia/filesystem/lib/common/files");
|
|
29
|
+
const chai_1 = require("chai");
|
|
30
|
+
const breakpoint_manager_1 = require("./breakpoint-manager");
|
|
31
|
+
const breakpoint_marker_1 = require("./breakpoint-marker");
|
|
32
|
+
const debug_data_breakpoint_1 = require("../model/debug-data-breakpoint");
|
|
33
|
+
disableJSDOM();
|
|
34
|
+
// ── Helpers ──
|
|
35
|
+
const FILE_A = new uri_1.default('file:///workspace/a.ts');
|
|
36
|
+
const FILE_B = new uri_1.default('file:///workspace/b.ts');
|
|
37
|
+
function makeSourceBreakpoint(uri, line, opts) {
|
|
38
|
+
return breakpoint_marker_1.SourceBreakpoint.create(uri, { line, column: opts?.column, condition: opts?.condition, hitCondition: opts?.hitCondition, logMessage: opts?.logMessage }, opts?.id ? { id: opts.id, uri: uri.toString(), enabled: opts?.enabled ?? true, raw: { line } } : undefined);
|
|
39
|
+
}
|
|
40
|
+
function makeFunctionBreakpoint(name) {
|
|
41
|
+
return breakpoint_marker_1.FunctionBreakpoint.create({ name });
|
|
42
|
+
}
|
|
43
|
+
function makeDataBreakpoint(dataId, description = 'some var') {
|
|
44
|
+
return breakpoint_marker_1.DataBreakpoint.create({ dataId, accessType: 'write' }, { dataId, description, accessTypes: ['read', 'write'], canPersist: true }, { type: 0 /* DataBreakpointSourceType.Variable */, variable: description });
|
|
45
|
+
}
|
|
46
|
+
const defaultCapabilities = {};
|
|
47
|
+
function makeSessionData(overrides = {}) {
|
|
48
|
+
return {
|
|
49
|
+
id: 1,
|
|
50
|
+
verified: true,
|
|
51
|
+
line: 5,
|
|
52
|
+
supportsConditionalBreakpoints: false,
|
|
53
|
+
supportsHitConditionalBreakpoints: false,
|
|
54
|
+
supportsLogPoints: false,
|
|
55
|
+
supportsFunctionBreakpoints: false,
|
|
56
|
+
supportsDataBreakpoints: false,
|
|
57
|
+
supportsInstructionBreakpoints: false,
|
|
58
|
+
...overrides,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// ── Test Setup ──
|
|
62
|
+
function createManager() {
|
|
63
|
+
const container = new inversify_1.Container();
|
|
64
|
+
const storageData = {};
|
|
65
|
+
const fileChangeEmitter = new common_1.Emitter();
|
|
66
|
+
container.bind(browser_1.LabelProvider).toConstantValue({
|
|
67
|
+
getName: (uri) => uri.path.base,
|
|
68
|
+
getLongName: (uri) => uri.path.toString(),
|
|
69
|
+
});
|
|
70
|
+
container.bind(browser_1.OpenerService).toConstantValue({});
|
|
71
|
+
container.bind(common_1.CommandService).toConstantValue({});
|
|
72
|
+
container.bind(storage_service_1.StorageService).toConstantValue({
|
|
73
|
+
getData: async (key, defaultValue) => storageData[key] ?? defaultValue,
|
|
74
|
+
setData: async (key, data) => { storageData[key] = data; },
|
|
75
|
+
});
|
|
76
|
+
container.bind(file_service_1.FileService).toConstantValue({
|
|
77
|
+
onDidFilesChange: fileChangeEmitter.event,
|
|
78
|
+
});
|
|
79
|
+
container.bind(breakpoint_manager_1.BreakpointManager).toSelf().inSingletonScope();
|
|
80
|
+
const manager = container.get(breakpoint_manager_1.BreakpointManager);
|
|
81
|
+
return { manager, storageData, fileChangeEmitter };
|
|
82
|
+
}
|
|
83
|
+
// ── Tests ──
|
|
84
|
+
describe('DebugBreakpoint.update() — session data lifecycle', () => {
|
|
85
|
+
let manager;
|
|
86
|
+
beforeEach(() => {
|
|
87
|
+
({ manager } = createManager());
|
|
88
|
+
});
|
|
89
|
+
it('adding session data for a session updates _raw', () => {
|
|
90
|
+
const bp = manager.addBreakpoint(makeSourceBreakpoint(FILE_A, 10));
|
|
91
|
+
bp.update('session-1', makeSessionData({ verified: true, line: 10 }));
|
|
92
|
+
(0, chai_1.expect)(bp.raw).to.not.be.undefined;
|
|
93
|
+
(0, chai_1.expect)(bp.raw.sessionId).to.equal('session-1');
|
|
94
|
+
(0, chai_1.expect)(bp.raw.line).to.equal(10);
|
|
95
|
+
});
|
|
96
|
+
it('verified single session: verified returns true', () => {
|
|
97
|
+
const bp = manager.addBreakpoint(makeSourceBreakpoint(FILE_A, 10));
|
|
98
|
+
bp.update('session-1', makeSessionData({ verified: true }));
|
|
99
|
+
(0, chai_1.expect)(bp.verified).to.be.true;
|
|
100
|
+
});
|
|
101
|
+
it('unverified single session: verified returns false, _raw still available', () => {
|
|
102
|
+
const bp = manager.addBreakpoint(makeSourceBreakpoint(FILE_A, 10));
|
|
103
|
+
bp.update('session-1', makeSessionData({ verified: false, message: 'not yet' }));
|
|
104
|
+
(0, chai_1.expect)(bp.verified).to.be.false;
|
|
105
|
+
(0, chai_1.expect)(bp.raw).to.not.be.undefined;
|
|
106
|
+
(0, chai_1.expect)(bp.raw.message).to.equal('not yet');
|
|
107
|
+
});
|
|
108
|
+
it('multiple sessions, one verified: _raw picks the verified one', () => {
|
|
109
|
+
const bp = manager.addBreakpoint(makeSourceBreakpoint(FILE_A, 10));
|
|
110
|
+
bp.update('session-1', makeSessionData({ verified: false, line: 10 }));
|
|
111
|
+
bp.update('session-2', makeSessionData({ verified: true, line: 11 }));
|
|
112
|
+
(0, chai_1.expect)(bp.verified).to.be.true;
|
|
113
|
+
(0, chai_1.expect)(bp.raw.sessionId).to.equal('session-2');
|
|
114
|
+
(0, chai_1.expect)(bp.raw.line).to.equal(11);
|
|
115
|
+
});
|
|
116
|
+
it('multiple sessions, both verified at same location: _raw picks one', () => {
|
|
117
|
+
const bp = manager.addBreakpoint(makeSourceBreakpoint(FILE_A, 10));
|
|
118
|
+
bp.update('session-1', makeSessionData({ verified: true, line: 10, column: 1 }));
|
|
119
|
+
bp.update('session-2', makeSessionData({ verified: true, line: 10, column: 1 }));
|
|
120
|
+
(0, chai_1.expect)(bp.verified).to.be.true;
|
|
121
|
+
// Both agree on location, so verifiedLocations.size === 1 → picks that one
|
|
122
|
+
(0, chai_1.expect)(bp.raw).to.not.be.undefined;
|
|
123
|
+
});
|
|
124
|
+
it('multiple sessions, verified at different locations: _raw cleared, verified stays true', () => {
|
|
125
|
+
const bp = manager.addBreakpoint(makeSourceBreakpoint(FILE_A, 10));
|
|
126
|
+
bp.update('session-1', makeSessionData({ verified: true, line: 10 }));
|
|
127
|
+
bp.update('session-2', makeSessionData({ verified: true, line: 20 }));
|
|
128
|
+
// Sessions disagree → _raw is undefined so the breakpoint falls back
|
|
129
|
+
// to its user-set position, but still shows as verified (VSCode semantics).
|
|
130
|
+
(0, chai_1.expect)(bp.raw).to.be.undefined;
|
|
131
|
+
(0, chai_1.expect)(bp.verified).to.be.true;
|
|
132
|
+
(0, chai_1.expect)(bp.installed).to.be.true;
|
|
133
|
+
// Per-session data is still accessible for callers that need it.
|
|
134
|
+
(0, chai_1.expect)(bp.getDebugProtocolBreakpoint('session-1').line).to.equal(10);
|
|
135
|
+
(0, chai_1.expect)(bp.getDebugProtocolBreakpoint('session-2').line).to.equal(20);
|
|
136
|
+
});
|
|
137
|
+
it('removing session data for a session that contributed: data is deleted, _raw recomputed', () => {
|
|
138
|
+
const bp = manager.addBreakpoint(makeSourceBreakpoint(FILE_A, 10));
|
|
139
|
+
bp.update('session-1', makeSessionData({ verified: true, line: 10 }));
|
|
140
|
+
bp.update('session-2', makeSessionData({ verified: true, line: 20 }));
|
|
141
|
+
bp.update('session-1', undefined);
|
|
142
|
+
(0, chai_1.expect)(bp.raw).to.not.be.undefined;
|
|
143
|
+
(0, chai_1.expect)(bp.raw.sessionId).to.equal('session-2');
|
|
144
|
+
});
|
|
145
|
+
it('removing session data for a session that never contributed: no-op', () => {
|
|
146
|
+
const bp = manager.addBreakpoint(makeSourceBreakpoint(FILE_A, 10));
|
|
147
|
+
bp.update('session-1', makeSessionData({ verified: true, line: 10 }));
|
|
148
|
+
const rawBefore = bp.raw;
|
|
149
|
+
bp.update('session-never', undefined);
|
|
150
|
+
(0, chai_1.expect)(bp.raw).to.equal(rawBefore);
|
|
151
|
+
});
|
|
152
|
+
it('removing all session data: _raw becomes undefined, verified defaults to true', () => {
|
|
153
|
+
const bp = manager.addBreakpoint(makeSourceBreakpoint(FILE_A, 10));
|
|
154
|
+
bp.update('session-1', makeSessionData({ verified: true, line: 10 }));
|
|
155
|
+
bp.update('session-1', undefined);
|
|
156
|
+
(0, chai_1.expect)(bp.raw).to.be.undefined;
|
|
157
|
+
// No session data at all → verified defaults to true (no adapter has
|
|
158
|
+
// said otherwise), installed is false (no session has reported).
|
|
159
|
+
(0, chai_1.expect)(bp.verified).to.be.true;
|
|
160
|
+
(0, chai_1.expect)(bp.installed).to.be.false;
|
|
161
|
+
});
|
|
162
|
+
it('before any session: verified defaults to true, installed is false', () => {
|
|
163
|
+
const bp = manager.addBreakpoint(makeSourceBreakpoint(FILE_A, 10));
|
|
164
|
+
(0, chai_1.expect)(bp.raw).to.be.undefined;
|
|
165
|
+
(0, chai_1.expect)(bp.verified).to.be.true;
|
|
166
|
+
(0, chai_1.expect)(bp.installed).to.be.false;
|
|
167
|
+
(0, chai_1.expect)(bp.enabled).to.be.true;
|
|
168
|
+
});
|
|
169
|
+
it('single session unverified: installed is true, verified is false', () => {
|
|
170
|
+
const bp = manager.addBreakpoint(makeSourceBreakpoint(FILE_A, 10));
|
|
171
|
+
bp.update('session-1', makeSessionData({ verified: false }));
|
|
172
|
+
(0, chai_1.expect)(bp.installed).to.be.true;
|
|
173
|
+
(0, chai_1.expect)(bp.verified).to.be.false;
|
|
174
|
+
});
|
|
175
|
+
it('disagreement resolved when one session removed: _raw restored from remaining', () => {
|
|
176
|
+
const bp = manager.addBreakpoint(makeSourceBreakpoint(FILE_A, 10));
|
|
177
|
+
bp.update('session-1', makeSessionData({ verified: true, line: 10 }));
|
|
178
|
+
bp.update('session-2', makeSessionData({ verified: true, line: 20 }));
|
|
179
|
+
(0, chai_1.expect)(bp.raw).to.be.undefined; // disagreement
|
|
180
|
+
bp.update('session-1', undefined);
|
|
181
|
+
// Only session-2 remains → single verified location → _raw restored
|
|
182
|
+
(0, chai_1.expect)(bp.raw).to.not.be.undefined;
|
|
183
|
+
(0, chai_1.expect)(bp.raw.sessionId).to.equal('session-2');
|
|
184
|
+
(0, chai_1.expect)(bp.raw.line).to.equal(20);
|
|
185
|
+
});
|
|
186
|
+
it('getIdForSession returns the adapter id', () => {
|
|
187
|
+
const bp = manager.addBreakpoint(makeSourceBreakpoint(FILE_A, 10));
|
|
188
|
+
bp.update('session-1', makeSessionData({ id: 42 }));
|
|
189
|
+
(0, chai_1.expect)(bp.getIdForSession('session-1')).to.equal(42);
|
|
190
|
+
(0, chai_1.expect)(bp.getIdForSession('unknown')).to.be.undefined;
|
|
191
|
+
});
|
|
192
|
+
it('getDebugProtocolBreakpoint returns protocol data for known session', () => {
|
|
193
|
+
const bp = manager.addBreakpoint(makeSourceBreakpoint(FILE_A, 10));
|
|
194
|
+
bp.update('session-1', makeSessionData({ id: 7, verified: true, line: 10, message: 'ok' }));
|
|
195
|
+
const proto = bp.getDebugProtocolBreakpoint('session-1');
|
|
196
|
+
(0, chai_1.expect)(proto).to.deep.include({ id: 7, verified: true, line: 10, message: 'ok' });
|
|
197
|
+
});
|
|
198
|
+
it('getDebugProtocolBreakpoint returns undefined for unknown session', () => {
|
|
199
|
+
const bp = manager.addBreakpoint(makeSourceBreakpoint(FILE_A, 10));
|
|
200
|
+
(0, chai_1.expect)(bp.getDebugProtocolBreakpoint('nope')).to.be.undefined;
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
describe('BreakpointManager — source breakpoint identity preservation', () => {
|
|
204
|
+
let manager;
|
|
205
|
+
beforeEach(() => {
|
|
206
|
+
({ manager } = createManager());
|
|
207
|
+
});
|
|
208
|
+
it('setBreakpoints with matching ID reuses existing wrapper', () => {
|
|
209
|
+
const original = makeSourceBreakpoint(FILE_A, 10);
|
|
210
|
+
manager.setBreakpoints(FILE_A, [original]);
|
|
211
|
+
const wrapper1 = manager.getBreakpoints(FILE_A)[0];
|
|
212
|
+
// Now "move" the breakpoint to line 20 but keep the same ID
|
|
213
|
+
const moved = { ...original, raw: { ...original.raw, line: 20 } };
|
|
214
|
+
manager.setBreakpoints(FILE_A, [moved]);
|
|
215
|
+
const wrapper2 = manager.getBreakpoints(FILE_A)[0];
|
|
216
|
+
(0, chai_1.expect)(wrapper2).to.equal(wrapper1); // same object identity
|
|
217
|
+
(0, chai_1.expect)(wrapper2.line).to.equal(20);
|
|
218
|
+
});
|
|
219
|
+
it('session data survives a position change via setBreakpoints', () => {
|
|
220
|
+
const original = makeSourceBreakpoint(FILE_A, 10);
|
|
221
|
+
manager.setBreakpoints(FILE_A, [original]);
|
|
222
|
+
const wrapper = manager.getBreakpoints(FILE_A)[0];
|
|
223
|
+
wrapper.update('s1', makeSessionData({ verified: true, line: 10 }));
|
|
224
|
+
(0, chai_1.expect)(wrapper.verified).to.be.true;
|
|
225
|
+
// Move to line 20
|
|
226
|
+
const moved = { ...original, raw: { ...original.raw, line: 20 } };
|
|
227
|
+
manager.setBreakpoints(FILE_A, [moved]);
|
|
228
|
+
const wrapper2 = manager.getBreakpoints(FILE_A)[0];
|
|
229
|
+
(0, chai_1.expect)(wrapper2).to.equal(wrapper);
|
|
230
|
+
(0, chai_1.expect)(wrapper2.verified).to.be.true; // session data survived
|
|
231
|
+
});
|
|
232
|
+
it('setBreakpoints with a genuinely new breakpoint creates a new wrapper', () => {
|
|
233
|
+
const bp1 = makeSourceBreakpoint(FILE_A, 10);
|
|
234
|
+
manager.setBreakpoints(FILE_A, [bp1]);
|
|
235
|
+
const wrapper1 = manager.getBreakpoints(FILE_A)[0];
|
|
236
|
+
const bp2 = makeSourceBreakpoint(FILE_A, 20);
|
|
237
|
+
manager.setBreakpoints(FILE_A, [bp1, bp2]);
|
|
238
|
+
const wrappers = manager.getBreakpoints(FILE_A);
|
|
239
|
+
(0, chai_1.expect)(wrappers).to.have.length(2);
|
|
240
|
+
(0, chai_1.expect)(wrappers[0]).to.equal(wrapper1);
|
|
241
|
+
(0, chai_1.expect)(wrappers[1]).to.not.equal(wrapper1);
|
|
242
|
+
});
|
|
243
|
+
it('setBreakpoints deduplicates by position', () => {
|
|
244
|
+
const bp1 = makeSourceBreakpoint(FILE_A, 10);
|
|
245
|
+
const bp2 = makeSourceBreakpoint(FILE_A, 10); // different id, same position
|
|
246
|
+
manager.setBreakpoints(FILE_A, [bp1, bp2]);
|
|
247
|
+
(0, chai_1.expect)(manager.getBreakpoints(FILE_A)).to.have.length(1);
|
|
248
|
+
});
|
|
249
|
+
it('addBreakpoint with a positional duplicate returns the existing wrapper', () => {
|
|
250
|
+
const bp1 = makeSourceBreakpoint(FILE_A, 10);
|
|
251
|
+
manager.setBreakpoints(FILE_A, [bp1]);
|
|
252
|
+
const wrapper1 = manager.getBreakpoints(FILE_A)[0];
|
|
253
|
+
const bp2 = makeSourceBreakpoint(FILE_A, 10);
|
|
254
|
+
const result = manager.addBreakpoint(bp2);
|
|
255
|
+
(0, chai_1.expect)(result).to.equal(wrapper1);
|
|
256
|
+
(0, chai_1.expect)(manager.getBreakpoints(FILE_A)).to.have.length(1);
|
|
257
|
+
});
|
|
258
|
+
it('removeBreakpoint removes by identity and fires correct events', () => {
|
|
259
|
+
const bp1 = makeSourceBreakpoint(FILE_A, 10);
|
|
260
|
+
const bp2 = makeSourceBreakpoint(FILE_A, 20);
|
|
261
|
+
manager.setBreakpoints(FILE_A, [bp1, bp2]);
|
|
262
|
+
const events = [];
|
|
263
|
+
manager.onDidChangeBreakpoints(e => events.push(e));
|
|
264
|
+
const wrapper = manager.getBreakpoints(FILE_A)[0];
|
|
265
|
+
manager.removeBreakpoint(wrapper);
|
|
266
|
+
(0, chai_1.expect)(manager.getBreakpoints(FILE_A)).to.have.length(1);
|
|
267
|
+
(0, chai_1.expect)(manager.getBreakpoints(FILE_A)[0].line).to.equal(20);
|
|
268
|
+
// At least one event should have the removed breakpoint
|
|
269
|
+
const removeEvent = events.find(e => e.removed.length > 0);
|
|
270
|
+
(0, chai_1.expect)(removeEvent).to.not.be.undefined;
|
|
271
|
+
(0, chai_1.expect)(removeEvent.removed[0]).to.equal(wrapper);
|
|
272
|
+
});
|
|
273
|
+
it('applySourceBreakpoints fires onDidChangeBreakpoints with correct added/removed/changed', () => {
|
|
274
|
+
const bp1 = makeSourceBreakpoint(FILE_A, 10);
|
|
275
|
+
const bp2 = makeSourceBreakpoint(FILE_A, 20);
|
|
276
|
+
manager.setBreakpoints(FILE_A, [bp1, bp2]);
|
|
277
|
+
const events = [];
|
|
278
|
+
manager.onDidChangeBreakpoints(e => events.push(e));
|
|
279
|
+
const bp3 = makeSourceBreakpoint(FILE_A, 30);
|
|
280
|
+
manager.setBreakpoints(FILE_A, [bp1, bp3]); // bp2 removed, bp3 added, bp1 changed (same identity)
|
|
281
|
+
(0, chai_1.expect)(events).to.have.length(1);
|
|
282
|
+
const event = events[0];
|
|
283
|
+
(0, chai_1.expect)(event.added).to.have.length(1);
|
|
284
|
+
(0, chai_1.expect)(event.added[0].line).to.equal(30);
|
|
285
|
+
(0, chai_1.expect)(event.removed).to.have.length(1);
|
|
286
|
+
(0, chai_1.expect)(event.removed[0].line).to.equal(20);
|
|
287
|
+
(0, chai_1.expect)(event.changed).to.have.length(1);
|
|
288
|
+
});
|
|
289
|
+
it('setBreakpoints sorts by line then column', () => {
|
|
290
|
+
const bp30 = makeSourceBreakpoint(FILE_A, 30);
|
|
291
|
+
const bp10 = makeSourceBreakpoint(FILE_A, 10);
|
|
292
|
+
const bp20 = makeSourceBreakpoint(FILE_A, 20);
|
|
293
|
+
manager.setBreakpoints(FILE_A, [bp30, bp10, bp20]);
|
|
294
|
+
const lines = manager.getBreakpoints(FILE_A).map(bp => bp.line);
|
|
295
|
+
(0, chai_1.expect)(lines).to.deep.equal([10, 20, 30]);
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
describe('BreakpointManager — enable/disable', () => {
|
|
299
|
+
let manager;
|
|
300
|
+
beforeEach(() => {
|
|
301
|
+
({ manager } = createManager());
|
|
302
|
+
});
|
|
303
|
+
it('enableAllBreakpoints(true) enables all breakpoint types', () => {
|
|
304
|
+
const bp = makeSourceBreakpoint(FILE_A, 10, { enabled: false });
|
|
305
|
+
manager.setBreakpoints(FILE_A, [bp]);
|
|
306
|
+
const fbp = makeFunctionBreakpoint('myFunc');
|
|
307
|
+
fbp.enabled = false;
|
|
308
|
+
manager.addFunctionBreakpoint(fbp);
|
|
309
|
+
manager.addInstructionBreakpoint('0xDEAD', 0);
|
|
310
|
+
const dbp = makeDataBreakpoint('data1');
|
|
311
|
+
dbp.enabled = false;
|
|
312
|
+
manager.addDataBreakpoint(dbp);
|
|
313
|
+
// Disable all first
|
|
314
|
+
manager.enableAllBreakpoints(false);
|
|
315
|
+
const sourceEvents = [];
|
|
316
|
+
const funcEvents = [];
|
|
317
|
+
const instrEvents = [];
|
|
318
|
+
const dataEvents = [];
|
|
319
|
+
manager.onDidChangeBreakpoints(e => sourceEvents.push(e));
|
|
320
|
+
manager.onDidChangeFunctionBreakpoints(e => funcEvents.push(e));
|
|
321
|
+
manager.onDidChangeInstructionBreakpoints(e => instrEvents.push(e));
|
|
322
|
+
manager.onDidChangeDataBreakpoints(e => dataEvents.push(e));
|
|
323
|
+
manager.enableAllBreakpoints(true);
|
|
324
|
+
(0, chai_1.expect)(manager.getBreakpoints(FILE_A)[0].origin.enabled).to.be.true;
|
|
325
|
+
(0, chai_1.expect)(manager.getFunctionBreakpoints()[0].origin.enabled).to.be.true;
|
|
326
|
+
(0, chai_1.expect)(manager.getInstructionBreakpoints()[0].origin.enabled).to.be.true;
|
|
327
|
+
(0, chai_1.expect)(manager.getDataBreakpoints()[0].origin.enabled).to.be.true;
|
|
328
|
+
(0, chai_1.expect)(sourceEvents).to.have.length.greaterThan(0);
|
|
329
|
+
(0, chai_1.expect)(funcEvents).to.have.length.greaterThan(0);
|
|
330
|
+
(0, chai_1.expect)(instrEvents).to.have.length.greaterThan(0);
|
|
331
|
+
(0, chai_1.expect)(dataEvents).to.have.length.greaterThan(0);
|
|
332
|
+
});
|
|
333
|
+
it('enableAllBreakpoints does not fire for types already in target state', () => {
|
|
334
|
+
const bp = makeSourceBreakpoint(FILE_A, 10, { enabled: true });
|
|
335
|
+
manager.setBreakpoints(FILE_A, [bp]);
|
|
336
|
+
// They're already enabled — should still fire because didChange is always true
|
|
337
|
+
// in current implementation (identity-based). This test verifies the function
|
|
338
|
+
// breakpoints emitter doesn't fire when there are no function breakpoints.
|
|
339
|
+
const funcEvents = [];
|
|
340
|
+
manager.onDidChangeFunctionBreakpoints(e => funcEvents.push(e));
|
|
341
|
+
manager.enableAllBreakpoints(true);
|
|
342
|
+
(0, chai_1.expect)(funcEvents).to.have.length(0);
|
|
343
|
+
});
|
|
344
|
+
it('set breakpointsEnabled fires onDidChangeMarkers for all synthetic URIs', () => {
|
|
345
|
+
manager.setBreakpoints(FILE_A, [makeSourceBreakpoint(FILE_A, 10)]);
|
|
346
|
+
manager.addFunctionBreakpoint(makeFunctionBreakpoint('fn'));
|
|
347
|
+
const markerUris = [];
|
|
348
|
+
manager.onDidChangeMarkers(uri => markerUris.push(uri.toString()));
|
|
349
|
+
manager.breakpointsEnabled = false;
|
|
350
|
+
(0, chai_1.expect)(markerUris).to.include(FILE_A.toString());
|
|
351
|
+
(0, chai_1.expect)(markerUris).to.include(breakpoint_manager_1.BreakpointManager.FUNCTION_URI.toString());
|
|
352
|
+
(0, chai_1.expect)(markerUris).to.include(breakpoint_manager_1.BreakpointManager.INSTRUCTION_URI.toString());
|
|
353
|
+
(0, chai_1.expect)(markerUris).to.include(breakpoint_manager_1.BreakpointManager.DATA_URI.toString());
|
|
354
|
+
(0, chai_1.expect)(markerUris).to.include(breakpoint_manager_1.BreakpointManager.EXCEPTION_URI.toString());
|
|
355
|
+
});
|
|
356
|
+
it('set breakpointsEnabled does not fire if value unchanged', () => {
|
|
357
|
+
const markerUris = [];
|
|
358
|
+
manager.onDidChangeMarkers(uri => markerUris.push(uri.toString()));
|
|
359
|
+
manager.breakpointsEnabled = true; // already true
|
|
360
|
+
(0, chai_1.expect)(markerUris).to.have.length(0);
|
|
361
|
+
});
|
|
362
|
+
it('enableBreakpoint fires fireBreakpointChanged', () => {
|
|
363
|
+
manager.setBreakpoints(FILE_A, [makeSourceBreakpoint(FILE_A, 10)]);
|
|
364
|
+
const wrapper = manager.getBreakpoints(FILE_A)[0];
|
|
365
|
+
const events = [];
|
|
366
|
+
manager.onDidChangeBreakpoints(e => events.push(e));
|
|
367
|
+
manager.enableBreakpoint(wrapper, false);
|
|
368
|
+
(0, chai_1.expect)(wrapper.origin.enabled).to.be.false;
|
|
369
|
+
(0, chai_1.expect)(events).to.have.length(1);
|
|
370
|
+
(0, chai_1.expect)(events[0].changed).to.include(wrapper);
|
|
371
|
+
});
|
|
372
|
+
it('enableBreakpoint does not fire if already at target state', () => {
|
|
373
|
+
manager.setBreakpoints(FILE_A, [makeSourceBreakpoint(FILE_A, 10)]);
|
|
374
|
+
const wrapper = manager.getBreakpoints(FILE_A)[0];
|
|
375
|
+
const events = [];
|
|
376
|
+
manager.onDidChangeBreakpoints(e => events.push(e));
|
|
377
|
+
manager.enableBreakpoint(wrapper, true); // already enabled
|
|
378
|
+
(0, chai_1.expect)(events).to.have.length(0);
|
|
379
|
+
});
|
|
380
|
+
});
|
|
381
|
+
describe('BreakpointManager — non-source breakpoint types', () => {
|
|
382
|
+
let manager;
|
|
383
|
+
beforeEach(() => {
|
|
384
|
+
({ manager } = createManager());
|
|
385
|
+
});
|
|
386
|
+
// Function breakpoints
|
|
387
|
+
it('addFunctionBreakpoint fires correct events', () => {
|
|
388
|
+
const events = [];
|
|
389
|
+
manager.onDidChangeFunctionBreakpoints(e => events.push(e));
|
|
390
|
+
const bp = makeFunctionBreakpoint('myFunction');
|
|
391
|
+
manager.addFunctionBreakpoint(bp);
|
|
392
|
+
(0, chai_1.expect)(manager.getFunctionBreakpoints()).to.have.length(1);
|
|
393
|
+
(0, chai_1.expect)(manager.getFunctionBreakpoints()[0].name).to.equal('myFunction');
|
|
394
|
+
(0, chai_1.expect)(events).to.have.length(1);
|
|
395
|
+
(0, chai_1.expect)(events[0].added).to.have.length(1);
|
|
396
|
+
});
|
|
397
|
+
it('addFunctionBreakpoint with duplicate name is a no-op', () => {
|
|
398
|
+
manager.addFunctionBreakpoint(makeFunctionBreakpoint('myFunc'));
|
|
399
|
+
manager.addFunctionBreakpoint(makeFunctionBreakpoint('myFunc'));
|
|
400
|
+
(0, chai_1.expect)(manager.getFunctionBreakpoints()).to.have.length(1);
|
|
401
|
+
});
|
|
402
|
+
it('removeFunctionBreakpoint fires correct events', () => {
|
|
403
|
+
manager.addFunctionBreakpoint(makeFunctionBreakpoint('fn'));
|
|
404
|
+
const wrapper = manager.getFunctionBreakpoints()[0];
|
|
405
|
+
const events = [];
|
|
406
|
+
manager.onDidChangeFunctionBreakpoints(e => events.push(e));
|
|
407
|
+
manager.removeFunctionBreakpoint(wrapper);
|
|
408
|
+
(0, chai_1.expect)(manager.getFunctionBreakpoints()).to.have.length(0);
|
|
409
|
+
(0, chai_1.expect)(events).to.have.length(1);
|
|
410
|
+
(0, chai_1.expect)(events[0].removed).to.include(wrapper);
|
|
411
|
+
});
|
|
412
|
+
it('updateFunctionBreakpoint with a name collision removes the colliding breakpoint', () => {
|
|
413
|
+
manager.addFunctionBreakpoint(makeFunctionBreakpoint('fn1'));
|
|
414
|
+
manager.addFunctionBreakpoint(makeFunctionBreakpoint('fn2'));
|
|
415
|
+
const fn1 = manager.getFunctionBreakpoints().find(b => b.name === 'fn1');
|
|
416
|
+
const events = [];
|
|
417
|
+
manager.onDidChangeFunctionBreakpoints(e => events.push(e));
|
|
418
|
+
manager.updateFunctionBreakpoint(fn1, { name: 'fn2' });
|
|
419
|
+
(0, chai_1.expect)(manager.getFunctionBreakpoints()).to.have.length(1);
|
|
420
|
+
(0, chai_1.expect)(manager.getFunctionBreakpoints()[0].name).to.equal('fn2');
|
|
421
|
+
// The event should have a removed entry for the colliding breakpoint
|
|
422
|
+
const removeEvent = events.find(e => e.removed.length > 0);
|
|
423
|
+
(0, chai_1.expect)(removeEvent).to.not.be.undefined;
|
|
424
|
+
});
|
|
425
|
+
// Instruction breakpoints
|
|
426
|
+
it('addInstructionBreakpoint fires correct events', () => {
|
|
427
|
+
const events = [];
|
|
428
|
+
manager.onDidChangeInstructionBreakpoints(e => events.push(e));
|
|
429
|
+
manager.addInstructionBreakpoint('0xDEAD', 0);
|
|
430
|
+
(0, chai_1.expect)(manager.getInstructionBreakpoints()).to.have.length(1);
|
|
431
|
+
(0, chai_1.expect)(events).to.have.length(1);
|
|
432
|
+
(0, chai_1.expect)(events[0].added).to.have.length(1);
|
|
433
|
+
});
|
|
434
|
+
it('addInstructionBreakpoint with duplicate address+offset is a no-op', () => {
|
|
435
|
+
manager.addInstructionBreakpoint('0xBEEF', 4);
|
|
436
|
+
manager.addInstructionBreakpoint('0xBEEF', 4);
|
|
437
|
+
(0, chai_1.expect)(manager.getInstructionBreakpoints()).to.have.length(1);
|
|
438
|
+
});
|
|
439
|
+
it('addInstructionBreakpoint with same address but different offset creates new', () => {
|
|
440
|
+
manager.addInstructionBreakpoint('0xBEEF', 0);
|
|
441
|
+
manager.addInstructionBreakpoint('0xBEEF', 4);
|
|
442
|
+
(0, chai_1.expect)(manager.getInstructionBreakpoints()).to.have.length(2);
|
|
443
|
+
});
|
|
444
|
+
it('removeInstructionBreakpoint fires correct events', () => {
|
|
445
|
+
manager.addInstructionBreakpoint('0xCAFE', 0);
|
|
446
|
+
const wrapper = manager.getInstructionBreakpoints()[0];
|
|
447
|
+
const events = [];
|
|
448
|
+
manager.onDidChangeInstructionBreakpoints(e => events.push(e));
|
|
449
|
+
manager.removeInstructionBreakpoint(wrapper);
|
|
450
|
+
(0, chai_1.expect)(manager.getInstructionBreakpoints()).to.have.length(0);
|
|
451
|
+
(0, chai_1.expect)(events).to.have.length(1);
|
|
452
|
+
(0, chai_1.expect)(events[0].removed).to.include(wrapper);
|
|
453
|
+
});
|
|
454
|
+
// Data breakpoints
|
|
455
|
+
it('addDataBreakpoint fires correct events', () => {
|
|
456
|
+
const events = [];
|
|
457
|
+
manager.onDidChangeDataBreakpoints(e => events.push(e));
|
|
458
|
+
manager.addDataBreakpoint(makeDataBreakpoint('data-1'));
|
|
459
|
+
(0, chai_1.expect)(manager.getDataBreakpoints()).to.have.length(1);
|
|
460
|
+
(0, chai_1.expect)(events).to.have.length(1);
|
|
461
|
+
(0, chai_1.expect)(events[0].added).to.have.length(1);
|
|
462
|
+
});
|
|
463
|
+
it('addDataBreakpoint with duplicate dataId is a no-op', () => {
|
|
464
|
+
manager.addDataBreakpoint(makeDataBreakpoint('data-1'));
|
|
465
|
+
manager.addDataBreakpoint(makeDataBreakpoint('data-1'));
|
|
466
|
+
(0, chai_1.expect)(manager.getDataBreakpoints()).to.have.length(1);
|
|
467
|
+
});
|
|
468
|
+
it('removeDataBreakpoint fires correct events', () => {
|
|
469
|
+
manager.addDataBreakpoint(makeDataBreakpoint('data-1'));
|
|
470
|
+
const wrapper = manager.getDataBreakpoints()[0];
|
|
471
|
+
const events = [];
|
|
472
|
+
manager.onDidChangeDataBreakpoints(e => events.push(e));
|
|
473
|
+
manager.removeDataBreakpoint(wrapper);
|
|
474
|
+
(0, chai_1.expect)(manager.getDataBreakpoints()).to.have.length(0);
|
|
475
|
+
(0, chai_1.expect)(events).to.have.length(1);
|
|
476
|
+
(0, chai_1.expect)(events[0].removed).to.include(wrapper);
|
|
477
|
+
});
|
|
478
|
+
// removeBreakpointsById
|
|
479
|
+
it('removeBreakpointsById removes across all types', () => {
|
|
480
|
+
manager.setBreakpoints(FILE_A, [makeSourceBreakpoint(FILE_A, 10)]);
|
|
481
|
+
manager.addFunctionBreakpoint(makeFunctionBreakpoint('fn'));
|
|
482
|
+
manager.addInstructionBreakpoint('0xABC', 0);
|
|
483
|
+
manager.addDataBreakpoint(makeDataBreakpoint('d1'));
|
|
484
|
+
const srcId = manager.getBreakpoints(FILE_A)[0].id;
|
|
485
|
+
const fnId = manager.getFunctionBreakpoints()[0].id;
|
|
486
|
+
const instrId = manager.getInstructionBreakpoints()[0].id;
|
|
487
|
+
const dataId = manager.getDataBreakpoints()[0].id;
|
|
488
|
+
manager.removeBreakpointsById([srcId, fnId, instrId, dataId]);
|
|
489
|
+
(0, chai_1.expect)(manager.getBreakpoints(FILE_A)).to.have.length(0);
|
|
490
|
+
(0, chai_1.expect)(manager.getFunctionBreakpoints()).to.have.length(0);
|
|
491
|
+
(0, chai_1.expect)(manager.getInstructionBreakpoints()).to.have.length(0);
|
|
492
|
+
(0, chai_1.expect)(manager.getDataBreakpoints()).to.have.length(0);
|
|
493
|
+
});
|
|
494
|
+
});
|
|
495
|
+
describe('BreakpointManager — updateSessionData', () => {
|
|
496
|
+
let manager;
|
|
497
|
+
beforeEach(() => {
|
|
498
|
+
({ manager } = createManager());
|
|
499
|
+
});
|
|
500
|
+
it('with bps map: only matching breakpoints get updated', () => {
|
|
501
|
+
const sb1 = makeSourceBreakpoint(FILE_A, 10);
|
|
502
|
+
const sb2 = makeSourceBreakpoint(FILE_A, 20);
|
|
503
|
+
manager.setBreakpoints(FILE_A, [sb1, sb2]);
|
|
504
|
+
const wrappers = manager.getBreakpoints(FILE_A);
|
|
505
|
+
const bpsMap = new Map();
|
|
506
|
+
bpsMap.set(wrappers[0].id, { id: 1, verified: true, line: 10 });
|
|
507
|
+
manager.updateSessionData('s1', defaultCapabilities, bpsMap);
|
|
508
|
+
(0, chai_1.expect)(wrappers[0].installed).to.be.true;
|
|
509
|
+
(0, chai_1.expect)(wrappers[0].verified).to.be.true;
|
|
510
|
+
(0, chai_1.expect)(wrappers[1].installed).to.be.false; // not in the map — no session touched it
|
|
511
|
+
});
|
|
512
|
+
it('without bps map: all breakpoints have the session removed', () => {
|
|
513
|
+
const sb = makeSourceBreakpoint(FILE_A, 10);
|
|
514
|
+
manager.setBreakpoints(FILE_A, [sb]);
|
|
515
|
+
const wrapper = manager.getBreakpoints(FILE_A)[0];
|
|
516
|
+
// First add session data
|
|
517
|
+
const bpsMap = new Map();
|
|
518
|
+
bpsMap.set(wrapper.id, { id: 1, verified: true, line: 10 });
|
|
519
|
+
manager.updateSessionData('s1', defaultCapabilities, bpsMap);
|
|
520
|
+
(0, chai_1.expect)(wrapper.installed).to.be.true;
|
|
521
|
+
(0, chai_1.expect)(wrapper.verified).to.be.true;
|
|
522
|
+
// Now cleanup (no bps map)
|
|
523
|
+
manager.updateSessionData('s1', defaultCapabilities, undefined);
|
|
524
|
+
(0, chai_1.expect)(wrapper.installed).to.be.false;
|
|
525
|
+
(0, chai_1.expect)(wrapper.raw).to.be.undefined;
|
|
526
|
+
// verified defaults to true when no session has weighed in
|
|
527
|
+
(0, chai_1.expect)(wrapper.verified).to.be.true;
|
|
528
|
+
});
|
|
529
|
+
it('cleanup short-circuits for breakpoints that never had data from the session', () => {
|
|
530
|
+
const sb = makeSourceBreakpoint(FILE_A, 10);
|
|
531
|
+
manager.setBreakpoints(FILE_A, [sb]);
|
|
532
|
+
const wrapper = manager.getBreakpoints(FILE_A)[0];
|
|
533
|
+
// Add data from session-1
|
|
534
|
+
const bpsMap = new Map();
|
|
535
|
+
bpsMap.set(wrapper.id, { id: 1, verified: true, line: 10 });
|
|
536
|
+
manager.updateSessionData('s1', defaultCapabilities, bpsMap);
|
|
537
|
+
// Cleanup session-2 (never contributed) — wrapper should still have s1 data
|
|
538
|
+
manager.updateSessionData('s2', defaultCapabilities, undefined);
|
|
539
|
+
(0, chai_1.expect)(wrapper.verified).to.be.true;
|
|
540
|
+
(0, chai_1.expect)(wrapper.raw.sessionId).to.equal('s1');
|
|
541
|
+
});
|
|
542
|
+
it('capabilities are correctly extracted and merged into BPSessionData', () => {
|
|
543
|
+
const sb = makeSourceBreakpoint(FILE_A, 10);
|
|
544
|
+
manager.setBreakpoints(FILE_A, [sb]);
|
|
545
|
+
const wrapper = manager.getBreakpoints(FILE_A)[0];
|
|
546
|
+
const caps = {
|
|
547
|
+
supportsConditionalBreakpoints: true,
|
|
548
|
+
supportsHitConditionalBreakpoints: true,
|
|
549
|
+
supportsLogPoints: false,
|
|
550
|
+
};
|
|
551
|
+
const bpsMap = new Map();
|
|
552
|
+
bpsMap.set(wrapper.id, { id: 1, verified: true, line: 10 });
|
|
553
|
+
manager.updateSessionData('s1', caps, bpsMap);
|
|
554
|
+
(0, chai_1.expect)(wrapper.raw.supportsConditionalBreakpoints).to.be.true;
|
|
555
|
+
(0, chai_1.expect)(wrapper.raw.supportsHitConditionalBreakpoints).to.be.true;
|
|
556
|
+
(0, chai_1.expect)(wrapper.raw.supportsLogPoints).to.be.false;
|
|
557
|
+
});
|
|
558
|
+
it('typed events fire grouped by URI', () => {
|
|
559
|
+
manager.setBreakpoints(FILE_A, [makeSourceBreakpoint(FILE_A, 10)]);
|
|
560
|
+
manager.setBreakpoints(FILE_B, [makeSourceBreakpoint(FILE_B, 5)]);
|
|
561
|
+
manager.addFunctionBreakpoint(makeFunctionBreakpoint('fn'));
|
|
562
|
+
const sourceEvents = [];
|
|
563
|
+
const funcEvents = [];
|
|
564
|
+
manager.onDidChangeBreakpoints(e => sourceEvents.push(e));
|
|
565
|
+
manager.onDidChangeFunctionBreakpoints(e => funcEvents.push(e));
|
|
566
|
+
const bpsMap = new Map();
|
|
567
|
+
for (const bp of manager.getBreakpoints()) {
|
|
568
|
+
bpsMap.set(bp.id, { id: 1, verified: true, line: bp.line });
|
|
569
|
+
}
|
|
570
|
+
for (const bp of manager.getFunctionBreakpoints()) {
|
|
571
|
+
bpsMap.set(bp.id, { id: 2, verified: true });
|
|
572
|
+
}
|
|
573
|
+
manager.updateSessionData('s1', defaultCapabilities, bpsMap);
|
|
574
|
+
// Source breakpoints for two different URIs → two events
|
|
575
|
+
(0, chai_1.expect)(sourceEvents).to.have.length(2);
|
|
576
|
+
const uris = sourceEvents.map(e => e.uri.toString()).sort();
|
|
577
|
+
(0, chai_1.expect)(uris).to.deep.equal([FILE_A.toString(), FILE_B.toString()].sort());
|
|
578
|
+
// Function breakpoint → one event
|
|
579
|
+
(0, chai_1.expect)(funcEvents).to.have.length(1);
|
|
580
|
+
});
|
|
581
|
+
});
|
|
582
|
+
describe('BreakpointManager — exception breakpoints', () => {
|
|
583
|
+
let manager;
|
|
584
|
+
beforeEach(() => {
|
|
585
|
+
({ manager } = createManager());
|
|
586
|
+
});
|
|
587
|
+
it('addExceptionBreakpoints creates new for unknown filters', () => {
|
|
588
|
+
const filter = { filter: 'all', label: 'All Exceptions' };
|
|
589
|
+
manager.addExceptionBreakpoints([filter], 'session-1');
|
|
590
|
+
(0, chai_1.expect)(manager.getExceptionBreakpoints()).to.have.length(1);
|
|
591
|
+
(0, chai_1.expect)(manager.getExceptionBreakpoints()[0].origin.raw.filter).to.equal('all');
|
|
592
|
+
});
|
|
593
|
+
it('addExceptionBreakpoints reuses existing for known filters', () => {
|
|
594
|
+
const filter = { filter: 'all', label: 'All Exceptions' };
|
|
595
|
+
manager.addExceptionBreakpoints([filter], 'session-1');
|
|
596
|
+
const first = manager.getExceptionBreakpoints()[0];
|
|
597
|
+
manager.addExceptionBreakpoints([filter], 'session-2');
|
|
598
|
+
(0, chai_1.expect)(manager.getExceptionBreakpoints()).to.have.length(1);
|
|
599
|
+
(0, chai_1.expect)(manager.getExceptionBreakpoints()[0]).to.equal(first);
|
|
600
|
+
});
|
|
601
|
+
it('clearExceptionSessionEnablement removes the session from all enablement sets', () => {
|
|
602
|
+
const filter = { filter: 'all', label: 'All Exceptions' };
|
|
603
|
+
manager.addExceptionBreakpoints([filter], 'session-1');
|
|
604
|
+
const bp = manager.getExceptionBreakpoints()[0];
|
|
605
|
+
(0, chai_1.expect)(bp.isEnabledForSession('session-1')).to.be.true;
|
|
606
|
+
manager.clearExceptionSessionEnablement('session-1');
|
|
607
|
+
(0, chai_1.expect)(bp.isEnabledForSession('session-1')).to.be.false;
|
|
608
|
+
});
|
|
609
|
+
it('persistentlyVisible remains true after session cleanup for filters that were visible', () => {
|
|
610
|
+
const filter = { filter: 'all', label: 'All Exceptions' };
|
|
611
|
+
manager.addExceptionBreakpoints([filter], 'session-1');
|
|
612
|
+
const bp = manager.getExceptionBreakpoints()[0];
|
|
613
|
+
// addExceptionBreakpoints calls doUpdateExceptionBreakpointVisibility which sets persistent visibility
|
|
614
|
+
(0, chai_1.expect)(bp.isPersistentlyVisible()).to.be.true;
|
|
615
|
+
// Clearing session enablement does NOT clear persistent visibility
|
|
616
|
+
manager.clearExceptionSessionEnablement('session-1');
|
|
617
|
+
(0, chai_1.expect)(bp.isPersistentlyVisible()).to.be.true;
|
|
618
|
+
});
|
|
619
|
+
it('getExceptionBreakpoint finds by filter match', () => {
|
|
620
|
+
const filter = { filter: 'uncaught', label: 'Uncaught Exceptions' };
|
|
621
|
+
manager.addExceptionBreakpoints([filter], 'session-1');
|
|
622
|
+
const found = manager.getExceptionBreakpoint(filter);
|
|
623
|
+
(0, chai_1.expect)(found).to.not.be.undefined;
|
|
624
|
+
(0, chai_1.expect)(found.origin.raw.filter).to.equal('uncaught');
|
|
625
|
+
const notFound = manager.getExceptionBreakpoint({ filter: 'other', label: 'Other' });
|
|
626
|
+
(0, chai_1.expect)(notFound).to.be.undefined;
|
|
627
|
+
});
|
|
628
|
+
});
|
|
629
|
+
describe('BreakpointManager — persistence', () => {
|
|
630
|
+
let manager;
|
|
631
|
+
let storageData;
|
|
632
|
+
beforeEach(() => {
|
|
633
|
+
({ manager, storageData } = createManager());
|
|
634
|
+
});
|
|
635
|
+
it('save() extracts origin from all wrapper types', () => {
|
|
636
|
+
manager.setBreakpoints(FILE_A, [makeSourceBreakpoint(FILE_A, 10)]);
|
|
637
|
+
manager.addFunctionBreakpoint(makeFunctionBreakpoint('fn'));
|
|
638
|
+
manager.addInstructionBreakpoint('0xDEAD', 0);
|
|
639
|
+
manager.addDataBreakpoint(makeDataBreakpoint('d1'));
|
|
640
|
+
// Add an exception breakpoint that's persistently visible
|
|
641
|
+
const filter = { filter: 'all', label: 'All Exceptions' };
|
|
642
|
+
manager.addExceptionBreakpoints([filter], 'session-1');
|
|
643
|
+
manager.save();
|
|
644
|
+
const data = storageData['breakpoints'];
|
|
645
|
+
(0, chai_1.expect)(data).to.not.be.undefined;
|
|
646
|
+
(0, chai_1.expect)(Object.keys(data.breakpoints)).to.have.length(1);
|
|
647
|
+
(0, chai_1.expect)(data.breakpoints[FILE_A.toString()]).to.have.length(1);
|
|
648
|
+
(0, chai_1.expect)(data.functionBreakpoints).to.have.length(1);
|
|
649
|
+
(0, chai_1.expect)(data.instructionBreakpoints).to.have.length(1);
|
|
650
|
+
(0, chai_1.expect)(data.dataBreakpoints).to.have.length(1);
|
|
651
|
+
(0, chai_1.expect)(data.exceptionBreakpoints).to.have.length(1);
|
|
652
|
+
});
|
|
653
|
+
it('round-trip: save then load produces equivalent breakpoints', async () => {
|
|
654
|
+
const sbp = makeSourceBreakpoint(FILE_A, 42, { condition: 'x > 5' });
|
|
655
|
+
manager.setBreakpoints(FILE_A, [sbp]);
|
|
656
|
+
manager.addFunctionBreakpoint(makeFunctionBreakpoint('myFn'));
|
|
657
|
+
manager.breakpointsEnabled = false;
|
|
658
|
+
manager.save();
|
|
659
|
+
// Create a fresh manager and load
|
|
660
|
+
const { manager: manager2 } = createManager();
|
|
661
|
+
// Copy stored data to the new manager's storage
|
|
662
|
+
const freshStorageData = manager2['storage'];
|
|
663
|
+
await freshStorageData.setData('breakpoints', storageData['breakpoints']);
|
|
664
|
+
await manager2.load();
|
|
665
|
+
(0, chai_1.expect)(manager2.breakpointsEnabled).to.be.false;
|
|
666
|
+
const loaded = manager2.getBreakpoints(FILE_A);
|
|
667
|
+
(0, chai_1.expect)(loaded).to.have.length(1);
|
|
668
|
+
(0, chai_1.expect)(loaded[0].origin.raw.line).to.equal(42);
|
|
669
|
+
(0, chai_1.expect)(loaded[0].origin.raw.condition).to.equal('x > 5');
|
|
670
|
+
(0, chai_1.expect)(manager2.getFunctionBreakpoints()).to.have.length(1);
|
|
671
|
+
(0, chai_1.expect)(manager2.getFunctionBreakpoints()[0].name).to.equal('myFn');
|
|
672
|
+
});
|
|
673
|
+
it('exception breakpoints: only persistentlyVisible ones are saved', () => {
|
|
674
|
+
const filter1 = { filter: 'all', label: 'All' };
|
|
675
|
+
const filter2 = { filter: 'uncaught', label: 'Uncaught' };
|
|
676
|
+
manager.addExceptionBreakpoints([filter1], 'session-1');
|
|
677
|
+
manager.addExceptionBreakpoints([filter2], 'session-1');
|
|
678
|
+
// filter1 and filter2 are persistentlyVisible after addExceptionBreakpoints
|
|
679
|
+
// Now mark one as not persistently visible
|
|
680
|
+
const bp2 = manager.getExceptionBreakpoints()[1];
|
|
681
|
+
bp2.setPersistentVisibility(false);
|
|
682
|
+
manager.save();
|
|
683
|
+
const data = storageData['breakpoints'];
|
|
684
|
+
(0, chai_1.expect)(data.exceptionBreakpoints).to.have.length(1);
|
|
685
|
+
(0, chai_1.expect)(data.exceptionBreakpoints[0].raw.filter).to.equal('all');
|
|
686
|
+
});
|
|
687
|
+
});
|
|
688
|
+
describe('BreakpointManager — file deletion', () => {
|
|
689
|
+
let manager;
|
|
690
|
+
let fileChangeEmitter;
|
|
691
|
+
beforeEach(() => {
|
|
692
|
+
({ manager, fileChangeEmitter } = createManager());
|
|
693
|
+
});
|
|
694
|
+
it('when a file is deleted, its source breakpoints are removed and onDidChangeMarkers fires', () => {
|
|
695
|
+
manager.setBreakpoints(FILE_A, [makeSourceBreakpoint(FILE_A, 10)]);
|
|
696
|
+
manager.setBreakpoints(FILE_B, [makeSourceBreakpoint(FILE_B, 5)]);
|
|
697
|
+
(0, chai_1.expect)(manager.getBreakpoints(FILE_A)).to.have.length(1);
|
|
698
|
+
const markerUris = [];
|
|
699
|
+
manager.onDidChangeMarkers(uri => markerUris.push(uri.toString()));
|
|
700
|
+
fileChangeEmitter.fire(new files_1.FileChangesEvent([{
|
|
701
|
+
resource: FILE_A,
|
|
702
|
+
type: 2 /* FileChangeType.DELETED */,
|
|
703
|
+
}]));
|
|
704
|
+
(0, chai_1.expect)(manager.getBreakpoints(FILE_A)).to.have.length(0);
|
|
705
|
+
(0, chai_1.expect)(markerUris).to.include(FILE_A.toString());
|
|
706
|
+
// FILE_B should be untouched
|
|
707
|
+
(0, chai_1.expect)(manager.getBreakpoints(FILE_B)).to.have.length(1);
|
|
708
|
+
});
|
|
709
|
+
});
|
|
710
|
+
describe('BreakpointManager — fireTypedBreakpointEvent dispatch', () => {
|
|
711
|
+
let manager;
|
|
712
|
+
beforeEach(() => {
|
|
713
|
+
({ manager } = createManager());
|
|
714
|
+
});
|
|
715
|
+
it('fires onDidChangeBreakpoints for DebugSourceBreakpoint instances', () => {
|
|
716
|
+
manager.setBreakpoints(FILE_A, [makeSourceBreakpoint(FILE_A, 10)]);
|
|
717
|
+
const events = [];
|
|
718
|
+
manager.onDidChangeBreakpoints(e => events.push(e));
|
|
719
|
+
const wrapper = manager.getBreakpoints(FILE_A)[0];
|
|
720
|
+
manager.fireBreakpointChanged(wrapper);
|
|
721
|
+
(0, chai_1.expect)(events).to.have.length(1);
|
|
722
|
+
(0, chai_1.expect)(events[0].changed).to.include(wrapper);
|
|
723
|
+
});
|
|
724
|
+
it('fires onDidChangeFunctionBreakpoints for DebugFunctionBreakpoint instances', () => {
|
|
725
|
+
manager.addFunctionBreakpoint(makeFunctionBreakpoint('fn'));
|
|
726
|
+
const events = [];
|
|
727
|
+
manager.onDidChangeFunctionBreakpoints(e => events.push(e));
|
|
728
|
+
const wrapper = manager.getFunctionBreakpoints()[0];
|
|
729
|
+
manager.fireBreakpointChanged(wrapper);
|
|
730
|
+
(0, chai_1.expect)(events).to.have.length(1);
|
|
731
|
+
(0, chai_1.expect)(events[0].changed[0]).to.equal(wrapper);
|
|
732
|
+
});
|
|
733
|
+
it('fires onDidChangeInstructionBreakpoints for DebugInstructionBreakpoint instances', () => {
|
|
734
|
+
manager.addInstructionBreakpoint('0xABC', 0);
|
|
735
|
+
const events = [];
|
|
736
|
+
manager.onDidChangeInstructionBreakpoints(e => events.push(e));
|
|
737
|
+
const wrapper = manager.getInstructionBreakpoints()[0];
|
|
738
|
+
manager.fireBreakpointChanged(wrapper);
|
|
739
|
+
(0, chai_1.expect)(events).to.have.length(1);
|
|
740
|
+
(0, chai_1.expect)(events[0].changed[0]).to.equal(wrapper);
|
|
741
|
+
});
|
|
742
|
+
it('fires onDidChangeDataBreakpoints for DebugDataBreakpoint instances', () => {
|
|
743
|
+
manager.addDataBreakpoint(makeDataBreakpoint('d1'));
|
|
744
|
+
const events = [];
|
|
745
|
+
manager.onDidChangeDataBreakpoints(e => events.push(e));
|
|
746
|
+
const wrapper = manager.getDataBreakpoints()[0];
|
|
747
|
+
manager.fireBreakpointChanged(wrapper);
|
|
748
|
+
(0, chai_1.expect)(events).to.have.length(1);
|
|
749
|
+
(0, chai_1.expect)(events[0].changed[0]).to.equal(wrapper);
|
|
750
|
+
});
|
|
751
|
+
});
|
|
752
|
+
describe('BreakpointManager — query helpers', () => {
|
|
753
|
+
let manager;
|
|
754
|
+
beforeEach(() => {
|
|
755
|
+
({ manager } = createManager());
|
|
756
|
+
});
|
|
757
|
+
it('getLineBreakpoints returns breakpoints at a specific line', () => {
|
|
758
|
+
manager.setBreakpoints(FILE_A, [
|
|
759
|
+
makeSourceBreakpoint(FILE_A, 10),
|
|
760
|
+
makeSourceBreakpoint(FILE_A, 20),
|
|
761
|
+
makeSourceBreakpoint(FILE_A, 10, { column: 5 }),
|
|
762
|
+
]);
|
|
763
|
+
const atLine10 = manager.getLineBreakpoints(FILE_A, 10);
|
|
764
|
+
(0, chai_1.expect)(atLine10).to.have.length(2);
|
|
765
|
+
});
|
|
766
|
+
it('getBreakpointById finds across all types', () => {
|
|
767
|
+
manager.setBreakpoints(FILE_A, [makeSourceBreakpoint(FILE_A, 10)]);
|
|
768
|
+
manager.addFunctionBreakpoint(makeFunctionBreakpoint('fn'));
|
|
769
|
+
manager.addInstructionBreakpoint('0x1', 0);
|
|
770
|
+
manager.addDataBreakpoint(makeDataBreakpoint('d1'));
|
|
771
|
+
const srcBp = manager.getBreakpoints(FILE_A)[0];
|
|
772
|
+
const fnBp = manager.getFunctionBreakpoints()[0];
|
|
773
|
+
const instrBp = manager.getInstructionBreakpoints()[0];
|
|
774
|
+
const dataBp = manager.getDataBreakpoints()[0];
|
|
775
|
+
(0, chai_1.expect)(manager.getBreakpointById(srcBp.id)).to.equal(srcBp);
|
|
776
|
+
(0, chai_1.expect)(manager.getBreakpointById(fnBp.id)).to.equal(fnBp);
|
|
777
|
+
(0, chai_1.expect)(manager.getBreakpointById(instrBp.id)).to.equal(instrBp);
|
|
778
|
+
(0, chai_1.expect)(manager.getBreakpointById(dataBp.id)).to.equal(dataBp);
|
|
779
|
+
(0, chai_1.expect)(manager.getBreakpointById('nonexistent')).to.be.undefined;
|
|
780
|
+
});
|
|
781
|
+
it('allBreakpoints yields all types', () => {
|
|
782
|
+
manager.setBreakpoints(FILE_A, [makeSourceBreakpoint(FILE_A, 10)]);
|
|
783
|
+
manager.addFunctionBreakpoint(makeFunctionBreakpoint('fn'));
|
|
784
|
+
manager.addInstructionBreakpoint('0x1', 0);
|
|
785
|
+
manager.addDataBreakpoint(makeDataBreakpoint('d1'));
|
|
786
|
+
manager.addExceptionBreakpoints([{ filter: 'all', label: 'All' }], 's1');
|
|
787
|
+
const all = [...manager.allBreakpoints()];
|
|
788
|
+
(0, chai_1.expect)(all).to.have.length(5);
|
|
789
|
+
const types = all.map(bp => bp.constructor.name);
|
|
790
|
+
(0, chai_1.expect)(types).to.include('DebugSourceBreakpoint');
|
|
791
|
+
(0, chai_1.expect)(types).to.include('DebugFunctionBreakpoint');
|
|
792
|
+
(0, chai_1.expect)(types).to.include('DebugInstructionBreakpoint');
|
|
793
|
+
(0, chai_1.expect)(types).to.include('DebugDataBreakpoint');
|
|
794
|
+
(0, chai_1.expect)(types).to.include('DebugExceptionBreakpoint');
|
|
795
|
+
});
|
|
796
|
+
it('hasBreakpoints returns true when any type exists', () => {
|
|
797
|
+
(0, chai_1.expect)(manager.hasBreakpoints()).to.be.false;
|
|
798
|
+
manager.addFunctionBreakpoint(makeFunctionBreakpoint('fn'));
|
|
799
|
+
(0, chai_1.expect)(manager.hasBreakpoints()).to.be.true;
|
|
800
|
+
});
|
|
801
|
+
it('getUris returns all URIs with source breakpoints', () => {
|
|
802
|
+
manager.setBreakpoints(FILE_A, [makeSourceBreakpoint(FILE_A, 10)]);
|
|
803
|
+
manager.setBreakpoints(FILE_B, [makeSourceBreakpoint(FILE_B, 5)]);
|
|
804
|
+
const uris = [...manager.getUris()];
|
|
805
|
+
(0, chai_1.expect)(uris).to.have.length(2);
|
|
806
|
+
(0, chai_1.expect)(uris).to.include(FILE_A.toString());
|
|
807
|
+
(0, chai_1.expect)(uris).to.include(FILE_B.toString());
|
|
808
|
+
});
|
|
809
|
+
it('getBreakpoints with no URI returns all source breakpoints', () => {
|
|
810
|
+
manager.setBreakpoints(FILE_A, [makeSourceBreakpoint(FILE_A, 10)]);
|
|
811
|
+
manager.setBreakpoints(FILE_B, [makeSourceBreakpoint(FILE_B, 5)]);
|
|
812
|
+
const all = manager.getBreakpoints();
|
|
813
|
+
(0, chai_1.expect)(all).to.have.length(2);
|
|
814
|
+
});
|
|
815
|
+
it('removeBreakpoints clears all breakpoints of all types', () => {
|
|
816
|
+
manager.setBreakpoints(FILE_A, [makeSourceBreakpoint(FILE_A, 10)]);
|
|
817
|
+
manager.addFunctionBreakpoint(makeFunctionBreakpoint('fn'));
|
|
818
|
+
manager.addInstructionBreakpoint('0x1', 0);
|
|
819
|
+
manager.addDataBreakpoint(makeDataBreakpoint('d1'));
|
|
820
|
+
manager.removeBreakpoints();
|
|
821
|
+
(0, chai_1.expect)(manager.getBreakpoints()).to.have.length(0);
|
|
822
|
+
(0, chai_1.expect)(manager.getFunctionBreakpoints()).to.have.length(0);
|
|
823
|
+
(0, chai_1.expect)(manager.getInstructionBreakpoints()).to.have.length(0);
|
|
824
|
+
(0, chai_1.expect)(manager.getDataBreakpoints()).to.have.length(0);
|
|
825
|
+
});
|
|
826
|
+
});
|
|
827
|
+
describe('BreakpointManager — updateBreakpoint', () => {
|
|
828
|
+
let manager;
|
|
829
|
+
beforeEach(() => {
|
|
830
|
+
({ manager } = createManager());
|
|
831
|
+
});
|
|
832
|
+
it('updateBreakpoint merges partial raw and fires changed event', () => {
|
|
833
|
+
const bp = makeSourceBreakpoint(FILE_A, 10);
|
|
834
|
+
manager.setBreakpoints(FILE_A, [bp]);
|
|
835
|
+
const wrapper = manager.getBreakpoints(FILE_A)[0];
|
|
836
|
+
const events = [];
|
|
837
|
+
manager.onDidChangeBreakpoints(e => events.push(e));
|
|
838
|
+
manager.updateBreakpoint(wrapper, { condition: 'x > 10' });
|
|
839
|
+
(0, chai_1.expect)(wrapper.origin.raw.condition).to.equal('x > 10');
|
|
840
|
+
(0, chai_1.expect)(wrapper.origin.raw.line).to.equal(10); // line preserved
|
|
841
|
+
(0, chai_1.expect)(events).to.have.length(1);
|
|
842
|
+
});
|
|
843
|
+
it('updateDataBreakpoint updates enabled and raw fields', () => {
|
|
844
|
+
manager.addDataBreakpoint(makeDataBreakpoint('d1'));
|
|
845
|
+
const wrapper = manager.getDataBreakpoints()[0];
|
|
846
|
+
const events = [];
|
|
847
|
+
manager.onDidChangeDataBreakpoints(e => events.push(e));
|
|
848
|
+
manager.updateDataBreakpoint(wrapper, { enabled: false, raw: { condition: 'val > 0' } });
|
|
849
|
+
(0, chai_1.expect)(wrapper.origin.enabled).to.be.false;
|
|
850
|
+
(0, chai_1.expect)(wrapper.origin.raw.condition).to.equal('val > 0');
|
|
851
|
+
(0, chai_1.expect)(events).to.have.length(1);
|
|
852
|
+
});
|
|
853
|
+
it('updateDataBreakpoint on unknown breakpoint is a no-op', () => {
|
|
854
|
+
const orphan = debug_data_breakpoint_1.DebugDataBreakpoint.create(makeDataBreakpoint('orphan'), manager.getBreakpointOptions());
|
|
855
|
+
const events = [];
|
|
856
|
+
manager.onDidChangeDataBreakpoints(e => events.push(e));
|
|
857
|
+
manager.updateDataBreakpoint(orphan, { enabled: false });
|
|
858
|
+
(0, chai_1.expect)(events).to.have.length(0);
|
|
859
|
+
});
|
|
860
|
+
});
|
|
861
|
+
//# sourceMappingURL=breakpoint-manager.spec.js.map
|