-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue with mirroring workspace #8225
Comments
fwiw this occurs in both v11.0.0 and v11.1.1 so it's not related to the disappearing input blocks. |
See also #7950. |
Root cause analysis (part I)Initially I knew the following (true) facts:
It therefore seemed logical that the solution would be to have I had actually begun making this change when I decided to do a little additional refactoring: specifically, pulling the connection-saving code out of The purpose of this (saving the connections on the clause blocks, and keeping them updated) is so that rearranging clause blocks in the mutator bubble will correspondingly rearrange the blocks connected to the Relevant to this issue is the fact that such rearrangements cannot be conveyed only via
and no sequence of such mutations can convey information about how to reorder connected blocks, so if such changes are to be mirrored they must be mirrored by another mechanism—and in fact they are. Playing around with the mirror demo further (after refining its logging code) demonstrated that in fact reconfiguring the In fact, after further playing around with various combinations of mutations—making a longer and longer This was very surprising, so I traced the execution of the reproduction case from the point that Why is this Further tracing revealed an interesting situation: at the time FIRE_QUEUE = [
/* 0: BlockMove */ {
blockId: "GHBo}8?anH~0O3/k#)9E",
newCoordinate: {x: 85.49684143066406, y: 120.89669799804688},
newInputName: undefined,
newParentId: undefined,
oldCoordinate: undefined,
oldInputName: "ELSE",
oldParentId: "R((cl0jw+oRvjZJ9JT}l",
reason: ['disconnect'],
},
/* 1: BlockMove */ {
blockId: "GHBo}8?anH~0O3/k#)9E",
newCoordinate: undefined,
newInputName: "ELSE",
newParentId: "R((cl0jw+oRvjZJ9JT}l",
oldCoordinate: {x: 85.49684143066406, y: 120.89669799804688},
oldInputName: undefined,
oldParentId: undefined,
reason: ['connect'],
},
/* 2: BlockChange */ {
blockId: "R((cl0jw+oRvjZJ9JT}l",
element: "mutation",
name: undefined
newValue: '{"elseIfCount":1,"hasElse":true}',
oldValue: '{"hasElse":true}',
}
} Well: that's not ideal: I'd expect So it looks like the two So, It appears that the actual cause of the failure reported in this issue is that the // Move mutation events to the top of the queue.
// Intentionally skip first event.
for (let i = 1, event; (event = queue[i]); i++) {
// AnyDuringMigration because: Property 'element' does not exist on type
// 'Abstract'.
if (
event.type === CHANGE &&
(event as AnyDuringMigration).element === 'mutation'
) {
queue.unshift(queue.splice(i, 1)[0]);
}
} This code first appears in 5578458, merged in PR #298. I have not so far been able to establish whether this was actually created to fix the emit-order issue or if it just happend to do so coincidentally. (The null-event filtering was added later, in PR #1398, attempting to fix issue #1373 that had resulted from changes made in PR #1205 to address the fact that the previous filter routine had been O(n^2) due to use of |
Root cause analysis (part II)The ultimate root cause of this issue, and the reason the private recomposeSourceBlock() {
// ...
this.sourceBlock.compose(this.rootBlock);
// ...
eventUtils.fire(/* BlockChange */, this.sourceBlock, 'mutation', /* ... */);
// ...
} The block's |
Possible remediesThere are three principle categories of fixes that could be applied to this issue. Emitting events in correct orderThis would seem to be the most elegant and notionally correct approach. The tricky thing is how to arrange for blocks'
In any case it should be possible to remove the existing post-filtering reorder hack from the Fix reordering of events between emission and executionThis would entail updating the
Introduce separate block method for reconnectionCurrently
Advantages:
Disadvantages:
(This option suggested by @BeksOmega.) Fix event reordering and introduce separate reconnect methodThis would take a belt-and-braces approach by doing both of the two previous options.
|
Summary of discussion in the team meeting:
I propose adding the block method first, since that is the less risky approach and definitely fixes the problem (for the library blocks, at least), and then looking at fixing the reordering code, and then attempting to improve the reordering code (after ensuring it has sufficient test coverage to reduce the likelihood of regression). |
Making note of some additional discoveries that have been made since I wrote up the above: It looks like issue #7026 and PR #7069 are related related to this, insofar as they deal with unexpected consequences of the way filtering currently works. There are some key insights there which are relevant to deciding how to proceed here:
My thoughts about this:
I am currently investigating what happens if I remove all of the filtering code. |
This has been adequately patched for the time being by the (new, higher quality) bandaid in #8539, but the underlying root cause remains and is tracked in #1036. |
Check for duplicates
Description
When all mirroring events from one workspace to another, I expect both workspaces to be identical. But when an "else if" is added to an "if" block, it is possible for the two workspace to differ.
The problem can be reproduced on https://google.github.io/blockly-samples/examples/mirror-demo/, and I have also verified it on my own application where I can confirmed that all events are being mirrored.
Reproduction steps
Stack trace
No response
Screenshots
No response
Browsers
No response
The text was updated successfully, but these errors were encountered: