Skip to content

Commit 514e875

Browse files
committed
Added missing WebAssemblyJSObjectReferenceJsonConverter fucntionality + fixed E2E tests
1 parent f73ca65 commit 514e875

File tree

4 files changed

+155
-94
lines changed

4 files changed

+155
-94
lines changed

src/Components/WebAssembly/JSInterop/src/WebAssemblyJSObjectReferenceJsonConverter.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ public override bool CanConvert(Type typeToConvert)
2626
public override IJSObjectReference? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
2727
{
2828
var id = JSObjectReferenceJsonWorker.ReadJSObjectReferenceIdentifier(ref reader);
29+
30+
if (id == -1)
31+
{
32+
return null;
33+
}
34+
2935
return new WebAssemblyJSObjectReference(_jsRuntime, id);
3036
}
3137

src/Components/WebAssembly/WebAssembly/test/JSObjectReferenceJsonConverterTest.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,17 @@ public void Read_ReadsJson_IJSInProcessObjectReference()
4444
// Assert
4545
Assert.Equal(expectedId, deserialized?.Id);
4646
}
47+
48+
[Fact]
49+
public void Read_ReturnsNull_WhenIdIsMinusOne()
50+
{
51+
// Arrange
52+
var json = "{\"__jsObjectId\":-1}";
53+
54+
// Act
55+
var deserialized = JsonSerializer.Deserialize<IJSObjectReference>(json, JsonSerializerOptions);
56+
57+
// Assert
58+
Assert.Null(deserialized);
59+
}
4760
}

src/Components/test/E2ETest/Tests/InteropTest.cs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,6 @@ public void CanInvokeInteropMethods()
8989
["invokeVoidAsyncReturnsWithoutSerializing"] = "Success",
9090
["invokeVoidAsyncReturnsWithoutSerializingInJSObjectReference"] = "Success",
9191
["invokeAsyncThrowsSerializingCircularStructure"] = "Success",
92-
["invokeAsyncUndefinedJSObjectReference"] = "Success",
93-
["invokeAsyncNullJSObjectReference"] = "Success",
94-
["invokeAsyncNullFromVariableJSObjectReference"] = "Success",
9592
["disposeJSObjectReferenceAsync"] = "Success",
9693
// GetValue tests
9794
["getValueFromDataPropertyAsync"] = "10",
@@ -109,7 +106,12 @@ public void CanInvokeInteropMethods()
109106
["invokeConstructorWithClassConstructorAsync.function"] = "6",
110107
["invokeConstructorWithNonConstructorAsync"] = "Success",
111108
// Function reference tests
112-
["changeFunctionViaObjectReferenceAsync"] = "42"
109+
["changeFunctionViaObjectReferenceAsync"] = "42",
110+
// JS Object Nullable reference tests
111+
["invokeAsyncUndefinedJSObjectReference"] = "Success",
112+
["invokeAsyncNullJSObjectReference"] = "Success",
113+
["invokeAsyncNullFromVariableJSObjectReference"] = "Success",
114+
["invokeAsyncNonExistentJSObjectReference"] = "Success",
113115
};
114116

115117
var expectedSyncValues = new Dictionary<string, string>
@@ -149,9 +151,6 @@ public void CanInvokeInteropMethods()
149151
["invokeVoidReturnsWithoutSerializingIJSInProcessRuntime"] = "Success",
150152
["invokeVoidReturnsWithoutSerializingInIJSInProcessObjectReference"] = "Success",
151153
["invokeThrowsSerializingCircularStructure"] = "Success",
152-
["invokeUndefinedJSObjectReference"] = "Success",
153-
["invokeNullJSObjectReference"] = "Success",
154-
["invokeNullFromVariableJSObjectReference"] = "Success",
155154
["stringValueUpperSync"] = "MY STRING",
156155
["testDtoNonSerializedValueSync"] = "99999",
157156
["testDtoSync"] = "Same",
@@ -176,7 +175,12 @@ public void CanInvokeInteropMethods()
176175
["invokeConstructorWithClassConstructor.function"] = "6",
177176
["invokeConstructorWithNonConstructor"] = "Success",
178177
// Function reference tests
179-
["changeFunctionViaObjectReference"] = "42"
178+
["changeFunctionViaObjectReference"] = "42",
179+
// JS Object Nullable reference tests
180+
["invokeUndefinedJSObjectReference"] = "Success",
181+
["invokeNullJSObjectReference"] = "Success",
182+
["invokeNullFromVariableJSObjectReference"] = "Success",
183+
["invokeNonExistentJSObjectReference"] = "Success",
180184
};
181185

182186
// Include the sync assertions only when running under WebAssembly

src/Components/test/testassets/BasicTestApp/InteropComponent.razor

Lines changed: 124 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -167,47 +167,6 @@
167167
ReturnValues["invokeAsyncThrowsSerializingCircularStructure"] = $"Failure: {ex.Message}";
168168
}
169169

170-
try
171-
{
172-
var undefinedJsObjectReference = await JSRuntime.InvokeAsync<IJSObjectReference>("returnUndefined");
173-
ReturnValues["invokeAsyncUndefinedJSObjectReference"] = undefinedJsObjectReference is null ? "Success" : "Failure: not null";
174-
}
175-
catch (JSException ex)
176-
{
177-
ReturnValues["invokeAsyncUndefinedJSObjectReference"] = $"Failure: {ex.Message}";
178-
}
179-
catch (Exception ex)
180-
{
181-
ReturnValues["invokeAsyncUndefinedJSObjectReference"] = $"Failure: {ex.Message}";
182-
}
183-
184-
try
185-
{
186-
var nullJsObjectReference = await JSRuntime.InvokeAsync<IJSObjectReference>("returnNull");
187-
ReturnValues["invokeAsyncNullJSObjectReference"] = nullJsObjectReference is null ? "Success" : "Failure: not null";
188-
}
189-
catch (JSException ex)
190-
{
191-
ReturnValues["invokeAsyncNullJSObjectReference"] = $"Failure: {ex.Message}";
192-
}
193-
catch (Exception ex)
194-
{
195-
ReturnValues["invokeAsyncNullJSObjectReference"] = $"Failure: {ex.Message}";
196-
}
197-
198-
try
199-
{
200-
var nullVariableJsObjectReference = await JSRuntime.GetValueAsync<IJSObjectReference>("jsInteropTests.testObject.nullProperty");
201-
ReturnValues["invokeAsyncNullFromVariableJSObjectReference"] = nullVariableJsObjectReference is null ? "Success" : "Failure: not null";
202-
}
203-
catch (JSException)
204-
{
205-
ReturnValues["invokeAsyncNullFromVariableJSObjectReference"] = "Failure";
206-
}
207-
catch (Exception ex)
208-
{
209-
ReturnValues["invokeAsyncNullFromVariableJSObjectReference"] = $"Failure: {ex.Message}";
210-
}
211170

212171
var jsObjectReference = await JSRuntime.InvokeAsync<IJSObjectReference>("returnJSObjectReference");
213172
ReturnValues["jsObjectReference.identity"] = await jsObjectReference.InvokeAsync<string>("identity", "Invoked from JSObjectReference");
@@ -322,6 +281,12 @@
322281
FunctionReferenceTests();
323282
}
324283

284+
await JSObjectReferenceAsyncTests();
285+
if (shouldSupportSyncInterop)
286+
{
287+
JSObjectReferenceTests();
288+
}
289+
325290
Invocations = invocations;
326291
DoneWithInterop = true;
327292
}
@@ -408,51 +373,6 @@
408373
ReturnValues["invokeThrowsSerializingCircularStructure"] = $"Failure: {ex.Message}";
409374
}
410375

411-
try
412-
{
413-
var undefinedJsObjectReference = inProcRuntime.Invoke<IJSObjectReference>("returnUndefined");
414-
ReturnValues["invokeUndefinedJSObjectReference"] = undefinedJsObjectReference is null ? "Success" : "Failure: not null";
415-
Console.WriteLine($"Received undefined JSObjectReference: {undefinedJsObjectReference}");
416-
}
417-
catch (JSException ex)
418-
{
419-
ReturnValues["invokeUndefinedJSObjectReference"] = $"Failure: {ex.Message}";
420-
}
421-
catch (Exception ex)
422-
{
423-
ReturnValues["invokeUndefinedJSObjectReference"] = $"Failure: {ex.Message}";
424-
}
425-
426-
try
427-
{
428-
var nullJsObjectReference = inProcRuntime.Invoke<IJSObjectReference>("returnNull");
429-
ReturnValues["invokeNullJSObjectReference"] = nullJsObjectReference is null ? "Success" : "Failure: not null";
430-
Console.WriteLine($"Received undefined JSObjectReference: {nullJsObjectReference}");
431-
}
432-
catch (JSException ex)
433-
{
434-
ReturnValues["invokeNullJSObjectReference"] = $"Failure: {ex.Message}";
435-
}
436-
catch (Exception ex)
437-
{
438-
ReturnValues["invokeNullJSObjectReference"] = $"Failure: {ex.Message}";
439-
}
440-
441-
try
442-
{
443-
var nullVariableJsObjectReference = inProcRuntime.GetValue<IJSObjectReference>("jsInteropTests.testObject.nullProperty");
444-
ReturnValues["invokeNullFromVariableJSObjectReference"] = nullVariableJsObjectReference is null ? "Success" : "Failure: not null";
445-
Console.WriteLine($"Received undefined JSObjectReference: {nullVariableJsObjectReference}");
446-
}
447-
catch (JSException ex)
448-
{
449-
ReturnValues["invokeNullFromVariableJSObjectReference"] = $"Failure: {ex.Message}";
450-
}
451-
catch (Exception ex)
452-
{
453-
ReturnValues["invokeNullFromVariableJSObjectReference"] = $"Failure: {ex.Message}";
454-
}
455-
456376
var jsInProcObjectReference = inProcRuntime.Invoke<IJSInProcessObjectReference>("returnJSObjectReference");
457377
ReturnValues["jsInProcessObjectReference.identity"] = jsInProcObjectReference.Invoke<string>("identity", "Invoked from JSInProcessObjectReference");
458378

@@ -657,6 +577,124 @@
657577
ReturnValues["changeFunctionViaObjectReference"] = testClassRef.Invoke<int>("getTextLength").ToString();
658578
}
659579

580+
private async Task JSObjectReferenceAsyncTests()
581+
{
582+
try
583+
{
584+
var undefinedJsObjectReference = await JSRuntime.InvokeAsync<IJSObjectReference>("jsInteropTests.returnUndefined");
585+
ReturnValues["invokeAsyncUndefinedJSObjectReference"] = undefinedJsObjectReference is null ? "Success" : $"Failure: not null (type: {undefinedJsObjectReference.GetType().FullName})";
586+
}
587+
catch (JSException ex)
588+
{
589+
ReturnValues["invokeAsyncUndefinedJSObjectReference"] = $"Failure: {ex.Message}";
590+
}
591+
catch (Exception ex)
592+
{
593+
ReturnValues["invokeAsyncUndefinedJSObjectReference"] = $"Failure: {ex.Message}";
594+
}
595+
596+
try
597+
{
598+
var nullJsObjectReference = await JSRuntime.InvokeAsync<IJSObjectReference>("jsInteropTests.returnNull");
599+
ReturnValues["invokeAsyncNullJSObjectReference"] = nullJsObjectReference is null ? "Success" : $"Failure: not null (type: {nullJsObjectReference.GetType().FullName})";
600+
}
601+
catch (JSException ex)
602+
{
603+
ReturnValues["invokeAsyncNullJSObjectReference"] = $"Failure: {ex.Message}";
604+
}
605+
catch (Exception ex)
606+
{
607+
ReturnValues["invokeAsyncNullJSObjectReference"] = $"Failure: {ex.Message}";
608+
}
609+
610+
try
611+
{
612+
var nullVariableJsObjectReference = await JSRuntime.GetValueAsync<IJSObjectReference>("jsInteropTests.testObject.nullProperty");
613+
ReturnValues["invokeAsyncNullFromVariableJSObjectReference"] = nullVariableJsObjectReference is null ? "Success" : $"Failure: not null (type: {nullVariableJsObjectReference.GetType().FullName})";
614+
}
615+
catch (JSException ex)
616+
{
617+
ReturnValues["invokeAsyncNullFromVariableJSObjectReference"] = $"Failure: {ex.Message}";
618+
}
619+
catch (Exception ex)
620+
{
621+
ReturnValues["invokeAsyncNullFromVariableJSObjectReference"] = $"Failure: {ex.Message}";
622+
}
623+
624+
try
625+
{
626+
await JSRuntime.GetValueAsync<IJSObjectReference>("nonexistend");
627+
}
628+
catch (JSException)
629+
{
630+
ReturnValues["invokeAsyncNonExistentJSObjectReference"] = "Success";
631+
}
632+
catch (Exception ex)
633+
{
634+
ReturnValues["invokeAsyncNonExistentJSObjectReference"] = "Failure";
635+
}
636+
}
637+
638+
private async Task JSObjectReferenceTests()
639+
{
640+
var inProcRuntime = ((IJSInProcessRuntime)JSRuntime);
641+
642+
try
643+
{
644+
var undefinedJsObjectReference = inProcRuntime.Invoke<IJSObjectReference>("returnUndefined");
645+
ReturnValues["invokeUndefinedJSObjectReference"] = undefinedJsObjectReference is null ? "Success" : $"Failure: not null (type: {undefinedJsObjectReference.GetType().FullName})";
646+
}
647+
catch (JSException ex)
648+
{
649+
ReturnValues["invokeUndefinedJSObjectReference"] = $"Failure: {ex.Message}";
650+
}
651+
catch (Exception ex)
652+
{
653+
ReturnValues["invokeUndefinedJSObjectReference"] = $"Failure: {ex.Message}";
654+
}
655+
656+
try
657+
{
658+
var nullJsObjectReference = inProcRuntime.Invoke<IJSObjectReference>("returnNull");
659+
ReturnValues["invokeNullJSObjectReference"] = nullJsObjectReference is null ? "Success" : $"Failure: not null (type: {nullJsObjectReference.GetType().FullName})";
660+
}
661+
catch (JSException ex)
662+
{
663+
ReturnValues["invokeNullJSObjectReference"] = $"Failure: {ex.Message}";
664+
}
665+
catch (Exception ex)
666+
{
667+
ReturnValues["invokeNullJSObjectReference"] = $"Failure: {ex.Message}";
668+
}
669+
670+
try
671+
{
672+
var nullVariableJsObjectReference = inProcRuntime.GetValue<IJSObjectReference>("jsInteropTests.testObject.nullProperty");
673+
ReturnValues["invokeNullFromVariableJSObjectReference"] = nullVariableJsObjectReference is null ? "Success" : $"Failure: not null (type: {nullVariableJsObjectReference.GetType().FullName})";
674+
}
675+
catch (JSException ex)
676+
{
677+
ReturnValues["invokeNullFromVariableJSObjectReference"] = $"Failure: {ex.Message}";
678+
}
679+
catch (Exception ex)
680+
{
681+
ReturnValues["invokeNullFromVariableJSObjectReference"] = $"Failure: {ex.Message}";
682+
}
683+
684+
try
685+
{
686+
inProcRuntime.GetValue<IJSObjectReference>("nonexistend");
687+
}
688+
catch (JSException)
689+
{
690+
ReturnValues["invokeNonExistentJSObjectReference"] = "Success";
691+
}
692+
catch (Exception ex)
693+
{
694+
ReturnValues["invokeNonExistentJSObjectReference"] = "Failure";
695+
}
696+
}
697+
660698
public class PassDotNetObjectByRefArgs
661699
{
662700
public string StringValue { get; set; }

0 commit comments

Comments
 (0)