Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[browser] Support AppContext switches on runtime #97449

Open
maraf opened this issue Jan 24, 2024 · 5 comments
Open

[browser] Support AppContext switches on runtime #97449

maraf opened this issue Jan 24, 2024 · 5 comments
Assignees
Labels
arch-wasm WebAssembly architecture area-Build-mono os-browser Browser variant of arch-wasm Priority:1 Work that is critical for the release, but we could probably ship without
Milestone

Comments

@maraf
Copy link
Member

maraf commented Jan 24, 2024

AppContext switches defined in csproj are not available on runtime

<ItemGroup>
    ...
    <RuntimeHostConfigurationOption Include="System.Runtime.OptionalFeatureBehavior"
                                    Condition="'$(UnoptimizedUserFacingBehavior)' != ''"
                                    Value="$(UnoptimizedUserFacingBehavior)"
                                    Link="false" />
    ...
</ItemGroup>

On other platforms, they end up in runtime.config.json. We should put them into blazor.boot.json as that's the only config required (for both wasmbrowser and blazor experience)

@maraf maraf added arch-wasm WebAssembly architecture area-Build-mono os-browser Browser variant of arch-wasm labels Jan 24, 2024
@maraf maraf added this to the 9.0.0 milestone Jan 24, 2024
@ghost
Copy link

ghost commented Jan 24, 2024

Tagging subscribers to 'arch-wasm': @lewing
See info in area-owners.md if you want to be subscribed.

Issue Details

AppContext switches defined in csproj are not available on runtime

<ItemGroup>
    ...
    <RuntimeHostConfigurationOption Include="System.Runtime.OptionalFeatureBehavior"
                                    Condition="'$(UnoptimizedUserFacingBehavior)' != ''"
                                    Value="$(UnoptimizedUserFacingBehavior)"
                                    Link="false" />
    ...
</ItemGroup>

On other platforms, they end up in runtime.config.json. We should put them into blazor.boot.json as that's the only config required (for both wasmbrowser and blazor experience)

Author: maraf
Assignees: -
Labels:

arch-wasm, area-Build-mono, os-browser

Milestone: 9.0.0

@lewing
Copy link
Member

lewing commented Jan 24, 2024

AppContext switches defined in csproj are not available on runtime

<ItemGroup>
    ...
    <RuntimeHostConfigurationOption Include="System.Runtime.OptionalFeatureBehavior"
                                    Condition="'$(UnoptimizedUserFacingBehavior)' != ''"
                                    Value="$(UnoptimizedUserFacingBehavior)"
                                    Link="false" />
    ...
</ItemGroup>

On other platforms, they end up in runtime.config.json. We should put them into blazor.boot.json as that's the only config required (for both wasmbrowser and blazor experience)

That works for browser but we will have the same issue in wasi where there is no json parser.

@maraf
Copy link
Member Author

maraf commented Jan 25, 2024

That works for browser but we will have the same issue in wasi where there is no json parser.

That's true. We can use the binary format for WASI and we bundle it into wasm file even for browser, but I would like to avoid distributing it as a separate file for browser scenario

@maraf maraf self-assigned this Jan 25, 2024
@lambdageek
Copy link
Member

Mono has a task that converts rutnimeconfig.json files into a binary blob at build time so you don't need to do JSON parsing at execution time
https://github.com/dotnet/runtime/blob/main/src/tasks/MonoTargetsTasks/RuntimeConfigParser/RuntimeConfigParser.cs

the binary blob can be passed by the driver to monovm_runtimeconfig_initialize:

MONO_API_FUNCTION(int, monovm_runtimeconfig_initialize, (MonovmRuntimeConfigArguments *arg, MonovmRuntimeConfigArgumentsCleanup cleanup_fn, void *user_data))

typedef struct {
uint32_t kind; // 0 = Path of runtimeconfig.blob, 1 = pointer to image data, >= 2 undefined
union {
struct {
const char *path;
} name;
struct {
const char *data;
uint32_t data_len;
} data;
} runtimeconfig;
} MonovmRuntimeConfigArguments;
typedef void (*MonovmRuntimeConfigArgumentsCleanup) (MonovmRuntimeConfigArguments *args, void *user_data);

This is used by xamarin-android, for example:

https://github.com/xamarin/xamarin-android/blob/e67afc7d7ae848da6b33026b80973d30713b98ad/src/monodroid/jni/monodroid-glue.cc#L846-L848

@pavelsavara
Copy link
Member

pavelsavara commented Mar 11, 2025

I need this to work in order to implement #111680 and it's P1 goal

After discussion with @maraf I learned that

  • There is RuntimeConfigParser which translates the JSON to .bin file on multiple Mono platforms. In order to avoid managed JSON deserialization during app startup.
  • we are able to load runtimeconfig.bin from VFS and parse it, also in "demo" mode
  • but the file is only being produced with workload installed
  • and with now obsolete tooling _WasmGenerateRuntimeConfig which is only triggered for WasmGenerateAppBundle
  • Blazor prevents downloading runtimeconfig.bin anyway.
  • .bin doesn't have great MIME type configured in most places
  • I dislike using VFS for anything
  • Blazor is full of managed reflection based JSON deserialization anyway

private static void ConvertDictionaryToBlob(Dictionary<string, string> properties, BlobBuilder builder)
{
int count = properties.Count;
builder.WriteCompressedInteger(count);
foreach (var kvp in properties)
{
builder.WriteSerializedString(kvp.Key);
builder.WriteSerializedString(kvp.Value);
}
}

char *file_name = RUNTIMECONFIG_BIN_FILE;
int str_len = strlen (file_name) + 1; // +1 is for the "/"
char *file_path = (char *)malloc (sizeof (char) * (str_len +1)); // +1 is for the terminating null character
int num_char = snprintf (file_path, (str_len + 1), "/%s", file_name);
struct stat buffer;
assert (num_char > 0 && num_char == str_len);
if (stat (file_path, &buffer) == 0) {
MonovmRuntimeConfigArguments *arg = (MonovmRuntimeConfigArguments *)malloc (sizeof (MonovmRuntimeConfigArguments));
arg->kind = 0;
arg->runtimeconfig.name.path = file_path;
monovm_runtimeconfig_initialize (arg, cleanup_runtime_config, file_path);
} else {
free (file_path);
}

internal static unsafe void Setup(char** pNames, uint* pNameLengths, char** pValues, uint* pValueLengths, int count)
{
Debug.Assert(s_dataStore == null, "s_dataStore is not expected to be inited before Setup is called");
s_dataStore = new Dictionary<string, object?>(count);
for (int i = 0; i < count; i++)
{
s_dataStore.Add(new string(pNames[i], 0, (int)pNameLengths[i]), new string(pValues[i], 0, (int)pValueLengths[i]));
}
}

That gives us following implementation options
A) add any runtimeconfig.json as subset of dotnet.boot.json via GenerateWasmBootJson.
Only process the string->string dictionary, same as current AppContext.Setup
But do the JSON parsing in JavaScript for free.
Remove support for .bin file from wasm build
This will also work without workload installed.
This would NOT work for WASI

B) For consistency with other Mono platforms, fix runtimeconfig.bin
Lift RuntimeConfigParser into Microsoft.NET.Sdk.WebAssembly.Pack.Tasks, so that we could use it outside of workload.
Include it in VFS also for Blazor.
Have one extra file to download.
Deal with MIME type.

I prefer A) at this time

@pavelsavara pavelsavara assigned pavelsavara and unassigned maraf Mar 11, 2025
@pavelsavara pavelsavara added Priority:1 Work that is critical for the release, but we could probably ship without and removed Priority:2 Work that is important, but not critical for the release labels Mar 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
arch-wasm WebAssembly architecture area-Build-mono os-browser Browser variant of arch-wasm Priority:1 Work that is critical for the release, but we could probably ship without
Projects
None yet
Development

No branches or pull requests

5 participants