fix(runtime): skip generated ids in auto-prefix-id + View.createId bridge (closes #9) - #10
Merged
Merged
Conversation
Previously, when a JSX view's createContent() threw (sync or async), the error propagated as a rejected Promise but was never written to the UI5 Log. In the showcase it was only rendered as a text control, invisible to log-scraping tooling and sap-ui-log-level debugging. The fix patches View.prototype.onControllerConnected (not createContent, which is bypassed by subclass dynamic dispatch) to install a per-instance wrapper on this.createContent before calling the original method. The wrapper opens the JSX scope (withScope), wraps the subclass call in try/catch plus .catch() for async, calls Log.error on failure, then re-throws — preserving all existing propagation behaviour. The instance own-property is deleted in a finally block so the prototype chain is fully restored after each view construction. ExploreSample.tsx also adds Log.error calls in both its catch handlers (demo-view load failure and docs-load failure) so the exact user-facing message is traceable in the log. Two QUnit regression tests verify both the sync-throw and async-reject paths: Log.error is called exactly once with the right message and component id, and View.create still rejects. Also brings runtime/forwarded-aggregation.qunit.ts from the fix/forwarded-aggregation-issue-9 branch (was missing on main).
…nstruction
Controls like sap.m.Menu declare their default aggregation (items) as
forwarded to an internal wrapper control created in init() and resolved
by id at add-time. Passing children via new Type({items}) made
applySettings attempt the lookup before the wrapper was registered,
crashing with a TypeError (issue #9).
The runtime now detects a forwarded default aggregation via
metadata.getAggregation(name)?.forwarding and defers concrete children
to a post-construction addAggregation loop, matching XMLView behaviour.
String-binding and template children are not affected.
- Add getAggregation() to the ControlMetadata structural type (plugin.ts)
- Patch the concrete-children branch in runtime.ts
- Add QUnit regression test (forwarded-aggregation.qunit.ts)
- Add ForwardedMenu showcase example (button menu + List contextMenu)
petermuessig
force-pushed
the
fix/forwarded-aggregation-issue-9
branch
from
September 9, 2026 15:00
3ceea55 to
a9c0438
Compare
3 tasks
…loses #9) UI5's View.onControllerConnected uses runWithPreprocessors to apply view.createId as the id-preprocessor for all ManagedObjects constructed inside createContent(). Controls like sap.m.Menu create internal helpers (MenuWrapper) whose ids are derived from an auto-generated parent id (e.g. "__menu0-menuWrapper"). With getAutoPrefixId() === true, these derived- generated ids were being run through view.createId(), making them unresolvable when the aggregation forwarder later looked them up by id. The fix is in two layers: 1. installViewScopeBridge: shadows view.createId with a guard that calls ManagedObjectMetadata.isGeneratedId and returns the id unchanged when it matches the generated-id pattern (starts with or contains the UID prefix, default "__"). This guards the runWithPreprocessors path — internal control ids stay stable regardless of the view's autoPrefixId setting. 2. runtime.ts: adds the same isGeneratedId guard to the explicit view.createId() call in the JSX auto-prefix-id block so JSX-authored id props are only prefixed when they are statically supplied by the app developer. Also reverts the incorrect "forwarded aggregation" deferral (defaultAggForwarded + post-construction addAggregation) that was a symptom-level workaround for the same root cause.
Merged
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.
Root cause
UI5's
View.onControllerConnectedusesrunWithPreprocessorsto applyview.createIdas the id-preprocessor for allManagedObjectconstructors invoked insidecreateContent(). Controls likesap.m.Menucreate internal helpers (MenuWrapper) whose ids are derived from a parent auto-generated id (e.g."__menu0-menuWrapper"). WithgetAutoPrefixId() === true, those derived-generated ids were run throughview.createId(), making them unresolvable when the aggregation forwarder later looked them up by id →TypeError: Cannot read properties of … (reading 'addItem').Fix
Two complementary guards, both using
ManagedObjectMetadata.isGeneratedId:installViewScopeBridge.ts— shadowsview.createIdwith a guarded version for the duration ofonControllerConnected. When therunWithPreprocessorsid-preprocessor callsview.createId("__menu0-menuWrapper"), the guard returns the id unchanged. The shadow is cleaned up infinallyalongside thecreateContentshadow.runtime.ts— adds the sameisGeneratedIdguard to our explicitview.createId()call in the JSX auto-prefix-id block so JSX-authoredidprops are only prefixed when they are statically supplied by the developer.Also reverts the incorrect "forwarded aggregation" deferral (
defaultAggForwarded+ post-constructionaddAggregation) that was an incorrect symptom-level workaround for the same root cause, and removes the correspondinggetAggregationaddition from theControlMetadataSPI type.Also included (folded in from #11)
installViewScopeBridge.ts: wrapscreateContent()inwithScope({ view })and logs errors viaLog.error(sync + async)view-error-logging.qunit.ts: regression tests for the error-logging pathExploreSample.tsxin the showcase:Log.errorin both catch blocksTests
All 12 suites green (53/53):
runtime/forwarded-aggregationruntime/auto-prefix-idruntime/view-error-logging