Pass with --fix

This commit is contained in:
Ray Schamp 2017-04-17 15:10:04 -04:00
parent f646a61c5b
commit e01c4ae108
41 changed files with 803 additions and 824 deletions

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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();
}

View file

@ -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;
};

View file

@ -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);
};

View file

@ -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);

View file

@ -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));
};

View file

@ -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;
};

View file

@ -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;
}

View file

@ -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);
};

View file

@ -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.<object>} 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.<object>} 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') {

View file

@ -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 = '<xml xmlns="http://www.w3.org/1999/xhtml">';
for (var i = 0; i < this._scripts.length; i++) {
let xmlString = '<xml xmlns="http://www.w3.org/1999/xhtml">';
for (let i = 0; i < this._scripts.length; i++) {
xmlString += this.blockToXML(this._scripts[i]);
}
return xmlString + '</xml>';
return `${xmlString}</xml>`;
};
/**
@ -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 += '<value name="' + blockInput.name + '">';
xmlString += `<value name="${blockInput.name}">`;
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 += '<field name="' + blockField.name + '">' +
value + '</field>';
xmlString += `<field name="${blockField.name}">${
value}</field>`;
}
// Add blocks connected to the next connection.
if (block.next) {
xmlString += '<next>' + this.blockToXML(block.next) + '</next>';
xmlString += `<next>${this.blockToXML(block.next)}</next>`;
}
xmlString += '</' + tagName + '>';
xmlString += `</${tagName}>`;
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 += '</' + mutation.tagName + '>';
mutationString += `</${mutation.tagName}>`;
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;

View file

@ -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);

View file

@ -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;
};

View file

@ -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;

View file

@ -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.<Thread>=} 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;

View file

@ -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 {

View file

@ -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;
};

View file

@ -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;

View file

@ -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;

View file

@ -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;
});

View file

@ -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);
});

View file

@ -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.<object>} 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.<object>} 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"

View file

@ -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: [

View file

@ -1,3 +1,3 @@
var VirtualMachine = require('./virtual-machine');
const VirtualMachine = require('./virtual-machine');
module.exports = VirtualMachine;

View file

@ -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;
};

View file

@ -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.<number>}
@ -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;
};

View file

@ -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',

View file

@ -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';

View file

@ -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.<number>} 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);
}

View file

@ -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) {

View file

@ -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.<number>} [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;
};
/**

View file

@ -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.

View file

@ -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),

View file

@ -1,4 +1,4 @@
var minilog = require('minilog');
const minilog = require('minilog');
minilog.enable();
module.exports = minilog('vm');

View file

@ -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);
};

View file

@ -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;
};

View file

@ -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;
/**

View file

@ -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('');

View file

@ -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 '&lt;';
case '>': return '&gt;';

View file

@ -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();
};