From ff7b5751145ddad7bacb83a0b7281c323845a781 Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Mon, 30 Apr 2018 11:51:52 -0400 Subject: [PATCH] Dynamically load music extension manifest --- src/extensions/scratch3_music/index.js | 53 +++++++++++++++++--------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index bfa55bee3..5569d21e4 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -5,17 +5,6 @@ const Cast = require('../../util/cast'); const MathUtil = require('../../util/math-util'); const Timer = require('../../util/timer'); -/** - * The instrument and drum sounds, loaded as static assets. - * @type {object} - */ -let assetData = {}; -try { - assetData = require('./manifest'); -} catch (e) { - // Non-webpack environment, don't worry about assets. -} - /** * Icon svg to be displayed at the left edge of each extension block, encoded as a data URI. * @type {string} @@ -102,6 +91,27 @@ class Scratch3MusicBlocks { }); } + _fetchSounds () { + if (!this._assetData) { + this._assetData = new Promise((resolve, reject) => { + // Use webpack supported require.ensure to dynamically load the + // manifest as an another javascript file. Once the file + // executes the callback will be called and we can require the + // manifest. + // + // You can either make require calls in the callback function or + // specify dependencies in the array to load. The third argument + // is an error callback. The forth argument is a name for the + // javascript that can be used depending on the webpack + // configuration. + require.ensure([], () => { + resolve(require('./manifest')); + }, reject, 'vm-music-manifest'); + }); + } + return this._assetData; + } + /** * Decode a sound and store the buffer in an array. * @param {string} filePath - the audio file name. @@ -112,14 +122,23 @@ class Scratch3MusicBlocks { _storeSound (filePath, index, bufferArray) { const fullPath = `${filePath}.mp3`; - if (!assetData[fullPath]) return; + return this._fetchSounds() + // In case require.ensure is not available (such as running this + // file directly in node instead of through the webpack built script + // for node) or that require.ensure fails, turn the error into an + // empty object. The music extension will ignore the sound files. + .catch(() => ({})) + .then(assetData => { + if (!assetData[fullPath]) return; - // The sound buffer has already been downloaded via the manifest file required above. - const soundBuffer = assetData[fullPath]; + // The sound buffer has already been downloaded via the manifest file required above. + const soundBuffer = assetData[fullPath]; - return this._decodeSound(soundBuffer).then(buffer => { - bufferArray[index] = buffer; - }); + return this._decodeSound(soundBuffer); + }) + .then(buffer => { + bufferArray[index] = buffer; + }); } /**