mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2025-06-30 08:10:27 -04:00
Ignore video sensing monitor and import music tempo monitor unless it is hidden. Load extensions for visible monitors. Add tests for new functionality.
This commit is contained in:
parent
fe186913ac
commit
cfa71723eb
8 changed files with 137 additions and 29 deletions
src/serialization
test
|
@ -245,17 +245,42 @@ const globalBroadcastMsgStateGenerator = (function () {
|
||||||
* @param {ImportedExtensionsInfo} extensions - (in/out) parsed extension information will be stored here.
|
* @param {ImportedExtensionsInfo} extensions - (in/out) parsed extension information will be stored here.
|
||||||
*/
|
*/
|
||||||
const parseMonitorObject = (object, runtime, targets, extensions) => {
|
const parseMonitorObject = (object, runtime, targets, extensions) => {
|
||||||
let target = null;
|
// In scratch 2.0, there are two monitors that now correspond to extension
|
||||||
|
// blocks (tempo and video motion/direction). In the case of the
|
||||||
|
// video motion/direction block, this reporter is not monitorable in Scratch 3.0.
|
||||||
|
// In the case of the tempo block, we should import it and load the music extension
|
||||||
|
// only when the monitor is actually visible.
|
||||||
|
|
||||||
const opcode = specMap[object.cmd].opcode;
|
const opcode = specMap[object.cmd].opcode;
|
||||||
const extIndex = opcode.indexOf('_');
|
const extIndex = opcode.indexOf('_');
|
||||||
const extID = opcode.substring(0, extIndex);
|
const extID = opcode.substring(0, extIndex);
|
||||||
|
|
||||||
// All non-core extensions should be added by blocks at this point
|
if (extID === 'videoSensing') {
|
||||||
// We can assume this is an unintended monitor and skip parsing if it belongs to a non-core extension
|
return;
|
||||||
if (CORE_EXTENSIONS.indexOf(extID) === -1) {
|
} else if (CORE_EXTENSIONS.indexOf(extID) === -1 && extID !== '' &&
|
||||||
if (extID !== '') return;
|
!extensions.extensionIDs.has(extID) && !object.visible) {
|
||||||
|
// Don't import this monitor if it refers to a non-core extension that
|
||||||
|
// doesn't exist anywhere else in the project and it isn't visible.
|
||||||
|
// This should only apply to the tempo block at this point since
|
||||||
|
// there are no other sb2 blocks that are now extension monitors.
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// if (!object.visible) {
|
||||||
|
// // If the monitor is invisible, check to see if it tries to load a new extension
|
||||||
|
// // (e.g. one that hasn't already been loaded by an actual block in the project).
|
||||||
|
// // If so, exit without importing the monitor.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// // All non-core extensions should be added by blocks at this point
|
||||||
|
// // We can assume this is an unintended monitor and skip parsing if it belongs to a non-core extension
|
||||||
|
// if () {
|
||||||
|
// if ( && !extensions.has(extID)) return;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
let target = null;
|
||||||
// List blocks don't come in with their target name set.
|
// List blocks don't come in with their target name set.
|
||||||
// Find the target by searching for a target with matching variable name/type.
|
// Find the target by searching for a target with matching variable name/type.
|
||||||
if (!object.hasOwnProperty('target')) {
|
if (!object.hasOwnProperty('target')) {
|
||||||
|
|
BIN
test/fixtures/invisible-tempo-monitor-no-other-music-blocks.sb2
vendored
Normal file
BIN
test/fixtures/invisible-tempo-monitor-no-other-music-blocks.sb2
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/load-extensions/music-visible-monitor-no-blocks.sb2
vendored
Normal file
BIN
test/fixtures/load-extensions/music-visible-monitor-no-blocks.sb2
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/visible-tempo-monitor-no-other-music-blocks.sb2
vendored
Normal file
BIN
test/fixtures/visible-tempo-monitor-no-other-music-blocks.sb2
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/visible-video-monitor-and-video-blocks.sb2
vendored
Normal file
BIN
test/fixtures/visible-video-monitor-and-video-blocks.sb2
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/visible-video-monitor-no-other-video-blocks.sb2
vendored
Normal file
BIN
test/fixtures/visible-video-monitor-no-other-video-blocks.sb2
vendored
Normal file
Binary file not shown.
107
test/integration/sb2-import-extension-monitors.js
Normal file
107
test/integration/sb2-import-extension-monitors.js
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
const path = require('path');
|
||||||
|
const test = require('tap').test;
|
||||||
|
const makeTestStorage = require('../fixtures/make-test-storage');
|
||||||
|
const {readFileToBuffer, extractProjectJson} = require('../fixtures/readProjectFile');
|
||||||
|
const VirtualMachine = require('../../src/index');
|
||||||
|
const sb2 = require('../../src/serialization/sb2');
|
||||||
|
|
||||||
|
const invisibleVideoMonitorProjectUri = path.resolve(__dirname, '../fixtures/invisible-video-monitor.sb2');
|
||||||
|
const invisibleVideoMonitorProject = readFileToBuffer(invisibleVideoMonitorProjectUri);
|
||||||
|
|
||||||
|
const visibleVideoMonitorProjectUri = path.resolve(
|
||||||
|
__dirname, '../fixtures/visible-video-monitor-no-other-video-blocks.sb2');
|
||||||
|
const visibleVideoMonitorProject = readFileToBuffer(visibleVideoMonitorProjectUri);
|
||||||
|
|
||||||
|
const visibleVideoMonitorAndBlocksProjectUri = path.resolve(
|
||||||
|
__dirname, '../fixtures/visible-video-monitor-and-video-blocks.sb2');
|
||||||
|
const visibleVideoMonitorAndBlocksProject = extractProjectJson(visibleVideoMonitorAndBlocksProjectUri);
|
||||||
|
|
||||||
|
const invisibleTempoMonitorProjectUri = path.resolve(
|
||||||
|
__dirname, '../fixtures/invisible-tempo-monitor-no-other-music-blocks.sb2');
|
||||||
|
const invisibleTempoMonitorProject = readFileToBuffer(invisibleTempoMonitorProjectUri);
|
||||||
|
|
||||||
|
const visibleTempoMonitorProjectUri = path.resolve(
|
||||||
|
__dirname, '../fixtures/visible-tempo-monitor-no-other-music-blocks.sb2');
|
||||||
|
const visibleTempoMonitorProject = readFileToBuffer(visibleTempoMonitorProjectUri);
|
||||||
|
|
||||||
|
test('loading sb2 project with invisible video monitor should not load monitor or extension', t => {
|
||||||
|
const vm = new VirtualMachine();
|
||||||
|
vm.attachStorage(makeTestStorage());
|
||||||
|
|
||||||
|
// Start VM, load project, and run
|
||||||
|
vm.start();
|
||||||
|
vm.clear();
|
||||||
|
vm.setCompatibilityMode(false);
|
||||||
|
vm.setTurboMode(false);
|
||||||
|
vm.loadProject(invisibleVideoMonitorProject).then(() => {
|
||||||
|
t.equal(vm.extensionManager.isExtensionLoaded('videoSensing'), false);
|
||||||
|
t.equal(vm.runtime._monitorState.size, 0);
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('loading sb2 project with visible video monitor should not load extension', t => {
|
||||||
|
const vm = new VirtualMachine();
|
||||||
|
vm.attachStorage(makeTestStorage());
|
||||||
|
|
||||||
|
// Start VM, load project, and run
|
||||||
|
vm.start();
|
||||||
|
vm.clear();
|
||||||
|
vm.setCompatibilityMode(false);
|
||||||
|
vm.setTurboMode(false);
|
||||||
|
vm.loadProject(visibleVideoMonitorProject).then(() => {
|
||||||
|
t.equal(vm.extensionManager.isExtensionLoaded('videoSensing'), false);
|
||||||
|
t.equal(vm.runtime._monitorState.size, 0);
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// This test looks a little different than the rest because loading a project with
|
||||||
|
// the video sensing block requires a mock renderer and other setup, so instead
|
||||||
|
// we are just using deserialize to test what we need instead
|
||||||
|
test('sb2 project with video sensing blocks and monitor should load extension but not monitor', t => {
|
||||||
|
const vm = new VirtualMachine();
|
||||||
|
|
||||||
|
sb2.deserialize(visibleVideoMonitorAndBlocksProject, vm.runtime).then(project => {
|
||||||
|
// Extension loads but monitor does not
|
||||||
|
project.extensions.extensionIDs.has('videoSensing');
|
||||||
|
// Non-core extension monitors haven't been added to the runtime
|
||||||
|
t.equal(vm.runtime._monitorState.size, 0);
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sb2 project with invisible music monitor should not load monitor or extension', t => {
|
||||||
|
const vm = new VirtualMachine();
|
||||||
|
vm.attachStorage(makeTestStorage());
|
||||||
|
|
||||||
|
// Start VM, load project, and run
|
||||||
|
vm.start();
|
||||||
|
vm.clear();
|
||||||
|
vm.setCompatibilityMode(false);
|
||||||
|
vm.setTurboMode(false);
|
||||||
|
vm.loadProject(invisibleTempoMonitorProject).then(() => {
|
||||||
|
t.equal(vm.extensionManager.isExtensionLoaded('music'), false);
|
||||||
|
t.equal(vm.runtime._monitorState.size, 0);
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sb2 project with visible music monitor should load monitor and extension', t => {
|
||||||
|
const vm = new VirtualMachine();
|
||||||
|
vm.attachStorage(makeTestStorage());
|
||||||
|
|
||||||
|
// Start VM, load project, and run
|
||||||
|
vm.start();
|
||||||
|
vm.clear();
|
||||||
|
vm.setCompatibilityMode(false);
|
||||||
|
vm.setTurboMode(false);
|
||||||
|
vm.loadProject(visibleTempoMonitorProject).then(() => {
|
||||||
|
t.equal(vm.extensionManager.isExtensionLoaded('music'), true);
|
||||||
|
t.equal(vm.runtime._monitorState.size, 1);
|
||||||
|
t.equal(vm.runtime._monitorState.has('music_getTempo'), true);
|
||||||
|
t.equal(vm.runtime._monitorState.get('music_getTempo').visible, true);
|
||||||
|
t.end();
|
||||||
|
process.nextTick(process.exit); // This is needed because this is the end of the last test in this file!!
|
||||||
|
});
|
||||||
|
});
|
|
@ -5,7 +5,6 @@ const extractProjectJson = require('../fixtures/readProjectFile').extractProject
|
||||||
const RenderedTarget = require('../../src/sprites/rendered-target');
|
const RenderedTarget = require('../../src/sprites/rendered-target');
|
||||||
const Runtime = require('../../src/engine/runtime');
|
const Runtime = require('../../src/engine/runtime');
|
||||||
const sb2 = require('../../src/serialization/sb2');
|
const sb2 = require('../../src/serialization/sb2');
|
||||||
const specMap = require('../../src/serialization/sb2_specmap.js');
|
|
||||||
|
|
||||||
test('spec', t => {
|
test('spec', t => {
|
||||||
t.type(sb2, 'object');
|
t.type(sb2, 'object');
|
||||||
|
@ -103,26 +102,3 @@ test('Ordering', t => {
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Prevent monitors from adding non-core extensions', t => {
|
|
||||||
const rt = new Runtime();
|
|
||||||
// This test project's video motion reporter block was checked, saved, then unchecked and saved
|
|
||||||
const videoSensingMonitor = path.resolve(__dirname, '../fixtures/invisible-video-monitor.sb2');
|
|
||||||
const projectJSON = extractProjectJson(videoSensingMonitor);
|
|
||||||
|
|
||||||
sb2.deserialize(projectJSON, rt).then(project => {
|
|
||||||
for (const child of projectJSON.children) {
|
|
||||||
// Check that monitor's extension hasn't been added to the serialized project's extensions
|
|
||||||
if (child.cmd) {
|
|
||||||
const opcode = specMap[child.cmd].opcode;
|
|
||||||
const extIndex = opcode.indexOf('_');
|
|
||||||
const extID = opcode.substring(0, extIndex);
|
|
||||||
t.notOk(project.extensions.extensionIDs.has(extID));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Non-core extension monitors haven't been added to the runtime
|
|
||||||
t.equal(rt._monitorState.size, 0);
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue