Resolve issue with readLazyAssembly returning stale value (#26642)

* Resolve issue with readLazyAssembly returning stale value

* Address feedback from peer review

* Update test to exercise loaded package
This commit is contained in:
Safia Abdalla 2020-10-07 22:57:13 -07:00 committed by GitHub
parent 8118a25e7f
commit 84e9f56bca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 16 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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;
@ -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;
}));
}
});

View File

@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
// 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"));
@ -100,11 +100,11 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
// 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);
}
@ -123,6 +123,39 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
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];

View File

@ -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>