Feature/webcomponents support#362
Open
IlianaB wants to merge 8 commits into
Open
Conversation
IlianaB
force-pushed
the
feature/webcomponents-support
branch
from
July 8, 2026 07:47
bced311 to
182fa6c
Compare
Extends the UI5 Inspector to detect and inspect UI5 Web Components-based applications, alongside existing classic OpenUI5/SAPUI5 support. Pages using both frameworks show a merged control tree. New files: - app/vendor/WebComponentsToolsAPI.js: introspection API for web components (tree walking, properties, slots, events) using element.constructor.getMetadata() - app/scripts/injected/detectWebComponents.js: page-context detection script - app/scripts/content/detectWebComponents.js: content script for detection and message bridging between background and the MAIN-world injected script - app/scripts/injected/webcMain.js: MAIN-world script handling get-initial-information-webc, do-control-select, do-control-property-change, with debounced MutationObserver for live tree updates Modified: - app/manifest.json: register detectWebComponents content script and add WebComponentsToolsAPI.js to web_accessible_resources - app/scripts/background/main.js: add do-webc-injection handler that uses chrome.scripting.executeScript with world: 'MAIN' (bypasses page CSP) - app/scripts/devtools/panel/ui5/main.js: WebC message handlers (on-webc-detected, on-receiving-initial-data-webc, etc.), merged tree rendering, dynamic 'Aggregations' to 'Slots' tab rename for pure WebC apps - app/html/panel/ui5/index.html: overlay text mentions UI5 Web Components Private members (prefixed with _) are filtered out of properties, slots, and events to keep the panel focused on the public API.
- Detect web components via element.isUI5Element === true (the framework's own getter) instead of a tag-prefix + getMetadata check. - Read framework version from meta.Runtimes[0].version, the JS property the runtime sets on the meta element. - Resolve slotted content via element[slotData.propertyName || slotName], which is how the framework exposes slot assignments. Fixes the Slots tab, which was previously always empty. - Walk the prototype chain to find the framework-applied default value for a property; fall back to type-based defaults. Improves the isDefault flag for non-empty default strings (e.g. 'None'). - Read event detail metadata (eventData.detail) and surface param types in the Events tab. - Send applicationInformation alongside the WebC initial data so the Application Info tab is no longer blank for pure WebC apps. Classic UI5 takes precedence when both frameworks are present, since it provides richer info.
Send the controlActions payload in the structure the DataView expects
({ actions: { data: [...] }, own: { options: { controlId } } }) so the
buttons are rendered. Add message handlers for do-control-focus,
do-copy-control-to-console, and do-control-copy-html. Invalidate is
omitted since web components re-render automatically on property and
attribute changes.
Each handler guards on WebCToolsAPI.getElementById so it no-ops on
classic UI5 ids, avoiding double-handling on mixed pages.
…hlighter Right-click + 'Inspect UI5 element' did not select web components in the tree, and hovering a tree row did not highlight the element on the page. Both stem from the same root cause: the classic mousedown handler walks up looking for data-sap-ui (which web components don't have) and the classic highlighter resolves elements via document.getElementById (which only matches DOM ids, not the framework-assigned _id). - Add a parallel mousedown handler in webcMain.js that walks up looking for isUI5Element === true and reports element._id. - Add an on-control-tree-hover handler in webcMain.js that resolves the id via WebCToolsAPI and positions a highlighter overlay. - Refactor modules/content/highLighter.ts from a singleton-with-id-lookup to a factory-with-element. Each caller resolves the id itself (document.getElementById for classic, WebCToolsAPI for webc) and passes an Element. The factory accepts a wrapperId option so multiple instances on the same page do not collide. Update the highLighter spec to cover the new API. - Some web components (e.g. ui5-breadcrumbs-item) are light-DOM data carriers with zero rect; their visible representation is rendered inside the parent's shadow root with id '<itemId>-<suffix>'. Add a helper that walks up to the shadow host and resolves a target with a real layout box. - Rename the context menu label from 'Inspect UI5 control' to 'Inspect UI5 element', since 'control' is SAPUI5 terminology while the menu now also covers web components.
IlianaB
force-pushed
the
feature/webcomponents-support
branch
from
July 8, 2026 08:10
182fa6c to
a2e3ad8
Compare
- Tighten shadow-root id match in _findVisibleInShadow: previously '[id^=ui5wc_1]' also matched ui5wc_10, ui5wc_100, etc.; now requires an exact match or a '-<suffix>' continuation. - Make the synthetic '__webc_root__' tree node non-selectable: its on-select and on-hover handlers in the panel no-op when the id is the WebC group root, since it has no element on the page. - Drop the dead 'target._id || target.id' fallback in the right-click handler. UI5Element's _id is a guaranteed getter, so the fallback is unreachable; using target._id directly makes the assumption explicit. - Document the precedence rule used to populate the App Info tab on mixed pages (classic UI5 wins because it provides richer info than the WebC equivalent). - Add an orientation block comment at the top of webcMain.js describing the MAIN-world placement, message-bridging path, and action-name conventions, so a reviewer can navigate the file without piecing the flow together.
Web Components has no declared defaultValue in metadata. Class field initializers compiled to ES2022 land on the instance, so we cannot reliably distinguish the framework default from a user-set value via prototype-chain inspection. The previous heuristic produced misleading results (e.g. selectionMode='None' shown as non-default; '' unconditionally treated as the string default). Stop emitting isDefault and remove the helper that approximated it. DataView already omits the '(default)' badge when the field is absent, so the UI silently loses the indicator rather than displaying wrong information. The structure is reversible: a future implementation can snapshot defaults by sampling document.createElement(tag) per tag at startup.
Previously the App Info tab for pure WebC pages only showed a single 'General' section (framework name, version, user agent, URL). The framework exposes far more through meta.Runtimes[0] (see packages/base/src/Runtimes.ts). Surface what is available, in dedicated sections: - General: framework name, version, runtime description, user agent, application URL. - Configuration: theme, themeRoot, baseTheme, language, timezone, animationMode, calendarType, secondaryCalendarType, noConflict, defaultFontLoading, enableDefaultTooltips, firstDayOfWeek, legacyDateCalendarCustomizing, ignoreUrlParams. - Registered tags (collapsed by default): all ui5-* tags the framework knows about, with a count in the section title. - Registered features (collapsed by default): feature module names. - Interop: openUI5Detected and openUI5LoadedFirst, when reported. - Runtimes: shown when more than one runtime is active on the page, with alias and description per entry. Each section is built by a small standalone function that returns null when there's nothing to report, so the orchestrator stays simple and the section list is open for extension. Add a comment in webcMain.js noting that message payload shapes (event.detail.target vs event.detail.data.controlId etc.) vary per action because they're determined by the panel side, mirroring injected/main.js.
The previous implementation built the section data as an object with numeric string keys (1, 2, 3, ...). DataView sorts object keys alphabetically by default, which placed '10' before '2', '100' before '20', etc. — visually scrambling the list. Emit the data as an array instead: DataView preserves array index order. Also sort entries alphabetically before emission so a 124-tag list is easy to scan. Applies to registered tags, registered features, and the (rarely populated) runtimes section.
IlianaB
force-pushed
the
feature/webcomponents-support
branch
from
July 8, 2026 09:02
a2e3ad8 to
2f215c1
Compare
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.
Extends the UI5 Inspector to detect and inspect UI5 Web Components-based applications, alongside the existing OpenUI5/SAPUI5 support. Pages using either framework — or both — show a merged control tree with per-framework introspection.
What's implemented
Detection. Pages using @ui5/webcomponents are detected automatically alongside classic UI5 detection. Mixed pages report both.
Control tree. Web components are listed alongside classic UI5 controls. On mixed pages the two are merged under a single tree, with the WebC portion grouped under a synthetic root labelled with the framework name and version. Private members (names beginning with _) are filtered from properties, slots, and events to keep the panel focused on the public API. Tree updates on DOM changes are debounced (150 ms) to collapse rapid bursts.
Properties tab. Reads property metadata via element.constructor.getMetadata() and current values from the live element. Editable inline (writes back via element[name] = value).
Slots tab. On pure WebC pages the "Aggregations" tab label is renamed to "Slots". Slotted content is resolved via element[slotData.propertyName || slotName] (how the framework itself exposes slot assignments), so nested elements are surfaced with their _ids.
Events tab. Lists declared events; when an event's metadata declares a detail shape, param types are reported.
Actions tab. Focus, Copy to Console, Copy HTML to Console. Invalidate is intentionally omitted — web components re-render automatically on property/attribute changes.
App Info tab (pure WebC). General, Configuration (theme, language, timezone, animation mode, calendar type, etc.), Registered tags, Registered features, Interop (OpenUI5 detection), Runtimes (when more than one is active). Data comes from meta.Runtimes[0] (packages/base/src/Runtimes.ts). Long lists (registered tags, features) are alphabetised and emitted as arrays so DataView preserves order.
Right-click "Inspect UI5 element" in the page selects the corresponding row in the tree. The context menu label was renamed from "Inspect UI5 control" since "control" is SAPUI5 terminology.
Tree hover highlight overlays the visible element on the page. Some components (e.g. ui5-breadcrumbs-item) are light-DOM data carriers with zero rect; the highlighter walks up to the shadow root and resolves the visible representation by the framework's - convention.
Architecture
The existing 4-layer communication (panel ↔ background ↔ content script ↔ page-injected script) was fully reusable. New pieces:
Script injection uses chrome.scripting.executeScript({world: 'MAIN'}) for the WebC scripts, bypassing page CSP that would block <script src> injection. This was required to support strict-CSP hosts (e.g. Fiori shell). Classic UI5 still uses the older <script src> approach.
Panel changes
Shared highlighter refactor
modules/content/highLighter.ts was refactored from a singleton with id-based lookup to a factory taking a resolved element:
Known limitations (deferred)
Two things intentionally not implemented in this PR:
= "Button"), which are erased at compile time. The runtime metadata contains no enum information, and the framework does not expose enum members on any global. There is no runtime path to recover the valid values. Options considered:For now the value is still editable as free text; the user just has to know the valid values.
Tested against