Skip to content

Commit

Permalink
Merge pull request #9 from KristofferStrube/feature/update-web-idl-ve…
Browse files Browse the repository at this point in the history
…rsion

Updated Blazor.WebIDL version to 0.5.0.
  • Loading branch information
KristofferStrube authored Mar 10, 2024
2 parents b3452a6 + 3055621 commit 40b69f7
Show file tree
Hide file tree
Showing 52 changed files with 832 additions and 629 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="HtmlAgilityPack" Version="1.11.59" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.0-rc.1.22427.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.0-rc.1.22427.2" PrivateAssets="all" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ The for-loop that consumes the <code>ReadableStream</code> also limits its consu

protected override async Task OnInitializedAsync()
{
var readableStream = await ReadableStream.CreateAsync(JSRuntime, new UnderlyingSource(JSRuntime)
await using ReadableStream readableStream = await ReadableStream.CreateAsync(JSRuntime, new UnderlyingSource(JSRuntime)
{
Start = async (ctr) =>
{
Expand All @@ -41,7 +41,7 @@ The for-loop that consumes the <code>ReadableStream</code> also limits its consu
HighWaterMark = 50,
Size = _ => 10,
});
var reader = await readableStream.GetDefaultReaderAsync();
await using ReadableStreamDefaultReader reader = await readableStream.GetDefaultReaderAsync();
await foreach (var chunk in reader.IterateByteArraysAsync())
{
if (chunk is not null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ We can create a new instance of a <code>WritableStream</code> which can receive

protected override async Task OnInitializedAsync()
{
var writableStream = await WritableStream.CreateAsync(JSRuntime, new UnderlyingSink(JSRuntime)
WritableStream writableStream = await WritableStream.CreateAsync(JSRuntime, new UnderlyingSink(JSRuntime)
{
Write = async (chunk, controller) =>
{
Expand All @@ -26,7 +26,7 @@ We can create a new instance of a <code>WritableStream</code> which can receive
}
}, await ByteLengthQueuingStrategy.CreateAsync(JSRuntime, new QueuingStrategyInit(20)));

var writer = await writableStream.GetWriterAsync();
await using WritableStreamDefaultWriter writer = await writableStream.GetWriterAsync();
for (int i = 0; i < 10; i++)
{
await Task.Delay(100);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,21 @@ Using the reader we read the chunks until there are no more.

protected override async Task OnInitializedAsync()
{
using var data = new System.IO.MemoryStream(new byte[dataSize]);
using var streamRef = new DotNetStreamReference(stream: data, leaveOpen: false);
var jSStreamReference = await JSRuntime.InvokeAsync<IJSInProcessObjectReference>("jSStreamReference", streamRef);
var readableStream = await ReadableStreamInProcess.CreateAsync(JSRuntime, jSStreamReference);
var readableStreamReader = readableStream.GetDefaultReader();
var read = await readableStreamReader.ReadAsync();
using Stream data = new System.IO.MemoryStream(new byte[dataSize]);
using DotNetStreamReference streamRef = new DotNetStreamReference(stream: data, leaveOpen: false);
await using IJSInProcessObjectReference jSStreamReference = await JSRuntime.InvokeAsync<IJSInProcessObjectReference>("jSStreamReference", streamRef);
await using ReadableStreamInProcess readableStream = await ReadableStreamInProcess.CreateAsync(JSRuntime, jSStreamReference);
await using ReadableStreamDefaultReaderInProcess readableStreamReader = readableStream.GetDefaultReader();
ReadableStreamReadResultInProcess read = await readableStreamReader.ReadAsync();
while (!read.Done)
{
var length = await JSRuntime.InvokeAsync<int>("getAttribute", read.Value, "length");
chunkSizes.Add(length);
await Task.Delay(100);
await read.DisposeAsync();
read = await readableStreamReader.ReadAsync();
StateHasChanged();
}
await read.DisposeAsync();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ We iterate the <code>ReadableStream</code> using <code>await foreach(var chunk i

protected override async Task OnInitializedAsync()
{
using var data = new System.IO.MemoryStream(new byte[dataSize]);
using var streamRef = new DotNetStreamReference(stream: data, leaveOpen: false);
var jSStreamReference = await JSRuntime.InvokeAsync<IJSInProcessObjectReference>("jSStreamReference", streamRef);
var readableStream = await ReadableStream.CreateAsync(JSRuntime, jSStreamReference);
var reader = await readableStream.GetDefaultReaderAsync();
using Stream data = new System.IO.MemoryStream(new byte[dataSize]);
using DotNetStreamReference streamRef = new DotNetStreamReference(stream: data, leaveOpen: false);
await using IJSInProcessObjectReference jSStreamReference = await JSRuntime.InvokeAsync<IJSInProcessObjectReference>("jSStreamReference", streamRef);
await using ReadableStream readableStream = await ReadableStream.CreateAsync(JSRuntime, jSStreamReference);
await using ReadableStreamDefaultReader reader = await readableStream.GetDefaultReaderAsync();
await foreach (var chunk in reader)
{
var length = await JSRuntime.InvokeAsync<int>("getAttribute", chunk, "length");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ In this sample we copy a <code>ReadableStream</code> containing an image to a .N

protected override async Task OnInitializedAsync()
{
var data = await HttpClient.GetStreamAsync("images/mountain.jpg");
using var streamRef = new DotNetStreamReference(stream: data, leaveOpen: false);
var jSStreamReference = await JSRuntime.InvokeAsync<IJSInProcessObjectReference>("jSStreamReference", streamRef);
var readableStream = await ReadableStreamInProcess.CreateAsync(JSRuntime, jSStreamReference);
using Stream data = await HttpClient.GetStreamAsync("images/mountain.jpg");
using DotNetStreamReference streamRef = new DotNetStreamReference(stream: data, leaveOpen: false);
await using IJSInProcessObjectReference jSStreamReference = await JSRuntime.InvokeAsync<IJSInProcessObjectReference>("jSStreamReference", streamRef);
await using ReadableStreamInProcess readableStream = await ReadableStreamInProcess.CreateAsync(JSRuntime, jSStreamReference);

using var writeStream = new System.IO.MemoryStream();
using MemoryStream writeStream = new System.IO.MemoryStream();
await readableStream.CopyToAsync(writeStream);
imageUrl = "data:image/png;base64," + Convert.ToBase64String(writeStream.ToArray());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,76 @@
@page "/Status"

@using HtmlAgilityPack;

@inject HttpClient HttpClient
@inject IJSRuntime JSRuntime

<PageTitle>Streams - Status</PageTitle>

<pre><code>@((MarkupString)compareText)</code></pre>
@if (compareText is not null)
{
<pre><code>
@((MarkupString)compareText)
</code></pre>
}
else
{
<text>Loading WebIDL from specs ...</text>
<br />
<small>This make take a while as it is fetching the current specification live.</small>
}

@code {
private string compareText = "";
private string? compareText;

protected override void OnInitialized()
protected override async Task OnAfterRenderAsync(bool firstRender)
{
var compareLines = new List<string>();
var lines = webIDL.Replace("<", "&lt;").Split('\n');
for (int i = 0; i < lines.Count(); i++)
if (firstRender)
{
var color = supportedRows.Any(interval => i >= interval.start && i <= interval.end) ? "lightgreen" : "pink";
compareLines.Add($"""<span style="background-color:{color};display:block;min-height:21px;">{lines[i]}</span>""");
string domString = await HttpClient.GetStringAsync("https://streams.spec.whatwg.org/#idl-index");

var dom = new HtmlDocument();
dom.LoadHtml(domString);
var idlIndexHeader = dom.GetElementbyId("idl-index");
var webIDLNode = idlIndexHeader.NextSibling.NextSibling;
var webIDLText = webIDLNode.InnerText;
// We normalize to indent with 4 spaces as that is inconsistent in the current WebIDL specs.
var fetchedLines = webIDLText.Replace(" ", " ").Replace("\n ", "\n ").Split('\n');
var supportedLines = currentlySupportedWebIDL.Replace("<", "&lt;").Split('\n');
var compareLines = new List<string>();
var fetchedIndex = 0;
var supportedIndex = 0;
while (fetchedIndex < fetchedLines.Length || supportedIndex < supportedLines.Length)
{
var color = "pink";
if (fetchedIndex == fetchedLines.Length)
{
color = "cyan";
supportedIndex++;
fetchedIndex--;
}
else if (supportedIndex == supportedLines.Length)
{
color = "lemonchiffon";
}
else if (fetchedLines[fetchedIndex].Trim() == supportedLines[supportedIndex].Trim())
{
color = "lightgreen";
supportedIndex++;
}
else if (new string(fetchedLines[fetchedIndex].Trim().Take(10).ToArray()) == new string(supportedLines[supportedIndex].Trim().Take(10).ToArray()))
{
color = "lemonchiffon";
supportedIndex++;
}
compareLines.Add($"""<span style="background-color:{color};display:block;min-height:21px;">{fetchedLines[fetchedIndex++]}</span>""");
}
compareText = string.Join("", compareLines);
StateHasChanged();
}

compareText = string.Join("", compareLines);
StateHasChanged();
}

private (int start, int end)[] supportedRows = new (int start, int end)[] { (0, 22), (26, 35), (37, 216) };

private const string webIDL = @"[Exposed=*, Transferable]
private const string currentlySupportedWebIDL = @"[Exposed=*, Transferable]
interface ReadableStream {
constructor(optional object underlyingSource, optional QueuingStrategy strategy = {});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ We iterate the reader using <code>await foreach (byte[] chunk in reader.IterateB

protected override async Task OnInitializedAsync()
{
using var data = new System.IO.MemoryStream(new byte[dataSize]);
using var streamRef = new DotNetStreamReference(stream: data, leaveOpen: false);
var jSStreamReference = await JSRuntime.InvokeAsync<IJSInProcessObjectReference>("jSStreamReference", streamRef);
var readableStream = await ReadableStream.CreateAsync(JSRuntime, jSStreamReference);
var reader = await readableStream.GetDefaultReaderAsync();
using Stream data = new System.IO.MemoryStream(new byte[dataSize]);
using DotNetStreamReference streamRef = new DotNetStreamReference(stream: data, leaveOpen: false);
IJSInProcessObjectReference jSStreamReference = await JSRuntime.InvokeAsync<IJSInProcessObjectReference>("jSStreamReference", streamRef);
ReadableStream readableStream = await ReadableStream.CreateAsync(JSRuntime, jSStreamReference);
ReadableStreamDefaultReader reader = await readableStream.GetDefaultReaderAsync();
await foreach (byte[] chunk in reader.IterateByteArraysAsync())
{
chunkSizes.Add(chunk.Length);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ Cras efficitur libero sed justo ultricies congue et in lacus.In elit orci, phare

protected override async Task OnInitializedAsync()
{
using var data = new System.IO.MemoryStream();
using var writer = new StreamWriter(data, encoding);
using Stream data = new System.IO.MemoryStream();
using StreamWriter writer = new StreamWriter(data, encoding);
writer.Write(loremIpsum);
writer.Flush();
data.Position = 0;
using var streamRef = new DotNetStreamReference(stream: data, leaveOpen: false);
var jSStreamReference = await JSRuntime.InvokeAsync<IJSInProcessObjectReference>("jSStreamReference", streamRef);
var readableStream = await ReadableStream.CreateAsync(JSRuntime, jSStreamReference);
var reader = await readableStream.GetDefaultReaderAsync();
using DotNetStreamReference streamRef = new DotNetStreamReference(stream: data, leaveOpen: false);
await using IJSInProcessObjectReference jSStreamReference = await JSRuntime.InvokeAsync<IJSInProcessObjectReference>("jSStreamReference", streamRef);
await using ReadableStream readableStream = await ReadableStream.CreateAsync(JSRuntime, jSStreamReference);
await using ReadableStreamDefaultReader reader = await readableStream.GetDefaultReaderAsync();
await foreach (string chunk in reader.IterateStringsAsync(encoding))
{
result += chunk;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ In this sample we copy a .NET <code>Stream</code> containing an image to a <code

protected override async Task OnInitializedAsync()
{
var data = await HttpClient.GetStreamAsync("images/mountain.jpg");
using Stream data = await HttpClient.GetStreamAsync("images/mountain.jpg");

var writableStream = await WritableStream.CreateAsync(JSRuntime, new UnderlyingSink(JSRuntime)
WritableStream writableStream = await WritableStream.CreateAsync(JSRuntime, new UnderlyingSink(JSRuntime)
{
Start = (_) =>
{
Expand Down
3 changes: 3 additions & 0 deletions src/KristofferStrube.Blazor.Streams/ArrayBufferView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,20 @@ namespace KristofferStrube.Blazor.Streams;
/// <summary>
/// <see href="https://webidl.spec.whatwg.org/#ArrayBufferView">WebIDL browser specs</see>
/// </summary>
[Obsolete("A richer implementation has been introduced in Blazor.WebIDL so we shouldn't use this simple wrapper anymore. Use IArrayBufferView from Blazor.WebIDL instead.")]
public class ArrayBufferView
{
public readonly IJSObjectReference JSReference;

Check warning on line 11 in src/KristofferStrube.Blazor.Streams/ArrayBufferView.cs

View workflow job for this annotation

GitHub Actions / build

Missing XML comment for publicly visible type or member 'ArrayBufferView.JSReference'

[Obsolete("A richer implementation has been introduced in Blazor.WebIDL so we shouldn't use this simple wrapper anymore. Use IArrayBufferView from Blazor.WebIDL instead.")]
public static async Task<ArrayBufferView> CreateByteArrayAsync(IJSRuntime jSRuntime, int size)

Check warning on line 14 in src/KristofferStrube.Blazor.Streams/ArrayBufferView.cs

View workflow job for this annotation

GitHub Actions / build

Missing XML comment for publicly visible type or member 'ArrayBufferView.CreateByteArrayAsync(IJSRuntime, int)'
{
IJSObjectReference helper = await jSRuntime.GetHelperAsync();
IJSObjectReference jSInstance = await helper.InvokeAsync<IJSObjectReference>("constructByteArray", size);
return new ArrayBufferView(jSInstance);
}

[Obsolete("A richer implementation has been introduced in Blazor.WebIDL so we shouldn't use this simple wrapper anymore. Use IArrayBufferView from Blazor.WebIDL instead.")]
protected internal ArrayBufferView(IJSObjectReference jSReference)

Check warning on line 22 in src/KristofferStrube.Blazor.Streams/ArrayBufferView.cs

View workflow job for this annotation

GitHub Actions / build

Missing XML comment for publicly visible type or member 'ArrayBufferView.ArrayBufferView(IJSObjectReference)'
{
JSReference = jSReference;
Expand Down
33 changes: 22 additions & 11 deletions src/KristofferStrube.Blazor.Streams/BaseJSStreamableWrapper.cs
Original file line number Diff line number Diff line change
@@ -1,23 +1,34 @@
using Microsoft.JSInterop;
using KristofferStrube.Blazor.WebIDL;
using Microsoft.JSInterop;

namespace KristofferStrube.Blazor.Streams;

public abstract class BaseJSStreamableWrapper : Stream, IAsyncDisposable
/// <summary>
/// A base class for all streamable wrappers in Blazor.Streams.
/// </summary>
public abstract class BaseJSStreamableWrapper : Stream, IAsyncDisposable, IJSWrapper
{
public readonly IJSObjectReference JSReference;
protected readonly Lazy<Task<IJSObjectReference>> helperTask;
protected readonly IJSRuntime jSRuntime;

/// <summary>
/// Constructs a wrapper instance for an equivalent JS instance.
/// A lazily loaded task that evaluates to a helper module instance from the Blazor.Streams library.
/// </summary>
/// <param name="jSRuntime">An <see cref="IJSRuntime"/> instance.</param>
/// <param name="jSReference">A JS reference to an existing JS instance that should be wrapped..</param>
internal BaseJSStreamableWrapper(IJSRuntime jSRuntime, IJSObjectReference jSReference)
protected readonly Lazy<Task<IJSObjectReference>> helperTask;

/// <inheritdoc/>
public IJSRuntime JSRuntime { get; }

/// <inheritdoc/>
public IJSObjectReference JSReference { get; }

/// <inheritdoc/>
public bool DisposesJSReference { get; }

/// <inheritdoc cref="IJSCreatable{T}.CreateAsync(IJSRuntime, IJSObjectReference, CreationOptions)"/>
protected internal BaseJSStreamableWrapper(IJSRuntime jSRuntime, IJSObjectReference jSReference, CreationOptions options)
{
helperTask = new(() => jSRuntime.GetHelperAsync());
JSRuntime = jSRuntime;
JSReference = jSReference;
this.jSRuntime = jSRuntime;
DisposesJSReference = options.DisposesJSReference;
}

public override async ValueTask DisposeAsync()

Check warning on line 34 in src/KristofferStrube.Blazor.Streams/BaseJSStreamableWrapper.cs

View workflow job for this annotation

GitHub Actions / build

Missing XML comment for publicly visible type or member 'BaseJSStreamableWrapper.DisposeAsync()'
Expand Down
28 changes: 21 additions & 7 deletions src/KristofferStrube.Blazor.Streams/BaseJSWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,46 @@

namespace KristofferStrube.Blazor.Streams;

public abstract class BaseJSWrapper : IAsyncDisposable, IJSWrapper
/// <summary>
/// A base class for all wrappers in Blazor.Streams.
/// </summary>
public abstract class BaseJSWrapper : IJSWrapper
{
public IJSObjectReference JSReference { get; }
public IJSRuntime JSRuntime { get; }

/// <summary>
/// A lazily loaded task that evaluates to a helper module instance from the Blazor.Streams library.
/// </summary>
protected readonly Lazy<Task<IJSObjectReference>> helperTask;

/// <inheritdoc/>
public IJSRuntime JSRuntime { get; }
/// <inheritdoc/>
public IJSObjectReference JSReference { get; }
/// <inheritdoc/>
public bool DisposesJSReference { get; }

/// <summary>
/// Constructs a wrapper instance for an equivalent JS instance.
/// </summary>
/// <param name="jSRuntime">An <see cref="IJSRuntime"/> instance.</param>
/// <param name="jSReference">A JS reference to an existing JS instance that should be wrapped..</param>
internal BaseJSWrapper(IJSRuntime jSRuntime, IJSObjectReference jSReference)
/// <param name="jSReference">A JS reference to an existing JS instance that should be wrapped.</param>
/// <param name="options">The options for constructing this wrapper.</param>
internal BaseJSWrapper(IJSRuntime jSRuntime, IJSObjectReference jSReference, CreationOptions options)
{
helperTask = new(() => jSRuntime.GetHelperAsync());
JSRuntime = jSRuntime;
JSReference = jSReference;
this.JSRuntime = jSRuntime;
DisposesJSReference = options.DisposesJSReference;
}

/// <inheritdoc/>
public async ValueTask DisposeAsync()
{
if (helperTask.IsValueCreated)
{
IJSObjectReference module = await helperTask.Value;
await module.DisposeAsync();
}
await IJSWrapper.DisposeJSReference(this);
GC.SuppressFinalize(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="KristofferStrube.Blazor.WebIDL" Version="0.1.0-alpha.1" />
<PackageReference Include="KristofferStrube.Blazor.WebIDL" Version="0.5.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="7.0.3" />
</ItemGroup>

Expand Down
Loading

0 comments on commit 40b69f7

Please sign in to comment.