Loading Blazor and Ren-C Wasm in the Same Page

So I'm cleaning some files off of a laptop that I'm giving my mom (in preparation for the moment when I get around to picking a new one to buy, whenever that happens).

One file I had just on this laptop pertained to getting Blazor to load a Ren-C interpreter. The only big deal was that some programs built with emscripten (like Blazor itself) do not play friendly with other emscripten programs loaded in the same page. The Wasm build is now done so that it moves itself out of the way. As a consequence, the loading just works about like any other "calling JS from Blazor" works.

There's really nothing to see in loading the two into the same page. There's a Blazor-related <script> tag and a Ren-C-related <script> tag. I didn't publish it because I didn't put together a meaningful demo once the two were loaded, but I wanted to put this somewhere before letting go of the laptop.

The more unique level of integration would be to be able to call Ren-C directly from C# / .NET built for Wasm without needing to go through a JavaScript bridge. But, getting them loading in the same page was a necessary but sufficient precondition for that.

For whatever it is worth, here is an index.html that loads both libraries, which you can call from JS (and you can call Ren-C from the JS bridge inside Blazor, and Blazor from Ren-C via the Blazor API exposed as JS):

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <title>Test Ren-C Integration</title>
    <base href="/" />
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    <link href="css/app.css" rel="stylesheet" />
</head>

<body>
    <app>Loading...</app>

    <div id="blazor-error-ui">
        An unhandled error has occurred.
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>

    <!-- Disable "autostart" so we can put a .then() on Blazor.start() -->
    <!-- https://github.com/dotnet/aspnetcore/issues/17504 -->
    <script src="_framework/blazor.webassembly.js" autostart="false"></script>

    <!-- The Ren-C interpreter loader for WebAssembly -->
    <script src="https://metaeducation.s3.amazonaws.com/travis-builds/load-r3.js"></script>
    <script>
        Blazor.start({}).then(() => {
            alert("blazor says its loaded?")

            reb.Startup({tracing_on: true}).then(() => {
                alert("Rebol says its loaded?")
            })
        });
    </script>
</body>

</html>
1 Like

I was a bit impressed with how well Blazor was working 3 years ago for how new it was. They'd done a pretty good job of making the "DLLs of WebAssembly" (side modules) which I haven't yet gotten a grip on. And their Wasm files for the various modules were surprisingly small.

But it seems in the intervening years, Blazor has gained a fair bit of momentum. A friend of mine is using it and sings its praises. He's using this:

I don't like going off on random tangents when there's still lots of design issues to hammer out. But providing Rebol services to C# running in the browser could be aligned with the browser-focus mission.

While I used C# right about when it came out for a few things, I've forgotten just about all I knew. And even if I did remember it I imagine it's quite different now (and more different if you're using Blazor). So I don't really know what the story is on variadics.

But we live in the age of AI!

I asked ChatGPT if it could handle it, and it says yes... there are variadics and everything can be considered an object, including string literals:

using System;

class Program
{
    static void someFunction(params object[] args)
    {
        foreach (var arg in args)
        {
            Console.Write($"{arg} ");
        }
        Console.WriteLine();
    }

    static int makeInt(int i) => i;

    static void Main()
    {
        // prints "1 hello world 2"
        someFunction(1, "hello", "world", 2);

        // prints "hello 1"
        someFunction("hello", 1);

        // prints "1 hello world 2"
        someFunction(makeInt(1), "hello", "world", makeInt(2));
    }
}

C# apparently uses UTF-16 internally (losers!) but you can convert the literal strings to UTF-8:

using System;
using System.Text;

class Program
{
    static byte[] StringToUtf8(string str)
    {
        return Encoding.UTF8.GetBytes(str);
    }

    static void Main()
    {
        string myString = "hello";
        byte[] utf8Buffer = StringToUtf8(myString);

        // Pass utf8Buffer to WebAssembly function...
    }
}

Here's how you set up Blazor to call JavaScript (which will call the WebAssembly export).

@inject IJSRuntime JS

@code {
    private async Task CallWasmFunction()
    {
        string myString = "hello";
        byte[] utf8Buffer = Encoding.UTF8.GetBytes(myString);

        // Pass the buffer to the JS function
        await JS.InvokeVoidAsync("callWasmFunction", utf8Buffer);
    }
}

Seems Very Promising...

Given the advancements in CSCAPE and all the information about the API already being captured structurally (enough to spit out the C/C++ and JavaScript interface code), adding C# might not be difficult at all.

So maybe if I get bored or blocked I'll hack this up.

1 Like