chrome-devtools-frontend 1.0.1015822 → 1.0.1016075
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/front_end/core/sdk/DebuggerModel.ts +2 -2
- package/front_end/core/sdk/Script.ts +10 -9
- package/front_end/models/bindings/BreakpointManager.ts +145 -92
- package/front_end/models/bindings/ResourceScriptMapping.ts +21 -7
- package/front_end/models/source_map_scopes/NamesResolver.ts +9 -5
- package/package.json +1 -1
@@ -314,7 +314,7 @@ export class DebuggerModel extends SDKModel<EventTypes> {
|
|
314
314
|
await this.agent.invoke_disable();
|
315
315
|
this.#isPausingInternal = false;
|
316
316
|
this.globalObjectCleared();
|
317
|
-
this.dispatchEventToListeners(Events.DebuggerWasDisabled);
|
317
|
+
this.dispatchEventToListeners(Events.DebuggerWasDisabled, this);
|
318
318
|
if (typeof this.#debuggerId === 'string') {
|
319
319
|
_debuggerIdToModel.delete(this.#debuggerId);
|
320
320
|
}
|
@@ -973,7 +973,7 @@ export enum Events {
|
|
973
973
|
|
974
974
|
export type EventTypes = {
|
975
975
|
[Events.DebuggerWasEnabled]: DebuggerModel,
|
976
|
-
[Events.DebuggerWasDisabled]:
|
976
|
+
[Events.DebuggerWasDisabled]: DebuggerModel,
|
977
977
|
[Events.DebuggerPaused]: DebuggerModel,
|
978
978
|
[Events.DebuggerResumed]: DebuggerModel,
|
979
979
|
[Events.ParsedScriptSource]: Script,
|
@@ -257,28 +257,29 @@ export class Script implements TextUtils.ContentProvider.ContentProvider, FrameA
|
|
257
257
|
return source + '\n //# sourceURL=' + this.sourceURL;
|
258
258
|
}
|
259
259
|
|
260
|
-
async editSource(newSource: string):
|
261
|
-
|
260
|
+
async editSource(newSource: string): Promise<
|
261
|
+
{status: Protocol.Debugger.SetScriptSourceResponseStatus, exceptionDetails?: Protocol.Runtime.ExceptionDetails}> {
|
262
262
|
newSource = Script.trimSourceURLComment(newSource);
|
263
263
|
// We append correct #sourceURL to script for consistency only. It's not actually needed for things to work correctly.
|
264
264
|
newSource = this.appendSourceURLCommentIfNeeded(newSource);
|
265
265
|
|
266
|
-
if (!this.scriptId) {
|
267
|
-
return {error: 'Script failed to parse'};
|
268
|
-
}
|
269
|
-
|
270
266
|
const {content: oldSource} = await this.requestContent();
|
271
267
|
if (oldSource === newSource) {
|
272
|
-
return {
|
268
|
+
return {status: Protocol.Debugger.SetScriptSourceResponseStatus.Ok};
|
273
269
|
}
|
274
270
|
const response = await this.debuggerModel.target().debuggerAgent().invoke_setScriptSource(
|
275
271
|
{scriptId: this.scriptId, scriptSource: newSource});
|
272
|
+
if (response.getError()) {
|
273
|
+
// Something went seriously wrong, like the V8 inspector no longer knowing about this script without
|
274
|
+
// shutting down the Debugger agent etc.
|
275
|
+
throw new Error(`Script#editSource failed for script with id ${this.scriptId}: ${response.getError()}`);
|
276
|
+
}
|
276
277
|
|
277
|
-
if (!response.getError() &&
|
278
|
+
if (!response.getError() && response.status === Protocol.Debugger.SetScriptSourceResponseStatus.Ok) {
|
278
279
|
this.#contentPromise = Promise.resolve({content: newSource, isEncoded: false});
|
279
280
|
}
|
280
281
|
|
281
|
-
return {
|
282
|
+
return {status: response.status, exceptionDetails: response.exceptionDetails};
|
282
283
|
}
|
283
284
|
|
284
285
|
rawLocation(lineNumber: number, columnNumber: number): Location|null {
|
@@ -409,6 +409,18 @@ export type EventTypes = {
|
|
409
409
|
[Events.BreakpointRemoved]: BreakpointLocation,
|
410
410
|
};
|
411
411
|
|
412
|
+
const enum DebuggerUpdateResult {
|
413
|
+
OK = 'OK',
|
414
|
+
ERROR = 'ERROR',
|
415
|
+
// PENDING implies that the current update requires another re-run.
|
416
|
+
PENDING = 'PENDING',
|
417
|
+
}
|
418
|
+
|
419
|
+
const enum ResolveLocationResult {
|
420
|
+
OK = 'OK',
|
421
|
+
ERROR = 'ERROR',
|
422
|
+
}
|
423
|
+
|
412
424
|
export class Breakpoint implements SDK.TargetManager.SDKModelObserver<SDK.DebuggerModel.DebuggerModel> {
|
413
425
|
readonly breakpointManager: BreakpointManager;
|
414
426
|
urlInternal: Platform.DevToolsPath.UrlString;
|
@@ -444,25 +456,49 @@ export class Breakpoint implements SDK.TargetManager.SDKModelObserver<SDK.Debugg
|
|
444
456
|
|
445
457
|
async refreshInDebugger(): Promise<void> {
|
446
458
|
if (!this.isRemoved) {
|
447
|
-
const
|
448
|
-
await Promise.all(
|
459
|
+
const modelBreakpoints = Array.from(this.#modelBreakpoints.values());
|
460
|
+
await Promise.all(modelBreakpoints.map(async modelBreakpoint => {
|
461
|
+
await modelBreakpoint.resetBreakpoint();
|
462
|
+
return this.#updateModel(modelBreakpoint);
|
463
|
+
}));
|
449
464
|
}
|
450
465
|
}
|
451
466
|
|
452
467
|
modelAdded(debuggerModel: SDK.DebuggerModel.DebuggerModel): void {
|
453
468
|
const debuggerWorkspaceBinding = this.breakpointManager.debuggerWorkspaceBinding;
|
454
|
-
|
469
|
+
const modelBreakpoint = new ModelBreakpoint(debuggerModel, this, debuggerWorkspaceBinding);
|
470
|
+
this.#modelBreakpoints.set(debuggerModel, modelBreakpoint);
|
471
|
+
void this.#updateModel(modelBreakpoint);
|
472
|
+
|
473
|
+
debuggerModel.addEventListener(SDK.DebuggerModel.Events.DebuggerWasEnabled, this.#onDebuggerEnabled, this);
|
474
|
+
debuggerModel.addEventListener(SDK.DebuggerModel.Events.DebuggerWasDisabled, this.#onDebuggerDisabled, this);
|
455
475
|
}
|
456
476
|
|
457
477
|
modelRemoved(debuggerModel: SDK.DebuggerModel.DebuggerModel): void {
|
458
478
|
const modelBreakpoint = this.#modelBreakpoints.get(debuggerModel);
|
479
|
+
modelBreakpoint?.cleanUpAfterDebuggerIsGone();
|
459
480
|
this.#modelBreakpoints.delete(debuggerModel);
|
460
481
|
|
461
|
-
|
462
|
-
|
482
|
+
this.#removeDebuggerModelListeners(debuggerModel);
|
483
|
+
}
|
484
|
+
|
485
|
+
#removeDebuggerModelListeners(debuggerModel: SDK.DebuggerModel.DebuggerModel): void {
|
486
|
+
debuggerModel.removeEventListener(SDK.DebuggerModel.Events.DebuggerWasEnabled, this.#onDebuggerEnabled, this);
|
487
|
+
debuggerModel.removeEventListener(SDK.DebuggerModel.Events.DebuggerWasDisabled, this.#onDebuggerDisabled, this);
|
488
|
+
}
|
489
|
+
|
490
|
+
#onDebuggerEnabled(event: Common.EventTarget.EventTargetEvent<SDK.DebuggerModel.DebuggerModel>): void {
|
491
|
+
const debuggerModel = event.data;
|
492
|
+
const model = this.#modelBreakpoints.get(debuggerModel);
|
493
|
+
if (model) {
|
494
|
+
void this.#updateModel(model);
|
463
495
|
}
|
464
|
-
|
465
|
-
|
496
|
+
}
|
497
|
+
|
498
|
+
#onDebuggerDisabled(event: Common.EventTarget.EventTargetEvent<SDK.DebuggerModel.DebuggerModel>): void {
|
499
|
+
const debuggerModel = event.data;
|
500
|
+
const model = this.#modelBreakpoints.get(debuggerModel);
|
501
|
+
model?.cleanUpAfterDebuggerIsGone();
|
466
502
|
}
|
467
503
|
|
468
504
|
modelBreakpoint(debuggerModel: SDK.DebuggerModel.DebuggerModel): ModelBreakpoint|undefined {
|
@@ -589,21 +625,17 @@ export class Breakpoint implements SDK.TargetManager.SDKModelObserver<SDK.Debugg
|
|
589
625
|
this.addAllUnboundLocations();
|
590
626
|
}
|
591
627
|
}
|
592
|
-
|
593
|
-
Array.from(this.#modelBreakpoints.values()).map(modelBreakpoint => modelBreakpoint.scheduleUpdateInDebugger()));
|
628
|
+
return this.#updateModels();
|
594
629
|
}
|
595
630
|
|
596
631
|
async remove(keepInStorage: boolean): Promise<void> {
|
597
632
|
this.isRemoved = true;
|
598
633
|
const removeFromStorage = !keepInStorage;
|
599
634
|
|
600
|
-
|
601
|
-
|
602
|
-
for (const modelBreakpoint of this.#modelBreakpoints.values()) {
|
603
|
-
modelBreakpoint.removeEventListeners();
|
604
|
-
updatePromises.push(modelBreakpoint.scheduleUpdateInDebugger());
|
635
|
+
for (const debuggerModel of this.#modelBreakpoints.keys()) {
|
636
|
+
this.#removeDebuggerModelListeners(debuggerModel);
|
605
637
|
}
|
606
|
-
await
|
638
|
+
await this.#updateModels();
|
607
639
|
|
608
640
|
this.breakpointManager.removeBreakpoint(this, removeFromStorage);
|
609
641
|
this.breakpointManager.targetManager.unobserveModels(SDK.DebuggerModel.DebuggerModel, this);
|
@@ -638,6 +670,17 @@ export class Breakpoint implements SDK.TargetManager.SDKModelObserver<SDK.Debugg
|
|
638
670
|
getIsRemoved(): boolean {
|
639
671
|
return this.isRemoved;
|
640
672
|
}
|
673
|
+
|
674
|
+
async #updateModels(): Promise<void> {
|
675
|
+
await Promise.all(Array.from(this.#modelBreakpoints.values()).map(model => this.#updateModel(model)));
|
676
|
+
}
|
677
|
+
|
678
|
+
async #updateModel(model: ModelBreakpoint): Promise<void> {
|
679
|
+
const success = await model.scheduleUpdateInDebugger();
|
680
|
+
if (!success) {
|
681
|
+
await this.remove(false);
|
682
|
+
}
|
683
|
+
}
|
641
684
|
}
|
642
685
|
|
643
686
|
export class ModelBreakpoint {
|
@@ -646,8 +689,7 @@ export class ModelBreakpoint {
|
|
646
689
|
readonly #debuggerWorkspaceBinding: DebuggerWorkspaceBinding;
|
647
690
|
readonly #liveLocations: LiveLocationPool;
|
648
691
|
readonly #uiLocations: Map<LiveLocation, Workspace.UISourceCode.UILocation>;
|
649
|
-
#
|
650
|
-
#updatePromise: Promise<void>|null;
|
692
|
+
#updateMutex = new Common.Mutex.Mutex();
|
651
693
|
#cancelCallback: boolean;
|
652
694
|
#currentState: Breakpoint.State|null;
|
653
695
|
#breakpointIds: Protocol.Debugger.BreakpointId[];
|
@@ -662,18 +704,9 @@ export class ModelBreakpoint {
|
|
662
704
|
this.#liveLocations = new LiveLocationPool();
|
663
705
|
|
664
706
|
this.#uiLocations = new Map();
|
665
|
-
this.#debuggerModel.addEventListener(
|
666
|
-
SDK.DebuggerModel.Events.DebuggerWasDisabled, this.cleanUpAfterDebuggerIsGone, this);
|
667
|
-
this.#debuggerModel.addEventListener(
|
668
|
-
SDK.DebuggerModel.Events.DebuggerWasEnabled, this.scheduleUpdateInDebugger, this);
|
669
|
-
this.#hasPendingUpdate = false;
|
670
|
-
this.#updatePromise = null;
|
671
707
|
this.#cancelCallback = false;
|
672
708
|
this.#currentState = null;
|
673
709
|
this.#breakpointIds = [];
|
674
|
-
if (this.#debuggerModel.debuggerEnabled()) {
|
675
|
-
void this.scheduleUpdateInDebugger();
|
676
|
-
}
|
677
710
|
}
|
678
711
|
|
679
712
|
get currentState(): Breakpoint.State|null {
|
@@ -689,18 +722,20 @@ export class ModelBreakpoint {
|
|
689
722
|
this.#liveLocations.disposeAll();
|
690
723
|
}
|
691
724
|
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
725
|
+
// Returns true, if scheduling ran as expected.
|
726
|
+
// Returns false, if an error occurred.
|
727
|
+
async scheduleUpdateInDebugger(): Promise<boolean> {
|
728
|
+
if (!this.#debuggerModel.debuggerEnabled()) {
|
729
|
+
return true;
|
730
|
+
}
|
731
|
+
|
732
|
+
const release = await this.#updateMutex.acquire();
|
733
|
+
let result = DebuggerUpdateResult.PENDING;
|
734
|
+
while (result === DebuggerUpdateResult.PENDING) {
|
735
|
+
result = await this.#updateInDebugger();
|
702
736
|
}
|
703
|
-
|
737
|
+
release();
|
738
|
+
return result === DebuggerUpdateResult.OK;
|
704
739
|
}
|
705
740
|
|
706
741
|
private scriptDiverged(): boolean {
|
@@ -713,16 +748,16 @@ export class ModelBreakpoint {
|
|
713
748
|
return false;
|
714
749
|
}
|
715
750
|
|
716
|
-
|
751
|
+
async #updateInDebugger(): Promise<DebuggerUpdateResult> {
|
717
752
|
if (this.#debuggerModel.target().isDisposed()) {
|
718
753
|
this.cleanUpAfterDebuggerIsGone();
|
719
|
-
return;
|
754
|
+
return DebuggerUpdateResult.OK;
|
720
755
|
}
|
721
|
-
|
722
756
|
const lineNumber = this.#breakpoint.lineNumber();
|
723
757
|
const columnNumber = this.#breakpoint.columnNumber();
|
724
758
|
const condition = this.#breakpoint.condition();
|
725
759
|
|
760
|
+
// Calculate the new state.
|
726
761
|
let newState: Breakpoint.State|null = null;
|
727
762
|
if (!this.#breakpoint.getIsRemoved() && this.#breakpoint.enabled() && !this.scriptDiverged()) {
|
728
763
|
let debuggerLocations: SDK.DebuggerModel.Location[] = [];
|
@@ -766,71 +801,97 @@ export class ModelBreakpoint {
|
|
766
801
|
}
|
767
802
|
}
|
768
803
|
}
|
804
|
+
const hasBackendState = this.#breakpointIds.length;
|
769
805
|
|
770
|
-
|
771
|
-
|
806
|
+
// Case 1: State hasn't changed, and back-end is up to date and has information
|
807
|
+
// on some breakpoints.
|
808
|
+
if (hasBackendState && Breakpoint.State.equals(newState, this.#currentState)) {
|
809
|
+
return DebuggerUpdateResult.OK;
|
772
810
|
}
|
811
|
+
|
773
812
|
this.#breakpoint.currentState = newState;
|
774
813
|
|
775
|
-
|
776
|
-
|
777
|
-
|
814
|
+
// Case 2: State has changed, and the back-end has outdated information on old
|
815
|
+
// breakpoints.
|
816
|
+
if (hasBackendState) {
|
817
|
+
// Reset the current state.
|
818
|
+
await this.resetBreakpoint();
|
819
|
+
// Schedule another run of updates, to finally update to the new state.
|
820
|
+
return DebuggerUpdateResult.PENDING;
|
778
821
|
}
|
779
822
|
|
823
|
+
// Case 3: State is null (no breakpoints to set), and back-end is up to date
|
824
|
+
// (no info on breakpoints).
|
780
825
|
if (!newState) {
|
781
|
-
return;
|
826
|
+
return DebuggerUpdateResult.OK;
|
782
827
|
}
|
783
828
|
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
}
|
788
|
-
return this.#debuggerModel.setBreakpointInAnonymousScript(
|
789
|
-
pos.scriptId, pos.scriptHash as string, pos.lineNumber, pos.columnNumber, condition);
|
790
|
-
}));
|
791
|
-
const breakpointIds: Protocol.Debugger.BreakpointId[] = [];
|
792
|
-
let locations: SDK.DebuggerModel.Location[] = [];
|
793
|
-
let maybeRescheduleUpdate = false;
|
794
|
-
for (const result of results) {
|
795
|
-
if (result.breakpointId) {
|
796
|
-
breakpointIds.push(result.breakpointId);
|
797
|
-
locations = locations.concat(result.locations);
|
798
|
-
} else if (this.#debuggerModel.debuggerEnabled() && !this.#debuggerModel.isReadyToPause()) {
|
799
|
-
maybeRescheduleUpdate = true;
|
800
|
-
}
|
801
|
-
}
|
829
|
+
// Case 4: State is not null, so we have breakpoints to set and the back-end
|
830
|
+
// has no information on breakpoints yet. Set the breakpoints.
|
831
|
+
const {breakpointIds, locations, serverError} = await this.#setBreakpointOnBackend(newState);
|
802
832
|
|
833
|
+
const maybeRescheduleUpdate =
|
834
|
+
serverError && this.#debuggerModel.debuggerEnabled() && !this.#debuggerModel.isReadyToPause();
|
803
835
|
if (!breakpointIds.length && maybeRescheduleUpdate) {
|
804
836
|
// TODO(crbug.com/1229541): This is a quickfix to prevent #breakpoints from
|
805
837
|
// disappearing if the Debugger is actually not enabled
|
806
838
|
// yet. This quickfix should be removed as soon as we have a solution
|
807
839
|
// to correctly synchronize the front-end with the inspector back-end.
|
808
|
-
|
809
|
-
return;
|
840
|
+
return DebuggerUpdateResult.PENDING;
|
810
841
|
}
|
811
842
|
|
812
843
|
this.#currentState = newState;
|
813
844
|
if (this.#cancelCallback) {
|
814
845
|
this.#cancelCallback = false;
|
815
|
-
return;
|
846
|
+
return DebuggerUpdateResult.OK;
|
816
847
|
}
|
817
848
|
|
849
|
+
// Something went wrong: we expect to have a non-null state, but have not received any
|
850
|
+
// breakpointIds from the back-end.
|
818
851
|
if (!breakpointIds.length) {
|
819
|
-
|
820
|
-
// dependency. Removing breakpoints will call `scheduleUpdateInDebugger` again.
|
821
|
-
// Calling it again would cause it to await this current run of `scheduleInDebugger`, which
|
822
|
-
// will then deadlock.
|
823
|
-
void this.#breakpoint.remove(true);
|
824
|
-
return;
|
852
|
+
return DebuggerUpdateResult.ERROR;
|
825
853
|
}
|
826
854
|
|
827
855
|
this.#breakpointIds = breakpointIds;
|
828
856
|
this.#breakpointIds.forEach(
|
829
857
|
breakpointId => this.#debuggerModel.addBreakpointListener(breakpointId, this.breakpointResolved, this));
|
830
|
-
await Promise.all(locations.map(location => this.addResolvedLocation(location)));
|
858
|
+
const resolvedResults = await Promise.all(locations.map(location => this.addResolvedLocation(location)));
|
859
|
+
|
860
|
+
// Breakpoint clash: the resolved location resolves to a different breakpoint, report an error.
|
861
|
+
if (resolvedResults.includes(ResolveLocationResult.ERROR)) {
|
862
|
+
return DebuggerUpdateResult.ERROR;
|
863
|
+
}
|
864
|
+
return DebuggerUpdateResult.OK;
|
865
|
+
}
|
866
|
+
|
867
|
+
async #setBreakpointOnBackend(newState: Breakpoint.State): Promise<{
|
868
|
+
breakpointIds: Protocol.Debugger.BreakpointId[],
|
869
|
+
locations: SDK.DebuggerModel.Location[],
|
870
|
+
serverError: boolean,
|
871
|
+
}> {
|
872
|
+
const condition = this.#breakpoint.condition();
|
873
|
+
const results = await Promise.all(newState.positions.map(pos => {
|
874
|
+
if (pos.url) {
|
875
|
+
return this.#debuggerModel.setBreakpointByURL(pos.url, pos.lineNumber, pos.columnNumber, condition);
|
876
|
+
}
|
877
|
+
return this.#debuggerModel.setBreakpointInAnonymousScript(
|
878
|
+
pos.scriptId, pos.scriptHash as string, pos.lineNumber, pos.columnNumber, condition);
|
879
|
+
}));
|
880
|
+
const breakpointIds: Protocol.Debugger.BreakpointId[] = [];
|
881
|
+
let locations: SDK.DebuggerModel.Location[] = [];
|
882
|
+
let serverError = false;
|
883
|
+
for (const result of results) {
|
884
|
+
if (result.breakpointId) {
|
885
|
+
breakpointIds.push(result.breakpointId);
|
886
|
+
locations = locations.concat(result.locations);
|
887
|
+
} else {
|
888
|
+
serverError = true;
|
889
|
+
}
|
890
|
+
}
|
891
|
+
return {breakpointIds, locations, serverError};
|
831
892
|
}
|
832
893
|
|
833
|
-
async
|
894
|
+
async resetBreakpoint(): Promise<void> {
|
834
895
|
if (!this.#breakpointIds.length) {
|
835
896
|
return;
|
836
897
|
}
|
@@ -838,7 +899,6 @@ export class ModelBreakpoint {
|
|
838
899
|
await Promise.all(this.#breakpointIds.map(id => this.#debuggerModel.removeBreakpoint(id)));
|
839
900
|
this.didRemoveFromDebugger();
|
840
901
|
this.#currentState = null;
|
841
|
-
void this.scheduleUpdateInDebugger();
|
842
902
|
}
|
843
903
|
|
844
904
|
private didRemoveFromDebugger(): void {
|
@@ -855,7 +915,10 @@ export class ModelBreakpoint {
|
|
855
915
|
|
856
916
|
private async breakpointResolved({data: location}: Common.EventTarget.EventTargetEvent<SDK.DebuggerModel.Location>):
|
857
917
|
Promise<void> {
|
858
|
-
await this.addResolvedLocation(location);
|
918
|
+
const result = await this.addResolvedLocation(location);
|
919
|
+
if (result === ResolveLocationResult.ERROR) {
|
920
|
+
await this.#breakpoint.remove(false);
|
921
|
+
}
|
859
922
|
}
|
860
923
|
|
861
924
|
private async locationUpdated(liveLocation: LiveLocation): Promise<void> {
|
@@ -874,39 +937,29 @@ export class ModelBreakpoint {
|
|
874
937
|
}
|
875
938
|
}
|
876
939
|
|
877
|
-
private async addResolvedLocation(location: SDK.DebuggerModel.Location): Promise<
|
940
|
+
private async addResolvedLocation(location: SDK.DebuggerModel.Location): Promise<ResolveLocationResult> {
|
878
941
|
const uiLocation = await this.#debuggerWorkspaceBinding.rawLocationToUILocation(location);
|
879
942
|
if (!uiLocation) {
|
880
|
-
return;
|
943
|
+
return ResolveLocationResult.OK;
|
881
944
|
}
|
882
945
|
const breakpointLocation = this.#breakpoint.breakpointManager.findBreakpoint(uiLocation);
|
883
946
|
if (breakpointLocation && breakpointLocation.breakpoint !== this.#breakpoint) {
|
884
947
|
// location clash
|
885
|
-
|
886
|
-
return;
|
948
|
+
return ResolveLocationResult.ERROR;
|
887
949
|
}
|
888
950
|
await this.#debuggerWorkspaceBinding.createLiveLocation(
|
889
951
|
location, this.locationUpdated.bind(this), this.#liveLocations);
|
952
|
+
return ResolveLocationResult.OK;
|
890
953
|
}
|
891
954
|
|
892
955
|
cleanUpAfterDebuggerIsGone(): void {
|
893
|
-
|
894
|
-
this.#cancelCallback = true;
|
895
|
-
}
|
896
|
-
this.#hasPendingUpdate = false;
|
956
|
+
this.#cancelCallback = true;
|
897
957
|
this.resetLocations();
|
898
958
|
this.#currentState = null;
|
899
959
|
if (this.#breakpointIds.length) {
|
900
960
|
this.didRemoveFromDebugger();
|
901
961
|
}
|
902
962
|
}
|
903
|
-
|
904
|
-
removeEventListeners(): void {
|
905
|
-
this.#debuggerModel.removeEventListener(
|
906
|
-
SDK.DebuggerModel.Events.DebuggerWasDisabled, this.cleanUpAfterDebuggerIsGone, this);
|
907
|
-
this.#debuggerModel.removeEventListener(
|
908
|
-
SDK.DebuggerModel.Events.DebuggerWasEnabled, this.scheduleUpdateInDebugger, this);
|
909
|
-
}
|
910
963
|
}
|
911
964
|
|
912
965
|
interface Position {
|
@@ -33,7 +33,7 @@ import * as i18n from '../../core/i18n/i18n.js';
|
|
33
33
|
import type * as Platform from '../../core/platform/platform.js';
|
34
34
|
import * as SDK from '../../core/sdk/sdk.js';
|
35
35
|
import * as Workspace from '../workspace/workspace.js';
|
36
|
-
import
|
36
|
+
import * as Protocol from '../../generated/protocol.js';
|
37
37
|
|
38
38
|
import type {Breakpoint} from './BreakpointManager.js';
|
39
39
|
import {BreakpointManager} from './BreakpointManager.js';
|
@@ -320,34 +320,48 @@ export class ResourceScriptFile extends Common.ObjectWrapper.ObjectWrapper<Resou
|
|
320
320
|
.breakpointLocationsForUISourceCode(this.#uiSourceCodeInternal)
|
321
321
|
.map(breakpointLocation => breakpointLocation.breakpoint);
|
322
322
|
const source = this.#uiSourceCodeInternal.workingCopy();
|
323
|
-
void this.scriptInternal.editSource(source).then(({
|
324
|
-
void this.scriptSourceWasSet(source, breakpoints,
|
323
|
+
void this.scriptInternal.editSource(source).then(({status, exceptionDetails}) => {
|
324
|
+
void this.scriptSourceWasSet(source, breakpoints, status, exceptionDetails);
|
325
325
|
});
|
326
326
|
}
|
327
327
|
|
328
328
|
async scriptSourceWasSet(
|
329
|
-
source: string, breakpoints: Breakpoint[],
|
329
|
+
source: string, breakpoints: Breakpoint[], status: Protocol.Debugger.SetScriptSourceResponseStatus,
|
330
330
|
exceptionDetails?: Protocol.Runtime.ExceptionDetails): Promise<void> {
|
331
|
-
if (
|
331
|
+
if (status === Protocol.Debugger.SetScriptSourceResponseStatus.Ok) {
|
332
332
|
this.#scriptSource = source;
|
333
333
|
}
|
334
334
|
await this.update();
|
335
335
|
|
336
|
-
if (
|
336
|
+
if (status === Protocol.Debugger.SetScriptSourceResponseStatus.Ok) {
|
337
337
|
// Live edit can cause #breakpoints to be in the wrong position, or to be lost altogether.
|
338
338
|
// If any #breakpoints were in the pre-live edit script, they need to be re-added.
|
339
339
|
await Promise.all(breakpoints.map(breakpoint => breakpoint.refreshInDebugger()));
|
340
340
|
return;
|
341
341
|
}
|
342
342
|
if (!exceptionDetails) {
|
343
|
+
// TODO(crbug.com/1334484): Instead of to the console, report these errors in an "info bar" at the bottom
|
344
|
+
// of the text editor, similar to e.g. source mapping errors.
|
343
345
|
Common.Console.Console.instance().addMessage(
|
344
|
-
i18nString(UIStrings.liveEditFailed, {PH1:
|
346
|
+
i18nString(UIStrings.liveEditFailed, {PH1: getErrorText(status)}), Common.Console.MessageLevel.Warning);
|
345
347
|
return;
|
346
348
|
}
|
347
349
|
const messageText = i18nString(UIStrings.liveEditCompileFailed, {PH1: exceptionDetails.text});
|
348
350
|
this.#uiSourceCodeInternal.addLineMessage(
|
349
351
|
Workspace.UISourceCode.Message.Level.Error, messageText, exceptionDetails.lineNumber,
|
350
352
|
exceptionDetails.columnNumber);
|
353
|
+
|
354
|
+
function getErrorText(status: Protocol.Debugger.SetScriptSourceResponseStatus): string {
|
355
|
+
switch (status) {
|
356
|
+
case Protocol.Debugger.SetScriptSourceResponseStatus.BlockedByActiveFunction:
|
357
|
+
return 'Functions that are on the stack (currently being executed) can not be edited';
|
358
|
+
case Protocol.Debugger.SetScriptSourceResponseStatus.BlockedByActiveGenerator:
|
359
|
+
return 'Async functions/generators that are active can not be edited';
|
360
|
+
case Protocol.Debugger.SetScriptSourceResponseStatus.CompileError:
|
361
|
+
case Protocol.Debugger.SetScriptSourceResponseStatus.Ok:
|
362
|
+
throw new Error('Compile errors and Ok status must not be reported on the console');
|
363
|
+
}
|
364
|
+
}
|
351
365
|
}
|
352
366
|
|
353
367
|
private async update(): Promise<void> {
|
@@ -181,13 +181,14 @@ export const scopeIdentifiers = async function(
|
|
181
181
|
}
|
182
182
|
};
|
183
183
|
|
184
|
-
const identifierAndPunctuationRegExp = /^\s*([A-Za-z_$][A-Za-z_$0-9]*)\s*([
|
184
|
+
const identifierAndPunctuationRegExp = /^\s*([A-Za-z_$][A-Za-z_$0-9]*)\s*([.;,=]?)\s*$/;
|
185
185
|
|
186
186
|
const enum Punctuation {
|
187
|
-
None =
|
188
|
-
Comma =
|
189
|
-
Dot =
|
190
|
-
Semicolon =
|
187
|
+
None = 'none',
|
188
|
+
Comma = 'comma',
|
189
|
+
Dot = 'dot',
|
190
|
+
Semicolon = 'semicolon',
|
191
|
+
Equals = 'equals',
|
191
192
|
}
|
192
193
|
|
193
194
|
const resolveScope =
|
@@ -341,6 +342,9 @@ const resolveScope =
|
|
341
342
|
case ';':
|
342
343
|
punctuation = Punctuation.Semicolon;
|
343
344
|
break;
|
345
|
+
case '=':
|
346
|
+
punctuation = Punctuation.Equals;
|
347
|
+
break;
|
344
348
|
case '':
|
345
349
|
punctuation = Punctuation.None;
|
346
350
|
break;
|
package/package.json
CHANGED