Repository navigation
fix(dia.Element): keep port ids that differ only in type apart - #3546
Merged
kumilingus merged 8 commits intoOct 12, 2026
Merged
Conversation
Index ports, their metrics and rendered port nodes by the id itself (Map)
instead of a plain object, so `hasPort('5')` no longer answers for a port
with id `5` and ports `5` and `'5'` can coexist. Removing a port no longer
keeps links to a removed port whose id stringifies like a remaining one.
Also handle port id `0` in `getPort()`, `getPointFromConnectedLink()` and
the `multiLinks` validation, keep non-integer numeric port ids in
`getLinkEnd()`, and accept numeric port ids in the port method typings.
Closes clientIO#3544
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`findProxyNode()` and the `useModelGeometry` connection points read the `port` attribute as a string, which no longer matches a numeric port id now that ports are indexed by the id itself. Read it through a shared `_findPortId()` helper that honours `port-id-type`, as `getLinkEnd()` did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kumilingus
reviewed
Oct 12, 2026
kumilingus
reviewed
Oct 12, 2026
Port metrics are keyed by the port id in a Map, which `getGroupPortsMetrics()` started returning. Keep the public method returning a plain object for backwards compatibility and read the Map internally through `_getGroupPortsMetrics()`. Merge the port lookup changesets into one entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`getGroupPortsMetrics()` is neither typed nor documented, so return the Map keyed by the port id directly instead of a plain object wrapper. Note on `getPortsPositions()` that it should return a Map in the next major version. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Type port ids as `Element.Port.ID` (`string | number`), as cell ids are typed as `Cell.ID`, in the `dia.Element` port methods, `ElementView.findPortNode(s)()` and `generatePortId()`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kumilingus
requested changes
Oct 12, 2026
Replace the `Element.Port.ID` namespace with an `Element.PortID` alias of `Cell.ID`, so cell and port ids share one type. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Expose the helper without the underscore, typed and marked internal (not documented) for now, as `Paper.requestCellViewInsertion()` is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kumilingus
approved these changes
Oct 12, 2026
…major Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kumilingus
approved these changes
Oct 12, 2026
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.
Description
Fixes #3544
Ports are now indexed by the id itself (
Map) rather than by its string form, so a numeric port id and a string one are two different ports everywhere - asgetPortIndex(),portProp()and theport-id-typeDOM round trip already assumed:PortData- the port index (portsMap) and the per-group port metrics (getGroupPortsMetrics(), which is neither typed nor documented, now returns thatMap)ElementView- the rendered port nodes cache (_portElementsCache)_processRemovedPort()- the set of removed ports whose links get removedTwo ports
5and'5'on one element now coexist instead of overwriting each other in these indexes.Port ids read back from the DOM go through a new
CellView.findNodePortId()(typed, internal and not documented for now), which restores a numeric id from theport-id-typeattribute.getLinkEnd()did this already;ElementView.findProxyNode()and theuseModelGeometryconnection points used the raw string attribute and relied on the old stringified index.Related fixes in the same area:
0was treated as "no port" inElement.getPort(),Element.getPointFromConnectedLink()and themultiLinksvalidationgetLinkEnd()truncated a non-integer numeric port id (parseInt->Number), e.g.1.5became1dia.Element.PortID(an alias ofdia.Cell.ID, so cell and port ids share one type) types the port id parameters of thedia.Elementport methods,ElementView.findPortNode(s)()andgeneratePortId().Port.iditself is unchanged (string), as widening it would be type-breaking - aTODOmarks it to becomeElement.PortIDin the next major version;insertPort(before)is unchanged, as a number there is an indexKnown limitation:
getPortsPositions()keeps returning a plain object (its typed public return value), so ports whose ids differ only in type overwrite each other in its result. ATODOmarks it to return aMapin the next major version.Motivation and Context
PortDatakeyed ports by a plain object, sohasPort(),getPort()and the port geometry methods answered for a port that was never asked for ('5'for5), disagreeing withgetPortIndex()/portProp(), which compare with===.Behaviour change worth noting: callers that stringify a numeric port id before passing it back (e.g. read it from a DOM attribute by hand, from JSON or a URL) no longer match the port. The changeset says port ids are matched by value and type.
Tests
port ids of different typesmodule intest/jointjs/elementPorts.js(11 tests) - each fails without the changeElement.PortIDchecked intest/ts/index.test.tskarma:jointpasses apart from two failures that are Windows-specific and present onmaster(util.breakText ellipsis, a float rounding in the port labelmatrix(...)string);test:tsand lint pass🤖 Generated with Claude Code