Skip to content

Commit

Permalink
Resolve issue with readLazyAssembly returning stale value (dotnet#26642)
Browse files Browse the repository at this point in the history
* Resolve issue with readLazyAssembly returning stale value

* Address feedback from peer review

* Update test to exercise loaded package
  • Loading branch information
captainsafia authored Oct 8, 2020
1 parent 8118a25 commit 84e9f56
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 16 deletions.
2 changes: 1 addition & 1 deletion src/Components/Web.JS/dist/Release/blazor.server.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/Components/Web.JS/dist/Release/blazor.webassembly.js

Large diffs are not rendered by default.

33 changes: 23 additions & 10 deletions src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,10 @@ function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourceLoade
return BINDING.js_to_mono_obj(Promise.resolve(0));
}

const lazyResources: {
assemblies?: (ArrayBuffer | null)[],
pdbs?: (ArrayBuffer | null)[]
} = {};
window['Blazor']._internal.getLazyAssemblies = (assembliesToLoadDotNetArray: System_Array<System_String>): System_Object => {
const assembliesToLoad = BINDING.mono_array_to_js_array<System_String, string>(assembliesToLoadDotNetArray);
const lazyAssemblies = resourceLoader.bootConfig.resources.lazyAssembly;
Expand Down Expand Up @@ -364,31 +368,40 @@ function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourceLoade
.map(assembly => resourceLoader.loadResource(assembly, `_framework/${assembly}`, lazyAssemblies[assembly], 'assembly'))
.map(async resource => (await resource.response).arrayBuffer()));


return BINDING.js_to_mono_obj(
Promise.all([resourcePromises, pdbPromises]).then(values => {
const resourcesToLoad = values[0];
const pdbsToLoad = values[1];
if (resourcesToLoad.length) {
lazyResources["assemblies"] = values[0];
lazyResources["pdbs"] = values[1];
if (lazyResources["assemblies"].length) {
window['Blazor']._internal.readLazyAssemblies = () => {
const assemblyBytes = BINDING.mono_obj_array_new(resourcesToLoad.length);
for (let i = 0; i < resourcesToLoad.length; i++) {
const assembly = resourcesToLoad[i] as ArrayBuffer;
const { assemblies } = lazyResources;
if (!assemblies) {
return BINDING.mono_obj_array_new(0);
}
const assemblyBytes = BINDING.mono_obj_array_new(assemblies.length);
for (let i = 0; i < assemblies.length; i++) {
const assembly = assemblies[i] as ArrayBuffer;
BINDING.mono_obj_array_set(assemblyBytes, i, BINDING.js_typed_array_to_array(new Uint8Array(assembly)));
}
return assemblyBytes;
};

window['Blazor']._internal.readLazyPdbs = () => {
const pdbBytes = BINDING.mono_obj_array_new(resourcesToLoad.length);
for (let i = 0; i < resourcesToLoad.length; i++) {
const pdb = pdbsToLoad && pdbsToLoad[i] ? new Uint8Array(pdbsToLoad[i] as ArrayBufferLike) : new Uint8Array();
const { assemblies, pdbs } = lazyResources;
if (!assemblies) {
return BINDING.mono_obj_array_new(0);
}
const pdbBytes = BINDING.mono_obj_array_new(assemblies.length);
for (let i = 0; i < assemblies.length; i++) {
const pdb = pdbs && pdbs[i] ? new Uint8Array(pdbs[i] as ArrayBufferLike) : new Uint8Array();
BINDING.mono_obj_array_set(pdbBytes, i, BINDING.js_typed_array_to_array(pdb));
}
return pdbBytes;
};
}

return resourcesToLoad.length;
return lazyResources["assemblies"].length;
}));
}
});
Expand Down
39 changes: 36 additions & 3 deletions src/Components/test/E2ETest/Tests/WebAssemblyLazyLoadTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public void CanLazyLoadOnRouteChange()
// Visit the route for the lazy-loaded assembly
SetUrlViaPushState("/WithLazyAssembly");

var button = app.FindElement(By.Id("use-package-button"));
var button = Browser.Exists(By.Id("use-package-button"));

// Now we should have requested the DLL
Assert.True(HasLoadedAssembly("Newtonsoft.Json.dll"));
Expand Down Expand Up @@ -100,11 +100,11 @@ public void CanLazyLoadAssemblyWithRoutes()
// Now the assembly has been loaded
Assert.True(HasLoadedAssembly("LazyTestContentPackage.dll"));

var button = app.FindElement(By.Id("go-to-lazy-route"));
var button = Browser.Exists(By.Id("go-to-lazy-route"));
button.Click();

// Navigating the lazy-loaded route should show its content
var renderedElement = app.FindElement(By.Id("lazy-page"));
var renderedElement = Browser.Exists(By.Id("lazy-page"));
Assert.True(renderedElement.Displayed);
}

Expand All @@ -123,6 +123,39 @@ public void ThrowsErrorForUnavailableAssemblies()
AssertLogContainsCriticalMessages("DoesNotExist.dll must be marked with 'BlazorWebAssemblyLazyLoad' item group in your project file to allow lazy-loading.");
}

[Fact]
public void CanLazyLoadViaLinkChange()
{
// Navigate to a page without any lazy-loaded dependencies
SetUrlViaPushState("/");
var app = Browser.MountTestComponent<TestRouterWithLazyAssembly>();

// We start off with no lazy assemblies loaded
Assert.False(HasLoadedAssembly("LazyTestContentPackage.dll"));
Assert.False(HasLoadedAssembly("Newtonsoft.Json.dll"));

// Click the first link and verify that it worked as expected
var lazyAssemblyLink = Browser.Exists(By.Id("with-lazy-assembly"));
lazyAssemblyLink.Click();
var pkgButton = Browser.Exists(By.Id("use-package-button"));
Assert.True(HasLoadedAssembly("Newtonsoft.Json.dll"));
pkgButton.Click();

// Navigate to the next page and verify that it loaded its assembly
var lazyRoutesLink = Browser.Exists(By.Id("with-lazy-routes"));
lazyRoutesLink.Click();
Browser.Exists(By.Id("lazy-load-msg"));
Assert.True(HasLoadedAssembly("LazyTestContentPackage.dll"));

// Interact with that assembly to ensure it was loaded properly
var button = Browser.Exists(By.Id("go-to-lazy-route"));
button.Click();

// Navigating the lazy-loaded route should show its content
var renderedElement = Browser.Exists(By.Id("lazy-page"));
Assert.True(renderedElement.Displayed);
}

private string SetUrlViaPushState(string relativeUri)
{
var pathBaseWithoutHash = ServerPathBase.Split('#')[0];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
<li><NavLink href="/subdir/WithParameters/Name/Abc/LastName/McDef">With more parameters</NavLink></li>
<li><NavLink href="/subdir/LongPage1">Long page 1</NavLink></li>
<li><NavLink href="/subdir/LongPage2">Long page 2</NavLink></li>
<li><NavLink href="/subdir/WithLazyAssembly">With lazy assembly</NavLink></li>
<li><NavLink href="/subdir/WithLazyAssembly" id="with-lazy-assembly">With lazy assembly</NavLink></li>
<li><NavLink href="/subdir/WithLazyLoadedRoutes" id="with-lazy-routes">With lazy loaded routes</NavLink></li>
<li><NavLink href="PreventDefaultCases">preventDefault cases</NavLink></li>
<li><NavLink>Null href never matches</NavLink></li>
</ul>
Expand Down

0 comments on commit 84e9f56

Please sign in to comment.