diff --git a/src/blocks/scratch3_control.js b/src/blocks/scratch3_control.js index 285b241ab53..1d7e8f42417 100644 --- a/src/blocks/scratch3_control.js +++ b/src/blocks/scratch3_control.js @@ -1,7 +1,7 @@ -var Cast = require('../util/cast'); -var Timer = require('../util/timer'); +const Cast = require('../util/cast'); +const Timer = require('../util/timer'); -var Scratch3ControlBlocks = function (runtime) { +const Scratch3ControlBlocks = function (runtime) { /** * The runtime instantiating this block package. * @type {Runtime} @@ -37,7 +37,7 @@ Scratch3ControlBlocks.prototype.getHats = function () { }; Scratch3ControlBlocks.prototype.repeat = function (args, util) { - var times = Math.floor(Cast.toNumber(args.TIMES)); + const times = Math.floor(Cast.toNumber(args.TIMES)); // Initialize loop if (typeof util.stackFrame.loopCounter === 'undefined') { util.stackFrame.loopCounter = times; @@ -54,7 +54,7 @@ Scratch3ControlBlocks.prototype.repeat = function (args, util) { }; Scratch3ControlBlocks.prototype.repeatUntil = function (args, util) { - var condition = Cast.toBoolean(args.CONDITION); + const condition = Cast.toBoolean(args.CONDITION); // If the condition is true, start the branch. if (!condition) { util.startBranch(1, true); @@ -62,7 +62,7 @@ Scratch3ControlBlocks.prototype.repeatUntil = function (args, util) { }; Scratch3ControlBlocks.prototype.waitUntil = function (args, util) { - var condition = Cast.toBoolean(args.CONDITION); + const condition = Cast.toBoolean(args.CONDITION); if (!condition) { util.yield(); } @@ -79,7 +79,7 @@ Scratch3ControlBlocks.prototype.wait = function (args, util) { util.yield(); this.runtime.requestRedraw(); } else { - var duration = Math.max(0, 1000 * Cast.toNumber(args.DURATION)); + const duration = Math.max(0, 1000 * Cast.toNumber(args.DURATION)); if (util.stackFrame.timer.timeElapsed() < duration) { util.yield(); } @@ -87,14 +87,14 @@ Scratch3ControlBlocks.prototype.wait = function (args, util) { }; Scratch3ControlBlocks.prototype.if = function (args, util) { - var condition = Cast.toBoolean(args.CONDITION); + const condition = Cast.toBoolean(args.CONDITION); if (condition) { util.startBranch(1, false); } }; Scratch3ControlBlocks.prototype.ifElse = function (args, util) { - var condition = Cast.toBoolean(args.CONDITION); + const condition = Cast.toBoolean(args.CONDITION); if (condition) { util.startBranch(1, false); } else { @@ -103,7 +103,7 @@ Scratch3ControlBlocks.prototype.ifElse = function (args, util) { }; Scratch3ControlBlocks.prototype.stop = function (args, util) { - var option = args.STOP_OPTION; + const option = args.STOP_OPTION; if (option === 'all') { util.stopAll(); } else if (option === 'other scripts in sprite' || @@ -115,7 +115,7 @@ Scratch3ControlBlocks.prototype.stop = function (args, util) { }; Scratch3ControlBlocks.prototype.createClone = function (args, util) { - var cloneTarget; + let cloneTarget; if (args.CLONE_OPTION === '_myself_') { cloneTarget = util.target; } else { @@ -124,7 +124,7 @@ Scratch3ControlBlocks.prototype.createClone = function (args, util) { if (!cloneTarget) { return; } - var newClone = cloneTarget.makeClone(); + const newClone = cloneTarget.makeClone(); if (newClone) { this.runtime.targets.push(newClone); } diff --git a/src/blocks/scratch3_data.js b/src/blocks/scratch3_data.js index b1783563820..3b3b0613965 100644 --- a/src/blocks/scratch3_data.js +++ b/src/blocks/scratch3_data.js @@ -1,6 +1,6 @@ -var Cast = require('../util/cast'); +const Cast = require('../util/cast'); -var Scratch3DataBlocks = function (runtime) { +const Scratch3DataBlocks = function (runtime) { /** * The runtime instantiating this block package. * @type {Runtime} @@ -29,30 +29,30 @@ Scratch3DataBlocks.prototype.getPrimitives = function () { }; Scratch3DataBlocks.prototype.getVariable = function (args, util) { - var variable = util.target.lookupOrCreateVariable(args.VARIABLE); + const variable = util.target.lookupOrCreateVariable(args.VARIABLE); return variable.value; }; Scratch3DataBlocks.prototype.setVariableTo = function (args, util) { - var variable = util.target.lookupOrCreateVariable(args.VARIABLE); + const variable = util.target.lookupOrCreateVariable(args.VARIABLE); variable.value = args.VALUE; }; Scratch3DataBlocks.prototype.changeVariableBy = function (args, util) { - var variable = util.target.lookupOrCreateVariable(args.VARIABLE); - var castedValue = Cast.toNumber(variable.value); - var dValue = Cast.toNumber(args.VALUE); + const variable = util.target.lookupOrCreateVariable(args.VARIABLE); + const castedValue = Cast.toNumber(variable.value); + const dValue = Cast.toNumber(args.VALUE); variable.value = castedValue + dValue; }; Scratch3DataBlocks.prototype.getListContents = function (args, util) { - var list = util.target.lookupOrCreateList(args.LIST); + const list = util.target.lookupOrCreateList(args.LIST); // Determine if the list is all single letters. // If it is, report contents joined together with no separator. // If it's not, report contents joined together with a space. - var allSingleLetters = true; - for (var i = 0; i < list.contents.length; i++) { - var listItem = list.contents[i]; + let allSingleLetters = true; + for (let i = 0; i < list.contents.length; i++) { + const listItem = list.contents[i]; if (!((typeof listItem === 'string') && (listItem.length === 1))) { allSingleLetters = false; @@ -61,19 +61,19 @@ Scratch3DataBlocks.prototype.getListContents = function (args, util) { } if (allSingleLetters) { return list.contents.join(''); - } else { - return list.contents.join(' '); } + return list.contents.join(' '); + }; Scratch3DataBlocks.prototype.addToList = function (args, util) { - var list = util.target.lookupOrCreateList(args.LIST); + const list = util.target.lookupOrCreateList(args.LIST); list.contents.push(args.ITEM); }; Scratch3DataBlocks.prototype.deleteOfList = function (args, util) { - var list = util.target.lookupOrCreateList(args.LIST); - var index = Cast.toListIndex(args.INDEX, list.contents.length); + const list = util.target.lookupOrCreateList(args.LIST); + const index = Cast.toListIndex(args.INDEX, list.contents.length); if (index === Cast.LIST_INVALID) { return; } else if (index === Cast.LIST_ALL) { @@ -84,9 +84,9 @@ Scratch3DataBlocks.prototype.deleteOfList = function (args, util) { }; Scratch3DataBlocks.prototype.insertAtList = function (args, util) { - var item = args.ITEM; - var list = util.target.lookupOrCreateList(args.LIST); - var index = Cast.toListIndex(args.INDEX, list.contents.length + 1); + const item = args.ITEM; + const list = util.target.lookupOrCreateList(args.LIST); + const index = Cast.toListIndex(args.INDEX, list.contents.length + 1); if (index === Cast.LIST_INVALID) { return; } @@ -94,9 +94,9 @@ Scratch3DataBlocks.prototype.insertAtList = function (args, util) { }; Scratch3DataBlocks.prototype.replaceItemOfList = function (args, util) { - var item = args.ITEM; - var list = util.target.lookupOrCreateList(args.LIST); - var index = Cast.toListIndex(args.INDEX, list.contents.length); + const item = args.ITEM; + const list = util.target.lookupOrCreateList(args.LIST); + const index = Cast.toListIndex(args.INDEX, list.contents.length); if (index === Cast.LIST_INVALID) { return; } @@ -104,8 +104,8 @@ Scratch3DataBlocks.prototype.replaceItemOfList = function (args, util) { }; Scratch3DataBlocks.prototype.getItemOfList = function (args, util) { - var list = util.target.lookupOrCreateList(args.LIST); - var index = Cast.toListIndex(args.INDEX, list.contents.length); + const list = util.target.lookupOrCreateList(args.LIST); + const index = Cast.toListIndex(args.INDEX, list.contents.length); if (index === Cast.LIST_INVALID) { return ''; } @@ -113,19 +113,19 @@ Scratch3DataBlocks.prototype.getItemOfList = function (args, util) { }; Scratch3DataBlocks.prototype.lengthOfList = function (args, util) { - var list = util.target.lookupOrCreateList(args.LIST); + const list = util.target.lookupOrCreateList(args.LIST); return list.contents.length; }; Scratch3DataBlocks.prototype.listContainsItem = function (args, util) { - var item = args.ITEM; - var list = util.target.lookupOrCreateList(args.LIST); + const item = args.ITEM; + const list = util.target.lookupOrCreateList(args.LIST); if (list.contents.indexOf(item) >= 0) { return true; } // Try using Scratch comparison operator on each item. // (Scratch considers the string '123' equal to the number 123). - for (var i = 0; i < list.contents.length; i++) { + for (let i = 0; i < list.contents.length; i++) { if (Cast.compare(list.contents[i], item) === 0) { return true; } diff --git a/src/blocks/scratch3_event.js b/src/blocks/scratch3_event.js index b4c40116ef0..62d65fa13c8 100644 --- a/src/blocks/scratch3_event.js +++ b/src/blocks/scratch3_event.js @@ -1,6 +1,6 @@ -var Cast = require('../util/cast'); +const Cast = require('../util/cast'); -var Scratch3EventBlocks = function (runtime) { +const Scratch3EventBlocks = function (runtime) { /** * The runtime instantiating this block package. * @type {Runtime} @@ -45,8 +45,8 @@ Scratch3EventBlocks.prototype.getHats = function () { }; Scratch3EventBlocks.prototype.hatGreaterThanPredicate = function (args, util) { - var option = Cast.toString(args.WHENGREATERTHANMENU).toLowerCase(); - var value = Cast.toNumber(args.VALUE); + const option = Cast.toString(args.WHENGREATERTHANMENU).toLowerCase(); + const value = Cast.toNumber(args.VALUE); // @todo: Other cases :) if (option === 'timer') { return util.ioQuery('clock', 'projectTimer') > value; @@ -55,14 +55,14 @@ Scratch3EventBlocks.prototype.hatGreaterThanPredicate = function (args, util) { }; Scratch3EventBlocks.prototype.broadcast = function (args, util) { - var broadcastOption = Cast.toString(args.BROADCAST_OPTION); + const broadcastOption = Cast.toString(args.BROADCAST_OPTION); util.startHats('event_whenbroadcastreceived', { BROADCAST_OPTION: broadcastOption }); }; Scratch3EventBlocks.prototype.broadcastAndWait = function (args, util) { - var broadcastOption = Cast.toString(args.BROADCAST_OPTION); + const broadcastOption = Cast.toString(args.BROADCAST_OPTION); // Have we run before, starting threads? if (!util.stackFrame.startedThreads) { // No - start hats for this broadcast. @@ -77,10 +77,8 @@ Scratch3EventBlocks.prototype.broadcastAndWait = function (args, util) { } } // We've run before; check if the wait is still going on. - var instance = this; - var waiting = util.stackFrame.startedThreads.some(function (thread) { - return instance.runtime.isActiveThread(thread); - }); + const instance = this; + const waiting = util.stackFrame.startedThreads.some(thread => instance.runtime.isActiveThread(thread)); if (waiting) { util.yield(); } diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index ac71558d435..e0807337c23 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -1,6 +1,6 @@ -var Cast = require('../util/cast'); +const Cast = require('../util/cast'); -var Scratch3LooksBlocks = function (runtime) { +const Scratch3LooksBlocks = function (runtime) { /** * The runtime instantiating this block package. * @type {Runtime} @@ -45,8 +45,8 @@ Scratch3LooksBlocks.prototype.say = function (args, util) { Scratch3LooksBlocks.prototype.sayforsecs = function (args, util) { util.target.setSay('say', args.MESSAGE); - return new Promise(function (resolve) { - setTimeout(function () { + return new Promise(resolve => { + setTimeout(() => { // Clear say bubble and proceed. util.target.setSay(); resolve(); @@ -60,8 +60,8 @@ Scratch3LooksBlocks.prototype.think = function (args, util) { Scratch3LooksBlocks.prototype.thinkforsecs = function (args, util) { util.target.setSay('think', args.MESSAGE); - return new Promise(function (resolve) { - setTimeout(function () { + return new Promise(resolve => { + setTimeout(() => { // Clear say bubble and proceed. util.target.setSay(); resolve(); @@ -91,7 +91,7 @@ Scratch3LooksBlocks.prototype._setCostumeOrBackdrop = function (target, target.setCostume(optZeroIndex ? requestedCostume : requestedCostume - 1); } else { - var costumeIndex = target.getCostumeIndexByName(requestedCostume); + const costumeIndex = target.getCostumeIndexByName(requestedCostume); if (costumeIndex > -1) { target.setCostume(costumeIndex); } else if (requestedCostume === 'previous costume' || @@ -101,7 +101,7 @@ Scratch3LooksBlocks.prototype._setCostumeOrBackdrop = function (target, requestedCostume === 'next backdrop') { target.setCostume(target.currentCostume + 1); } else { - var forcedNumber = Number(requestedCostume); + const forcedNumber = Number(requestedCostume); if (!isNaN(forcedNumber)) { target.setCostume(optZeroIndex ? forcedNumber : forcedNumber - 1); @@ -110,7 +110,7 @@ Scratch3LooksBlocks.prototype._setCostumeOrBackdrop = function (target, } if (target === this.runtime.getTargetForStage()) { // Target is the stage - start hats. - var newName = target.sprite.costumes[target.currentCostume].name; + const newName = target.sprite.costumes[target.currentCostume].name; return this.runtime.startHats('event_whenbackdropswitchesto', { BACKDROP: newName }); @@ -148,33 +148,31 @@ Scratch3LooksBlocks.prototype.switchBackdropAndWait = function (args, util) { } } // We've run before; check if the wait is still going on. - var instance = this; - var waiting = util.stackFrame.startedThreads.some(function (thread) { - return instance.runtime.isActiveThread(thread); - }); + const instance = this; + const waiting = util.stackFrame.startedThreads.some(thread => instance.runtime.isActiveThread(thread)); if (waiting) { util.yield(); } }; Scratch3LooksBlocks.prototype.nextBackdrop = function () { - var stage = this.runtime.getTargetForStage(); + const stage = this.runtime.getTargetForStage(); this._setCostumeOrBackdrop( stage, stage.currentCostume + 1, true ); }; Scratch3LooksBlocks.prototype.changeEffect = function (args, util) { - var effect = Cast.toString(args.EFFECT).toLowerCase(); - var change = Cast.toNumber(args.CHANGE); + const effect = Cast.toString(args.EFFECT).toLowerCase(); + const change = Cast.toNumber(args.CHANGE); if (!util.target.effects.hasOwnProperty(effect)) return; - var newValue = change + util.target.effects[effect]; + const newValue = change + util.target.effects[effect]; util.target.setEffect(effect, newValue); }; Scratch3LooksBlocks.prototype.setEffect = function (args, util) { - var effect = Cast.toString(args.EFFECT).toLowerCase(); - var value = Cast.toNumber(args.VALUE); + const effect = Cast.toString(args.EFFECT).toLowerCase(); + const value = Cast.toNumber(args.VALUE); util.target.setEffect(effect, value); }; @@ -183,12 +181,12 @@ Scratch3LooksBlocks.prototype.clearEffects = function (args, util) { }; Scratch3LooksBlocks.prototype.changeSize = function (args, util) { - var change = Cast.toNumber(args.CHANGE); + const change = Cast.toNumber(args.CHANGE); util.target.setSize(util.target.size + change); }; Scratch3LooksBlocks.prototype.setSize = function (args, util) { - var size = Cast.toNumber(args.SIZE); + const size = Cast.toNumber(args.SIZE); util.target.setSize(size); }; @@ -205,12 +203,12 @@ Scratch3LooksBlocks.prototype.getSize = function (args, util) { }; Scratch3LooksBlocks.prototype.getBackdropIndex = function () { - var stage = this.runtime.getTargetForStage(); + const stage = this.runtime.getTargetForStage(); return stage.currentCostume + 1; }; Scratch3LooksBlocks.prototype.getBackdropName = function () { - var stage = this.runtime.getTargetForStage(); + const stage = this.runtime.getTargetForStage(); return stage.sprite.costumes[stage.currentCostume].name; }; diff --git a/src/blocks/scratch3_motion.js b/src/blocks/scratch3_motion.js index 857644dd542..c70eb3bde9e 100644 --- a/src/blocks/scratch3_motion.js +++ b/src/blocks/scratch3_motion.js @@ -1,8 +1,8 @@ -var Cast = require('../util/cast'); -var MathUtil = require('../util/math-util'); -var Timer = require('../util/timer'); +const Cast = require('../util/cast'); +const MathUtil = require('../util/math-util'); +const Timer = require('../util/timer'); -var Scratch3MotionBlocks = function (runtime) { +const Scratch3MotionBlocks = function (runtime) { /** * The runtime instantiating this block package. * @type {Runtime} @@ -37,32 +37,32 @@ Scratch3MotionBlocks.prototype.getPrimitives = function () { }; Scratch3MotionBlocks.prototype.moveSteps = function (args, util) { - var steps = Cast.toNumber(args.STEPS); - var radians = MathUtil.degToRad(90 - util.target.direction); - var dx = steps * Math.cos(radians); - var dy = steps * Math.sin(radians); + const steps = Cast.toNumber(args.STEPS); + const radians = MathUtil.degToRad(90 - util.target.direction); + const dx = steps * Math.cos(radians); + const dy = steps * Math.sin(radians); util.target.setXY(util.target.x + dx, util.target.y + dy); }; Scratch3MotionBlocks.prototype.goToXY = function (args, util) { - var x = Cast.toNumber(args.X); - var y = Cast.toNumber(args.Y); + const x = Cast.toNumber(args.X); + const y = Cast.toNumber(args.Y); util.target.setXY(x, y); }; Scratch3MotionBlocks.prototype.goTo = function (args, util) { - var targetX = 0; - var targetY = 0; + let targetX = 0; + let targetY = 0; if (args.TO === '_mouse_') { targetX = util.ioQuery('mouse', 'getX'); targetY = util.ioQuery('mouse', 'getY'); } else if (args.TO === '_random_') { - var stageWidth = this.runtime.constructor.STAGE_WIDTH; - var stageHeight = this.runtime.constructor.STAGE_HEIGHT; + const stageWidth = this.runtime.constructor.STAGE_WIDTH; + const stageHeight = this.runtime.constructor.STAGE_HEIGHT; targetX = Math.round(stageWidth * (Math.random() - 0.5)); targetY = Math.round(stageHeight * (Math.random() - 0.5)); } else { - var goToTarget = this.runtime.getSpriteTargetByName(args.TO); + const goToTarget = this.runtime.getSpriteTargetByName(args.TO); if (!goToTarget) return; targetX = goToTarget.x; targetY = goToTarget.y; @@ -71,36 +71,36 @@ Scratch3MotionBlocks.prototype.goTo = function (args, util) { }; Scratch3MotionBlocks.prototype.turnRight = function (args, util) { - var degrees = Cast.toNumber(args.DEGREES); + const degrees = Cast.toNumber(args.DEGREES); util.target.setDirection(util.target.direction + degrees); }; Scratch3MotionBlocks.prototype.turnLeft = function (args, util) { - var degrees = Cast.toNumber(args.DEGREES); + const degrees = Cast.toNumber(args.DEGREES); util.target.setDirection(util.target.direction - degrees); }; Scratch3MotionBlocks.prototype.pointInDirection = function (args, util) { - var direction = Cast.toNumber(args.DIRECTION); + const direction = Cast.toNumber(args.DIRECTION); util.target.setDirection(direction); }; Scratch3MotionBlocks.prototype.pointTowards = function (args, util) { - var targetX = 0; - var targetY = 0; + let targetX = 0; + let targetY = 0; if (args.TOWARDS === '_mouse_') { targetX = util.ioQuery('mouse', 'getX'); targetY = util.ioQuery('mouse', 'getY'); } else { - var pointTarget = this.runtime.getSpriteTargetByName(args.TOWARDS); + const pointTarget = this.runtime.getSpriteTargetByName(args.TOWARDS); if (!pointTarget) return; targetX = pointTarget.x; targetY = pointTarget.y; } - var dx = targetX - util.target.x; - var dy = targetY - util.target.y; - var direction = 90 - MathUtil.radToDeg(Math.atan2(dy, dx)); + const dx = targetX - util.target.x; + const dy = targetY - util.target.y; + const direction = 90 - MathUtil.radToDeg(Math.atan2(dy, dx)); util.target.setDirection(direction); }; @@ -121,12 +121,12 @@ Scratch3MotionBlocks.prototype.glide = function (args, util) { } util.yield(); } else { - var timeElapsed = util.stackFrame.timer.timeElapsed(); + const timeElapsed = util.stackFrame.timer.timeElapsed(); if (timeElapsed < util.stackFrame.duration * 1000) { // In progress: move to intermediate position. - var frac = timeElapsed / (util.stackFrame.duration * 1000); - var dx = frac * (util.stackFrame.endX - util.stackFrame.startX); - var dy = frac * (util.stackFrame.endY - util.stackFrame.startY); + const frac = timeElapsed / (util.stackFrame.duration * 1000); + const dx = frac * (util.stackFrame.endX - util.stackFrame.startX); + const dy = frac * (util.stackFrame.endY - util.stackFrame.startY); util.target.setXY( util.stackFrame.startX + dx, util.stackFrame.startY + dy @@ -140,22 +140,22 @@ Scratch3MotionBlocks.prototype.glide = function (args, util) { }; Scratch3MotionBlocks.prototype.ifOnEdgeBounce = function (args, util) { - var bounds = util.target.getBounds(); + const bounds = util.target.getBounds(); if (!bounds) { return; } // Measure distance to edges. // Values are positive when the sprite is far away, // and clamped to zero when the sprite is beyond. - var stageWidth = this.runtime.constructor.STAGE_WIDTH; - var stageHeight = this.runtime.constructor.STAGE_HEIGHT; - var distLeft = Math.max(0, (stageWidth / 2) + bounds.left); - var distTop = Math.max(0, (stageHeight / 2) - bounds.top); - var distRight = Math.max(0, (stageWidth / 2) - bounds.right); - var distBottom = Math.max(0, (stageHeight / 2) + bounds.bottom); + const stageWidth = this.runtime.constructor.STAGE_WIDTH; + const stageHeight = this.runtime.constructor.STAGE_HEIGHT; + const distLeft = Math.max(0, (stageWidth / 2) + bounds.left); + const distTop = Math.max(0, (stageHeight / 2) - bounds.top); + const distRight = Math.max(0, (stageWidth / 2) - bounds.right); + const distBottom = Math.max(0, (stageHeight / 2) + bounds.bottom); // Find the nearest edge. - var nearestEdge = ''; - var minDist = Infinity; + let nearestEdge = ''; + let minDist = Infinity; if (distLeft < minDist) { minDist = distLeft; nearestEdge = 'left'; @@ -176,9 +176,9 @@ Scratch3MotionBlocks.prototype.ifOnEdgeBounce = function (args, util) { return; // Not touching any edge. } // Point away from the nearest edge. - var radians = MathUtil.degToRad(90 - util.target.direction); - var dx = Math.cos(radians); - var dy = -Math.sin(radians); + const radians = MathUtil.degToRad(90 - util.target.direction); + let dx = Math.cos(radians); + let dy = -Math.sin(radians); if (nearestEdge === 'left') { dx = Math.max(0.2, Math.abs(dx)); } else if (nearestEdge === 'top') { @@ -188,10 +188,10 @@ Scratch3MotionBlocks.prototype.ifOnEdgeBounce = function (args, util) { } else if (nearestEdge === 'bottom') { dy = 0 - Math.max(0.2, Math.abs(dy)); } - var newDirection = MathUtil.radToDeg(Math.atan2(dy, dx)) + 90; + const newDirection = MathUtil.radToDeg(Math.atan2(dy, dx)) + 90; util.target.setDirection(newDirection); // Keep within the stage. - var fencedPosition = util.target.keepInFence(util.target.x, util.target.y); + const fencedPosition = util.target.keepInFence(util.target.x, util.target.y); util.target.setXY(fencedPosition[0], fencedPosition[1]); }; @@ -200,22 +200,22 @@ Scratch3MotionBlocks.prototype.setRotationStyle = function (args, util) { }; Scratch3MotionBlocks.prototype.changeX = function (args, util) { - var dx = Cast.toNumber(args.DX); + const dx = Cast.toNumber(args.DX); util.target.setXY(util.target.x + dx, util.target.y); }; Scratch3MotionBlocks.prototype.setX = function (args, util) { - var x = Cast.toNumber(args.X); + const x = Cast.toNumber(args.X); util.target.setXY(x, util.target.y); }; Scratch3MotionBlocks.prototype.changeY = function (args, util) { - var dy = Cast.toNumber(args.DY); + const dy = Cast.toNumber(args.DY); util.target.setXY(util.target.x, util.target.y + dy); }; Scratch3MotionBlocks.prototype.setY = function (args, util) { - var y = Cast.toNumber(args.Y); + const y = Cast.toNumber(args.Y); util.target.setXY(util.target.x, y); }; diff --git a/src/blocks/scratch3_operators.js b/src/blocks/scratch3_operators.js index fce7fb3a7e2..54a983c9060 100644 --- a/src/blocks/scratch3_operators.js +++ b/src/blocks/scratch3_operators.js @@ -1,7 +1,7 @@ -var Cast = require('../util/cast.js'); -var MathUtil = require('../util/math-util.js'); +const Cast = require('../util/cast.js'); +const MathUtil = require('../util/math-util.js'); -var Scratch3OperatorsBlocks = function (runtime) { +const Scratch3OperatorsBlocks = function (runtime) { /** * The runtime instantiating this block package. * @type {Runtime} @@ -76,10 +76,10 @@ Scratch3OperatorsBlocks.prototype.not = function (args) { }; Scratch3OperatorsBlocks.prototype.random = function (args) { - var nFrom = Cast.toNumber(args.FROM); - var nTo = Cast.toNumber(args.TO); - var low = nFrom <= nTo ? nFrom : nTo; - var high = nFrom <= nTo ? nTo : nFrom; + const nFrom = Cast.toNumber(args.FROM); + const nTo = Cast.toNumber(args.TO); + const low = nFrom <= nTo ? nFrom : nTo; + const high = nFrom <= nTo ? nTo : nFrom; if (low === high) return low; // If both arguments are ints, truncate the result to an int. if (Cast.isInt(args.FROM) && Cast.isInt(args.TO)) { @@ -93,8 +93,8 @@ Scratch3OperatorsBlocks.prototype.join = function (args) { }; Scratch3OperatorsBlocks.prototype.letterOf = function (args) { - var index = Cast.toNumber(args.LETTER) - 1; - var str = Cast.toString(args.STRING); + const index = Cast.toNumber(args.LETTER) - 1; + const str = Cast.toString(args.STRING); // Out of bounds? if (index < 0 || index >= str.length) { return ''; @@ -107,9 +107,9 @@ Scratch3OperatorsBlocks.prototype.length = function (args) { }; Scratch3OperatorsBlocks.prototype.mod = function (args) { - var n = Cast.toNumber(args.NUM1); - var modulus = Cast.toNumber(args.NUM2); - var result = n % modulus; + const n = Cast.toNumber(args.NUM1); + const modulus = Cast.toNumber(args.NUM2); + let result = n % modulus; // Scratch mod is kept positive. if (result / modulus < 0) result += modulus; return result; @@ -120,8 +120,8 @@ Scratch3OperatorsBlocks.prototype.round = function (args) { }; Scratch3OperatorsBlocks.prototype.mathop = function (args) { - var operator = Cast.toString(args.OPERATOR).toLowerCase(); - var n = Cast.toNumber(args.NUM); + const operator = Cast.toString(args.OPERATOR).toLowerCase(); + const n = Cast.toNumber(args.NUM); switch (operator) { case 'abs': return Math.abs(n); case 'floor': return Math.floor(n); diff --git a/src/blocks/scratch3_pen.js b/src/blocks/scratch3_pen.js index 9b9f64919b5..4f59492d8ed 100644 --- a/src/blocks/scratch3_pen.js +++ b/src/blocks/scratch3_pen.js @@ -1,8 +1,8 @@ -var Cast = require('../util/cast'); -var Clone = require('../util/clone'); -var Color = require('../util/color'); -var MathUtil = require('../util/math-util'); -var RenderedTarget = require('../sprites/rendered-target'); +const Cast = require('../util/cast'); +const Clone = require('../util/clone'); +const Color = require('../util/color'); +const MathUtil = require('../util/math-util'); +const RenderedTarget = require('../sprites/rendered-target'); /** * @typedef {object} PenState - the pen state associated with a particular target. @@ -18,7 +18,7 @@ var RenderedTarget = require('../sprites/rendered-target'); * @param {Runtime} runtime - the runtime instantiating this block package. * @constructor */ -var Scratch3PenBlocks = function (runtime) { +const Scratch3PenBlocks = function (runtime) { /** * The runtime instantiating this block package. * @type {Runtime} @@ -107,7 +107,7 @@ Scratch3PenBlocks.prototype._getPenLayerID = function () { * @private */ Scratch3PenBlocks.prototype._getPenState = function (target) { - var penState = target.getCustomState(Scratch3PenBlocks.STATE_KEY); + let penState = target.getCustomState(Scratch3PenBlocks.STATE_KEY); if (!penState) { penState = Clone.simple(Scratch3PenBlocks.DEFAULT_PEN_STATE); target.setCustomState(Scratch3PenBlocks.STATE_KEY, penState); @@ -123,9 +123,9 @@ Scratch3PenBlocks.prototype._getPenState = function (target) { * @private */ Scratch3PenBlocks.prototype._onTargetMoved = function (target, oldX, oldY) { - var penSkinId = this._getPenLayerID(); + const penSkinId = this._getPenLayerID(); if (penSkinId >= 0) { - var penState = this._getPenState(target); + const penState = this._getPenState(target); this.runtime.renderer.penLine(penSkinId, penState.penAttributes, oldX, oldY, target.x, target.y); this.runtime.requestRedraw(); } @@ -137,8 +137,8 @@ Scratch3PenBlocks.prototype._onTargetMoved = function (target, oldX, oldY) { * @private */ Scratch3PenBlocks.prototype._updatePenColor = function (penState) { - var rgb = Color.hsvToRgb({h: penState.hue * 180 / 100, s: 1, v: 1}); - var shade = (penState.shade > 100) ? 200 - penState.shade : penState.shade; + let rgb = Color.hsvToRgb({h: penState.hue * 180 / 100, s: 1, v: 1}); + const shade = (penState.shade > 100) ? 200 - penState.shade : penState.shade; if (shade < 50) { rgb = Color.mixRgb(Color.RGB_BLACK, rgb, (10 + shade) / 60); } else { @@ -186,7 +186,7 @@ Scratch3PenBlocks.prototype.getPrimitives = function () { * The pen "clear" block clears the pen layer's contents. */ Scratch3PenBlocks.prototype.clear = function () { - var penSkinId = this._getPenLayerID(); + const penSkinId = this._getPenLayerID(); if (penSkinId >= 0) { this.runtime.renderer.penClear(penSkinId); this.runtime.requestRedraw(); @@ -199,9 +199,9 @@ Scratch3PenBlocks.prototype.clear = function () { * @param {object} util - utility object provided by the runtime. */ Scratch3PenBlocks.prototype.stamp = function (args, util) { - var penSkinId = this._getPenLayerID(); + const penSkinId = this._getPenLayerID(); if (penSkinId >= 0) { - var target = util.target; + const target = util.target; this.runtime.renderer.penStamp(penSkinId, target.drawableID); this.runtime.requestRedraw(); } @@ -213,15 +213,15 @@ Scratch3PenBlocks.prototype.stamp = function (args, util) { * @param {object} util - utility object provided by the runtime. */ Scratch3PenBlocks.prototype.penDown = function (args, util) { - var target = util.target; - var penState = this._getPenState(target); + const target = util.target; + const penState = this._getPenState(target); if (!penState.penDown) { penState.penDown = true; target.addListener(RenderedTarget.EVENT_TARGET_MOVED, this._onTargetMoved); } - var penSkinId = this._getPenLayerID(); + const penSkinId = this._getPenLayerID(); if (penSkinId >= 0) { this.runtime.renderer.penPoint(penSkinId, penState.penAttributes, target.x, target.y); this.runtime.requestRedraw(); @@ -234,8 +234,8 @@ Scratch3PenBlocks.prototype.penDown = function (args, util) { * @param {object} util - utility object provided by the runtime. */ Scratch3PenBlocks.prototype.penUp = function (args, util) { - var target = util.target; - var penState = this._getPenState(target); + const target = util.target; + const penState = this._getPenState(target); if (penState.penDown) { penState.penDown = false; @@ -250,9 +250,9 @@ Scratch3PenBlocks.prototype.penUp = function (args, util) { * @param {object} util - utility object provided by the runtime. */ Scratch3PenBlocks.prototype.setPenColorToColor = function (args, util) { - var penState = this._getPenState(util.target); - var rgb = Cast.toRgbColorObject(args.COLOR); - var hsv = Color.rgbToHsv(rgb); + const penState = this._getPenState(util.target); + const rgb = Cast.toRgbColorObject(args.COLOR); + const hsv = Color.rgbToHsv(rgb); penState.hue = 200 * hsv.h / 360; penState.shade = 50 * hsv.v; @@ -273,7 +273,7 @@ Scratch3PenBlocks.prototype.setPenColorToColor = function (args, util) { * @param {object} util - utility object provided by the runtime. */ Scratch3PenBlocks.prototype.changePenHueBy = function (args, util) { - var penState = this._getPenState(util.target); + const penState = this._getPenState(util.target); penState.hue = this._wrapHueOrShade(penState.hue + Cast.toNumber(args.COLOR)); this._updatePenColor(penState); }; @@ -285,7 +285,7 @@ Scratch3PenBlocks.prototype.changePenHueBy = function (args, util) { * @param {object} util - utility object provided by the runtime. */ Scratch3PenBlocks.prototype.setPenHueToNumber = function (args, util) { - var penState = this._getPenState(util.target); + const penState = this._getPenState(util.target); penState.hue = this._wrapHueOrShade(Cast.toNumber(args.COLOR)); this._updatePenColor(penState); }; @@ -297,7 +297,7 @@ Scratch3PenBlocks.prototype.setPenHueToNumber = function (args, util) { * @param {object} util - utility object provided by the runtime. */ Scratch3PenBlocks.prototype.changePenShadeBy = function (args, util) { - var penState = this._getPenState(util.target); + const penState = this._getPenState(util.target); penState.shade = this._wrapHueOrShade(penState.shade + Cast.toNumber(args.SHADE)); this._updatePenColor(penState); }; @@ -309,7 +309,7 @@ Scratch3PenBlocks.prototype.changePenShadeBy = function (args, util) { * @param {object} util - utility object provided by the runtime. */ Scratch3PenBlocks.prototype.setPenShadeToNumber = function (args, util) { - var penState = this._getPenState(util.target); + const penState = this._getPenState(util.target); penState.shade = this._wrapHueOrShade(Cast.toNumber(args.SHADE)); this._updatePenColor(penState); }; @@ -321,7 +321,7 @@ Scratch3PenBlocks.prototype.setPenShadeToNumber = function (args, util) { * @param {object} util - utility object provided by the runtime. */ Scratch3PenBlocks.prototype.changePenSizeBy = function (args, util) { - var penAttributes = this._getPenState(util.target).penAttributes; + const penAttributes = this._getPenState(util.target).penAttributes; penAttributes.diameter = this._clampPenSize(penAttributes.diameter + Cast.toNumber(args.SIZE)); }; @@ -332,7 +332,7 @@ Scratch3PenBlocks.prototype.changePenSizeBy = function (args, util) { * @param {object} util - utility object provided by the runtime. */ Scratch3PenBlocks.prototype.setPenSizeTo = function (args, util) { - var penAttributes = this._getPenState(util.target).penAttributes; + const penAttributes = this._getPenState(util.target).penAttributes; penAttributes.diameter = this._clampPenSize(Cast.toNumber(args.SIZE)); }; diff --git a/src/blocks/scratch3_procedures.js b/src/blocks/scratch3_procedures.js index 471205f4890..549ecb3c7c6 100644 --- a/src/blocks/scratch3_procedures.js +++ b/src/blocks/scratch3_procedures.js @@ -1,4 +1,4 @@ -var Scratch3ProcedureBlocks = function (runtime) { +const Scratch3ProcedureBlocks = function (runtime) { /** * The runtime instantiating this block package. * @type {Runtime} @@ -24,11 +24,11 @@ Scratch3ProcedureBlocks.prototype.defNoReturn = function () { Scratch3ProcedureBlocks.prototype.callNoReturn = function (args, util) { if (!util.stackFrame.executed) { - var procedureCode = args.mutation.proccode; - var paramNames = util.getProcedureParamNames(procedureCode); - for (var i = 0; i < paramNames.length; i++) { - if (args.hasOwnProperty('input' + i)) { - util.pushParam(paramNames[i], args['input' + i]); + const procedureCode = args.mutation.proccode; + const paramNames = util.getProcedureParamNames(procedureCode); + for (let i = 0; i < paramNames.length; i++) { + if (args.hasOwnProperty(`input${i}`)) { + util.pushParam(paramNames[i], args[`input${i}`]); } } util.stackFrame.executed = true; @@ -37,7 +37,7 @@ Scratch3ProcedureBlocks.prototype.callNoReturn = function (args, util) { }; Scratch3ProcedureBlocks.prototype.param = function (args, util) { - var value = util.getParam(args.mutation.paramname); + const value = util.getParam(args.mutation.paramname); return value; }; diff --git a/src/blocks/scratch3_sensing.js b/src/blocks/scratch3_sensing.js index 8c43e7636e2..272342840b9 100644 --- a/src/blocks/scratch3_sensing.js +++ b/src/blocks/scratch3_sensing.js @@ -1,6 +1,6 @@ -var Cast = require('../util/cast'); +const Cast = require('../util/cast'); -var Scratch3SensingBlocks = function (runtime) { +const Scratch3SensingBlocks = function (runtime) { /** * The runtime instantiating this block package. * @type {Runtime} @@ -32,39 +32,39 @@ Scratch3SensingBlocks.prototype.getPrimitives = function () { }; Scratch3SensingBlocks.prototype.touchingObject = function (args, util) { - var requestedObject = args.TOUCHINGOBJECTMENU; + const requestedObject = args.TOUCHINGOBJECTMENU; if (requestedObject === '_mouse_') { - var mouseX = util.ioQuery('mouse', 'getX'); - var mouseY = util.ioQuery('mouse', 'getY'); + const mouseX = util.ioQuery('mouse', 'getX'); + const mouseY = util.ioQuery('mouse', 'getY'); return util.target.isTouchingPoint(mouseX, mouseY); } else if (requestedObject === '_edge_') { return util.target.isTouchingEdge(); - } else { - return util.target.isTouchingSprite(requestedObject); } + return util.target.isTouchingSprite(requestedObject); + }; Scratch3SensingBlocks.prototype.touchingColor = function (args, util) { - var color = Cast.toRgbColorList(args.COLOR); + const color = Cast.toRgbColorList(args.COLOR); return util.target.isTouchingColor(color); }; Scratch3SensingBlocks.prototype.colorTouchingColor = function (args, util) { - var maskColor = Cast.toRgbColorList(args.COLOR); - var targetColor = Cast.toRgbColorList(args.COLOR2); + const maskColor = Cast.toRgbColorList(args.COLOR); + const targetColor = Cast.toRgbColorList(args.COLOR2); return util.target.colorIsTouchingColor(targetColor, maskColor); }; Scratch3SensingBlocks.prototype.distanceTo = function (args, util) { if (util.target.isStage) return 10000; - var targetX = 0; - var targetY = 0; + let targetX = 0; + let targetY = 0; if (args.DISTANCETOMENU === '_mouse_') { targetX = util.ioQuery('mouse', 'getX'); targetY = util.ioQuery('mouse', 'getY'); } else { - var distTarget = this.runtime.getSpriteTargetByName( + const distTarget = this.runtime.getSpriteTargetByName( args.DISTANCETOMENU ); if (!distTarget) return 10000; @@ -72,8 +72,8 @@ Scratch3SensingBlocks.prototype.distanceTo = function (args, util) { targetY = distTarget.y; } - var dx = util.target.x - targetX; - var dy = util.target.y - targetY; + const dx = util.target.x - targetX; + const dy = util.target.y - targetY; return Math.sqrt((dx * dx) + (dy * dy)); }; @@ -98,8 +98,8 @@ Scratch3SensingBlocks.prototype.getMouseDown = function (args, util) { }; Scratch3SensingBlocks.prototype.current = function (args) { - var menuOption = Cast.toString(args.CURRENTMENU).toLowerCase(); - var date = new Date(); + const menuOption = Cast.toString(args.CURRENTMENU).toLowerCase(); + const date = new Date(); switch (menuOption) { case 'year': return date.getFullYear(); case 'month': return date.getMonth() + 1; // getMonth is zero-based @@ -117,11 +117,11 @@ Scratch3SensingBlocks.prototype.getKeyPressed = function (args, util) { }; Scratch3SensingBlocks.prototype.daysSince2000 = function () { - var msPerDay = 24 * 60 * 60 * 1000; - var start = new Date(2000, 0, 1); // Months are 0-indexed. - var today = new Date(); - var dstAdjust = today.getTimezoneOffset() - start.getTimezoneOffset(); - var mSecsSinceStart = today.valueOf() - start.valueOf(); + const msPerDay = 24 * 60 * 60 * 1000; + const start = new Date(2000, 0, 1); // Months are 0-indexed. + const today = new Date(); + const dstAdjust = today.getTimezoneOffset() - start.getTimezoneOffset(); + let mSecsSinceStart = today.valueOf() - start.valueOf(); mSecsSinceStart += ((today.getTimezoneOffset() - dstAdjust) * 60 * 1000); return mSecsSinceStart / msPerDay; }; @@ -132,7 +132,7 @@ Scratch3SensingBlocks.prototype.getLoudness = function () { }; Scratch3SensingBlocks.prototype.getAttributeOf = function (args) { - var attrTarget; + let attrTarget; if (args.OBJECT === '_stage_') { attrTarget = this.runtime.getTargetForStage(); @@ -165,7 +165,7 @@ Scratch3SensingBlocks.prototype.getAttributeOf = function (args) { } // Variables - var varName = args.PROPERTY; + const varName = args.PROPERTY; if (attrTarget.variables.hasOwnProperty(varName)) { return attrTarget.variables[varName].value; } diff --git a/src/blocks/scratch3_sound.js b/src/blocks/scratch3_sound.js index c60e41fb03c..098c1c0fae6 100644 --- a/src/blocks/scratch3_sound.js +++ b/src/blocks/scratch3_sound.js @@ -1,8 +1,8 @@ -var MathUtil = require('../util/math-util'); -var Cast = require('../util/cast'); -var Clone = require('../util/clone'); +const MathUtil = require('../util/math-util'); +const Cast = require('../util/cast'); +const Clone = require('../util/clone'); -var Scratch3SoundBlocks = function (runtime) { +const Scratch3SoundBlocks = function (runtime) { /** * The runtime instantiating this block package. * @type {Runtime} @@ -69,7 +69,7 @@ Scratch3SoundBlocks.EFFECT_RANGE = { * @private */ Scratch3SoundBlocks.prototype._getSoundState = function (target) { - var soundState = target.getCustomState(Scratch3SoundBlocks.STATE_KEY); + let soundState = target.getCustomState(Scratch3SoundBlocks.STATE_KEY); if (!soundState) { soundState = Clone.simple(Scratch3SoundBlocks.DEFAULT_SOUND_STATE); target.setCustomState(Scratch3SoundBlocks.STATE_KEY, soundState); @@ -106,18 +106,18 @@ Scratch3SoundBlocks.prototype.getPrimitives = function () { }; Scratch3SoundBlocks.prototype.playSound = function (args, util) { - var index = this._getSoundIndex(args.SOUND_MENU, util); + const index = this._getSoundIndex(args.SOUND_MENU, util); if (index >= 0) { - var md5 = util.target.sprite.sounds[index].md5; + const md5 = util.target.sprite.sounds[index].md5; if (util.target.audioPlayer === null) return; util.target.audioPlayer.playSound(md5); } }; Scratch3SoundBlocks.prototype.playSoundAndWait = function (args, util) { - var index = this._getSoundIndex(args.SOUND_MENU, util); + const index = this._getSoundIndex(args.SOUND_MENU, util); if (index >= 0) { - var md5 = util.target.sprite.sounds[index].md5; + const md5 = util.target.sprite.sounds[index].md5; if (util.target.audioPlayer === null) return; return util.target.audioPlayer.playSound(md5); } @@ -125,15 +125,15 @@ Scratch3SoundBlocks.prototype.playSoundAndWait = function (args, util) { Scratch3SoundBlocks.prototype._getSoundIndex = function (soundName, util) { // if the sprite has no sounds, return -1 - var len = util.target.sprite.sounds.length; + const len = util.target.sprite.sounds.length; if (len === 0) { return -1; } - var index; + let index; // try to convert to a number and use that as an index - var num = parseInt(soundName, 10); + const num = parseInt(soundName, 10); if (!isNaN(num)) { index = MathUtil.wrapClamp(num, 0, len - 1); return index; @@ -145,8 +145,8 @@ Scratch3SoundBlocks.prototype._getSoundIndex = function (soundName, util) { }; Scratch3SoundBlocks.prototype.getSoundIndexByName = function (soundName, util) { - var sounds = util.target.sprite.sounds; - for (var i = 0; i < sounds.length; i++) { + const sounds = util.target.sprite.sounds; + for (let i = 0; i < sounds.length; i++) { if (sounds[i].name === soundName) { return i; } @@ -161,30 +161,30 @@ Scratch3SoundBlocks.prototype.stopAllSounds = function (args, util) { }; Scratch3SoundBlocks.prototype.playNoteForBeats = function (args, util) { - var note = Cast.toNumber(args.NOTE); + let note = Cast.toNumber(args.NOTE); note = MathUtil.clamp(note, Scratch3SoundBlocks.MIDI_NOTE_RANGE.min, Scratch3SoundBlocks.MIDI_NOTE_RANGE.max); - var beats = Cast.toNumber(args.BEATS); + let beats = Cast.toNumber(args.BEATS); beats = this._clampBeats(beats); - var soundState = this._getSoundState(util.target); - var inst = soundState.currentInstrument; - var vol = soundState.volume; + const soundState = this._getSoundState(util.target); + const inst = soundState.currentInstrument; + const vol = soundState.volume; if (typeof this.runtime.audioEngine === 'undefined') return; return this.runtime.audioEngine.playNoteForBeatsWithInstAndVol(note, beats, inst, vol); }; Scratch3SoundBlocks.prototype.playDrumForBeats = function (args, util) { - var drum = Cast.toNumber(args.DRUM); + let drum = Cast.toNumber(args.DRUM); drum -= 1; // drums are one-indexed if (typeof this.runtime.audioEngine === 'undefined') return; drum = MathUtil.wrapClamp(drum, 0, this.runtime.audioEngine.numDrums); - var beats = Cast.toNumber(args.BEATS); + let beats = Cast.toNumber(args.BEATS); beats = this._clampBeats(beats); if (util.target.audioPlayer === null) return; return util.target.audioPlayer.playDrumForBeats(drum, beats); }; Scratch3SoundBlocks.prototype.restForBeats = function (args) { - var beats = Cast.toNumber(args.BEATS); + let beats = Cast.toNumber(args.BEATS); beats = this._clampBeats(beats); if (typeof this.runtime.audioEngine === 'undefined') return; return this.runtime.audioEngine.waitForBeats(beats); @@ -195,8 +195,8 @@ Scratch3SoundBlocks.prototype._clampBeats = function (beats) { }; Scratch3SoundBlocks.prototype.setInstrument = function (args, util) { - var soundState = this._getSoundState(util.target); - var instNum = Cast.toNumber(args.INSTRUMENT); + const soundState = this._getSoundState(util.target); + let instNum = Cast.toNumber(args.INSTRUMENT); instNum -= 1; // instruments are one-indexed if (typeof this.runtime.audioEngine === 'undefined') return; instNum = MathUtil.wrapClamp(instNum, 0, this.runtime.audioEngine.numInstruments); @@ -213,10 +213,10 @@ Scratch3SoundBlocks.prototype.changeEffect = function (args, util) { }; Scratch3SoundBlocks.prototype._updateEffect = function (args, util, change) { - var effect = Cast.toString(args.EFFECT).toLowerCase(); - var value = Cast.toNumber(args.VALUE); + const effect = Cast.toString(args.EFFECT).toLowerCase(); + const value = Cast.toNumber(args.VALUE); - var soundState = this._getSoundState(util.target); + const soundState = this._getSoundState(util.target); if (!soundState.effects.hasOwnProperty(effect)) return; if (change) { @@ -225,7 +225,7 @@ Scratch3SoundBlocks.prototype._updateEffect = function (args, util, change) { soundState.effects[effect] = value; } - var effectRange = Scratch3SoundBlocks.EFFECT_RANGE[effect]; + const effectRange = Scratch3SoundBlocks.EFFECT_RANGE[effect]; soundState.effects[effect] = MathUtil.clamp(soundState.effects[effect], effectRange.min, effectRange.max); if (util.target.audioPlayer === null) return; @@ -233,8 +233,8 @@ Scratch3SoundBlocks.prototype._updateEffect = function (args, util, change) { }; Scratch3SoundBlocks.prototype.clearEffects = function (args, util) { - var soundState = this._getSoundState(util.target); - for (var effect in soundState.effects) { + const soundState = this._getSoundState(util.target); + for (const effect in soundState.effects) { if (!soundState.effects.hasOwnProperty(effect)) continue; soundState.effects[effect] = 0; } @@ -243,18 +243,18 @@ Scratch3SoundBlocks.prototype.clearEffects = function (args, util) { }; Scratch3SoundBlocks.prototype.setVolume = function (args, util) { - var volume = Cast.toNumber(args.VOLUME); + const volume = Cast.toNumber(args.VOLUME); this._updateVolume(volume, util); }; Scratch3SoundBlocks.prototype.changeVolume = function (args, util) { - var soundState = this._getSoundState(util.target); - var volume = Cast.toNumber(args.VOLUME) + soundState.volume; + const soundState = this._getSoundState(util.target); + const volume = Cast.toNumber(args.VOLUME) + soundState.volume; this._updateVolume(volume, util); }; Scratch3SoundBlocks.prototype._updateVolume = function (volume, util) { - var soundState = this._getSoundState(util.target); + const soundState = this._getSoundState(util.target); volume = MathUtil.clamp(volume, 0, 100); soundState.volume = volume; if (util.target.audioPlayer === null) return; @@ -262,19 +262,19 @@ Scratch3SoundBlocks.prototype._updateVolume = function (volume, util) { }; Scratch3SoundBlocks.prototype.getVolume = function (args, util) { - var soundState = this._getSoundState(util.target); + const soundState = this._getSoundState(util.target); return soundState.volume; }; Scratch3SoundBlocks.prototype.setTempo = function (args) { - var tempo = Cast.toNumber(args.TEMPO); + const tempo = Cast.toNumber(args.TEMPO); this._updateTempo(tempo); }; Scratch3SoundBlocks.prototype.changeTempo = function (args) { - var change = Cast.toNumber(args.TEMPO); + const change = Cast.toNumber(args.TEMPO); if (typeof this.runtime.audioEngine === 'undefined') return; - var tempo = change + this.runtime.audioEngine.currentTempo; + const tempo = change + this.runtime.audioEngine.currentTempo; this._updateTempo(tempo); }; diff --git a/src/engine/adapter.js b/src/engine/adapter.js index 88c8a18c50b..68a098c670e 100644 --- a/src/engine/adapter.js +++ b/src/engine/adapter.js @@ -1,5 +1,5 @@ -var mutationAdapter = require('./mutation-adapter'); -var html = require('htmlparser2'); +const mutationAdapter = require('./mutation-adapter'); +const html = require('htmlparser2'); /** * Convert outer blocks DOM from a Blockly CREATE event @@ -8,22 +8,22 @@ var html = require('htmlparser2'); * @param {Element} blocksDOM DOM tree for this event. * @return {Array.} Usable list of blocks from this CREATE event. */ -var domToBlocks = function (blocksDOM) { +const domToBlocks = function (blocksDOM) { // At this level, there could be multiple blocks adjacent in the DOM tree. - var blocks = {}; - for (var i = 0; i < blocksDOM.length; i++) { - var block = blocksDOM[i]; + const blocks = {}; + for (let i = 0; i < blocksDOM.length; i++) { + const block = blocksDOM[i]; if (!block.name || !block.attribs) { continue; } - var tagName = block.name.toLowerCase(); + const tagName = block.name.toLowerCase(); if (tagName === 'block' || tagName === 'shadow') { domToBlock(block, blocks, true, null); } } // Flatten blocks object into a list. - var blocksList = []; - for (var b in blocks) { + const blocksList = []; + for (const b in blocks) { if (!blocks.hasOwnProperty(b)) continue; blocksList.push(blocks[b]); } @@ -36,7 +36,7 @@ var domToBlocks = function (blocksDOM) { * @param {object} e `Blockly.events.create` * @return {Array.} List of blocks from this CREATE event. */ -var adapter = function (e) { +const adapter = function (e) { // Validate input if (typeof e !== 'object') return; if (typeof e.xml !== 'object') return; @@ -55,7 +55,7 @@ var adapter = function (e) { */ var domToBlock = function (blockDOM, blocks, isTopBlock, parent) { // Block skeleton. - var block = { + const block = { id: blockDOM.attribs.id, // Block ID opcode: blockDOM.attribs.type, // For execution, "event_whengreenflag". inputs: {}, // Inputs to this block and the blocks they point to. @@ -72,18 +72,18 @@ var domToBlock = function (blockDOM, blocks, isTopBlock, parent) { blocks[block.id] = block; // Process XML children and find enclosed blocks, fields, etc. - for (var i = 0; i < blockDOM.children.length; i++) { - var xmlChild = blockDOM.children[i]; + for (let i = 0; i < blockDOM.children.length; i++) { + const xmlChild = blockDOM.children[i]; // Enclosed blocks and shadows - var childBlockNode = null; - var childShadowNode = null; - for (var j = 0; j < xmlChild.children.length; j++) { - var grandChildNode = xmlChild.children[j]; + let childBlockNode = null; + let childShadowNode = null; + for (let j = 0; j < xmlChild.children.length; j++) { + const grandChildNode = xmlChild.children[j]; if (!grandChildNode.name) { // Non-XML tag node. continue; } - var grandChildNodeName = grandChildNode.name.toLowerCase(); + const grandChildNodeName = grandChildNode.name.toLowerCase(); if (grandChildNodeName === 'block') { childBlockNode = grandChildNode; } else if (grandChildNodeName === 'shadow') { diff --git a/src/engine/blocks.js b/src/engine/blocks.js index e1852119689..1b562f0d9b5 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -1,6 +1,6 @@ -var adapter = require('./adapter'); -var mutationAdapter = require('./mutation-adapter'); -var xmlEscape = require('../util/xml-escape'); +const adapter = require('./adapter'); +const mutationAdapter = require('./mutation-adapter'); +const xmlEscape = require('../util/xml-escape'); /** * @fileoverview @@ -8,7 +8,7 @@ var xmlEscape = require('../util/xml-escape'); * and handle updates from Scratch Blocks events. */ -var Blocks = function () { +const Blocks = function () { /** * All blocks in the workspace. * Keys are block IDs, values are metadata about the block. @@ -54,7 +54,7 @@ Blocks.prototype.getScripts = function () { * @return {?string} ID of next block in the sequence */ Blocks.prototype.getNextBlock = function (id) { - var block = this._blocks[id]; + const block = this._blocks[id]; return (typeof block === 'undefined') ? null : block.next; }; @@ -65,17 +65,17 @@ Blocks.prototype.getNextBlock = function (id) { * @return {?string} ID of block in the branch. */ Blocks.prototype.getBranch = function (id, branchNum) { - var block = this._blocks[id]; + const block = this._blocks[id]; if (typeof block === 'undefined') return null; if (!branchNum) branchNum = 1; - var inputName = Blocks.BRANCH_INPUT_PREFIX; + let inputName = Blocks.BRANCH_INPUT_PREFIX; if (branchNum > 1) { inputName += branchNum; } // Empty C-block? - var input = block.inputs[inputName]; + const input = block.inputs[inputName]; return (typeof input === 'undefined') ? null : input.block; }; @@ -104,8 +104,8 @@ Blocks.prototype.getFields = function (block) { */ Blocks.prototype.getInputs = function (block) { if (typeof block === 'undefined') return null; - var inputs = {}; - for (var input in block.inputs) { + const inputs = {}; + for (const input in block.inputs) { // Ignore blocks prefixed with branch prefix. if (input.substring(0, Blocks.BRANCH_INPUT_PREFIX.length) !== Blocks.BRANCH_INPUT_PREFIX) { @@ -130,7 +130,7 @@ Blocks.prototype.getMutation = function (block) { * @return {?string} ID of top-level script block. */ Blocks.prototype.getTopLevelScript = function (id) { - var block = this._blocks[id]; + let block = this._blocks[id]; if (typeof block === 'undefined') return null; while (block.parent !== null) { block = this._blocks[block.parent]; @@ -144,9 +144,9 @@ Blocks.prototype.getTopLevelScript = function (id) { * @return {?string} ID of procedure definition. */ Blocks.prototype.getProcedureDefinition = function (name) { - for (var id in this._blocks) { + for (const id in this._blocks) { if (!this._blocks.hasOwnProperty(id)) continue; - var block = this._blocks[id]; + const block = this._blocks[id]; if ((block.opcode === 'procedures_defnoreturn' || block.opcode === 'procedures_defreturn') && block.mutation.proccode === name) { @@ -162,9 +162,9 @@ Blocks.prototype.getProcedureDefinition = function (name) { * @return {?string} ID of procedure definition. */ Blocks.prototype.getProcedureParamNames = function (name) { - for (var id in this._blocks) { + for (const id in this._blocks) { if (!this._blocks.hasOwnProperty(id)) continue; - var block = this._blocks[id]; + const block = this._blocks[id]; if ((block.opcode === 'procedures_defnoreturn' || block.opcode === 'procedures_defreturn') && block.mutation.proccode === name) { @@ -201,7 +201,7 @@ Blocks.prototype.blocklyListen = function (e, optRuntime) { case 'create': var newBlocks = adapter(e); // A create event can create many blocks. Add them all. - for (var i = 0; i < newBlocks.length; i++) { + for (let i = 0; i < newBlocks.length; i++) { this.createBlock(newBlocks[i]); } break; @@ -270,7 +270,7 @@ Blocks.prototype.createBlock = function (block) { Blocks.prototype.changeBlock = function (args) { // Validate if (args.element !== 'field' && args.element !== 'mutation') return; - var block = this._blocks[args.id]; + const block = this._blocks[args.id]; if (typeof block === 'undefined') return; if (args.element === 'field') { @@ -299,7 +299,7 @@ Blocks.prototype.moveBlock = function (e) { // Remove from any old parent. if (typeof e.oldParent !== 'undefined') { - var oldParent = this._blocks[e.oldParent]; + const oldParent = this._blocks[e.oldParent]; if (typeof e.oldInput !== 'undefined' && oldParent.inputs[e.oldInput].block === e.id) { // This block was connected to the old parent's input. @@ -324,7 +324,7 @@ Blocks.prototype.moveBlock = function (e) { } else { // Moved to the new parent's input. // Don't obscure the shadow block. - var oldShadow = null; + let oldShadow = null; if (this._blocks[e.newParent].inputs.hasOwnProperty(e.newInput)) { oldShadow = this._blocks[e.newParent].inputs[e.newInput].shadow; } @@ -346,7 +346,7 @@ Blocks.prototype.deleteBlock = function (e) { // @todo In runtime, stop threads running on this script. // Get block - var block = this._blocks[e.id]; + const block = this._blocks[e.id]; // Delete children if (block.next !== null) { @@ -354,7 +354,7 @@ Blocks.prototype.deleteBlock = function (e) { } // Delete inputs (including branches) - for (var input in block.inputs) { + for (const input in block.inputs) { // If it's null, the block in this input moved away. if (block.inputs[input].block !== null) { this.deleteBlock({id: block.inputs[input].block}); @@ -381,11 +381,11 @@ Blocks.prototype.deleteBlock = function (e) { * @return {string} String of XML representing this object's blocks. */ Blocks.prototype.toXML = function () { - var xmlString = ''; - for (var i = 0; i < this._scripts.length; i++) { + let xmlString = ''; + for (let i = 0; i < this._scripts.length; i++) { xmlString += this.blockToXML(this._scripts[i]); } - return xmlString + ''; + return `${xmlString}`; }; /** @@ -395,29 +395,29 @@ Blocks.prototype.toXML = function () { * @return {string} String of XML representing this block and any children. */ Blocks.prototype.blockToXML = function (blockId) { - var block = this._blocks[blockId]; + const block = this._blocks[blockId]; // Encode properties of this block. - var tagName = (block.shadow) ? 'shadow' : 'block'; - var xy = (block.topLevel) ? - ' x="' + block.x + '" y="' + block.y + '"' : + const tagName = (block.shadow) ? 'shadow' : 'block'; + const xy = (block.topLevel) ? + ` x="${block.x}" y="${block.y}"` : ''; - var xmlString = ''; - xmlString += '<' + tagName + - ' id="' + block.id + '"' + - ' type="' + block.opcode + '"' + - xy + - '>'; + let xmlString = ''; + xmlString += `<${tagName + } id="${block.id}"` + + ` type="${block.opcode}"${ + xy + }>`; // Add any mutation. Must come before inputs. if (block.mutation) { xmlString += this.mutationToXML(block.mutation); } // Add any inputs on this block. - for (var input in block.inputs) { + for (const input in block.inputs) { if (!block.inputs.hasOwnProperty(input)) continue; - var blockInput = block.inputs[input]; + const blockInput = block.inputs[input]; // Only encode a value tag if the value input is occupied. if (blockInput.block || blockInput.shadow) { - xmlString += ''; + xmlString += ``; if (blockInput.block) { xmlString += this.blockToXML(blockInput.block); } @@ -429,21 +429,21 @@ Blocks.prototype.blockToXML = function (blockId) { } } // Add any fields on this block. - for (var field in block.fields) { + for (const field in block.fields) { if (!block.fields.hasOwnProperty(field)) continue; - var blockField = block.fields[field]; - var value = blockField.value; + const blockField = block.fields[field]; + let value = blockField.value; if (typeof value === 'string') { value = xmlEscape(blockField.value); } - xmlString += '' + - value + ''; + xmlString += `${ + value}`; } // Add blocks connected to the next connection. if (block.next) { - xmlString += '' + this.blockToXML(block.next) + ''; + xmlString += `${this.blockToXML(block.next)}`; } - xmlString += ''; + xmlString += ``; return xmlString; }; @@ -453,18 +453,18 @@ Blocks.prototype.blockToXML = function (blockId) { * @return {string} XML string representing a mutation. */ Blocks.prototype.mutationToXML = function (mutation) { - var mutationString = '<' + mutation.tagName; - for (var prop in mutation) { + let mutationString = `<${mutation.tagName}`; + for (const prop in mutation) { if (prop === 'children' || prop === 'tagName') continue; - var mutationValue = (typeof mutation[prop] === 'string') ? + const mutationValue = (typeof mutation[prop] === 'string') ? xmlEscape(mutation[prop]) : mutation[prop]; - mutationString += ' ' + prop + '="' + mutationValue + '"'; + mutationString += ` ${prop}="${mutationValue}"`; } mutationString += '>'; - for (var i = 0; i < mutation.children.length; i++) { + for (let i = 0; i < mutation.children.length; i++) { mutationString += this.mutationToXML(mutation.children[i]); } - mutationString += ''; + mutationString += ``; return mutationString; }; @@ -475,7 +475,7 @@ Blocks.prototype.mutationToXML = function (mutation) { * @param {?string} topBlockId ID of block that starts the script. */ Blocks.prototype._addScript = function (topBlockId) { - var i = this._scripts.indexOf(topBlockId); + const i = this._scripts.indexOf(topBlockId); if (i > -1) return; // Already in scripts. this._scripts.push(topBlockId); // Update `topLevel` property on the top block. @@ -487,7 +487,7 @@ Blocks.prototype._addScript = function (topBlockId) { * @param {?string} topBlockId ID of block that starts the script. */ Blocks.prototype._deleteScript = function (topBlockId) { - var i = this._scripts.indexOf(topBlockId); + const i = this._scripts.indexOf(topBlockId); if (i > -1) this._scripts.splice(i, 1); // Update `topLevel` property on the top block. if (this._blocks[topBlockId]) this._blocks[topBlockId].topLevel = false; diff --git a/src/engine/execute.js b/src/engine/execute.js index 0847c7b411f..660eacb34d1 100644 --- a/src/engine/execute.js +++ b/src/engine/execute.js @@ -1,12 +1,12 @@ -var log = require('../util/log'); -var Thread = require('./thread'); +const log = require('../util/log'); +const Thread = require('./thread'); /** * Utility function to determine if a value is a Promise. * @param {*} value Value to check for a Promise. * @return {boolean} True if the value appears to be a Promise. */ -var isPromise = function (value) { +const isPromise = function (value) { return value && value.then && typeof value.then === 'function'; }; @@ -16,8 +16,8 @@ var isPromise = function (value) { * @param {!Thread} thread Thread which to read and execute. */ var execute = function (sequencer, thread) { - var runtime = sequencer.runtime; - var target = thread.target; + const runtime = sequencer.runtime; + const target = thread.target; // Stop if block or target no longer exists. if (target === null) { @@ -27,11 +27,11 @@ var execute = function (sequencer, thread) { } // Current block to execute is the one on the top of the stack. - var currentBlockId = thread.peekStack(); - var currentStackFrame = thread.peekStackFrame(); + const currentBlockId = thread.peekStack(); + const currentStackFrame = thread.peekStackFrame(); - var blockContainer = target.blocks; - var block = blockContainer.getBlock(currentBlockId); + let blockContainer = target.blocks; + let block = blockContainer.getBlock(currentBlockId); if (typeof block === 'undefined') { blockContainer = runtime.flyoutBlocks; block = blockContainer.getBlock(currentBlockId); @@ -43,15 +43,15 @@ var execute = function (sequencer, thread) { } } - var opcode = blockContainer.getOpcode(block); - var fields = blockContainer.getFields(block); - var inputs = blockContainer.getInputs(block); - var blockFunction = runtime.getOpcodeFunction(opcode); - var isHat = runtime.getIsHat(opcode); + const opcode = blockContainer.getOpcode(block); + const fields = blockContainer.getFields(block); + const inputs = blockContainer.getInputs(block); + const blockFunction = runtime.getOpcodeFunction(opcode); + const isHat = runtime.getIsHat(opcode); if (!opcode) { - log.warn('Could not get opcode for block: ' + currentBlockId); + log.warn(`Could not get opcode for block: ${currentBlockId}`); return; } @@ -60,18 +60,18 @@ var execute = function (sequencer, thread) { * or after a promise resolves. * @param {*} resolvedValue Value eventually returned from the primitive. */ - var handleReport = function (resolvedValue) { + const handleReport = function (resolvedValue) { thread.pushReportedValue(resolvedValue); if (isHat) { // Hat predicate was evaluated. if (runtime.getIsEdgeActivatedHat(opcode)) { // If this is an edge-activated hat, only proceed if // the value is true and used to be false. - var oldEdgeValue = runtime.updateEdgeActivatedValue( + const oldEdgeValue = runtime.updateEdgeActivatedValue( currentBlockId, resolvedValue ); - var edgeWasActivated = !oldEdgeValue && resolvedValue; + const edgeWasActivated = !oldEdgeValue && resolvedValue; if (!edgeWasActivated) { sequencer.retireThread(thread); } @@ -104,31 +104,31 @@ var execute = function (sequencer, thread) { // Skip through the block (hat with no predicate). return; } - var keys = Object.keys(fields); + const keys = Object.keys(fields); if (keys.length === 1 && Object.keys(inputs).length === 0) { // One field and no inputs - treat as arg. handleReport(fields[keys[0]].value); } else { - log.warn('Could not get implementation for opcode: ' + opcode); + log.warn(`Could not get implementation for opcode: ${opcode}`); } thread.requestScriptGlowInFrame = true; return; } // Generate values for arguments (inputs). - var argValues = {}; + const argValues = {}; // Add all fields on this block to the argValues. - for (var fieldName in fields) { + for (const fieldName in fields) { if (!fields.hasOwnProperty(fieldName)) continue; argValues[fieldName] = fields[fieldName].value; } // Recursively evaluate input blocks. - for (var inputName in inputs) { + for (const inputName in inputs) { if (!inputs.hasOwnProperty(inputName)) continue; - var input = inputs[inputName]; - var inputBlockId = input.block; + const input = inputs[inputName]; + const inputBlockId = input.block; // Is there no value for this input waiting in the stack frame? if (inputBlockId !== null && typeof currentStackFrame.reported[inputName] === 'undefined') { // If there's not, we need to evaluate the block. @@ -151,7 +151,7 @@ var execute = function (sequencer, thread) { } // Add any mutation to args (e.g., for procedures). - var mutation = blockContainer.getMutation(block); + const mutation = blockContainer.getMutation(block); if (mutation !== null) { argValues.mutation = mutation; } @@ -162,7 +162,7 @@ var execute = function (sequencer, thread) { // (e.g., on return from a branch) gets fresh inputs. currentStackFrame.reported = {}; - var primitiveReportedValue = null; + let primitiveReportedValue = null; primitiveReportedValue = blockFunction(argValues, { stackFrame: currentStackFrame.executionContext, target: target, @@ -201,7 +201,7 @@ var execute = function (sequencer, thread) { ioQuery: function (device, func, args) { // Find the I/O device and execute the query/function call. if (runtime.ioDevices[device] && runtime.ioDevices[device][func]) { - var devObject = runtime.ioDevices[device]; + const devObject = runtime.ioDevices[device]; // @todo Figure out why eslint complains about no-useless-call // no-useless-call can't tell if the call is useless for dynamic // expressions... or something. Not exactly sure why it @@ -225,13 +225,13 @@ var execute = function (sequencer, thread) { thread.status = Thread.STATUS_PROMISE_WAIT; } // Promise handlers - primitiveReportedValue.then(function (resolvedValue) { + primitiveReportedValue.then(resolvedValue => { handleReport(resolvedValue); if (typeof resolvedValue === 'undefined') { do { // In the case that the promise is the last block in the current thread stack // We need to pop out repeatedly until we find the next block. - var popped = thread.popStack(); + const popped = thread.popStack(); if (popped === null) { return; } @@ -249,7 +249,7 @@ var execute = function (sequencer, thread) { } else { thread.popStack(); } - }, function (rejectionReason) { + }, rejectionReason => { // Promise rejected: the primitive had some error. // Log it and proceed. log.warn('Primitive rejected promise: ', rejectionReason); diff --git a/src/engine/list.js b/src/engine/list.js index d8be65a3301..c26213e26ef 100644 --- a/src/engine/list.js +++ b/src/engine/list.js @@ -8,7 +8,7 @@ * @param {Array} contents Contents of the list, as an array. * @constructor */ -var List = function (name, contents) { +const List = function (name, contents) { this.name = name; this.contents = contents; }; diff --git a/src/engine/mutation-adapter.js b/src/engine/mutation-adapter.js index 54bf7b4ee14..a057f80f076 100644 --- a/src/engine/mutation-adapter.js +++ b/src/engine/mutation-adapter.js @@ -1,4 +1,4 @@ -var html = require('htmlparser2'); +const html = require('htmlparser2'); /** * Convert a part of a mutation DOM to a mutation VM object, recursively. @@ -6,14 +6,14 @@ var html = require('htmlparser2'); * @return {object} Object representing useful parts of this mutation. */ var mutatorTagToObject = function (dom) { - var obj = Object.create(null); + const obj = Object.create(null); obj.tagName = dom.name; obj.children = []; - for (var prop in dom.attribs) { + for (const prop in dom.attribs) { if (prop === 'xmlns') continue; obj[prop] = dom.attribs[prop]; } - for (var i = 0; i < dom.children.length; i++) { + for (let i = 0; i < dom.children.length; i++) { obj.children.push( mutatorTagToObject(dom.children[i]) ); @@ -27,8 +27,8 @@ var mutatorTagToObject = function (dom) { * @param {(object|string)} mutation Mutation XML string or DOM. * @return {object} Object representing the mutation. */ -var mutationAdpater = function (mutation) { - var mutationParsed; +const mutationAdpater = function (mutation) { + let mutationParsed; // Check if the mutation is already parsed; if not, parse it. if (typeof mutation === 'object') { mutationParsed = mutation; diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 65f3c5fc748..6bde2ddf258 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -1,15 +1,15 @@ -var EventEmitter = require('events'); -var Sequencer = require('./sequencer'); -var Blocks = require('./blocks'); -var Thread = require('./thread'); -var util = require('util'); +const EventEmitter = require('events'); +const Sequencer = require('./sequencer'); +const Blocks = require('./blocks'); +const Thread = require('./thread'); +const util = require('util'); // Virtual I/O devices. -var Clock = require('../io/clock'); -var Keyboard = require('../io/keyboard'); -var Mouse = require('../io/mouse'); +const Clock = require('../io/clock'); +const Keyboard = require('../io/keyboard'); +const Mouse = require('../io/mouse'); -var defaultBlockPackages = { +const defaultBlockPackages = { scratch3_control: require('../blocks/scratch3_control'), scratch3_event: require('../blocks/scratch3_event'), scratch3_looks: require('../blocks/scratch3_looks'), @@ -26,7 +26,7 @@ var defaultBlockPackages = { * Manages targets, scripts, and the sequencer. * @constructor */ -var Runtime = function () { +const Runtime = function () { // Bind event emitter EventEmitter.call(this); @@ -237,14 +237,14 @@ Runtime.MAX_CLONES = 300; * @private */ Runtime.prototype._registerBlockPackages = function () { - for (var packageName in defaultBlockPackages) { + for (const packageName in defaultBlockPackages) { if (defaultBlockPackages.hasOwnProperty(packageName)) { // @todo pass a different runtime depending on package privilege? - var packageObject = new (defaultBlockPackages[packageName])(this); + const packageObject = new (defaultBlockPackages[packageName])(this); // Collect primitives from package. if (packageObject.getPrimitives) { - var packagePrimitives = packageObject.getPrimitives(); - for (var op in packagePrimitives) { + const packagePrimitives = packageObject.getPrimitives(); + for (const op in packagePrimitives) { if (packagePrimitives.hasOwnProperty(op)) { this._primitives[op] = packagePrimitives[op].bind(packageObject); @@ -253,8 +253,8 @@ Runtime.prototype._registerBlockPackages = function () { } // Collect hat metadata from package. if (packageObject.getHats) { - var packageHats = packageObject.getHats(); - for (var hatName in packageHats) { + const packageHats = packageObject.getHats(); + for (const hatName in packageHats) { if (packageHats.hasOwnProperty(hatName)) { this._hats[hatName] = packageHats[hatName]; } @@ -299,7 +299,7 @@ Runtime.prototype.getIsEdgeActivatedHat = function (opcode) { * @return {*} The old value for the edge-activated hat. */ Runtime.prototype.updateEdgeActivatedValue = function (blockId, newValue) { - var oldValue = this._edgeActivatedHatValues[blockId]; + const oldValue = this._edgeActivatedHatValues[blockId]; this._edgeActivatedHatValues[blockId] = newValue; return oldValue; }; @@ -345,7 +345,7 @@ Runtime.prototype.attachStorage = function (storage) { * @return {!Thread} The newly created thread. */ Runtime.prototype._pushThread = function (id, target) { - var thread = new Thread(id); + const thread = new Thread(id); thread.target = target; thread.pushStack(id); this.threads.push(thread); @@ -360,7 +360,7 @@ Runtime.prototype._removeThread = function (thread) { // Inform sequencer to stop executing that thread. this.sequencer.retireThread(thread); // Remove from the list. - var i = this.threads.indexOf(thread); + const i = this.threads.indexOf(thread); if (i > -1) { this.threads.splice(i, 1); } @@ -373,10 +373,10 @@ Runtime.prototype._removeThread = function (thread) { * @param {!Thread} thread Thread object to restart. */ Runtime.prototype._restartThread = function (thread) { - var newThread = new Thread(thread.topBlock); + const newThread = new Thread(thread.topBlock); newThread.target = thread.target; newThread.pushStack(thread.topBlock); - var i = this.threads.indexOf(thread); + const i = this.threads.indexOf(thread); if (i > -1) { this.threads[i] = newThread; } else { @@ -399,7 +399,7 @@ Runtime.prototype.isActiveThread = function (thread) { */ Runtime.prototype.toggleScript = function (topBlockId) { // Remove any existing thread. - for (var i = 0; i < this.threads.length; i++) { + for (let i = 0; i < this.threads.length; i++) { if (this.threads[i].topBlock === topBlockId) { this._removeThread(this.threads[i]); return; @@ -418,15 +418,15 @@ Runtime.prototype.toggleScript = function (topBlockId) { * @param {Target=} optTarget Optionally, a target to restrict to. */ Runtime.prototype.allScriptsDo = function (f, optTarget) { - var targets = this.targets; + let targets = this.targets; if (optTarget) { targets = [optTarget]; } - for (var t = targets.length - 1; t >= 0; t--) { - var target = targets[t]; - var scripts = target.blocks.getScripts(); - for (var j = 0; j < scripts.length; j++) { - var topBlockId = scripts[j]; + for (let t = targets.length - 1; t >= 0; t--) { + const target = targets[t]; + const scripts = target.blocks.getScripts(); + for (let j = 0; j < scripts.length; j++) { + const topBlockId = scripts[j]; f(topBlockId, target); } } @@ -445,19 +445,19 @@ Runtime.prototype.startHats = function (requestedHatOpcode, // No known hat with this opcode. return; } - var instance = this; - var newThreads = []; + const instance = this; + const newThreads = []; - for (var opts in optMatchFields) { + for (const opts in optMatchFields) { if (!optMatchFields.hasOwnProperty(opts)) continue; optMatchFields[opts] = optMatchFields[opts].toUpperCase(); } // Consider all scripts, looking for hats with opcode `requestedHatOpcode`. - this.allScriptsDo(function (topBlockId, target) { - var blocks = target.blocks; - var block = blocks.getBlock(topBlockId); - var potentialHatOpcode = block.opcode; + this.allScriptsDo((topBlockId, target) => { + const blocks = target.blocks; + const block = blocks.getBlock(topBlockId); + const potentialHatOpcode = block.opcode; if (potentialHatOpcode !== requestedHatOpcode) { // Not the right hat. return; @@ -468,22 +468,22 @@ Runtime.prototype.startHats = function (requestedHatOpcode, // This needs to happen before the block is evaluated // (i.e., before the predicate can be run) because "broadcast and wait" // needs to have a precise collection of started threads. - var hatFields = blocks.getFields(block); + let hatFields = blocks.getFields(block); // If no fields are present, check inputs (horizontal blocks) if (Object.keys(hatFields).length === 0) { - var hatInputs = blocks.getInputs(block); - for (var input in hatInputs) { + const hatInputs = blocks.getInputs(block); + for (const input in hatInputs) { if (!hatInputs.hasOwnProperty(input)) continue; - var id = hatInputs[input].block; - var inpBlock = blocks.getBlock(id); - var fields = blocks.getFields(inpBlock); + const id = hatInputs[input].block; + const inpBlock = blocks.getBlock(id); + const fields = blocks.getFields(inpBlock); hatFields = Object.assign(fields, hatFields); } } if (optMatchFields) { - for (var matchField in optMatchFields) { + for (const matchField in optMatchFields) { if (hatFields[matchField].value.toUpperCase() !== optMatchFields[matchField]) { // Field mismatch. @@ -493,11 +493,11 @@ Runtime.prototype.startHats = function (requestedHatOpcode, } // Look up metadata for the relevant hat. - var hatMeta = instance._hats[requestedHatOpcode]; + const hatMeta = instance._hats[requestedHatOpcode]; if (hatMeta.restartExistingThreads) { // If `restartExistingThreads` is true, we should stop // any existing threads starting with the top block. - for (var i = 0; i < instance.threads.length; i++) { + for (let i = 0; i < instance.threads.length; i++) { if (instance.threads[i].topBlock === topBlockId && instance.threads[i].target === target) { instance._restartThread(instance.threads[i]); @@ -507,7 +507,7 @@ Runtime.prototype.startHats = function (requestedHatOpcode, } else { // If `restartExistingThreads` is false, we should // give up if any threads with the top block are running. - for (var j = 0; j < instance.threads.length; j++) { + for (let j = 0; j < instance.threads.length; j++) { if (instance.threads[j].topBlock === topBlockId && instance.threads[j].target === target) { // Some thread is already running. @@ -534,7 +534,7 @@ Runtime.prototype.dispose = function () { * @param {!Target} disposingTarget Target to dispose of. */ Runtime.prototype.disposeTarget = function (disposingTarget) { - this.targets = this.targets.filter(function (target) { + this.targets = this.targets.filter(target => { if (disposingTarget !== target) return true; // Allow target to do dispose actions. target.dispose(); @@ -550,7 +550,7 @@ Runtime.prototype.disposeTarget = function (disposingTarget) { */ Runtime.prototype.stopForTarget = function (target, optThreadException) { // Stop any threads on the target. - for (var i = 0; i < this.threads.length; i++) { + for (let i = 0; i < this.threads.length; i++) { if (this.threads[i] === optThreadException) { continue; } @@ -568,7 +568,7 @@ Runtime.prototype.greenFlag = function () { this.ioDevices.clock.resetProjectTimer(); this.clearEdgeActivatedValues(); // Inform all targets of the green flag. - for (var i = 0; i < this.targets.length; i++) { + for (let i = 0; i < this.targets.length; i++) { this.targets[i].onGreenFlag(); } this.startHats('event_whenflagclicked'); @@ -579,8 +579,8 @@ Runtime.prototype.greenFlag = function () { */ Runtime.prototype.stopAll = function () { // Dispose all clones. - var newTargets = []; - for (var i = 0; i < this.targets.length; i++) { + const newTargets = []; + for (let i = 0; i < this.targets.length; i++) { this.targets[i].onStopAll(); if (this.targets[i].hasOwnProperty('isOriginal') && !this.targets[i].isOriginal) { @@ -591,9 +591,9 @@ Runtime.prototype.stopAll = function () { } this.targets = newTargets; // Dispose all threads. - var threadsCopy = this.threads.slice(); + const threadsCopy = this.threads.slice(); while (threadsCopy.length > 0) { - var poppedThread = threadsCopy.pop(); + const poppedThread = threadsCopy.pop(); this._removeThread(poppedThread); } }; @@ -604,15 +604,15 @@ Runtime.prototype.stopAll = function () { */ Runtime.prototype._step = function () { // Find all edge-activated hats, and add them to threads to be evaluated. - for (var hatType in this._hats) { + for (const hatType in this._hats) { if (!this._hats.hasOwnProperty(hatType)) continue; - var hat = this._hats[hatType]; + const hat = this._hats[hatType]; if (hat.edgeActivated) { this.startHats(hatType); } } this.redrawRequested = false; - var doneThreads = this.sequencer.stepThreads(); + const doneThreads = this.sequencer.stepThreads(); this._updateGlows(doneThreads); this._setThreadCount(this.threads.length + doneThreads.length); if (this.renderer) { @@ -651,23 +651,23 @@ Runtime.prototype.setCompatibilityMode = function (compatibilityModeOn) { * @param {Array.=} optExtraThreads Optional list of inactive threads. */ Runtime.prototype._updateGlows = function (optExtraThreads) { - var searchThreads = []; + const searchThreads = []; searchThreads.push.apply(searchThreads, this.threads); if (optExtraThreads) { searchThreads.push.apply(searchThreads, optExtraThreads); } // Set of scripts that request a glow this frame. - var requestedGlowsThisFrame = []; + const requestedGlowsThisFrame = []; // Final set of scripts glowing during this frame. - var finalScriptGlows = []; + const finalScriptGlows = []; // Find all scripts that should be glowing. - for (var i = 0; i < searchThreads.length; i++) { - var thread = searchThreads[i]; - var target = thread.target; + for (let i = 0; i < searchThreads.length; i++) { + const thread = searchThreads[i]; + const target = thread.target; if (target === this._editingTarget) { - var blockForThread = thread.blockGlowInFrame; + const blockForThread = thread.blockGlowInFrame; if (thread.requestScriptGlowInFrame) { - var script = target.blocks.getTopLevelScript(blockForThread); + let script = target.blocks.getTopLevelScript(blockForThread); if (!script) { // Attempt to find in flyout blocks. script = this.flyoutBlocks.getTopLevelScript( @@ -681,8 +681,8 @@ Runtime.prototype._updateGlows = function (optExtraThreads) { } } // Compare to previous frame. - for (var j = 0; j < this._scriptGlowsPreviousFrame.length; j++) { - var previousFrameGlow = this._scriptGlowsPreviousFrame[j]; + for (let j = 0; j < this._scriptGlowsPreviousFrame.length; j++) { + const previousFrameGlow = this._scriptGlowsPreviousFrame[j]; if (requestedGlowsThisFrame.indexOf(previousFrameGlow) < 0) { // Glow turned off. this.glowScript(previousFrameGlow, false); @@ -691,8 +691,8 @@ Runtime.prototype._updateGlows = function (optExtraThreads) { finalScriptGlows.push(previousFrameGlow); } } - for (var k = 0; k < requestedGlowsThisFrame.length; k++) { - var currentFrameGlow = requestedGlowsThisFrame[k]; + for (let k = 0; k < requestedGlowsThisFrame.length; k++) { + const currentFrameGlow = requestedGlowsThisFrame[k]; if (this._scriptGlowsPreviousFrame.indexOf(currentFrameGlow) < 0) { // Glow turned on. this.glowScript(currentFrameGlow, true); @@ -725,7 +725,7 @@ Runtime.prototype._setThreadCount = function (threadCount) { * @param {!string} scriptBlockId Id of top-level block in script to quiet. */ Runtime.prototype.quietGlow = function (scriptBlockId) { - var index = this._scriptGlowsPreviousFrame.indexOf(scriptBlockId); + const index = this._scriptGlowsPreviousFrame.indexOf(scriptBlockId); if (index > -1) { this._scriptGlowsPreviousFrame.splice(index, 1); } @@ -782,8 +782,8 @@ Runtime.prototype.spriteInfoReport = function (target) { * @return {?Target} The target, if found. */ Runtime.prototype.getTargetById = function (targetId) { - for (var i = 0; i < this.targets.length; i++) { - var target = this.targets[i]; + for (let i = 0; i < this.targets.length; i++) { + const target = this.targets[i]; if (target.id === targetId) { return target; } @@ -796,8 +796,8 @@ Runtime.prototype.getTargetById = function (targetId) { * @return {?Target} Target representing a sprite of the given name. */ Runtime.prototype.getSpriteTargetByName = function (spriteName) { - for (var i = 0; i < this.targets.length; i++) { - var target = this.targets[i]; + for (let i = 0; i < this.targets.length; i++) { + const target = this.targets[i]; if (target.sprite && target.sprite.name === spriteName) { return target; } @@ -810,8 +810,8 @@ Runtime.prototype.getSpriteTargetByName = function (spriteName) { * @return {?Target} The target, if found */ Runtime.prototype.getTargetByDrawableId = function (drawableID) { - for (var i = 0; i < this.targets.length; i++) { - var target = this.targets[i]; + for (let i = 0; i < this.targets.length; i++) { + const target = this.targets[i]; if (target.drawableID === drawableID) return target; } }; @@ -837,8 +837,8 @@ Runtime.prototype.clonesAvailable = function () { * @return {?Target} The target, if found. */ Runtime.prototype.getTargetForStage = function () { - for (var i = 0; i < this.targets.length; i++) { - var target = this.targets[i]; + for (let i = 0; i < this.targets.length; i++) { + const target = this.targets[i]; if (target.isStage) { return target; } @@ -857,14 +857,14 @@ Runtime.prototype.requestRedraw = function () { * Set up timers to repeatedly step in a browser. */ Runtime.prototype.start = function () { - var interval = Runtime.THREAD_STEP_INTERVAL; + let interval = Runtime.THREAD_STEP_INTERVAL; if (this.compatibilityMode) { interval = Runtime.THREAD_STEP_INTERVAL_COMPATIBILITY; } this.currentStepTime = interval; - this._steppingInterval = setInterval(function () { + this._steppingInterval = setInterval(() => { this._step(); - }.bind(this), interval); + }, interval); }; module.exports = Runtime; diff --git a/src/engine/sequencer.js b/src/engine/sequencer.js index 06deb38f978..bb6bbe4c820 100644 --- a/src/engine/sequencer.js +++ b/src/engine/sequencer.js @@ -1,8 +1,8 @@ -var Timer = require('../util/timer'); -var Thread = require('./thread'); -var execute = require('./execute.js'); +const Timer = require('../util/timer'); +const Thread = require('./thread'); +const execute = require('./execute.js'); -var Sequencer = function (runtime) { +const Sequencer = function (runtime) { /** * A utility timer for timing thread sequencing. * @type {!Timer} @@ -28,14 +28,14 @@ Sequencer.WARP_TIME = 500; */ Sequencer.prototype.stepThreads = function () { // Work time is 75% of the thread stepping interval. - var WORK_TIME = 0.75 * this.runtime.currentStepTime; + const WORK_TIME = 0.75 * this.runtime.currentStepTime; // Start counting toward WORK_TIME. this.timer.start(); // Count of active threads. - var numActiveThreads = Infinity; + let numActiveThreads = Infinity; // Whether `stepThreads` has run through a full single tick. - var ranFirstTick = false; - var doneThreads = []; + let ranFirstTick = false; + const doneThreads = []; // Conditions for continuing to stepping threads: // 1. We must have threads in the list, and some must be active. // 2. Time elapsed must be less than WORK_TIME. @@ -46,8 +46,8 @@ Sequencer.prototype.stepThreads = function () { (this.runtime.turboMode || !this.runtime.redrawRequested)) { numActiveThreads = 0; // Attempt to run each thread one time. - for (var i = 0; i < this.runtime.threads.length; i++) { - var activeThread = this.runtime.threads[i]; + for (let i = 0; i < this.runtime.threads.length; i++) { + const activeThread = this.runtime.threads[i]; if (activeThread.stack.length === 0 || activeThread.status === Thread.STATUS_DONE) { // Finished with this thread. @@ -76,7 +76,7 @@ Sequencer.prototype.stepThreads = function () { ranFirstTick = true; } // Filter inactive threads from `this.runtime.threads`. - this.runtime.threads = this.runtime.threads.filter(function (thread) { + this.runtime.threads = this.runtime.threads.filter(thread => { if (doneThreads.indexOf(thread) > -1) { return false; } @@ -90,13 +90,13 @@ Sequencer.prototype.stepThreads = function () { * @param {!Thread} thread Thread object to step. */ Sequencer.prototype.stepThread = function (thread) { - var currentBlockId = thread.peekStack(); + let currentBlockId = thread.peekStack(); if (!currentBlockId) { // A "null block" - empty branch. thread.popStack(); } while (thread.peekStack()) { - var isWarpMode = thread.peekStackFrame().warpMode; + let isWarpMode = thread.peekStackFrame().warpMode; if (isWarpMode && !thread.warpTimer) { // Initialize warp-mode timer if it hasn't been already. // This will start counting the thread toward `Sequencer.WARP_TIME`. @@ -138,7 +138,7 @@ Sequencer.prototype.stepThread = function (thread) { return; } - var stackFrame = thread.peekStackFrame(); + const stackFrame = thread.peekStackFrame(); isWarpMode = stackFrame.warpMode; if (stackFrame.isLoop) { @@ -151,11 +151,11 @@ Sequencer.prototype.stepThread = function (thread) { // Don't do anything to the stack, since loops need // to be re-executed. return; - } else { + } // Don't go to the next block for this level of the stack, // since loops need to be re-executed. - continue; - } + continue; + } else if (stackFrame.waitingReporter) { // This level of the stack was waiting for a value. // This means a reporter has just returned - so don't go @@ -178,8 +178,8 @@ Sequencer.prototype.stepToBranch = function (thread, branchNum, isLoop) { if (!branchNum) { branchNum = 1; } - var currentBlockId = thread.peekStack(); - var branchId = thread.target.blocks.getBranch( + const currentBlockId = thread.peekStack(); + const branchId = thread.target.blocks.getBranch( currentBlockId, branchNum ); @@ -198,13 +198,13 @@ Sequencer.prototype.stepToBranch = function (thread, branchNum, isLoop) { * @param {!string} procedureCode Procedure code of procedure to step to. */ Sequencer.prototype.stepToProcedure = function (thread, procedureCode) { - var definition = thread.target.blocks.getProcedureDefinition(procedureCode); + const definition = thread.target.blocks.getProcedureDefinition(procedureCode); if (!definition) { return; } // Check if the call is recursive. // If so, set the thread to yield after pushing. - var isRecursive = thread.isRecursiveCall(procedureCode); + const isRecursive = thread.isRecursiveCall(procedureCode); // To step to a procedure, we put its definition on the stack. // Execution for the thread will proceed through the definition hat // and on to the main definition of the procedure. @@ -218,8 +218,8 @@ Sequencer.prototype.stepToProcedure = function (thread, procedureCode) { } else { // Look for warp-mode flag on definition, and set the thread // to warp-mode if needed. - var definitionBlock = thread.target.blocks.getBlock(definition); - var doWarp = definitionBlock.mutation.warp; + const definitionBlock = thread.target.blocks.getBlock(definition); + const doWarp = definitionBlock.mutation.warp; if (doWarp) { thread.peekStackFrame().warpMode = true; } else { diff --git a/src/engine/target.js b/src/engine/target.js index 947df53d398..0c5c9881262 100644 --- a/src/engine/target.js +++ b/src/engine/target.js @@ -1,10 +1,10 @@ -var EventEmitter = require('events'); -var util = require('util'); +const EventEmitter = require('events'); +const util = require('util'); -var Blocks = require('./blocks'); -var Variable = require('../engine/variable'); -var List = require('../engine/list'); -var uid = require('../util/uid'); +const Blocks = require('./blocks'); +const Variable = require('../engine/variable'); +const List = require('../engine/list'); +const uid = require('../util/uid'); /** * @fileoverview @@ -16,7 +16,7 @@ var uid = require('../util/uid'); * @param {?Blocks} blocks Blocks instance for the blocks owned by this target. * @constructor */ -var Target = function (blocks) { +const Target = function (blocks) { EventEmitter.call(this); if (!blocks) { @@ -87,13 +87,13 @@ Target.prototype.lookupOrCreateVariable = function (name) { } // If the stage has a global copy, return it. if (this.runtime && !this.isStage) { - var stage = this.runtime.getTargetForStage(); + const stage = this.runtime.getTargetForStage(); if (stage.variables.hasOwnProperty(name)) { return stage.variables[name]; } } // No variable with this name exists - create it locally. - var newVariable = new Variable(name, 0, false); + const newVariable = new Variable(name, 0, false); this.variables[name] = newVariable; return newVariable; }; @@ -111,13 +111,13 @@ Target.prototype.lookupOrCreateList = function (name) { } // If the stage has a global copy, return it. if (this.runtime && !this.isStage) { - var stage = this.runtime.getTargetForStage(); + const stage = this.runtime.getTargetForStage(); if (stage.lists.hasOwnProperty(name)) { return stage.lists[name]; } } // No list with this name exists - create it locally. - var newList = new List(name, []); + const newList = new List(name, []); this.lists[name] = newList; return newList; }; diff --git a/src/engine/thread.js b/src/engine/thread.js index f093f886eb7..bedd132d891 100644 --- a/src/engine/thread.js +++ b/src/engine/thread.js @@ -3,7 +3,7 @@ * @param {?string} firstBlock First block to execute in the thread. * @constructor */ -var Thread = function (firstBlock) { +const Thread = function (firstBlock) { /** * ID of top block of the thread * @type {!string} @@ -100,7 +100,7 @@ Thread.prototype.pushStack = function (blockId) { // Might not, if we just popped the stack. if (this.stack.length > this.stackFrames.length) { // Copy warp mode from any higher level. - var warpMode = false; + let warpMode = false; if (this.stackFrames.length > 0 && this.stackFrames[this.stackFrames.length - 1]) { warpMode = this.stackFrames[this.stackFrames.length - 1].warpMode; } @@ -122,7 +122,7 @@ Thread.prototype.pushStack = function (blockId) { */ Thread.prototype.reuseStackForNextBlock = function (blockId) { this.stack[this.stack.length - 1] = blockId; - var frame = this.stackFrames[this.stackFrames.length - 1]; + const frame = this.stackFrames[this.stackFrames.length - 1]; frame.isLoop = false; // frame.warpMode = warpMode; // warp mode stays the same when reusing the stack frame. frame.reported = {}; @@ -144,9 +144,9 @@ Thread.prototype.popStack = function () { * Pop back down the stack frame until we hit a procedure call or the stack frame is emptied */ Thread.prototype.stopThisScript = function () { - var blockID = this.peekStack(); + let blockID = this.peekStack(); while (blockID !== null) { - var block = this.target.blocks.getBlock(blockID); + const block = this.target.blocks.getBlock(blockID); if (typeof block !== 'undefined' && block.opcode === 'procedures_callnoreturn') { break; } @@ -191,9 +191,9 @@ Thread.prototype.peekParentStackFrame = function () { * @param {*} value Reported value to push. */ Thread.prototype.pushReportedValue = function (value) { - var parentStackFrame = this.peekParentStackFrame(); + const parentStackFrame = this.peekParentStackFrame(); if (parentStackFrame) { - var waitingReporter = parentStackFrame.waitingReporter; + const waitingReporter = parentStackFrame.waitingReporter; parentStackFrame.reported[waitingReporter] = value; } }; @@ -205,7 +205,7 @@ Thread.prototype.pushReportedValue = function (value) { * @param {*} value Value to set for parameter. */ Thread.prototype.pushParam = function (paramName, value) { - var stackFrame = this.peekStackFrame(); + const stackFrame = this.peekStackFrame(); stackFrame.params[paramName] = value; }; @@ -215,8 +215,8 @@ Thread.prototype.pushParam = function (paramName, value) { * @return {*} value Value for parameter. */ Thread.prototype.getParam = function (paramName) { - for (var i = this.stackFrames.length - 1; i >= 0; i--) { - var frame = this.stackFrames[i]; + for (let i = this.stackFrames.length - 1; i >= 0; i--) { + const frame = this.stackFrames[i]; if (frame.params.hasOwnProperty(paramName)) { return frame.params[paramName]; } @@ -239,7 +239,7 @@ Thread.prototype.atStackTop = function () { * where execution proceeds from one block to the next. */ Thread.prototype.goToNextBlock = function () { - var nextBlockId = this.target.blocks.getNextBlock(this.peekStack()); + const nextBlockId = this.target.blocks.getNextBlock(this.peekStack()); this.reuseStackForNextBlock(nextBlockId); }; @@ -250,10 +250,10 @@ Thread.prototype.goToNextBlock = function () { * @return {boolean} True if the call appears recursive. */ Thread.prototype.isRecursiveCall = function (procedureCode) { - var callCount = 5; // Max number of enclosing procedure calls to examine. - var sp = this.stack.length - 1; - for (var i = sp - 1; i >= 0; i--) { - var block = this.target.blocks.getBlock(this.stack[i]); + let callCount = 5; // Max number of enclosing procedure calls to examine. + const sp = this.stack.length - 1; + for (let i = sp - 1; i >= 0; i--) { + const block = this.target.blocks.getBlock(this.stack[i]); if (block.opcode === 'procedures_callnoreturn' && block.mutation.proccode === procedureCode) { return true; diff --git a/src/engine/variable.js b/src/engine/variable.js index 3f2dcc5de20..eab090ca3a2 100644 --- a/src/engine/variable.js +++ b/src/engine/variable.js @@ -9,7 +9,7 @@ * @param {boolean} isCloud Whether the variable is stored in the cloud. * @constructor */ -var Variable = function (name, value, isCloud) { +const Variable = function (name, value, isCloud) { this.name = name; this.value = value; this.isCloud = isCloud; diff --git a/src/import/load-costume.js b/src/import/load-costume.js index bc7e3f17631..4c4ed9ac891 100644 --- a/src/import/load-costume.js +++ b/src/import/load-costume.js @@ -1,5 +1,5 @@ -var AssetType = require('scratch-storage').AssetType; -var log = require('../util/log'); +const AssetType = require('scratch-storage').AssetType; +const log = require('../util/log'); /** * Load a costume's asset into memory asynchronously. @@ -13,62 +13,58 @@ var log = require('../util/log'); * @param {!Runtime} runtime - Scratch runtime, used to access the storage module. * @returns {?Promise} - a promise which will resolve after skinId is set, or null on error. */ -var loadCostume = function (md5ext, costume, runtime) { +const loadCostume = function (md5ext, costume, runtime) { if (!runtime.storage) { log.error('No storage module present; cannot load costume asset: ', md5ext); return Promise.resolve(costume); } - var idParts = md5ext.split('.'); - var md5 = idParts[0]; - var ext = idParts[1].toUpperCase(); - var assetType = (ext === 'SVG') ? AssetType.ImageVector : AssetType.ImageBitmap; + const idParts = md5ext.split('.'); + const md5 = idParts[0]; + const ext = idParts[1].toUpperCase(); + const assetType = (ext === 'SVG') ? AssetType.ImageVector : AssetType.ImageBitmap; - var rotationCenter = [ + const rotationCenter = [ costume.rotationCenterX / costume.bitmapResolution, costume.rotationCenterY / costume.bitmapResolution ]; - var promise = runtime.storage.load(assetType, md5).then(function (costumeAsset) { + let promise = runtime.storage.load(assetType, md5).then(costumeAsset => { costume.url = costumeAsset.encodeDataURI(); return costumeAsset; }); if (!runtime.renderer) { log.error('No rendering module present; cannot load costume asset: ', md5ext); - return promise.then(function () { - return costume; - }); + return promise.then(() => costume); } if (assetType === AssetType.ImageVector) { - promise = promise.then(function (costumeAsset) { + promise = promise.then(costumeAsset => { costume.skinId = runtime.renderer.createSVGSkin(costumeAsset.decodeText(), rotationCenter); return costume; }); } else { - promise = promise.then(function (costumeAsset) { - return new Promise(function (resolve, reject) { - var imageElement = new Image(); - var removeEventListeners; // fix no-use-before-define - var onError = function () { - removeEventListeners(); - reject(); - }; - var onLoad = function () { - removeEventListeners(); - resolve(imageElement); - }; - removeEventListeners = function () { - imageElement.removeEventListener('error', onError); - imageElement.removeEventListener('load', onLoad); - }; - imageElement.addEventListener('error', onError); - imageElement.addEventListener('load', onLoad); - imageElement.src = costumeAsset.encodeDataURI(); - }); - }).then(function (imageElement) { + promise = promise.then(costumeAsset => new Promise((resolve, reject) => { + const imageElement = new Image(); + let removeEventListeners; // fix no-use-before-define + const onError = function () { + removeEventListeners(); + reject(); + }; + const onLoad = function () { + removeEventListeners(); + resolve(imageElement); + }; + removeEventListeners = function () { + imageElement.removeEventListener('error', onError); + imageElement.removeEventListener('load', onLoad); + }; + imageElement.addEventListener('error', onError); + imageElement.addEventListener('load', onLoad); + imageElement.src = costumeAsset.encodeDataURI(); + })).then(imageElement => { costume.skinId = runtime.renderer.createBitmapSkin(imageElement, costume.bitmapResolution, rotationCenter); return costume; }); diff --git a/src/import/load-sound.js b/src/import/load-sound.js index 74856326a3b..6502b793279 100644 --- a/src/import/load-sound.js +++ b/src/import/load-sound.js @@ -1,5 +1,5 @@ -var AssetType = require('scratch-storage').AssetType; -var log = require('../util/log'); +const AssetType = require('scratch-storage').AssetType; +const log = require('../util/log'); /** * Load a sound's asset into memory asynchronously. @@ -9,7 +9,7 @@ var log = require('../util/log'); * @param {!Runtime} runtime - Scratch runtime, used to access the storage module. * @returns {!Promise} - a promise which will resolve after sound is loaded */ -var loadSound = function (sound, runtime) { +const loadSound = function (sound, runtime) { if (!runtime.storage) { log.error('No storage module present; cannot load sound asset: ', sound.md5); return Promise.resolve(sound); @@ -18,9 +18,9 @@ var loadSound = function (sound, runtime) { log.error('No audio engine present; cannot load sound asset: ', sound.md5); return Promise.resolve(sound); } - var idParts = sound.md5.split('.'); - var md5 = idParts[0]; - return runtime.storage.load(AssetType.Sound, md5).then(function (soundAsset) { + const idParts = sound.md5.split('.'); + const md5 = idParts[0]; + return runtime.storage.load(AssetType.Sound, md5).then(soundAsset => { sound.data = soundAsset.data; return runtime.audioEngine.decodeSound(sound); }); diff --git a/src/import/sb2import.js b/src/import/sb2import.js index ac905d335d9..c896d01d8ef 100644 --- a/src/import/sb2import.js +++ b/src/import/sb2import.js @@ -5,18 +5,18 @@ * scratch-vm runtime structures. */ -var Blocks = require('../engine/blocks'); -var RenderedTarget = require('../sprites/rendered-target'); -var Sprite = require('../sprites/sprite'); -var Color = require('../util/color'); -var log = require('../util/log'); -var uid = require('../util/uid'); -var specMap = require('./sb2specmap'); -var Variable = require('../engine/variable'); -var List = require('../engine/list'); +const Blocks = require('../engine/blocks'); +const RenderedTarget = require('../sprites/rendered-target'); +const Sprite = require('../sprites/sprite'); +const Color = require('../util/color'); +const log = require('../util/log'); +const uid = require('../util/uid'); +const specMap = require('./sb2specmap'); +const Variable = require('../engine/variable'); +const List = require('../engine/list'); -var loadCostume = require('./load-costume.js'); -var loadSound = require('./load-sound.js'); +const loadCostume = require('./load-costume.js'); +const loadSound = require('./load-sound.js'); /** * Parse a single "Scratch object" and create all its in-memory VM objects. @@ -32,19 +32,19 @@ var parseScratchObject = function (object, runtime, topLevel) { return null; } // Blocks container for this object. - var blocks = new Blocks(); + const blocks = new Blocks(); // @todo: For now, load all Scratch objects (stage/sprites) as a Sprite. - var sprite = new Sprite(blocks, runtime); + const sprite = new Sprite(blocks, runtime); // Sprite/stage name from JSON. if (object.hasOwnProperty('objName')) { sprite.name = object.objName; } // Costumes from JSON. - var costumePromises = []; + const costumePromises = []; if (object.hasOwnProperty('costumes')) { - for (var i = 0; i < object.costumes.length; i++) { - var costumeSource = object.costumes[i]; - var costume = { + for (let i = 0; i < object.costumes.length; i++) { + const costumeSource = object.costumes[i]; + const costume = { name: costumeSource.costumeName, bitmapResolution: costumeSource.bitmapResolution || 1, rotationCenterX: costumeSource.rotationCenterX, @@ -57,9 +57,9 @@ var parseScratchObject = function (object, runtime, topLevel) { } // Sounds from JSON if (object.hasOwnProperty('sounds')) { - for (var s = 0; s < object.sounds.length; s++) { - var soundSource = object.sounds[s]; - var sound = { + for (let s = 0; s < object.sounds.length; s++) { + const soundSource = object.sounds[s]; + const sound = { name: soundSource.soundName, format: soundSource.format, rate: soundSource.rate, @@ -77,13 +77,13 @@ var parseScratchObject = function (object, runtime, topLevel) { parseScripts(object.scripts, blocks); } // Create the first clone, and load its run-state from JSON. - var target = sprite.createClone(); + const target = sprite.createClone(); // Add it to the runtime's list of targets. runtime.targets.push(target); // Load target properties from JSON. if (object.hasOwnProperty('variables')) { - for (var j = 0; j < object.variables.length; j++) { - var variable = object.variables[j]; + for (let j = 0; j < object.variables.length; j++) { + const variable = object.variables[j]; target.variables[variable.name] = new Variable( variable.name, variable.value, @@ -92,8 +92,8 @@ var parseScratchObject = function (object, runtime, topLevel) { } } if (object.hasOwnProperty('lists')) { - for (var k = 0; k < object.lists.length; k++) { - var list = object.lists[k]; + for (let k = 0; k < object.lists.length; k++) { + const list = object.lists[k]; // @todo: monitor properties. target.lists[list.listName] = new List( list.listName, @@ -133,13 +133,13 @@ var parseScratchObject = function (object, runtime, topLevel) { } } target.isStage = topLevel; - Promise.all(costumePromises).then(function (costumes) { + Promise.all(costumePromises).then(costumes => { sprite.costumes = costumes; target.updateAllDrawableProperties(); }); // The stage will have child objects; recursively process them. if (object.children) { - for (var m = 0; m < object.children.length; m++) { + for (let m = 0; m < object.children.length; m++) { parseScratchObject(object.children[m], runtime, false); } } @@ -154,7 +154,7 @@ var parseScratchObject = function (object, runtime, topLevel) { * @param {boolean=} optForceSprite If set, treat as sprite (Sprite2). * @return {?Target} Top-level target created (stage or sprite). */ -var sb2import = function (json, runtime, optForceSprite) { +const sb2import = function (json, runtime, optForceSprite) { return parseScratchObject( JSON.parse(json), runtime, @@ -169,12 +169,12 @@ var sb2import = function (json, runtime, optForceSprite) { * @param {!Blocks} blocks Blocks object to load parsed blocks into. */ var parseScripts = function (scripts, blocks) { - for (var i = 0; i < scripts.length; i++) { - var script = scripts[i]; - var scriptX = script[0]; - var scriptY = script[1]; - var blockList = script[2]; - var parsedBlockList = parseBlockList(blockList); + for (let i = 0; i < scripts.length; i++) { + const script = scripts[i]; + const scriptX = script[0]; + const scriptY = script[1]; + const blockList = script[2]; + const parsedBlockList = parseBlockList(blockList); if (parsedBlockList[0]) { // Adjust script coordinates to account for // larger block size in scratch-blocks. @@ -185,8 +185,8 @@ var parseScripts = function (scripts, blocks) { parsedBlockList[0].parent = null; } // Flatten children and create add the blocks. - var convertedBlocks = flatten(parsedBlockList); - for (var j = 0; j < convertedBlocks.length; j++) { + const convertedBlocks = flatten(parsedBlockList); + for (let j = 0; j < convertedBlocks.length; j++) { blocks.createBlock(convertedBlocks[j]); } } @@ -201,11 +201,11 @@ var parseScripts = function (scripts, blocks) { * @return {Array.} Scratch VM-format block list. */ var parseBlockList = function (blockList) { - var resultingList = []; - var previousBlock = null; // For setting next. - for (var i = 0; i < blockList.length; i++) { - var block = blockList[i]; - var parsedBlock = parseBlock(block); + const resultingList = []; + let previousBlock = null; // For setting next. + for (let i = 0; i < blockList.length; i++) { + const block = blockList[i]; + const parsedBlock = parseBlock(block); if (typeof parsedBlock === 'undefined') continue; if (previousBlock) { parsedBlock.parent = previousBlock.id; @@ -224,9 +224,9 @@ var parseBlockList = function (blockList) { * @return {Array.} Flattened list to be passed to `blocks.createBlock`. */ var flatten = function (blocks) { - var finalBlocks = []; - for (var i = 0; i < blocks.length; i++) { - var block = blocks[i]; + let finalBlocks = []; + for (let i = 0; i < blocks.length; i++) { + const block = blocks[i]; finalBlocks.push(block); if (block.children) { finalBlocks = finalBlocks.concat(flatten(block.children)); @@ -243,19 +243,19 @@ var flatten = function (blocks) { * @param {string} procCode Scratch 2.0 procedure string. * @return {object} Argument map compatible with those in sb2specmap. */ -var parseProcedureArgMap = function (procCode) { - var argMap = [ +const parseProcedureArgMap = function (procCode) { + const argMap = [ {} // First item in list is op string. ]; - var INPUT_PREFIX = 'input'; - var inputCount = 0; + const INPUT_PREFIX = 'input'; + let inputCount = 0; // Split by %n, %b, %s. - var parts = procCode.split(/(?=[^\\]%[nbs])/); - for (var i = 0; i < parts.length; i++) { - var part = parts[i].trim(); + const parts = procCode.split(/(?=[^\\]%[nbs])/); + for (let i = 0; i < parts.length; i++) { + const part = parts[i].trim(); if (part.substring(0, 1) === '%') { - var argType = part.substring(1, 2); - var arg = { + const argType = part.substring(1, 2); + const arg = { type: 'input', inputName: INPUT_PREFIX + (inputCount++) }; @@ -277,15 +277,15 @@ var parseProcedureArgMap = function (procCode) { */ var parseBlock = function (sb2block) { // First item in block object is the old opcode (e.g., 'forward:'). - var oldOpcode = sb2block[0]; + const oldOpcode = sb2block[0]; // Convert the block using the specMap. See sb2specmap.js. if (!oldOpcode || !specMap[oldOpcode]) { log.warn('Couldn\'t find SB2 block: ', oldOpcode); return; } - var blockMetadata = specMap[oldOpcode]; + const blockMetadata = specMap[oldOpcode]; // Block skeleton. - var activeBlock = { + const activeBlock = { id: uid(), // Generate a new block unique ID. opcode: blockMetadata.opcode, // Converted, e.g. "motion_movesteps". inputs: {}, // Inputs to this block and the blocks they point to. @@ -301,15 +301,15 @@ var parseBlock = function (sb2block) { // Look at the expected arguments in `blockMetadata.argMap.` // The basic problem here is to turn positional SB2 arguments into // non-positional named Scratch VM arguments. - for (var i = 0; i < blockMetadata.argMap.length; i++) { - var expectedArg = blockMetadata.argMap[i]; - var providedArg = sb2block[i + 1]; // (i = 0 is opcode) + for (let i = 0; i < blockMetadata.argMap.length; i++) { + const expectedArg = blockMetadata.argMap[i]; + const providedArg = sb2block[i + 1]; // (i = 0 is opcode) // Whether the input is obscuring a shadow. - var shadowObscured = false; + let shadowObscured = false; // Positional argument is an input. if (expectedArg.type === 'input') { // Create a new block and input metadata. - var inputUid = uid(); + const inputUid = uid(); activeBlock.inputs[expectedArg.inputName] = { name: expectedArg.inputName, block: null, @@ -325,8 +325,8 @@ var parseBlock = function (sb2block) { // Single block occupies the input. innerBlocks = [parseBlock(providedArg)]; } - var previousBlock = null; - for (var j = 0; j < innerBlocks.length; j++) { + let previousBlock = null; + for (let j = 0; j < innerBlocks.length; j++) { if (j === 0) { innerBlocks[j].parent = activeBlock.id; } else { @@ -350,9 +350,9 @@ var parseBlock = function (sb2block) { } // Each shadow has a field generated for it automatically. // Value to be filled in the field. - var fieldValue = providedArg; + let fieldValue = providedArg; // Shadows' field names match the input name, except for these: - var fieldName = expectedArg.inputName; + let fieldName = expectedArg.inputName; if (expectedArg.inputOp === 'math_number' || expectedArg.inputOp === 'math_whole_number' || expectedArg.inputOp === 'math_positive_number' || @@ -379,7 +379,7 @@ var parseBlock = function (sb2block) { // Filled drop-down menu. fieldValue = ''; } - var fields = {}; + const fields = {}; fields[fieldName] = { name: fieldName, value: fieldValue @@ -422,7 +422,7 @@ var parseBlock = function (sb2block) { } else if (oldOpcode === 'procDef') { // Mutation for procedure definition: // store all 2.0 proc data. - var procData = sb2block.slice(1); + const procData = sb2block.slice(1); activeBlock.mutation = { tagName: 'mutation', proccode: procData[0], // e.g., "abc %n %b %s" diff --git a/src/import/sb2specmap.js b/src/import/sb2specmap.js index 5ff494059fd..a16104f671f 100644 --- a/src/import/sb2specmap.js +++ b/src/import/sb2specmap.js @@ -21,7 +21,7 @@ * properties. By hand, I matched the opcode name to the 3.0 opcode. * Finally, I filled in the expected arguments as below. */ -var specMap = { +const specMap = { 'forward:': { opcode: 'motion_movesteps', argMap: [ diff --git a/src/index.js b/src/index.js index e449758e345..dfb56632998 100644 --- a/src/index.js +++ b/src/index.js @@ -1,3 +1,3 @@ -var VirtualMachine = require('./virtual-machine'); +const VirtualMachine = require('./virtual-machine'); module.exports = VirtualMachine; diff --git a/src/io/clock.js b/src/io/clock.js index aaefa9d5ab8..6a28e30cf30 100644 --- a/src/io/clock.js +++ b/src/io/clock.js @@ -1,6 +1,6 @@ -var Timer = require('../util/timer'); +const Timer = require('../util/timer'); -var Clock = function (runtime) { +const Clock = function (runtime) { this._projectTimer = new Timer(); this._projectTimer.start(); this._pausedTime = null; @@ -26,7 +26,7 @@ Clock.prototype.pause = function () { Clock.prototype.resume = function () { this._paused = false; - var dt = this._projectTimer.timeElapsed() - this._pausedTime; + const dt = this._projectTimer.timeElapsed() - this._pausedTime; this._projectTimer.startTime += dt; }; diff --git a/src/io/keyboard.js b/src/io/keyboard.js index c7a21080389..7fe46dc3ca0 100644 --- a/src/io/keyboard.js +++ b/src/io/keyboard.js @@ -1,6 +1,6 @@ -var Cast = require('../util/cast'); +const Cast = require('../util/cast'); -var Keyboard = function (runtime) { +const Keyboard = function (runtime) { /** * List of currently pressed keys. * @type{Array.} @@ -25,7 +25,7 @@ Keyboard.prototype._scratchKeyToKeyCode = function (keyName) { // Key codes placed in with number blocks. return keyName; } - var keyString = Cast.toString(keyName); + const keyString = Cast.toString(keyName); switch (keyString) { case 'space': return 32; case 'left arrow': return 37; @@ -65,7 +65,7 @@ Keyboard.prototype._keyCodeToScratchKey = function (keyCode) { */ Keyboard.prototype.postData = function (data) { if (data.keyCode) { - var index = this._keysPressed.indexOf(data.keyCode); + const index = this._keysPressed.indexOf(data.keyCode); if (data.isDown) { // If not already present, add to the list. if (index < 0) { @@ -94,7 +94,7 @@ Keyboard.prototype.getKeyIsDown = function (key) { if (key === 'any') { return this._keysPressed.length > 0; } - var keyCode = this._scratchKeyToKeyCode(key); + const keyCode = this._scratchKeyToKeyCode(key); return this._keysPressed.indexOf(keyCode) > -1; }; diff --git a/src/io/mouse.js b/src/io/mouse.js index 4a7361fa435..9d2721a29b1 100644 --- a/src/io/mouse.js +++ b/src/io/mouse.js @@ -1,6 +1,6 @@ -var MathUtil = require('../util/math-util'); +const MathUtil = require('../util/math-util'); -var Mouse = function (runtime) { +const Mouse = function (runtime) { this._x = 0; this._y = 0; this._isDown = false; @@ -20,9 +20,9 @@ var Mouse = function (runtime) { */ Mouse.prototype._activateClickHats = function (x, y) { if (this.runtime.renderer) { - var drawableID = this.runtime.renderer.pick(x, y); - for (var i = 0; i < this.runtime.targets.length; i++) { - var target = this.runtime.targets[i]; + const drawableID = this.runtime.renderer.pick(x, y); + for (let i = 0; i < this.runtime.targets.length; i++) { + const target = this.runtime.targets[i]; if (target.hasOwnProperty('drawableID') && target.drawableID === drawableID) { this.runtime.startHats('event_whenthisspriteclicked', diff --git a/src/playground/playground.js b/src/playground/playground.js index b37fda7e3ad..81d6f74669f 100644 --- a/src/playground/playground.js +++ b/src/playground/playground.js @@ -1,10 +1,10 @@ -var Scratch = window.Scratch = window.Scratch || {}; +const Scratch = window.Scratch = window.Scratch || {}; -var ASSET_SERVER = 'https://cdn.assets.scratch.mit.edu/'; -var PROJECT_SERVER = 'https://cdn.projects.scratch.mit.edu/'; +const ASSET_SERVER = 'https://cdn.assets.scratch.mit.edu/'; +const PROJECT_SERVER = 'https://cdn.projects.scratch.mit.edu/'; -var loadProject = function () { - var id = location.hash.substring(1); +const loadProject = function () { + let id = location.hash.substring(1); if (id.length < 1 || !isFinite(id)) { id = '119615668'; } @@ -15,9 +15,9 @@ var loadProject = function () { * @param {Asset} asset - calculate a URL for this asset. * @returns {string} a URL to download a project file. */ -var getProjectUrl = function (asset) { - var assetIdParts = asset.assetId.split('.'); - var assetUrlParts = [PROJECT_SERVER, 'internalapi/project/', assetIdParts[0], '/get/']; +const getProjectUrl = function (asset) { + const assetIdParts = asset.assetId.split('.'); + const assetUrlParts = [PROJECT_SERVER, 'internalapi/project/', assetIdParts[0], '/get/']; if (assetIdParts[1]) { assetUrlParts.push(assetIdParts[1]); } @@ -28,8 +28,8 @@ var getProjectUrl = function (asset) { * @param {Asset} asset - calculate a URL for this asset. * @returns {string} a URL to download a project asset (PNG, WAV, etc.) */ -var getAssetUrl = function (asset) { - var assetUrlParts = [ +const getAssetUrl = function (asset) { + const assetUrlParts = [ ASSET_SERVER, 'internalapi/asset/', asset.assetId, @@ -43,32 +43,32 @@ var getAssetUrl = function (asset) { window.onload = function () { // Lots of global variables to make debugging easier // Instantiate the VM. - var vm = new window.VirtualMachine(); + const vm = new window.VirtualMachine(); Scratch.vm = vm; - var storage = new Scratch.Storage(); - var AssetType = Scratch.Storage.AssetType; + const storage = new Scratch.Storage(); + const AssetType = Scratch.Storage.AssetType; storage.addWebSource([AssetType.Project], getProjectUrl); storage.addWebSource([AssetType.ImageVector, AssetType.ImageBitmap, AssetType.Sound], getAssetUrl); vm.attachStorage(storage); // Loading projects from the server. document.getElementById('projectLoadButton').onclick = function () { - document.location = '#' + document.getElementById('projectId').value; + document.location = `#${document.getElementById('projectId').value}`; location.reload(); }; loadProject(); // Instantiate the renderer and connect it to the VM. - var canvas = document.getElementById('scratch-stage'); - var renderer = new window.RenderWebGL(canvas); + const canvas = document.getElementById('scratch-stage'); + const renderer = new window.RenderWebGL(canvas); Scratch.renderer = renderer; vm.attachRenderer(renderer); - var audioEngine = new window.AudioEngine(); + const audioEngine = new window.AudioEngine(); vm.attachAudioEngine(audioEngine); // Instantiate scratch-blocks and attach it to the DOM. - var workspace = window.Blockly.inject('blocks', { + const workspace = window.Blockly.inject('blocks', { media: './media/', zoom: { controls: true, @@ -90,27 +90,27 @@ window.onload = function () { // Attach scratch-blocks events to VM. workspace.addChangeListener(vm.blockListener); - var flyoutWorkspace = workspace.getFlyout().getWorkspace(); + const flyoutWorkspace = workspace.getFlyout().getWorkspace(); flyoutWorkspace.addChangeListener(vm.flyoutBlockListener); // Create FPS counter. - var stats = new window.Stats(); + const stats = new window.Stats(); document.getElementById('tab-renderexplorer').appendChild(stats.dom); stats.dom.style.position = 'relative'; stats.begin(); // Playground data tabs. // Block representation tab. - var blockexplorer = document.getElementById('blockexplorer'); - var updateBlockExplorer = function (blocks) { + const blockexplorer = document.getElementById('blockexplorer'); + const updateBlockExplorer = function (blocks) { blockexplorer.innerHTML = JSON.stringify(blocks, null, 2); window.hljs.highlightBlock(blockexplorer); }; // Thread representation tab. - var threadexplorer = document.getElementById('threadexplorer'); - var cachedThreadJSON = ''; - var updateThreadExplorer = function (newJSON) { + const threadexplorer = document.getElementById('threadexplorer'); + let cachedThreadJSON = ''; + const updateThreadExplorer = function (newJSON) { if (newJSON !== cachedThreadJSON) { cachedThreadJSON = newJSON; threadexplorer.innerHTML = cachedThreadJSON; @@ -129,28 +129,28 @@ window.onload = function () { // VM handlers. // Receipt of new playground data (thread, block representations). - vm.on('playgroundData', function (data) { + vm.on('playgroundData', data => { updateThreadExplorer(data.threads); updateBlockExplorer(data.blocks); }); // Receipt of new block XML for the selected target. - vm.on('workspaceUpdate', function (data) { + vm.on('workspaceUpdate', data => { workspace.clear(); - var dom = window.Blockly.Xml.textToDom(data.xml); + const dom = window.Blockly.Xml.textToDom(data.xml); window.Blockly.Xml.domToWorkspace(dom, workspace); }); // Receipt of new list of targets, selected target update. - var selectedTarget = document.getElementById('selectedTarget'); - vm.on('targetsUpdate', function (data) { + const selectedTarget = document.getElementById('selectedTarget'); + vm.on('targetsUpdate', data => { // Clear select box. while (selectedTarget.firstChild) { selectedTarget.removeChild(selectedTarget.firstChild); } // Generate new select box. - for (var i = 0; i < data.targetList.length; i++) { - var targetOption = document.createElement('option'); + for (let i = 0; i < data.targetList.length; i++) { + const targetOption = document.createElement('option'); targetOption.setAttribute('value', data.targetList[i].id); // If target id matches editingTarget id, select it. if (data.targetList[i].id === data.editingTarget) { @@ -167,23 +167,23 @@ window.onload = function () { }; // Feedback for stacks and blocks running. - vm.on('SCRIPT_GLOW_ON', function (data) { + vm.on('SCRIPT_GLOW_ON', data => { workspace.glowStack(data.id, true); }); - vm.on('SCRIPT_GLOW_OFF', function (data) { + vm.on('SCRIPT_GLOW_OFF', data => { workspace.glowStack(data.id, false); }); - vm.on('BLOCK_GLOW_ON', function (data) { + vm.on('BLOCK_GLOW_ON', data => { workspace.glowBlock(data.id, true); }); - vm.on('BLOCK_GLOW_OFF', function (data) { + vm.on('BLOCK_GLOW_OFF', data => { workspace.glowBlock(data.id, false); }); - vm.on('VISUAL_REPORT', function (data) { + vm.on('VISUAL_REPORT', data => { workspace.reportValue(data.id, data.value); }); - vm.on('SPRITE_INFO_REPORT', function (data) { + vm.on('SPRITE_INFO_REPORT', data => { if (data.id !== selectedTarget.value) return; // Not the editingTarget document.getElementById('sinfo-x').value = data.x; document.getElementById('sinfo-y').value = data.y; @@ -193,8 +193,8 @@ window.onload = function () { document.getElementById('sinfo-visible').value = data.visible; }); - document.getElementById('sinfo-post').addEventListener('click', function () { - var data = {}; + document.getElementById('sinfo-post').addEventListener('click', () => { + const data = {}; data.x = document.getElementById('sinfo-x').value; data.y = document.getElementById('sinfo-y').value; data.direction = document.getElementById('sinfo-direction').value; @@ -204,9 +204,9 @@ window.onload = function () { }); // Feed mouse events as VM I/O events. - document.addEventListener('mousemove', function (e) { - var rect = canvas.getBoundingClientRect(); - var coordinates = { + document.addEventListener('mousemove', e => { + const rect = canvas.getBoundingClientRect(); + const coordinates = { x: e.clientX - rect.left, y: e.clientY - rect.top, canvasWidth: rect.width, @@ -214,9 +214,9 @@ window.onload = function () { }; Scratch.vm.postIOData('mouse', coordinates); }); - canvas.addEventListener('mousedown', function (e) { - var rect = canvas.getBoundingClientRect(); - var data = { + canvas.addEventListener('mousedown', e => { + const rect = canvas.getBoundingClientRect(); + const data = { isDown: true, x: e.clientX - rect.left, y: e.clientY - rect.top, @@ -226,9 +226,9 @@ window.onload = function () { Scratch.vm.postIOData('mouse', data); e.preventDefault(); }); - canvas.addEventListener('mouseup', function (e) { - var rect = canvas.getBoundingClientRect(); - var data = { + canvas.addEventListener('mouseup', e => { + const rect = canvas.getBoundingClientRect(); + const data = { isDown: false, x: e.clientX - rect.left, y: e.clientY - rect.top, @@ -240,7 +240,7 @@ window.onload = function () { }); // Feed keyboard events as VM I/O events. - document.addEventListener('keydown', function (e) { + document.addEventListener('keydown', e => { // Don't capture keys intended for Blockly inputs. if (e.target !== document && e.target !== document.body) { return; @@ -251,7 +251,7 @@ window.onload = function () { }); e.preventDefault(); }); - document.addEventListener('keyup', function (e) { + document.addEventListener('keyup', e => { // Always capture up events, // even those that have switched to other targets. Scratch.vm.postIOData('keyboard', { @@ -275,29 +275,29 @@ window.onload = function () { requestAnimationFrame(animate); // Handlers for green flag and stop all. - document.getElementById('greenflag').addEventListener('click', function () { + document.getElementById('greenflag').addEventListener('click', () => { vm.greenFlag(); }); - document.getElementById('stopall').addEventListener('click', function () { + document.getElementById('stopall').addEventListener('click', () => { vm.stopAll(); }); - document.getElementById('turbomode').addEventListener('change', function () { - var turboOn = document.getElementById('turbomode').checked; + document.getElementById('turbomode').addEventListener('change', () => { + const turboOn = document.getElementById('turbomode').checked; vm.setTurboMode(turboOn); }); document.getElementById('compatmode').addEventListener('change', - function () { - var compatibilityMode = document.getElementById('compatmode').checked; + () => { + const compatibilityMode = document.getElementById('compatmode').checked; vm.setCompatibilityMode(compatibilityMode); }); - var tabBlockExplorer = document.getElementById('tab-blockexplorer'); - var tabThreadExplorer = document.getElementById('tab-threadexplorer'); - var tabRenderExplorer = document.getElementById('tab-renderexplorer'); - var tabImportExport = document.getElementById('tab-importexport'); + const tabBlockExplorer = document.getElementById('tab-blockexplorer'); + const tabThreadExplorer = document.getElementById('tab-threadexplorer'); + const tabRenderExplorer = document.getElementById('tab-renderexplorer'); + const tabImportExport = document.getElementById('tab-importexport'); // Handlers to show different explorers. document.getElementById('threadexplorer-link').addEventListener('click', - function () { + () => { Scratch.exploreTabOpen = true; getPlaygroundData(); tabBlockExplorer.style.display = 'none'; @@ -306,7 +306,7 @@ window.onload = function () { tabImportExport.style.display = 'none'; }); document.getElementById('blockexplorer-link').addEventListener('click', - function () { + () => { Scratch.exploreTabOpen = true; getPlaygroundData(); tabBlockExplorer.style.display = 'block'; @@ -315,7 +315,7 @@ window.onload = function () { tabImportExport.style.display = 'none'; }); document.getElementById('renderexplorer-link').addEventListener('click', - function () { + () => { Scratch.exploreTabOpen = false; tabBlockExplorer.style.display = 'none'; tabRenderExplorer.style.display = 'block'; @@ -323,7 +323,7 @@ window.onload = function () { tabImportExport.style.display = 'none'; }); document.getElementById('importexport-link').addEventListener('click', - function () { + () => { Scratch.exploreTabOpen = false; tabBlockExplorer.style.display = 'none'; tabRenderExplorer.style.display = 'none'; diff --git a/src/sprites/rendered-target.js b/src/sprites/rendered-target.js index 29154af344f..f6465da416b 100644 --- a/src/sprites/rendered-target.js +++ b/src/sprites/rendered-target.js @@ -1,8 +1,8 @@ -var util = require('util'); +const util = require('util'); -var log = require('../util/log'); -var MathUtil = require('../util/math-util'); -var Target = require('../engine/target'); +const log = require('../util/log'); +const MathUtil = require('../util/math-util'); +const Target = require('../engine/target'); /** * Rendered target: instance of a sprite (clone), or the stage. @@ -10,7 +10,7 @@ var Target = require('../engine/target'); * @param {Runtime} runtime Reference to the runtime. * @constructor */ -var RenderedTarget = function (sprite, runtime) { +const RenderedTarget = function (sprite, runtime) { Target.call(this, sprite.blocks); this.runtime = runtime; /** @@ -175,10 +175,10 @@ RenderedTarget.prototype.rotationStyle = ( RenderedTarget.prototype.setXY = function (x, y, force) { if (this.isStage) return; if (this.dragging && !force) return; - var oldX = this.x; - var oldY = this.y; + const oldX = this.x; + const oldY = this.y; if (this.renderer) { - var position = this.renderer.getFencedPositionOfDrawable(this.drawableID, [x, y]); + const position = this.renderer.getFencedPositionOfDrawable(this.drawableID, [x, y]); this.x = position[0]; this.y = position[1]; @@ -202,15 +202,15 @@ RenderedTarget.prototype.setXY = function (x, y, force) { */ RenderedTarget.prototype._getRenderedDirectionAndScale = function () { // Default: no changes to `this.direction` or `this.scale`. - var finalDirection = this.direction; - var finalScale = [this.size, this.size]; + let finalDirection = this.direction; + let finalScale = [this.size, this.size]; if (this.rotationStyle === RenderedTarget.ROTATION_STYLE_NONE) { // Force rendered direction to be 90. finalDirection = 90; } else if (this.rotationStyle === RenderedTarget.ROTATION_STYLE_LEFT_RIGHT) { // Force rendered direction to be 90, and flip drawable if needed. finalDirection = 90; - var scaleFlip = (this.direction < 0) ? -1 : 1; + const scaleFlip = (this.direction < 0) ? -1 : 1; finalScale = [scaleFlip * this.size, this.size]; } return {direction: finalDirection, scale: finalScale}; @@ -227,7 +227,7 @@ RenderedTarget.prototype.setDirection = function (direction) { // Keep direction between -179 and +180. this.direction = MathUtil.wrapClamp(direction, -179, 180); if (this.renderer) { - var renderedDirectionScale = this._getRenderedDirectionAndScale(); + const renderedDirectionScale = this._getRenderedDirectionAndScale(); this.renderer.updateDrawableProperties(this.drawableID, { direction: renderedDirectionScale.direction, scale: renderedDirectionScale.scale @@ -297,16 +297,16 @@ RenderedTarget.prototype.setSize = function (size) { if (this.renderer) { // Clamp to scales relative to costume and stage size. // See original ScratchSprite.as:setSize. - var costumeSize = this.renderer.getSkinSize(this.drawableID); - var origW = costumeSize[0]; - var origH = costumeSize[1]; - var minScale = Math.min(1, Math.max(5 / origW, 5 / origH)); - var maxScale = Math.min( + const costumeSize = this.renderer.getSkinSize(this.drawableID); + const origW = costumeSize[0]; + const origH = costumeSize[1]; + const minScale = Math.min(1, Math.max(5 / origW, 5 / origH)); + const maxScale = Math.min( (1.5 * this.runtime.constructor.STAGE_WIDTH) / origW, (1.5 * this.runtime.constructor.STAGE_HEIGHT) / origH ); this.size = MathUtil.clamp(size / 100, minScale, maxScale) * 100; - var renderedDirectionScale = this._getRenderedDirectionAndScale(); + const renderedDirectionScale = this._getRenderedDirectionAndScale(); this.renderer.updateDrawableProperties(this.drawableID, { direction: renderedDirectionScale.direction, scale: renderedDirectionScale.scale @@ -326,7 +326,7 @@ RenderedTarget.prototype.setEffect = function (effectName, value) { if (!this.effects.hasOwnProperty(effectName)) return; this.effects[effectName] = value; if (this.renderer) { - var props = {}; + const props = {}; props[effectName] = this.effects[effectName]; this.renderer.updateDrawableProperties(this.drawableID, props); if (this.visible) { @@ -339,7 +339,7 @@ RenderedTarget.prototype.setEffect = function (effectName, value) { * Clear all graphic effects on this rendered target. */ RenderedTarget.prototype.clearEffects = function () { - for (var effectName in this.effects) { + for (const effectName in this.effects) { if (!this.effects.hasOwnProperty(effectName)) continue; this.effects[effectName] = 0; } @@ -362,8 +362,8 @@ RenderedTarget.prototype.setCostume = function (index) { index, 0, this.sprite.costumes.length - 1 ); if (this.renderer) { - var costume = this.sprite.costumes[this.currentCostume]; - var drawableProperties = { + const costume = this.sprite.costumes[this.currentCostume]; + const drawableProperties = { skinId: costume.skinId, costumeResolution: costume.bitmapResolution }; @@ -371,7 +371,7 @@ RenderedTarget.prototype.setCostume = function (index) { typeof costume.rotationCenterX !== 'undefined' && typeof costume.rotationCenterY !== 'undefined' ) { - var scale = costume.bitmapResolution || 1; + const scale = costume.bitmapResolution || 1; drawableProperties.rotationCenter = [ costume.rotationCenterX / scale, costume.rotationCenterY / scale @@ -398,7 +398,7 @@ RenderedTarget.prototype.setRotationStyle = function (rotationStyle) { this.rotationStyle = RenderedTarget.ROTATION_STYLE_LEFT_RIGHT; } if (this.renderer) { - var renderedDirectionScale = this._getRenderedDirectionAndScale(); + const renderedDirectionScale = this._getRenderedDirectionAndScale(); this.renderer.updateDrawableProperties(this.drawableID, { direction: renderedDirectionScale.direction, scale: renderedDirectionScale.scale @@ -416,7 +416,7 @@ RenderedTarget.prototype.setRotationStyle = function (rotationStyle) { * @return {number} Index of the named costume, or -1 if not present. */ RenderedTarget.prototype.getCostumeIndexByName = function (costumeName) { - for (var i = 0; i < this.sprite.costumes.length; i++) { + for (let i = 0; i < this.sprite.costumes.length; i++) { if (this.sprite.costumes[i].name === costumeName) { return i; } @@ -454,10 +454,10 @@ RenderedTarget.prototype.getSounds = function () { */ RenderedTarget.prototype.updateAllDrawableProperties = function () { if (this.renderer) { - var renderedDirectionScale = this._getRenderedDirectionAndScale(); - var costume = this.sprite.costumes[this.currentCostume]; - var bitmapResolution = costume.bitmapResolution || 1; - var props = { + const renderedDirectionScale = this._getRenderedDirectionAndScale(); + const costume = this.sprite.costumes[this.currentCostume]; + const bitmapResolution = costume.bitmapResolution || 1; + const props = { position: [this.x, this.y], direction: renderedDirectionScale.direction, draggable: this.draggable, @@ -470,7 +470,7 @@ RenderedTarget.prototype.updateAllDrawableProperties = function () { costume.rotationCenterY / bitmapResolution ] }; - for (var effectName in this.effects) { + for (const effectName in this.effects) { if (!this.effects.hasOwnProperty(effectName)) continue; props[effectName] = this.effects[effectName]; } @@ -522,7 +522,7 @@ RenderedTarget.prototype.isTouchingPoint = function (x, y) { // @todo: Update once pick is in Scratch coordinates. // Limits test to this Drawable, so this will return true // even if the clone is obscured by another Drawable. - var pickResult = this.runtime.renderer.pick( + const pickResult = this.runtime.renderer.pick( x + (this.runtime.constructor.STAGE_WIDTH / 2), -y + (this.runtime.constructor.STAGE_HEIGHT / 2), null, null, @@ -539,9 +539,9 @@ RenderedTarget.prototype.isTouchingPoint = function (x, y) { */ RenderedTarget.prototype.isTouchingEdge = function () { if (this.renderer) { - var stageWidth = this.runtime.constructor.STAGE_WIDTH; - var stageHeight = this.runtime.constructor.STAGE_HEIGHT; - var bounds = this.getBounds(); + const stageWidth = this.runtime.constructor.STAGE_WIDTH; + const stageHeight = this.runtime.constructor.STAGE_HEIGHT; + const bounds = this.getBounds(); if (bounds.left < -stageWidth / 2 || bounds.right > stageWidth / 2 || bounds.top > stageHeight / 2 || @@ -558,13 +558,11 @@ RenderedTarget.prototype.isTouchingEdge = function () { * @return {boolean} True iff touching a clone of the sprite. */ RenderedTarget.prototype.isTouchingSprite = function (spriteName) { - var firstClone = this.runtime.getSpriteTargetByName(spriteName); + const firstClone = this.runtime.getSpriteTargetByName(spriteName); if (!firstClone || !this.renderer) { return false; } - var drawableCandidates = firstClone.sprite.clones.map(function (clone) { - return clone.drawableID; - }); + const drawableCandidates = firstClone.sprite.clones.map(clone => clone.drawableID); return this.renderer.isTouchingDrawables( this.drawableID, drawableCandidates); }; @@ -623,7 +621,7 @@ RenderedTarget.prototype.goBackLayers = function (nLayers) { */ RenderedTarget.prototype.goBehindOther = function (other) { if (this.renderer) { - var otherLayer = this.renderer.setDrawableOrder( + const otherLayer = this.renderer.setDrawableOrder( other.drawableID, 0, true); this.renderer.setDrawableOrder(this.drawableID, otherLayer); } @@ -637,7 +635,7 @@ RenderedTarget.prototype.goBehindOther = function (other) { * @return {Array.} Fenced X and Y coordinates. */ RenderedTarget.prototype.keepInFence = function (newX, newY, optFence) { - var fence = optFence; + let fence = optFence; if (!fence) { fence = { left: -this.runtime.constructor.STAGE_WIDTH / 2, @@ -646,7 +644,7 @@ RenderedTarget.prototype.keepInFence = function (newX, newY, optFence) { bottom: -this.runtime.constructor.STAGE_HEIGHT / 2 }; } - var bounds = this.getBounds(); + const bounds = this.getBounds(); if (!bounds) return; // Adjust the known bounds to the target position. bounds.left += (newX - this.x); @@ -654,8 +652,8 @@ RenderedTarget.prototype.keepInFence = function (newX, newY, optFence) { bounds.top += (newY - this.y); bounds.bottom += (newY - this.y); // Find how far we need to move the target position. - var dx = 0; - var dy = 0; + let dx = 0; + let dy = 0; if (bounds.left < fence.left) { dx += fence.left - bounds.left; } @@ -681,7 +679,7 @@ RenderedTarget.prototype.makeClone = function () { return null; // Hit max clone limit, or this is the stage. } this.runtime.changeCloneCounter(1); - var newClone = this.sprite.createClone(); + const newClone = this.sprite.createClone(); // Copy all properties. newClone.x = this.x; newClone.y = this.y; @@ -726,7 +724,7 @@ RenderedTarget.prototype.onStopAll = function () { * @param {object} data An object with sprite info data to set. */ RenderedTarget.prototype.postSpriteInfo = function (data) { - var force = data.hasOwnProperty('force') ? data.force : null; + const force = data.hasOwnProperty('force') ? data.force : null; if (data.hasOwnProperty('x')) { this.setXY(data.x, this.y, force); } diff --git a/src/sprites/sprite.js b/src/sprites/sprite.js index 8f341987d4e..a6b00c2e1f2 100644 --- a/src/sprites/sprite.js +++ b/src/sprites/sprite.js @@ -1,5 +1,5 @@ -var RenderedTarget = require('./rendered-target'); -var Blocks = require('../engine/blocks'); +const RenderedTarget = require('./rendered-target'); +const Blocks = require('../engine/blocks'); /** * Sprite to be used on the Scratch stage. @@ -8,7 +8,7 @@ var Blocks = require('../engine/blocks'); * @param {Runtime} runtime Reference to the runtime. * @constructor */ -var Sprite = function (blocks, runtime) { +const Sprite = function (blocks, runtime) { this.runtime = runtime; if (!blocks) { // Shared set of blocks for all clones. @@ -49,7 +49,7 @@ var Sprite = function (blocks, runtime) { * @returns {!RenderedTarget} Newly created clone. */ Sprite.prototype.createClone = function () { - var newClone = new RenderedTarget(this, this.runtime); + const newClone = new RenderedTarget(this, this.runtime); newClone.isOriginal = this.clones.length === 0; this.clones.push(newClone); if (newClone.isOriginal) { diff --git a/src/util/cast.js b/src/util/cast.js index 79e76b13488..0d4f26dbf24 100644 --- a/src/util/cast.js +++ b/src/util/cast.js @@ -1,6 +1,6 @@ -var Color = require('../util/color'); +const Color = require('../util/color'); -var Cast = function () {}; +const Cast = function () {}; /** * @fileoverview @@ -21,7 +21,7 @@ var Cast = function () {}; * @return {number} The Scratch-casted number value. */ Cast.toNumber = function (value) { - var n = Number(value); + const n = Number(value); if (isNaN(n)) { // Scratch treats NaN as 0, when needed as a number. // E.g., 0 + NaN -> 0. @@ -71,7 +71,7 @@ Cast.toString = function (value) { * @return {Array.} [r,g,b], values between 0-255. */ Cast.toRgbColorList = function (value) { - var color = Cast.toRgbColorObject(value); + const color = Cast.toRgbColorObject(value); return [color.r, color.g, color.b]; }; @@ -81,7 +81,7 @@ Cast.toRgbColorList = function (value) { * @return {RGBOject} [r,g,b], values between 0-255. */ Cast.toRgbColorObject = function (value) { - var color; + let color; if (typeof value === 'string' && value.substring(0, 1) === '#') { color = Color.hexToRgb(value); } else { @@ -107,8 +107,8 @@ Cast.isWhiteSpace = function (val) { * @returns {number} Negative number if v1 < v2; 0 if equal; positive otherwise. */ Cast.compare = function (v1, v2) { - var n1 = Number(v1); - var n2 = Number(v2); + let n1 = Number(v1); + let n2 = Number(v2); if (n1 === 0 && Cast.isWhiteSpace(v1)) { n1 = NaN; } else if (n2 === 0 && Cast.isWhiteSpace(v2)) { @@ -117,13 +117,13 @@ Cast.compare = function (v1, v2) { if (isNaN(n1) || isNaN(n2)) { // At least one argument can't be converted to a number. // Scratch compares strings as case insensitive. - var s1 = String(v1).toLowerCase(); - var s2 = String(v2).toLowerCase(); + const s1 = String(v1).toLowerCase(); + const s2 = String(v2).toLowerCase(); return s1.localeCompare(s2); - } else { - // Compare as numbers. - return n1 - n2; } + // Compare as numbers. + return n1 - n2; + }; /** diff --git a/src/util/clone.js b/src/util/clone.js index 5e1011a294a..035cadc6dcb 100644 --- a/src/util/clone.js +++ b/src/util/clone.js @@ -2,7 +2,7 @@ * Methods for cloning JavaScript objects. * @type {object} */ -var Clone = {}; +const Clone = {}; /** * Deep-clone a "simple" object: one which can be fully expressed with JSON. diff --git a/src/util/color.js b/src/util/color.js index 11082d66008..1229e0eaf63 100644 --- a/src/util/color.js +++ b/src/util/color.js @@ -1,4 +1,4 @@ -var Color = function () {}; +const Color = function () {}; /** * @typedef {object} RGBObject - An object representing a color in RGB format. @@ -29,8 +29,8 @@ Color.decimalToHex = function (decimal) { if (decimal < 0) { decimal += 0xFFFFFF + 1; } - var hex = Number(decimal).toString(16); - hex = '#' + '000000'.substr(0, 6 - hex.length) + hex; + let hex = Number(decimal).toString(16); + hex = `#${'000000'.substr(0, 6 - hex.length)}${hex}`; return hex; }; @@ -40,10 +40,10 @@ Color.decimalToHex = function (decimal) { * @return {RGBObject} rgb - {r: red [0,255], g: green [0,255], b: blue [0,255]}. */ Color.decimalToRgb = function (decimal) { - var a = (decimal >> 24) & 0xFF; - var r = (decimal >> 16) & 0xFF; - var g = (decimal >> 8) & 0xFF; - var b = decimal & 0xFF; + const a = (decimal >> 24) & 0xFF; + const r = (decimal >> 16) & 0xFF; + const g = (decimal >> 8) & 0xFF; + const b = decimal & 0xFF; return {r: r, g: g, b: b, a: a > 0 ? a : 255}; }; @@ -55,11 +55,9 @@ Color.decimalToRgb = function (decimal) { * @return {RGBObject} null on failure, or rgb: {r: red [0,255], g: green [0,255], b: blue [0,255]}. */ Color.hexToRgb = function (hex) { - var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; - hex = hex.replace(shorthandRegex, function (m, r, g, b) { - return r + r + g + g + b + b; - }); - var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; + hex = hex.replace(shorthandRegex, (m, r, g, b) => r + r + g + g + b + b); + const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), @@ -100,20 +98,20 @@ Color.hexToDecimal = function (hex) { * @return {RGBObject} rgb - {r: red [0,255], g: green [0,255], b: blue [0,255]}. */ Color.hsvToRgb = function (hsv) { - var h = hsv.h % 360; + let h = hsv.h % 360; if (h < 0) h += 360; - var s = Math.max(0, Math.min(hsv.s, 1)); - var v = Math.max(0, Math.min(hsv.v, 1)); + const s = Math.max(0, Math.min(hsv.s, 1)); + const v = Math.max(0, Math.min(hsv.v, 1)); - var i = Math.floor(h / 60); - var f = (h / 60) - i; - var p = v * (1 - s); - var q = v * (1 - (s * f)); - var t = v * (1 - (s * (1 - f))); + const i = Math.floor(h / 60); + const f = (h / 60) - i; + const p = v * (1 - s); + const q = v * (1 - (s * f)); + const t = v * (1 - (s * (1 - f))); - var r; - var g; - var b; + let r; + let g; + let b; switch (i) { default: @@ -162,18 +160,18 @@ Color.hsvToRgb = function (hsv) { * @return {HSVObject} hsv - {h: hue [0,360), s: saturation [0,1], v: value [0,1]} */ Color.rgbToHsv = function (rgb) { - var r = rgb.r / 255; - var g = rgb.g / 255; - var b = rgb.b / 255; - var x = Math.min(Math.min(r, g), b); - var v = Math.max(Math.max(r, g), b); + const r = rgb.r / 255; + const g = rgb.g / 255; + const b = rgb.b / 255; + const x = Math.min(Math.min(r, g), b); + const v = Math.max(Math.max(r, g), b); // For grays, hue will be arbitrarily reported as zero. Otherwise, calculate - var h = 0; - var s = 0; + let h = 0; + let s = 0; if (x !== v) { - var f = (r === x) ? g - b : ((g === x) ? b - r : r - g); - var i = (r === x) ? 3 : ((g === x) ? 5 : 1); + const f = (r === x) ? g - b : ((g === x) ? b - r : r - g); + const i = (r === x) ? 3 : ((g === x) ? 5 : 1); h = ((i - (f / (v - x))) * 60) % 360; s = (v - x) / v; } @@ -191,7 +189,7 @@ Color.rgbToHsv = function (rgb) { Color.mixRgb = function (rgb0, rgb1, fraction1) { if (fraction1 <= 0) return rgb0; if (fraction1 >= 1) return rgb1; - var fraction0 = 1 - fraction1; + const fraction0 = 1 - fraction1; return { r: (fraction0 * rgb0.r) + (fraction1 * rgb1.r), g: (fraction0 * rgb0.g) + (fraction1 * rgb1.g), diff --git a/src/util/log.js b/src/util/log.js index 28e596a1272..cdc04520e0c 100644 --- a/src/util/log.js +++ b/src/util/log.js @@ -1,4 +1,4 @@ -var minilog = require('minilog'); +const minilog = require('minilog'); minilog.enable(); module.exports = minilog('vm'); diff --git a/src/util/math-util.js b/src/util/math-util.js index 6191fdec5ec..b92452b1cdd 100644 --- a/src/util/math-util.js +++ b/src/util/math-util.js @@ -1,4 +1,4 @@ -var MathUtil = function () {}; +const MathUtil = function () {}; /** * Convert a value from degrees to radians. @@ -41,7 +41,7 @@ MathUtil.clamp = function (n, min, max) { * @return {!number} Value of n wrapped between min and max. */ MathUtil.wrapClamp = function (n, min, max) { - var range = (max - min) + 1; + const range = (max - min) + 1; return n - (Math.floor((n - min) / range) * range); }; diff --git a/src/util/string-util.js b/src/util/string-util.js index 6270cd88509..ed40a2e6ce2 100644 --- a/src/util/string-util.js +++ b/src/util/string-util.js @@ -1,7 +1,7 @@ -var StringUtil = function () {}; +const StringUtil = function () {}; StringUtil.withoutTrailingDigits = function (s) { - var i = s.length - 1; + let i = s.length - 1; while ((i >= 0) && ('0123456789'.indexOf(s.charAt(i)) > -1)) i--; return s.slice(0, i + 1); }; @@ -9,7 +9,7 @@ StringUtil.withoutTrailingDigits = function (s) { StringUtil.unusedName = function (name, existingNames) { if (existingNames.indexOf(name) < 0) return name; name = StringUtil.withoutTrailingDigits(name); - var i = 2; + let i = 2; while (existingNames.indexOf(name + i) >= 0) i++; return name + i; }; diff --git a/src/util/timer.js b/src/util/timer.js index 9a60e56880d..79a1852b5fd 100644 --- a/src/util/timer.js +++ b/src/util/timer.js @@ -15,7 +15,7 @@ /** * @constructor */ -var Timer = function () {}; +const Timer = function () {}; /** * Used to store the start time of a timer action. @@ -28,13 +28,13 @@ Timer.prototype.startTime = 0; * However, instancing it like below (caching the self.performance to a local variable) negates most of the issues. * @type {boolean} */ -var USE_PERFORMANCE = false; +const USE_PERFORMANCE = false; /** * Legacy object to allow for us to call now to get the old style date time (for backwards compatibility) * @deprecated This is only called via the nowObj.now() if no other means is possible... */ -var legacyDateCode = { +const legacyDateCode = { now: function () { return new Date().getTime(); } @@ -43,7 +43,7 @@ var legacyDateCode = { /** * Use this object to route all time functions through single access points. */ -var nowObj = (USE_PERFORMANCE && typeof self !== 'undefined' && self.performance && 'now' in self.performance) ? +const nowObj = (USE_PERFORMANCE && typeof self !== 'undefined' && self.performance && 'now' in self.performance) ? self.performance : Date.now ? Date : legacyDateCode; /** diff --git a/src/util/uid.js b/src/util/uid.js index 532f9e9bf38..fd4c41e8710 100644 --- a/src/util/uid.js +++ b/src/util/uid.js @@ -8,7 +8,7 @@ * Removed $ due to issue 251. * @private */ -var soup_ = '!#%()*+,-./:;=?@[]^_`{|}~' + +const soup_ = '!#%()*+,-./:;=?@[]^_`{|}~' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; /** @@ -16,11 +16,11 @@ var soup_ = '!#%()*+,-./:;=?@[]^_`{|}~' + * 87 characters ^ 20 length > 128 bits (better than a UUID). * @return {string} A globally unique ID string. */ -var uid = function () { - var length = 20; - var soupLength = soup_.length; - var id = []; - for (var i = 0; i < length; i++) { +const uid = function () { + const length = 20; + const soupLength = soup_.length; + const id = []; + for (let i = 0; i < length; i++) { id[i] = soup_.charAt(Math.random() * soupLength); } return id.join(''); diff --git a/src/util/xml-escape.js b/src/util/xml-escape.js index 00ce5bff61a..66daf83b44a 100644 --- a/src/util/xml-escape.js +++ b/src/util/xml-escape.js @@ -6,8 +6,8 @@ * @param {!string} unsafe Unsafe string. * @return {string} XML-escaped string, for use within an XML tag. */ -var xmlEscape = function (unsafe) { - return unsafe.replace(/[<>&'"]/g, function (c) { +const xmlEscape = function (unsafe) { + return unsafe.replace(/[<>&'"]/g, c => { switch (c) { case '<': return '<'; case '>': return '>'; diff --git a/src/virtual-machine.js b/src/virtual-machine.js index b85705e379a..845dd3296cb 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -1,25 +1,25 @@ -var EventEmitter = require('events'); -var util = require('util'); +const EventEmitter = require('events'); +const util = require('util'); -var log = require('./util/log'); -var Runtime = require('./engine/runtime'); -var ScratchStorage = require('scratch-storage'); -var sb2import = require('./import/sb2import'); -var StringUtil = require('./util/string-util'); +const log = require('./util/log'); +const Runtime = require('./engine/runtime'); +const ScratchStorage = require('scratch-storage'); +const sb2import = require('./import/sb2import'); +const StringUtil = require('./util/string-util'); -var loadCostume = require('./import/load-costume.js'); -var loadSound = require('./import/load-sound.js'); +const loadCostume = require('./import/load-costume.js'); +const loadSound = require('./import/load-sound.js'); -var RESERVED_NAMES = ['_mouse_', '_stage_', '_edge_', '_myself_', '_random_']; +const RESERVED_NAMES = ['_mouse_', '_stage_', '_edge_', '_myself_', '_random_']; -var AssetType = ScratchStorage.AssetType; +const AssetType = ScratchStorage.AssetType; /** * Handles connections between blocks, stage, and extensions. * @constructor */ -var VirtualMachine = function () { - var instance = this; +const VirtualMachine = function () { + const instance = this; // Bind event emitter and runtime to VM instance EventEmitter.call(instance); /** @@ -34,28 +34,28 @@ var VirtualMachine = function () { */ instance.editingTarget = null; // Runtime emits are passed along as VM emits. - instance.runtime.on(Runtime.SCRIPT_GLOW_ON, function (glowData) { + instance.runtime.on(Runtime.SCRIPT_GLOW_ON, glowData => { instance.emit(Runtime.SCRIPT_GLOW_ON, glowData); }); - instance.runtime.on(Runtime.SCRIPT_GLOW_OFF, function (glowData) { + instance.runtime.on(Runtime.SCRIPT_GLOW_OFF, glowData => { instance.emit(Runtime.SCRIPT_GLOW_OFF, glowData); }); - instance.runtime.on(Runtime.BLOCK_GLOW_ON, function (glowData) { + instance.runtime.on(Runtime.BLOCK_GLOW_ON, glowData => { instance.emit(Runtime.BLOCK_GLOW_ON, glowData); }); - instance.runtime.on(Runtime.BLOCK_GLOW_OFF, function (glowData) { + instance.runtime.on(Runtime.BLOCK_GLOW_OFF, glowData => { instance.emit(Runtime.BLOCK_GLOW_OFF, glowData); }); - instance.runtime.on(Runtime.PROJECT_RUN_START, function () { + instance.runtime.on(Runtime.PROJECT_RUN_START, () => { instance.emit(Runtime.PROJECT_RUN_START); }); - instance.runtime.on(Runtime.PROJECT_RUN_STOP, function () { + instance.runtime.on(Runtime.PROJECT_RUN_STOP, () => { instance.emit(Runtime.PROJECT_RUN_STOP); }); - instance.runtime.on(Runtime.VISUAL_REPORT, function (visualReport) { + instance.runtime.on(Runtime.VISUAL_REPORT, visualReport => { instance.emit(Runtime.VISUAL_REPORT, visualReport); }); - instance.runtime.on(Runtime.SPRITE_INFO_REPORT, function (spriteInfo) { + instance.runtime.on(Runtime.SPRITE_INFO_REPORT, spriteInfo => { instance.emit(Runtime.SPRITE_INFO_REPORT, spriteInfo); }); @@ -120,13 +120,11 @@ VirtualMachine.prototype.clear = function () { * Get data for playground. Data comes back in an emitted event. */ VirtualMachine.prototype.getPlaygroundData = function () { - var instance = this; + const instance = this; // Only send back thread data for the current editingTarget. - var threadData = this.runtime.threads.filter(function (thread) { - return thread.target === instance.editingTarget; - }); + const threadData = this.runtime.threads.filter(thread => thread.target === instance.editingTarget); // Remove the target key, since it's a circular reference. - var filteredThreadData = JSON.stringify(threadData, function (key, value) { + const filteredThreadData = JSON.stringify(threadData, (key, value) => { if (key === 'target') return; return value; }, 2); @@ -172,9 +170,9 @@ VirtualMachine.prototype.downloadProjectId = function (id) { log.error('No storage module present; cannot load project: ', id); return; } - var vm = this; - var promise = this.runtime.storage.load(AssetType.Project, id); - promise.then(function (projectAsset) { + const vm = this; + const promise = this.runtime.storage.load(AssetType.Project, id); + promise.then(projectAsset => { vm.loadProject(projectAsset.decodeText()); }); }; @@ -202,12 +200,12 @@ VirtualMachine.prototype.addSprite2 = function (json) { * @property {number} [bitmapResolution] - the resolution scale for a bitmap costume. */ VirtualMachine.prototype.addCostume = function (md5ext, costumeObject) { - loadCostume(md5ext, costumeObject, this.runtime).then(function () { + loadCostume(md5ext, costumeObject, this.runtime).then(() => { this.editingTarget.sprite.costumes.push(costumeObject); this.editingTarget.setCostume( this.editingTarget.sprite.costumes.length - 1 ); - }.bind(this)); + }); }; /** @@ -216,10 +214,10 @@ VirtualMachine.prototype.addCostume = function (md5ext, costumeObject) { * @returns {?Promise} - a promise that resolves when the sound has been decoded and added */ VirtualMachine.prototype.addSound = function (soundObject) { - return loadSound(soundObject, this.runtime).then(function () { + return loadSound(soundObject, this.runtime).then(() => { this.editingTarget.sprite.sounds.push(soundObject); this.emitTargetsUpdate(); - }.bind(this)); + }); }; /** @@ -232,11 +230,11 @@ VirtualMachine.prototype.addSound = function (soundObject) { * @property {number} [bitmapResolution] - the resolution scale for a bitmap backdrop. */ VirtualMachine.prototype.addBackdrop = function (md5ext, backdropObject) { - loadCostume(md5ext, backdropObject, this.runtime).then(function () { - var stage = this.runtime.getTargetForStage(); + loadCostume(md5ext, backdropObject, this.runtime).then(() => { + const stage = this.runtime.getTargetForStage(); stage.sprite.costumes.push(backdropObject); stage.setCostume(stage.sprite.costumes.length - 1); - }.bind(this)); + }); }; /** @@ -245,21 +243,17 @@ VirtualMachine.prototype.addBackdrop = function (md5ext, backdropObject) { * @param {string} newName New name of the sprite. */ VirtualMachine.prototype.renameSprite = function (targetId, newName) { - var target = this.runtime.getTargetById(targetId); + const target = this.runtime.getTargetById(targetId); if (target) { if (!target.isSprite()) { throw new Error('Cannot rename non-sprite targets.'); } - var sprite = target.sprite; + const sprite = target.sprite; if (!sprite) { throw new Error('No sprite associated with this target.'); } if (newName && RESERVED_NAMES.indexOf(newName) === -1) { - var names = this.runtime.targets.filter(function (runtimeTarget) { - return runtimeTarget.isSprite(); - }).map(function (runtimeTarget) { - return runtimeTarget.sprite.name; - }); + const names = this.runtime.targets.filter(runtimeTarget => runtimeTarget.isSprite()).map(runtimeTarget => runtimeTarget.sprite.name); sprite.name = StringUtil.unusedName(newName, names); } @@ -274,18 +268,18 @@ VirtualMachine.prototype.renameSprite = function (targetId, newName) { * @param {string} targetId ID of a target whose sprite to delete. */ VirtualMachine.prototype.deleteSprite = function (targetId) { - var target = this.runtime.getTargetById(targetId); + const target = this.runtime.getTargetById(targetId); if (target) { if (!target.isSprite()) { throw new Error('Cannot delete non-sprite targets.'); } - var sprite = target.sprite; + const sprite = target.sprite; if (!sprite) { throw new Error('No sprite associated with this target.'); } - var currentEditingTarget = this.editingTarget; - for (var i = 0; i < sprite.clones.length; i++) { - var clone = sprite.clones[i]; + const currentEditingTarget = this.editingTarget; + for (let i = 0; i < sprite.clones.length; i++) { + const clone = sprite.clones[i]; this.runtime.stopForTarget(sprite.clones[i]); this.runtime.disposeTarget(sprite.clones[i]); // Ensure editing target is switched if we are deleting it. @@ -355,7 +349,7 @@ VirtualMachine.prototype.setEditingTarget = function (targetId) { if (targetId === this.editingTarget.id) { return; } - var target = this.runtime.getTargetById(targetId); + const target = this.runtime.getTargetById(targetId); if (target) { this.editingTarget = target; // Emit appropriate UI updates. @@ -373,12 +367,9 @@ VirtualMachine.prototype.setEditingTarget = function (targetId) { VirtualMachine.prototype.emitTargetsUpdate = function () { this.emit('targetsUpdate', { // [[target id, human readable target name], ...]. - targetList: this.runtime.targets.filter(function (target) { + targetList: this.runtime.targets.filter(target => // Don't report clones. - return !target.hasOwnProperty('isOriginal') || target.isOriginal; - }).map(function (target) { - return target.toJSON(); - }), + !target.hasOwnProperty('isOriginal') || target.isOriginal).map(target => target.toJSON()), // Currently editing target id. editingTarget: this.editingTarget ? this.editingTarget.id : null }); @@ -400,7 +391,7 @@ VirtualMachine.prototype.emitWorkspaceUpdate = function () { * @returns {?string} The target id, if found. Will also be null if the target found is the stage. */ VirtualMachine.prototype.getTargetIdForDrawableId = function (drawableId) { - var target = this.runtime.getTargetByDrawableId(drawableId); + const target = this.runtime.getTargetByDrawableId(drawableId); if (target && target.hasOwnProperty('id') && target.hasOwnProperty('isStage') && !target.isStage) { return target.id; } @@ -413,7 +404,7 @@ VirtualMachine.prototype.getTargetIdForDrawableId = function (drawableId) { * @param {string} targetId The id for the target to put into a drag state */ VirtualMachine.prototype.startDrag = function (targetId) { - var target = this.runtime.getTargetById(targetId); + const target = this.runtime.getTargetById(targetId); if (target) { target.startDrag(); this.setEditingTarget(target.id); @@ -425,7 +416,7 @@ VirtualMachine.prototype.startDrag = function (targetId) { * @param {string} targetId The id for the target to remove from the drag state */ VirtualMachine.prototype.stopDrag = function (targetId) { - var target = this.runtime.getTargetById(targetId); + const target = this.runtime.getTargetById(targetId); if (target) target.stopDrag(); };