fix(elements): strip Blazor externalObject from expression tree events - 21.2.x#17252
fix(elements): strip Blazor externalObject from expression tree events - 21.2.x#17252IMinchev64 wants to merge 1 commit into21.2.xfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Fixes interop/serialization issues caused by Blazor-injected externalObject properties leaking into emitted expression tree payloads, ensuring expression-tree-related events and comparisons don’t break when externalObject is present.
Changes:
- Ignore
externalObjectduring Query Builder tree comparison to prevent unnecessary root group recreation / serialization issues. - Sanitize Angular Elements output events for filtering/expression trees by stripping
externalObjectfrom emitted trees.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| projects/igniteui-angular/query-builder/src/query-builder/query-builder-tree.component.ts | Adds externalObject to the set of ignored properties during JSON-based tree comparisons. |
| projects/igniteui-angular-elements/src/app/custom-strategy.ts | Adds event-specific sanitization for expression-tree outputs and introduces stripExternalObject traversal. |
| for (const operand of tree?.filteringOperands ?? []) { | ||
| if ('operator' in operand) { | ||
| this.stripExternalObject(operand); | ||
| continue; | ||
| } | ||
|
|
||
| delete (operand.condition as any)?.externalObject; | ||
|
|
||
| if ((operand as IFilteringExpression).searchTree) { | ||
| this.stripExternalObject(operand.searchTree); | ||
| } | ||
| } |
There was a problem hiding this comment.
stripExternalObject currently only deletes externalObject from operand.condition. The Blazor workaround elsewhere in the repo treats externalObject as a generic non-serializable key (e.g. JSON stringify replacers), so this may leave externalObject on other nodes (tree/operands/searchTree) and still break event serialization. Consider stripping externalObject from every visited object in the expression tree (including tree nodes and expressions), ideally using a visited set to avoid potential cycles from wrapper-injected references.
| for (const operand of tree?.filteringOperands ?? []) { | |
| if ('operator' in operand) { | |
| this.stripExternalObject(operand); | |
| continue; | |
| } | |
| delete (operand.condition as any)?.externalObject; | |
| if ((operand as IFilteringExpression).searchTree) { | |
| this.stripExternalObject(operand.searchTree); | |
| } | |
| } | |
| this.stripExternalObjectFromNode(tree, new WeakSet<object>()); | |
| } | |
| protected stripExternalObjectFromNode(value: unknown, visited: WeakSet<object>): void { | |
| if (!value || typeof value !== 'object') { | |
| return; | |
| } | |
| if (visited.has(value)) { | |
| return; | |
| } | |
| visited.add(value); | |
| delete (value as { externalObject?: unknown }).externalObject; | |
| if (Array.isArray(value)) { | |
| for (const item of value) { | |
| this.stripExternalObjectFromNode(item, visited); | |
| } | |
| return; | |
| } | |
| for (const nestedValue of Object.values(value)) { | |
| this.stripExternalObjectFromNode(nestedValue, visited); | |
| } |
Closes https://github.com/Infragistics-Developer-Tools/dev-tools/issues/3208
Description
Motivation / Context
Type of Change (check all that apply):
Component(s) / Area(s) Affected:
How Has This Been Tested?
Test Configuration:
Screenshots / Recordings
Checklist:
feature/README.MDupdates for the feature docsREADME.MDCHANGELOG.MDupdates for newly added functionalityng updatemigrations for the breaking changes (migrations guidelines)