feat(browser-only): add static extension support - #17966
Open
robertjndw wants to merge 9 commits into
Open
Conversation
…ckend Adds `toPluginUri` for plugin assets read through the `FileService` (color themes, icon themes, icon fonts), which need a scheme to resolve against, and `encodePluginAssetPath` to re-encode an already decoded path so names with `#`, `?` or `%` survive a round trip. Moves the plugin path constants out of `main/node` so the browser-only frontend can share them, and adds the `frontend` plugin host id. Signed-off-by: Robert Jandow <robert@jandow.de>
One plugin whose manifest cannot be loaded - a 404 on `package.json`, say - used to reject the whole `Promise.all` and take every other plugin down with it. Each plugin is now prepared in isolation and a failure only skips that one. Because the host can now skip a plugin, `$start` reports back which ones it skipped so the frontend stops reporting them as started, activated or stopped. Skipped plugins go back to `LOADED` so a later load cycle can retry them. Also gives a plugin with no entry point a real manifest: it contributes only grammars, themes and the like, but still turns up in `theia.extensions`, where reading `packageJSON` must not throw. Signed-off-by: Robert Jandow <robert@jandow.de>
Adds the browser-only counterparts of the backend plugin services, bound through a new `frontendOnly` entry point: - `FrontendHostedPluginServer` / `FrontendPluginServer` serve the statically deployed plugins bundled into the application. - `FrontendPluginPathService` derives the log, global and workspace storage paths that the backend would otherwise hand out, guarding the shared session log folder with a Web Lock. - `HostedPluginFileSystemProvider` reads `hostedPlugin:` assets over HTTP. Declarative-only plugins are deployed on the `frontend` host: without a backend, the host inferred for them never answers and every RPC to it hangs, saving included. Signed-off-by: Robert Jandow <robert@jandow.de>
With a backend, icon fonts and icon themes sit in the extracted VSIX and their paths are cut at the `extension` segment. Browser-only addresses them as `hostedPlugin:/<id>/<path>`, where everything past the plugin id already is the path relative to the plugin root, so both shapes now resolve. Encodes those paths per segment as well, so `/` stays literal and asset names containing `#`, `?` or `%` are not mangled. Signed-off-by: Robert Jandow <robert@jandow.de>
…ookups There is no backend to run a shell in, so `TerminalFrontendContribution` is rebound to a browser-only subclass. Rebinding the contribution rather than only `TerminalService` redirects every contribution point bound with `toService(TerminalFrontendContribution)` - UI commands, profiles, and the `TerminalService` token used by plugins, tasks and debug. `VSXExtension` also resolved the registry URI eagerly in `@postConstruct`, firing one doomed request per extension in the list. It is now resolved lazily in `getRegistryLink`, the only method that needs it. Signed-off-by: Robert Jandow <robert@jandow.de>
Co-authored-by: Stefan Dirix <sdirix@eclipsesource.com> Signed-off-by: Robert Jandow <robert@jandow.de>
Signed-off-by: Robert Jandow <robert@jandow.de>
Contributor
Author
|
@sdirix took me ages, but finally managed to find some time to fix the regression and update the original code 😅 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What it does
Reopens #14776 on a rebased branch. That PR has since been split in two: the build-time half, preparing the plugins via
@theia/plugin-utils, landed separately in #17758, so what is left here is the runtime side, i.e. actually running those prepared plugins in a browser-only application.@theia/plugin-extand@theia/terminalnow contributefrontendOnlymodules:FrontendHostedPluginServerserves the plugins the build prepared, fromlib/frontend/hostedPlugin/list.json. Adopters who keep their plugin metadata somewhere the build can't see can bindPluginLocalOptionsand supply it themselves.FrontendPluginServerkeeps the plugin key-value storage behindglobalState/workspaceStatein the browser storage. Install, uninstall, enable and disable reject, since there is no backend to deploy anything at runtime. Writes are serialized through the Web Locks API so two tabs don't clobber each other, with a per-realm mutex as fallback where that API isn't available.FrontendPluginPathServiceresolves the plugin log and storage directories under the config directory, and prunes old session log folders the way the backend does.HostedPluginFileSystemProviderserves thehostedPlugin:scheme read-only over HTTP, for the assets that are read through theFileService: color themes, icon themes and icon fonts.BrowserOnlyTerminalFrontendContributionstubs out the terminal. It rebindsTerminalFrontendContributionrather than onlyTerminalService, because the terminal module binds all of its contribution points viatoServiceon that class, so rebinding just the service would miss most callers.A few plugin host fixes were needed along the way that aren't browser-only specific:
package.json, say) rejected the wholePromise.allin the web worker host and took every other plugin down with it. Failures are now isolated and logged per plugin.$startreports back which plugins the host skipped, so the frontend stops counting them as started and can pick them up again on a later load cycle.rawModelgetter that throws. They do show up intheia.extensions, where readingpackageJSONmust not throw, so they now get a real manifest.PluginIconServiceandPluginIconThemeServicecan resolve icon fonts fromhostedPlugin:URIs, not just from extracted VSIX paths.VSXExtensionresolves the registry URI lazily instead of in@postConstruct. It was requested eagerly for every extension in the list, which in browser-only meant one request per extension that was known to fail.One breaking change: the browser-only
EnvVariablesServerstub returned''fromgetConfigDirUri().new URI('')resolves tofile:///, so in practice all application state was written to the OPFS root, next to the user's own folders, and the UTF-8 encoding override applied to the entire file tree. It now returnsfile:///.theia, matching the backend's default configuration folder. What that means for existing deployments is written up indoc/Migration.md.How to test
The Typescript language tools are a good real-world check, they exercise a plugin with a frontend entry point as well as declarative contributions:
npm run download:pluginsnpm run build:browser-onlynpm run start:browser-only, then openlocalhost:3000builtin.tsfile. Syntax highlighting and completion should workglobalStateshould still be thereOpening a terminal should tell you terminals aren't supported instead of failing with an error, and the application should start without terminal errors in the log.
Follow-ups
module is undefined, thrown from inside their own bundled code in statements likemodule.exports = i. Deployment and loading themselves work, so this looks like a bundling issue on the extension side. Worth investigating separately./.theiaconfig directory automatically. If that turns out to matter for adopters, a one-time migration on first run could be added.Breaking changes
Attribution
Review checklist
nlsservice (for details, please see the Internationalization/Localization section in the Coding Guidelines)Reminder for reviewers