mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2025-08-28 22:30:40 -04:00
Load extensions before sharing blocks.
This commit fixes the unit tests so the assertions are made after the promise resolves
This commit is contained in:
parent
bc1da9fa44
commit
c8ad1955d4
2 changed files with 90 additions and 74 deletions
|
@ -1107,6 +1107,7 @@ class VirtualMachine extends EventEmitter {
|
||||||
* @param {!string} targetId Id of target to add blocks to.
|
* @param {!string} targetId Id of target to add blocks to.
|
||||||
* @param {?string} optFromTargetId Optional target id indicating that blocks are being
|
* @param {?string} optFromTargetId Optional target id indicating that blocks are being
|
||||||
* shared from that target. This is needed for resolving any potential variable conflicts.
|
* shared from that target. This is needed for resolving any potential variable conflicts.
|
||||||
|
* @return {!Promise} Promise that resolves when the extensions and blocks have been added.
|
||||||
*/
|
*/
|
||||||
shareBlocksToTarget (blocks, targetId, optFromTargetId) {
|
shareBlocksToTarget (blocks, targetId, optFromTargetId) {
|
||||||
const copiedBlocks = JSON.parse(JSON.stringify(blocks));
|
const copiedBlocks = JSON.parse(JSON.stringify(blocks));
|
||||||
|
@ -1119,10 +1120,24 @@ class VirtualMachine extends EventEmitter {
|
||||||
fromTarget.resolveVariableSharingConflictsWithTarget(copiedBlocks, target);
|
fromTarget.resolveVariableSharingConflictsWithTarget(copiedBlocks, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < copiedBlocks.length; i++) {
|
// Create a unique set of extensionIds that are not yet loaded
|
||||||
target.blocks.createBlock(copiedBlocks[i]);
|
const extensionIDs = new Set(copiedBlocks
|
||||||
}
|
.map(b => sb3.getExtensionIdForOpcode(b.opcode))
|
||||||
target.blocks.updateTargetSpecificBlocks(target.isStage);
|
.filter(id => !!id) // Remove ids that do not exist
|
||||||
|
.filter(id => !this.extensionManager.isExtensionLoaded(id)) // and remove loaded extensions
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create an array promises for extensions to load
|
||||||
|
const extensionPromises = Array.from(extensionIDs,
|
||||||
|
id => this.extensionManager.loadExtensionURL(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
return Promise.all(extensionPromises).then(() => {
|
||||||
|
copiedBlocks.forEach(block => {
|
||||||
|
target.blocks.createBlock(block);
|
||||||
|
});
|
||||||
|
target.blocks.updateTargetSpecificBlocks(target.isStage);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -744,28 +744,29 @@ test('shareBlocksToTarget shares global variables without any name changes', t =
|
||||||
t.type(stage.blocks.getBlock('a block'), 'undefined');
|
t.type(stage.blocks.getBlock('a block'), 'undefined');
|
||||||
|
|
||||||
// Share the block to the stage
|
// Share the block to the stage
|
||||||
vm.shareBlocksToTarget([target.blocks.getBlock('a block')], stage.id, target.id);
|
vm.shareBlocksToTarget([target.blocks.getBlock('a block')], stage.id, target.id).then(() => {
|
||||||
|
|
||||||
// Verify that the block now exists on the target as well as the stage
|
// Verify that the block now exists on the target as well as the stage
|
||||||
t.type(target.blocks.getBlock('a block'), 'object');
|
t.type(target.blocks.getBlock('a block'), 'object');
|
||||||
t.type(target.blocks.getBlock('a block').fields, 'object');
|
t.type(target.blocks.getBlock('a block').fields, 'object');
|
||||||
t.type(target.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
t.type(target.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
||||||
t.equal(target.blocks.getBlock('a block').fields.VARIABLE.id, 'mock var id');
|
t.equal(target.blocks.getBlock('a block').fields.VARIABLE.id, 'mock var id');
|
||||||
|
|
||||||
t.type(stage.blocks.getBlock('a block'), 'object');
|
t.type(stage.blocks.getBlock('a block'), 'object');
|
||||||
t.type(stage.blocks.getBlock('a block').fields, 'object');
|
t.type(stage.blocks.getBlock('a block').fields, 'object');
|
||||||
t.type(stage.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
t.type(stage.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
||||||
t.equal(stage.blocks.getBlock('a block').fields.VARIABLE.id, 'mock var id');
|
t.equal(stage.blocks.getBlock('a block').fields.VARIABLE.id, 'mock var id');
|
||||||
|
|
||||||
// Verify that the variables haven't changed, the variable still exists on the
|
// Verify that the variables haven't changed, the variable still exists on the
|
||||||
// stage, it should still have the same name and value, and there should be
|
// stage, it should still have the same name and value, and there should be
|
||||||
// no variables on the target.
|
// no variables on the target.
|
||||||
t.equal(Object.keys(target.variables).length, 0);
|
t.equal(Object.keys(target.variables).length, 0);
|
||||||
t.equal(Object.keys(stage.variables).length, 1);
|
t.equal(Object.keys(stage.variables).length, 1);
|
||||||
t.equal(stage.variables['mock var id'].name, 'a mock variable');
|
t.equal(stage.variables['mock var id'].name, 'a mock variable');
|
||||||
t.equal(vm.getVariableValue(stage.id, 'mock var id'), 10);
|
t.equal(vm.getVariableValue(stage.id, 'mock var id'), 10);
|
||||||
|
|
||||||
t.end();
|
t.end();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('shareBlocksToTarget shares a local variable to the stage, creating a global variable with a new name', t => {
|
test('shareBlocksToTarget shares a local variable to the stage, creating a global variable with a new name', t => {
|
||||||
|
@ -803,36 +804,36 @@ test('shareBlocksToTarget shares a local variable to the stage, creating a globa
|
||||||
t.type(stage.blocks.getBlock('a block'), 'undefined');
|
t.type(stage.blocks.getBlock('a block'), 'undefined');
|
||||||
|
|
||||||
// Share the block to the stage
|
// Share the block to the stage
|
||||||
vm.shareBlocksToTarget([target.blocks.getBlock('a block')], stage.id, target.id);
|
vm.shareBlocksToTarget([target.blocks.getBlock('a block')], stage.id, target.id).then(() => {
|
||||||
|
// Verify that the block still exists on the target and remains unchanged
|
||||||
|
t.type(target.blocks.getBlock('a block'), 'object');
|
||||||
|
t.type(target.blocks.getBlock('a block').fields, 'object');
|
||||||
|
t.type(target.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
||||||
|
t.equal(target.blocks.getBlock('a block').fields.VARIABLE.id, 'mock var id');
|
||||||
|
|
||||||
// Verify that the block still exists on the target and remains unchanged
|
t.type(stage.blocks.getBlock('a block'), 'object');
|
||||||
t.type(target.blocks.getBlock('a block'), 'object');
|
t.type(stage.blocks.getBlock('a block').fields, 'object');
|
||||||
t.type(target.blocks.getBlock('a block').fields, 'object');
|
t.type(stage.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
||||||
t.type(target.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
t.equal(stage.blocks.getBlock('a block').fields.VARIABLE.id, 'StageVarFromLocal_mock var id');
|
||||||
t.equal(target.blocks.getBlock('a block').fields.VARIABLE.id, 'mock var id');
|
|
||||||
|
|
||||||
t.type(stage.blocks.getBlock('a block'), 'object');
|
// Verify that a new global variable was created, the old one still exists on
|
||||||
t.type(stage.blocks.getBlock('a block').fields, 'object');
|
// the target and still has the same name and value, and the new one has
|
||||||
t.type(stage.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
// a new name and value 0.
|
||||||
t.equal(stage.blocks.getBlock('a block').fields.VARIABLE.id, 'StageVarFromLocal_mock var id');
|
t.equal(Object.keys(target.variables).length, 1);
|
||||||
|
t.equal(target.variables['mock var id'].name, 'a mock variable');
|
||||||
|
t.equal(vm.getVariableValue(target.id, 'mock var id'), 10);
|
||||||
|
|
||||||
// Verify that a new global variable was created, the old one still exists on
|
// Verify that a new variable was created on the stage, with a new name and new id
|
||||||
// the target and still has the same name and value, and the new one has
|
t.equal(Object.keys(stage.variables).length, 1);
|
||||||
// a new name and value 0.
|
t.type(stage.variables['mock var id'], 'undefined');
|
||||||
t.equal(Object.keys(target.variables).length, 1);
|
const newGlobalVar = Object.values(stage.variables)[0];
|
||||||
t.equal(target.variables['mock var id'].name, 'a mock variable');
|
t.equal(newGlobalVar.name, 'Stage: a mock variable');
|
||||||
t.equal(vm.getVariableValue(target.id, 'mock var id'), 10);
|
const newId = newGlobalVar.id;
|
||||||
|
t.notEqual(newId, 'mock var id');
|
||||||
|
t.equals(vm.getVariableValue(stage.id, newId), 0);
|
||||||
|
|
||||||
// Verify that a new variable was created on the stage, with a new name and new id
|
t.end();
|
||||||
t.equal(Object.keys(stage.variables).length, 1);
|
});
|
||||||
t.type(stage.variables['mock var id'], 'undefined');
|
|
||||||
const newGlobalVar = Object.values(stage.variables)[0];
|
|
||||||
t.equal(newGlobalVar.name, 'Stage: a mock variable');
|
|
||||||
const newId = newGlobalVar.id;
|
|
||||||
t.notEqual(newId, 'mock var id');
|
|
||||||
t.equals(vm.getVariableValue(stage.id, newId), 0);
|
|
||||||
|
|
||||||
t.end();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('shareBlocksToTarget chooses a fresh name for a new global variable checking for conflicts on all sprites', t => {
|
test('shareBlocksToTarget chooses a fresh name for a new global variable checking for conflicts on all sprites', t => {
|
||||||
|
@ -877,36 +878,36 @@ test('shareBlocksToTarget chooses a fresh name for a new global variable checkin
|
||||||
otherTarget.createVariable('a different var', 'Stage: a mock variable', Variable.SCALAR_TYPE);
|
otherTarget.createVariable('a different var', 'Stage: a mock variable', Variable.SCALAR_TYPE);
|
||||||
|
|
||||||
// Share the block to the stage
|
// Share the block to the stage
|
||||||
vm.shareBlocksToTarget([target.blocks.getBlock('a block')], stage.id, target.id);
|
vm.shareBlocksToTarget([target.blocks.getBlock('a block')], stage.id, target.id).then(() => {
|
||||||
|
// Verify that the block still exists on the target and remains unchanged
|
||||||
|
t.type(target.blocks.getBlock('a block'), 'object');
|
||||||
|
t.type(target.blocks.getBlock('a block').fields, 'object');
|
||||||
|
t.type(target.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
||||||
|
t.equal(target.blocks.getBlock('a block').fields.VARIABLE.id, 'mock var id');
|
||||||
|
|
||||||
// Verify that the block still exists on the target and remains unchanged
|
t.type(stage.blocks.getBlock('a block'), 'object');
|
||||||
t.type(target.blocks.getBlock('a block'), 'object');
|
t.type(stage.blocks.getBlock('a block').fields, 'object');
|
||||||
t.type(target.blocks.getBlock('a block').fields, 'object');
|
t.type(stage.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
||||||
t.type(target.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
t.equal(stage.blocks.getBlock('a block').fields.VARIABLE.id, 'StageVarFromLocal_mock var id');
|
||||||
t.equal(target.blocks.getBlock('a block').fields.VARIABLE.id, 'mock var id');
|
|
||||||
|
|
||||||
t.type(stage.blocks.getBlock('a block'), 'object');
|
// Verify that a new global variable was created, the old one still exists on
|
||||||
t.type(stage.blocks.getBlock('a block').fields, 'object');
|
// the target and still has the same name and value, and the new one has
|
||||||
t.type(stage.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
// a new name and value 0.
|
||||||
t.equal(stage.blocks.getBlock('a block').fields.VARIABLE.id, 'StageVarFromLocal_mock var id');
|
t.equal(Object.keys(target.variables).length, 1);
|
||||||
|
t.equal(target.variables['mock var id'].name, 'a mock variable');
|
||||||
|
t.equal(vm.getVariableValue(target.id, 'mock var id'), 10);
|
||||||
|
|
||||||
// Verify that a new global variable was created, the old one still exists on
|
// Verify that a new variable was created on the stage, with a new name and new id
|
||||||
// the target and still has the same name and value, and the new one has
|
t.equal(Object.keys(stage.variables).length, 1);
|
||||||
// a new name and value 0.
|
t.type(stage.variables['mock var id'], 'undefined');
|
||||||
t.equal(Object.keys(target.variables).length, 1);
|
const newGlobalVar = Object.values(stage.variables)[0];
|
||||||
t.equal(target.variables['mock var id'].name, 'a mock variable');
|
t.equal(newGlobalVar.name, 'Stage: a mock variable2');
|
||||||
t.equal(vm.getVariableValue(target.id, 'mock var id'), 10);
|
const newId = newGlobalVar.id;
|
||||||
|
t.notEqual(newId, 'mock var id');
|
||||||
|
t.equals(vm.getVariableValue(stage.id, newId), 0);
|
||||||
|
|
||||||
// Verify that a new variable was created on the stage, with a new name and new id
|
t.end();
|
||||||
t.equal(Object.keys(stage.variables).length, 1);
|
});
|
||||||
t.type(stage.variables['mock var id'], 'undefined');
|
|
||||||
const newGlobalVar = Object.values(stage.variables)[0];
|
|
||||||
t.equal(newGlobalVar.name, 'Stage: a mock variable2');
|
|
||||||
const newId = newGlobalVar.id;
|
|
||||||
t.notEqual(newId, 'mock var id');
|
|
||||||
t.equals(vm.getVariableValue(stage.id, newId), 0);
|
|
||||||
|
|
||||||
t.end();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Setting turbo mode emits events', t => {
|
test('Setting turbo mode emits events', t => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue