Skip to content

Project dirty state fixes #1962

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

Merged
merged 7 commits into from
Feb 5, 2019
Merged

Project dirty state fixes #1962

merged 7 commits into from
Feb 5, 2019

Conversation

kchadha
Copy link
Contributor

@kchadha kchadha commented Jan 29, 2019

Proposed Changes

Depends on #1941 (and currently the diff includes changes from that PR).

@chrisgarrity and I worked on all of these changes together.

Fix erroneous project changed state reporting.

This PR starts to decouple emitting a targets update from emitting a project changed.
Prior to this PR, we were erroneously emitting a project changed state in the following cases:

  1. Loading a project
  2. Running a project (scratch 2.0 did not consider running a project to change the dirty state of a project, this also includes clicking a block in the toolbox or on a sprite's workspace).
  3. Switching from project page to editor mode
  4. Switching sprites

The above scenarios were getting triggered by emitting project changes in the following scenarios:

  1. during vm.clear() (which happens during load project),
  2. during renaming a sprite whether or not such a change occurred (also happens during project load), 3) when receiving any scratch blocks event in a blocks container that can affect the project (e.g. blocks containers for actual sprites but not blocks containers for the flyout or monitors).
  3. during runtime._step() which is always running (before/during/after project load)

After investigating and comparing the cases in which Scratch 2.0 and Scratch 3.0 track dirty state, we decided to resolve these issues by:

  1. No longer emitting project state changes from runtime._step()
  2. No longer emitting project state changes from vm.clear()
  3. Being more specific about when blocks events emit project changes (e.g. we check if an actual change took place in the VM rather than just upon receiving an event). This doesn't resolve all of our issues since we have some scenarios in which switching sprites still causes a project change because we're effectively deleting a block and recreating that block in the VM. This is a known issue we hope to address in a future PR.
  4. As a side effect of removing emitting project changes from runtime._step, we now specifically track project changes that were previously being emitted as a side effect (e.g. adding a sprite, adding a costume, etc. -- all the changes in src/virtual-machine.js)
  5. changing renameSprite() to only emit a project change/targets update if an actual rename occurred.

Test Coverage

Added lots of unit tests and an integration test. Also did lots of manual testing!
We have documented our investigation and manual testing in the following doc. We have also documented some known issues in the doc.

https://docs.google.com/document/d/1DKM4rf-ajioOrAeipsgtuIluJNMIo71L3MfgB84y3JE/edit

Changes can be tested at https://llk.github.io/scratch-gui/project-state-changes

Copy link
Contributor

@rschamp rschamp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this looks great, thanks for all the tests! I don't think this necessarily has to change before merging, there were just more than a few questions/suggestions.

@@ -564,7 +582,8 @@ class Blocks {
// Changing the value in a dropdown
block.fields[args.name].value = args.value;

if (!optRuntime){
if (!this.runtime){
log.warn('Runtime is not optional, it should get passed in when the block container is created.');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this check should be farther up (and fatal) or can just be removed altogether. We assume it exists above... and all over the place elsewhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rschamp, I think you're right. We had this check from before updating tests to resolve #1942 and this can probably be updated now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

@@ -592,7 +611,8 @@ class Blocks {
block.mutation = mutationAdapter(args.value);
break;
case 'checkbox': {
if (!optRuntime) {
if (!this.runtime) {
log.warn('Runtime is not optional, it should get passed in when the block container is created.');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

@@ -663,6 +683,10 @@ class Blocks {
}
}

// TODO maybe track actual changes,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this super hard to figure out in this pass?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I had actually put this in here as a note to myself to see whether we needed to track actual changes or if this was good enough. I think in general it is usually rare that we would receive a change event from scratch-blocks where a change did not occur. This is unlike the other cases (create, move, delete) where we get the respective events from scratch-blocks but effectively no change occurs in the VM.

I don't think it's possible to get a change event for a block without some user interaction with the block. @picklesrus, I would be interested to know, can you think of scenarios where this would happen?

I think I'll probably remove this TODO comment.

}
if (projectVersion === 3) {
return this._addSprite3(validatedInput[0], validatedInput[1]);
return this._addSprite3(validatedInput[0], validatedInput[1])
.then(() => this.runtime.emitProjectChanged());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we reject in case of neither of these, can't we put this in the next then()? I.e. chained to .then(validatedInput =>...).then(/* here? */)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that makes sense! Good catch!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

this.runtime.on(Runtime.TARGETS_UPDATE, () => {
this.emitTargetsUpdate();
this.runtime.on(Runtime.TARGETS_UPDATE, emitProjectChanged => {
this.emitTargetsUpdate(emitProjectChanged);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this ever true?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now it isn't, but I don't know whether it's better to just assume always false here...

In a future pass we plan to completely separate out targets update and project changed, so we can fix this there then too. I'll file an actual issue for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filed in #1964

@kchadha
Copy link
Contributor Author

kchadha commented Jan 30, 2019

Towards resolving scratchfoundation/scratch-gui#4275

@kchadha kchadha force-pushed the project-dirty-state-fixes branch from 5a4a11b to b270fae Compare January 30, 2019 21:44
@kchadha kchadha force-pushed the project-dirty-state-fixes branch from b270fae to 13e69ba Compare January 30, 2019 21:46
@kchadha kchadha added QA-OK and removed needs-qa labels Feb 5, 2019
@kchadha kchadha merged commit c796a8b into develop Feb 5, 2019
@kchadha kchadha deleted the project-dirty-state-fixes branch February 5, 2019 21:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants