From b91904efde2cabbb6838b842daa5bd848ce7c5b1 Mon Sep 17 00:00:00 2001 From: Safia Abdalla Date: Tue, 21 Jul 2020 12:35:34 -0700 Subject: [PATCH 1/2] Follow-ups to lazy-load from API review --- .../Components/src/Routing/Router.cs | 19 +++---- .../Web.JS/dist/Release/blazor.webassembly.js | 2 +- .../Web.JS/src/Platform/Mono/MonoPlatform.ts | 17 ++++-- .../src/Hosting/WebAssemblyHostBuilder.cs | 4 +- .../src/Services/LazyAssemblyLoader.cs | 56 ++++++++++--------- .../E2ETest/Tests/WebAssemblyLazyLoadTest.cs | 28 ++++++++++ .../TestRouterWithLazyAssembly.razor | 33 ++++++----- 7 files changed, 99 insertions(+), 60 deletions(-) diff --git a/src/Components/Components/src/Routing/Router.cs b/src/Components/Components/src/Routing/Router.cs index 7d6b778d291f..ab95ee2c6334 100644 --- a/src/Components/Components/src/Routing/Router.cs +++ b/src/Components/Components/src/Routing/Router.cs @@ -68,12 +68,12 @@ static readonly ReadOnlyDictionary _emptyParametersDictionary /// /// Get or sets the content to display when asynchronous navigation is in progress. /// - [Parameter] public RenderFragment Navigating { get; set; } + [Parameter] public RenderFragment? Navigating { get; set; } /// /// Gets or sets a handler that should be called before navigating to a new page. /// - [Parameter] public Func OnNavigateAsync { get; set; } + [Parameter] public Func? OnNavigateAsync { get; set; } private RouteTable Routes { get; set; } @@ -195,10 +195,6 @@ internal virtual void Refresh(bool isNavigationIntercepted) private async ValueTask RunOnNavigateAsync(string path, Task previousOnNavigate) { - if (OnNavigateAsync == null) - { - return true; - } // Cancel the CTS instead of disposing it, since disposing does not // actually cancel and can cause unintended Object Disposed Exceptions. @@ -210,6 +206,11 @@ private async ValueTask RunOnNavigateAsync(string path, Task previousOnNav // invocation. await previousOnNavigate; + if (OnNavigateAsync == null) + { + return true; + } + _onNavigateCts = new CancellationTokenSource(); var navigateContext = new NavigationContext(path, _onNavigateCts.Token); @@ -227,14 +228,12 @@ private async ValueTask RunOnNavigateAsync(string path, Task previousOnNav if (e.CancellationToken != navigateContext.CancellationToken) { var rethrownException = new InvalidOperationException("OnNavigateAsync can only be cancelled via NavigateContext.CancellationToken.", e); - _renderHandle.Render(builder => ExceptionDispatchInfo.Capture(rethrownException).Throw()); - return false; + _renderHandle.Render(builder => ExceptionDispatchInfo.Throw(rethrownException)); } } catch (Exception e) { - _renderHandle.Render(builder => ExceptionDispatchInfo.Capture(e).Throw()); - return false; + _renderHandle.Render(builder => ExceptionDispatchInfo.Throw(e)); } return false; diff --git a/src/Components/Web.JS/dist/Release/blazor.webassembly.js b/src/Components/Web.JS/dist/Release/blazor.webassembly.js index ae1a7a2138a3..caaa8d8a97e6 100644 --- a/src/Components/Web.JS/dist/Release/blazor.webassembly.js +++ b/src/Components/Web.JS/dist/Release/blazor.webassembly.js @@ -1 +1 @@ -!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=45)}([,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){window.DotNet=e;var t=[],n={},r={},o=1,i=null;function a(e){t.push(e)}function s(e,t,n,r){var o=c();if(o.invokeDotNetFromJS){var i=JSON.stringify(r,m),a=o.invokeDotNetFromJS(e,t,n,i);return a?f(a):null}throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeMethodAsync instead.")}function u(e,t,r,i){if(e&&r)throw new Error("For instance method calls, assemblyName should be null. Received '"+e+"'.");var a=o++,s=new Promise((function(e,t){n[a]={resolve:e,reject:t}}));try{var u=JSON.stringify(i,m);c().beginInvokeDotNetFromJS(a,e,t,r,u)}catch(e){l(a,!1,e)}return s}function c(){if(null!==i)return i;throw new Error("No .NET call dispatcher has been set.")}function l(e,t,r){if(!n.hasOwnProperty(e))throw new Error("There is no pending async call with ID "+e+".");var o=n[e];delete n[e],t?o.resolve(r):o.reject(r)}function f(e){return e?JSON.parse(e,(function(e,n){return t.reduce((function(t,n){return n(e,t)}),n)})):null}function d(e){return e instanceof Error?e.message+"\n"+e.stack:e?e.toString():"null"}function p(e){if(Object.prototype.hasOwnProperty.call(r,e))return r[e];var t,n=window,o="window";if(e.split(".").forEach((function(e){if(!(e in n))throw new Error("Could not find '"+e+"' in '"+o+"'.");t=n,n=n[e],o+="."+e})),n instanceof Function)return n=n.bind(t),r[e]=n,n;throw new Error("The value '"+o+"' is not a function.")}e.attachDispatcher=function(e){i=e},e.attachReviver=a,e.invokeMethod=function(e,t){for(var n=[],r=2;r0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return r in e||(e[r]=[]),e}function s(e,t,n){var i=e;if(e instanceof Comment&&(c(i)&&c(i).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(u(i))throw new Error("Not implemented: moving existing logical children");var a=c(t);if(n0;)e(r,0)}var i=r;i.parentNode.removeChild(i)},t.getLogicalParent=u,t.getLogicalSiblingEnd=function(e){return e[i]||null},t.getLogicalChild=function(e,t){return c(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===l(e).namespaceURI},t.getLogicalChildrenArray=c,t.permuteLogicalChildren=function(e,t){var n=c(e);t.forEach((function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=f(t);if(n)return n.previousSibling;var r=u(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)})),t.forEach((function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):d(r,e)})),t.forEach((function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,i=r;i;){var a=i.nextSibling;if(n.insertBefore(i,t),i===o)break;i=a}n.removeChild(t)})),t.forEach((function(e){n[e.toSiblingIndex]=e.moveRangeStart}))},t.getClosestDomElement=l},,,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.setPlatform=function(e){return t.platform=e,t.platform}},function(e,t,n){"use strict";var r;Object.defineProperty(t,"__esModule",{value:!0}),t.dispatchEvent=function(e,t){if(!r)throw new Error("eventDispatcher not initialized. Call 'setEventDispatcher' to configure it.");r(e,t)},t.setEventDispatcher=function(e){r=e}},,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(8),o=n(4),i=n(31),a=n(5);window.Blazor={navigateTo:r.navigateTo,_internal:{attachRootComponentToElement:o.attachRootComponentToElement,navigationManager:r.internalFunctions,domWrapper:i.domFunctions,setProfilingEnabled:a.setProfilingEnabled}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(26),o=n(27),i=n(13),a=n(30),s=n(19),u=n(8),c=n(5),l=document.createElement("template"),f=document.createElementNS("http://www.w3.org/2000/svg","g"),d={submit:!0},p={},h=function(){function e(e){var t=this;this.childComponentLocations={},this.browserRendererId=e,this.eventDelegator=new o.EventDelegator((function(e,n,r,o){!function(e,t,n,r,o){d[e.type]&&e.preventDefault();var i={browserRendererId:t,eventHandlerId:n,eventArgsType:r.type,eventFieldInfo:o};s.dispatchEvent(i,r.data)}(e,t.browserRendererId,n,r,o)})),u.attachToEventDelegator(this.eventDelegator)}return e.prototype.attachRootComponentToLogicalElement=function(e,t){this.attachComponentToElement(e,t),p[e]=t},e.prototype.updateComponent=function(e,t,n,r){c.profileStart("updateComponent");var o=this.childComponentLocations[t];if(!o)throw new Error("No element is currently associated with component "+t);var a=p[t];if(a){var s=i.getLogicalSiblingEnd(a);delete p[t],s?function(e,t){var n=i.getLogicalParent(e);if(!n)throw new Error("Can't clear between nodes. The start node does not have a logical parent.");for(var r=i.getLogicalChildrenArray(n),o=r.indexOf(e)+1,a=r.indexOf(t),s=o;s<=a;s++)i.removeLogicalChild(n,o);e.textContent="!"}(a,s):function(e){var t;for(;t=e.firstChild;)e.removeChild(t)}(a)}var u=i.getClosestDomElement(o).ownerDocument,l=u&&u.activeElement;this.applyEdits(e,t,o,0,n,r),l instanceof HTMLElement&&u&&u.activeElement!==l&&l.focus(),c.profileEnd("updateComponent")},e.prototype.disposeComponent=function(e){delete this.childComponentLocations[e]},e.prototype.disposeEventHandler=function(e){this.eventDelegator.removeListener(e)},e.prototype.attachComponentToElement=function(e,t){this.childComponentLocations[e]=t},e.prototype.applyEdits=function(e,t,n,o,a,s){for(var u,c=0,l=o,f=e.arrayBuilderSegmentReader,d=e.editReader,p=e.frameReader,h=f.values(a),m=f.offset(a),v=m+f.count(a),y=m;y0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]>>0)}t.readInt32LE=function(e,t){return e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24},t.readUint32LE=i,t.readUint64LE=function(e,t){var n=i(e,t+4);if(n>o)throw new Error("Cannot read uint64 with high order part "+n+", because the result would exceed Number.MAX_SAFE_INTEGER.");return n*r+i(e,t)},t.readLEB128=function(e,t){for(var n=0,r=0,o=0;o<4;o++){var i=e[t+o];if(n|=(127&i)<65535&&(c-=65536,r.push(c>>>10&1023|55296),c=56320|1023&c),r.push(c)}r.length>1024&&(o.push(String.fromCharCode.apply(null,r)),r.length=0)}return o.push(String.fromCharCode.apply(null,r)),o.join("")}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.shouldAutoStart=function(){return!(!document||!document.currentScript||"false"===document.currentScript.getAttribute("autostart"))}},,,,,,,,,,function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{u(r.next(e))}catch(e){i(e)}}function s(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,s)}u((r=r.apply(e,t||[])).next())}))},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0)&&!(r=i.next()).done;)a.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return a};Object.defineProperty(t,"__esModule",{value:!0});var a=n(3);n(23);var s=n(18),u=n(46),c=n(4),l=n(49),f=n(35),d=n(19),p=n(50),h=n(51),m=n(52),v=n(5),y=!1;function b(e){return r(this,void 0,void 0,(function(){var t,n,f,b,g,w,E,_=this;return o(this,(function(C){switch(C.label){case 0:if(y)throw new Error("Blazor has already started.");return y=!0,d.setEventDispatcher((function(e,t){u.monoPlatform.invokeWhenHeapUnlocked((function(){return a.DotNet.invokeMethodAsync("Microsoft.AspNetCore.Components.WebAssembly","DispatchEvent",e,JSON.stringify(t))}))})),t=s.setPlatform(u.monoPlatform),window.Blazor.platform=t,window.Blazor._internal.renderBatch=function(e,t){v.profileStart("renderBatch");var n=u.monoPlatform.beginHeapLock();try{c.renderBatch(e,new l.SharedMemoryRenderBatch(t))}finally{n.release()}v.profileEnd("renderBatch")},n=window.Blazor._internal.navigationManager.getBaseURI,f=window.Blazor._internal.navigationManager.getLocationHref,window.Blazor._internal.navigationManager.getUnmarshalledBaseURI=function(){return BINDING.js_string_to_mono_string(n())},window.Blazor._internal.navigationManager.getUnmarshalledLocationHref=function(){return BINDING.js_string_to_mono_string(f())},window.Blazor._internal.navigationManager.listenForNavigationEvents((function(e,t){return r(_,void 0,void 0,(function(){return o(this,(function(n){switch(n.label){case 0:return[4,a.DotNet.invokeMethodAsync("Microsoft.AspNetCore.Components.WebAssembly","NotifyLocationChanged",e,t)];case 1:return n.sent(),[2]}}))}))})),[4,m.BootConfigResult.initAsync()];case 1:return b=C.sent(),[4,Promise.all([p.WebAssemblyResourceLoader.initAsync(b.bootConfig,e||{}),h.WebAssemblyConfigLoader.initAsync(b)])];case 2:g=i.apply(void 0,[C.sent(),1]),w=g[0],C.label=3;case 3:return C.trys.push([3,5,,6]),[4,t.start(w)];case 4:return C.sent(),[3,6];case 5:throw E=C.sent(),new Error("Failed to start platform. Reason: "+E);case 6:return t.callEntryPoint(w.bootConfig.entryAssembly),[2]}}))}))}window.Blazor.start=b,f.shouldAutoStart()&&b().catch((function(e){"undefined"!=typeof Module&&Module.printErr?Module.printErr(e):console.error(e)}))},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{u(r.next(e))}catch(e){i(e)}}function s(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,s)}u((r=r.apply(e,t||[])).next())}))},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]>2]}t.monoPlatform={start:function(e){return new Promise((function(t,n){var f,d;s.attachDebuggerHotkey(e),l.initializeProfiling((function(e){y("Microsoft.AspNetCore.Components","Microsoft.AspNetCore.Components.Profiling.WebAssemblyComponentsProfiling","SetCapturing")(e)})),window.Browser={init:function(){}},f=function(){window.Module=function(e,t,n){var l=this,f=e.bootConfig.resources,d=window.Module||{},p=["DEBUGGING ENABLED"];d.print=function(e){return p.indexOf(e)<0&&console.log(e)},d.printErr=function(e){console.error(e),u.showErrorNotification()},d.preRun=d.preRun||[],d.postRun=d.postRun||[],d.preloadPlugins=[];var h,v=e.loadResources(f.assembly,(function(e){return"_framework/"+e}),"assembly"),w=e.loadResources(f.pdb||{},(function(e){return"_framework/"+e}),"pdb"),E=e.loadResource("dotnet.wasm","_framework/dotnet.wasm",e.bootConfig.resources.runtime["dotnet.wasm"],"dotnetwasm");return e.bootConfig.resources.runtime.hasOwnProperty("dotnet.timezones.dat")&&(h=e.loadResource("dotnet.timezones.dat","_framework/dotnet.timezones.dat",e.bootConfig.resources.runtime["dotnet.timezones.dat"],"timezonedata")),d.instantiateWasm=function(e,t){return r(l,void 0,void 0,(function(){var n,r;return o(this,(function(o){switch(o.label){case 0:return o.trys.push([0,3,,4]),[4,E];case 1:return[4,b(o.sent(),e)];case 2:return n=o.sent(),[3,4];case 3:throw r=o.sent(),d.printErr(r),r;case 4:return t(n),[2]}}))})),[]},d.preRun.push((function(){i=cwrap("mono_wasm_add_assembly",null,["string","number","number"]),MONO.loaded_files=[],h&&function(e){r(this,void 0,void 0,(function(){var t,n;return o(this,(function(r){switch(r.label){case 0:return t="blazor:timezonedata",addRunDependency(t),[4,e.response];case 1:return[4,r.sent().arrayBuffer()];case 2:return n=r.sent(),c.loadTimezoneData(n),removeRunDependency(t),[2]}}))}))}(h),v.forEach((function(e){return _(e,function(e,t){var n=e.lastIndexOf(".");if(n<0)throw new Error("No extension to replace in '"+e+"'");return e.substr(0,n)+t}(e.name,".dll"))})),w.forEach((function(e){return _(e,e.name)})),window.Blazor._internal.dotNetCriticalError=function(e){d.printErr(BINDING.conv_string(e)||"(null)")},window.Blazor._internal.getSatelliteAssemblies=function(t){var n=BINDING.mono_array_to_js_array(t),i=e.bootConfig.resources.satelliteResources;if(i){var a=Promise.all(n.filter((function(e){return i.hasOwnProperty(e)})).map((function(t){return e.loadResources(i[t],(function(e){return"_framework/"+e}),"assembly")})).reduce((function(e,t){return e.concat(t)}),new Array).map((function(e){return r(l,void 0,void 0,(function(){return o(this,(function(t){switch(t.label){case 0:return[4,e.response];case 1:return[2,t.sent().arrayBuffer()]}}))}))})));return BINDING.js_to_mono_obj(a.then((function(e){return e.length&&(window.Blazor._internal.readSatelliteAssemblies=function(){for(var t=BINDING.mono_obj_array_new(e.length),n=0;n>1];var n},readInt32Field:function(e,t){return h(e+(t||0))},readUint64Field:function(e,t){return function(e){var t=e>>2,n=Module.HEAPU32[t+1];if(n>d)throw new Error("Cannot read uint64 with high order part "+n+", because the result would exceed Number.MAX_SAFE_INTEGER.");return n*f+Module.HEAPU32[t]}(e+(t||0))},readFloatField:function(e,t){return n=e+(t||0),Module.HEAPF32[n>>2];var n},readObjectField:function(e,t){return h(e+(t||0))},readStringField:function(e,t,n){var r,o=h(e+(t||0));if(0===o)return null;if(n){var i=BINDING.unbox_mono_obj(o);return"boolean"==typeof i?i?"":null:i}return p?void 0===(r=p.stringCache.get(o))&&(r=BINDING.conv_string(o),p.stringCache.set(o,r)):r=BINDING.conv_string(o),r},readStructField:function(e,t){return e+(t||0)},beginHeapLock:function(){return g(),p=new w},invokeWhenHeapUnlocked:function(e){p?p.enqueuePostReleaseAction(e):e()}};var m=document.createElement("a");function v(e){return e+12}function y(e,t,n){var r="["+e+"] "+t+":"+n;return BINDING.bind_static_method(r)}function b(e,t){return r(this,void 0,void 0,(function(){var n,r;return o(this,(function(o){switch(o.label){case 0:if("function"!=typeof WebAssembly.instantiateStreaming)return[3,4];o.label=1;case 1:return o.trys.push([1,3,,4]),[4,WebAssembly.instantiateStreaming(e.response,t)];case 2:return[2,o.sent().instance];case 3:return n=o.sent(),console.info("Streaming compilation failed. Falling back to ArrayBuffer instantiation. ",n),[3,4];case 4:return[4,e.response.then((function(e){return e.arrayBuffer()}))];case 5:return r=o.sent(),[4,WebAssembly.instantiate(r,t)];case 6:return[2,o.sent().instance]}}))}))}function g(){if(p)throw new Error("Assertion failed - heap is currently locked")}var w=function(){function e(){this.stringCache=new Map}return e.prototype.enqueuePostReleaseAction=function(e){this.postReleaseActions||(this.postReleaseActions=[]),this.postReleaseActions.push(e)},e.prototype.release=function(){var e;if(p!==this)throw new Error("Trying to release a lock which isn't current");for(p=null;null===(e=this.postReleaseActions)||void 0===e?void 0:e.length;){this.postReleaseActions.shift()(),g()}},e}()},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=window.chrome&&navigator.userAgent.indexOf("Edge")<0,o=!1;function i(){return o&&r}t.hasDebuggingEnabled=i,t.attachDebuggerHotkey=function(e){o=!!e.bootConfig.resources.pdb;var t=navigator.platform.match(/^Mac/i)?"Cmd":"Alt";i()&&console.info("Debugging hotkey: Shift+"+t+"+D (when application has focus)"),document.addEventListener("keydown",(function(e){var t;e.shiftKey&&(e.metaKey||e.altKey)&&"KeyD"===e.code&&(o?r?((t=document.createElement("a")).href="_framework/debug?url="+encodeURIComponent(location.href),t.target="_blank",t.rel="noopener noreferrer",t.click()):console.error("Currently, only Microsoft Edge (80+), or Google Chrome, are supported for debugging."):console.error("Cannot start debugging, because the application was not compiled with debugging enabled."))}))}},function(e,t,n){"use strict";var r=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,o,i=n.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(r=i.next()).done;)a.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return a};Object.defineProperty(t,"__esModule",{value:!0});var i=n(33),a=n(34);t.loadTimezoneData=function(e){var t,n,s=new Uint8Array(e),u=i.readInt32LE(s,0);s=s.slice(4);var c=a.decodeUtf8(s.slice(0,u)),l=JSON.parse(c);s=s.slice(u),Module.FS_createPath("/","zoneinfo",!0,!0),new Set(l.map((function(e){return e[0].split("/")[0]}))).forEach((function(e){return Module.FS_createPath("/zoneinfo",e,!0,!0)}));try{for(var f=r(l),d=f.next();!d.done;d=f.next()){var p=o(d.value,2),h=p[0],m=p[1],v=s.slice(0,m);Module.FS_createDataFile("/zoneinfo/"+h,null,v,!0,!0,!0),s=s.slice(m)}}catch(e){t={error:e}}finally{try{d&&!d.done&&(n=f.return)&&n.call(f)}finally{if(t)throw t.error}}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(18),o=function(){function e(e){this.batchAddress=e,this.arrayRangeReader=i,this.arrayBuilderSegmentReader=a,this.diffReader=s,this.editReader=u,this.frameReader=c}return e.prototype.updatedComponents=function(){return r.platform.readStructField(this.batchAddress,0)},e.prototype.referenceFrames=function(){return r.platform.readStructField(this.batchAddress,i.structLength)},e.prototype.disposedComponentIds=function(){return r.platform.readStructField(this.batchAddress,2*i.structLength)},e.prototype.disposedEventHandlerIds=function(){return r.platform.readStructField(this.batchAddress,3*i.structLength)},e.prototype.updatedComponentsEntry=function(e,t){return l(e,t,s.structLength)},e.prototype.referenceFramesEntry=function(e,t){return l(e,t,c.structLength)},e.prototype.disposedComponentIdsEntry=function(e,t){var n=l(e,t,4);return r.platform.readInt32Field(n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=l(e,t,8);return r.platform.readUint64Field(n)},e}();t.SharedMemoryRenderBatch=o;var i={structLength:8,values:function(e){return r.platform.readObjectField(e,0)},count:function(e){return r.platform.readInt32Field(e,4)}},a={structLength:12,values:function(e){var t=r.platform.readObjectField(e,0),n=r.platform.getObjectFieldsBaseAddress(t);return r.platform.readObjectField(n,0)},offset:function(e){return r.platform.readInt32Field(e,4)},count:function(e){return r.platform.readInt32Field(e,8)}},s={structLength:4+a.structLength,componentId:function(e){return r.platform.readInt32Field(e,0)},edits:function(e){return r.platform.readStructField(e,4)},editsEntry:function(e,t){return l(e,t,u.structLength)}},u={structLength:20,editType:function(e){return r.platform.readInt32Field(e,0)},siblingIndex:function(e){return r.platform.readInt32Field(e,4)},newTreeIndex:function(e){return r.platform.readInt32Field(e,8)},moveToSiblingIndex:function(e){return r.platform.readInt32Field(e,8)},removedAttributeName:function(e){return r.platform.readStringField(e,16)}},c={structLength:36,frameType:function(e){return r.platform.readInt16Field(e,4)},subtreeLength:function(e){return r.platform.readInt32Field(e,8)},elementReferenceCaptureId:function(e){return r.platform.readStringField(e,16)},componentId:function(e){return r.platform.readInt32Field(e,12)},elementName:function(e){return r.platform.readStringField(e,16)},textContent:function(e){return r.platform.readStringField(e,16)},markupContent:function(e){return r.platform.readStringField(e,16)},attributeName:function(e){return r.platform.readStringField(e,16)},attributeValue:function(e){return r.platform.readStringField(e,24,!0)},attributeEventHandlerId:function(e){return r.platform.readUint64Field(e,8)}};function l(e,t,n){return r.platform.getArrayEntryPtr(e,t,n)}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{u(r.next(e))}catch(e){i(e)}}function s(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,s)}u((r=r.apply(e,t||[])).next())}))},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return r in e||(e[r]=[]),e}function s(e,t,n){var i=e;if(e instanceof Comment&&(l(i)&&l(i).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(u(i))throw new Error("Not implemented: moving existing logical children");var a=l(t);if(n0;)e(r,0)}var i=r;i.parentNode.removeChild(i)},t.getLogicalParent=u,t.getLogicalSiblingEnd=function(e){return e[i]||null},t.getLogicalChild=function(e,t){return l(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===c(e).namespaceURI},t.getLogicalChildrenArray=l,t.permuteLogicalChildren=function(e,t){var n=l(e);t.forEach((function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=f(t);if(n)return n.previousSibling;var r=u(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)})),t.forEach((function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):d(r,e)})),t.forEach((function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,i=r;i;){var a=i.nextSibling;if(n.insertBefore(i,t),i===o)break;i=a}n.removeChild(t)})),t.forEach((function(e){n[e.toSiblingIndex]=e.moveRangeStart}))},t.getClosestDomElement=c},,,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.setPlatform=function(e){return t.platform=e,t.platform}},function(e,t,n){"use strict";var r;Object.defineProperty(t,"__esModule",{value:!0}),t.dispatchEvent=function(e,t){if(!r)throw new Error("eventDispatcher not initialized. Call 'setEventDispatcher' to configure it.");r(e,t)},t.setEventDispatcher=function(e){r=e}},,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(8),o=n(4),i=n(31),a=n(5);window.Blazor={navigateTo:r.navigateTo,_internal:{attachRootComponentToElement:o.attachRootComponentToElement,navigationManager:r.internalFunctions,domWrapper:i.domFunctions,setProfilingEnabled:a.setProfilingEnabled}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(26),o=n(27),i=n(13),a=n(30),s=n(19),u=n(8),l=n(5),c=document.createElement("template"),f=document.createElementNS("http://www.w3.org/2000/svg","g"),d={submit:!0},p={},h=function(){function e(e){var t=this;this.childComponentLocations={},this.browserRendererId=e,this.eventDelegator=new o.EventDelegator((function(e,n,r,o){!function(e,t,n,r,o){d[e.type]&&e.preventDefault();var i={browserRendererId:t,eventHandlerId:n,eventArgsType:r.type,eventFieldInfo:o};s.dispatchEvent(i,r.data)}(e,t.browserRendererId,n,r,o)})),u.attachToEventDelegator(this.eventDelegator)}return e.prototype.attachRootComponentToLogicalElement=function(e,t){this.attachComponentToElement(e,t),p[e]=t},e.prototype.updateComponent=function(e,t,n,r){l.profileStart("updateComponent");var o=this.childComponentLocations[t];if(!o)throw new Error("No element is currently associated with component "+t);var a=p[t];if(a){var s=i.getLogicalSiblingEnd(a);delete p[t],s?function(e,t){var n=i.getLogicalParent(e);if(!n)throw new Error("Can't clear between nodes. The start node does not have a logical parent.");for(var r=i.getLogicalChildrenArray(n),o=r.indexOf(e)+1,a=r.indexOf(t),s=o;s<=a;s++)i.removeLogicalChild(n,o);e.textContent="!"}(a,s):function(e){var t;for(;t=e.firstChild;)e.removeChild(t)}(a)}var u=i.getClosestDomElement(o).ownerDocument,c=u&&u.activeElement;this.applyEdits(e,t,o,0,n,r),c instanceof HTMLElement&&u&&u.activeElement!==c&&c.focus(),l.profileEnd("updateComponent")},e.prototype.disposeComponent=function(e){delete this.childComponentLocations[e]},e.prototype.disposeEventHandler=function(e){this.eventDelegator.removeListener(e)},e.prototype.attachComponentToElement=function(e,t){this.childComponentLocations[e]=t},e.prototype.applyEdits=function(e,t,n,o,a,s){for(var u,l=0,c=o,f=e.arrayBuilderSegmentReader,d=e.editReader,p=e.frameReader,h=f.values(a),m=f.offset(a),y=m+f.count(a),v=m;v0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]>>0)}t.readInt32LE=function(e,t){return e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24},t.readUint32LE=i,t.readUint64LE=function(e,t){var n=i(e,t+4);if(n>o)throw new Error("Cannot read uint64 with high order part "+n+", because the result would exceed Number.MAX_SAFE_INTEGER.");return n*r+i(e,t)},t.readLEB128=function(e,t){for(var n=0,r=0,o=0;o<4;o++){var i=e[t+o];if(n|=(127&i)<65535&&(l-=65536,r.push(l>>>10&1023|55296),l=56320|1023&l),r.push(l)}r.length>1024&&(o.push(String.fromCharCode.apply(null,r)),r.length=0)}return o.push(String.fromCharCode.apply(null,r)),o.join("")}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.shouldAutoStart=function(){return!(!document||!document.currentScript||"false"===document.currentScript.getAttribute("autostart"))}},,,,,,,,,,function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{u(r.next(e))}catch(e){i(e)}}function s(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,s)}u((r=r.apply(e,t||[])).next())}))},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0)&&!(r=i.next()).done;)a.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return a};Object.defineProperty(t,"__esModule",{value:!0});var a=n(3);n(23);var s=n(18),u=n(46),l=n(4),c=n(49),f=n(35),d=n(19),p=n(50),h=n(51),m=n(52),y=n(5),v=!1;function b(e){return r(this,void 0,void 0,(function(){var t,n,f,b,g,w,E,_=this;return o(this,(function(C){switch(C.label){case 0:if(v)throw new Error("Blazor has already started.");return v=!0,d.setEventDispatcher((function(e,t){u.monoPlatform.invokeWhenHeapUnlocked((function(){return a.DotNet.invokeMethodAsync("Microsoft.AspNetCore.Components.WebAssembly","DispatchEvent",e,JSON.stringify(t))}))})),t=s.setPlatform(u.monoPlatform),window.Blazor.platform=t,window.Blazor._internal.renderBatch=function(e,t){y.profileStart("renderBatch");var n=u.monoPlatform.beginHeapLock();try{l.renderBatch(e,new c.SharedMemoryRenderBatch(t))}finally{n.release()}y.profileEnd("renderBatch")},n=window.Blazor._internal.navigationManager.getBaseURI,f=window.Blazor._internal.navigationManager.getLocationHref,window.Blazor._internal.navigationManager.getUnmarshalledBaseURI=function(){return BINDING.js_string_to_mono_string(n())},window.Blazor._internal.navigationManager.getUnmarshalledLocationHref=function(){return BINDING.js_string_to_mono_string(f())},window.Blazor._internal.navigationManager.listenForNavigationEvents((function(e,t){return r(_,void 0,void 0,(function(){return o(this,(function(n){switch(n.label){case 0:return[4,a.DotNet.invokeMethodAsync("Microsoft.AspNetCore.Components.WebAssembly","NotifyLocationChanged",e,t)];case 1:return n.sent(),[2]}}))}))})),[4,m.BootConfigResult.initAsync()];case 1:return b=C.sent(),[4,Promise.all([p.WebAssemblyResourceLoader.initAsync(b.bootConfig,e||{}),h.WebAssemblyConfigLoader.initAsync(b)])];case 2:g=i.apply(void 0,[C.sent(),1]),w=g[0],C.label=3;case 3:return C.trys.push([3,5,,6]),[4,t.start(w)];case 4:return C.sent(),[3,6];case 5:throw E=C.sent(),new Error("Failed to start platform. Reason: "+E);case 6:return t.callEntryPoint(w.bootConfig.entryAssembly),[2]}}))}))}window.Blazor.start=b,f.shouldAutoStart()&&b().catch((function(e){"undefined"!=typeof Module&&Module.printErr?Module.printErr(e):console.error(e)}))},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{u(r.next(e))}catch(e){i(e)}}function s(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,s)}u((r=r.apply(e,t||[])).next())}))},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]>2]}t.monoPlatform={start:function(e){return new Promise((function(t,n){var f,d;s.attachDebuggerHotkey(e),c.initializeProfiling((function(e){v("Microsoft.AspNetCore.Components","Microsoft.AspNetCore.Components.Profiling.WebAssemblyComponentsProfiling","SetCapturing")(e)})),window.Browser={init:function(){}},f=function(){window.Module=function(e,t,n){var c=this,f=e.bootConfig.resources,d=window.Module||{},p=["DEBUGGING ENABLED"];d.print=function(e){return p.indexOf(e)<0&&console.log(e)},d.printErr=function(e){console.error(e),u.showErrorNotification()},d.preRun=d.preRun||[],d.postRun=d.postRun||[],d.preloadPlugins=[];var h,y=e.loadResources(f.assembly,(function(e){return"_framework/"+e}),"assembly"),w=e.loadResources(f.pdb||{},(function(e){return"_framework/"+e}),"pdb"),E=e.loadResource("dotnet.wasm","_framework/dotnet.wasm",e.bootConfig.resources.runtime["dotnet.wasm"],"dotnetwasm");return e.bootConfig.resources.runtime.hasOwnProperty("dotnet.timezones.dat")&&(h=e.loadResource("dotnet.timezones.dat","_framework/dotnet.timezones.dat",e.bootConfig.resources.runtime["dotnet.timezones.dat"],"timezonedata")),d.instantiateWasm=function(e,t){return r(c,void 0,void 0,(function(){var n,r;return o(this,(function(o){switch(o.label){case 0:return o.trys.push([0,3,,4]),[4,E];case 1:return[4,b(o.sent(),e)];case 2:return n=o.sent(),[3,4];case 3:throw r=o.sent(),d.printErr(r),r;case 4:return t(n),[2]}}))})),[]},d.preRun.push((function(){i=cwrap("mono_wasm_add_assembly",null,["string","number","number"]),MONO.loaded_files=[],h&&function(e){r(this,void 0,void 0,(function(){var t,n;return o(this,(function(r){switch(r.label){case 0:return t="blazor:timezonedata",addRunDependency(t),[4,e.response];case 1:return[4,r.sent().arrayBuffer()];case 2:return n=r.sent(),l.loadTimezoneData(n),removeRunDependency(t),[2]}}))}))}(h),y.forEach((function(e){return _(e,function(e,t){var n=e.lastIndexOf(".");if(n<0)throw new Error("No extension to replace in '"+e+"'");return e.substr(0,n)+t}(e.name,".dll"))})),w.forEach((function(e){return _(e,e.name)})),window.Blazor._internal.dotNetCriticalError=function(e){d.printErr(BINDING.conv_string(e)||"(null)")},window.Blazor._internal.getSatelliteAssemblies=function(t){var n=BINDING.mono_array_to_js_array(t),i=e.bootConfig.resources.satelliteResources;if(i){var a=Promise.all(n.filter((function(e){return i.hasOwnProperty(e)})).map((function(t){return e.loadResources(i[t],(function(e){return"_framework/"+e}),"assembly")})).reduce((function(e,t){return e.concat(t)}),new Array).map((function(e){return r(c,void 0,void 0,(function(){return o(this,(function(t){switch(t.label){case 0:return[4,e.response];case 1:return[2,t.sent().arrayBuffer()]}}))}))})));return BINDING.js_to_mono_obj(a.then((function(e){return e.length&&(window.Blazor._internal.readSatelliteAssemblies=function(){for(var t=BINDING.mono_obj_array_new(e.length),n=0;n>1];var n},readInt32Field:function(e,t){return h(e+(t||0))},readUint64Field:function(e,t){return function(e){var t=e>>2,n=Module.HEAPU32[t+1];if(n>d)throw new Error("Cannot read uint64 with high order part "+n+", because the result would exceed Number.MAX_SAFE_INTEGER.");return n*f+Module.HEAPU32[t]}(e+(t||0))},readFloatField:function(e,t){return n=e+(t||0),Module.HEAPF32[n>>2];var n},readObjectField:function(e,t){return h(e+(t||0))},readStringField:function(e,t,n){var r,o=h(e+(t||0));if(0===o)return null;if(n){var i=BINDING.unbox_mono_obj(o);return"boolean"==typeof i?i?"":null:i}return p?void 0===(r=p.stringCache.get(o))&&(r=BINDING.conv_string(o),p.stringCache.set(o,r)):r=BINDING.conv_string(o),r},readStructField:function(e,t){return e+(t||0)},beginHeapLock:function(){return g(),p=new w},invokeWhenHeapUnlocked:function(e){p?p.enqueuePostReleaseAction(e):e()}};var m=document.createElement("a");function y(e){return e+12}function v(e,t,n){var r="["+e+"] "+t+":"+n;return BINDING.bind_static_method(r)}function b(e,t){return r(this,void 0,void 0,(function(){var n,r;return o(this,(function(o){switch(o.label){case 0:if("function"!=typeof WebAssembly.instantiateStreaming)return[3,4];o.label=1;case 1:return o.trys.push([1,3,,4]),[4,WebAssembly.instantiateStreaming(e.response,t)];case 2:return[2,o.sent().instance];case 3:return n=o.sent(),console.info("Streaming compilation failed. Falling back to ArrayBuffer instantiation. ",n),[3,4];case 4:return[4,e.response.then((function(e){return e.arrayBuffer()}))];case 5:return r=o.sent(),[4,WebAssembly.instantiate(r,t)];case 6:return[2,o.sent().instance]}}))}))}function g(){if(p)throw new Error("Assertion failed - heap is currently locked")}var w=function(){function e(){this.stringCache=new Map}return e.prototype.enqueuePostReleaseAction=function(e){this.postReleaseActions||(this.postReleaseActions=[]),this.postReleaseActions.push(e)},e.prototype.release=function(){var e;if(p!==this)throw new Error("Trying to release a lock which isn't current");for(p=null;null===(e=this.postReleaseActions)||void 0===e?void 0:e.length;){this.postReleaseActions.shift()(),g()}},e}()},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=window.chrome&&navigator.userAgent.indexOf("Edge")<0,o=!1;function i(){return o&&r}t.hasDebuggingEnabled=i,t.attachDebuggerHotkey=function(e){o=!!e.bootConfig.resources.pdb;var t=navigator.platform.match(/^Mac/i)?"Cmd":"Alt";i()&&console.info("Debugging hotkey: Shift+"+t+"+D (when application has focus)"),document.addEventListener("keydown",(function(e){var t;e.shiftKey&&(e.metaKey||e.altKey)&&"KeyD"===e.code&&(o?r?((t=document.createElement("a")).href="_framework/debug?url="+encodeURIComponent(location.href),t.target="_blank",t.rel="noopener noreferrer",t.click()):console.error("Currently, only Microsoft Edge (80+), or Google Chrome, are supported for debugging."):console.error("Cannot start debugging, because the application was not compiled with debugging enabled."))}))}},function(e,t,n){"use strict";var r=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,o,i=n.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(r=i.next()).done;)a.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return a};Object.defineProperty(t,"__esModule",{value:!0});var i=n(33),a=n(34);t.loadTimezoneData=function(e){var t,n,s=new Uint8Array(e),u=i.readInt32LE(s,0);s=s.slice(4);var l=a.decodeUtf8(s.slice(0,u)),c=JSON.parse(l);s=s.slice(u),Module.FS_createPath("/","zoneinfo",!0,!0),new Set(c.map((function(e){return e[0].split("/")[0]}))).forEach((function(e){return Module.FS_createPath("/zoneinfo",e,!0,!0)}));try{for(var f=r(c),d=f.next();!d.done;d=f.next()){var p=o(d.value,2),h=p[0],m=p[1],y=s.slice(0,m);Module.FS_createDataFile("/zoneinfo/"+h,null,y,!0,!0,!0),s=s.slice(m)}}catch(e){t={error:e}}finally{try{d&&!d.done&&(n=f.return)&&n.call(f)}finally{if(t)throw t.error}}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(18),o=function(){function e(e){this.batchAddress=e,this.arrayRangeReader=i,this.arrayBuilderSegmentReader=a,this.diffReader=s,this.editReader=u,this.frameReader=l}return e.prototype.updatedComponents=function(){return r.platform.readStructField(this.batchAddress,0)},e.prototype.referenceFrames=function(){return r.platform.readStructField(this.batchAddress,i.structLength)},e.prototype.disposedComponentIds=function(){return r.platform.readStructField(this.batchAddress,2*i.structLength)},e.prototype.disposedEventHandlerIds=function(){return r.platform.readStructField(this.batchAddress,3*i.structLength)},e.prototype.updatedComponentsEntry=function(e,t){return c(e,t,s.structLength)},e.prototype.referenceFramesEntry=function(e,t){return c(e,t,l.structLength)},e.prototype.disposedComponentIdsEntry=function(e,t){var n=c(e,t,4);return r.platform.readInt32Field(n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=c(e,t,8);return r.platform.readUint64Field(n)},e}();t.SharedMemoryRenderBatch=o;var i={structLength:8,values:function(e){return r.platform.readObjectField(e,0)},count:function(e){return r.platform.readInt32Field(e,4)}},a={structLength:12,values:function(e){var t=r.platform.readObjectField(e,0),n=r.platform.getObjectFieldsBaseAddress(t);return r.platform.readObjectField(n,0)},offset:function(e){return r.platform.readInt32Field(e,4)},count:function(e){return r.platform.readInt32Field(e,8)}},s={structLength:4+a.structLength,componentId:function(e){return r.platform.readInt32Field(e,0)},edits:function(e){return r.platform.readStructField(e,4)},editsEntry:function(e,t){return c(e,t,u.structLength)}},u={structLength:20,editType:function(e){return r.platform.readInt32Field(e,0)},siblingIndex:function(e){return r.platform.readInt32Field(e,4)},newTreeIndex:function(e){return r.platform.readInt32Field(e,8)},moveToSiblingIndex:function(e){return r.platform.readInt32Field(e,8)},removedAttributeName:function(e){return r.platform.readStringField(e,16)}},l={structLength:36,frameType:function(e){return r.platform.readInt16Field(e,4)},subtreeLength:function(e){return r.platform.readInt32Field(e,8)},elementReferenceCaptureId:function(e){return r.platform.readStringField(e,16)},componentId:function(e){return r.platform.readInt32Field(e,12)},elementName:function(e){return r.platform.readStringField(e,16)},textContent:function(e){return r.platform.readStringField(e,16)},markupContent:function(e){return r.platform.readStringField(e,16)},attributeName:function(e){return r.platform.readStringField(e,16)},attributeValue:function(e){return r.platform.readStringField(e,24,!0)},attributeEventHandlerId:function(e){return r.platform.readUint64Field(e,8)}};function c(e,t,n){return r.platform.getArrayEntryPtr(e,t,n)}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{u(r.next(e))}catch(e){i(e)}}function s(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,s)}u((r=r.apply(e,t||[])).next())}))},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1](assembliesToLoadDotNetArray); const lazyAssemblies = resourceLoader.bootConfig.resources.lazyAssembly; - if (lazyAssemblies) { - const resourcePromises = Promise.all(assembliesToLoad - .filter(assembly => lazyAssemblies.hasOwnProperty(assembly)) + 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."); + } + + var assembliesMarkedAsLazy = assembliesToLoad.filter(assembly => lazyAssemblies.hasOwnProperty(assembly)); + + if (assembliesMarkedAsLazy.length != assembliesToLoad.length) { + var notMarked = assembliesToLoad.filter(assembly => !assembliesMarkedAsLazy.includes(assembly)); + throw new Error(`${notMarked.join()} must be marked with 'BlazorWebAssemblyLazyLoad' item group in your project file to allow lazy-loading.`); + } + + const resourcePromises = Promise.all(assembliesMarkedAsLazy .map(assembly => resourceLoader.loadResource(assembly, `_framework/${assembly}`, lazyAssemblies[assembly], 'assembly')) .map(async resource => (await resource.response).arrayBuffer())); @@ -345,8 +354,6 @@ function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourceLoade return resourcesToLoad.length; })); } - return BINDING.js_to_mono_obj(Promise.resolve(0)); - } }); module.postRun.push(() => { diff --git a/src/Components/WebAssembly/WebAssembly/src/Hosting/WebAssemblyHostBuilder.cs b/src/Components/WebAssembly/WebAssembly/src/Hosting/WebAssemblyHostBuilder.cs index 02477205502c..a65e4117cd1c 100644 --- a/src/Components/WebAssembly/WebAssembly/src/Hosting/WebAssemblyHostBuilder.cs +++ b/src/Components/WebAssembly/WebAssembly/src/Hosting/WebAssemblyHostBuilder.cs @@ -130,7 +130,7 @@ private WebAssemblyHostEnvironment InitializeEnvironment(WebAssemblyJSRuntimeInv /// /// Gets the logging builder for configuring logging services. /// - public ILoggingBuilder Logging { get; } + public ILoggingBuilder Logging { get; } /// /// Registers a instance to be used to create the . @@ -189,7 +189,7 @@ internal void InitializeDefaultServices() Services.AddSingleton(DefaultWebAssemblyJSRuntime.Instance); Services.AddSingleton(WebAssemblyNavigationManager.Instance); Services.AddSingleton(WebAssemblyNavigationInterception.Instance); - Services.AddSingleton(provider => new LazyAssemblyLoader(provider)); + Services.AddSingleton(new LazyAssemblyLoader(DefaultWebAssemblyJSRuntime.Instance)); Services.AddLogging(builder => { builder.AddProvider(new WebAssemblyConsoleLoggerProvider(DefaultWebAssemblyJSRuntime.Instance)); }); diff --git a/src/Components/WebAssembly/WebAssembly/src/Services/LazyAssemblyLoader.cs b/src/Components/WebAssembly/WebAssembly/src/Services/LazyAssemblyLoader.cs index 07f35c236efc..60a633b4ca14 100644 --- a/src/Components/WebAssembly/WebAssembly/src/Services/LazyAssemblyLoader.cs +++ b/src/Components/WebAssembly/WebAssembly/src/Services/LazyAssemblyLoader.cs @@ -9,7 +9,6 @@ using System.Runtime.InteropServices; using System.Runtime.Loader; using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; using Microsoft.JSInterop; using Microsoft.JSInterop.WebAssembly; @@ -20,19 +19,18 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Services /// /// Supports finding pre-loaded assemblies in a server or pre-rendering context. /// - public class LazyAssemblyLoader + public sealed class LazyAssemblyLoader { internal const string GetDynamicAssemblies = "window.Blazor._internal.getLazyAssemblies"; internal const string ReadDynamicAssemblies = "window.Blazor._internal.readLazyAssemblies"; - private List _loadedAssemblyCache = new List(); + private readonly IJSRuntime _jsRuntime; + private readonly Dictionary _loadedAssemblyCache; - private readonly IServiceProvider _provider; - - public LazyAssemblyLoader(IServiceProvider provider) + public LazyAssemblyLoader(IJSRuntime jsRuntime) { - _provider = provider; - _loadedAssemblyCache = AppDomain.CurrentDomain.GetAssemblies().ToList(); + _jsRuntime = jsRuntime; + _loadedAssemblyCache = AppDomain.CurrentDomain.GetAssemblies().ToDictionary(assembly => assembly.GetName().Name + ".dll", assembly => assembly); } /// @@ -53,39 +51,47 @@ public async Task> LoadAssembliesAsync(IEnumerable return await LoadAssembliesInServerAsync(assembliesToLoad); } - private Task> LoadAssembliesInServerAsync(IEnumerable assembliesToLoad) + private async Task> LoadAssembliesInServerAsync(IEnumerable assembliesToLoad) { - var loadedAssemblies = _loadedAssemblyCache.Where(assembly => - assembliesToLoad.Contains(assembly.GetName().Name + ".dll")); + var loadedAssemblies = new List(); - if (loadedAssemblies.Count() != assembliesToLoad.Count()) + try + { + foreach (var assemblyName in assembliesToLoad) + { + loadedAssemblies.Add(Assembly.Load(Path.GetFileNameWithoutExtension(assemblyName))); + } + } + catch (FileNotFoundException ex) { - var unloadedAssemblies = assembliesToLoad.Except(loadedAssemblies.Select(a => a.GetName().Name + ".dll")); - throw new InvalidOperationException($"Unable to find the following assemblies: {string.Join(",", unloadedAssemblies)}. Make sure that the appplication is referencing the assemblies and that they are present in the output folder."); + throw new InvalidOperationException($"Unable to find the following assembly: {ex.FileName}. Make sure that the appplication is referencing the assemblies and that they are present in the output folder."); } - return Task.FromResult(loadedAssemblies); + return await Task.FromResult(loadedAssemblies); } private async Task> LoadAssembliesInClientAsync(IEnumerable assembliesToLoad) { - var jsRuntime = _provider.GetRequiredService(); - // Only load assemblies that haven't already been lazily-loaded - var newAssembliesToLoad = assembliesToLoad.Except(_loadedAssemblyCache.Select(a => a.GetName().Name + ".dll")); + // Check to see if the assembly has already been loaded and avoids reloading it if so. + // Note: in the future, as an extra precuation, we can call `Assembly.Load` and check + // to see if it throws FileNotFound to ensure that an assembly hasn't been loaded + // between when the cache of loaded assemblies was instantiated in the constructor + // and the invocation of this method. + var newAssembliesToLoad = assembliesToLoad.Except(_loadedAssemblyCache.Keys); var loadedAssemblies = new List(); - var count = (int)await ((WebAssemblyJSRuntime)jsRuntime).InvokeUnmarshalled>( - GetDynamicAssemblies, - assembliesToLoad.ToArray(), - null, - null); + var count = (int)await ((WebAssemblyJSRuntime)_jsRuntime).InvokeUnmarshalled>( + GetDynamicAssemblies, + newAssembliesToLoad.ToArray(), + null, + null); if (count == 0) { return loadedAssemblies; } - var assemblies = ((WebAssemblyJSRuntime)jsRuntime).InvokeUnmarshalled( + var assemblies = ((WebAssemblyJSRuntime)_jsRuntime).InvokeUnmarshalled( ReadDynamicAssemblies, null, null, @@ -99,7 +105,7 @@ private async Task> LoadAssembliesInClientAsync(IEnumerabl // into the default app context. var loadedAssembly = AssemblyLoadContext.Default.LoadFromStream(new MemoryStream(assembly)); loadedAssemblies.Add(loadedAssembly); - _loadedAssemblyCache.Add(loadedAssembly); + _loadedAssemblyCache.Add(loadedAssembly.GetName().Name + ".dll", loadedAssembly); } return loadedAssemblies; diff --git a/src/Components/test/E2ETest/Tests/WebAssemblyLazyLoadTest.cs b/src/Components/test/E2ETest/Tests/WebAssemblyLazyLoadTest.cs index 828127854d5c..8076ae61dc6b 100644 --- a/src/Components/test/E2ETest/Tests/WebAssemblyLazyLoadTest.cs +++ b/src/Components/test/E2ETest/Tests/WebAssemblyLazyLoadTest.cs @@ -111,6 +111,21 @@ public void CanLazyLoadAssemblyWithRoutes() Assert.True(renderedElement.Displayed); } + [Fact] + public void ThrowsErrorForUnavailableAssemblies() + { + // Navigate to a page with lazy loaded assemblies for the first time + SetUrlViaPushState("/Other"); + var app = Browser.MountTestComponent(); + + // Should've thrown an error for unhandled error + var errorUiElem = Browser.Exists(By.Id("blazor-error-ui"), TimeSpan.FromSeconds(10)); + Assert.NotNull(errorUiElem); + + + AssertLogContainsCriticalMessages("DoesNotExist.dll must be marked with 'BlazorWebAssemblyLazyLoad' item group in your project file to allow lazy-loading."); + } + private string SetUrlViaPushState(string relativeUri) { var pathBaseWithoutHash = ServerPathBase.Split('#')[0]; @@ -145,5 +160,18 @@ private void AssertLogDoesNotContainCriticalMessages(params string[] messages) }); } } + + void AssertLogContainsCriticalMessages(params string[] messages) + { + var log = Browser.Manage().Logs.GetLog(LogType.Browser); + foreach (var message in messages) + { + Assert.Contains(log, entry => + { + return entry.Level == LogLevel.Severe + && entry.Message.Contains(message); + }); + } + } } } diff --git a/src/Components/test/testassets/BasicTestApp/RouterTest/TestRouterWithLazyAssembly.razor b/src/Components/test/testassets/BasicTestApp/RouterTest/TestRouterWithLazyAssembly.razor index ced83679de87..ccdd22f2b5d4 100644 --- a/src/Components/test/testassets/BasicTestApp/RouterTest/TestRouterWithLazyAssembly.razor +++ b/src/Components/test/testassets/BasicTestApp/RouterTest/TestRouterWithLazyAssembly.razor @@ -1,6 +1,6 @@ @using Microsoft.AspNetCore.Components.Routing @using System.Reflection -@using Microsoft.AspNetCore.Components.WebAssembly.Services +@using Microsoft.AspNetCore.Components.WebAssembly.Services @inject LazyAssemblyLoader lazyLoader @@ -31,25 +31,24 @@ private async Task LoadAssemblies(string uri) { - try + if (uri.EndsWith("WithLazyAssembly")) { - if (uri.EndsWith("WithLazyAssembly")) - { - Console.WriteLine($"Loading assemblies for WithLazyAssembly..."); - var assemblies = await lazyLoader.LoadAssembliesAsync(new List() { "Newtonsoft.Json.dll" }); - lazyLoadedAssemblies.AddRange(assemblies); - } - - if (uri.EndsWith("WithLazyLoadedRoutes")) - { - Console.WriteLine($"Loading assemblies for WithLazyLoadedRoutes..."); - var assemblies = await lazyLoader.LoadAssembliesAsync(new List() { "LazyTestContentPackage.dll" }); - lazyLoadedAssemblies.AddRange(assemblies); - } + Console.WriteLine($"Loading assemblies for WithLazyAssembly..."); + var assemblies = await lazyLoader.LoadAssembliesAsync(new List() { "Newtonsoft.Json.dll" }); + lazyLoadedAssemblies.AddRange(assemblies); } - catch (Exception e) + + if (uri.EndsWith("WithLazyLoadedRoutes")) { - Console.WriteLine($"Error when loading assemblies: {e}"); + Console.WriteLine($"Loading assemblies for WithLazyLoadedRoutes..."); + var assemblies = await lazyLoader.LoadAssembliesAsync(new List() { "LazyTestContentPackage.dll" }); + lazyLoadedAssemblies.AddRange(assemblies); + } + + if (uri.EndsWith("Other")) { + Console.WriteLine($"Loading assemblies for Other..."); + var assemblies = await lazyLoader.LoadAssembliesAsync(new List() { "DoesNotExist.dll" }); + lazyLoadedAssemblies.AddRange(assemblies); } } } From f98d0a4e5e5f116f46639de772ba92a53f4b9d29 Mon Sep 17 00:00:00 2001 From: Safia Abdalla Date: Wed, 22 Jul 2020 11:14:03 -0700 Subject: [PATCH 2/2] Address feedback from peer review --- .../WebAssembly/src/Services/LazyAssemblyLoader.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Components/WebAssembly/WebAssembly/src/Services/LazyAssemblyLoader.cs b/src/Components/WebAssembly/WebAssembly/src/Services/LazyAssemblyLoader.cs index 60a633b4ca14..74e6ee705f21 100644 --- a/src/Components/WebAssembly/WebAssembly/src/Services/LazyAssemblyLoader.cs +++ b/src/Components/WebAssembly/WebAssembly/src/Services/LazyAssemblyLoader.cs @@ -25,12 +25,12 @@ public sealed class LazyAssemblyLoader internal const string ReadDynamicAssemblies = "window.Blazor._internal.readLazyAssemblies"; private readonly IJSRuntime _jsRuntime; - private readonly Dictionary _loadedAssemblyCache; + private readonly HashSet _loadedAssemblyCache; public LazyAssemblyLoader(IJSRuntime jsRuntime) { _jsRuntime = jsRuntime; - _loadedAssemblyCache = AppDomain.CurrentDomain.GetAssemblies().ToDictionary(assembly => assembly.GetName().Name + ".dll", assembly => assembly); + _loadedAssemblyCache = AppDomain.CurrentDomain.GetAssemblies().Select(a => a.GetName().Name + ".dll").ToHashSet(); } /// @@ -51,7 +51,7 @@ public async Task> LoadAssembliesAsync(IEnumerable return await LoadAssembliesInServerAsync(assembliesToLoad); } - private async Task> LoadAssembliesInServerAsync(IEnumerable assembliesToLoad) + private Task> LoadAssembliesInServerAsync(IEnumerable assembliesToLoad) { var loadedAssemblies = new List(); @@ -67,7 +67,7 @@ private async Task> LoadAssembliesInServerAsync(IEnumerabl throw new InvalidOperationException($"Unable to find the following assembly: {ex.FileName}. Make sure that the appplication is referencing the assemblies and that they are present in the output folder."); } - return await Task.FromResult(loadedAssemblies); + return Task.FromResult>(loadedAssemblies); } private async Task> LoadAssembliesInClientAsync(IEnumerable assembliesToLoad) @@ -77,7 +77,7 @@ private async Task> LoadAssembliesInClientAsync(IEnumerabl // to see if it throws FileNotFound to ensure that an assembly hasn't been loaded // between when the cache of loaded assemblies was instantiated in the constructor // and the invocation of this method. - var newAssembliesToLoad = assembliesToLoad.Except(_loadedAssemblyCache.Keys); + var newAssembliesToLoad = assembliesToLoad.Where(assembly => !_loadedAssemblyCache.Contains(assembly)); var loadedAssemblies = new List(); var count = (int)await ((WebAssemblyJSRuntime)_jsRuntime).InvokeUnmarshalled>( @@ -105,7 +105,7 @@ private async Task> LoadAssembliesInClientAsync(IEnumerabl // into the default app context. var loadedAssembly = AssemblyLoadContext.Default.LoadFromStream(new MemoryStream(assembly)); loadedAssemblies.Add(loadedAssembly); - _loadedAssemblyCache.Add(loadedAssembly.GetName().Name + ".dll", loadedAssembly); + _loadedAssemblyCache.Add(loadedAssembly.GetName().Name + ".dll"); } return loadedAssemblies;