Skip to content

Commit

Permalink
Minor: Add proxy JS runtime to intercept calls to import module
Browse files Browse the repository at this point in the history
  • Loading branch information
mingyaulee committed Apr 14, 2024
1 parent 0c7bc64 commit 4b0c0c4
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 7 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Blazor.BrowserExtension

[![Nuget](https://img.shields.io/nuget/v/Blazor.BrowserExtension?style=for-the-badge&color=blue)](https://www.nuget.org/packages/Blazor.BrowserExtension/)
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/mingyaulee/Blazor.BrowserExtension/Blazor.BrowserExtension-Build.yml?branch=main&style=for-the-badge&color=blue)](https://github.com/mingyaulee/JsBind.Net/actions/workflows/JsBind.Net-Build.yml)
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/mingyaulee/Blazor.BrowserExtension/Blazor.BrowserExtension-Build.yml?branch=main&style=for-the-badge&color=blue)](https://github.com/mingyaulee/Blazor.BrowserExtension/actions/workflows/Blazor.BrowserExtension-Build.yml)
[![Sonar Quality Gate](https://img.shields.io/sonar/quality_gate/Blazor.BrowserExtension?server=https%3A%2F%2Fsonarcloud.io&style=for-the-badge)](https://sonarcloud.io/dashboard?id=Blazor.BrowserExtension)

You can now easily build a browser extension with Blazor!
Expand Down
1 change: 1 addition & 0 deletions src/Blazor.BrowserExtension/Blazor.BrowserExtension.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
</PropertyGroup>

<ItemGroup>
<Content Update="content\*.json" CopyToOutputDirectory="Never" />
<Content Include="build\**">
<Pack>true</Pack>
<PackagePath>build</PackagePath>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,19 @@ public static partial class ServiceCollectionExtensions
{
public static IServiceCollection AddBrowserExtensionServices(this IServiceCollection services)
{
#if NET7_0_OR_GREATER
var browserExtensionEnvironment = new BrowserExtensionEnvironment(GetBrowserExtensionMode());
#else
if (services.FirstOrDefault(service => service.ServiceType == typeof(IJSRuntime))?.ImplementationInstance is not IJSUnmarshalledRuntime jsRuntime)
var iJsRuntimeService = services.FirstOrDefault(service => service.ServiceType == typeof(IJSRuntime));
if (iJsRuntimeService?.ImplementationInstance is not IJSRuntime jsRuntime)
{
throw new NotSupportedException("An instance of IJSUnmarshalledRuntime must be registered by Blazor.");
throw new NotSupportedException("An instance of IJSRuntime must be registered by Blazor.");
}

var browserExtensionEnvironment = new BrowserExtensionEnvironment(GetBrowserExtensionMode(jsRuntime));
services.Remove(iJsRuntimeService);
services.AddSingleton<IJSRuntime>(new ProxyJsRuntime(jsRuntime));

#if NET7_0_OR_GREATER
var browserExtensionEnvironment = new BrowserExtensionEnvironment(GetBrowserExtensionMode());
#else
var browserExtensionEnvironment = new BrowserExtensionEnvironment(GetBrowserExtensionMode((IJSUnmarshalledRuntime)jsRuntime));
#endif
IBrowserExtensionEnvironment.Instance = browserExtensionEnvironment;
services.AddSingleton<IBrowserExtensionEnvironment>(browserExtensionEnvironment);
Expand Down
50 changes: 50 additions & 0 deletions src/Blazor.BrowserExtension/ProxyJsRuntime.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.JSInterop;

namespace Blazor.BrowserExtension
{
internal class ProxyJsRuntime : IJSInProcessRuntime
{
private readonly IJSRuntime instance;
private readonly IJSInProcessRuntime inProcessInstance;

public ProxyJsRuntime(IJSRuntime instance)
{
this.instance = instance;
inProcessInstance = instance as IJSInProcessRuntime;
}

public ValueTask<TValue> InvokeAsync<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicProperties)] TValue>(string identifier, object[] args)
{
return instance.InvokeAsync<TValue>(identifier, InterceptArgs(identifier, args));
}

public ValueTask<TValue> InvokeAsync<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicProperties)] TValue>(string identifier, CancellationToken cancellationToken, object[] args)
{
return instance.InvokeAsync<TValue>(identifier, cancellationToken, InterceptArgs(identifier, args));
}

public TResult Invoke<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicProperties)] TResult>(string identifier, params object[] args)
{
return inProcessInstance.Invoke<TResult>(identifier, args);
}

static object[] InterceptArgs(string identifier, object[] args)
{
if (identifier == "import")
{
return args?.Select(importArg => importArg is string importPath ? ReplaceImportPath(importPath) : importArg).ToArray();
}
return args;
}

static string ReplaceImportPath(string importPath)
{
var splitPaths = importPath.Split('/');
return string.Join('/', splitPaths.Select((path, index) => index < splitPaths.Length - 1 && path.StartsWith('_') ? path[1..] : path));
}
}
}

0 comments on commit 4b0c0c4

Please sign in to comment.