[Google Blockly] keep variables in sync between workspaces #58780
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.
Recently, two related bug reports came in where Sprite Lab projects were behaving strangely due to variable blocks. My investigation led to the discovery of a few related bugs:
score
in on the main workspace, then not find it on the modal workspace. If they created it a second time there, it would conflict and throw an error.Custom Variables Category
We customize the variable category to provide our own button/prompt for creating variables and to make sure that blocks from the level XML get merged with the auto-populated blocks driven by the variable map. When we added this to Google Blockly, we only added it to the main workspace, which resulted in this inconsistent experience:
Main Workspace:
Editor workspace:
Expected custom prompt:
Unexpected prompt:
Fixing this was just a matter of calling
registerToolboxCategoryCallback
on the editor workspace.Duplicate block ids from toolbox blocks
If the toolbox XML for a block includes an ID, Blockly will try to give preserve it for the first block created on that workspace. Once the id is in use on that workspace, it will randomly generate new ones. We needed Blockly to preserve this functionality for us because we use these hard-coded block ids for UI tests that involve dragging blocks out of the toolbox. However, if this is done in the modal editor it has the potential to cause problems. Steps:
Because the block from step 2 is no longer on the editor workspace, Blockly doesn't detect the conflict so it allow the id to be used. The block create event is then mirrored to the hidden workspace, which fails because a block with that id already exists. The subsequent block event is also mirror to the hidden workspace, which "succeeds" by moving the first block into the new position intended for the second block. Now, if you re-open the first function, the expected block has disappeared.
I considered several alternatives here, but ultimately what worked was just to strip block ids out of the toolbox string before injecting the editor workspace. This should be fine because we don't have any UI tests for the modal editor that rely upon the static block id.
Mirroring variable events
Currently, on staging, we mirror events in the following ways:
The first rule is needed so that we can create the right procedure call blocks and so that functions and behaviors are still defined on the main workspace. The second rule is needed so that our source of truth for definitions (ie. the hidden workspace) is always kept up to date.
What's missing from the system is proper mirroring of variable events. With Blockly, all variables are created within the global scope. We concatenate the generated code from the main and hidden workspace, so it shouldn't matter which workspace is active when a variable is created. If a variable is created (or renamed or deleted) from the main workspace, we should do the same thing on both the editor and hidden workspaces (and vice versa).
To solve this problem, we need mirror these events from the main workspace to both other workspaces. I did this via a new change listener. We also need to mirror from the modal editor workspace to both the main and hidden workspaces. For the first case, I just latched onto where we were already mirroring procedure events. For the second case, we were already handling this sufficiently because variable events are non-UI events.
The results of the changes here are variables can now be managed on either workspace and will stay in sync. If blocks are dragged out which reference a certain variable, it will either be found on that workspace's map (and all of them) or it will be created. And toolboxes will be stripped of block ids so that we don't continue having issues with duplicate block ids being used on the hidden workspace.
Full Bug Reports
The first was reported by @cnbrenci. From the ticket:
Cassi added on Slack:
This screenshot shows a reproduction of the affected user's project, now working as expected:
The second was reported by @molly-moen. From the ticket:
This screenshot demonstrates that the bug described above has been fixed:
Links
Jira: https://codedotorg.atlassian.net/browse/CT-573
Slack thread: https://codedotorg.slack.com/archives/C05DK21DAHK/p1715971343769239
Zendesk tickets:
Broken user project: https://studio.code.org/projects/spritelab/6bBUKGra5IGR_JIpK8I-tr5Fvc-CUjGwoDkCzOzczMQ/view
Testing story
Deployment strategy
Follow-up work
Privacy
Security
Caching
PR Checklist: