mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2024-12-24 15:02:52 -05:00
Merge pull request #4151 from scratchfoundation/renovate/major-eslint-config-scratch
chore(deps): update eslint-config-scratch (major)
This commit is contained in:
commit
ef86783a79
37 changed files with 3610 additions and 2520 deletions
5645
package-lock.json
generated
5645
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -74,8 +74,8 @@
|
||||||
"callsite": "1.0.0",
|
"callsite": "1.0.0",
|
||||||
"copy-webpack-plugin": "4.5.4",
|
"copy-webpack-plugin": "4.5.4",
|
||||||
"docdash": "1.2.0",
|
"docdash": "1.2.0",
|
||||||
"eslint": "5.3.0",
|
"eslint": "8.55.0",
|
||||||
"eslint-config-scratch": "5.1.0",
|
"eslint-config-scratch": "9.0.3",
|
||||||
"expose-loader": "0.7.5",
|
"expose-loader": "0.7.5",
|
||||||
"file-loader": "2.0.0",
|
"file-loader": "2.0.0",
|
||||||
"format-message-cli": "6.2.0",
|
"format-message-cli": "6.2.0",
|
||||||
|
|
|
@ -540,7 +540,7 @@ class Scratch3LooksBlocks {
|
||||||
changeEffect (args, util) {
|
changeEffect (args, util) {
|
||||||
const effect = Cast.toString(args.EFFECT).toLowerCase();
|
const effect = Cast.toString(args.EFFECT).toLowerCase();
|
||||||
const change = Cast.toNumber(args.CHANGE);
|
const change = Cast.toNumber(args.CHANGE);
|
||||||
if (!util.target.effects.hasOwnProperty(effect)) return;
|
if (!Object.prototype.hasOwnProperty.call(util.target.effects, effect)) return;
|
||||||
let newValue = change + util.target.effects[effect];
|
let newValue = change + util.target.effects[effect];
|
||||||
newValue = this.clampEffect(effect, newValue);
|
newValue = this.clampEffect(effect, newValue);
|
||||||
util.target.setEffect(effect, newValue);
|
util.target.setEffect(effect, newValue);
|
||||||
|
|
|
@ -43,7 +43,7 @@ class Scratch3ProcedureBlocks {
|
||||||
// at earlier stack frames for the values of a given parameter (#1729)
|
// at earlier stack frames for the values of a given parameter (#1729)
|
||||||
util.initParams();
|
util.initParams();
|
||||||
for (let i = 0; i < paramIds.length; i++) {
|
for (let i = 0; i < paramIds.length; i++) {
|
||||||
if (args.hasOwnProperty(paramIds[i])) {
|
if (Object.prototype.hasOwnProperty.call(args, paramIds[i])) {
|
||||||
util.pushParam(paramNames[i], args[paramIds[i]]);
|
util.pushParam(paramNames[i], args[paramIds[i]]);
|
||||||
} else {
|
} else {
|
||||||
util.pushParam(paramNames[i], paramDefaults[i]);
|
util.pushParam(paramNames[i], paramDefaults[i]);
|
||||||
|
|
|
@ -267,7 +267,7 @@ class Scratch3SoundBlocks {
|
||||||
const value = Cast.toNumber(args.VALUE);
|
const value = Cast.toNumber(args.VALUE);
|
||||||
|
|
||||||
const soundState = this._getSoundState(util.target);
|
const soundState = this._getSoundState(util.target);
|
||||||
if (!soundState.effects.hasOwnProperty(effect)) return;
|
if (!Object.prototype.hasOwnProperty.call(soundState.effects, effect)) return;
|
||||||
|
|
||||||
if (change) {
|
if (change) {
|
||||||
soundState.effects[effect] += value;
|
soundState.effects[effect] += value;
|
||||||
|
@ -297,7 +297,7 @@ class Scratch3SoundBlocks {
|
||||||
_clearEffectsForTarget (target) {
|
_clearEffectsForTarget (target) {
|
||||||
const soundState = this._getSoundState(target);
|
const soundState = this._getSoundState(target);
|
||||||
for (const effect in soundState.effects) {
|
for (const effect in soundState.effects) {
|
||||||
if (!soundState.effects.hasOwnProperty(effect)) continue;
|
if (!Object.prototype.hasOwnProperty.call(soundState.effects, effect)) continue;
|
||||||
soundState.effects[effect] = 0;
|
soundState.effects[effect] = 0;
|
||||||
}
|
}
|
||||||
this._syncEffectsForTarget(target);
|
this._syncEffectsForTarget(target);
|
||||||
|
|
|
@ -50,6 +50,8 @@ class CentralDispatch extends SharedDispatch {
|
||||||
throw new Error(`Cannot use 'callSync' on remote provider for service ${service}.`);
|
throw new Error(`Cannot use 'callSync' on remote provider for service ${service}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: verify correct `this` after switching from apply to spread
|
||||||
|
// eslint-disable-next-line prefer-spread
|
||||||
return provider[method].apply(provider, args);
|
return provider[method].apply(provider, args);
|
||||||
}
|
}
|
||||||
throw new Error(`Provider not found for service: ${service}`);
|
throw new Error(`Provider not found for service: ${service}`);
|
||||||
|
@ -62,7 +64,7 @@ class CentralDispatch extends SharedDispatch {
|
||||||
* @param {object} provider - a local object which provides this service.
|
* @param {object} provider - a local object which provides this service.
|
||||||
*/
|
*/
|
||||||
setServiceSync (service, provider) {
|
setServiceSync (service, provider) {
|
||||||
if (this.services.hasOwnProperty(service)) {
|
if (Object.prototype.hasOwnProperty.call(this.services, service)) {
|
||||||
log.warn(`Central dispatch replacing existing service provider for ${service}`);
|
log.warn(`Central dispatch replacing existing service provider for ${service}`);
|
||||||
}
|
}
|
||||||
this.services[service] = provider;
|
this.services[service] = provider;
|
||||||
|
|
|
@ -82,6 +82,8 @@ class SharedDispatch {
|
||||||
return this._remoteTransferCall(provider, service, method, transfer, ...args);
|
return this._remoteTransferCall(provider, service, method, transfer, ...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: verify correct `this` after switching from apply to spread
|
||||||
|
// eslint-disable-next-line prefer-spread
|
||||||
const result = provider[method].apply(provider, args);
|
const result = provider[method].apply(provider, args);
|
||||||
return Promise.resolve(result);
|
return Promise.resolve(result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ class WorkerDispatch extends SharedDispatch {
|
||||||
* @returns {Promise} - a promise which will resolve once the service is registered.
|
* @returns {Promise} - a promise which will resolve once the service is registered.
|
||||||
*/
|
*/
|
||||||
setService (service, provider) {
|
setService (service, provider) {
|
||||||
if (this.services.hasOwnProperty(service)) {
|
if (Object.prototype.hasOwnProperty.call(this.services, service)) {
|
||||||
log.warn(`Worker dispatch replacing existing service provider for ${service}`);
|
log.warn(`Worker dispatch replacing existing service provider for ${service}`);
|
||||||
}
|
}
|
||||||
this.services[service] = provider;
|
this.services[service] = provider;
|
||||||
|
|
|
@ -153,7 +153,7 @@ const domToBlocks = function (blocksDOM) {
|
||||||
// Flatten blocks object into a list.
|
// Flatten blocks object into a list.
|
||||||
const blocksList = [];
|
const blocksList = [];
|
||||||
for (const b in blocks) {
|
for (const b in blocks) {
|
||||||
if (!blocks.hasOwnProperty(b)) continue;
|
if (!Object.prototype.hasOwnProperty.call(blocks, b)) continue;
|
||||||
blocksList.push(blocks[b]);
|
blocksList.push(blocks[b]);
|
||||||
}
|
}
|
||||||
return blocksList;
|
return blocksList;
|
||||||
|
|
|
@ -232,6 +232,8 @@ class BlockUtility {
|
||||||
this.sequencer.runtime.ioDevices[device] &&
|
this.sequencer.runtime.ioDevices[device] &&
|
||||||
this.sequencer.runtime.ioDevices[device][func]) {
|
this.sequencer.runtime.ioDevices[device][func]) {
|
||||||
const devObject = this.sequencer.runtime.ioDevices[device];
|
const devObject = this.sequencer.runtime.ioDevices[device];
|
||||||
|
// TODO: verify correct `this` after switching from apply to spread
|
||||||
|
// eslint-disable-next-line prefer-spread
|
||||||
return devObject[func].apply(devObject, args);
|
return devObject[func].apply(devObject, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ class RuntimeScriptCache {
|
||||||
if (Object.keys(fields).length === 0) {
|
if (Object.keys(fields).length === 0) {
|
||||||
const inputs = container.getInputs(block);
|
const inputs = container.getInputs(block);
|
||||||
for (const input in inputs) {
|
for (const input in inputs) {
|
||||||
if (!inputs.hasOwnProperty(input)) continue;
|
if (!Object.prototype.hasOwnProperty.call(inputs, input)) continue;
|
||||||
const id = inputs[input].block;
|
const id = inputs[input].block;
|
||||||
const inputBlock = container.getBlock(id);
|
const inputBlock = container.getBlock(id);
|
||||||
const inputFields = container.getFields(inputBlock);
|
const inputFields = container.getFields(inputBlock);
|
||||||
|
|
|
@ -231,7 +231,7 @@ class Blocks {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const id in this._blocks) {
|
for (const id in this._blocks) {
|
||||||
if (!this._blocks.hasOwnProperty(id)) continue;
|
if (!Object.prototype.hasOwnProperty.call(this._blocks, id)) continue;
|
||||||
const block = this._blocks[id];
|
const block = this._blocks[id];
|
||||||
if (block.opcode === 'procedures_definition') {
|
if (block.opcode === 'procedures_definition') {
|
||||||
const internal = this._getCustomBlockInternal(block);
|
const internal = this._getCustomBlockInternal(block);
|
||||||
|
@ -267,7 +267,7 @@ class Blocks {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const id in this._blocks) {
|
for (const id in this._blocks) {
|
||||||
if (!this._blocks.hasOwnProperty(id)) continue;
|
if (!Object.prototype.hasOwnProperty.call(this._blocks, id)) continue;
|
||||||
const block = this._blocks[id];
|
const block = this._blocks[id];
|
||||||
if (block.opcode === 'procedures_prototype' &&
|
if (block.opcode === 'procedures_prototype' &&
|
||||||
block.mutation.proccode === name) {
|
block.mutation.proccode === name) {
|
||||||
|
@ -357,7 +357,7 @@ class Blocks {
|
||||||
case 'delete':
|
case 'delete':
|
||||||
// Don't accept delete events for missing blocks,
|
// Don't accept delete events for missing blocks,
|
||||||
// or shadow blocks being obscured.
|
// or shadow blocks being obscured.
|
||||||
if (!this._blocks.hasOwnProperty(e.blockId) ||
|
if (!Object.prototype.hasOwnProperty.call(this._blocks, e.blockId) ||
|
||||||
this._blocks[e.blockId].shadow) {
|
this._blocks[e.blockId].shadow) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -397,7 +397,7 @@ class Blocks {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'var_rename':
|
case 'var_rename':
|
||||||
if (editingTarget && editingTarget.variables.hasOwnProperty(e.varId)) {
|
if (editingTarget && Object.prototype.hasOwnProperty.call(editingTarget.variables, e.varId)) {
|
||||||
// This is a local variable, rename on the current target
|
// This is a local variable, rename on the current target
|
||||||
editingTarget.renameVariable(e.varId, e.newName);
|
editingTarget.renameVariable(e.varId, e.newName);
|
||||||
// Update all the blocks on the current target that use
|
// Update all the blocks on the current target that use
|
||||||
|
@ -416,7 +416,7 @@ class Blocks {
|
||||||
this.emitProjectChanged();
|
this.emitProjectChanged();
|
||||||
break;
|
break;
|
||||||
case 'var_delete': {
|
case 'var_delete': {
|
||||||
const target = (editingTarget && editingTarget.variables.hasOwnProperty(e.varId)) ?
|
const target = (editingTarget && Object.prototype.hasOwnProperty.call(editingTarget.variables, e.varId)) ?
|
||||||
editingTarget : stage;
|
editingTarget : stage;
|
||||||
target.deleteVariable(e.varId);
|
target.deleteVariable(e.varId);
|
||||||
this.emitProjectChanged();
|
this.emitProjectChanged();
|
||||||
|
@ -445,20 +445,21 @@ class Blocks {
|
||||||
case 'comment_change':
|
case 'comment_change':
|
||||||
if (this.runtime.getEditingTarget()) {
|
if (this.runtime.getEditingTarget()) {
|
||||||
const currTarget = this.runtime.getEditingTarget();
|
const currTarget = this.runtime.getEditingTarget();
|
||||||
if (!currTarget.comments.hasOwnProperty(e.commentId)) {
|
if (!Object.prototype.hasOwnProperty.call(currTarget.comments, e.commentId)) {
|
||||||
log.warn(`Cannot change comment with id ${e.commentId} because it does not exist.`);
|
log.warn(`Cannot change comment with id ${e.commentId} because it does not exist.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const comment = currTarget.comments[e.commentId];
|
const comment = currTarget.comments[e.commentId];
|
||||||
const change = e.newContents_;
|
const change = e.newContents_;
|
||||||
if (change.hasOwnProperty('minimized')) {
|
if (Object.prototype.hasOwnProperty.call(change, 'minimized')) {
|
||||||
comment.minimized = change.minimized;
|
comment.minimized = change.minimized;
|
||||||
}
|
}
|
||||||
if (change.hasOwnProperty('width') && change.hasOwnProperty('height')){
|
if (Object.prototype.hasOwnProperty.call(change, 'width') &&
|
||||||
|
Object.prototype.hasOwnProperty.call(change, 'height')) {
|
||||||
comment.width = change.width;
|
comment.width = change.width;
|
||||||
comment.height = change.height;
|
comment.height = change.height;
|
||||||
}
|
}
|
||||||
if (change.hasOwnProperty('text')) {
|
if (Object.prototype.hasOwnProperty.call(change, 'text')) {
|
||||||
comment.text = change.text;
|
comment.text = change.text;
|
||||||
}
|
}
|
||||||
this.emitProjectChanged();
|
this.emitProjectChanged();
|
||||||
|
@ -467,7 +468,7 @@ class Blocks {
|
||||||
case 'comment_move':
|
case 'comment_move':
|
||||||
if (this.runtime.getEditingTarget()) {
|
if (this.runtime.getEditingTarget()) {
|
||||||
const currTarget = this.runtime.getEditingTarget();
|
const currTarget = this.runtime.getEditingTarget();
|
||||||
if (currTarget && !currTarget.comments.hasOwnProperty(e.commentId)) {
|
if (currTarget && !Object.prototype.hasOwnProperty.call(currTarget.comments, e.commentId)) {
|
||||||
log.warn(`Cannot change comment with id ${e.commentId} because it does not exist.`);
|
log.warn(`Cannot change comment with id ${e.commentId} because it does not exist.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -482,7 +483,7 @@ class Blocks {
|
||||||
case 'comment_delete':
|
case 'comment_delete':
|
||||||
if (this.runtime.getEditingTarget()) {
|
if (this.runtime.getEditingTarget()) {
|
||||||
const currTarget = this.runtime.getEditingTarget();
|
const currTarget = this.runtime.getEditingTarget();
|
||||||
if (!currTarget.comments.hasOwnProperty(e.commentId)) {
|
if (!Object.prototype.hasOwnProperty.call(currTarget.comments, e.commentId)) {
|
||||||
// If we're in this state, we have probably received
|
// If we're in this state, we have probably received
|
||||||
// a delete event from a workspace that we switched from
|
// a delete event from a workspace that we switched from
|
||||||
// (e.g. a delete event for a comment on sprite a's workspace
|
// (e.g. a delete event for a comment on sprite a's workspace
|
||||||
|
@ -536,7 +537,7 @@ class Blocks {
|
||||||
createBlock (block) {
|
createBlock (block) {
|
||||||
// Does the block already exist?
|
// Does the block already exist?
|
||||||
// Could happen, e.g., for an unobscured shadow.
|
// Could happen, e.g., for an unobscured shadow.
|
||||||
if (this._blocks.hasOwnProperty(block.id)) {
|
if (Object.prototype.hasOwnProperty.call(this._blocks, block.id)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Create new block.
|
// Create new block.
|
||||||
|
@ -650,7 +651,7 @@ class Blocks {
|
||||||
}
|
}
|
||||||
|
|
||||||
const isSpriteSpecific = isSpriteLocalVariable ||
|
const isSpriteSpecific = isSpriteLocalVariable ||
|
||||||
(this.runtime.monitorBlockInfo.hasOwnProperty(block.opcode) &&
|
(Object.prototype.hasOwnProperty.call(this.runtime.monitorBlockInfo, block.opcode) &&
|
||||||
this.runtime.monitorBlockInfo[block.opcode].isSpriteSpecific);
|
this.runtime.monitorBlockInfo[block.opcode].isSpriteSpecific);
|
||||||
if (isSpriteSpecific) {
|
if (isSpriteSpecific) {
|
||||||
// If creating a new sprite specific monitor, the only possible target is
|
// If creating a new sprite specific monitor, the only possible target is
|
||||||
|
@ -692,7 +693,7 @@ class Blocks {
|
||||||
* @param {!object} e Blockly move event to be processed
|
* @param {!object} e Blockly move event to be processed
|
||||||
*/
|
*/
|
||||||
moveBlock (e) {
|
moveBlock (e) {
|
||||||
if (!this._blocks.hasOwnProperty(e.id)) {
|
if (!Object.prototype.hasOwnProperty.call(this._blocks, e.id)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -740,7 +741,7 @@ class Blocks {
|
||||||
// Moved to the new parent's input.
|
// Moved to the new parent's input.
|
||||||
// Don't obscure the shadow block.
|
// Don't obscure the shadow block.
|
||||||
let oldShadow = null;
|
let oldShadow = null;
|
||||||
if (this._blocks[e.newParent].inputs.hasOwnProperty(e.newInput)) {
|
if (Object.prototype.hasOwnProperty.call(this._blocks[e.newParent].inputs, e.newInput)) {
|
||||||
oldShadow = this._blocks[e.newParent].inputs[e.newInput].shadow;
|
oldShadow = this._blocks[e.newParent].inputs[e.newInput].shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -990,7 +991,7 @@ class Blocks {
|
||||||
*/
|
*/
|
||||||
_getCostumeField (blockId) {
|
_getCostumeField (blockId) {
|
||||||
const block = this.getBlock(blockId);
|
const block = this.getBlock(blockId);
|
||||||
if (block && block.fields.hasOwnProperty('COSTUME')) {
|
if (block && Object.prototype.hasOwnProperty.call(block.fields, 'COSTUME')) {
|
||||||
return block.fields.COSTUME;
|
return block.fields.COSTUME;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -1005,7 +1006,7 @@ class Blocks {
|
||||||
*/
|
*/
|
||||||
_getSoundField (blockId) {
|
_getSoundField (blockId) {
|
||||||
const block = this.getBlock(blockId);
|
const block = this.getBlock(blockId);
|
||||||
if (block && block.fields.hasOwnProperty('SOUND_MENU')) {
|
if (block && Object.prototype.hasOwnProperty.call(block.fields, 'SOUND_MENU')) {
|
||||||
return block.fields.SOUND_MENU;
|
return block.fields.SOUND_MENU;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -1020,7 +1021,7 @@ class Blocks {
|
||||||
*/
|
*/
|
||||||
_getBackdropField (blockId) {
|
_getBackdropField (blockId) {
|
||||||
const block = this.getBlock(blockId);
|
const block = this.getBlock(blockId);
|
||||||
if (block && block.fields.hasOwnProperty('BACKDROP')) {
|
if (block && Object.prototype.hasOwnProperty.call(block.fields, 'BACKDROP')) {
|
||||||
return block.fields.BACKDROP;
|
return block.fields.BACKDROP;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -1042,7 +1043,7 @@ class Blocks {
|
||||||
'DISTANCETOMENU', 'TOUCHINGOBJECTMENU', 'CLONE_OPTION'];
|
'DISTANCETOMENU', 'TOUCHINGOBJECTMENU', 'CLONE_OPTION'];
|
||||||
for (let i = 0; i < spriteMenuNames.length; i++) {
|
for (let i = 0; i < spriteMenuNames.length; i++) {
|
||||||
const menuName = spriteMenuNames[i];
|
const menuName = spriteMenuNames[i];
|
||||||
if (block.fields.hasOwnProperty(menuName)) {
|
if (Object.prototype.hasOwnProperty.call(block.fields, menuName)) {
|
||||||
return block.fields[menuName];
|
return block.fields[menuName];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1085,7 +1086,7 @@ class Blocks {
|
||||||
const commentId = block.comment;
|
const commentId = block.comment;
|
||||||
if (commentId) {
|
if (commentId) {
|
||||||
if (comments) {
|
if (comments) {
|
||||||
if (comments.hasOwnProperty(commentId)) {
|
if (Object.prototype.hasOwnProperty.call(comments, commentId)) {
|
||||||
xmlString += comments[commentId].toXML();
|
xmlString += comments[commentId].toXML();
|
||||||
} else {
|
} else {
|
||||||
log.warn(`Could not find comment with id: ${commentId} in provided comment descriptions.`);
|
log.warn(`Could not find comment with id: ${commentId} in provided comment descriptions.`);
|
||||||
|
@ -1100,7 +1101,7 @@ class Blocks {
|
||||||
}
|
}
|
||||||
// Add any inputs on this block.
|
// Add any inputs on this block.
|
||||||
for (const input in block.inputs) {
|
for (const input in block.inputs) {
|
||||||
if (!block.inputs.hasOwnProperty(input)) continue;
|
if (!Object.prototype.hasOwnProperty.call(block.inputs, input)) continue;
|
||||||
const blockInput = block.inputs[input];
|
const blockInput = block.inputs[input];
|
||||||
// Only encode a value tag if the value input is occupied.
|
// Only encode a value tag if the value input is occupied.
|
||||||
if (blockInput.block || blockInput.shadow) {
|
if (blockInput.block || blockInput.shadow) {
|
||||||
|
@ -1117,7 +1118,7 @@ class Blocks {
|
||||||
}
|
}
|
||||||
// Add any fields on this block.
|
// Add any fields on this block.
|
||||||
for (const field in block.fields) {
|
for (const field in block.fields) {
|
||||||
if (!block.fields.hasOwnProperty(field)) continue;
|
if (!Object.prototype.hasOwnProperty.call(block.fields, field)) continue;
|
||||||
const blockField = block.fields[field];
|
const blockField = block.fields[field];
|
||||||
xmlString += `<field name="${blockField.name}"`;
|
xmlString += `<field name="${blockField.name}"`;
|
||||||
const fieldId = blockField.id;
|
const fieldId = blockField.id;
|
||||||
|
|
|
@ -764,14 +764,14 @@ class Runtime extends EventEmitter {
|
||||||
*/
|
*/
|
||||||
_registerBlockPackages () {
|
_registerBlockPackages () {
|
||||||
for (const packageName in defaultBlockPackages) {
|
for (const packageName in defaultBlockPackages) {
|
||||||
if (defaultBlockPackages.hasOwnProperty(packageName)) {
|
if (Object.prototype.hasOwnProperty.call(defaultBlockPackages, packageName)) {
|
||||||
// @todo pass a different runtime depending on package privilege?
|
// @todo pass a different runtime depending on package privilege?
|
||||||
const packageObject = new (defaultBlockPackages[packageName])(this);
|
const packageObject = new (defaultBlockPackages[packageName])(this);
|
||||||
// Collect primitives from package.
|
// Collect primitives from package.
|
||||||
if (packageObject.getPrimitives) {
|
if (packageObject.getPrimitives) {
|
||||||
const packagePrimitives = packageObject.getPrimitives();
|
const packagePrimitives = packageObject.getPrimitives();
|
||||||
for (const op in packagePrimitives) {
|
for (const op in packagePrimitives) {
|
||||||
if (packagePrimitives.hasOwnProperty(op)) {
|
if (Object.prototype.hasOwnProperty.call(packagePrimitives, op)) {
|
||||||
this._primitives[op] =
|
this._primitives[op] =
|
||||||
packagePrimitives[op].bind(packageObject);
|
packagePrimitives[op].bind(packageObject);
|
||||||
}
|
}
|
||||||
|
@ -781,7 +781,7 @@ class Runtime extends EventEmitter {
|
||||||
if (packageObject.getHats) {
|
if (packageObject.getHats) {
|
||||||
const packageHats = packageObject.getHats();
|
const packageHats = packageObject.getHats();
|
||||||
for (const hatName in packageHats) {
|
for (const hatName in packageHats) {
|
||||||
if (packageHats.hasOwnProperty(hatName)) {
|
if (Object.prototype.hasOwnProperty.call(packageHats, hatName)) {
|
||||||
this._hats[hatName] = packageHats[hatName];
|
this._hats[hatName] = packageHats[hatName];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -851,7 +851,7 @@ class Runtime extends EventEmitter {
|
||||||
this._fillExtensionCategory(categoryInfo, extensionInfo);
|
this._fillExtensionCategory(categoryInfo, extensionInfo);
|
||||||
|
|
||||||
for (const fieldTypeName in categoryInfo.customFieldTypes) {
|
for (const fieldTypeName in categoryInfo.customFieldTypes) {
|
||||||
if (extensionInfo.customFieldTypes.hasOwnProperty(fieldTypeName)) {
|
if (Object.prototype.hasOwnProperty.call(extensionInfo.customFieldTypes, fieldTypeName)) {
|
||||||
const fieldTypeInfo = categoryInfo.customFieldTypes[fieldTypeName];
|
const fieldTypeInfo = categoryInfo.customFieldTypes[fieldTypeName];
|
||||||
|
|
||||||
// Emit events for custom field types from extension
|
// Emit events for custom field types from extension
|
||||||
|
@ -894,7 +894,7 @@ class Runtime extends EventEmitter {
|
||||||
categoryInfo.menuInfo = {};
|
categoryInfo.menuInfo = {};
|
||||||
|
|
||||||
for (const menuName in extensionInfo.menus) {
|
for (const menuName in extensionInfo.menus) {
|
||||||
if (extensionInfo.menus.hasOwnProperty(menuName)) {
|
if (Object.prototype.hasOwnProperty.call(extensionInfo.menus, menuName)) {
|
||||||
const menuInfo = extensionInfo.menus[menuName];
|
const menuInfo = extensionInfo.menus[menuName];
|
||||||
const convertedMenu = this._buildMenuForScratchBlocks(menuName, menuInfo, categoryInfo);
|
const convertedMenu = this._buildMenuForScratchBlocks(menuName, menuInfo, categoryInfo);
|
||||||
categoryInfo.menus.push(convertedMenu);
|
categoryInfo.menus.push(convertedMenu);
|
||||||
|
@ -902,7 +902,7 @@ class Runtime extends EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const fieldTypeName in extensionInfo.customFieldTypes) {
|
for (const fieldTypeName in extensionInfo.customFieldTypes) {
|
||||||
if (extensionInfo.customFieldTypes.hasOwnProperty(fieldTypeName)) {
|
if (Object.prototype.hasOwnProperty.call(extensionInfo.customFieldTypes, fieldTypeName)) {
|
||||||
const fieldType = extensionInfo.customFieldTypes[fieldTypeName];
|
const fieldType = extensionInfo.customFieldTypes[fieldTypeName];
|
||||||
const fieldTypeInfo = this._buildCustomFieldInfo(
|
const fieldTypeInfo = this._buildCustomFieldInfo(
|
||||||
fieldTypeName,
|
fieldTypeName,
|
||||||
|
@ -1138,7 +1138,7 @@ class Runtime extends EventEmitter {
|
||||||
break;
|
break;
|
||||||
case BlockType.HAT:
|
case BlockType.HAT:
|
||||||
case BlockType.EVENT:
|
case BlockType.EVENT:
|
||||||
if (!blockInfo.hasOwnProperty('isEdgeActivated')) {
|
if (!Object.prototype.hasOwnProperty.call(blockInfo, 'isEdgeActivated')) {
|
||||||
// if absent, this property defaults to true
|
// if absent, this property defaults to true
|
||||||
blockInfo.isEdgeActivated = true;
|
blockInfo.isEdgeActivated = true;
|
||||||
}
|
}
|
||||||
|
@ -1584,7 +1584,7 @@ class Runtime extends EventEmitter {
|
||||||
* @return {boolean} True if the op is known to be a hat.
|
* @return {boolean} True if the op is known to be a hat.
|
||||||
*/
|
*/
|
||||||
getIsHat (opcode) {
|
getIsHat (opcode) {
|
||||||
return this._hats.hasOwnProperty(opcode);
|
return Object.prototype.hasOwnProperty.call(this._hats, opcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1593,7 +1593,7 @@ class Runtime extends EventEmitter {
|
||||||
* @return {boolean} True if the op is known to be a edge-activated hat.
|
* @return {boolean} True if the op is known to be a edge-activated hat.
|
||||||
*/
|
*/
|
||||||
getIsEdgeActivatedHat (opcode) {
|
getIsEdgeActivatedHat (opcode) {
|
||||||
return this._hats.hasOwnProperty(opcode) &&
|
return Object.prototype.hasOwnProperty.call(this._hats, opcode) &&
|
||||||
this._hats[opcode].edgeActivated;
|
this._hats[opcode].edgeActivated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1817,7 +1817,7 @@ class Runtime extends EventEmitter {
|
||||||
*/
|
*/
|
||||||
startHats (requestedHatOpcode,
|
startHats (requestedHatOpcode,
|
||||||
optMatchFields, optTarget) {
|
optMatchFields, optTarget) {
|
||||||
if (!this._hats.hasOwnProperty(requestedHatOpcode)) {
|
if (!Object.prototype.hasOwnProperty.call(this._hats, requestedHatOpcode)) {
|
||||||
// No known hat with this opcode.
|
// No known hat with this opcode.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1827,7 +1827,7 @@ class Runtime extends EventEmitter {
|
||||||
const hatMeta = instance._hats[requestedHatOpcode];
|
const hatMeta = instance._hats[requestedHatOpcode];
|
||||||
|
|
||||||
for (const opts in optMatchFields) {
|
for (const opts in optMatchFields) {
|
||||||
if (!optMatchFields.hasOwnProperty(opts)) continue;
|
if (!Object.prototype.hasOwnProperty.call(optMatchFields, opts)) continue;
|
||||||
optMatchFields[opts] = optMatchFields[opts].toUpperCase();
|
optMatchFields[opts] = optMatchFields[opts].toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2062,7 +2062,7 @@ class Runtime extends EventEmitter {
|
||||||
const newTargets = [];
|
const newTargets = [];
|
||||||
for (let i = 0; i < this.targets.length; i++) {
|
for (let i = 0; i < this.targets.length; i++) {
|
||||||
this.targets[i].onStopAll();
|
this.targets[i].onStopAll();
|
||||||
if (this.targets[i].hasOwnProperty('isOriginal') &&
|
if (Object.prototype.hasOwnProperty.call(this.targets[i], 'isOriginal') &&
|
||||||
!this.targets[i].isOriginal) {
|
!this.targets[i].isOriginal) {
|
||||||
this.targets[i].dispose();
|
this.targets[i].dispose();
|
||||||
} else {
|
} else {
|
||||||
|
@ -2097,7 +2097,7 @@ class Runtime extends EventEmitter {
|
||||||
|
|
||||||
// Find all edge-activated hats, and add them to threads to be evaluated.
|
// Find all edge-activated hats, and add them to threads to be evaluated.
|
||||||
for (const hatType in this._hats) {
|
for (const hatType in this._hats) {
|
||||||
if (!this._hats.hasOwnProperty(hatType)) continue;
|
if (!Object.prototype.hasOwnProperty.call(this._hats, hatType)) continue;
|
||||||
const hat = this._hats[hatType];
|
const hat = this._hats[hatType];
|
||||||
if (hat.edgeActivated) {
|
if (hat.edgeActivated) {
|
||||||
this.startHats(hatType);
|
this.startHats(hatType);
|
||||||
|
@ -2211,9 +2211,9 @@ class Runtime extends EventEmitter {
|
||||||
*/
|
*/
|
||||||
_updateGlows (optExtraThreads) {
|
_updateGlows (optExtraThreads) {
|
||||||
const searchThreads = [];
|
const searchThreads = [];
|
||||||
searchThreads.push.apply(searchThreads, this.threads);
|
searchThreads.push(...this.threads);
|
||||||
if (optExtraThreads) {
|
if (optExtraThreads) {
|
||||||
searchThreads.push.apply(searchThreads, optExtraThreads);
|
searchThreads.push(...optExtraThreads);
|
||||||
}
|
}
|
||||||
// Set of scripts that request a glow this frame.
|
// Set of scripts that request a glow this frame.
|
||||||
const requestedGlowsThisFrame = [];
|
const requestedGlowsThisFrame = [];
|
||||||
|
|
|
@ -101,7 +101,7 @@ class Target extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
hasEdgeActivatedValue (blockId) {
|
hasEdgeActivatedValue (blockId) {
|
||||||
return this._edgeActivatedHatValues.hasOwnProperty(blockId);
|
return Object.prototype.hasOwnProperty.call(this._edgeActivatedHatValues, blockId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -186,13 +186,13 @@ class Target extends EventEmitter {
|
||||||
*/
|
*/
|
||||||
lookupVariableById (id) {
|
lookupVariableById (id) {
|
||||||
// If we have a local copy, return it.
|
// If we have a local copy, return it.
|
||||||
if (this.variables.hasOwnProperty(id)) {
|
if (Object.prototype.hasOwnProperty.call(this.variables, id)) {
|
||||||
return this.variables[id];
|
return this.variables[id];
|
||||||
}
|
}
|
||||||
// If the stage has a global copy, return it.
|
// If the stage has a global copy, return it.
|
||||||
if (this.runtime && !this.isStage) {
|
if (this.runtime && !this.isStage) {
|
||||||
const stage = this.runtime.getTargetForStage();
|
const stage = this.runtime.getTargetForStage();
|
||||||
if (stage && stage.variables.hasOwnProperty(id)) {
|
if (stage && Object.prototype.hasOwnProperty.call(stage.variables, id)) {
|
||||||
return stage.variables[id];
|
return stage.variables[id];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,7 +264,7 @@ class Target extends EventEmitter {
|
||||||
* Additional checks are made that the variable can be created as a cloud variable.
|
* Additional checks are made that the variable can be created as a cloud variable.
|
||||||
*/
|
*/
|
||||||
createVariable (id, name, type, isCloud) {
|
createVariable (id, name, type, isCloud) {
|
||||||
if (!this.variables.hasOwnProperty(id)) {
|
if (!Object.prototype.hasOwnProperty.call(this.variables, id)) {
|
||||||
const newVariable = new Variable(id, name, type, false);
|
const newVariable = new Variable(id, name, type, false);
|
||||||
if (isCloud && this.isStage && this.runtime.canAddCloudVariable()) {
|
if (isCloud && this.isStage && this.runtime.canAddCloudVariable()) {
|
||||||
newVariable.isCloud = true;
|
newVariable.isCloud = true;
|
||||||
|
@ -288,7 +288,7 @@ class Target extends EventEmitter {
|
||||||
* @param {boolean} minimized Whether the comment is minimized.
|
* @param {boolean} minimized Whether the comment is minimized.
|
||||||
*/
|
*/
|
||||||
createComment (id, blockId, text, x, y, width, height, minimized) {
|
createComment (id, blockId, text, x, y, width, height, minimized) {
|
||||||
if (!this.comments.hasOwnProperty(id)) {
|
if (!Object.prototype.hasOwnProperty.call(this.comments, id)) {
|
||||||
const newComment = new Comment(id, text, x, y,
|
const newComment = new Comment(id, text, x, y,
|
||||||
width, height, minimized);
|
width, height, minimized);
|
||||||
if (blockId) {
|
if (blockId) {
|
||||||
|
@ -311,7 +311,7 @@ class Target extends EventEmitter {
|
||||||
* @param {string} newName New name for the variable.
|
* @param {string} newName New name for the variable.
|
||||||
*/
|
*/
|
||||||
renameVariable (id, newName) {
|
renameVariable (id, newName) {
|
||||||
if (this.variables.hasOwnProperty(id)) {
|
if (Object.prototype.hasOwnProperty.call(this.variables, id)) {
|
||||||
const variable = this.variables[id];
|
const variable = this.variables[id];
|
||||||
if (variable.id === id) {
|
if (variable.id === id) {
|
||||||
const oldName = variable.name;
|
const oldName = variable.name;
|
||||||
|
@ -362,7 +362,7 @@ class Target extends EventEmitter {
|
||||||
* @param {string} id Id of variable to delete.
|
* @param {string} id Id of variable to delete.
|
||||||
*/
|
*/
|
||||||
deleteVariable (id) {
|
deleteVariable (id) {
|
||||||
if (this.variables.hasOwnProperty(id)) {
|
if (Object.prototype.hasOwnProperty.call(this.variables, id)) {
|
||||||
// Get info about the variable before deleting it
|
// Get info about the variable before deleting it
|
||||||
const deletedVariableName = this.variables[id].name;
|
const deletedVariableName = this.variables[id].name;
|
||||||
const deletedVariableWasCloud = this.variables[id].isCloud;
|
const deletedVariableWasCloud = this.variables[id].isCloud;
|
||||||
|
@ -408,7 +408,7 @@ class Target extends EventEmitter {
|
||||||
* the original variable was not found.
|
* the original variable was not found.
|
||||||
*/
|
*/
|
||||||
duplicateVariable (id, optKeepOriginalId) {
|
duplicateVariable (id, optKeepOriginalId) {
|
||||||
if (this.variables.hasOwnProperty(id)) {
|
if (Object.prototype.hasOwnProperty.call(this.variables, id)) {
|
||||||
const originalVariable = this.variables[id];
|
const originalVariable = this.variables[id];
|
||||||
const newVariable = new Variable(
|
const newVariable = new Variable(
|
||||||
optKeepOriginalId ? id : null, // conditionally keep original id or generate a new one
|
optKeepOriginalId ? id : null, // conditionally keep original id or generate a new one
|
||||||
|
@ -695,7 +695,7 @@ class Target extends EventEmitter {
|
||||||
const unreferencedLocalVarIds = [];
|
const unreferencedLocalVarIds = [];
|
||||||
if (Object.keys(this.variables).length > 0) {
|
if (Object.keys(this.variables).length > 0) {
|
||||||
for (const localVarId in this.variables) {
|
for (const localVarId in this.variables) {
|
||||||
if (!this.variables.hasOwnProperty(localVarId)) continue;
|
if (!Object.prototype.hasOwnProperty.call(this.variables, localVarId)) continue;
|
||||||
if (!allReferences[localVarId]) unreferencedLocalVarIds.push(localVarId);
|
if (!allReferences[localVarId]) unreferencedLocalVarIds.push(localVarId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -720,7 +720,7 @@ class Target extends EventEmitter {
|
||||||
if (this.lookupVariableById(varId)) {
|
if (this.lookupVariableById(varId)) {
|
||||||
// Found a variable with the id in either the target or the stage,
|
// Found a variable with the id in either the target or the stage,
|
||||||
// figure out which one.
|
// figure out which one.
|
||||||
if (this.variables.hasOwnProperty(varId)) {
|
if (Object.prototype.hasOwnProperty.call(this.variables, varId)) {
|
||||||
// If the target has the variable, then check whether the stage
|
// If the target has the variable, then check whether the stage
|
||||||
// has one with the same name and type. If it does, then rename
|
// has one with the same name and type. If it does, then rename
|
||||||
// this target specific variable so that there is a distinction.
|
// this target specific variable so that there is a distinction.
|
||||||
|
|
|
@ -353,7 +353,7 @@ class Thread {
|
||||||
if (frame.params === null) {
|
if (frame.params === null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (frame.params.hasOwnProperty(paramName)) {
|
if (Object.prototype.hasOwnProperty.call(frame.params, paramName)) {
|
||||||
return frame.params[paramName];
|
return frame.params[paramName];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -116,7 +116,7 @@ class ExtensionManager {
|
||||||
* @param {string} extensionId - the ID of an internal extension
|
* @param {string} extensionId - the ID of an internal extension
|
||||||
*/
|
*/
|
||||||
loadExtensionIdSync (extensionId) {
|
loadExtensionIdSync (extensionId) {
|
||||||
if (!builtinExtensions.hasOwnProperty(extensionId)) {
|
if (!Object.prototype.hasOwnProperty.call(builtinExtensions, extensionId)) {
|
||||||
log.warn(`Could not find extension ${extensionId} in the built in extensions.`);
|
log.warn(`Could not find extension ${extensionId} in the built in extensions.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ class ExtensionManager {
|
||||||
* @returns {Promise} resolved once the extension is loaded and initialized or rejected on failure
|
* @returns {Promise} resolved once the extension is loaded and initialized or rejected on failure
|
||||||
*/
|
*/
|
||||||
loadExtensionURL (extensionURL) {
|
loadExtensionURL (extensionURL) {
|
||||||
if (builtinExtensions.hasOwnProperty(extensionURL)) {
|
if (Object.prototype.hasOwnProperty.call(builtinExtensions, extensionURL)) {
|
||||||
/** @TODO dupe handling for non-builtin extensions. See commit 670e51d33580e8a2e852b3b038bb3afc282f81b9 */
|
/** @TODO dupe handling for non-builtin extensions. See commit 670e51d33580e8a2e852b3b038bb3afc282f81b9 */
|
||||||
if (this.isExtensionLoaded(extensionURL)) {
|
if (this.isExtensionLoaded(extensionURL)) {
|
||||||
const message = `Rejecting attempt to load a second extension with ID ${extensionURL}`;
|
const message = `Rejecting attempt to load a second extension with ID ${extensionURL}`;
|
||||||
|
|
|
@ -368,7 +368,7 @@ class Scratch3MakeyMakeyBlocks {
|
||||||
*/
|
*/
|
||||||
addSequence (sequenceString, sequenceArray) {
|
addSequence (sequenceString, sequenceArray) {
|
||||||
// If we already have this sequence string, return.
|
// If we already have this sequence string, return.
|
||||||
if (this.sequences.hasOwnProperty(sequenceString)) {
|
if (Object.prototype.hasOwnProperty.call(this.sequences, sequenceString)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.sequences[sequenceString] = {
|
this.sequences[sequenceString] = {
|
||||||
|
|
|
@ -569,7 +569,7 @@ class Scratch3PenBlocks {
|
||||||
penState.color = (hsv.h / 360) * 100;
|
penState.color = (hsv.h / 360) * 100;
|
||||||
penState.saturation = hsv.s * 100;
|
penState.saturation = hsv.s * 100;
|
||||||
penState.brightness = hsv.v * 100;
|
penState.brightness = hsv.v * 100;
|
||||||
if (rgb.hasOwnProperty('a')) {
|
if (Object.prototype.hasOwnProperty.call(rgb, 'a')) {
|
||||||
penState.transparency = 100 * (1 - (rgb.a / 255.0));
|
penState.transparency = 100 * (1 - (rgb.a / 255.0));
|
||||||
} else {
|
} else {
|
||||||
penState.transparency = 0;
|
penState.transparency = 0;
|
||||||
|
|
|
@ -222,11 +222,11 @@ class Scratch3TranslateBlocks {
|
||||||
getLanguageCodeFromArg (arg) {
|
getLanguageCodeFromArg (arg) {
|
||||||
const languageArg = Cast.toString(arg).toLowerCase();
|
const languageArg = Cast.toString(arg).toLowerCase();
|
||||||
// Check if the arg matches a language code in the menu.
|
// Check if the arg matches a language code in the menu.
|
||||||
if (languageNames.menuMap.hasOwnProperty(languageArg)) {
|
if (Object.prototype.hasOwnProperty.call(languageNames.menuMap, languageArg)) {
|
||||||
return languageArg;
|
return languageArg;
|
||||||
}
|
}
|
||||||
// Check for a dropped-in language name, and convert to a language code.
|
// Check for a dropped-in language name, and convert to a language code.
|
||||||
if (languageNames.nameMap.hasOwnProperty(languageArg)) {
|
if (Object.prototype.hasOwnProperty.call(languageNames.nameMap, languageArg)) {
|
||||||
return languageNames.nameMap[languageArg];
|
return languageNames.nameMap[languageArg];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -167,7 +167,6 @@ class Scratch3VideoSensingBlocks {
|
||||||
if (stage) {
|
if (stage) {
|
||||||
stage.videoTransparency = transparency;
|
stage.videoTransparency = transparency;
|
||||||
}
|
}
|
||||||
return transparency;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -191,7 +190,6 @@ class Scratch3VideoSensingBlocks {
|
||||||
if (stage) {
|
if (stage) {
|
||||||
stage.videoState = state;
|
stage.videoState = state;
|
||||||
}
|
}
|
||||||
return state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -100,9 +100,13 @@ const canvasPool = (function () {
|
||||||
*/
|
*/
|
||||||
const fetchBitmapCanvas_ = function (costume, runtime, rotationCenter) {
|
const fetchBitmapCanvas_ = function (costume, runtime, rotationCenter) {
|
||||||
if (!costume || !costume.asset) { // TODO: We can probably remove this check...
|
if (!costume || !costume.asset) { // TODO: We can probably remove this check...
|
||||||
|
// TODO: reject with an Error (breaking API change!)
|
||||||
|
// eslint-disable-next-line prefer-promise-reject-errors
|
||||||
return Promise.reject('Costume load failed. Assets were missing.');
|
return Promise.reject('Costume load failed. Assets were missing.');
|
||||||
}
|
}
|
||||||
if (!runtime.v2BitmapAdapter) {
|
if (!runtime.v2BitmapAdapter) {
|
||||||
|
// TODO: reject with an Error (breaking API change!)
|
||||||
|
// eslint-disable-next-line prefer-promise-reject-errors
|
||||||
return Promise.reject('No V2 Bitmap adapter present.');
|
return Promise.reject('No V2 Bitmap adapter present.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,6 +129,8 @@ const fetchBitmapCanvas_ = function (costume, runtime, rotationCenter) {
|
||||||
image.onerror = null;
|
image.onerror = null;
|
||||||
};
|
};
|
||||||
image.onerror = function () {
|
image.onerror = function () {
|
||||||
|
// TODO: reject with an Error (breaking API change!)
|
||||||
|
// eslint-disable-next-line prefer-promise-reject-errors
|
||||||
reject('Costume load failed. Asset could not be read.');
|
reject('Costume load failed. Asset could not be read.');
|
||||||
image.onload = null;
|
image.onload = null;
|
||||||
image.onerror = null;
|
image.onerror = null;
|
||||||
|
@ -194,6 +200,8 @@ const loadBitmap_ = function (costume, runtime, _rotationCenter) {
|
||||||
// somewhere and act on that error (like logging).
|
// somewhere and act on that error (like logging).
|
||||||
//
|
//
|
||||||
// Return a rejection to stop executing updateCostumeAsset.
|
// Return a rejection to stop executing updateCostumeAsset.
|
||||||
|
// TODO: reject with an Error (breaking API change!)
|
||||||
|
// eslint-disable-next-line prefer-promise-reject-errors
|
||||||
return Promise.reject('No V2 Bitmap adapter present.');
|
return Promise.reject('No V2 Bitmap adapter present.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ class Mouse {
|
||||||
const drawableID = this.runtime.renderer.pick(x, y);
|
const drawableID = this.runtime.renderer.pick(x, y);
|
||||||
for (let i = 0; i < this.runtime.targets.length; i++) {
|
for (let i = 0; i < this.runtime.targets.length; i++) {
|
||||||
const target = this.runtime.targets[i];
|
const target = this.runtime.targets[i];
|
||||||
if (target.hasOwnProperty('drawableID') &&
|
if (Object.prototype.hasOwnProperty.call(target, 'drawableID') &&
|
||||||
target.drawableID === drawableID) {
|
target.drawableID === drawableID) {
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
|
@ -288,7 +288,7 @@ const parseMonitorObject = (object, runtime, targets, extensions) => {
|
||||||
let target = null;
|
let target = null;
|
||||||
// List blocks don't come in with their target name set.
|
// List blocks don't come in with their target name set.
|
||||||
// Find the target by searching for a target with matching variable name/type.
|
// Find the target by searching for a target with matching variable name/type.
|
||||||
if (!object.hasOwnProperty('target')) {
|
if (!Object.prototype.hasOwnProperty.call(object, 'target')) {
|
||||||
for (let i = 0; i < targets.length; i++) {
|
for (let i = 0; i < targets.length; i++) {
|
||||||
const currTarget = targets[i];
|
const currTarget = targets[i];
|
||||||
const listVariables = Object.keys(currTarget.variables).filter(key => {
|
const listVariables = Object.keys(currTarget.variables).filter(key => {
|
||||||
|
@ -326,7 +326,7 @@ const parseMonitorObject = (object, runtime, targets, extensions) => {
|
||||||
block.id = getVariableId(object.param, Variable.SCALAR_TYPE);
|
block.id = getVariableId(object.param, Variable.SCALAR_TYPE);
|
||||||
} else if (object.cmd === 'contentsOfList:') {
|
} else if (object.cmd === 'contentsOfList:') {
|
||||||
block.id = getVariableId(object.param, Variable.LIST_TYPE);
|
block.id = getVariableId(object.param, Variable.LIST_TYPE);
|
||||||
} else if (runtime.monitorBlockInfo.hasOwnProperty(block.opcode)) {
|
} else if (Object.prototype.hasOwnProperty.call(runtime.monitorBlockInfo, block.opcode)) {
|
||||||
block.id = runtime.monitorBlockInfo[block.opcode].getId(target.id, block.fields);
|
block.id = runtime.monitorBlockInfo[block.opcode].getId(target.id, block.fields);
|
||||||
} else {
|
} else {
|
||||||
// If the opcode can't be found in the runtime monitorBlockInfo,
|
// If the opcode can't be found in the runtime monitorBlockInfo,
|
||||||
|
@ -405,7 +405,7 @@ const parseMonitorObject = (object, runtime, targets, extensions) => {
|
||||||
* objects.
|
* objects.
|
||||||
*/
|
*/
|
||||||
const parseScratchAssets = function (object, runtime, topLevel, zip) {
|
const parseScratchAssets = function (object, runtime, topLevel, zip) {
|
||||||
if (!object.hasOwnProperty('objName')) {
|
if (!Object.prototype.hasOwnProperty.call(object, 'objName')) {
|
||||||
// Skip parsing monitors. Or any other objects missing objName.
|
// Skip parsing monitors. Or any other objects missing objName.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -419,7 +419,7 @@ const parseScratchAssets = function (object, runtime, topLevel, zip) {
|
||||||
|
|
||||||
// Costumes from JSON.
|
// Costumes from JSON.
|
||||||
const costumePromises = assets.costumePromises;
|
const costumePromises = assets.costumePromises;
|
||||||
if (object.hasOwnProperty('costumes')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'costumes')) {
|
||||||
for (let i = 0; i < object.costumes.length; i++) {
|
for (let i = 0; i < object.costumes.length; i++) {
|
||||||
const costumeSource = object.costumes[i];
|
const costumeSource = object.costumes[i];
|
||||||
const bitmapResolution = costumeSource.bitmapResolution || 1;
|
const bitmapResolution = costumeSource.bitmapResolution || 1;
|
||||||
|
@ -464,7 +464,7 @@ const parseScratchAssets = function (object, runtime, topLevel, zip) {
|
||||||
}
|
}
|
||||||
// Sounds from JSON
|
// Sounds from JSON
|
||||||
const {soundBank, soundPromises} = assets;
|
const {soundBank, soundPromises} = assets;
|
||||||
if (object.hasOwnProperty('sounds')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'sounds')) {
|
||||||
for (let s = 0; s < object.sounds.length; s++) {
|
for (let s = 0; s < object.sounds.length; s++) {
|
||||||
const soundSource = object.sounds[s];
|
const soundSource = object.sounds[s];
|
||||||
const sound = {
|
const sound = {
|
||||||
|
@ -523,8 +523,8 @@ const parseScratchAssets = function (object, runtime, topLevel, zip) {
|
||||||
* @return {!Promise.<Array.<Target>>} Promise for the loaded targets when ready, or null for unsupported objects.
|
* @return {!Promise.<Array.<Target>>} Promise for the loaded targets when ready, or null for unsupported objects.
|
||||||
*/
|
*/
|
||||||
const parseScratchObject = function (object, runtime, extensions, topLevel, zip, assets) {
|
const parseScratchObject = function (object, runtime, extensions, topLevel, zip, assets) {
|
||||||
if (!object.hasOwnProperty('objName')) {
|
if (!Object.prototype.hasOwnProperty.call(object, 'objName')) {
|
||||||
if (object.hasOwnProperty('listName')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'listName')) {
|
||||||
// Shim these objects so they can be processed as monitors
|
// Shim these objects so they can be processed as monitors
|
||||||
object.cmd = 'contentsOfList:';
|
object.cmd = 'contentsOfList:';
|
||||||
object.param = object.listName;
|
object.param = object.listName;
|
||||||
|
@ -540,10 +540,10 @@ const parseScratchObject = function (object, runtime, extensions, topLevel, zip,
|
||||||
// @todo: For now, load all Scratch objects (stage/sprites) as a Sprite.
|
// @todo: For now, load all Scratch objects (stage/sprites) as a Sprite.
|
||||||
const sprite = new Sprite(blocks, runtime);
|
const sprite = new Sprite(blocks, runtime);
|
||||||
// Sprite/stage name from JSON.
|
// Sprite/stage name from JSON.
|
||||||
if (object.hasOwnProperty('objName')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'objName')) {
|
||||||
if (topLevel && object.objName !== 'Stage') {
|
if (topLevel && object.objName !== 'Stage') {
|
||||||
for (const child of object.children) {
|
for (const child of object.children) {
|
||||||
if (!child.hasOwnProperty('objName') && child.target === object.objName) {
|
if (!Object.prototype.hasOwnProperty.call(child, 'objName') && child.target === object.objName) {
|
||||||
child.target = 'Stage';
|
child.target = 'Stage';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -566,7 +566,7 @@ const parseScratchObject = function (object, runtime, extensions, topLevel, zip,
|
||||||
const addBroadcastMsg = globalBroadcastMsgObj.broadcastMsgMapUpdater;
|
const addBroadcastMsg = globalBroadcastMsgObj.broadcastMsgMapUpdater;
|
||||||
|
|
||||||
// Load target properties from JSON.
|
// Load target properties from JSON.
|
||||||
if (object.hasOwnProperty('variables')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'variables')) {
|
||||||
for (let j = 0; j < object.variables.length; j++) {
|
for (let j = 0; j < object.variables.length; j++) {
|
||||||
const variable = object.variables[j];
|
const variable = object.variables[j];
|
||||||
// A variable is a cloud variable if:
|
// A variable is a cloud variable if:
|
||||||
|
@ -589,7 +589,7 @@ const parseScratchObject = function (object, runtime, extensions, topLevel, zip,
|
||||||
// If included, parse any and all comments on the object (this includes top-level
|
// If included, parse any and all comments on the object (this includes top-level
|
||||||
// workspace comments as well as comments attached to specific blocks)
|
// workspace comments as well as comments attached to specific blocks)
|
||||||
const blockComments = {};
|
const blockComments = {};
|
||||||
if (object.hasOwnProperty('scriptComments')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'scriptComments')) {
|
||||||
const comments = object.scriptComments.map(commentDesc => {
|
const comments = object.scriptComments.map(commentDesc => {
|
||||||
const [
|
const [
|
||||||
commentX,
|
commentX,
|
||||||
|
@ -624,7 +624,7 @@ const parseScratchObject = function (object, runtime, extensions, topLevel, zip,
|
||||||
newComment.blockId = flattenedBlockIndex;
|
newComment.blockId = flattenedBlockIndex;
|
||||||
// Add this comment to the block comments object with its script index
|
// Add this comment to the block comments object with its script index
|
||||||
// as the key
|
// as the key
|
||||||
if (blockComments.hasOwnProperty(flattenedBlockIndex)) {
|
if (Object.prototype.hasOwnProperty.call(blockComments, flattenedBlockIndex)) {
|
||||||
blockComments[flattenedBlockIndex].push(newComment);
|
blockComments[flattenedBlockIndex].push(newComment);
|
||||||
} else {
|
} else {
|
||||||
blockComments[flattenedBlockIndex] = [newComment];
|
blockComments[flattenedBlockIndex] = [newComment];
|
||||||
|
@ -641,7 +641,7 @@ const parseScratchObject = function (object, runtime, extensions, topLevel, zip,
|
||||||
}
|
}
|
||||||
|
|
||||||
// If included, parse any and all scripts/blocks on the object.
|
// If included, parse any and all scripts/blocks on the object.
|
||||||
if (object.hasOwnProperty('scripts')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'scripts')) {
|
||||||
parseScripts(object.scripts, blocks, addBroadcastMsg, getVariableId, extensions, blockComments);
|
parseScripts(object.scripts, blocks, addBroadcastMsg, getVariableId, extensions, blockComments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -664,7 +664,7 @@ const parseScratchObject = function (object, runtime, extensions, topLevel, zip,
|
||||||
// Update stage specific blocks (e.g. sprite clicked <=> stage clicked)
|
// Update stage specific blocks (e.g. sprite clicked <=> stage clicked)
|
||||||
blocks.updateTargetSpecificBlocks(topLevel); // topLevel = isStage
|
blocks.updateTargetSpecificBlocks(topLevel); // topLevel = isStage
|
||||||
|
|
||||||
if (object.hasOwnProperty('lists')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'lists')) {
|
||||||
for (let k = 0; k < object.lists.length; k++) {
|
for (let k = 0; k < object.lists.length; k++) {
|
||||||
const list = object.lists[k];
|
const list = object.lists[k];
|
||||||
const newVariable = new Variable(
|
const newVariable = new Variable(
|
||||||
|
@ -677,34 +677,34 @@ const parseScratchObject = function (object, runtime, extensions, topLevel, zip,
|
||||||
target.variables[newVariable.id] = newVariable;
|
target.variables[newVariable.id] = newVariable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('scratchX')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'scratchX')) {
|
||||||
target.x = object.scratchX;
|
target.x = object.scratchX;
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('scratchY')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'scratchY')) {
|
||||||
target.y = object.scratchY;
|
target.y = object.scratchY;
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('direction')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'direction')) {
|
||||||
// Sometimes the direction can be outside of the range: LLK/scratch-gui#5806
|
// Sometimes the direction can be outside of the range: LLK/scratch-gui#5806
|
||||||
// wrapClamp it (like we do on RenderedTarget.setDirection)
|
// wrapClamp it (like we do on RenderedTarget.setDirection)
|
||||||
target.direction = MathUtil.wrapClamp(object.direction, -179, 180);
|
target.direction = MathUtil.wrapClamp(object.direction, -179, 180);
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('isDraggable')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'isDraggable')) {
|
||||||
target.draggable = object.isDraggable;
|
target.draggable = object.isDraggable;
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('scale')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'scale')) {
|
||||||
// SB2 stores as 1.0 = 100%; we use % in the VM.
|
// SB2 stores as 1.0 = 100%; we use % in the VM.
|
||||||
target.size = object.scale * 100;
|
target.size = object.scale * 100;
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('visible')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'visible')) {
|
||||||
target.visible = object.visible;
|
target.visible = object.visible;
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('currentCostumeIndex')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'currentCostumeIndex')) {
|
||||||
// Current costume index can sometimes be a floating
|
// Current costume index can sometimes be a floating
|
||||||
// point number, use Math.floor to come up with an appropriate index
|
// point number, use Math.floor to come up with an appropriate index
|
||||||
// and clamp it to the actual number of costumes the object has for good measure.
|
// and clamp it to the actual number of costumes the object has for good measure.
|
||||||
target.currentCostume = MathUtil.clamp(Math.floor(object.currentCostumeIndex), 0, object.costumes.length - 1);
|
target.currentCostume = MathUtil.clamp(Math.floor(object.currentCostumeIndex), 0, object.costumes.length - 1);
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('rotationStyle')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'rotationStyle')) {
|
||||||
if (object.rotationStyle === 'none') {
|
if (object.rotationStyle === 'none') {
|
||||||
target.rotationStyle = RenderedTarget.ROTATION_STYLE_NONE;
|
target.rotationStyle = RenderedTarget.ROTATION_STYLE_NONE;
|
||||||
} else if (object.rotationStyle === 'leftRight') {
|
} else if (object.rotationStyle === 'leftRight') {
|
||||||
|
@ -713,16 +713,16 @@ const parseScratchObject = function (object, runtime, extensions, topLevel, zip,
|
||||||
target.rotationStyle = RenderedTarget.ROTATION_STYLE_ALL_AROUND;
|
target.rotationStyle = RenderedTarget.ROTATION_STYLE_ALL_AROUND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('tempoBPM')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'tempoBPM')) {
|
||||||
target.tempo = object.tempoBPM;
|
target.tempo = object.tempoBPM;
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('videoAlpha')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'videoAlpha')) {
|
||||||
// SB2 stores alpha as opacity, where 1.0 is opaque.
|
// SB2 stores alpha as opacity, where 1.0 is opaque.
|
||||||
// We convert to a percentage, and invert it so 100% is full transparency.
|
// We convert to a percentage, and invert it so 100% is full transparency.
|
||||||
target.videoTransparency = 100 - (100 * object.videoAlpha);
|
target.videoTransparency = 100 - (100 * object.videoAlpha);
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('info')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'info')) {
|
||||||
if (object.info.hasOwnProperty('videoOn')) {
|
if (Object.prototype.hasOwnProperty.call(object.info, 'videoOn')) {
|
||||||
if (object.info.videoOn) {
|
if (object.info.videoOn) {
|
||||||
target.videoState = RenderedTarget.VIDEO_STATE.ON;
|
target.videoState = RenderedTarget.VIDEO_STATE.ON;
|
||||||
} else {
|
} else {
|
||||||
|
@ -730,7 +730,7 @@ const parseScratchObject = function (object, runtime, extensions, topLevel, zip,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('indexInLibrary')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'indexInLibrary')) {
|
||||||
// Temporarily store the 'indexInLibrary' property from the sb2 file
|
// Temporarily store the 'indexInLibrary' property from the sb2 file
|
||||||
// so that we can correctly order sprites in the target pane.
|
// so that we can correctly order sprites in the target pane.
|
||||||
// This will be deleted after we are done parsing and ordering the targets list.
|
// This will be deleted after we are done parsing and ordering the targets list.
|
||||||
|
|
|
@ -173,7 +173,7 @@ const serializeFields = function (fields) {
|
||||||
for (const fieldName in fields) {
|
for (const fieldName in fields) {
|
||||||
if (!hasOwnProperty.call(fields, fieldName)) continue;
|
if (!hasOwnProperty.call(fields, fieldName)) continue;
|
||||||
obj[fieldName] = [fields[fieldName].value];
|
obj[fieldName] = [fields[fieldName].value];
|
||||||
if (fields[fieldName].hasOwnProperty('id')) {
|
if (Object.prototype.hasOwnProperty.call(fields[fieldName], 'id')) {
|
||||||
obj[fieldName].push(fields[fieldName].id);
|
obj[fieldName].push(fields[fieldName].id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,7 +301,7 @@ const serializeBlocks = function (blocks) {
|
||||||
const obj = Object.create(null);
|
const obj = Object.create(null);
|
||||||
const extensionIDs = new Set();
|
const extensionIDs = new Set();
|
||||||
for (const blockID in blocks) {
|
for (const blockID in blocks) {
|
||||||
if (!blocks.hasOwnProperty(blockID)) continue;
|
if (!Object.prototype.hasOwnProperty.call(blocks, blockID)) continue;
|
||||||
obj[blockID] = serializeBlock(blocks[blockID], blocks);
|
obj[blockID] = serializeBlock(blocks[blockID], blocks);
|
||||||
const extensionID = getExtensionIdForOpcode(blocks[blockID].opcode);
|
const extensionID = getExtensionIdForOpcode(blocks[blockID].opcode);
|
||||||
if (extensionID) {
|
if (extensionID) {
|
||||||
|
@ -428,7 +428,7 @@ const serializeVariables = function (variables) {
|
||||||
const serializeComments = function (comments) {
|
const serializeComments = function (comments) {
|
||||||
const obj = Object.create(null);
|
const obj = Object.create(null);
|
||||||
for (const commentId in comments) {
|
for (const commentId in comments) {
|
||||||
if (!comments.hasOwnProperty(commentId)) continue;
|
if (!Object.prototype.hasOwnProperty.call(comments, commentId)) continue;
|
||||||
const comment = comments[commentId];
|
const comment = comments[commentId];
|
||||||
|
|
||||||
const serializedComment = Object.create(null);
|
const serializedComment = Object.create(null);
|
||||||
|
@ -473,13 +473,21 @@ const serializeTarget = function (target, extensions) {
|
||||||
obj.currentCostume = target.currentCostume;
|
obj.currentCostume = target.currentCostume;
|
||||||
obj.costumes = target.costumes.map(serializeCostume);
|
obj.costumes = target.costumes.map(serializeCostume);
|
||||||
obj.sounds = target.sounds.map(serializeSound);
|
obj.sounds = target.sounds.map(serializeSound);
|
||||||
if (target.hasOwnProperty('volume')) obj.volume = target.volume;
|
if (Object.prototype.hasOwnProperty.call(target, 'volume')) obj.volume = target.volume;
|
||||||
if (target.hasOwnProperty('layerOrder')) obj.layerOrder = target.layerOrder;
|
if (Object.prototype.hasOwnProperty.call(target, 'layerOrder')) obj.layerOrder = target.layerOrder;
|
||||||
if (obj.isStage) { // Only the stage should have these properties
|
if (obj.isStage) { // Only the stage should have these properties
|
||||||
if (target.hasOwnProperty('tempo')) obj.tempo = target.tempo;
|
if (Object.prototype.hasOwnProperty.call(target, 'tempo')) {
|
||||||
if (target.hasOwnProperty('videoTransparency')) obj.videoTransparency = target.videoTransparency;
|
obj.tempo = target.tempo;
|
||||||
if (target.hasOwnProperty('videoState')) obj.videoState = target.videoState;
|
}
|
||||||
if (target.hasOwnProperty('textToSpeechLanguage')) obj.textToSpeechLanguage = target.textToSpeechLanguage;
|
if (Object.prototype.hasOwnProperty.call(target, 'videoTransparency')) {
|
||||||
|
obj.videoTransparency = target.videoTransparency;
|
||||||
|
}
|
||||||
|
if (Object.prototype.hasOwnProperty.call(target, 'videoState')) {
|
||||||
|
obj.videoState = target.videoState;
|
||||||
|
}
|
||||||
|
if (Object.prototype.hasOwnProperty.call(target, 'textToSpeechLanguage')) {
|
||||||
|
obj.textToSpeechLanguage = target.textToSpeechLanguage;
|
||||||
|
}
|
||||||
} else { // The stage does not need the following properties, but sprites should
|
} else { // The stage does not need the following properties, but sprites should
|
||||||
obj.visible = target.visible;
|
obj.visible = target.visible;
|
||||||
obj.x = target.x;
|
obj.x = target.x;
|
||||||
|
@ -852,7 +860,7 @@ const deserializeBlocks = function (blocks) {
|
||||||
* SoundBank for the sound assets. null for unsupported objects.
|
* SoundBank for the sound assets. null for unsupported objects.
|
||||||
*/
|
*/
|
||||||
const parseScratchAssets = function (object, runtime, zip) {
|
const parseScratchAssets = function (object, runtime, zip) {
|
||||||
if (!object.hasOwnProperty('name')) {
|
if (!Object.prototype.hasOwnProperty.call(object, 'name')) {
|
||||||
// Watcher/monitor - skip this object until those are implemented in VM.
|
// Watcher/monitor - skip this object until those are implemented in VM.
|
||||||
// @todo
|
// @todo
|
||||||
return Promise.resolve(null);
|
return Promise.resolve(null);
|
||||||
|
@ -882,7 +890,7 @@ const parseScratchAssets = function (object, runtime, zip) {
|
||||||
costumeSource.dataFormat ||
|
costumeSource.dataFormat ||
|
||||||
(costumeSource.assetType && costumeSource.assetType.runtimeFormat) || // older format
|
(costumeSource.assetType && costumeSource.assetType.runtimeFormat) || // older format
|
||||||
'png'; // if all else fails, guess that it might be a PNG
|
'png'; // if all else fails, guess that it might be a PNG
|
||||||
const costumeMd5Ext = costumeSource.hasOwnProperty('md5ext') ?
|
const costumeMd5Ext = Object.prototype.hasOwnProperty.call(costumeSource, 'md5ext') ?
|
||||||
costumeSource.md5ext : `${costumeSource.assetId}.${dataFormat}`;
|
costumeSource.md5ext : `${costumeSource.assetId}.${dataFormat}`;
|
||||||
costume.md5 = costumeMd5Ext;
|
costume.md5 = costumeMd5Ext;
|
||||||
costume.dataFormat = dataFormat;
|
costume.dataFormat = dataFormat;
|
||||||
|
@ -936,7 +944,7 @@ const parseScratchAssets = function (object, runtime, zip) {
|
||||||
* @return {!Promise.<Target>} Promise for the target created (stage or sprite), or null for unsupported objects.
|
* @return {!Promise.<Target>} Promise for the target created (stage or sprite), or null for unsupported objects.
|
||||||
*/
|
*/
|
||||||
const parseScratchObject = function (object, runtime, extensions, zip, assets) {
|
const parseScratchObject = function (object, runtime, extensions, zip, assets) {
|
||||||
if (!object.hasOwnProperty('name')) {
|
if (!Object.prototype.hasOwnProperty.call(object, 'name')) {
|
||||||
// Watcher/monitor - skip this object until those are implemented in VM.
|
// Watcher/monitor - skip this object until those are implemented in VM.
|
||||||
// @todo
|
// @todo
|
||||||
return Promise.resolve(null);
|
return Promise.resolve(null);
|
||||||
|
@ -948,14 +956,14 @@ const parseScratchObject = function (object, runtime, extensions, zip, assets) {
|
||||||
const sprite = new Sprite(blocks, runtime);
|
const sprite = new Sprite(blocks, runtime);
|
||||||
|
|
||||||
// Sprite/stage name from JSON.
|
// Sprite/stage name from JSON.
|
||||||
if (object.hasOwnProperty('name')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'name')) {
|
||||||
sprite.name = object.name;
|
sprite.name = object.name;
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('blocks')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'blocks')) {
|
||||||
deserializeBlocks(object.blocks);
|
deserializeBlocks(object.blocks);
|
||||||
// Take a second pass to create objects and add extensions
|
// Take a second pass to create objects and add extensions
|
||||||
for (const blockId in object.blocks) {
|
for (const blockId in object.blocks) {
|
||||||
if (!object.blocks.hasOwnProperty(blockId)) continue;
|
if (!Object.prototype.hasOwnProperty.call(object.blocks, blockId)) continue;
|
||||||
const blockJSON = object.blocks[blockId];
|
const blockJSON = object.blocks[blockId];
|
||||||
blocks.createBlock(blockJSON);
|
blocks.createBlock(blockJSON);
|
||||||
|
|
||||||
|
@ -973,22 +981,22 @@ const parseScratchObject = function (object, runtime, extensions, zip, assets) {
|
||||||
// Create the first clone, and load its run-state from JSON.
|
// Create the first clone, and load its run-state from JSON.
|
||||||
const target = sprite.createClone(object.isStage ? StageLayering.BACKGROUND_LAYER : StageLayering.SPRITE_LAYER);
|
const target = sprite.createClone(object.isStage ? StageLayering.BACKGROUND_LAYER : StageLayering.SPRITE_LAYER);
|
||||||
// Load target properties from JSON.
|
// Load target properties from JSON.
|
||||||
if (object.hasOwnProperty('tempo')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'tempo')) {
|
||||||
target.tempo = object.tempo;
|
target.tempo = object.tempo;
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('volume')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'volume')) {
|
||||||
target.volume = object.volume;
|
target.volume = object.volume;
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('videoTransparency')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'videoTransparency')) {
|
||||||
target.videoTransparency = object.videoTransparency;
|
target.videoTransparency = object.videoTransparency;
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('videoState')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'videoState')) {
|
||||||
target.videoState = object.videoState;
|
target.videoState = object.videoState;
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('textToSpeechLanguage')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'textToSpeechLanguage')) {
|
||||||
target.textToSpeechLanguage = object.textToSpeechLanguage;
|
target.textToSpeechLanguage = object.textToSpeechLanguage;
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('variables')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'variables')) {
|
||||||
for (const varId in object.variables) {
|
for (const varId in object.variables) {
|
||||||
const variable = object.variables[varId];
|
const variable = object.variables[varId];
|
||||||
// A variable is a cloud variable if:
|
// A variable is a cloud variable if:
|
||||||
|
@ -1008,7 +1016,7 @@ const parseScratchObject = function (object, runtime, extensions, zip, assets) {
|
||||||
target.variables[newVariable.id] = newVariable;
|
target.variables[newVariable.id] = newVariable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('lists')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'lists')) {
|
||||||
for (const listId in object.lists) {
|
for (const listId in object.lists) {
|
||||||
const list = object.lists[listId];
|
const list = object.lists[listId];
|
||||||
const newList = new Variable(
|
const newList = new Variable(
|
||||||
|
@ -1021,7 +1029,7 @@ const parseScratchObject = function (object, runtime, extensions, zip, assets) {
|
||||||
target.variables[newList.id] = newList;
|
target.variables[newList.id] = newList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('broadcasts')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'broadcasts')) {
|
||||||
for (const broadcastId in object.broadcasts) {
|
for (const broadcastId in object.broadcasts) {
|
||||||
const broadcast = object.broadcasts[broadcastId];
|
const broadcast = object.broadcasts[broadcastId];
|
||||||
const newBroadcast = new Variable(
|
const newBroadcast = new Variable(
|
||||||
|
@ -1035,7 +1043,7 @@ const parseScratchObject = function (object, runtime, extensions, zip, assets) {
|
||||||
target.variables[newBroadcast.id] = newBroadcast;
|
target.variables[newBroadcast.id] = newBroadcast;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('comments')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'comments')) {
|
||||||
for (const commentId in object.comments) {
|
for (const commentId in object.comments) {
|
||||||
const comment = object.comments[commentId];
|
const comment = object.comments[commentId];
|
||||||
const newComment = new Comment(
|
const newComment = new Comment(
|
||||||
|
@ -1053,39 +1061,39 @@ const parseScratchObject = function (object, runtime, extensions, zip, assets) {
|
||||||
target.comments[newComment.id] = newComment;
|
target.comments[newComment.id] = newComment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('x')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'x')) {
|
||||||
target.x = object.x;
|
target.x = object.x;
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('y')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'y')) {
|
||||||
target.y = object.y;
|
target.y = object.y;
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('direction')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'direction')) {
|
||||||
// Sometimes the direction can be outside of the range: LLK/scratch-gui#5806
|
// Sometimes the direction can be outside of the range: LLK/scratch-gui#5806
|
||||||
// wrapClamp it (like we do on RenderedTarget.setDirection)
|
// wrapClamp it (like we do on RenderedTarget.setDirection)
|
||||||
target.direction = MathUtil.wrapClamp(object.direction, -179, 180);
|
target.direction = MathUtil.wrapClamp(object.direction, -179, 180);
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('size')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'size')) {
|
||||||
target.size = object.size;
|
target.size = object.size;
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('visible')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'visible')) {
|
||||||
target.visible = object.visible;
|
target.visible = object.visible;
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('currentCostume')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'currentCostume')) {
|
||||||
target.currentCostume = MathUtil.clamp(object.currentCostume, 0, object.costumes.length - 1);
|
target.currentCostume = MathUtil.clamp(object.currentCostume, 0, object.costumes.length - 1);
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('rotationStyle')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'rotationStyle')) {
|
||||||
target.rotationStyle = object.rotationStyle;
|
target.rotationStyle = object.rotationStyle;
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('isStage')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'isStage')) {
|
||||||
target.isStage = object.isStage;
|
target.isStage = object.isStage;
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('targetPaneOrder')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'targetPaneOrder')) {
|
||||||
// Temporarily store the 'targetPaneOrder' property
|
// Temporarily store the 'targetPaneOrder' property
|
||||||
// so that we can correctly order sprites in the target pane.
|
// so that we can correctly order sprites in the target pane.
|
||||||
// This will be deleted after we are done parsing and ordering the targets list.
|
// This will be deleted after we are done parsing and ordering the targets list.
|
||||||
target.targetPaneOrder = object.targetPaneOrder;
|
target.targetPaneOrder = object.targetPaneOrder;
|
||||||
}
|
}
|
||||||
if (object.hasOwnProperty('draggable')) {
|
if (Object.prototype.hasOwnProperty.call(object, 'draggable')) {
|
||||||
target.draggable = object.draggable;
|
target.draggable = object.draggable;
|
||||||
}
|
}
|
||||||
Promise.all(costumePromises).then(costumes => {
|
Promise.all(costumePromises).then(costumes => {
|
||||||
|
|
|
@ -395,7 +395,7 @@ class RenderedTarget extends Target {
|
||||||
* @param {!number} value Numerical magnitude of effect.
|
* @param {!number} value Numerical magnitude of effect.
|
||||||
*/
|
*/
|
||||||
setEffect (effectName, value) {
|
setEffect (effectName, value) {
|
||||||
if (!this.effects.hasOwnProperty(effectName)) return;
|
if (!Object.prototype.hasOwnProperty.call(this.effects, effectName)) return;
|
||||||
this.effects[effectName] = value;
|
this.effects[effectName] = value;
|
||||||
if (this.renderer) {
|
if (this.renderer) {
|
||||||
this.renderer.updateDrawableEffect(this.drawableID, effectName, value);
|
this.renderer.updateDrawableEffect(this.drawableID, effectName, value);
|
||||||
|
@ -411,12 +411,12 @@ class RenderedTarget extends Target {
|
||||||
*/
|
*/
|
||||||
clearEffects () {
|
clearEffects () {
|
||||||
for (const effectName in this.effects) {
|
for (const effectName in this.effects) {
|
||||||
if (!this.effects.hasOwnProperty(effectName)) continue;
|
if (!Object.prototype.hasOwnProperty.call(this.effects, effectName)) continue;
|
||||||
this.effects[effectName] = 0;
|
this.effects[effectName] = 0;
|
||||||
}
|
}
|
||||||
if (this.renderer) {
|
if (this.renderer) {
|
||||||
for (const effectName in this.effects) {
|
for (const effectName in this.effects) {
|
||||||
if (!this.effects.hasOwnProperty(effectName)) continue;
|
if (!Object.prototype.hasOwnProperty.call(this.effects, effectName)) continue;
|
||||||
this.renderer.updateDrawableEffect(this.drawableID, effectName, 0);
|
this.renderer.updateDrawableEffect(this.drawableID, effectName, 0);
|
||||||
}
|
}
|
||||||
if (this.visible) {
|
if (this.visible) {
|
||||||
|
@ -682,7 +682,7 @@ class RenderedTarget extends Target {
|
||||||
this.renderer.updateDrawableSkinId(this.drawableID, costume.skinId);
|
this.renderer.updateDrawableSkinId(this.drawableID, costume.skinId);
|
||||||
|
|
||||||
for (const effectName in this.effects) {
|
for (const effectName in this.effects) {
|
||||||
if (!this.effects.hasOwnProperty(effectName)) continue;
|
if (!Object.prototype.hasOwnProperty.call(this.effects, effectName)) continue;
|
||||||
this.renderer.updateDrawableEffect(this.drawableID, effectName, this.effects[effectName]);
|
this.renderer.updateDrawableEffect(this.drawableID, effectName, this.effects[effectName]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1020,25 +1020,25 @@ class RenderedTarget extends Target {
|
||||||
* @param {object} data An object with sprite info data to set.
|
* @param {object} data An object with sprite info data to set.
|
||||||
*/
|
*/
|
||||||
postSpriteInfo (data) {
|
postSpriteInfo (data) {
|
||||||
const force = data.hasOwnProperty('force') ? data.force : null;
|
const force = Object.prototype.hasOwnProperty.call(data, 'force') ? data.force : null;
|
||||||
const isXChanged = data.hasOwnProperty('x');
|
const isXChanged = Object.prototype.hasOwnProperty.call(data, 'x');
|
||||||
const isYChanged = data.hasOwnProperty('y');
|
const isYChanged = Object.prototype.hasOwnProperty.call(data, 'y');
|
||||||
if (isXChanged || isYChanged) {
|
if (isXChanged || isYChanged) {
|
||||||
this.setXY(isXChanged ? data.x : this.x, isYChanged ? data.y : this.y, force);
|
this.setXY(isXChanged ? data.x : this.x, isYChanged ? data.y : this.y, force);
|
||||||
}
|
}
|
||||||
if (data.hasOwnProperty('direction')) {
|
if (Object.prototype.hasOwnProperty.call(data, 'direction')) {
|
||||||
this.setDirection(data.direction);
|
this.setDirection(data.direction);
|
||||||
}
|
}
|
||||||
if (data.hasOwnProperty('draggable')) {
|
if (Object.prototype.hasOwnProperty.call(data, 'draggable')) {
|
||||||
this.setDraggable(data.draggable);
|
this.setDraggable(data.draggable);
|
||||||
}
|
}
|
||||||
if (data.hasOwnProperty('rotationStyle')) {
|
if (Object.prototype.hasOwnProperty.call(data, 'rotationStyle')) {
|
||||||
this.setRotationStyle(data.rotationStyle);
|
this.setRotationStyle(data.rotationStyle);
|
||||||
}
|
}
|
||||||
if (data.hasOwnProperty('visible')) {
|
if (Object.prototype.hasOwnProperty.call(data, 'visible')) {
|
||||||
this.setVisible(data.visible);
|
this.setVisible(data.visible);
|
||||||
}
|
}
|
||||||
if (data.hasOwnProperty('size')) {
|
if (Object.prototype.hasOwnProperty.call(data, 'size')) {
|
||||||
this.setSize(data.size);
|
this.setSize(data.size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ class JSONRPC {
|
||||||
if (json.jsonrpc !== '2.0') {
|
if (json.jsonrpc !== '2.0') {
|
||||||
throw new Error(`Bad or missing JSON-RPC version in message: ${json}`);
|
throw new Error(`Bad or missing JSON-RPC version in message: ${json}`);
|
||||||
}
|
}
|
||||||
if (json.hasOwnProperty('method')) {
|
if (Object.prototype.hasOwnProperty.call(json, 'method')) {
|
||||||
this._handleRequest(json);
|
this._handleRequest(json);
|
||||||
} else {
|
} else {
|
||||||
this._handleResponse(json);
|
this._handleResponse(json);
|
||||||
|
|
|
@ -21,8 +21,10 @@ class TaskQueue {
|
||||||
this._maxTokens = maxTokens;
|
this._maxTokens = maxTokens;
|
||||||
this._refillRate = refillRate;
|
this._refillRate = refillRate;
|
||||||
this._pendingTaskRecords = [];
|
this._pendingTaskRecords = [];
|
||||||
this._tokenCount = options.hasOwnProperty('startingTokens') ? options.startingTokens : maxTokens;
|
this._tokenCount = Object.prototype.hasOwnProperty.call(options, 'startingTokens') ?
|
||||||
this._maxTotalCost = options.hasOwnProperty('maxTotalCost') ? options.maxTotalCost : Infinity;
|
options.startingTokens : maxTokens;
|
||||||
|
this._maxTotalCost = Object.prototype.hasOwnProperty.call(options, 'maxTotalCost') ?
|
||||||
|
options.maxTotalCost : Infinity;
|
||||||
this._timer = new Timer();
|
this._timer = new Timer();
|
||||||
this._timer.start();
|
this._timer.start();
|
||||||
this._timeout = null;
|
this._timeout = null;
|
||||||
|
@ -53,7 +55,7 @@ class TaskQueue {
|
||||||
if (this._maxTotalCost < Infinity) {
|
if (this._maxTotalCost < Infinity) {
|
||||||
const currentTotalCost = this._pendingTaskRecords.reduce((t, r) => t + r.cost, 0);
|
const currentTotalCost = this._pendingTaskRecords.reduce((t, r) => t + r.cost, 0);
|
||||||
if (currentTotalCost + cost > this._maxTotalCost) {
|
if (currentTotalCost + cost > this._maxTotalCost) {
|
||||||
return Promise.reject('Maximum total cost exceeded');
|
return Promise.reject(new Error('Maximum total cost exceeded'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const newRecord = {
|
const newRecord = {
|
||||||
|
|
|
@ -2,7 +2,6 @@ let _TextEncoder;
|
||||||
if (typeof TextEncoder === 'undefined') {
|
if (typeof TextEncoder === 'undefined') {
|
||||||
_TextEncoder = require('text-encoding').TextEncoder;
|
_TextEncoder = require('text-encoding').TextEncoder;
|
||||||
} else {
|
} else {
|
||||||
/* global TextEncoder */
|
|
||||||
_TextEncoder = TextEncoder;
|
_TextEncoder = TextEncoder;
|
||||||
}
|
}
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
|
@ -354,7 +353,7 @@ class VirtualMachine extends EventEmitter {
|
||||||
.then(() => this.runtime.handleProjectLoaded())
|
.then(() => this.runtime.handleProjectLoaded())
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
// Intentionally rejecting here (want errors to be handled by caller)
|
// Intentionally rejecting here (want errors to be handled by caller)
|
||||||
if (error.hasOwnProperty('validationError')) {
|
if (Object.prototype.hasOwnProperty.call(error, 'validationError')) {
|
||||||
return Promise.reject(JSON.stringify(error));
|
return Promise.reject(JSON.stringify(error));
|
||||||
}
|
}
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
|
@ -503,6 +502,8 @@ class VirtualMachine extends EventEmitter {
|
||||||
const sb3 = require('./serialization/sb3');
|
const sb3 = require('./serialization/sb3');
|
||||||
return sb3.deserialize(projectJSON, runtime, zip);
|
return sb3.deserialize(projectJSON, runtime, zip);
|
||||||
}
|
}
|
||||||
|
// TODO: reject with an Error (possible breaking API change!)
|
||||||
|
// eslint-disable-next-line prefer-promise-reject-errors
|
||||||
return Promise.reject('Unable to verify Scratch Project version.');
|
return Promise.reject('Unable to verify Scratch Project version.');
|
||||||
};
|
};
|
||||||
return deserializePromise()
|
return deserializePromise()
|
||||||
|
@ -607,14 +608,18 @@ class VirtualMachine extends EventEmitter {
|
||||||
if (projectVersion === 3) {
|
if (projectVersion === 3) {
|
||||||
return this._addSprite3(validatedInput[0], validatedInput[1]);
|
return this._addSprite3(validatedInput[0], validatedInput[1]);
|
||||||
}
|
}
|
||||||
|
// TODO: reject with an Error (possible breaking API change!)
|
||||||
|
// eslint-disable-next-line prefer-promise-reject-errors
|
||||||
return Promise.reject(`${errorPrefix} Unable to verify sprite version.`);
|
return Promise.reject(`${errorPrefix} Unable to verify sprite version.`);
|
||||||
})
|
})
|
||||||
.then(() => this.runtime.emitProjectChanged())
|
.then(() => this.runtime.emitProjectChanged())
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
// Intentionally rejecting here (want errors to be handled by caller)
|
// Intentionally rejecting here (want errors to be handled by caller)
|
||||||
if (error.hasOwnProperty('validationError')) {
|
if (Object.prototype.hasOwnProperty.call(error, 'validationError')) {
|
||||||
return Promise.reject(JSON.stringify(error));
|
return Promise.reject(JSON.stringify(error));
|
||||||
}
|
}
|
||||||
|
// TODO: reject with an Error (possible breaking API change!)
|
||||||
|
// eslint-disable-next-line prefer-promise-reject-errors
|
||||||
return Promise.reject(`${errorPrefix} ${error}`);
|
return Promise.reject(`${errorPrefix} ${error}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -673,6 +678,8 @@ class VirtualMachine extends EventEmitter {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// If the target cannot be found by id, return a rejected promise
|
// If the target cannot be found by id, return a rejected promise
|
||||||
|
// TODO: reject with an Error (possible breaking API change!)
|
||||||
|
// eslint-disable-next-line prefer-promise-reject-errors
|
||||||
return Promise.reject();
|
return Promise.reject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -687,6 +694,8 @@ class VirtualMachine extends EventEmitter {
|
||||||
* @returns {?Promise} - a promise that resolves when the costume has been added
|
* @returns {?Promise} - a promise that resolves when the costume has been added
|
||||||
*/
|
*/
|
||||||
addCostumeFromLibrary (md5ext, costumeObject) {
|
addCostumeFromLibrary (md5ext, costumeObject) {
|
||||||
|
// TODO: reject with an Error (possible breaking API change!)
|
||||||
|
// eslint-disable-next-line prefer-promise-reject-errors
|
||||||
if (!this.editingTarget) return Promise.reject();
|
if (!this.editingTarget) return Promise.reject();
|
||||||
return this.addCostume(md5ext, costumeObject, this.editingTarget.id, 2 /* optVersion */);
|
return this.addCostume(md5ext, costumeObject, this.editingTarget.id, 2 /* optVersion */);
|
||||||
}
|
}
|
||||||
|
@ -1338,7 +1347,7 @@ class VirtualMachine extends EventEmitter {
|
||||||
targetList: this.runtime.targets
|
targetList: this.runtime.targets
|
||||||
.filter(
|
.filter(
|
||||||
// Don't report clones.
|
// Don't report clones.
|
||||||
target => !target.hasOwnProperty('isOriginal') || target.isOriginal
|
target => !Object.prototype.hasOwnProperty.call(target, 'isOriginal') || target.isOriginal
|
||||||
).map(
|
).map(
|
||||||
target => target.toJSON()
|
target => target.toJSON()
|
||||||
),
|
),
|
||||||
|
@ -1414,7 +1423,10 @@ class VirtualMachine extends EventEmitter {
|
||||||
*/
|
*/
|
||||||
getTargetIdForDrawableId (drawableId) {
|
getTargetIdForDrawableId (drawableId) {
|
||||||
const target = this.runtime.getTargetByDrawableId(drawableId);
|
const target = this.runtime.getTargetByDrawableId(drawableId);
|
||||||
if (target && target.hasOwnProperty('id') && target.hasOwnProperty('isStage') && !target.isStage) {
|
if (target &&
|
||||||
|
Object.prototype.hasOwnProperty.call(target, 'id') &&
|
||||||
|
Object.prototype.hasOwnProperty.call(target, 'isStage') &&
|
||||||
|
!target.isStage) {
|
||||||
return target.id;
|
return target.id;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
2
test/fixtures/dispatch-test-worker-shim.js
vendored
2
test/fixtures/dispatch-test-worker-shim.js
vendored
|
@ -6,6 +6,8 @@ const path = require('path');
|
||||||
const oldRequire = Module.prototype.require;
|
const oldRequire = Module.prototype.require;
|
||||||
Module.prototype.require = function (target) {
|
Module.prototype.require = function (target) {
|
||||||
if (target.indexOf('/') === -1) {
|
if (target.indexOf('/') === -1) {
|
||||||
|
// we really do just want to forward the arguments here
|
||||||
|
// eslint-disable-next-line prefer-rest-params
|
||||||
return oldRequire.apply(this, arguments);
|
return oldRequire.apply(this, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,9 @@ test('importing sb2 project with special chars in message names', t => {
|
||||||
t.equal(allBroadcastFields[ltPerfectMessageId].length, 1);
|
t.equal(allBroadcastFields[ltPerfectMessageId].length, 1);
|
||||||
t.equal(allBroadcastFields[abMessageId].length, 1);
|
t.equal(allBroadcastFields[abMessageId].length, 1);
|
||||||
const catBlocks = Object.keys(cat.blocks._blocks).map(blockId => cat.blocks._blocks[blockId]);
|
const catBlocks = Object.keys(cat.blocks._blocks).map(blockId => cat.blocks._blocks[blockId]);
|
||||||
const catMessageBlocks = catBlocks.filter(block => block.fields.hasOwnProperty('BROADCAST_OPTION'));
|
const catMessageBlocks = catBlocks.filter(
|
||||||
|
block => Object.prototype.hasOwnProperty.call(block.fields, 'BROADCAST_OPTION')
|
||||||
|
);
|
||||||
t.equal(catMessageBlocks.length, 2);
|
t.equal(catMessageBlocks.length, 2);
|
||||||
t.equal(catMessageBlocks[0].fields.BROADCAST_OPTION.id, ltPerfectMessageId);
|
t.equal(catMessageBlocks[0].fields.BROADCAST_OPTION.id, ltPerfectMessageId);
|
||||||
t.equal(catMessageBlocks[1].fields.BROADCAST_OPTION.id, abMessageId);
|
t.equal(catMessageBlocks[1].fields.BROADCAST_OPTION.id, abMessageId);
|
||||||
|
|
|
@ -57,7 +57,9 @@ test('importing sb3 project with special chars in message names', t => {
|
||||||
t.equal(allBroadcastFields[ltPerfectMessageId].length, 1);
|
t.equal(allBroadcastFields[ltPerfectMessageId].length, 1);
|
||||||
t.equal(allBroadcastFields[abMessageId].length, 1);
|
t.equal(allBroadcastFields[abMessageId].length, 1);
|
||||||
const catBlocks = Object.keys(cat.blocks._blocks).map(blockId => cat.blocks._blocks[blockId]);
|
const catBlocks = Object.keys(cat.blocks._blocks).map(blockId => cat.blocks._blocks[blockId]);
|
||||||
const catMessageBlocks = catBlocks.filter(block => block.fields.hasOwnProperty('BROADCAST_OPTION'));
|
const catMessageBlocks = catBlocks.filter(
|
||||||
|
block => Object.prototype.hasOwnProperty.call(block.fields, 'BROADCAST_OPTION')
|
||||||
|
);
|
||||||
t.equal(catMessageBlocks.length, 2);
|
t.equal(catMessageBlocks.length, 2);
|
||||||
t.equal(catMessageBlocks[0].fields.BROADCAST_OPTION.id, ltPerfectMessageId);
|
t.equal(catMessageBlocks[0].fields.BROADCAST_OPTION.id, ltPerfectMessageId);
|
||||||
t.equal(catMessageBlocks[1].fields.BROADCAST_OPTION.id, abMessageId);
|
t.equal(catMessageBlocks[1].fields.BROADCAST_OPTION.id, abMessageId);
|
||||||
|
|
|
@ -55,12 +55,12 @@ test('importing sb2 project with special chars in variable names', t => {
|
||||||
// There should be 3 fields, 2 on the stage, and one on the cat
|
// There should be 3 fields, 2 on the stage, and one on the cat
|
||||||
t.equal(allVarListFields[abVarId].length, 3);
|
t.equal(allVarListFields[abVarId].length, 3);
|
||||||
const stageBlocks = Object.keys(stage.blocks._blocks).map(blockId => stage.blocks._blocks[blockId]);
|
const stageBlocks = Object.keys(stage.blocks._blocks).map(blockId => stage.blocks._blocks[blockId]);
|
||||||
const stageListBlocks = stageBlocks.filter(block => block.fields.hasOwnProperty('LIST'));
|
const stageListBlocks = stageBlocks.filter(block => Object.prototype.hasOwnProperty.call(block.fields, 'LIST'));
|
||||||
t.equal(stageListBlocks.length, 2);
|
t.equal(stageListBlocks.length, 2);
|
||||||
t.equal(stageListBlocks[0].fields.LIST.id, abVarId);
|
t.equal(stageListBlocks[0].fields.LIST.id, abVarId);
|
||||||
t.equal(stageListBlocks[1].fields.LIST.id, abVarId);
|
t.equal(stageListBlocks[1].fields.LIST.id, abVarId);
|
||||||
const catBlocks = Object.keys(cat.blocks._blocks).map(blockId => cat.blocks._blocks[blockId]);
|
const catBlocks = Object.keys(cat.blocks._blocks).map(blockId => cat.blocks._blocks[blockId]);
|
||||||
const catListBlocks = catBlocks.filter(block => block.fields.hasOwnProperty('LIST'));
|
const catListBlocks = catBlocks.filter(block => Object.prototype.hasOwnProperty.call(block.fields, 'LIST'));
|
||||||
t.equal(catListBlocks.length, 1);
|
t.equal(catListBlocks.length, 1);
|
||||||
t.equal(catListBlocks[0].fields.LIST.id, abVarId);
|
t.equal(catListBlocks[0].fields.LIST.id, abVarId);
|
||||||
|
|
||||||
|
@ -83,10 +83,12 @@ test('importing sb2 project with special chars in variable names', t => {
|
||||||
// Find all the references for this variable, and verify they have the correct ID
|
// Find all the references for this variable, and verify they have the correct ID
|
||||||
// There should be only two, one on the stage and one on bananas
|
// There should be only two, one on the stage and one on bananas
|
||||||
t.equal(allVarListFields[fooVarId].length, 2);
|
t.equal(allVarListFields[fooVarId].length, 2);
|
||||||
const stageVarBlocks = stageBlocks.filter(block => block.fields.hasOwnProperty('VARIABLE'));
|
const stageVarBlocks = stageBlocks.filter(
|
||||||
|
block => Object.prototype.hasOwnProperty.call(block.fields, 'VARIABLE')
|
||||||
|
);
|
||||||
t.equal(stageVarBlocks.length, 1);
|
t.equal(stageVarBlocks.length, 1);
|
||||||
t.equal(stageVarBlocks[0].fields.VARIABLE.id, fooVarId);
|
t.equal(stageVarBlocks[0].fields.VARIABLE.id, fooVarId);
|
||||||
const catVarBlocks = catBlocks.filter(block => block.fields.hasOwnProperty('VARIABLE'));
|
const catVarBlocks = catBlocks.filter(block => Object.prototype.hasOwnProperty.call(block.fields, 'VARIABLE'));
|
||||||
t.equal(catVarBlocks.length, 1);
|
t.equal(catVarBlocks.length, 1);
|
||||||
t.equal(catVarBlocks[0].fields.VARIABLE.id, fooVarId);
|
t.equal(catVarBlocks[0].fields.VARIABLE.id, fooVarId);
|
||||||
|
|
||||||
|
@ -110,7 +112,9 @@ test('importing sb2 project with special chars in variable names', t => {
|
||||||
// There should be one
|
// There should be one
|
||||||
t.equal(allVarListFields[ltPerfectVarId].length, 1);
|
t.equal(allVarListFields[ltPerfectVarId].length, 1);
|
||||||
const bananasBlocks = Object.keys(bananas.blocks._blocks).map(blockId => bananas.blocks._blocks[blockId]);
|
const bananasBlocks = Object.keys(bananas.blocks._blocks).map(blockId => bananas.blocks._blocks[blockId]);
|
||||||
const bananasVarBlocks = bananasBlocks.filter(block => block.fields.hasOwnProperty('VARIABLE'));
|
const bananasVarBlocks = bananasBlocks.filter(
|
||||||
|
block => Object.prototype.hasOwnProperty.call(block.fields, 'VARIABLE')
|
||||||
|
);
|
||||||
t.equal(bananasVarBlocks.length, 1);
|
t.equal(bananasVarBlocks.length, 1);
|
||||||
t.equal(bananasVarBlocks[0].fields.VARIABLE.id, ltPerfectVarId);
|
t.equal(bananasVarBlocks[0].fields.VARIABLE.id, ltPerfectVarId);
|
||||||
|
|
||||||
|
|
|
@ -55,12 +55,12 @@ test('importing sb3 project with special chars in variable names', t => {
|
||||||
// There should be 3 fields, 2 on the stage, and one on the cat
|
// There should be 3 fields, 2 on the stage, and one on the cat
|
||||||
t.equal(allVarListFields[abVarId].length, 3);
|
t.equal(allVarListFields[abVarId].length, 3);
|
||||||
const stageBlocks = Object.keys(stage.blocks._blocks).map(blockId => stage.blocks._blocks[blockId]);
|
const stageBlocks = Object.keys(stage.blocks._blocks).map(blockId => stage.blocks._blocks[blockId]);
|
||||||
const stageListBlocks = stageBlocks.filter(block => block.fields.hasOwnProperty('LIST'));
|
const stageListBlocks = stageBlocks.filter(block => Object.prototype.hasOwnProperty.call(block.fields, 'LIST'));
|
||||||
t.equal(stageListBlocks.length, 2);
|
t.equal(stageListBlocks.length, 2);
|
||||||
t.equal(stageListBlocks[0].fields.LIST.id, abVarId);
|
t.equal(stageListBlocks[0].fields.LIST.id, abVarId);
|
||||||
t.equal(stageListBlocks[1].fields.LIST.id, abVarId);
|
t.equal(stageListBlocks[1].fields.LIST.id, abVarId);
|
||||||
const catBlocks = Object.keys(cat.blocks._blocks).map(blockId => cat.blocks._blocks[blockId]);
|
const catBlocks = Object.keys(cat.blocks._blocks).map(blockId => cat.blocks._blocks[blockId]);
|
||||||
const catListBlocks = catBlocks.filter(block => block.fields.hasOwnProperty('LIST'));
|
const catListBlocks = catBlocks.filter(block => Object.prototype.hasOwnProperty.call(block.fields, 'LIST'));
|
||||||
t.equal(catListBlocks.length, 1);
|
t.equal(catListBlocks.length, 1);
|
||||||
t.equal(catListBlocks[0].fields.LIST.id, abVarId);
|
t.equal(catListBlocks[0].fields.LIST.id, abVarId);
|
||||||
|
|
||||||
|
@ -83,10 +83,14 @@ test('importing sb3 project with special chars in variable names', t => {
|
||||||
// Find all the references for this variable, and verify they have the correct ID
|
// Find all the references for this variable, and verify they have the correct ID
|
||||||
// There should be only two, one on the stage and one on bananas
|
// There should be only two, one on the stage and one on bananas
|
||||||
t.equal(allVarListFields[fooVarId].length, 2);
|
t.equal(allVarListFields[fooVarId].length, 2);
|
||||||
const stageVarBlocks = stageBlocks.filter(block => block.fields.hasOwnProperty('VARIABLE'));
|
const stageVarBlocks = stageBlocks.filter(
|
||||||
|
block => Object.prototype.hasOwnProperty.call(block.fields, 'VARIABLE')
|
||||||
|
);
|
||||||
t.equal(stageVarBlocks.length, 1);
|
t.equal(stageVarBlocks.length, 1);
|
||||||
t.equal(stageVarBlocks[0].fields.VARIABLE.id, fooVarId);
|
t.equal(stageVarBlocks[0].fields.VARIABLE.id, fooVarId);
|
||||||
const catVarBlocks = catBlocks.filter(block => block.fields.hasOwnProperty('VARIABLE'));
|
const catVarBlocks = catBlocks.filter(
|
||||||
|
block => Object.prototype.hasOwnProperty.call(block.fields, 'VARIABLE')
|
||||||
|
);
|
||||||
t.equal(catVarBlocks.length, 1);
|
t.equal(catVarBlocks.length, 1);
|
||||||
t.equal(catVarBlocks[0].fields.VARIABLE.id, fooVarId);
|
t.equal(catVarBlocks[0].fields.VARIABLE.id, fooVarId);
|
||||||
|
|
||||||
|
@ -110,7 +114,9 @@ test('importing sb3 project with special chars in variable names', t => {
|
||||||
// There should be one
|
// There should be one
|
||||||
t.equal(allVarListFields[ltPerfectVarId].length, 1);
|
t.equal(allVarListFields[ltPerfectVarId].length, 1);
|
||||||
const bananasBlocks = Object.keys(bananas.blocks._blocks).map(blockId => bananas.blocks._blocks[blockId]);
|
const bananasBlocks = Object.keys(bananas.blocks._blocks).map(blockId => bananas.blocks._blocks[blockId]);
|
||||||
const bananasVarBlocks = bananasBlocks.filter(block => block.fields.hasOwnProperty('VARIABLE'));
|
const bananasVarBlocks = bananasBlocks.filter(
|
||||||
|
block => Object.prototype.hasOwnProperty.call(block.fields, 'VARIABLE')
|
||||||
|
);
|
||||||
t.equal(bananasVarBlocks.length, 1);
|
t.equal(bananasVarBlocks.length, 1);
|
||||||
t.equal(bananasVarBlocks[0].fields.VARIABLE.id, ltPerfectVarId);
|
t.equal(bananasVarBlocks[0].fields.VARIABLE.id, ltPerfectVarId);
|
||||||
|
|
||||||
|
|
|
@ -290,8 +290,8 @@ test('wait', t => {
|
||||||
t.equal(yields, 1, 'Second call after timeElapsed does not yield');
|
t.equal(yields, 1, 'Second call after timeElapsed does not yield');
|
||||||
t.equal(waitTime, mockUtil.stackFrame.duration);
|
t.equal(waitTime, mockUtil.stackFrame.duration);
|
||||||
t.ok(timeElapsed >= (waitTime - thresholdSmall),
|
t.ok(timeElapsed >= (waitTime - thresholdSmall),
|
||||||
'Wait block ended too early: ${timeElapsed} < ${waitTime} - ${thresholdSmall}');
|
`Wait block ended too early: ${timeElapsed} < ${waitTime} - ${thresholdSmall}`);
|
||||||
t.ok(timeElapsed <= (waitTime + thresholdLarge),
|
t.ok(timeElapsed <= (waitTime + thresholdLarge),
|
||||||
'Wait block ended too late: ${timeElapsed} > ${waitTime} + ${thresholdLarge}');
|
`Wait block ended too late: ${timeElapsed} > ${waitTime} + ${thresholdLarge}`);
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
|
@ -402,10 +402,10 @@ test('duplicateVariables duplicates all variables', t => {
|
||||||
|
|
||||||
// Should be able to find original var IDs in both this target's variables and
|
// Should be able to find original var IDs in both this target's variables and
|
||||||
// the duplicate variables since a blocks container was not specified.
|
// the duplicate variables since a blocks container was not specified.
|
||||||
t.equal(target.variables.hasOwnProperty('var ID 1'), true);
|
t.equal(Object.prototype.hasOwnProperty.call(target.variables, 'var ID 1'), true);
|
||||||
t.equal(target.variables.hasOwnProperty('var ID 2'), true);
|
t.equal(Object.prototype.hasOwnProperty.call(target.variables, 'var ID 2'), true);
|
||||||
t.equal(duplicateVariables.hasOwnProperty('var ID 1'), true);
|
t.equal(Object.prototype.hasOwnProperty.call(duplicateVariables, 'var ID 1'), true);
|
||||||
t.equal(duplicateVariables.hasOwnProperty('var ID 1'), true);
|
t.equal(Object.prototype.hasOwnProperty.call(duplicateVariables, 'var ID 1'), true);
|
||||||
|
|
||||||
// Values of the duplicate varaiables should match the value of the original values at the time of duplication
|
// Values of the duplicate varaiables should match the value of the original values at the time of duplication
|
||||||
t.equal(target.variables['var ID 1'].value, duplicateVariables['var ID 1'].value);
|
t.equal(target.variables['var ID 1'].value, duplicateVariables['var ID 1'].value);
|
||||||
|
|
|
@ -142,11 +142,11 @@ const testReporter = function (t, reporter) {
|
||||||
t.equal(reporter.json.checkboxInFlyout, true);
|
t.equal(reporter.json.checkboxInFlyout, true);
|
||||||
t.equal(reporter.json.outputShape, ScratchBlocksConstants.OUTPUT_SHAPE_ROUND);
|
t.equal(reporter.json.outputShape, ScratchBlocksConstants.OUTPUT_SHAPE_ROUND);
|
||||||
t.equal(reporter.json.output, 'String');
|
t.equal(reporter.json.output, 'String');
|
||||||
t.notOk(reporter.json.hasOwnProperty('previousStatement'));
|
t.notOk(Object.prototype.hasOwnProperty.call(reporter.json, 'previousStatement'));
|
||||||
t.notOk(reporter.json.hasOwnProperty('nextStatement'));
|
t.notOk(Object.prototype.hasOwnProperty.call(reporter.json, 'nextStatement'));
|
||||||
t.same(reporter.json.extensions, ['scratch_extension']);
|
t.same(reporter.json.extensions, ['scratch_extension']);
|
||||||
t.equal(reporter.json.message0, '%1 %2simple text'); // "%1 %2" from the block icon
|
t.equal(reporter.json.message0, '%1 %2simple text'); // "%1 %2" from the block icon
|
||||||
t.notOk(reporter.json.hasOwnProperty('message1'));
|
t.notOk(Object.prototype.hasOwnProperty.call(reporter.json, 'message1'));
|
||||||
t.same(reporter.json.args0, [
|
t.same(reporter.json.args0, [
|
||||||
// %1 in message0: the block icon
|
// %1 in message0: the block icon
|
||||||
{
|
{
|
||||||
|
@ -160,7 +160,7 @@ const testReporter = function (t, reporter) {
|
||||||
type: 'field_vertical_separator'
|
type: 'field_vertical_separator'
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
t.notOk(reporter.json.hasOwnProperty('args1'));
|
t.notOk(Object.prototype.hasOwnProperty.call(reporter.json, 'args1'));
|
||||||
t.equal(reporter.xml, '<block type="test_reporter"></block>');
|
t.equal(reporter.xml, '<block type="test_reporter"></block>');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -170,11 +170,11 @@ const testInlineImage = function (t, inlineImage) {
|
||||||
t.equal(inlineImage.json.checkboxInFlyout, true);
|
t.equal(inlineImage.json.checkboxInFlyout, true);
|
||||||
t.equal(inlineImage.json.outputShape, ScratchBlocksConstants.OUTPUT_SHAPE_ROUND);
|
t.equal(inlineImage.json.outputShape, ScratchBlocksConstants.OUTPUT_SHAPE_ROUND);
|
||||||
t.equal(inlineImage.json.output, 'String');
|
t.equal(inlineImage.json.output, 'String');
|
||||||
t.notOk(inlineImage.json.hasOwnProperty('previousStatement'));
|
t.notOk(Object.prototype.hasOwnProperty.call(inlineImage.json, 'previousStatement'));
|
||||||
t.notOk(inlineImage.json.hasOwnProperty('nextStatement'));
|
t.notOk(Object.prototype.hasOwnProperty.call(inlineImage.json, 'nextStatement'));
|
||||||
t.notOk(inlineImage.json.extensions && inlineImage.json.extensions.length); // OK if it's absent or empty
|
t.notOk(inlineImage.json.extensions && inlineImage.json.extensions.length); // OK if it's absent or empty
|
||||||
t.equal(inlineImage.json.message0, 'text and %1'); // block text followed by inline image
|
t.equal(inlineImage.json.message0, 'text and %1'); // block text followed by inline image
|
||||||
t.notOk(inlineImage.json.hasOwnProperty('message1'));
|
t.notOk(Object.prototype.hasOwnProperty.call(inlineImage.json, 'message1'));
|
||||||
t.same(inlineImage.json.args0, [
|
t.same(inlineImage.json.args0, [
|
||||||
// %1 in message0: the block icon
|
// %1 in message0: the block icon
|
||||||
{
|
{
|
||||||
|
@ -185,7 +185,7 @@ const testInlineImage = function (t, inlineImage) {
|
||||||
flip_rtl: false // False by default
|
flip_rtl: false // False by default
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
t.notOk(inlineImage.json.hasOwnProperty('args1'));
|
t.notOk(Object.prototype.hasOwnProperty.call(inlineImage.json, 'args1'));
|
||||||
t.equal(inlineImage.xml, '<block type="test_inlineImage"></block>');
|
t.equal(inlineImage.xml, '<block type="test_inlineImage"></block>');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -198,16 +198,16 @@ const testCommand = function (t, command) {
|
||||||
t.equal(command.json.type, 'test_command');
|
t.equal(command.json.type, 'test_command');
|
||||||
testCategoryInfo(t, command);
|
testCategoryInfo(t, command);
|
||||||
t.equal(command.json.outputShape, ScratchBlocksConstants.OUTPUT_SHAPE_SQUARE);
|
t.equal(command.json.outputShape, ScratchBlocksConstants.OUTPUT_SHAPE_SQUARE);
|
||||||
t.assert(command.json.hasOwnProperty('previousStatement'));
|
t.assert(Object.prototype.hasOwnProperty.call(command.json, 'previousStatement'));
|
||||||
t.assert(command.json.hasOwnProperty('nextStatement'));
|
t.assert(Object.prototype.hasOwnProperty.call(command.json, 'nextStatement'));
|
||||||
t.notOk(command.json.extensions && command.json.extensions.length); // OK if it's absent or empty
|
t.notOk(command.json.extensions && command.json.extensions.length); // OK if it's absent or empty
|
||||||
t.equal(command.json.message0, 'text with %1 %2');
|
t.equal(command.json.message0, 'text with %1 %2');
|
||||||
t.notOk(command.json.hasOwnProperty('message1'));
|
t.notOk(Object.prototype.hasOwnProperty.call(command.json, 'message1'));
|
||||||
t.strictSame(command.json.args0[0], {
|
t.strictSame(command.json.args0[0], {
|
||||||
type: 'input_value',
|
type: 'input_value',
|
||||||
name: 'ARG'
|
name: 'ARG'
|
||||||
});
|
});
|
||||||
t.notOk(command.json.hasOwnProperty('args1'));
|
t.notOk(Object.prototype.hasOwnProperty.call(command.json, 'args1'));
|
||||||
t.equal(command.xml,
|
t.equal(command.xml,
|
||||||
'<block type="test_command"><value name="ARG"><shadow type="text"></shadow></value>' +
|
'<block type="test_command"><value name="ARG"><shadow type="text"></shadow></value>' +
|
||||||
'<value name="ARG_WITH_DEFAULT"><shadow type="text"><field name="TEXT">' +
|
'<value name="ARG_WITH_DEFAULT"><shadow type="text"><field name="TEXT">' +
|
||||||
|
@ -218,14 +218,14 @@ const testConditional = function (t, conditional) {
|
||||||
t.equal(conditional.json.type, 'test_ifElse');
|
t.equal(conditional.json.type, 'test_ifElse');
|
||||||
testCategoryInfo(t, conditional);
|
testCategoryInfo(t, conditional);
|
||||||
t.equal(conditional.json.outputShape, ScratchBlocksConstants.OUTPUT_SHAPE_SQUARE);
|
t.equal(conditional.json.outputShape, ScratchBlocksConstants.OUTPUT_SHAPE_SQUARE);
|
||||||
t.ok(conditional.json.hasOwnProperty('previousStatement'));
|
t.ok(Object.prototype.hasOwnProperty.call(conditional.json, 'previousStatement'));
|
||||||
t.ok(conditional.json.hasOwnProperty('nextStatement'));
|
t.ok(Object.prototype.hasOwnProperty.call(conditional.json, 'nextStatement'));
|
||||||
t.notOk(conditional.json.extensions && conditional.json.extensions.length); // OK if it's absent or empty
|
t.notOk(conditional.json.extensions && conditional.json.extensions.length); // OK if it's absent or empty
|
||||||
t.equal(conditional.json.message0, 'test if %1 is spiffy and if so then');
|
t.equal(conditional.json.message0, 'test if %1 is spiffy and if so then');
|
||||||
t.equal(conditional.json.message1, '%1'); // placeholder for substack #1
|
t.equal(conditional.json.message1, '%1'); // placeholder for substack #1
|
||||||
t.equal(conditional.json.message2, 'or elsewise');
|
t.equal(conditional.json.message2, 'or elsewise');
|
||||||
t.equal(conditional.json.message3, '%1'); // placeholder for substack #2
|
t.equal(conditional.json.message3, '%1'); // placeholder for substack #2
|
||||||
t.notOk(conditional.json.hasOwnProperty('message4'));
|
t.notOk(Object.prototype.hasOwnProperty.call(conditional.json, 'message4'));
|
||||||
t.strictSame(conditional.json.args0[0], {
|
t.strictSame(conditional.json.args0[0], {
|
||||||
type: 'input_value',
|
type: 'input_value',
|
||||||
name: 'THING',
|
name: 'THING',
|
||||||
|
@ -235,12 +235,12 @@ const testConditional = function (t, conditional) {
|
||||||
type: 'input_statement',
|
type: 'input_statement',
|
||||||
name: 'SUBSTACK'
|
name: 'SUBSTACK'
|
||||||
});
|
});
|
||||||
t.notOk(conditional.json.hasOwnProperty(conditional.json.args2));
|
t.notOk(Object.prototype.hasOwnProperty.call(conditional.json, conditional.json.args2));
|
||||||
t.strictSame(conditional.json.args3[0], {
|
t.strictSame(conditional.json.args3[0], {
|
||||||
type: 'input_statement',
|
type: 'input_statement',
|
||||||
name: 'SUBSTACK2'
|
name: 'SUBSTACK2'
|
||||||
});
|
});
|
||||||
t.notOk(conditional.json.hasOwnProperty('args4'));
|
t.notOk(Object.prototype.hasOwnProperty.call(conditional.json, 'args4'));
|
||||||
t.equal(conditional.xml, '<block type="test_ifElse"><value name="THING"></value></block>');
|
t.equal(conditional.xml, '<block type="test_ifElse"><value name="THING"></value></block>');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -248,13 +248,13 @@ const testLoop = function (t, loop) {
|
||||||
t.equal(loop.json.type, 'test_loop');
|
t.equal(loop.json.type, 'test_loop');
|
||||||
testCategoryInfo(t, loop);
|
testCategoryInfo(t, loop);
|
||||||
t.equal(loop.json.outputShape, ScratchBlocksConstants.OUTPUT_SHAPE_SQUARE);
|
t.equal(loop.json.outputShape, ScratchBlocksConstants.OUTPUT_SHAPE_SQUARE);
|
||||||
t.ok(loop.json.hasOwnProperty('previousStatement'));
|
t.ok(Object.prototype.hasOwnProperty.call(loop.json, 'previousStatement'));
|
||||||
t.notOk(loop.json.hasOwnProperty('nextStatement')); // isTerminal is set on this block
|
t.notOk(Object.prototype.hasOwnProperty.call(loop.json, 'nextStatement')); // isTerminal is set on this block
|
||||||
t.notOk(loop.json.extensions && loop.json.extensions.length); // OK if it's absent or empty
|
t.notOk(loop.json.extensions && loop.json.extensions.length); // OK if it's absent or empty
|
||||||
t.equal(loop.json.message0, 'loopty %1 loops');
|
t.equal(loop.json.message0, 'loopty %1 loops');
|
||||||
t.equal(loop.json.message1, '%1'); // placeholder for substack
|
t.equal(loop.json.message1, '%1'); // placeholder for substack
|
||||||
t.equal(loop.json.message2, '%1'); // placeholder for loop arrow
|
t.equal(loop.json.message2, '%1'); // placeholder for loop arrow
|
||||||
t.notOk(loop.json.hasOwnProperty('message3'));
|
t.notOk(Object.prototype.hasOwnProperty.call(loop.json, 'message3'));
|
||||||
t.strictSame(loop.json.args0[0], {
|
t.strictSame(loop.json.args0[0], {
|
||||||
type: 'input_value',
|
type: 'input_value',
|
||||||
name: 'MANY'
|
name: 'MANY'
|
||||||
|
@ -266,7 +266,7 @@ const testLoop = function (t, loop) {
|
||||||
t.equal(loop.json.lastDummyAlign2, 'RIGHT'); // move loop arrow to right side
|
t.equal(loop.json.lastDummyAlign2, 'RIGHT'); // move loop arrow to right side
|
||||||
t.equal(loop.json.args2[0].type, 'field_image');
|
t.equal(loop.json.args2[0].type, 'field_image');
|
||||||
t.equal(loop.json.args2[0].flip_rtl, true);
|
t.equal(loop.json.args2[0].flip_rtl, true);
|
||||||
t.notOk(loop.json.hasOwnProperty('args3'));
|
t.notOk(Object.prototype.hasOwnProperty.call(loop.json, 'args3'));
|
||||||
t.equal(loop.xml,
|
t.equal(loop.xml,
|
||||||
'<block type="test_loop"><value name="MANY"><shadow type="math_number"></shadow></value></block>');
|
'<block type="test_loop"><value name="MANY"><shadow type="math_number"></shadow></value></block>');
|
||||||
};
|
};
|
||||||
|
|
|
@ -40,7 +40,7 @@ test('blocks get new id on duplicate', t => {
|
||||||
rt.blocks.createBlock(block);
|
rt.blocks.createBlock(block);
|
||||||
|
|
||||||
return rt.duplicate().then(duplicate => {
|
return rt.duplicate().then(duplicate => {
|
||||||
t.notOk(duplicate.blocks._blocks.hasOwnProperty(block.id));
|
t.notOk(Object.prototype.hasOwnProperty.call(duplicate.blocks._blocks, block.id));
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue