diff --git a/src/serialization/sb2.js b/src/serialization/sb2.js index fc1e0afde..945c183d1 100644 --- a/src/serialization/sb2.js +++ b/src/serialization/sb2.js @@ -442,7 +442,15 @@ const parseScratchObject = function (object, runtime, extensions, topLevel, zip) const md5ext = costumeSource.baseLayerMD5; const idParts = StringUtil.splitFirst(md5ext, '.'); const md5 = idParts[0]; - const ext = idParts[1].toLowerCase(); + let ext; + if (idParts.length === 2 && idParts[1]) { + ext = idParts[1]; + } else { + // Default to 'png' if baseLayerMD5 is not formatted correctly + ext = 'png'; + // Fix costume md5 for later + costume.md5 = `${costume.md5}.${ext}`; + } costume.dataFormat = ext; costume.assetId = md5; if (costumeSource.textLayerMD5) { diff --git a/test/fixtures/sb2-from-sb1-missing-backdrop-image.sb2 b/test/fixtures/sb2-from-sb1-missing-backdrop-image.sb2 new file mode 100644 index 000000000..6c36c68b2 Binary files /dev/null and b/test/fixtures/sb2-from-sb1-missing-backdrop-image.sb2 differ diff --git a/test/integration/load-sb2-originally-sb1-without-backdrop-image.js b/test/integration/load-sb2-originally-sb1-without-backdrop-image.js new file mode 100644 index 000000000..8a79cd223 --- /dev/null +++ b/test/integration/load-sb2-originally-sb1-without-backdrop-image.js @@ -0,0 +1,41 @@ +const path = require('path'); +const test = require('tap').test; +const makeTestStorage = require('../fixtures/make-test-storage'); +const readFileToBuffer = require('../fixtures/readProjectFile').readFileToBuffer; + +const VirtualMachine = require('../../src/virtual-machine'); + +const projectUri = path.resolve(__dirname, '../fixtures/sb2-from-sb1-missing-backdrop-image.sb2'); +const project = readFileToBuffer(projectUri); + +const vm = new VirtualMachine(); + +test('sb2 project (originally from Scratch 1.4) with missing backdrop image should load', t => { + vm.attachStorage(makeTestStorage()); + + // Evaluate playground data and exit + vm.on('playgroundData', e => { + const threads = JSON.parse(e.threads); + t.ok(threads.length === 0); + t.end(); + process.nextTick(process.exit); + }); + + vm.start(); + vm.clear(); + vm.setCompatibilityMode(false); + vm.setTurboMode(false); + t.doesNotThrow(() => { + vm.loadProject(project).then(() => { + + t.equal(vm.runtime.targets.length, 2); // stage and default sprite + + vm.greenFlag(); + + setTimeout(() => { + vm.getPlaygroundData(); + vm.stopAll(); + }, 1000); + }); + }); +});