Skip to content

Commit

Permalink
When Hot Reload change fails to apply in the browser send full error … (
Browse files Browse the repository at this point in the history
  • Loading branch information
tmat authored Aug 3, 2023
1 parent 3061a14 commit 0df5c5e
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 21 deletions.
22 changes: 14 additions & 8 deletions src/BuiltInTools/BrowserRefresh/WebSocketScriptInjection.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ setTimeout(async function () {
const payload = JSON.parse(message.data);
const action = {
'UpdateStaticFile': () => updateStaticFile(payload.path),
'BlazorHotReloadDeltav1': () => applyBlazorDeltas(payload.sharedSecret, payload.deltas),
'BlazorHotReloadDeltav1': () => applyBlazorDeltas(payload.sharedSecret, payload.deltas, false),
'BlazorHotReloadDeltav2': () => applyBlazorDeltas(payload.sharedSecret, payload.deltas, true),
'HotReloadDiagnosticsv1': () => displayDiagnostics(payload.diagnostics),
'BlazorRequestApplyUpdateCapabilities': getBlazorWasmApplyUpdateCapabilities,
'AspNetCoreHotReloadApplied': () => aspnetCoreHotReloadApplied()
Expand Down Expand Up @@ -123,14 +124,14 @@ setTimeout(async function () {
styleElement.parentNode.insertBefore(newElement, styleElement.nextSibling);
}

function applyBlazorDeltas(serverSecret, deltas) {
function applyBlazorDeltas(serverSecret, deltas, sendErrorToClient) {
if (sharedSecret && (serverSecret != sharedSecret.encodedSharedSecret)) {
// Validate the shared secret if it was specified. It might be unspecified in older versions of VS
// that do not support this feature as yet.
throw 'Unable to validate the server. Rejecting apply-update payload.';
}

let applyFailed = false;
let applyError = undefined;
if (window.Blazor?._internal?.applyHotReload) {
// Only apply hot reload deltas if Blazor has been initialized.
// It's possible for Blazor to start after the initial page load, so we don't consider skipping this step
Expand All @@ -140,7 +141,7 @@ setTimeout(async function () {
window.Blazor._internal.applyHotReload(d.moduleId, d.metadataDelta, d.ilDelta, d.pdbDelta)
} catch (error) {
console.warn(error);
applyFailed = true;
applyError = error;
}
});
}
Expand All @@ -153,8 +154,8 @@ setTimeout(async function () {
}
});

if (applyFailed) {
sendDeltaNotApplied();
if (applyError) {
sendDeltaNotApplied(sendErrorToClient ? applyError : undefined);
} else {
sendDeltaApplied();
notifyHotReloadApplied();
Expand Down Expand Up @@ -202,8 +203,13 @@ setTimeout(async function () {
connection.send(new Uint8Array([1]).buffer);
}

function sendDeltaNotApplied() {
connection.send(new Uint8Array([0]).buffer);
function sendDeltaNotApplied(error) {
if (error) {
let encoder = new TextEncoder()
connection.send(encoder.encode("\0" + error.message + "\0" + error.stack));
} else {
connection.send(new Uint8Array([0]).buffer);
}
}

async function getSecret(serverKeyString) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,30 +105,46 @@ public override async Task<ApplyStatus> Apply(DotNetWatchContext context, Immuta

private async Task<bool> ReceiveApplyUpdateResult(BrowserRefreshServer browserRefresh, CancellationToken cancellationToken)
{
var _receiveBuffer = new byte[1];
var result = await browserRefresh.ReceiveAsync(_receiveBuffer, cancellationToken);
if (result is null)
var buffer = new byte[1];

var result = await browserRefresh.ReceiveAsync(buffer, cancellationToken);
if (result is not { MessageType: WebSocketMessageType.Binary })
{
// A null result indicates no clients are connected. No deltas could have been applied in this state.
_reporter.Verbose("Apply confirmation: No browser is connected");
return false;
}

if (IsDeltaReceivedMessage(result.Value))
if (result is { Count: 1, EndOfMessage: true })
{
// 1 indicates success.
return _receiveBuffer[0] == 1;
return buffer[0] == 1;
}

return false;
_reporter.Verbose("Browser failed to apply the change and reported error:");

buffer = new byte[1024];
var messageStream = new MemoryStream();

bool IsDeltaReceivedMessage(ValueWebSocketReceiveResult result)
while (true)
{
_reporter.Verbose($"Apply confirmation: Received {_receiveBuffer[0]} from browser in [Count: {result.Count}, MessageType: {result.MessageType}, EndOfMessage: {result.EndOfMessage}].");
return result.Count == 1 // Should have received 1 byte on the socket for the acknowledgement
&& result.MessageType is WebSocketMessageType.Binary
&& result.EndOfMessage;
result = await browserRefresh.ReceiveAsync(buffer, cancellationToken);
if (result is not { MessageType: WebSocketMessageType.Binary })
{
_reporter.Verbose("Failed to receive error message");
break;
}

messageStream.Write(buffer, 0, result.Value.Count);

if (result is { EndOfMessage: true })
{
// message and stack trace are separated by '\0'
_reporter.Verbose(Encoding.UTF8.GetString(messageStream.ToArray()).Replace("\0", Environment.NewLine));
break;
}
}

return false;
}

public override void Dispose()
Expand All @@ -138,7 +154,7 @@ public override void Dispose()

private readonly struct UpdatePayload
{
public string Type => "BlazorHotReloadDeltav1";
public string Type => "BlazorHotReloadDeltav2";
public string? SharedSecret { get; init; }
public IEnumerable<UpdateDelta> Deltas { get; init; }
}
Expand Down

0 comments on commit 0df5c5e

Please sign in to comment.