commandHandler.pasteSelection() not working after update from 2.2.7 to 3.0.16

Hi, not so long ago we updated gojs from 2.2.7 to 3.0.16 which went very smoothly :). But I just realized there were some slight issues that are probably implicitly because of our implementation. But basically, when we call

diagram.commandHandler.pasteSelection(diagram.lastInput.documentPoint);

it throws an exception in code that isn’t ours

(go-debug.mjs:15 Uncaught TypeError: Cannot read properties of null (reading 'iterator')). 

and pane-center:124 for clarification:

if you’re wondering about the .get() part:

export default class NullWrapper<T> {
  private value: T | null = null;

  get(): T {
    if (this.value === null) {
      throw new ValueError('NullWrapper: value is null');
    }
    return this.value;
  }

  set(value: T): void {
    this.value = value;
  }

  reset(): void {
    this.value = null;
  }
}

(I’m not entirely sure why this was implemented, but it shouldn’t matter much considering that diagram is not null)

We have a diagram listener on ‘ClipboardChanged’ which verifies that the copying part went well, but the pasting does not.

Let me know what I’d need to create a better idea of what is happening here. Thanks in advance.

nvm, I fixed this by fixing ctrl click dragging which was also broken. Not sure how to close this item.

What was the problem with control-dragging (i.e. copying)?
I think there was a real bug in the library involving a rarely-null reference in DraggingTool that we fixed in 3.0.18. Wait – maybe that was in 3.0.16. Still, you might want to get the latest (3.0.18 at this moment) while you are doing development.

The problem was rather interesting, but easily fixable on our side.

For some clarification:

This is our model

export class Model extends go.GraphLinksModel {
  constructor(makeUniqueNodeKeyFunction: (base: string) => string) {
    super();

    this.nodeKeyProperty = 'id';
    this.linkKeyProperty = '_key';

    this.linkFromKeyProperty = '_from';
    this.linkFromPortIdProperty = '_fromPort';
    this.linkToKeyProperty = '_to';
    this.linkToPortIdProperty = '_toPort';

    //todo: figure out how to not use this suppression
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    this.makeUniqueLinkKeyFunction = (_: any, ld: any) => this.getKeyForLinkData2(ld);
    this.makeUniqueKeyFunction = (_: DiagramModel, nd: ObjectData) => makeUniqueNodeKeyFunction(nd.descriptionName);
  }

The makeUniqueKeyFunction was the issue. Before it was this:

    this.makeUniqueKeyFunction = (_: DiagramModel, nd: ObjectData) => makeUniqueNodeKeyFunction(nd.id);

Our ids are basically descriptionName + instance count

Our nodeData interface

export interface NodeData extends EntityInstance {
  _layerName: string;
  _location: go.Point;
  _angle: number;
  _isNonRoot: boolean;
  _category: string;
}

// and its parent

export interface EntityInstance {
  descriptionName: string;
  displayName: string;
  id: string;
  parentId: string;
  pose: Readonly<Pose>;
  properties: Readonly<Properties>;
}

But for some reason, ‘id’ is undefined… But ONLY from this makeUniqueKeyFunction call, it’s weird. So when it was called for both copying and pasting and or control dragging copying. It broke.

As I said, we did some magic by getting the description name from the id by splitting it up so in the long term the solution/fix I made is more than fine. But it’s still interesting.

now when I change

   this.nodeKeyProperty = 'anythingelse';

This happens:

Pretty odd right? Haha.

ps: this is on gojs 3.0.18

The GoJS library never sets the “id” property on anything unless, for model data, you have set the Model.nodeKeyProperty or GraphLinksModel.linkKeyProperty to “id”. Or you have set Model.makeUniqueKeyFunction or GraphLinksModel.makeUniqueLinkKeyFunction to a function that sets “id”.

So I’m wondering if there is some other code that might be setting the “id” property.

mayhaps, it’s still odd that changing the GOjs code changes the behaviour. I’ll look into it further at a later moment.