SEPURI-SAI-KRISHNA opened a new pull request, #21735:
URL: https://github.com/apache/echarts/pull/21735

   ## Brief Information
   
   This pull request is in the type of:
   
   - [x] bug fixing
   - [ ] new feature
   - [ ] others
   
   
   
   ### What does this PR do?
   
   Fixes two crashes in the tree series: rendering a tree with no laid-out 
nodes, and removing several nodes in one update.
   
   
   
   ### Fixed issues
   
   <!-- No existing issue; found while auditing tree update paths. -->
   
   
   ## Details
   
   ### Before: What was the problem?
   
   Two independent crashes, both hit by ordinary tree data updates.
   
   **1. A tree with no nodes to lay out throws.**
   
   ```js
   chart.setOption({series: [{type: 'tree', data: []}]});
   ```
   
   ```
   TypeError: Cannot read properties of null (reading '0')
       at legacyCopyOverallTrans (src/coord/View.ts:567)
       at viewCoordSysUpdateOverallTrans (src/coord/View.ts:548)
       ...
       at TreeView._updateViewCoordSys (src/chart/tree/TreeView.ts)
   ```
   
   `_updateViewCoordSys` collects node positions and computes their extent:
   
   ```js
   const min: number[] = [];
   const max: number[] = [];
   bbox.fromPoints(points, min, max);
   ```
   
   `bbox.fromPoints` returns immediately without writing anything when `points` 
is
   empty, so `min` and `max` stay empty arrays. `max[0] - min[0]` is then 
`NaN`, the
   existing zero-size corrections below only test `=== 0` so they never fire, 
and the
   dataRect handed to the view coordinate system is `NaN`. That makes the 
resulting
   matrix non-invertible, `matrix.invert` returns `null`, and 
`legacyCopyOverallTrans`
   dereferences it.
   
   This is not only the literal `data: []` case — it also covers a tree whose 
nodes
   have no valid layout yet, e.g. rendering before an async fetch resolves, or 
after
   filtering the data down to nothing.
   
   **2. Removing several nodes in one update throws.**
   
   ```js
   chart.setOption({animation: false, series: [{type: 'tree', data: 
fullTree}]});
   // drop a subtree
   chart.setOption({series: [{type: 'tree', data: smallerTree}]}, true);
   ```
   
   ```
   TypeError: Cannot read properties of null (reading '__edge')
       at removeNodeEdge (src/chart/tree/TreeView.ts:590)
       at removeNode (src/chart/tree/TreeView.ts:690)
       at DataDiffer._remove
   ```
   
   `removeNodeEdge` guards its own node's graphic element but not its source's:
   
   ```js
   const symbolEl = data.getItemGraphicEl(node.dataIndex) as TreeSymbol;
   if (!symbolEl) {
       return;
   }
   const sourceSymbolEl = data.getItemGraphicEl(source.dataIndex) as TreeSymbol;
   const sourceEdge = sourceSymbolEl.__edge;   // <- source may already be gone
   ```
   
   `removeNode` sets `data.setItemGraphicEl(dataIndex, null)` in the removal 
callback.
   With `animation: false` that callback runs synchronously, so when a batch of 
nodes
   is removed the source node's element is frequently already `null` by the 
time its
   children's edges are cleaned up.
   
   This one is independent of the empty-data case: it fires whenever removed 
nodes
   include a parent, even when the resulting tree is not empty (dropping a 
subtree, or
   collapsing back to just the root).
   
   ### After: How does it behave after the fixing?
   
   1. `min`/`max` are seeded when there is no valid point — from the previous 
extent if
      there is one (the mechanism already used for the collapsed-root case), 
otherwise
      from zero. The existing zero-size corrections then expand it into a 
usable rect,
      so the view transform stays invertible.
   2. `sourceSymbolEl` is guarded exactly like `symbolEl` immediately above it.
      `sourceEdge` is only used as a fallback and everything downstream is 
already
      behind `if (edge)`, so a missing source simply means there is no edge to 
remove.
   
   Emptying a tree, refilling it, and removing subtrees all work with animation 
on and off.
   
   
   
   ## Document Info
   
   One of the following should be checked.
   
   - [x] This PR doesn't relate to document changes
   - [ ] The document should be updated later
   - [ ] The document changes have been made in apache/echarts-doc#xxx
   
   
   
   ## Misc
   
   ### Security Checking
   
   - [ ] This PR uses security-sensitive Web APIs.
   
   ### ZRender Changes
   
   - [ ] This PR depends on ZRender changes (ecomfe/zrender#xxx).
   
   ### Related test cases or examples to use the new APIs
   
   Added `test/ut/spec/series/treeUpdate.test.ts`, covering an initially empty 
tree, a
   tree emptied after having data, removing a subtree, removing all but the 
root, and
   refilling an empty tree — with `animation` both `false` and `true`.
   
   On `master` the empty-data cases fail regardless of animation, and the 
node-removal
   cases fail with `animation: false`. The `animation: true` removal cases pass 
before
   and after, and are kept to document that the timing of the removal callback 
is what
   exposes the second bug.
   
   `npm run test`, `npx tsc --noEmit` and `eslint` on the changed file all pass.
   
   ### Merging options
   
   - [x] Please squash the commits into a single one when merging.
   
   ### Other information
   
   `src/chart/tree/TreeView.ts` is also touched by #18491, #21603 and #21681. 
Those
   changes are in different functions from the two guards here, though 
whichever lands
   first may need a trivial rebase.
   
   Both crashes end in the same place from a user's point of view — clearing or
   shrinking tree data — so they are fixed together rather than split across 
two PRs
   that would conflict in the same file.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to