You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
piral-core and piral-ng: 0.15.5 (any 0.15 version should do).
OS: tested on Win10 and Linux Mint
Browser: tested with latest Edge and Firefox
Description and steps to reproduce
Scenario:
There is an Angular pilet using piral-ng that provides components from different modules all defined using defineNgModule.
For easy reproducibility load one extension from each module into the shell.
Perform an action that unloads one of the extension slots.
piral-ng will not only correctly destroy that component and the now unused module, but also all other Angular modules loaded via piral-ng.
The other extension slot's DOM will be empty, since the Angular component got wrongly unloaded.
Trying to unload that other extension as well, will result in a hard React crash, since React still thinks that the component is loaded.
Expected behavior
When all components of an Angular module go out of scope, only that module should be unloaded.
Actual behavior
All Angular modules and components will be unloaded/unmounted.
Analysis
This is the code called when a piral-ng component is to be unmounted:
Looking closely at this, you'll notice that platformBrowserDynamic by default always returns the same instance!
That means that destroying the platform of one module, you'll destroy the platform of all modules, actually destroying every Angular component and module that's loaded.
Possible Solutions
1. The easy but dumb solution
Let everything just run on a single platform and don't destroy it.
This has a lot of bad implications for performance and sandboxing of the pilets and probably isn't really worth much.
2. The intended way
From looking at the code, I can guess that it was intended for every module to run on its own platform.
With the help of a bunch of Angular internals (namely ALLOW_MULTIPLE_PLATFORMS as seen above) one can enable multi-platform behavior for the platform factory.
Since I've already gotten all the way there, I'm going to submit a pull request for this solution shortly.
The text was updated successfully, but these errors were encountered:
Bug Report
Prerequisites
Environment Details and Version
Reproducible with:
Description and steps to reproduce
Scenario:
There is an Angular pilet using
piral-ng
that provides components from different modules all defined usingdefineNgModule
.For easy reproducibility load one extension from each module into the shell.
Expected behavior
When all components of an Angular module go out of scope, only that module should be unloaded.
Actual behavior
All Angular modules and components will be unloaded/unmounted.
Analysis
This is the code called when a piral-ng component is to be unmounted:
piral/src/converters/piral-ng/src/module.ts
Lines 74 to 85 in 143d72e
This method correctly tries to tear down the module if no other component instances of that module are left.
The
teardown
method looks like this:piral/src/converters/piral-ng/src/startup.ts
Lines 55 to 66 in 143d72e
The code tries to unload the platform of the currently running module, which is also technically correct.
But what are the platforms used?
piral/src/converters/piral-ng/src/startup.ts
Lines 16 to 21 in 143d72e
They are
platformBrowserDynamic
platforms which looks ok at first too.However, looking at Angular's implementation reveals the following:
https://github.com/angular/angular/blob/2fc5b70fcedb8ac35b825b245c0ae394dc125244/packages/platform-browser-dynamic/src/platform-browser-dynamic.ts#L33-L34
https://github.com/angular/angular/blob/2fc5b70fcedb8ac35b825b245c0ae394dc125244/packages/core/src/application_ref.ts#L272-L293
Looking closely at this, you'll notice that
platformBrowserDynamic
by default always returns the same instance!That means that destroying the platform of one module, you'll destroy the platform of all modules, actually destroying every Angular component and module that's loaded.
Possible Solutions
1. The easy but dumb solution
Let everything just run on a single platform and don't destroy it.
This has a lot of bad implications for performance and sandboxing of the pilets and probably isn't really worth much.
2. The intended way
From looking at the code, I can guess that it was intended for every module to run on its own platform.
With the help of a bunch of Angular internals (namely
ALLOW_MULTIPLE_PLATFORMS
as seen above) one can enable multi-platform behavior for the platform factory.Since I've already gotten all the way there, I'm going to submit a pull request for this solution shortly.
The text was updated successfully, but these errors were encountered: