# BlazorJSRuntime `BlazorJSRuntime` is the central JavaScript interop service in SpawnDev.BlazorJS. It provides synchronous and asynchronous access to the JavaScript global scope, including property access, method calls, object creation, type checking, script loading, and scope detection. **Namespace:** `SpawnDev.BlazorJS` --- ## Registration Register in `Program.cs`: ```csharp builder.Services.AddBlazorJSRuntime(); ``` Or with early access (the `out var JS` pattern): ```csharp builder.Services.AddBlazorJSRuntime(out var JS); // JS is available immediately for scope detection, script loading, etc. ``` --- ## Injection ### In Components ```csharp [Inject] BlazorJSRuntime JS { get; set; } ``` ### In Services ```csharp public class MyService { private readonly BlazorJSRuntime _js; public MyService(BlazorJSRuntime js) => _js = js; } ``` ### Static Access (from JSObject subclasses) All `JSObject` subclasses have access to a protected static `JS` property that refers to the singleton `BlazorJSRuntime`: ```csharp public class MyWrapper : JSObject { // This static JS property is provided by JSObject base class // It is equivalent to BlazorJSRuntime.JS public MyWrapper(string url) : base(JS.New("MyClass", url)) { } public MyWrapper(IJSInProcessObjectReference _ref) : base(_ref) { } } ``` The static `BlazorJSRuntime.JS` property is also accessible from anywhere: ```csharp var height = BlazorJSRuntime.JS.Get("window.innerHeight"); ``` --- ## Property Access ### Get\(string propertyPath) Reads a JavaScript property and deserializes it to type `T`. Supports dot notation and null-conditional `?.` operator. ```csharp // Primitive types int height = JS.Get("window.innerHeight"); string title = JS.Get("document.title"); bool hidden = JS.Get("document.hidden"); double ratio = JS.Get("window.devicePixelRatio"); // JSObject types - REMEMBER to dispose using var window = JS.Get("window"); using var document = JS.Get("document"); using var navigator = JS.Get("navigator"); using var localStorage = JS.Get("localStorage"); // Nullable with null-conditional int? size = JS.Get("fruit.options?.size"); string? theme = JS.Get("app?.config?.theme"); // IJSInProcessObjectReference (raw reference) var rawRef = JS.Get("someObject"); ``` ### Set(string propertyPath, object? value) Sets a JavaScript property. ```csharp JS.Set("document.title", "My App"); JS.Set("myGlobalVar", 42); JS.Set("myGlobalObj", new { name = "test", count = 5 }); // Set to null JS.Set("myVar", null); ``` ### Delete(string propertyPath) Deletes a JavaScript property (equivalent to the `delete` operator). ```csharp JS.Delete("myGlobalVar"); ``` --- ## Method Calls ### Call\(string methodPath, params object?[] args) Calls a synchronous JavaScript method and returns the result as type `T`. ```csharp // Returns a value string? item = JS.Call("localStorage.getItem", "myKey"); int max = JS.Call("Math.max", 10, 20); double random = JS.Call("Math.random"); string json = JS.Call("JSON.stringify", myObject); // Returns a JSObject type using var parsed = JS.Call("JSON.parse", jsonString); ``` ### CallVoid(string methodPath, params object?[] args) Calls a synchronous JavaScript method that returns void. ```csharp JS.CallVoid("console.log", "Hello from Blazor!"); JS.CallVoid("localStorage.setItem", "key", "value"); JS.CallVoid("localStorage.removeItem", "key"); JS.CallVoid("alert", "Warning!"); ``` ### CallAsync\(string methodPath, params object?[] args) Calls a JavaScript method that returns a Promise, awaits it, and returns the resolved value as type `T`. ```csharp // Fetch API using var response = await JS.CallAsync("fetch", "/api/data"); // Any async/Promise-returning function string result = await JS.CallAsync("myAsyncFunction", arg1); ``` --- ## Sync vs Async - CRITICAL Rules SpawnDev.BlazorJS is a 1:1 mapping to JavaScript. Using the wrong call type **throws an error**. | JavaScript Returns | Correct C# Call | Wrong Call | |---|---|---| | Value (synchronous) | `JS.Call()` or `JS.Get()` | `JS.CallAsync()` THROWS | | Promise (asynchronous) | `JS.CallAsync()` | `JS.Call()` returns a Promise object, not the value | | void (synchronous) | `JS.CallVoid()` | - | | void Promise (asynchronous) | `JS.CallVoidAsync()` | `JS.CallVoid()` won't await the Promise | **Examples of correct usage:** ```csharp // Synchronous JS function // function addNum(a, b) { return a + b; } var total = JS.Call("addNum", 20, 22); // Asynchronous JS function // async function fetchData(url) { ... } var data = await JS.CallAsync("fetchData", "/api/items"); // Alternative for async: get the Promise, then await it using var promise = JS.Call>("fetchData", "/api/items"); var data = await promise.ThenAsync(); // Alternative for async: use Task var data = await JS.Call>("fetchData", "/api/items"); ``` --- ## Object Creation ### New(string constructorName, params object?[] args) Creates a new JavaScript object using the given constructor and returns an `IJSInProcessObjectReference`. ```csharp var workerRef = JS.New("Worker", "my-worker.js"); ``` ### New\(string constructorName, params object?[] args) Creates a new JavaScript object and wraps it in a typed JSObject wrapper. ```csharp using var audio = JS.New