@@ -26,22 +26,38 @@ setTimeout(async function () {
2626
2727 let waiting = false ;
2828
29- connection . onmessage = function ( message ) {
30- const payload = JSON . parse ( message . data ) ;
31- const action = {
32- 'Reload' : ( ) => reload ( ) ,
33- 'Wait' : ( ) => wait ( ) ,
34- 'UpdateStaticFile' : ( ) => updateStaticFile ( payload . path ) ,
35- 'ApplyManagedCodeUpdates' : ( ) => applyManagedCodeUpdates ( payload . sharedSecret , payload . updateId , payload . deltas , payload . responseLoggingLevel ) ,
36- 'ReportDiagnostics' : ( ) => reportDiagnostics ( payload . diagnostics ) ,
37- 'GetApplyUpdateCapabilities' : ( ) => getApplyUpdateCapabilities ( ) ,
38- 'RefreshBrowser' : ( ) => refreshBrowser ( )
39- } ;
40-
41- if ( payload . type && action . hasOwnProperty ( payload . type ) ) {
42- action [ payload . type ] ( ) ;
29+ connection . onmessage = function ( message ) {
30+ if ( message . data === 'Reload' ) {
31+ console . debug ( 'Server is ready. Reloading...' ) ;
32+ location . reload ( ) ;
33+ } else if ( message . data === 'Wait' ) {
34+ if ( waiting ) {
35+ return ;
36+ }
37+ waiting = true ;
38+ console . debug ( 'File changes detected. Waiting for application to rebuild.' ) ;
39+ const glyphs = [ '☱' , '☲' , '☴' ] ;
40+ const title = document . title ;
41+ let i = 0 ;
42+ setInterval ( function ( ) { document . title = glyphs [ i ++ % glyphs . length ] + ' ' + title ; } , 240 ) ;
4343 } else {
44- console . error ( 'Unknown payload:' , message . data ) ;
44+ const payload = JSON . parse ( message . data ) ;
45+ const action = {
46+ 'UpdateStaticFile' : ( ) => updateStaticFile ( payload . path ) ,
47+ 'BlazorHotReloadDeltav1' : ( ) => applyBlazorDeltas_legacy ( payload . sharedSecret , payload . deltas , false ) ,
48+ 'BlazorHotReloadDeltav2' : ( ) => applyBlazorDeltas_legacy ( payload . sharedSecret , payload . deltas , true ) ,
49+ 'BlazorHotReloadDeltav3' : ( ) => applyBlazorDeltas ( payload . sharedSecret , payload . updateId , payload . deltas , payload . responseLoggingLevel ) ,
50+ 'HotReloadDiagnosticsv1' : ( ) => displayDiagnostics ( payload . diagnostics ) ,
51+ 'BlazorRequestApplyUpdateCapabilities' : ( ) => getBlazorWasmApplyUpdateCapabilities ( false ) ,
52+ 'BlazorRequestApplyUpdateCapabilities2' : ( ) => getBlazorWasmApplyUpdateCapabilities ( true ) ,
53+ 'AspNetCoreHotReloadApplied' : ( ) => aspnetCoreHotReloadApplied ( )
54+ } ;
55+
56+ if ( payload . type && action . hasOwnProperty ( payload . type ) ) {
57+ action [ payload . type ] ( ) ;
58+ } else {
59+ console . error ( 'Unknown payload:' , message . data ) ;
60+ }
4561 }
4662 }
4763
@@ -90,12 +106,12 @@ setTimeout(async function () {
90106 return messageAndStack
91107 }
92108
93- function getApplyUpdateCapabilities ( ) {
109+ function getBlazorWasmApplyUpdateCapabilities ( sendErrorToClient ) {
94110 let applyUpdateCapabilities ;
95111 try {
96112 applyUpdateCapabilities = window . Blazor . _internal . getApplyUpdateCapabilities ( ) ;
97113 } catch ( error ) {
98- applyUpdateCapabilities = "!" + getMessageAndStack ( error ) ;
114+ applyUpdateCapabilities = sendErrorToClient ? "!" + getMessageAndStack ( error ) : '' ;
99115 }
100116 connection . send ( applyUpdateCapabilities ) ;
101117 }
@@ -121,6 +137,41 @@ setTimeout(async function () {
121137 styleElement . parentNode . insertBefore ( newElement , styleElement . nextSibling ) ;
122138 }
123139
140+ async function applyBlazorDeltas_legacy ( serverSecret , deltas , sendErrorToClient ) {
141+ if ( sharedSecret && ( serverSecret != sharedSecret . encodedSharedSecret ) ) {
142+ // Validate the shared secret if it was specified. It might be unspecified in older versions of VS
143+ // that do not support this feature as yet.
144+ throw 'Unable to validate the server. Rejecting apply-update payload.' ;
145+ }
146+
147+ let applyError = undefined ;
148+
149+ try {
150+ applyDeltas_legacy ( deltas )
151+ } catch ( error ) {
152+ console . warn ( error ) ;
153+ applyError = error ;
154+ }
155+
156+ const body = JSON . stringify ( {
157+ id : deltas [ 0 ] . sequenceId ,
158+ deltas : deltas
159+ } ) ;
160+ try {
161+ await fetch ( '/_framework/blazor-hotreload' , { method : 'post' , headers : { 'content-type' : 'application/json' } , body : body } ) ;
162+ } catch ( error ) {
163+ console . warn ( error ) ;
164+ applyError = error ;
165+ }
166+
167+ if ( applyError ) {
168+ sendDeltaNotApplied ( sendErrorToClient ? applyError : undefined ) ;
169+ } else {
170+ sendDeltaApplied ( ) ;
171+ notifyHotReloadApplied ( ) ;
172+ }
173+ }
174+
124175 function applyDeltas_legacy ( deltas ) {
125176 let apply = window . Blazor ?. _internal ?. applyHotReload
126177
@@ -139,16 +190,26 @@ setTimeout(async function () {
139190 } ) ;
140191 }
141192 }
193+ function sendDeltaApplied ( ) {
194+ connection . send ( new Uint8Array ( [ 1 ] ) . buffer ) ;
195+ }
196+
197+ function sendDeltaNotApplied ( error ) {
198+ if ( error ) {
199+ let encoder = new TextEncoder ( )
200+ connection . send ( encoder . encode ( "\0" + error . message + "\0" + error . stack ) ) ;
201+ } else {
202+ connection . send ( new Uint8Array ( [ 0 ] ) . buffer ) ;
203+ }
204+ }
142205
143- async function applyManagedCodeUpdates ( serverSecret , updateId , deltas , responseLoggingLevel ) {
206+ async function applyBlazorDeltas ( serverSecret , updateId , deltas , responseLoggingLevel ) {
144207 if ( sharedSecret && ( serverSecret != sharedSecret . encodedSharedSecret ) ) {
145208 // Validate the shared secret if it was specified. It might be unspecified in older versions of VS
146209 // that do not support this feature as yet.
147210 throw 'Unable to validate the server. Rejecting apply-update payload.' ;
148211 }
149212
150- console . debug ( 'Applying managed code updates.' ) ;
151-
152213 const AgentMessageSeverity_Error = 2
153214
154215 let applyError = undefined ;
@@ -200,13 +261,11 @@ setTimeout(async function () {
200261 } ) ) ;
201262
202263 if ( ! applyError ) {
203- displayChangesAppliedToast ( ) ;
264+ notifyHotReloadApplied ( ) ;
204265 }
205266 }
206267
207- function reportDiagnostics ( diagnostics ) {
208- console . debug ( 'Reporting Hot Reload diagnostics.' ) ;
209-
268+ function displayDiagnostics ( diagnostics ) {
210269 document . querySelectorAll ( '#dotnet-compile-error' ) . forEach ( el => el . remove ( ) ) ;
211270 const el = document . body . appendChild ( document . createElement ( 'div' ) ) ;
212271 el . id = 'dotnet-compile-error' ;
@@ -221,7 +280,7 @@ setTimeout(async function () {
221280 } ) ;
222281 }
223282
224- function displayChangesAppliedToast ( ) {
283+ function notifyHotReloadApplied ( ) {
225284 document . querySelectorAll ( '#dotnet-compile-error' ) . forEach ( el => el . remove ( ) ) ;
226285 if ( document . querySelector ( '#dotnet-hotreload-toast' ) ) {
227286 return ;
@@ -239,47 +298,25 @@ setTimeout(async function () {
239298 setTimeout ( ( ) => el . remove ( ) , 2000 ) ;
240299 }
241300
242- function refreshBrowser ( ) {
301+ function aspnetCoreHotReloadApplied ( ) {
243302 if ( window . Blazor ) {
244303 window [ hotReloadActiveKey ] = true ;
245304 // hotReloadApplied triggers an enhanced navigation to
246305 // refresh pages that have been statically rendered with
247306 // Blazor SSR.
248307 if ( window . Blazor ?. _internal ?. hotReloadApplied )
249308 {
250- console . debug ( 'Refreshing browser: WASM.' ) ;
251309 Blazor . _internal . hotReloadApplied ( ) ;
252310 }
253311 else
254312 {
255- console . debug ( 'Refreshing browser.' ) ;
256- displayChangesAppliedToast ( ) ;
313+ notifyHotReloadApplied ( ) ;
257314 }
258315 } else {
259- console . debug ( 'Refreshing browser: Reloading.' ) ;
260316 location . reload ( ) ;
261317 }
262318 }
263319
264- function reload ( ) {
265- console . debug ( 'Reloading.' ) ;
266- location . reload ( ) ;
267- }
268-
269- function wait ( ) {
270- console . debug ( 'Waiting for application to rebuild.' ) ;
271-
272- if ( waiting ) {
273- return ;
274- }
275-
276- waiting = true ;
277- const glyphs = [ '☱' , '☲' , '☴' ] ;
278- const title = document . title ;
279- let i = 0 ;
280- setInterval ( function ( ) { document . title = glyphs [ i ++ % glyphs . length ] + ' ' + title ; } , 240 ) ;
281- }
282-
283320 async function getSecret ( serverKeyString ) {
284321 if ( ! serverKeyString || ! window . crypto || ! window . crypto . subtle ) {
285322 return null ;
@@ -345,8 +382,8 @@ setTimeout(async function () {
345382 webSocket . addEventListener ( 'close' , onClose ) ;
346383 if ( window . Blazor ?. removeEventListener && window . Blazor ?. addEventListener )
347384 {
348- webSocket . addEventListener ( 'close' , ( ) => window . Blazor ?. removeEventListener ( 'enhancedload' , displayChangesAppliedToast ) ) ;
349- window . Blazor ?. addEventListener ( 'enhancedload' , displayChangesAppliedToast ) ;
385+ webSocket . addEventListener ( 'close' , ( ) => window . Blazor ?. removeEventListener ( 'enhancedload' , notifyHotReloadApplied ) ) ;
386+ window . Blazor ?. addEventListener ( 'enhancedload' , notifyHotReloadApplied ) ;
350387 }
351388 } ) ;
352389 }
0 commit comments