Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -372,8 +372,8 @@ Copyright (c) .NET Foundation. All rights reserved.
RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)"
Extensions="@(WasmBootConfigExtension)"
TargetFrameworkVersion="$(TargetFrameworkVersion)"
ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)"
ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" />
LibraryInitializerOnRuntimeConfigLoaded="@(WasmLibraryInitializerOnRuntimeConfigLoaded)"
LibraryInitializerOnRuntimeReady="@(WasmLibraryInitializerOnRuntimeReady)" />

<ItemGroup>
<FileWrites Include="$(_WasmBuildBootJsonPath)" />
Expand DownExpand Up@@ -563,8 +563,8 @@ Copyright (c) .NET Foundation. All rights reserved.
RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)"
Extensions="@(WasmBootConfigExtension)"
TargetFrameworkVersion="$(TargetFrameworkVersion)"
ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)"
ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" />
LibraryInitializerOnRuntimeConfigLoaded="@(WasmLibraryInitializerOnRuntimeConfigLoaded)"
LibraryInitializerOnRuntimeReady="@(WasmLibraryInitializerOnRuntimeReady)" />

<ItemGroup>
<FileWrites Include="$(IntermediateOutputPath)blazor.publish.boot.json" />
Expand Down
10 changes: 2 additions & 8 deletions src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -390,21 +390,15 @@ public void AssertBootJson(AssertBundleOptionsBase options)
Assert.True(File.Exists(bootJsonPath), $"Expected to find {bootJsonPath}");

BootJsonData bootJson = ParseBootData(bootJsonPath);
var bootJsonEntries = bootJson.resources.jsModuleNative.Keys
.Union(bootJson.resources.jsModuleRuntime.Keys)
.Union(bootJson.resources.jsModuleWorker?.Keys ?? Enumerable.Empty<string>())
.Union(bootJson.resources.jsSymbols?.Keys ?? Enumerable.Empty<string>())
.Union(bootJson.resources.wasmNative.Keys)
.ToArray();
var bootJsonEntries = bootJson.resources.runtime.Keys.Where(k => k.StartsWith("dotnet.", StringComparison.Ordinal)).ToArray();

var expectedEntries = new SortedDictionary<string, Action<string>>();
IReadOnlySet<string> expected = GetDotNetFilesExpectedSet(options);

var knownSet = GetAllKnownDotnetFilesToFingerprintMap(options);
foreach (string expectedFilename in expected)
{
// FIXME: Find a systematic solution for skipping dotnet.js from boot json check
if (expectedFilename == "dotnet.js" || Path.GetExtension(expectedFilename) == ".map")
if (Path.GetExtension(expectedFilename) == ".map")
continue;

bool expectFingerprint = knownSet[expectedFilename];
Expand Down
101 changes: 53 additions & 48 deletions src/mono/wasm/runtime/dotnet.d.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -95,6 +95,14 @@ interface DotnetHostBuilder {
run(): Promise<number>;
}
type MonoConfig = {
/**
* The subfolder containing managed assemblies and pdbs. This is relative to dotnet.js script.
*/
assemblyRootFolder?: string;
/**
* A list of assets to load along with the runtime.
*/
assets?: AssetEntry[];
/**
* Additional search locations for assets.
*/
Expand DownExpand Up@@ -125,10 +133,6 @@ type MonoConfig = {
* debugLevel < 0 enables debugging and disables debug logging.
*/
debugLevel?: number;
/**
* Gets a value that determines whether to enable caching of the 'resources' inside a CacheStorage instance within the browser.
*/
cacheBootResources?: boolean;
/**
* Enables diagnostic log messages during startup
*/
Expand All@@ -147,6 +151,10 @@ type MonoConfig = {
* If true, the snapshot of runtime's memory will be stored in the browser and used for faster startup next time. Default is false.
*/
startupMemoryCache?: boolean;
/**
* hash of assets
*/
assetsHash?: string;
/**
* application environment
*/
Expand All@@ -159,10 +167,6 @@ type MonoConfig = {
* definition of assets to load along with the runtime.
*/
resources?: ResourceGroups;
/**
* appsettings files to load to VFS
*/
appsettings?: string[];
/**
* config extensions declared in MSBuild items @(WasmBootConfigExtension)
*/
Expand All@@ -174,31 +178,26 @@ type ResourceExtensions = {
[extensionName: string]: ResourceList;
};
interface ResourceGroups {
hash?: string;
assembly?: ResourceList;
lazyAssembly?: ResourceList;
pdb?: ResourceList;
jsModuleWorker?: ResourceList;
jsModuleNative: ResourceList;
jsModuleRuntime: ResourceList;
jsSymbols?: ResourceList;
wasmNative: ResourceList;
icu?: ResourceList;
satelliteResources?: {
readonly hash?: string;
readonly assembly?: ResourceList;
readonly lazyAssembly?: ResourceList;
readonly pdb?: ResourceList;
readonly runtime?: ResourceList;
readonly satelliteResources?: {
[cultureName: string]: ResourceList;
};
modulesAfterConfigLoaded?: ResourceList;
modulesAfterRuntimeReady?: ResourceList;
extensions?: ResourceExtensions;
vfs?: {
readonly libraryInitializers?: ResourceList;
readonly libraryStartupModules?: {
readonly onRuntimeConfigLoaded?: ResourceList;
readonly onRuntimeReady?: ResourceList;
};
readonly extensions?: ResourceExtensions;
readonly vfs?: {
[virtualPath: string]: ResourceList;
};
}
/**
* A "key" is name of the file, a "value" is optional hash for integrity check.
*/
type ResourceList = {
[name: string]: string | null | "";
[name: string]: string;
};
/**
* Overrides the built-in boot resource loading mechanism so that boot resources can be fetched
Expand All@@ -209,12 +208,12 @@ type ResourceList = {
* @param integrity The integrity string representing the expected content in the response.
* @returns A URI string or a Response promise to override the loading process, or null/undefined to allow the default loading behavior.
*/
type LoadBootResourceCallback = (type: AssetBehaviors | "manifest", name: string, defaultUri: string, integrity: string) => string | Promise<Response> | null | undefined;
type LoadBootResourceCallback = (type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string) => string | Promise<Response> | null | undefined;
interface ResourceRequest {
name: string;
behavior: AssetBehaviors;
behavior: AssetBehaviours;
resolvedUrl?: string;
hash?: string | null | "";
hash?: string;
}
interface LoadingResource {
name: string;
Expand DownExpand Up@@ -249,24 +248,7 @@ interface AssetEntry extends ResourceRequest {
*/
pendingDownload?: LoadingResource;
}
type SingleAssetBehaviors =
/**
* The binary of the dotnet runtime.
*/
"dotnetwasm"
/**
* The javascript module for threads.
*/
| "js-module-threads"
/**
* The javascript module for threads.
*/
| "js-module-runtime"
/**
* The javascript module for threads.
*/
| "js-module-native";
type AssetBehaviors = SingleAssetBehaviors |
type AssetBehaviours =
/**
* Load asset as a managed resource assembly.
*/
Expand All@@ -291,6 +273,26 @@ type AssetBehaviors = SingleAssetBehaviors |
* Load asset into the virtual filesystem (for fopen, File.Open, etc).
*/
| "vfs"
/**
* The binary of the dotnet runtime.
*/
| "dotnetwasm"
/**
* The javascript module for threads.
*/
| "js-module-threads"
/**
* The javascript module for threads.
*/
| "js-module-runtime"
/**
* The javascript module for threads.
*/
| "js-module-dotnet"
/**
* The javascript module for threads.
*/
| "js-module-native"
/**
* The javascript module that came from nuget package .
*/
Expand DownExpand Up@@ -328,8 +330,10 @@ type DotnetModuleConfig = {
onConfigLoaded?: (config: MonoConfig) => void | Promise<void>;
onDotnetReady?: () => void | Promise<void>;
onDownloadResourceProgress?: (resourcesLoaded: number, totalResources: number) => void;
getApplicationEnvironment?: (bootConfigResponse: Response) => string | null;
imports?: any;
exports?: string[];
downloadResource?: (request: ResourceRequest) => LoadingResource | undefined;
} & Partial<EmscriptenModule>;
type APIType = {
runMain: (mainAssemblyName: string, args: string[]) => Promise<number>;
Expand DownExpand Up@@ -396,6 +400,7 @@ type ModuleAPI = {
exit: (code: number, reason?: any) => void;
};
type CreateDotnetRuntimeType = (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)) => Promise<RuntimeAPI>;
type WebAssemblyBootResourceType = "assembly" | "pdb" | "dotnetjs" | "dotnetwasm" | "globalization" | "manifest" | "configuration";

interface IDisposable {
dispose(): void;
Expand Down
34 changes: 12 additions & 22 deletions src/mono/wasm/runtime/lazyLoading.ts
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,40 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import { loaderHelpers, runtimeHelpers } from "./globals";
import { AssetEntry } from "./types";
import { INTERNAL, loaderHelpers, runtimeHelpers } from "./globals";
import type { WebAssemblyResourceLoader } from "./loader/blazor/WebAssemblyResourceLoader";

export async function loadLazyAssembly(assemblyNameToLoad: string): Promise<boolean> {
const resources = loaderHelpers.config.resources!;
const resourceLoader: WebAssemblyResourceLoader = INTERNAL.resourceLoader;
const resources = resourceLoader.bootConfig.resources;
const lazyAssemblies = resources.lazyAssembly;
if (!lazyAssemblies) {
throw new Error("No assemblies have been marked as lazy-loadable. Use the 'BlazorWebAssemblyLazyLoad' item group in your project file to enable lazy loading an assembly.");
}

if (!lazyAssemblies[assemblyNameToLoad]) {
const assemblyMarkedAsLazy = Object.prototype.hasOwnProperty.call(lazyAssemblies, assemblyNameToLoad);
if (!assemblyMarkedAsLazy) {
throw new Error(`${assemblyNameToLoad} must be marked with 'BlazorWebAssemblyLazyLoad' item group in your project file to allow lazy-loading.`);
}

const dllAsset: AssetEntry = {
name: assemblyNameToLoad,
hash: lazyAssemblies[assemblyNameToLoad],
behavior: "assembly",
};

if (loaderHelpers.loadedAssemblies.some(f => f.includes(assemblyNameToLoad))) {
return false;
}

const pdbNameToLoad = changeExtension(dllAsset.name, ".pdb");
const shouldLoadPdb = loaderHelpers.hasDebuggingEnabled(loaderHelpers.config) && Object.prototype.hasOwnProperty.call(lazyAssemblies, pdbNameToLoad);
const dllNameToLoad = assemblyNameToLoad;
const pdbNameToLoad = changeExtension(assemblyNameToLoad, ".pdb");
const shouldLoadPdb = loaderHelpers.hasDebuggingEnabled(resourceLoader.bootConfig) && resources.pdb && Object.prototype.hasOwnProperty.call(lazyAssemblies, pdbNameToLoad);

const dllBytesPromise = loaderHelpers.retrieve_asset_download(dllAsset);
const dllBytesPromise = resourceLoader.loadResource(dllNameToLoad, loaderHelpers.locateFile(dllNameToLoad), lazyAssemblies[dllNameToLoad], "assembly").response.then(response => response.arrayBuffer());

let dll = null;
let pdb = null;
if (shouldLoadPdb) {
const pdbBytesPromise = lazyAssemblies[pdbNameToLoad]
? loaderHelpers.retrieve_asset_download({
name: pdbNameToLoad,
hash: lazyAssemblies[pdbNameToLoad],
behavior: "pdb"
})
: Promise.resolve(null);

const pdbBytesPromise = await resourceLoader.loadResource(pdbNameToLoad, loaderHelpers.locateFile(pdbNameToLoad), lazyAssemblies[pdbNameToLoad], "pdb").response.then(response => response.arrayBuffer());
const [dllBytes, pdbBytes] = await Promise.all([dllBytesPromise, pdbBytesPromise]);

dll = new Uint8Array(dllBytes);
pdb = pdbBytes ? new Uint8Array(pdbBytes) : null;
pdb = new Uint8Array(pdbBytes);
} else {
const dllBytes = await dllBytesPromise;
dll = new Uint8Array(dllBytes);
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Revert "[browser] Clean-up typescript code imported from Blazor (#89435)" by radical · Pull Request #89828 · dotnet/runtime · GitHub
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -372,8 +372,8 @@ Copyright (c) .NET Foundation. All rights reserved.
RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)"
Extensions="@(WasmBootConfigExtension)"
TargetFrameworkVersion="$(TargetFrameworkVersion)"
ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)"
ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" />
LibraryInitializerOnRuntimeConfigLoaded="@(WasmLibraryInitializerOnRuntimeConfigLoaded)"
LibraryInitializerOnRuntimeReady="@(WasmLibraryInitializerOnRuntimeReady)" />

<ItemGroup>
<FileWrites Include="$(_WasmBuildBootJsonPath)" />
Expand DownExpand Up@@ -563,8 +563,8 @@ Copyright (c) .NET Foundation. All rights reserved.
RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)"
Extensions="@(WasmBootConfigExtension)"
TargetFrameworkVersion="$(TargetFrameworkVersion)"
ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)"
ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" />
LibraryInitializerOnRuntimeConfigLoaded="@(WasmLibraryInitializerOnRuntimeConfigLoaded)"
LibraryInitializerOnRuntimeReady="@(WasmLibraryInitializerOnRuntimeReady)" />

<ItemGroup>
<FileWrites Include="$(IntermediateOutputPath)blazor.publish.boot.json" />
Expand Down
10 changes: 2 additions & 8 deletions src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -390,21 +390,15 @@ public void AssertBootJson(AssertBundleOptionsBase options)
Assert.True(File.Exists(bootJsonPath), $"Expected to find {bootJsonPath}");

BootJsonData bootJson = ParseBootData(bootJsonPath);
var bootJsonEntries = bootJson.resources.jsModuleNative.Keys
.Union(bootJson.resources.jsModuleRuntime.Keys)
.Union(bootJson.resources.jsModuleWorker?.Keys ?? Enumerable.Empty<string>())
.Union(bootJson.resources.jsSymbols?.Keys ?? Enumerable.Empty<string>())
.Union(bootJson.resources.wasmNative.Keys)
.ToArray();
var bootJsonEntries = bootJson.resources.runtime.Keys.Where(k => k.StartsWith("dotnet.", StringComparison.Ordinal)).ToArray();

var expectedEntries = new SortedDictionary<string, Action<string>>();
IReadOnlySet<string> expected = GetDotNetFilesExpectedSet(options);

var knownSet = GetAllKnownDotnetFilesToFingerprintMap(options);
foreach (string expectedFilename in expected)
{
// FIXME: Find a systematic solution for skipping dotnet.js from boot json check
if (expectedFilename == "dotnet.js" || Path.GetExtension(expectedFilename) == ".map")
if (Path.GetExtension(expectedFilename) == ".map")
continue;

bool expectFingerprint = knownSet[expectedFilename];
Expand Down
101 changes: 53 additions & 48 deletions src/mono/wasm/runtime/dotnet.d.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -95,6 +95,14 @@ interface DotnetHostBuilder {
run(): Promise<number>;
}
type MonoConfig = {
/**
* The subfolder containing managed assemblies and pdbs. This is relative to dotnet.js script.
*/
assemblyRootFolder?: string;
/**
* A list of assets to load along with the runtime.
*/
assets?: AssetEntry[];
/**
* Additional search locations for assets.
*/
Expand DownExpand Up@@ -125,10 +133,6 @@ type MonoConfig = {
* debugLevel < 0 enables debugging and disables debug logging.
*/
debugLevel?: number;
/**
* Gets a value that determines whether to enable caching of the 'resources' inside a CacheStorage instance within the browser.
*/
cacheBootResources?: boolean;
/**
* Enables diagnostic log messages during startup
*/
Expand All@@ -147,6 +151,10 @@ type MonoConfig = {
* If true, the snapshot of runtime's memory will be stored in the browser and used for faster startup next time. Default is false.
*/
startupMemoryCache?: boolean;
/**
* hash of assets
*/
assetsHash?: string;
/**
* application environment
*/
Expand All@@ -159,10 +167,6 @@ type MonoConfig = {
* definition of assets to load along with the runtime.
*/
resources?: ResourceGroups;
/**
* appsettings files to load to VFS
*/
appsettings?: string[];
/**
* config extensions declared in MSBuild items @(WasmBootConfigExtension)
*/
Expand All@@ -174,31 +178,26 @@ type ResourceExtensions = {
[extensionName: string]: ResourceList;
};
interface ResourceGroups {
hash?: string;
assembly?: ResourceList;
lazyAssembly?: ResourceList;
pdb?: ResourceList;
jsModuleWorker?: ResourceList;
jsModuleNative: ResourceList;
jsModuleRuntime: ResourceList;
jsSymbols?: ResourceList;
wasmNative: ResourceList;
icu?: ResourceList;
satelliteResources?: {
readonly hash?: string;
readonly assembly?: ResourceList;
readonly lazyAssembly?: ResourceList;
readonly pdb?: ResourceList;
readonly runtime?: ResourceList;
readonly satelliteResources?: {
[cultureName: string]: ResourceList;
};
modulesAfterConfigLoaded?: ResourceList;
modulesAfterRuntimeReady?: ResourceList;
extensions?: ResourceExtensions;
vfs?: {
readonly libraryInitializers?: ResourceList;
readonly libraryStartupModules?: {
readonly onRuntimeConfigLoaded?: ResourceList;
readonly onRuntimeReady?: ResourceList;
};
readonly extensions?: ResourceExtensions;
readonly vfs?: {
[virtualPath: string]: ResourceList;
};
}
/**
* A "key" is name of the file, a "value" is optional hash for integrity check.
*/
type ResourceList = {
[name: string]: string | null | "";
[name: string]: string;
};
/**
* Overrides the built-in boot resource loading mechanism so that boot resources can be fetched
Expand All@@ -209,12 +208,12 @@ type ResourceList = {
* @param integrity The integrity string representing the expected content in the response.
* @returns A URI string or a Response promise to override the loading process, or null/undefined to allow the default loading behavior.
*/
type LoadBootResourceCallback = (type: AssetBehaviors | "manifest", name: string, defaultUri: string, integrity: string) => string | Promise<Response> | null | undefined;
type LoadBootResourceCallback = (type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string) => string | Promise<Response> | null | undefined;
interface ResourceRequest {
name: string;
behavior: AssetBehaviors;
behavior: AssetBehaviours;
resolvedUrl?: string;
hash?: string | null | "";
hash?: string;
}
interface LoadingResource {
name: string;
Expand DownExpand Up@@ -249,24 +248,7 @@ interface AssetEntry extends ResourceRequest {
*/
pendingDownload?: LoadingResource;
}
type SingleAssetBehaviors =
/**
* The binary of the dotnet runtime.
*/
"dotnetwasm"
/**
* The javascript module for threads.
*/
| "js-module-threads"
/**
* The javascript module for threads.
*/
| "js-module-runtime"
/**
* The javascript module for threads.
*/
| "js-module-native";
type AssetBehaviors = SingleAssetBehaviors |
type AssetBehaviours =
/**
* Load asset as a managed resource assembly.
*/
Expand All@@ -291,6 +273,26 @@ type AssetBehaviors = SingleAssetBehaviors |
* Load asset into the virtual filesystem (for fopen, File.Open, etc).
*/
| "vfs"
/**
* The binary of the dotnet runtime.
*/
| "dotnetwasm"
/**
* The javascript module for threads.
*/
| "js-module-threads"
/**
* The javascript module for threads.
*/
| "js-module-runtime"
/**
* The javascript module for threads.
*/
| "js-module-dotnet"
/**
* The javascript module for threads.
*/
| "js-module-native"
/**
* The javascript module that came from nuget package .
*/
Expand DownExpand Up@@ -328,8 +330,10 @@ type DotnetModuleConfig = {
onConfigLoaded?: (config: MonoConfig) => void | Promise<void>;
onDotnetReady?: () => void | Promise<void>;
onDownloadResourceProgress?: (resourcesLoaded: number, totalResources: number) => void;
getApplicationEnvironment?: (bootConfigResponse: Response) => string | null;
imports?: any;
exports?: string[];
downloadResource?: (request: ResourceRequest) => LoadingResource | undefined;
} & Partial<EmscriptenModule>;
type APIType = {
runMain: (mainAssemblyName: string, args: string[]) => Promise<number>;
Expand DownExpand Up@@ -396,6 +400,7 @@ type ModuleAPI = {
exit: (code: number, reason?: any) => void;
};
type CreateDotnetRuntimeType = (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)) => Promise<RuntimeAPI>;
type WebAssemblyBootResourceType = "assembly" | "pdb" | "dotnetjs" | "dotnetwasm" | "globalization" | "manifest" | "configuration";

interface IDisposable {
dispose(): void;
Expand Down
34 changes: 12 additions & 22 deletions src/mono/wasm/runtime/lazyLoading.ts
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,40 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import { loaderHelpers, runtimeHelpers } from "./globals";
import { AssetEntry } from "./types";
import { INTERNAL, loaderHelpers, runtimeHelpers } from "./globals";
import type { WebAssemblyResourceLoader } from "./loader/blazor/WebAssemblyResourceLoader";

export async function loadLazyAssembly(assemblyNameToLoad: string): Promise<boolean> {
const resources = loaderHelpers.config.resources!;
const resourceLoader: WebAssemblyResourceLoader = INTERNAL.resourceLoader;
const resources = resourceLoader.bootConfig.resources;
const lazyAssemblies = resources.lazyAssembly;
if (!lazyAssemblies) {
throw new Error("No assemblies have been marked as lazy-loadable. Use the 'BlazorWebAssemblyLazyLoad' item group in your project file to enable lazy loading an assembly.");
}

if (!lazyAssemblies[assemblyNameToLoad]) {
const assemblyMarkedAsLazy = Object.prototype.hasOwnProperty.call(lazyAssemblies, assemblyNameToLoad);
if (!assemblyMarkedAsLazy) {
throw new Error(`${assemblyNameToLoad} must be marked with 'BlazorWebAssemblyLazyLoad' item group in your project file to allow lazy-loading.`);
}

const dllAsset: AssetEntry = {
name: assemblyNameToLoad,
hash: lazyAssemblies[assemblyNameToLoad],
behavior: "assembly",
};

if (loaderHelpers.loadedAssemblies.some(f => f.includes(assemblyNameToLoad))) {
return false;
}

const pdbNameToLoad = changeExtension(dllAsset.name, ".pdb");
const shouldLoadPdb = loaderHelpers.hasDebuggingEnabled(loaderHelpers.config) && Object.prototype.hasOwnProperty.call(lazyAssemblies, pdbNameToLoad);
const dllNameToLoad = assemblyNameToLoad;
const pdbNameToLoad = changeExtension(assemblyNameToLoad, ".pdb");
const shouldLoadPdb = loaderHelpers.hasDebuggingEnabled(resourceLoader.bootConfig) && resources.pdb && Object.prototype.hasOwnProperty.call(lazyAssemblies, pdbNameToLoad);

const dllBytesPromise = loaderHelpers.retrieve_asset_download(dllAsset);
const dllBytesPromise = resourceLoader.loadResource(dllNameToLoad, loaderHelpers.locateFile(dllNameToLoad), lazyAssemblies[dllNameToLoad], "assembly").response.then(response => response.arrayBuffer());

let dll = null;
let pdb = null;
if (shouldLoadPdb) {
const pdbBytesPromise = lazyAssemblies[pdbNameToLoad]
? loaderHelpers.retrieve_asset_download({
name: pdbNameToLoad,
hash: lazyAssemblies[pdbNameToLoad],
behavior: "pdb"
})
: Promise.resolve(null);

const pdbBytesPromise = await resourceLoader.loadResource(pdbNameToLoad, loaderHelpers.locateFile(pdbNameToLoad), lazyAssemblies[pdbNameToLoad], "pdb").response.then(response => response.arrayBuffer());
const [dllBytes, pdbBytes] = await Promise.all([dllBytesPromise, pdbBytesPromise]);

dll = new Uint8Array(dllBytes);
pdb = pdbBytes ? new Uint8Array(pdbBytes) : null;
pdb = new Uint8Array(pdbBytes);
} else {
const dllBytes = await dllBytesPromise;
dll = new Uint8Array(dllBytes);
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Revert "[browser] Clean-up typescript code imported from Blazor (#89435)" by radical · Pull Request #89828 · dotnet/runtime · GitHub
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -372,8 +372,8 @@ Copyright (c) .NET Foundation. All rights reserved.
RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)"
Extensions="@(WasmBootConfigExtension)"
TargetFrameworkVersion="$(TargetFrameworkVersion)"
ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)"
ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" />
LibraryInitializerOnRuntimeConfigLoaded="@(WasmLibraryInitializerOnRuntimeConfigLoaded)"
LibraryInitializerOnRuntimeReady="@(WasmLibraryInitializerOnRuntimeReady)" />

<ItemGroup>
<FileWrites Include="$(_WasmBuildBootJsonPath)" />
Expand DownExpand Up@@ -563,8 +563,8 @@ Copyright (c) .NET Foundation. All rights reserved.
RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)"
Extensions="@(WasmBootConfigExtension)"
TargetFrameworkVersion="$(TargetFrameworkVersion)"
ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)"
ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" />
LibraryInitializerOnRuntimeConfigLoaded="@(WasmLibraryInitializerOnRuntimeConfigLoaded)"
LibraryInitializerOnRuntimeReady="@(WasmLibraryInitializerOnRuntimeReady)" />

<ItemGroup>
<FileWrites Include="$(IntermediateOutputPath)blazor.publish.boot.json" />
Expand Down
10 changes: 2 additions & 8 deletions src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -390,21 +390,15 @@ public void AssertBootJson(AssertBundleOptionsBase options)
Assert.True(File.Exists(bootJsonPath), $"Expected to find {bootJsonPath}");

BootJsonData bootJson = ParseBootData(bootJsonPath);
var bootJsonEntries = bootJson.resources.jsModuleNative.Keys
.Union(bootJson.resources.jsModuleRuntime.Keys)
.Union(bootJson.resources.jsModuleWorker?.Keys ?? Enumerable.Empty<string>())
.Union(bootJson.resources.jsSymbols?.Keys ?? Enumerable.Empty<string>())
.Union(bootJson.resources.wasmNative.Keys)
.ToArray();
var bootJsonEntries = bootJson.resources.runtime.Keys.Where(k => k.StartsWith("dotnet.", StringComparison.Ordinal)).ToArray();

var expectedEntries = new SortedDictionary<string, Action<string>>();
IReadOnlySet<string> expected = GetDotNetFilesExpectedSet(options);

var knownSet = GetAllKnownDotnetFilesToFingerprintMap(options);
foreach (string expectedFilename in expected)
{
// FIXME: Find a systematic solution for skipping dotnet.js from boot json check
if (expectedFilename == "dotnet.js" || Path.GetExtension(expectedFilename) == ".map")
if (Path.GetExtension(expectedFilename) == ".map")
continue;

bool expectFingerprint = knownSet[expectedFilename];
Expand Down
101 changes: 53 additions & 48 deletions src/mono/wasm/runtime/dotnet.d.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -95,6 +95,14 @@ interface DotnetHostBuilder {
run(): Promise<number>;
}
type MonoConfig = {
/**
* The subfolder containing managed assemblies and pdbs. This is relative to dotnet.js script.
*/
assemblyRootFolder?: string;
/**
* A list of assets to load along with the runtime.
*/
assets?: AssetEntry[];
/**
* Additional search locations for assets.
*/
Expand DownExpand Up@@ -125,10 +133,6 @@ type MonoConfig = {
* debugLevel < 0 enables debugging and disables debug logging.
*/
debugLevel?: number;
/**
* Gets a value that determines whether to enable caching of the 'resources' inside a CacheStorage instance within the browser.
*/
cacheBootResources?: boolean;
/**
* Enables diagnostic log messages during startup
*/
Expand All@@ -147,6 +151,10 @@ type MonoConfig = {
* If true, the snapshot of runtime's memory will be stored in the browser and used for faster startup next time. Default is false.
*/
startupMemoryCache?: boolean;
/**
* hash of assets
*/
assetsHash?: string;
/**
* application environment
*/
Expand All@@ -159,10 +167,6 @@ type MonoConfig = {
* definition of assets to load along with the runtime.
*/
resources?: ResourceGroups;
/**
* appsettings files to load to VFS
*/
appsettings?: string[];
/**
* config extensions declared in MSBuild items @(WasmBootConfigExtension)
*/
Expand All@@ -174,31 +178,26 @@ type ResourceExtensions = {
[extensionName: string]: ResourceList;
};
interface ResourceGroups {
hash?: string;
assembly?: ResourceList;
lazyAssembly?: ResourceList;
pdb?: ResourceList;
jsModuleWorker?: ResourceList;
jsModuleNative: ResourceList;
jsModuleRuntime: ResourceList;
jsSymbols?: ResourceList;
wasmNative: ResourceList;
icu?: ResourceList;
satelliteResources?: {
readonly hash?: string;
readonly assembly?: ResourceList;
readonly lazyAssembly?: ResourceList;
readonly pdb?: ResourceList;
readonly runtime?: ResourceList;
readonly satelliteResources?: {
[cultureName: string]: ResourceList;
};
modulesAfterConfigLoaded?: ResourceList;
modulesAfterRuntimeReady?: ResourceList;
extensions?: ResourceExtensions;
vfs?: {
readonly libraryInitializers?: ResourceList;
readonly libraryStartupModules?: {
readonly onRuntimeConfigLoaded?: ResourceList;
readonly onRuntimeReady?: ResourceList;
};
readonly extensions?: ResourceExtensions;
readonly vfs?: {
[virtualPath: string]: ResourceList;
};
}
/**
* A "key" is name of the file, a "value" is optional hash for integrity check.
*/
type ResourceList = {
[name: string]: string | null | "";
[name: string]: string;
};
/**
* Overrides the built-in boot resource loading mechanism so that boot resources can be fetched
Expand All@@ -209,12 +208,12 @@ type ResourceList = {
* @param integrity The integrity string representing the expected content in the response.
* @returns A URI string or a Response promise to override the loading process, or null/undefined to allow the default loading behavior.
*/
type LoadBootResourceCallback = (type: AssetBehaviors | "manifest", name: string, defaultUri: string, integrity: string) => string | Promise<Response> | null | undefined;
type LoadBootResourceCallback = (type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string) => string | Promise<Response> | null | undefined;
interface ResourceRequest {
name: string;
behavior: AssetBehaviors;
behavior: AssetBehaviours;
resolvedUrl?: string;
hash?: string | null | "";
hash?: string;
}
interface LoadingResource {
name: string;
Expand DownExpand Up@@ -249,24 +248,7 @@ interface AssetEntry extends ResourceRequest {
*/
pendingDownload?: LoadingResource;
}
type SingleAssetBehaviors =
/**
* The binary of the dotnet runtime.
*/
"dotnetwasm"
/**
* The javascript module for threads.
*/
| "js-module-threads"
/**
* The javascript module for threads.
*/
| "js-module-runtime"
/**
* The javascript module for threads.
*/
| "js-module-native";
type AssetBehaviors = SingleAssetBehaviors |
type AssetBehaviours =
/**
* Load asset as a managed resource assembly.
*/
Expand All@@ -291,6 +273,26 @@ type AssetBehaviors = SingleAssetBehaviors |
* Load asset into the virtual filesystem (for fopen, File.Open, etc).
*/
| "vfs"
/**
* The binary of the dotnet runtime.
*/
| "dotnetwasm"
/**
* The javascript module for threads.
*/
| "js-module-threads"
/**
* The javascript module for threads.
*/
| "js-module-runtime"
/**
* The javascript module for threads.
*/
| "js-module-dotnet"
/**
* The javascript module for threads.
*/
| "js-module-native"
/**
* The javascript module that came from nuget package .
*/
Expand DownExpand Up@@ -328,8 +330,10 @@ type DotnetModuleConfig = {
onConfigLoaded?: (config: MonoConfig) => void | Promise<void>;
onDotnetReady?: () => void | Promise<void>;
onDownloadResourceProgress?: (resourcesLoaded: number, totalResources: number) => void;
getApplicationEnvironment?: (bootConfigResponse: Response) => string | null;
imports?: any;
exports?: string[];
downloadResource?: (request: ResourceRequest) => LoadingResource | undefined;
} & Partial<EmscriptenModule>;
type APIType = {
runMain: (mainAssemblyName: string, args: string[]) => Promise<number>;
Expand DownExpand Up@@ -396,6 +400,7 @@ type ModuleAPI = {
exit: (code: number, reason?: any) => void;
};
type CreateDotnetRuntimeType = (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)) => Promise<RuntimeAPI>;
type WebAssemblyBootResourceType = "assembly" | "pdb" | "dotnetjs" | "dotnetwasm" | "globalization" | "manifest" | "configuration";

interface IDisposable {
dispose(): void;
Expand Down
34 changes: 12 additions & 22 deletions src/mono/wasm/runtime/lazyLoading.ts
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,40 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import { loaderHelpers, runtimeHelpers } from "./globals";
import { AssetEntry } from "./types";
import { INTERNAL, loaderHelpers, runtimeHelpers } from "./globals";
import type { WebAssemblyResourceLoader } from "./loader/blazor/WebAssemblyResourceLoader";

export async function loadLazyAssembly(assemblyNameToLoad: string): Promise<boolean> {
const resources = loaderHelpers.config.resources!;
const resourceLoader: WebAssemblyResourceLoader = INTERNAL.resourceLoader;
const resources = resourceLoader.bootConfig.resources;
const lazyAssemblies = resources.lazyAssembly;
if (!lazyAssemblies) {
throw new Error("No assemblies have been marked as lazy-loadable. Use the 'BlazorWebAssemblyLazyLoad' item group in your project file to enable lazy loading an assembly.");
}

if (!lazyAssemblies[assemblyNameToLoad]) {
const assemblyMarkedAsLazy = Object.prototype.hasOwnProperty.call(lazyAssemblies, assemblyNameToLoad);
if (!assemblyMarkedAsLazy) {
throw new Error(`${assemblyNameToLoad} must be marked with 'BlazorWebAssemblyLazyLoad' item group in your project file to allow lazy-loading.`);
}

const dllAsset: AssetEntry = {
name: assemblyNameToLoad,
hash: lazyAssemblies[assemblyNameToLoad],
behavior: "assembly",
};

if (loaderHelpers.loadedAssemblies.some(f => f.includes(assemblyNameToLoad))) {
return false;
}

const pdbNameToLoad = changeExtension(dllAsset.name, ".pdb");
const shouldLoadPdb = loaderHelpers.hasDebuggingEnabled(loaderHelpers.config) && Object.prototype.hasOwnProperty.call(lazyAssemblies, pdbNameToLoad);
const dllNameToLoad = assemblyNameToLoad;
const pdbNameToLoad = changeExtension(assemblyNameToLoad, ".pdb");
const shouldLoadPdb = loaderHelpers.hasDebuggingEnabled(resourceLoader.bootConfig) && resources.pdb && Object.prototype.hasOwnProperty.call(lazyAssemblies, pdbNameToLoad);

const dllBytesPromise = loaderHelpers.retrieve_asset_download(dllAsset);
const dllBytesPromise = resourceLoader.loadResource(dllNameToLoad, loaderHelpers.locateFile(dllNameToLoad), lazyAssemblies[dllNameToLoad], "assembly").response.then(response => response.arrayBuffer());

let dll = null;
let pdb = null;
if (shouldLoadPdb) {
const pdbBytesPromise = lazyAssemblies[pdbNameToLoad]
? loaderHelpers.retrieve_asset_download({
name: pdbNameToLoad,
hash: lazyAssemblies[pdbNameToLoad],
behavior: "pdb"
})
: Promise.resolve(null);

const pdbBytesPromise = await resourceLoader.loadResource(pdbNameToLoad, loaderHelpers.locateFile(pdbNameToLoad), lazyAssemblies[pdbNameToLoad], "pdb").response.then(response => response.arrayBuffer());
const [dllBytes, pdbBytes] = await Promise.all([dllBytesPromise, pdbBytesPromise]);

dll = new Uint8Array(dllBytes);
pdb = pdbBytes ? new Uint8Array(pdbBytes) : null;
pdb = new Uint8Array(pdbBytes);
} else {
const dllBytes = await dllBytesPromise;
dll = new Uint8Array(dllBytes);
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Revert "[browser] Clean-up typescript code imported from Blazor (#89435)" by radical · Pull Request #89828 · dotnet/runtime · GitHub
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -372,8 +372,8 @@ Copyright (c) .NET Foundation. All rights reserved.
RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)"
Extensions="@(WasmBootConfigExtension)"
TargetFrameworkVersion="$(TargetFrameworkVersion)"
ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)"
ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" />
LibraryInitializerOnRuntimeConfigLoaded="@(WasmLibraryInitializerOnRuntimeConfigLoaded)"
LibraryInitializerOnRuntimeReady="@(WasmLibraryInitializerOnRuntimeReady)" />

<ItemGroup>
<FileWrites Include="$(_WasmBuildBootJsonPath)" />
Expand DownExpand Up@@ -563,8 +563,8 @@ Copyright (c) .NET Foundation. All rights reserved.
RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)"
Extensions="@(WasmBootConfigExtension)"
TargetFrameworkVersion="$(TargetFrameworkVersion)"
ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)"
ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" />
LibraryInitializerOnRuntimeConfigLoaded="@(WasmLibraryInitializerOnRuntimeConfigLoaded)"
LibraryInitializerOnRuntimeReady="@(WasmLibraryInitializerOnRuntimeReady)" />

<ItemGroup>
<FileWrites Include="$(IntermediateOutputPath)blazor.publish.boot.json" />
Expand Down
10 changes: 2 additions & 8 deletions src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -390,21 +390,15 @@ public void AssertBootJson(AssertBundleOptionsBase options)
Assert.True(File.Exists(bootJsonPath), $"Expected to find {bootJsonPath}");

BootJsonData bootJson = ParseBootData(bootJsonPath);
var bootJsonEntries = bootJson.resources.jsModuleNative.Keys
.Union(bootJson.resources.jsModuleRuntime.Keys)
.Union(bootJson.resources.jsModuleWorker?.Keys ?? Enumerable.Empty<string>())
.Union(bootJson.resources.jsSymbols?.Keys ?? Enumerable.Empty<string>())
.Union(bootJson.resources.wasmNative.Keys)
.ToArray();
var bootJsonEntries = bootJson.resources.runtime.Keys.Where(k => k.StartsWith("dotnet.", StringComparison.Ordinal)).ToArray();

var expectedEntries = new SortedDictionary<string, Action<string>>();
IReadOnlySet<string> expected = GetDotNetFilesExpectedSet(options);

var knownSet = GetAllKnownDotnetFilesToFingerprintMap(options);
foreach (string expectedFilename in expected)
{
// FIXME: Find a systematic solution for skipping dotnet.js from boot json check
if (expectedFilename == "dotnet.js" || Path.GetExtension(expectedFilename) == ".map")
if (Path.GetExtension(expectedFilename) == ".map")
continue;

bool expectFingerprint = knownSet[expectedFilename];
Expand Down
101 changes: 53 additions & 48 deletions src/mono/wasm/runtime/dotnet.d.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -95,6 +95,14 @@ interface DotnetHostBuilder {
run(): Promise<number>;
}
type MonoConfig = {
/**
* The subfolder containing managed assemblies and pdbs. This is relative to dotnet.js script.
*/
assemblyRootFolder?: string;
/**
* A list of assets to load along with the runtime.
*/
assets?: AssetEntry[];
/**
* Additional search locations for assets.
*/
Expand DownExpand Up@@ -125,10 +133,6 @@ type MonoConfig = {
* debugLevel < 0 enables debugging and disables debug logging.
*/
debugLevel?: number;
/**
* Gets a value that determines whether to enable caching of the 'resources' inside a CacheStorage instance within the browser.
*/
cacheBootResources?: boolean;
/**
* Enables diagnostic log messages during startup
*/
Expand All@@ -147,6 +151,10 @@ type MonoConfig = {
* If true, the snapshot of runtime's memory will be stored in the browser and used for faster startup next time. Default is false.
*/
startupMemoryCache?: boolean;
/**
* hash of assets
*/
assetsHash?: string;
/**
* application environment
*/
Expand All@@ -159,10 +167,6 @@ type MonoConfig = {
* definition of assets to load along with the runtime.
*/
resources?: ResourceGroups;
/**
* appsettings files to load to VFS
*/
appsettings?: string[];
/**
* config extensions declared in MSBuild items @(WasmBootConfigExtension)
*/
Expand All@@ -174,31 +178,26 @@ type ResourceExtensions = {
[extensionName: string]: ResourceList;
};
interface ResourceGroups {
hash?: string;
assembly?: ResourceList;
lazyAssembly?: ResourceList;
pdb?: ResourceList;
jsModuleWorker?: ResourceList;
jsModuleNative: ResourceList;
jsModuleRuntime: ResourceList;
jsSymbols?: ResourceList;
wasmNative: ResourceList;
icu?: ResourceList;
satelliteResources?: {
readonly hash?: string;
readonly assembly?: ResourceList;
readonly lazyAssembly?: ResourceList;
readonly pdb?: ResourceList;
readonly runtime?: ResourceList;
readonly satelliteResources?: {
[cultureName: string]: ResourceList;
};
modulesAfterConfigLoaded?: ResourceList;
modulesAfterRuntimeReady?: ResourceList;
extensions?: ResourceExtensions;
vfs?: {
readonly libraryInitializers?: ResourceList;
readonly libraryStartupModules?: {
readonly onRuntimeConfigLoaded?: ResourceList;
readonly onRuntimeReady?: ResourceList;
};
readonly extensions?: ResourceExtensions;
readonly vfs?: {
[virtualPath: string]: ResourceList;
};
}
/**
* A "key" is name of the file, a "value" is optional hash for integrity check.
*/
type ResourceList = {
[name: string]: string | null | "";
[name: string]: string;
};
/**
* Overrides the built-in boot resource loading mechanism so that boot resources can be fetched
Expand All@@ -209,12 +208,12 @@ type ResourceList = {
* @param integrity The integrity string representing the expected content in the response.
* @returns A URI string or a Response promise to override the loading process, or null/undefined to allow the default loading behavior.
*/
type LoadBootResourceCallback = (type: AssetBehaviors | "manifest", name: string, defaultUri: string, integrity: string) => string | Promise<Response> | null | undefined;
type LoadBootResourceCallback = (type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string) => string | Promise<Response> | null | undefined;
interface ResourceRequest {
name: string;
behavior: AssetBehaviors;
behavior: AssetBehaviours;
resolvedUrl?: string;
hash?: string | null | "";
hash?: string;
}
interface LoadingResource {
name: string;
Expand DownExpand Up@@ -249,24 +248,7 @@ interface AssetEntry extends ResourceRequest {
*/
pendingDownload?: LoadingResource;
}
type SingleAssetBehaviors =
/**
* The binary of the dotnet runtime.
*/
"dotnetwasm"
/**
* The javascript module for threads.
*/
| "js-module-threads"
/**
* The javascript module for threads.
*/
| "js-module-runtime"
/**
* The javascript module for threads.
*/
| "js-module-native";
type AssetBehaviors = SingleAssetBehaviors |
type AssetBehaviours =
/**
* Load asset as a managed resource assembly.
*/
Expand All@@ -291,6 +273,26 @@ type AssetBehaviors = SingleAssetBehaviors |
* Load asset into the virtual filesystem (for fopen, File.Open, etc).
*/
| "vfs"
/**
* The binary of the dotnet runtime.
*/
| "dotnetwasm"
/**
* The javascript module for threads.
*/
| "js-module-threads"
/**
* The javascript module for threads.
*/
| "js-module-runtime"
/**
* The javascript module for threads.
*/
| "js-module-dotnet"
/**
* The javascript module for threads.
*/
| "js-module-native"
/**
* The javascript module that came from nuget package .
*/
Expand DownExpand Up@@ -328,8 +330,10 @@ type DotnetModuleConfig = {
onConfigLoaded?: (config: MonoConfig) => void | Promise<void>;
onDotnetReady?: () => void | Promise<void>;
onDownloadResourceProgress?: (resourcesLoaded: number, totalResources: number) => void;
getApplicationEnvironment?: (bootConfigResponse: Response) => string | null;
imports?: any;
exports?: string[];
downloadResource?: (request: ResourceRequest) => LoadingResource | undefined;
} & Partial<EmscriptenModule>;
type APIType = {
runMain: (mainAssemblyName: string, args: string[]) => Promise<number>;
Expand DownExpand Up@@ -396,6 +400,7 @@ type ModuleAPI = {
exit: (code: number, reason?: any) => void;
};
type CreateDotnetRuntimeType = (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)) => Promise<RuntimeAPI>;
type WebAssemblyBootResourceType = "assembly" | "pdb" | "dotnetjs" | "dotnetwasm" | "globalization" | "manifest" | "configuration";

interface IDisposable {
dispose(): void;
Expand Down
34 changes: 12 additions & 22 deletions src/mono/wasm/runtime/lazyLoading.ts
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,40 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import { loaderHelpers, runtimeHelpers } from "./globals";
import { AssetEntry } from "./types";
import { INTERNAL, loaderHelpers, runtimeHelpers } from "./globals";
import type { WebAssemblyResourceLoader } from "./loader/blazor/WebAssemblyResourceLoader";

export async function loadLazyAssembly(assemblyNameToLoad: string): Promise<boolean> {
const resources = loaderHelpers.config.resources!;
const resourceLoader: WebAssemblyResourceLoader = INTERNAL.resourceLoader;
const resources = resourceLoader.bootConfig.resources;
const lazyAssemblies = resources.lazyAssembly;
if (!lazyAssemblies) {
throw new Error("No assemblies have been marked as lazy-loadable. Use the 'BlazorWebAssemblyLazyLoad' item group in your project file to enable lazy loading an assembly.");
}

if (!lazyAssemblies[assemblyNameToLoad]) {
const assemblyMarkedAsLazy = Object.prototype.hasOwnProperty.call(lazyAssemblies, assemblyNameToLoad);
if (!assemblyMarkedAsLazy) {
throw new Error(`${assemblyNameToLoad} must be marked with 'BlazorWebAssemblyLazyLoad' item group in your project file to allow lazy-loading.`);
}

const dllAsset: AssetEntry = {
name: assemblyNameToLoad,
hash: lazyAssemblies[assemblyNameToLoad],
behavior: "assembly",
};

if (loaderHelpers.loadedAssemblies.some(f => f.includes(assemblyNameToLoad))) {
return false;
}

const pdbNameToLoad = changeExtension(dllAsset.name, ".pdb");
const shouldLoadPdb = loaderHelpers.hasDebuggingEnabled(loaderHelpers.config) && Object.prototype.hasOwnProperty.call(lazyAssemblies, pdbNameToLoad);
const dllNameToLoad = assemblyNameToLoad;
const pdbNameToLoad = changeExtension(assemblyNameToLoad, ".pdb");
const shouldLoadPdb = loaderHelpers.hasDebuggingEnabled(resourceLoader.bootConfig) && resources.pdb && Object.prototype.hasOwnProperty.call(lazyAssemblies, pdbNameToLoad);

const dllBytesPromise = loaderHelpers.retrieve_asset_download(dllAsset);
const dllBytesPromise = resourceLoader.loadResource(dllNameToLoad, loaderHelpers.locateFile(dllNameToLoad), lazyAssemblies[dllNameToLoad], "assembly").response.then(response => response.arrayBuffer());

let dll = null;
let pdb = null;
if (shouldLoadPdb) {
const pdbBytesPromise = lazyAssemblies[pdbNameToLoad]
? loaderHelpers.retrieve_asset_download({
name: pdbNameToLoad,
hash: lazyAssemblies[pdbNameToLoad],
behavior: "pdb"
})
: Promise.resolve(null);

const pdbBytesPromise = await resourceLoader.loadResource(pdbNameToLoad, loaderHelpers.locateFile(pdbNameToLoad), lazyAssemblies[pdbNameToLoad], "pdb").response.then(response => response.arrayBuffer());
const [dllBytes, pdbBytes] = await Promise.all([dllBytesPromise, pdbBytesPromise]);

dll = new Uint8Array(dllBytes);
pdb = pdbBytes ? new Uint8Array(pdbBytes) : null;
pdb = new Uint8Array(pdbBytes);
} else {
const dllBytes = await dllBytesPromise;
dll = new Uint8Array(dllBytes);
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Revert "[browser] Clean-up typescript code imported from Blazor (#89435)" by radical · Pull Request #89828 · dotnet/runtime · GitHub
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -372,8 +372,8 @@ Copyright (c) .NET Foundation. All rights reserved.
RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)"
Extensions="@(WasmBootConfigExtension)"
TargetFrameworkVersion="$(TargetFrameworkVersion)"
ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)"
ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" />
LibraryInitializerOnRuntimeConfigLoaded="@(WasmLibraryInitializerOnRuntimeConfigLoaded)"
LibraryInitializerOnRuntimeReady="@(WasmLibraryInitializerOnRuntimeReady)" />

<ItemGroup>
<FileWrites Include="$(_WasmBuildBootJsonPath)" />
Expand DownExpand Up@@ -563,8 +563,8 @@ Copyright (c) .NET Foundation. All rights reserved.
RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)"
Extensions="@(WasmBootConfigExtension)"
TargetFrameworkVersion="$(TargetFrameworkVersion)"
ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)"
ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" />
LibraryInitializerOnRuntimeConfigLoaded="@(WasmLibraryInitializerOnRuntimeConfigLoaded)"
LibraryInitializerOnRuntimeReady="@(WasmLibraryInitializerOnRuntimeReady)" />

<ItemGroup>
<FileWrites Include="$(IntermediateOutputPath)blazor.publish.boot.json" />
Expand Down
10 changes: 2 additions & 8 deletions src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -390,21 +390,15 @@ public void AssertBootJson(AssertBundleOptionsBase options)
Assert.True(File.Exists(bootJsonPath), $"Expected to find {bootJsonPath}");

BootJsonData bootJson = ParseBootData(bootJsonPath);
var bootJsonEntries = bootJson.resources.jsModuleNative.Keys
.Union(bootJson.resources.jsModuleRuntime.Keys)
.Union(bootJson.resources.jsModuleWorker?.Keys ?? Enumerable.Empty<string>())
.Union(bootJson.resources.jsSymbols?.Keys ?? Enumerable.Empty<string>())
.Union(bootJson.resources.wasmNative.Keys)
.ToArray();
var bootJsonEntries = bootJson.resources.runtime.Keys.Where(k => k.StartsWith("dotnet.", StringComparison.Ordinal)).ToArray();

var expectedEntries = new SortedDictionary<string, Action<string>>();
IReadOnlySet<string> expected = GetDotNetFilesExpectedSet(options);

var knownSet = GetAllKnownDotnetFilesToFingerprintMap(options);
foreach (string expectedFilename in expected)
{
// FIXME: Find a systematic solution for skipping dotnet.js from boot json check
if (expectedFilename == "dotnet.js" || Path.GetExtension(expectedFilename) == ".map")
if (Path.GetExtension(expectedFilename) == ".map")
continue;

bool expectFingerprint = knownSet[expectedFilename];
Expand Down
101 changes: 53 additions & 48 deletions src/mono/wasm/runtime/dotnet.d.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -95,6 +95,14 @@ interface DotnetHostBuilder {
run(): Promise<number>;
}
type MonoConfig = {
/**
* The subfolder containing managed assemblies and pdbs. This is relative to dotnet.js script.
*/
assemblyRootFolder?: string;
/**
* A list of assets to load along with the runtime.
*/
assets?: AssetEntry[];
/**
* Additional search locations for assets.
*/
Expand DownExpand Up@@ -125,10 +133,6 @@ type MonoConfig = {
* debugLevel < 0 enables debugging and disables debug logging.
*/
debugLevel?: number;
/**
* Gets a value that determines whether to enable caching of the 'resources' inside a CacheStorage instance within the browser.
*/
cacheBootResources?: boolean;
/**
* Enables diagnostic log messages during startup
*/
Expand All@@ -147,6 +151,10 @@ type MonoConfig = {
* If true, the snapshot of runtime's memory will be stored in the browser and used for faster startup next time. Default is false.
*/
startupMemoryCache?: boolean;
/**
* hash of assets
*/
assetsHash?: string;
/**
* application environment
*/
Expand All@@ -159,10 +167,6 @@ type MonoConfig = {
* definition of assets to load along with the runtime.
*/
resources?: ResourceGroups;
/**
* appsettings files to load to VFS
*/
appsettings?: string[];
/**
* config extensions declared in MSBuild items @(WasmBootConfigExtension)
*/
Expand All@@ -174,31 +178,26 @@ type ResourceExtensions = {
[extensionName: string]: ResourceList;
};
interface ResourceGroups {
hash?: string;
assembly?: ResourceList;
lazyAssembly?: ResourceList;
pdb?: ResourceList;
jsModuleWorker?: ResourceList;
jsModuleNative: ResourceList;
jsModuleRuntime: ResourceList;
jsSymbols?: ResourceList;
wasmNative: ResourceList;
icu?: ResourceList;
satelliteResources?: {
readonly hash?: string;
readonly assembly?: ResourceList;
readonly lazyAssembly?: ResourceList;
readonly pdb?: ResourceList;
readonly runtime?: ResourceList;
readonly satelliteResources?: {
[cultureName: string]: ResourceList;
};
modulesAfterConfigLoaded?: ResourceList;
modulesAfterRuntimeReady?: ResourceList;
extensions?: ResourceExtensions;
vfs?: {
readonly libraryInitializers?: ResourceList;
readonly libraryStartupModules?: {
readonly onRuntimeConfigLoaded?: ResourceList;
readonly onRuntimeReady?: ResourceList;
};
readonly extensions?: ResourceExtensions;
readonly vfs?: {
[virtualPath: string]: ResourceList;
};
}
/**
* A "key" is name of the file, a "value" is optional hash for integrity check.
*/
type ResourceList = {
[name: string]: string | null | "";
[name: string]: string;
};
/**
* Overrides the built-in boot resource loading mechanism so that boot resources can be fetched
Expand All@@ -209,12 +208,12 @@ type ResourceList = {
* @param integrity The integrity string representing the expected content in the response.
* @returns A URI string or a Response promise to override the loading process, or null/undefined to allow the default loading behavior.
*/
type LoadBootResourceCallback = (type: AssetBehaviors | "manifest", name: string, defaultUri: string, integrity: string) => string | Promise<Response> | null | undefined;
type LoadBootResourceCallback = (type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string) => string | Promise<Response> | null | undefined;
interface ResourceRequest {
name: string;
behavior: AssetBehaviors;
behavior: AssetBehaviours;
resolvedUrl?: string;
hash?: string | null | "";
hash?: string;
}
interface LoadingResource {
name: string;
Expand DownExpand Up@@ -249,24 +248,7 @@ interface AssetEntry extends ResourceRequest {
*/
pendingDownload?: LoadingResource;
}
type SingleAssetBehaviors =
/**
* The binary of the dotnet runtime.
*/
"dotnetwasm"
/**
* The javascript module for threads.
*/
| "js-module-threads"
/**
* The javascript module for threads.
*/
| "js-module-runtime"
/**
* The javascript module for threads.
*/
| "js-module-native";
type AssetBehaviors = SingleAssetBehaviors |
type AssetBehaviours =
/**
* Load asset as a managed resource assembly.
*/
Expand All@@ -291,6 +273,26 @@ type AssetBehaviors = SingleAssetBehaviors |
* Load asset into the virtual filesystem (for fopen, File.Open, etc).
*/
| "vfs"
/**
* The binary of the dotnet runtime.
*/
| "dotnetwasm"
/**
* The javascript module for threads.
*/
| "js-module-threads"
/**
* The javascript module for threads.
*/
| "js-module-runtime"
/**
* The javascript module for threads.
*/
| "js-module-dotnet"
/**
* The javascript module for threads.
*/
| "js-module-native"
/**
* The javascript module that came from nuget package .
*/
Expand DownExpand Up@@ -328,8 +330,10 @@ type DotnetModuleConfig = {
onConfigLoaded?: (config: MonoConfig) => void | Promise<void>;
onDotnetReady?: () => void | Promise<void>;
onDownloadResourceProgress?: (resourcesLoaded: number, totalResources: number) => void;
getApplicationEnvironment?: (bootConfigResponse: Response) => string | null;
imports?: any;
exports?: string[];
downloadResource?: (request: ResourceRequest) => LoadingResource | undefined;
} & Partial<EmscriptenModule>;
type APIType = {
runMain: (mainAssemblyName: string, args: string[]) => Promise<number>;
Expand DownExpand Up@@ -396,6 +400,7 @@ type ModuleAPI = {
exit: (code: number, reason?: any) => void;
};
type CreateDotnetRuntimeType = (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)) => Promise<RuntimeAPI>;
type WebAssemblyBootResourceType = "assembly" | "pdb" | "dotnetjs" | "dotnetwasm" | "globalization" | "manifest" | "configuration";

interface IDisposable {
dispose(): void;
Expand Down
34 changes: 12 additions & 22 deletions src/mono/wasm/runtime/lazyLoading.ts
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,40 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import { loaderHelpers, runtimeHelpers } from "./globals";
import { AssetEntry } from "./types";
import { INTERNAL, loaderHelpers, runtimeHelpers } from "./globals";
import type { WebAssemblyResourceLoader } from "./loader/blazor/WebAssemblyResourceLoader";

export async function loadLazyAssembly(assemblyNameToLoad: string): Promise<boolean> {
const resources = loaderHelpers.config.resources!;
const resourceLoader: WebAssemblyResourceLoader = INTERNAL.resourceLoader;
const resources = resourceLoader.bootConfig.resources;
const lazyAssemblies = resources.lazyAssembly;
if (!lazyAssemblies) {
throw new Error("No assemblies have been marked as lazy-loadable. Use the 'BlazorWebAssemblyLazyLoad' item group in your project file to enable lazy loading an assembly.");
}

if (!lazyAssemblies[assemblyNameToLoad]) {
const assemblyMarkedAsLazy = Object.prototype.hasOwnProperty.call(lazyAssemblies, assemblyNameToLoad);
if (!assemblyMarkedAsLazy) {
throw new Error(`${assemblyNameToLoad} must be marked with 'BlazorWebAssemblyLazyLoad' item group in your project file to allow lazy-loading.`);
}

const dllAsset: AssetEntry = {
name: assemblyNameToLoad,
hash: lazyAssemblies[assemblyNameToLoad],
behavior: "assembly",
};

if (loaderHelpers.loadedAssemblies.some(f => f.includes(assemblyNameToLoad))) {
return false;
}

const pdbNameToLoad = changeExtension(dllAsset.name, ".pdb");
const shouldLoadPdb = loaderHelpers.hasDebuggingEnabled(loaderHelpers.config) && Object.prototype.hasOwnProperty.call(lazyAssemblies, pdbNameToLoad);
const dllNameToLoad = assemblyNameToLoad;
const pdbNameToLoad = changeExtension(assemblyNameToLoad, ".pdb");
const shouldLoadPdb = loaderHelpers.hasDebuggingEnabled(resourceLoader.bootConfig) && resources.pdb && Object.prototype.hasOwnProperty.call(lazyAssemblies, pdbNameToLoad);

const dllBytesPromise = loaderHelpers.retrieve_asset_download(dllAsset);
const dllBytesPromise = resourceLoader.loadResource(dllNameToLoad, loaderHelpers.locateFile(dllNameToLoad), lazyAssemblies[dllNameToLoad], "assembly").response.then(response => response.arrayBuffer());

let dll = null;
let pdb = null;
if (shouldLoadPdb) {
const pdbBytesPromise = lazyAssemblies[pdbNameToLoad]
? loaderHelpers.retrieve_asset_download({
name: pdbNameToLoad,
hash: lazyAssemblies[pdbNameToLoad],
behavior: "pdb"
})
: Promise.resolve(null);

const pdbBytesPromise = await resourceLoader.loadResource(pdbNameToLoad, loaderHelpers.locateFile(pdbNameToLoad), lazyAssemblies[pdbNameToLoad], "pdb").response.then(response => response.arrayBuffer());
const [dllBytes, pdbBytes] = await Promise.all([dllBytesPromise, pdbBytesPromise]);

dll = new Uint8Array(dllBytes);
pdb = pdbBytes ? new Uint8Array(pdbBytes) : null;
pdb = new Uint8Array(pdbBytes);
} else {
const dllBytes = await dllBytesPromise;
dll = new Uint8Array(dllBytes);
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Revert "[browser] Clean-up typescript code imported from Blazor (#89435)" by radical · Pull Request #89828 · dotnet/runtime · GitHub
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -372,8 +372,8 @@ Copyright (c) .NET Foundation. All rights reserved.
RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)"
Extensions="@(WasmBootConfigExtension)"
TargetFrameworkVersion="$(TargetFrameworkVersion)"
ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)"
ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" />
LibraryInitializerOnRuntimeConfigLoaded="@(WasmLibraryInitializerOnRuntimeConfigLoaded)"
LibraryInitializerOnRuntimeReady="@(WasmLibraryInitializerOnRuntimeReady)" />

<ItemGroup>
<FileWrites Include="$(_WasmBuildBootJsonPath)" />
Expand DownExpand Up@@ -563,8 +563,8 @@ Copyright (c) .NET Foundation. All rights reserved.
RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)"
Extensions="@(WasmBootConfigExtension)"
TargetFrameworkVersion="$(TargetFrameworkVersion)"
ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)"
ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" />
LibraryInitializerOnRuntimeConfigLoaded="@(WasmLibraryInitializerOnRuntimeConfigLoaded)"
LibraryInitializerOnRuntimeReady="@(WasmLibraryInitializerOnRuntimeReady)" />

<ItemGroup>
<FileWrites Include="$(IntermediateOutputPath)blazor.publish.boot.json" />
Expand Down
10 changes: 2 additions & 8 deletions src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -390,21 +390,15 @@ public void AssertBootJson(AssertBundleOptionsBase options)
Assert.True(File.Exists(bootJsonPath), $"Expected to find {bootJsonPath}");

BootJsonData bootJson = ParseBootData(bootJsonPath);
var bootJsonEntries = bootJson.resources.jsModuleNative.Keys
.Union(bootJson.resources.jsModuleRuntime.Keys)
.Union(bootJson.resources.jsModuleWorker?.Keys ?? Enumerable.Empty<string>())
.Union(bootJson.resources.jsSymbols?.Keys ?? Enumerable.Empty<string>())
.Union(bootJson.resources.wasmNative.Keys)
.ToArray();
var bootJsonEntries = bootJson.resources.runtime.Keys.Where(k => k.StartsWith("dotnet.", StringComparison.Ordinal)).ToArray();

var expectedEntries = new SortedDictionary<string, Action<string>>();
IReadOnlySet<string> expected = GetDotNetFilesExpectedSet(options);

var knownSet = GetAllKnownDotnetFilesToFingerprintMap(options);
foreach (string expectedFilename in expected)
{
// FIXME: Find a systematic solution for skipping dotnet.js from boot json check
if (expectedFilename == "dotnet.js" || Path.GetExtension(expectedFilename) == ".map")
if (Path.GetExtension(expectedFilename) == ".map")
continue;

bool expectFingerprint = knownSet[expectedFilename];
Expand Down
101 changes: 53 additions & 48 deletions src/mono/wasm/runtime/dotnet.d.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -95,6 +95,14 @@ interface DotnetHostBuilder {
run(): Promise<number>;
}
type MonoConfig = {
/**
* The subfolder containing managed assemblies and pdbs. This is relative to dotnet.js script.
*/
assemblyRootFolder?: string;
/**
* A list of assets to load along with the runtime.
*/
assets?: AssetEntry[];
/**
* Additional search locations for assets.
*/
Expand DownExpand Up@@ -125,10 +133,6 @@ type MonoConfig = {
* debugLevel < 0 enables debugging and disables debug logging.
*/
debugLevel?: number;
/**
* Gets a value that determines whether to enable caching of the 'resources' inside a CacheStorage instance within the browser.
*/
cacheBootResources?: boolean;
/**
* Enables diagnostic log messages during startup
*/
Expand All@@ -147,6 +151,10 @@ type MonoConfig = {
* If true, the snapshot of runtime's memory will be stored in the browser and used for faster startup next time. Default is false.
*/
startupMemoryCache?: boolean;
/**
* hash of assets
*/
assetsHash?: string;
/**
* application environment
*/
Expand All@@ -159,10 +167,6 @@ type MonoConfig = {
* definition of assets to load along with the runtime.
*/
resources?: ResourceGroups;
/**
* appsettings files to load to VFS
*/
appsettings?: string[];
/**
* config extensions declared in MSBuild items @(WasmBootConfigExtension)
*/
Expand All@@ -174,31 +178,26 @@ type ResourceExtensions = {
[extensionName: string]: ResourceList;
};
interface ResourceGroups {
hash?: string;
assembly?: ResourceList;
lazyAssembly?: ResourceList;
pdb?: ResourceList;
jsModuleWorker?: ResourceList;
jsModuleNative: ResourceList;
jsModuleRuntime: ResourceList;
jsSymbols?: ResourceList;
wasmNative: ResourceList;
icu?: ResourceList;
satelliteResources?: {
readonly hash?: string;
readonly assembly?: ResourceList;
readonly lazyAssembly?: ResourceList;
readonly pdb?: ResourceList;
readonly runtime?: ResourceList;
readonly satelliteResources?: {
[cultureName: string]: ResourceList;
};
modulesAfterConfigLoaded?: ResourceList;
modulesAfterRuntimeReady?: ResourceList;
extensions?: ResourceExtensions;
vfs?: {
readonly libraryInitializers?: ResourceList;
readonly libraryStartupModules?: {
readonly onRuntimeConfigLoaded?: ResourceList;
readonly onRuntimeReady?: ResourceList;
};
readonly extensions?: ResourceExtensions;
readonly vfs?: {
[virtualPath: string]: ResourceList;
};
}
/**
* A "key" is name of the file, a "value" is optional hash for integrity check.
*/
type ResourceList = {
[name: string]: string | null | "";
[name: string]: string;
};
/**
* Overrides the built-in boot resource loading mechanism so that boot resources can be fetched
Expand All@@ -209,12 +208,12 @@ type ResourceList = {
* @param integrity The integrity string representing the expected content in the response.
* @returns A URI string or a Response promise to override the loading process, or null/undefined to allow the default loading behavior.
*/
type LoadBootResourceCallback = (type: AssetBehaviors | "manifest", name: string, defaultUri: string, integrity: string) => string | Promise<Response> | null | undefined;
type LoadBootResourceCallback = (type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string) => string | Promise<Response> | null | undefined;
interface ResourceRequest {
name: string;
behavior: AssetBehaviors;
behavior: AssetBehaviours;
resolvedUrl?: string;
hash?: string | null | "";
hash?: string;
}
interface LoadingResource {
name: string;
Expand DownExpand Up@@ -249,24 +248,7 @@ interface AssetEntry extends ResourceRequest {
*/
pendingDownload?: LoadingResource;
}
type SingleAssetBehaviors =
/**
* The binary of the dotnet runtime.
*/
"dotnetwasm"
/**
* The javascript module for threads.
*/
| "js-module-threads"
/**
* The javascript module for threads.
*/
| "js-module-runtime"
/**
* The javascript module for threads.
*/
| "js-module-native";
type AssetBehaviors = SingleAssetBehaviors |
type AssetBehaviours =
/**
* Load asset as a managed resource assembly.
*/
Expand All@@ -291,6 +273,26 @@ type AssetBehaviors = SingleAssetBehaviors |
* Load asset into the virtual filesystem (for fopen, File.Open, etc).
*/
| "vfs"
/**
* The binary of the dotnet runtime.
*/
| "dotnetwasm"
/**
* The javascript module for threads.
*/
| "js-module-threads"
/**
* The javascript module for threads.
*/
| "js-module-runtime"
/**
* The javascript module for threads.
*/
| "js-module-dotnet"
/**
* The javascript module for threads.
*/
| "js-module-native"
/**
* The javascript module that came from nuget package .
*/
Expand DownExpand Up@@ -328,8 +330,10 @@ type DotnetModuleConfig = {
onConfigLoaded?: (config: MonoConfig) => void | Promise<void>;
onDotnetReady?: () => void | Promise<void>;
onDownloadResourceProgress?: (resourcesLoaded: number, totalResources: number) => void;
getApplicationEnvironment?: (bootConfigResponse: Response) => string | null;
imports?: any;
exports?: string[];
downloadResource?: (request: ResourceRequest) => LoadingResource | undefined;
} & Partial<EmscriptenModule>;
type APIType = {
runMain: (mainAssemblyName: string, args: string[]) => Promise<number>;
Expand DownExpand Up@@ -396,6 +400,7 @@ type ModuleAPI = {
exit: (code: number, reason?: any) => void;
};
type CreateDotnetRuntimeType = (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)) => Promise<RuntimeAPI>;
type WebAssemblyBootResourceType = "assembly" | "pdb" | "dotnetjs" | "dotnetwasm" | "globalization" | "manifest" | "configuration";

interface IDisposable {
dispose(): void;
Expand Down
34 changes: 12 additions & 22 deletions src/mono/wasm/runtime/lazyLoading.ts
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,40 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import { loaderHelpers, runtimeHelpers } from "./globals";
import { AssetEntry } from "./types";
import { INTERNAL, loaderHelpers, runtimeHelpers } from "./globals";
import type { WebAssemblyResourceLoader } from "./loader/blazor/WebAssemblyResourceLoader";

export async function loadLazyAssembly(assemblyNameToLoad: string): Promise<boolean> {
const resources = loaderHelpers.config.resources!;
const resourceLoader: WebAssemblyResourceLoader = INTERNAL.resourceLoader;
const resources = resourceLoader.bootConfig.resources;
const lazyAssemblies = resources.lazyAssembly;
if (!lazyAssemblies) {
throw new Error("No assemblies have been marked as lazy-loadable. Use the 'BlazorWebAssemblyLazyLoad' item group in your project file to enable lazy loading an assembly.");
}

if (!lazyAssemblies[assemblyNameToLoad]) {
const assemblyMarkedAsLazy = Object.prototype.hasOwnProperty.call(lazyAssemblies, assemblyNameToLoad);
if (!assemblyMarkedAsLazy) {
throw new Error(`${assemblyNameToLoad} must be marked with 'BlazorWebAssemblyLazyLoad' item group in your project file to allow lazy-loading.`);
}

const dllAsset: AssetEntry = {
name: assemblyNameToLoad,
hash: lazyAssemblies[assemblyNameToLoad],
behavior: "assembly",
};

if (loaderHelpers.loadedAssemblies.some(f => f.includes(assemblyNameToLoad))) {
return false;
}

const pdbNameToLoad = changeExtension(dllAsset.name, ".pdb");
const shouldLoadPdb = loaderHelpers.hasDebuggingEnabled(loaderHelpers.config) && Object.prototype.hasOwnProperty.call(lazyAssemblies, pdbNameToLoad);
const dllNameToLoad = assemblyNameToLoad;
const pdbNameToLoad = changeExtension(assemblyNameToLoad, ".pdb");
const shouldLoadPdb = loaderHelpers.hasDebuggingEnabled(resourceLoader.bootConfig) && resources.pdb && Object.prototype.hasOwnProperty.call(lazyAssemblies, pdbNameToLoad);

const dllBytesPromise = loaderHelpers.retrieve_asset_download(dllAsset);
const dllBytesPromise = resourceLoader.loadResource(dllNameToLoad, loaderHelpers.locateFile(dllNameToLoad), lazyAssemblies[dllNameToLoad], "assembly").response.then(response => response.arrayBuffer());

let dll = null;
let pdb = null;
if (shouldLoadPdb) {
const pdbBytesPromise = lazyAssemblies[pdbNameToLoad]
? loaderHelpers.retrieve_asset_download({
name: pdbNameToLoad,
hash: lazyAssemblies[pdbNameToLoad],
behavior: "pdb"
})
: Promise.resolve(null);

const pdbBytesPromise = await resourceLoader.loadResource(pdbNameToLoad, loaderHelpers.locateFile(pdbNameToLoad), lazyAssemblies[pdbNameToLoad], "pdb").response.then(response => response.arrayBuffer());
const [dllBytes, pdbBytes] = await Promise.all([dllBytesPromise, pdbBytesPromise]);

dll = new Uint8Array(dllBytes);
pdb = pdbBytes ? new Uint8Array(pdbBytes) : null;
pdb = new Uint8Array(pdbBytes);
} else {
const dllBytes = await dllBytesPromise;
dll = new Uint8Array(dllBytes);
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Revert "[browser] Clean-up typescript code imported from Blazor (#89435)" by radical · Pull Request #89828 · dotnet/runtime · GitHub
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -372,8 +372,8 @@ Copyright (c) .NET Foundation. All rights reserved.
RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)"
Extensions="@(WasmBootConfigExtension)"
TargetFrameworkVersion="$(TargetFrameworkVersion)"
ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)"
ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" />
LibraryInitializerOnRuntimeConfigLoaded="@(WasmLibraryInitializerOnRuntimeConfigLoaded)"
LibraryInitializerOnRuntimeReady="@(WasmLibraryInitializerOnRuntimeReady)" />

<ItemGroup>
<FileWrites Include="$(_WasmBuildBootJsonPath)" />
Expand DownExpand Up@@ -563,8 +563,8 @@ Copyright (c) .NET Foundation. All rights reserved.
RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)"
Extensions="@(WasmBootConfigExtension)"
TargetFrameworkVersion="$(TargetFrameworkVersion)"
ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)"
ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" />
LibraryInitializerOnRuntimeConfigLoaded="@(WasmLibraryInitializerOnRuntimeConfigLoaded)"
LibraryInitializerOnRuntimeReady="@(WasmLibraryInitializerOnRuntimeReady)" />

<ItemGroup>
<FileWrites Include="$(IntermediateOutputPath)blazor.publish.boot.json" />
Expand Down
10 changes: 2 additions & 8 deletions src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -390,21 +390,15 @@ public void AssertBootJson(AssertBundleOptionsBase options)
Assert.True(File.Exists(bootJsonPath), $"Expected to find {bootJsonPath}");

BootJsonData bootJson = ParseBootData(bootJsonPath);
var bootJsonEntries = bootJson.resources.jsModuleNative.Keys
.Union(bootJson.resources.jsModuleRuntime.Keys)
.Union(bootJson.resources.jsModuleWorker?.Keys ?? Enumerable.Empty<string>())
.Union(bootJson.resources.jsSymbols?.Keys ?? Enumerable.Empty<string>())
.Union(bootJson.resources.wasmNative.Keys)
.ToArray();
var bootJsonEntries = bootJson.resources.runtime.Keys.Where(k => k.StartsWith("dotnet.", StringComparison.Ordinal)).ToArray();

var expectedEntries = new SortedDictionary<string, Action<string>>();
IReadOnlySet<string> expected = GetDotNetFilesExpectedSet(options);

var knownSet = GetAllKnownDotnetFilesToFingerprintMap(options);
foreach (string expectedFilename in expected)
{
// FIXME: Find a systematic solution for skipping dotnet.js from boot json check
if (expectedFilename == "dotnet.js" || Path.GetExtension(expectedFilename) == ".map")
if (Path.GetExtension(expectedFilename) == ".map")
continue;

bool expectFingerprint = knownSet[expectedFilename];
Expand Down
101 changes: 53 additions & 48 deletions src/mono/wasm/runtime/dotnet.d.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -95,6 +95,14 @@ interface DotnetHostBuilder {
run(): Promise<number>;
}
type MonoConfig = {
/**
* The subfolder containing managed assemblies and pdbs. This is relative to dotnet.js script.
*/
assemblyRootFolder?: string;
/**
* A list of assets to load along with the runtime.
*/
assets?: AssetEntry[];
/**
* Additional search locations for assets.
*/
Expand DownExpand Up@@ -125,10 +133,6 @@ type MonoConfig = {
* debugLevel < 0 enables debugging and disables debug logging.
*/
debugLevel?: number;
/**
* Gets a value that determines whether to enable caching of the 'resources' inside a CacheStorage instance within the browser.
*/
cacheBootResources?: boolean;
/**
* Enables diagnostic log messages during startup
*/
Expand All@@ -147,6 +151,10 @@ type MonoConfig = {
* If true, the snapshot of runtime's memory will be stored in the browser and used for faster startup next time. Default is false.
*/
startupMemoryCache?: boolean;
/**
* hash of assets
*/
assetsHash?: string;
/**
* application environment
*/
Expand All@@ -159,10 +167,6 @@ type MonoConfig = {
* definition of assets to load along with the runtime.
*/
resources?: ResourceGroups;
/**
* appsettings files to load to VFS
*/
appsettings?: string[];
/**
* config extensions declared in MSBuild items @(WasmBootConfigExtension)
*/
Expand All@@ -174,31 +178,26 @@ type ResourceExtensions = {
[extensionName: string]: ResourceList;
};
interface ResourceGroups {
hash?: string;
assembly?: ResourceList;
lazyAssembly?: ResourceList;
pdb?: ResourceList;
jsModuleWorker?: ResourceList;
jsModuleNative: ResourceList;
jsModuleRuntime: ResourceList;
jsSymbols?: ResourceList;
wasmNative: ResourceList;
icu?: ResourceList;
satelliteResources?: {
readonly hash?: string;
readonly assembly?: ResourceList;
readonly lazyAssembly?: ResourceList;
readonly pdb?: ResourceList;
readonly runtime?: ResourceList;
readonly satelliteResources?: {
[cultureName: string]: ResourceList;
};
modulesAfterConfigLoaded?: ResourceList;
modulesAfterRuntimeReady?: ResourceList;
extensions?: ResourceExtensions;
vfs?: {
readonly libraryInitializers?: ResourceList;
readonly libraryStartupModules?: {
readonly onRuntimeConfigLoaded?: ResourceList;
readonly onRuntimeReady?: ResourceList;
};
readonly extensions?: ResourceExtensions;
readonly vfs?: {
[virtualPath: string]: ResourceList;
};
}
/**
* A "key" is name of the file, a "value" is optional hash for integrity check.
*/
type ResourceList = {
[name: string]: string | null | "";
[name: string]: string;
};
/**
* Overrides the built-in boot resource loading mechanism so that boot resources can be fetched
Expand All@@ -209,12 +208,12 @@ type ResourceList = {
* @param integrity The integrity string representing the expected content in the response.
* @returns A URI string or a Response promise to override the loading process, or null/undefined to allow the default loading behavior.
*/
type LoadBootResourceCallback = (type: AssetBehaviors | "manifest", name: string, defaultUri: string, integrity: string) => string | Promise<Response> | null | undefined;
type LoadBootResourceCallback = (type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string) => string | Promise<Response> | null | undefined;
interface ResourceRequest {
name: string;
behavior: AssetBehaviors;
behavior: AssetBehaviours;
resolvedUrl?: string;
hash?: string | null | "";
hash?: string;
}
interface LoadingResource {
name: string;
Expand DownExpand Up@@ -249,24 +248,7 @@ interface AssetEntry extends ResourceRequest {
*/
pendingDownload?: LoadingResource;
}
type SingleAssetBehaviors =
/**
* The binary of the dotnet runtime.
*/
"dotnetwasm"
/**
* The javascript module for threads.
*/
| "js-module-threads"
/**
* The javascript module for threads.
*/
| "js-module-runtime"
/**
* The javascript module for threads.
*/
| "js-module-native";
type AssetBehaviors = SingleAssetBehaviors |
type AssetBehaviours =
/**
* Load asset as a managed resource assembly.
*/
Expand All@@ -291,6 +273,26 @@ type AssetBehaviors = SingleAssetBehaviors |
* Load asset into the virtual filesystem (for fopen, File.Open, etc).
*/
| "vfs"
/**
* The binary of the dotnet runtime.
*/
| "dotnetwasm"
/**
* The javascript module for threads.
*/
| "js-module-threads"
/**
* The javascript module for threads.
*/
| "js-module-runtime"
/**
* The javascript module for threads.
*/
| "js-module-dotnet"
/**
* The javascript module for threads.
*/
| "js-module-native"
/**
* The javascript module that came from nuget package .
*/
Expand DownExpand Up@@ -328,8 +330,10 @@ type DotnetModuleConfig = {
onConfigLoaded?: (config: MonoConfig) => void | Promise<void>;
onDotnetReady?: () => void | Promise<void>;
onDownloadResourceProgress?: (resourcesLoaded: number, totalResources: number) => void;
getApplicationEnvironment?: (bootConfigResponse: Response) => string | null;
imports?: any;
exports?: string[];
downloadResource?: (request: ResourceRequest) => LoadingResource | undefined;
} & Partial<EmscriptenModule>;
type APIType = {
runMain: (mainAssemblyName: string, args: string[]) => Promise<number>;
Expand DownExpand Up@@ -396,6 +400,7 @@ type ModuleAPI = {
exit: (code: number, reason?: any) => void;
};
type CreateDotnetRuntimeType = (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)) => Promise<RuntimeAPI>;
type WebAssemblyBootResourceType = "assembly" | "pdb" | "dotnetjs" | "dotnetwasm" | "globalization" | "manifest" | "configuration";

interface IDisposable {
dispose(): void;
Expand Down
34 changes: 12 additions & 22 deletions src/mono/wasm/runtime/lazyLoading.ts
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,40 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import { loaderHelpers, runtimeHelpers } from "./globals";
import { AssetEntry } from "./types";
import { INTERNAL, loaderHelpers, runtimeHelpers } from "./globals";
import type { WebAssemblyResourceLoader } from "./loader/blazor/WebAssemblyResourceLoader";

export async function loadLazyAssembly(assemblyNameToLoad: string): Promise<boolean> {
const resources = loaderHelpers.config.resources!;
const resourceLoader: WebAssemblyResourceLoader = INTERNAL.resourceLoader;
const resources = resourceLoader.bootConfig.resources;
const lazyAssemblies = resources.lazyAssembly;
if (!lazyAssemblies) {
throw new Error("No assemblies have been marked as lazy-loadable. Use the 'BlazorWebAssemblyLazyLoad' item group in your project file to enable lazy loading an assembly.");
}

if (!lazyAssemblies[assemblyNameToLoad]) {
const assemblyMarkedAsLazy = Object.prototype.hasOwnProperty.call(lazyAssemblies, assemblyNameToLoad);
if (!assemblyMarkedAsLazy) {
throw new Error(`${assemblyNameToLoad} must be marked with 'BlazorWebAssemblyLazyLoad' item group in your project file to allow lazy-loading.`);
}

const dllAsset: AssetEntry = {
name: assemblyNameToLoad,
hash: lazyAssemblies[assemblyNameToLoad],
behavior: "assembly",
};

if (loaderHelpers.loadedAssemblies.some(f => f.includes(assemblyNameToLoad))) {
return false;
}

const pdbNameToLoad = changeExtension(dllAsset.name, ".pdb");
const shouldLoadPdb = loaderHelpers.hasDebuggingEnabled(loaderHelpers.config) && Object.prototype.hasOwnProperty.call(lazyAssemblies, pdbNameToLoad);
const dllNameToLoad = assemblyNameToLoad;
const pdbNameToLoad = changeExtension(assemblyNameToLoad, ".pdb");
const shouldLoadPdb = loaderHelpers.hasDebuggingEnabled(resourceLoader.bootConfig) && resources.pdb && Object.prototype.hasOwnProperty.call(lazyAssemblies, pdbNameToLoad);

const dllBytesPromise = loaderHelpers.retrieve_asset_download(dllAsset);
const dllBytesPromise = resourceLoader.loadResource(dllNameToLoad, loaderHelpers.locateFile(dllNameToLoad), lazyAssemblies[dllNameToLoad], "assembly").response.then(response => response.arrayBuffer());

let dll = null;
let pdb = null;
if (shouldLoadPdb) {
const pdbBytesPromise = lazyAssemblies[pdbNameToLoad]
? loaderHelpers.retrieve_asset_download({
name: pdbNameToLoad,
hash: lazyAssemblies[pdbNameToLoad],
behavior: "pdb"
})
: Promise.resolve(null);

const pdbBytesPromise = await resourceLoader.loadResource(pdbNameToLoad, loaderHelpers.locateFile(pdbNameToLoad), lazyAssemblies[pdbNameToLoad], "pdb").response.then(response => response.arrayBuffer());
const [dllBytes, pdbBytes] = await Promise.all([dllBytesPromise, pdbBytesPromise]);

dll = new Uint8Array(dllBytes);
pdb = pdbBytes ? new Uint8Array(pdbBytes) : null;
pdb = new Uint8Array(pdbBytes);
} else {
const dllBytes = await dllBytesPromise;
dll = new Uint8Array(dllBytes);
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Revert "[browser] Clean-up typescript code imported from Blazor (#89435)" by radical · Pull Request #89828 · dotnet/runtime · GitHub
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -372,8 +372,8 @@ Copyright (c) .NET Foundation. All rights reserved.
RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)"
Extensions="@(WasmBootConfigExtension)"
TargetFrameworkVersion="$(TargetFrameworkVersion)"
ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)"
ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" />
LibraryInitializerOnRuntimeConfigLoaded="@(WasmLibraryInitializerOnRuntimeConfigLoaded)"
LibraryInitializerOnRuntimeReady="@(WasmLibraryInitializerOnRuntimeReady)" />

<ItemGroup>
<FileWrites Include="$(_WasmBuildBootJsonPath)" />
Expand DownExpand Up@@ -563,8 +563,8 @@ Copyright (c) .NET Foundation. All rights reserved.
RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)"
Extensions="@(WasmBootConfigExtension)"
TargetFrameworkVersion="$(TargetFrameworkVersion)"
ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)"
ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" />
LibraryInitializerOnRuntimeConfigLoaded="@(WasmLibraryInitializerOnRuntimeConfigLoaded)"
LibraryInitializerOnRuntimeReady="@(WasmLibraryInitializerOnRuntimeReady)" />

<ItemGroup>
<FileWrites Include="$(IntermediateOutputPath)blazor.publish.boot.json" />
Expand Down
10 changes: 2 additions & 8 deletions src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -390,21 +390,15 @@ public void AssertBootJson(AssertBundleOptionsBase options)
Assert.True(File.Exists(bootJsonPath), $"Expected to find {bootJsonPath}");

BootJsonData bootJson = ParseBootData(bootJsonPath);
var bootJsonEntries = bootJson.resources.jsModuleNative.Keys
.Union(bootJson.resources.jsModuleRuntime.Keys)
.Union(bootJson.resources.jsModuleWorker?.Keys ?? Enumerable.Empty<string>())
.Union(bootJson.resources.jsSymbols?.Keys ?? Enumerable.Empty<string>())
.Union(bootJson.resources.wasmNative.Keys)
.ToArray();
var bootJsonEntries = bootJson.resources.runtime.Keys.Where(k => k.StartsWith("dotnet.", StringComparison.Ordinal)).ToArray();

var expectedEntries = new SortedDictionary<string, Action<string>>();
IReadOnlySet<string> expected = GetDotNetFilesExpectedSet(options);

var knownSet = GetAllKnownDotnetFilesToFingerprintMap(options);
foreach (string expectedFilename in expected)
{
// FIXME: Find a systematic solution for skipping dotnet.js from boot json check
if (expectedFilename == "dotnet.js" || Path.GetExtension(expectedFilename) == ".map")
if (Path.GetExtension(expectedFilename) == ".map")
continue;

bool expectFingerprint = knownSet[expectedFilename];
Expand Down
101 changes: 53 additions & 48 deletions src/mono/wasm/runtime/dotnet.d.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -95,6 +95,14 @@ interface DotnetHostBuilder {
run(): Promise<number>;
}
type MonoConfig = {
/**
* The subfolder containing managed assemblies and pdbs. This is relative to dotnet.js script.
*/
assemblyRootFolder?: string;
/**
* A list of assets to load along with the runtime.
*/
assets?: AssetEntry[];
/**
* Additional search locations for assets.
*/
Expand DownExpand Up@@ -125,10 +133,6 @@ type MonoConfig = {
* debugLevel < 0 enables debugging and disables debug logging.
*/
debugLevel?: number;
/**
* Gets a value that determines whether to enable caching of the 'resources' inside a CacheStorage instance within the browser.
*/
cacheBootResources?: boolean;
/**
* Enables diagnostic log messages during startup
*/
Expand All@@ -147,6 +151,10 @@ type MonoConfig = {
* If true, the snapshot of runtime's memory will be stored in the browser and used for faster startup next time. Default is false.
*/
startupMemoryCache?: boolean;
/**
* hash of assets
*/
assetsHash?: string;
/**
* application environment
*/
Expand All@@ -159,10 +167,6 @@ type MonoConfig = {
* definition of assets to load along with the runtime.
*/
resources?: ResourceGroups;
/**
* appsettings files to load to VFS
*/
appsettings?: string[];
/**
* config extensions declared in MSBuild items @(WasmBootConfigExtension)
*/
Expand All@@ -174,31 +178,26 @@ type ResourceExtensions = {
[extensionName: string]: ResourceList;
};
interface ResourceGroups {
hash?: string;
assembly?: ResourceList;
lazyAssembly?: ResourceList;
pdb?: ResourceList;
jsModuleWorker?: ResourceList;
jsModuleNative: ResourceList;
jsModuleRuntime: ResourceList;
jsSymbols?: ResourceList;
wasmNative: ResourceList;
icu?: ResourceList;
satelliteResources?: {
readonly hash?: string;
readonly assembly?: ResourceList;
readonly lazyAssembly?: ResourceList;
readonly pdb?: ResourceList;
readonly runtime?: ResourceList;
readonly satelliteResources?: {
[cultureName: string]: ResourceList;
};
modulesAfterConfigLoaded?: ResourceList;
modulesAfterRuntimeReady?: ResourceList;
extensions?: ResourceExtensions;
vfs?: {
readonly libraryInitializers?: ResourceList;
readonly libraryStartupModules?: {
readonly onRuntimeConfigLoaded?: ResourceList;
readonly onRuntimeReady?: ResourceList;
};
readonly extensions?: ResourceExtensions;
readonly vfs?: {
[virtualPath: string]: ResourceList;
};
}
/**
* A "key" is name of the file, a "value" is optional hash for integrity check.
*/
type ResourceList = {
[name: string]: string | null | "";
[name: string]: string;
};
/**
* Overrides the built-in boot resource loading mechanism so that boot resources can be fetched
Expand All@@ -209,12 +208,12 @@ type ResourceList = {
* @param integrity The integrity string representing the expected content in the response.
* @returns A URI string or a Response promise to override the loading process, or null/undefined to allow the default loading behavior.
*/
type LoadBootResourceCallback = (type: AssetBehaviors | "manifest", name: string, defaultUri: string, integrity: string) => string | Promise<Response> | null | undefined;
type LoadBootResourceCallback = (type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string) => string | Promise<Response> | null | undefined;
interface ResourceRequest {
name: string;
behavior: AssetBehaviors;
behavior: AssetBehaviours;
resolvedUrl?: string;
hash?: string | null | "";
hash?: string;
}
interface LoadingResource {
name: string;
Expand DownExpand Up@@ -249,24 +248,7 @@ interface AssetEntry extends ResourceRequest {
*/
pendingDownload?: LoadingResource;
}
type SingleAssetBehaviors =
/**
* The binary of the dotnet runtime.
*/
"dotnetwasm"
/**
* The javascript module for threads.
*/
| "js-module-threads"
/**
* The javascript module for threads.
*/
| "js-module-runtime"
/**
* The javascript module for threads.
*/
| "js-module-native";
type AssetBehaviors = SingleAssetBehaviors |
type AssetBehaviours =
/**
* Load asset as a managed resource assembly.
*/
Expand All@@ -291,6 +273,26 @@ type AssetBehaviors = SingleAssetBehaviors |
* Load asset into the virtual filesystem (for fopen, File.Open, etc).
*/
| "vfs"
/**
* The binary of the dotnet runtime.
*/
| "dotnetwasm"
/**
* The javascript module for threads.
*/
| "js-module-threads"
/**
* The javascript module for threads.
*/
| "js-module-runtime"
/**
* The javascript module for threads.
*/
| "js-module-dotnet"
/**
* The javascript module for threads.
*/
| "js-module-native"
/**
* The javascript module that came from nuget package .
*/
Expand DownExpand Up@@ -328,8 +330,10 @@ type DotnetModuleConfig = {
onConfigLoaded?: (config: MonoConfig) => void | Promise<void>;
onDotnetReady?: () => void | Promise<void>;
onDownloadResourceProgress?: (resourcesLoaded: number, totalResources: number) => void;
getApplicationEnvironment?: (bootConfigResponse: Response) => string | null;
imports?: any;
exports?: string[];
downloadResource?: (request: ResourceRequest) => LoadingResource | undefined;
} & Partial<EmscriptenModule>;
type APIType = {
runMain: (mainAssemblyName: string, args: string[]) => Promise<number>;
Expand DownExpand Up@@ -396,6 +400,7 @@ type ModuleAPI = {
exit: (code: number, reason?: any) => void;
};
type CreateDotnetRuntimeType = (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)) => Promise<RuntimeAPI>;
type WebAssemblyBootResourceType = "assembly" | "pdb" | "dotnetjs" | "dotnetwasm" | "globalization" | "manifest" | "configuration";

interface IDisposable {
dispose(): void;
Expand Down
34 changes: 12 additions & 22 deletions src/mono/wasm/runtime/lazyLoading.ts
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,40 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import { loaderHelpers, runtimeHelpers } from "./globals";
import { AssetEntry } from "./types";
import { INTERNAL, loaderHelpers, runtimeHelpers } from "./globals";
import type { WebAssemblyResourceLoader } from "./loader/blazor/WebAssemblyResourceLoader";

export async function loadLazyAssembly(assemblyNameToLoad: string): Promise<boolean> {
const resources = loaderHelpers.config.resources!;
const resourceLoader: WebAssemblyResourceLoader = INTERNAL.resourceLoader;
const resources = resourceLoader.bootConfig.resources;
const lazyAssemblies = resources.lazyAssembly;
if (!lazyAssemblies) {
throw new Error("No assemblies have been marked as lazy-loadable. Use the 'BlazorWebAssemblyLazyLoad' item group in your project file to enable lazy loading an assembly.");
}

if (!lazyAssemblies[assemblyNameToLoad]) {
const assemblyMarkedAsLazy = Object.prototype.hasOwnProperty.call(lazyAssemblies, assemblyNameToLoad);
if (!assemblyMarkedAsLazy) {
throw new Error(`${assemblyNameToLoad} must be marked with 'BlazorWebAssemblyLazyLoad' item group in your project file to allow lazy-loading.`);
}

const dllAsset: AssetEntry = {
name: assemblyNameToLoad,
hash: lazyAssemblies[assemblyNameToLoad],
behavior: "assembly",
};

if (loaderHelpers.loadedAssemblies.some(f => f.includes(assemblyNameToLoad))) {
return false;
}

const pdbNameToLoad = changeExtension(dllAsset.name, ".pdb");
const shouldLoadPdb = loaderHelpers.hasDebuggingEnabled(loaderHelpers.config) && Object.prototype.hasOwnProperty.call(lazyAssemblies, pdbNameToLoad);
const dllNameToLoad = assemblyNameToLoad;
const pdbNameToLoad = changeExtension(assemblyNameToLoad, ".pdb");
const shouldLoadPdb = loaderHelpers.hasDebuggingEnabled(resourceLoader.bootConfig) && resources.pdb && Object.prototype.hasOwnProperty.call(lazyAssemblies, pdbNameToLoad);

const dllBytesPromise = loaderHelpers.retrieve_asset_download(dllAsset);
const dllBytesPromise = resourceLoader.loadResource(dllNameToLoad, loaderHelpers.locateFile(dllNameToLoad), lazyAssemblies[dllNameToLoad], "assembly").response.then(response => response.arrayBuffer());

let dll = null;
let pdb = null;
if (shouldLoadPdb) {
const pdbBytesPromise = lazyAssemblies[pdbNameToLoad]
? loaderHelpers.retrieve_asset_download({
name: pdbNameToLoad,
hash: lazyAssemblies[pdbNameToLoad],
behavior: "pdb"
})
: Promise.resolve(null);

const pdbBytesPromise = await resourceLoader.loadResource(pdbNameToLoad, loaderHelpers.locateFile(pdbNameToLoad), lazyAssemblies[pdbNameToLoad], "pdb").response.then(response => response.arrayBuffer());
const [dllBytes, pdbBytes] = await Promise.all([dllBytesPromise, pdbBytesPromise]);

dll = new Uint8Array(dllBytes);
pdb = pdbBytes ? new Uint8Array(pdbBytes) : null;
pdb = new Uint8Array(pdbBytes);
} else {
const dllBytes = await dllBytesPromise;
dll = new Uint8Array(dllBytes);
Expand Down
Loading