Skip to content

WorkspaceToDOM Includes Insertion Markers #2322

@amber-cd

Description

@amber-cd

Problem statement

If workspaceToDom is called while an insertion marker is visible, the insertion marker is included and can become a 'real' block.

Expected Behavior

workspaceToDom should ignore insertion markers, as they are UI only.

Actual Behavior

If workspaceToDom is called while an insertion marker is visible, the insertion marker is included and can become a 'real' block.

Steps to Reproduce

This is probably a bit of a tough one to run into 'in the wild'... we ran into it due to a timing issue with Blockly as nested in a React component where we run workspaceToDom in order to save the XML to the store, then repopulate the workspace from that 'changed' XML before the insertion marker can be deleted. However, to verify the issue, I believe you can just do:

  1. Add a listener to the workspace to run workspaceToDom when it changes.
  2. Begin dragging the child out of a top-level block
  3. While the insertion marker is still visible, check the output of workspaceToDom.

(This may require a bit of playing around... we specifically encountered it by dragging the block and holding it for a little while.)

Operating System and Browser

  • Desktop Chrome

I expect it applies to other browsers, but haven't tested it.

Additional Information

I realize this is a pretty obscure scenario that only really occurs in scenarios like ours wherein we use React to try to make Blockly behave like a controlled component; however, I do believe this still constitutes a legitimate bug.

I nearly just made a PR to fix this, but I wanted advice on whether it would be accepted/whether this was an appropriate solution. For the record, my fix is just a simple fix to workspaceToDom to skip insertion markers:

Blockly.Xml.workspaceToDom = function(workspace, opt_noId) {
  var xml = Blockly.Xml.utils.createElement('xml');
  var variablesElement = Blockly.Xml.variablesToDom(
      Blockly.Variables.allUsedVarModels(workspace));
  if (variablesElement.hasChildNodes()) {
    xml.appendChild(variablesElement);
  }
  var comments = workspace.getTopComments(true);
  for (var i = 0, comment; comment = comments[i]; i++) {
    xml.appendChild(comment.toXmlWithXY(opt_noId));
  }
  var blocks = workspace.getTopBlocks(true);
  for (var i = 0, block; block = blocks[i]; i++) {
    if (!block.isInsertionMarker_) {
      xml.appendChild(Blockly.Xml.blockToDomWithXY(block, opt_noId));
    }
  }
  return xml;
};

We may wind up just implementing this in our own fork, but I wanted to run it by you guys first to see if this was something you wanted a fix for and/or if my fix is appropriate or if there would be a more appropriate one.

Metadata

Metadata

Labels

issue: bugDescribes why the code or behaviour is wrong

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions