@@ -57,6 +57,8 @@ export class DevToolsPanel {
57
57
private collectConsoleMessages = true ;
58
58
private currentRevision : string | undefined ;
59
59
private cssWarningActive : boolean ;
60
+ private fallbackChain : ( ( ) => void ) [ ] = [ ] ;
61
+ private getFallbackRevisionFunction : ( ( ) => void ) = ( ) => { } ;
60
62
61
63
private constructor (
62
64
panel : vscode . WebviewPanel ,
@@ -72,7 +74,7 @@ export class DevToolsPanel {
72
74
this . config = config ;
73
75
this . timeStart = null ;
74
76
this . devtoolsBaseUri = this . config . devtoolsBaseUri || null ;
75
- this . isHeadless = false ;
77
+ this . isHeadless = SettingsProvider . instance . getHeadlessSettings ( ) ;
76
78
this . cssWarningActive = false ;
77
79
78
80
// Hook up the socket events
@@ -103,7 +105,12 @@ export class DevToolsPanel {
103
105
// This Websocket is only used on initial connection to determine the browser version.
104
106
// The browser version is used to select the correct hashed version of the devtools
105
107
this . versionDetectionSocket = new BrowserVersionDetectionSocket ( this . targetUrl ) ;
106
- this . versionDetectionSocket . on ( 'setCdnParameters' , ( msg : { revision : string ; isHeadless : boolean } ) => this . setCdnParameters ( msg ) ) ;
108
+
109
+ // Gets an array of functions that will be tried to get the right Devtools revision.
110
+ this . fallbackChain = this . determineVersionFallback ( ) ;
111
+ if ( this . fallbackChain . length > 0 ) {
112
+ this . getFallbackRevisionFunction = this . fallbackChain . pop ( ) || this . getFallbackRevisionFunction ;
113
+ }
107
114
108
115
// Handle closing
109
116
this . panel . onDidDispose ( ( ) => {
@@ -117,8 +124,7 @@ export class DevToolsPanel {
117
124
// Connection type determined already
118
125
this . update ( ) ;
119
126
} else {
120
- // Use version socket to determine which Webview/Tools to use
121
- this . versionDetectionSocket . detectVersion ( ) ;
127
+ this . getFallbackRevisionFunction ( ) ;
122
128
}
123
129
}
124
130
} , this , this . disposables ) ;
@@ -137,12 +143,52 @@ export class DevToolsPanel {
137
143
} ) ;
138
144
}
139
145
146
+ /**
147
+ * Allows multiple fallbacks, allowing the user to select between stability
148
+ * or latest features.
149
+ * @returns A function array that has the fallback chain.
150
+ */
151
+ determineVersionFallback ( ) {
152
+ const browserFlavor = this . config . browserFlavor ;
153
+ const storedRevision = this . context . globalState . get < string > ( 'fallbackRevision' ) || '' ;
154
+ const callWrapper = ( revision : string ) => {
155
+ this . setCdnParameters ( { revision, isHeadless : this . isHeadless } ) ;
156
+ } ;
157
+
158
+ // Use version socket to determine which Webview/Tools to use
159
+ const detectedVersion = ( ) => {
160
+ this . versionDetectionSocket . on ( 'setCdnParameters' , ( msg : { revision : string ; isHeadless : boolean } ) => {
161
+ this . setCdnParameters ( msg ) ;
162
+ } ) ;
163
+
164
+ this . versionDetectionSocket . detectVersion . bind ( this . versionDetectionSocket ) ( ) ;
165
+ } ;
166
+
167
+ // we reverse the array so that it behaves like a stack.
168
+ switch ( browserFlavor ) {
169
+ case 'Beta' :
170
+ case 'Canary' :
171
+ case 'Dev' :
172
+ case 'Stable' : {
173
+ return [ detectedVersion ,
174
+ ( ) => callWrapper ( CDN_FALLBACK_REVISION ) ,
175
+ ( ) => callWrapper ( storedRevision ) ] . reverse ( ) ;
176
+ }
177
+
178
+ case 'Default' :
179
+ default : {
180
+ return [ ( ) => callWrapper ( CDN_FALLBACK_REVISION ) ,
181
+ detectedVersion ,
182
+ ( ) => callWrapper ( storedRevision ) ] . reverse ( ) ;
183
+ }
184
+ }
185
+ }
186
+
140
187
dispose ( ) : void {
141
188
DevToolsPanel . instance = undefined ;
142
189
143
190
this . panel . dispose ( ) ;
144
191
this . panelSocket . dispose ( ) ;
145
- this . versionDetectionSocket . dispose ( ) ;
146
192
if ( this . timeStart !== null ) {
147
193
const timeEnd = performance . now ( ) ;
148
194
const sessionTime = timeEnd - this . timeStart ;
@@ -406,41 +452,18 @@ export class DevToolsPanel {
406
452
private onSocketDevToolsConnection ( success : string ) {
407
453
if ( success === 'true' ) {
408
454
void this . context . globalState . update ( 'fallbackRevision' , this . currentRevision ) ;
409
- this . context . globalState . update ( 'retryAttemptToLoadCDN' , '1' ) ;
455
+ this . fallbackChain = this . determineVersionFallback ( ) ;
410
456
} else {
411
- let retryNumber : number ;
412
- try {
413
- retryNumber = parseInt ( this . context . globalState . get < string > ( 'retryAttemptToLoadCDN' ) || '1' , 10 ) ;
414
- } catch {
415
- retryNumber = 1 ;
416
- }
417
-
418
- let fallbackRevision ;
419
- switch ( retryNumber ) {
420
- case 1 : {
421
- // Always try the latest specified revision first, this will keep it updated.
422
- fallbackRevision = CDN_FALLBACK_REVISION ;
423
- this . context . globalState . update ( 'retryAttemptToLoadCDN' , ++ retryNumber ) ;
424
- break ;
425
- }
426
- case 2 : {
427
- // Retry connection with latest well known fallback that this environment knows.
428
- fallbackRevision = this . context . globalState . get < string > ( 'fallbackRevision' ) ?? '' ;
429
- this . context . globalState . update ( 'retryAttemptToLoadCDN' , ++ retryNumber ) ;
430
- break ;
431
- }
432
- default : {
433
- // Could not find suitable version.
434
- this . context . globalState . update ( 'retryAttemptToLoadCDN' , '1' ) ;
435
- return ;
436
- }
437
- }
438
-
439
457
if ( this . currentRevision ) {
440
458
this . telemetryReporter . sendTelemetryEvent ( 'websocket/failedConnection' , { revision : this . currentRevision } ) ;
441
459
}
442
460
443
- this . setCdnParameters ( { revision : fallbackRevision , isHeadless : this . isHeadless } ) ;
461
+ // We failed trying to retrieve the specified revision
462
+ // we fallback to the next option if available.
463
+ if ( this . fallbackChain . length > 0 ) {
464
+ this . getFallbackRevisionFunction = this . fallbackChain . pop ( ) || ( ( ) => { } ) ;
465
+ this . getFallbackRevisionFunction ( ) ;
466
+ }
444
467
}
445
468
}
446
469
@@ -574,7 +597,7 @@ export class DevToolsPanel {
574
597
}
575
598
576
599
private setCdnParameters ( msg : { revision : string , isHeadless : boolean } ) {
577
- this . currentRevision = msg . revision || CDN_FALLBACK_REVISION ;
600
+ this . currentRevision = msg . revision ;
578
601
this . devtoolsBaseUri = `https://devtools.azureedge.net/serve_file/${ this . currentRevision } /vscode_app.html` ;
579
602
this . isHeadless = msg . isHeadless ;
580
603
this . update ( ) ;
0 commit comments