{"id":26280079,"url":"https://github.com/kristofferstrube/blazor.webidl","last_synced_at":"2025-10-23T23:43:34.292Z","repository":{"id":109456264,"uuid":"592064132","full_name":"KristofferStrube/Blazor.WebIDL","owner":"KristofferStrube","description":"A Blazor wrapper for types and interfaces used in and defined in the standard WebIDL specification.","archived":false,"fork":false,"pushed_at":"2024-10-23T16:33:03.000Z","size":6967,"stargazers_count":20,"open_issues_count":4,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-07T03:04:12.044Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/KristofferStrube.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-01-22T20:06:45.000Z","updated_at":"2025-03-13T18:12:49.000Z","dependencies_parsed_at":"2024-01-04T17:42:43.384Z","dependency_job_id":"16373afb-4e51-4b32-be6f-a07eed5a9a50","html_url":"https://github.com/KristofferStrube/Blazor.WebIDL","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KristofferStrube%2FBlazor.WebIDL","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KristofferStrube%2FBlazor.WebIDL/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KristofferStrube%2FBlazor.WebIDL/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KristofferStrube%2FBlazor.WebIDL/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/KristofferStrube","download_url":"https://codeload.github.com/KristofferStrube/Blazor.WebIDL/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252804206,"owners_count":21806769,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-14T14:18:34.448Z","updated_at":"2025-10-23T23:43:34.194Z","avatar_url":"https://github.com/KristofferStrube.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](/LICENSE.md)\n[![GitHub issues](https://img.shields.io/github/issues/KristofferStrube/Blazor.WebIDL)](https://github.com/KristofferStrube/Blazor.WebIDL/issues)\n[![GitHub forks](https://img.shields.io/github/forks/KristofferStrube/Blazor.WebIDL)](https://github.com/KristofferStrube/Blazor.WebIDL/network/members)\n[![GitHub stars](https://img.shields.io/github/stars/KristofferStrube/Blazor.WebIDL)](https://github.com/KristofferStrube/Blazor.WebIDL/stargazers)\n[![NuGet Downloads (official NuGet)](https://img.shields.io/nuget/dt/KristofferStrube.Blazor.WebIDL?label=NuGet%20Downloads)](https://www.nuget.org/packages/KristofferStrube.Blazor.WebIDL/)\n\n# Blazor.WebIDL\nA Blazor wrapper for types and interfaces used in and defined in [the standard WebIDL specification](https://webidl.spec.whatwg.org/).\nAmong these are declarations that define specific behavior for interfaces and the standard exception definition types used across all WebIDL based APIs.\n\n# Demo\nThe sample project can be demoed at https://kristofferstrube.github.io/Blazor.WebIDL/\n\nOn each page you can find the corresponding code for the example in the top right corner.\n\n# Exceptions\nThe specification defines the types and names for all the standard exceptions and the standard names for [DomExceptions](https://webidl.spec.whatwg.org/#idl-DOMException-error-names).\n\nIt also provides a way to make JSInterop calls that automatically throw these typed errors when a standard exception is thrown in JS.\n\n## Setting it up\nIn `Programs.cs`, we can inject a service to make Error Handling JSInterop easy in each of our pages/components. In Blazor WASM, we additionally need to call a function in `Program.cs` before being able to use Error Handling JSInterop. This is only needed for WASM, as JSInterop in WASM can return `IJSObjectReferences` synchronously.\n\n```csharp\nvar builder = WebAssemblyHostBuilder.CreateDefault(args);\n\n// Setting up other services before this.\nbuilder.Services.AddErrorHandlingJSRuntime();\n\nvar app = builder.Build();\n\n// For Blazor WASM you need to call this to make Error Handling JSInterop.\nawait app.Services.SetupErrorHandlingJSInterop();\n\nawait app.RunAsync();\n```\n\n## Error Handling JSInterop calls in a page.\n\nThis can be used to catch strongly typed JS errors from Blazor. An example could be trying to access the clipboard which can fail in many ways.\n```razor\n@using KristofferStrube.Blazor.WebIDL.Exceptions;\n@inject IErrorHandlingJSRuntime ErrorHandlingJSRuntime\n@inject ILogger Logger\n\n@code {\n    protected override async Task OnAfterRenderAsync(bool firstRender)\n    {\n        if (!firstRender) return;\n        try\n        {\n            var result = await ErrorHandlingJSRuntime.InvokeAsync\u003cstring\u003e(\"navigator.clipboard.readText\");\n            Console.WriteLine(result);\n        }\n        catch (NotAllowedErrorException exception)\n        {\n            Logger.LogWarning(exception, \"The user has not given permission to read the clipboard.\");\n        }\n        catch (DOMException exception)\n        {\n            Logger.LogError(exception, $\"{exception.Name} (which is a DOMException): \\\"{exception.Message}\\\"\");\n        }\n        catch (WebIDLException exception)\n        {\n            Logger.LogError(exception, $\"{exception.GetType().Name}: \\\"{exception.Message}\\\"\");\n        }\n    }\n}\n```\n\n# Standard behavior and method definitions\nThe standard WebIDL specification make definitions that are used across all API specifications that use WebIDL for defining their interfaces.\nDeclarations like `Iterable`, `Asynchronously iterable`, `Maplike`, `Setlike` define expected behavior and methods that should apply to the interfaces that use these definitions. This wrapper defines C# interfaces for these declarations that have implementations for the expected methods. This makes it easy and safe to implement wrappers for interfaces that define i.e. Setlike behavior.\n\nWe have currently implemented 2 interfaces for the `Setlike` declaration called `IReadonlySetlike` and `IReadWriteSetlike` where `IReadWriteSetlike` inherits from `IReadonlySetlike`\n\nThey can be used like this to make a very simple wrapper for the JS `Set` type:\n```csharp\n[IJSWrapperConverter]\npublic class Set : IReadWriteSetlike\u003cSet\u003e\n{\n    /// \u003cinheritdoc/\u003e\n    public IJSObjectReference JSReference { get; }\n    /// \u003cinheritdoc/\u003e\n    public IJSRuntime JSRuntime { get; }\n    /// \u003cinheritdoc/\u003e\n    public bool DisposesJSReference { get; }\n\n    public static async Task\u003cSet\u003e CreateAsync\u003cT\u003e(IJSRuntime jSRuntime, IEnumerable\u003cT\u003e? iterable = null)\n    {\n        var jSInstance = await jSRuntime.InvokeAsync\u003cIJSObjectReference\u003e(\"constructSet\", iterable);\n        return new Set(jSRuntime, jSInstance, new() { DisposesJSReference = true });\n    }\n\n    public Set(IJSRuntime jSRuntime, IJSObjectReference jSReference, CreationOptions options)\n    {\n        JSRuntime = jSRuntime;\n        JSReference = jSReference;\n        DisposesJSReference = options.DisposesJSReference;\n    }\n\n    /// \u003cinheritdoc/\u003e\n    public async ValueTask DisposeAsync()\n    {\n        await IJSWrapper.DisposeJSReference(this);\n        GC.SuppressFinalize(this);\n    }\n}\n```\n\n# Issues\nFeel free to open issues on the repository if you find any errors with the package or have wishes for features. Read [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to best contribute to the repository.\n\n# Related repositories\nThis project is used in the following projects:\n- https://github.com/KristofferStrube/Blazor.Streams\n- https://github.com/KristofferStrube/Blazor.DOM\n- https://github.com/KristofferStrube/Blazor.MediaCaptureStreams\n- https://github.com/KristofferStrube/Blazor.WebAudio\n\nAnd it is planned to be used in these projects:\n- https://github.com/KristofferStrube/Blazor.FileAPI\n- https://github.com/KristofferStrube/Blazor.FileSystem\n- https://github.com/KristofferStrube/Blazor.FileSystemAccess\n\n# Related articles\nHow this project was developed is explored in this article from my blog:\n- [Typed exceptions for JSInterop in Blazor](https://kristoffer-strube.dk/post/typed-exceptions-for-jsinterop-in-blazor/)\n\nThis repository was build with inspiration and help from the following series of articles:\n- [Wrapping JavaScript libraries in Blazor WebAssembly/WASM](https://blog.elmah.io/wrapping-javascript-libraries-in-blazor-webassembly-wasm/)\n- [Call anonymous C# functions from JS in Blazor WASM](https://blog.elmah.io/call-anonymous-c-functions-from-js-in-blazor-wasm/)\n- [Using JS Object References in Blazor WASM to wrap JS libraries](https://blog.elmah.io/using-js-object-references-in-blazor-wasm-to-wrap-js-libraries/)\n- [Blazor WASM 404 error and fix for GitHub Pages](https://blog.elmah.io/blazor-wasm-404-error-and-fix-for-github-pages/)\n- [How to fix Blazor WASM base path problems](https://blog.elmah.io/how-to-fix-blazor-wasm-base-path-problems/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkristofferstrube%2Fblazor.webidl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkristofferstrube%2Fblazor.webidl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkristofferstrube%2Fblazor.webidl/lists"}