Merge pull request #4151 from scratchfoundation/renovate/major-eslint-config-scratch

chore(deps): update eslint-config-scratch (major)
This commit is contained in:
Christopher Willis-Ford 2023-12-15 17:46:53 -08:00 committed by GitHub
commit ef86783a79
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 3610 additions and 2520 deletions

5691
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -74,8 +74,8 @@
"callsite": "1.0.0",
"copy-webpack-plugin": "4.5.4",
"docdash": "1.2.0",
"eslint": "5.3.0",
"eslint-config-scratch": "5.1.0",
"eslint": "8.55.0",
"eslint-config-scratch": "9.0.3",
"expose-loader": "0.7.5",
"file-loader": "2.0.0",
"format-message-cli": "6.2.0",

View file

@ -540,7 +540,7 @@ class Scratch3LooksBlocks {
changeEffect (args, util) {
const effect = Cast.toString(args.EFFECT).toLowerCase();
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];
newValue = this.clampEffect(effect, newValue);
util.target.setEffect(effect, newValue);

View file

@ -43,7 +43,7 @@ class Scratch3ProcedureBlocks {
// at earlier stack frames for the values of a given parameter (#1729)
util.initParams();
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]]);
} else {
util.pushParam(paramNames[i], paramDefaults[i]);

View file

@ -267,7 +267,7 @@ class Scratch3SoundBlocks {
const value = Cast.toNumber(args.VALUE);
const soundState = this._getSoundState(util.target);
if (!soundState.effects.hasOwnProperty(effect)) return;
if (!Object.prototype.hasOwnProperty.call(soundState.effects, effect)) return;
if (change) {
soundState.effects[effect] += value;
@ -297,7 +297,7 @@ class Scratch3SoundBlocks {
_clearEffectsForTarget (target) {
const soundState = this._getSoundState(target);
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;
}
this._syncEffectsForTarget(target);

View file

@ -50,6 +50,8 @@ class CentralDispatch extends SharedDispatch {
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);
}
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.
*/
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}`);
}
this.services[service] = provider;

View file

@ -82,6 +82,8 @@ class SharedDispatch {
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);
return Promise.resolve(result);
}

View file

@ -58,7 +58,7 @@ class WorkerDispatch extends SharedDispatch {
* @returns {Promise} - a promise which will resolve once the service is registered.
*/
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}`);
}
this.services[service] = provider;

View file

@ -153,7 +153,7 @@ const domToBlocks = function (blocksDOM) {
// Flatten blocks object into a list.
const blocksList = [];
for (const b in blocks) {
if (!blocks.hasOwnProperty(b)) continue;
if (!Object.prototype.hasOwnProperty.call(blocks, b)) continue;
blocksList.push(blocks[b]);
}
return blocksList;

View file

@ -232,6 +232,8 @@ class BlockUtility {
this.sequencer.runtime.ioDevices[device] &&
this.sequencer.runtime.ioDevices[device][func]) {
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);
}
}

View file

@ -44,7 +44,7 @@ class RuntimeScriptCache {
if (Object.keys(fields).length === 0) {
const inputs = container.getInputs(block);
for (const input in inputs) {
if (!inputs.hasOwnProperty(input)) continue;
if (!Object.prototype.hasOwnProperty.call(inputs, input)) continue;
const id = inputs[input].block;
const inputBlock = container.getBlock(id);
const inputFields = container.getFields(inputBlock);

View file

@ -231,7 +231,7 @@ class 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];
if (block.opcode === 'procedures_definition') {
const internal = this._getCustomBlockInternal(block);
@ -267,7 +267,7 @@ class 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];
if (block.opcode === 'procedures_prototype' &&
block.mutation.proccode === name) {
@ -357,7 +357,7 @@ class Blocks {
case 'delete':
// Don't accept delete events for missing blocks,
// 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) {
return;
}
@ -397,7 +397,7 @@ class Blocks {
}
break;
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
editingTarget.renameVariable(e.varId, e.newName);
// Update all the blocks on the current target that use
@ -416,7 +416,7 @@ class Blocks {
this.emitProjectChanged();
break;
case 'var_delete': {
const target = (editingTarget && editingTarget.variables.hasOwnProperty(e.varId)) ?
const target = (editingTarget && Object.prototype.hasOwnProperty.call(editingTarget.variables, e.varId)) ?
editingTarget : stage;
target.deleteVariable(e.varId);
this.emitProjectChanged();
@ -445,20 +445,21 @@ class Blocks {
case 'comment_change':
if (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.`);
return;
}
const comment = currTarget.comments[e.commentId];
const change = e.newContents_;
if (change.hasOwnProperty('minimized')) {
if (Object.prototype.hasOwnProperty.call(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.height = change.height;
}
if (change.hasOwnProperty('text')) {
if (Object.prototype.hasOwnProperty.call(change, 'text')) {
comment.text = change.text;
}
this.emitProjectChanged();
@ -467,7 +468,7 @@ class Blocks {
case 'comment_move':
if (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.`);
return;
}
@ -482,7 +483,7 @@ class Blocks {
case 'comment_delete':
if (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
// a delete event from a workspace that we switched from
// (e.g. a delete event for a comment on sprite a's workspace
@ -536,7 +537,7 @@ class Blocks {
createBlock (block) {
// Does the block already exist?
// Could happen, e.g., for an unobscured shadow.
if (this._blocks.hasOwnProperty(block.id)) {
if (Object.prototype.hasOwnProperty.call(this._blocks, block.id)) {
return;
}
// Create new block.
@ -650,7 +651,7 @@ class Blocks {
}
const isSpriteSpecific = isSpriteLocalVariable ||
(this.runtime.monitorBlockInfo.hasOwnProperty(block.opcode) &&
(Object.prototype.hasOwnProperty.call(this.runtime.monitorBlockInfo, block.opcode) &&
this.runtime.monitorBlockInfo[block.opcode].isSpriteSpecific);
if (isSpriteSpecific) {
// 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
*/
moveBlock (e) {
if (!this._blocks.hasOwnProperty(e.id)) {
if (!Object.prototype.hasOwnProperty.call(this._blocks, e.id)) {
return;
}
@ -740,7 +741,7 @@ class Blocks {
// Moved to the new parent's input.
// Don't obscure the shadow block.
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;
}
@ -990,7 +991,7 @@ class Blocks {
*/
_getCostumeField (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 null;
@ -1005,7 +1006,7 @@ class Blocks {
*/
_getSoundField (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 null;
@ -1020,7 +1021,7 @@ class Blocks {
*/
_getBackdropField (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 null;
@ -1042,7 +1043,7 @@ class Blocks {
'DISTANCETOMENU', 'TOUCHINGOBJECTMENU', 'CLONE_OPTION'];
for (let i = 0; i < spriteMenuNames.length; i++) {
const menuName = spriteMenuNames[i];
if (block.fields.hasOwnProperty(menuName)) {
if (Object.prototype.hasOwnProperty.call(block.fields, menuName)) {
return block.fields[menuName];
}
}
@ -1085,7 +1086,7 @@ class Blocks {
const commentId = block.comment;
if (commentId) {
if (comments) {
if (comments.hasOwnProperty(commentId)) {
if (Object.prototype.hasOwnProperty.call(comments, commentId)) {
xmlString += comments[commentId].toXML();
} else {
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.
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];
// Only encode a value tag if the value input is occupied.
if (blockInput.block || blockInput.shadow) {
@ -1117,7 +1118,7 @@ class Blocks {
}
// Add any fields on this block.
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];
xmlString += `<field name="${blockField.name}"`;
const fieldId = blockField.id;

View file

@ -764,14 +764,14 @@ class Runtime extends EventEmitter {
*/
_registerBlockPackages () {
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?
const packageObject = new (defaultBlockPackages[packageName])(this);
// Collect primitives from package.
if (packageObject.getPrimitives) {
const packagePrimitives = packageObject.getPrimitives();
for (const op in packagePrimitives) {
if (packagePrimitives.hasOwnProperty(op)) {
if (Object.prototype.hasOwnProperty.call(packagePrimitives, op)) {
this._primitives[op] =
packagePrimitives[op].bind(packageObject);
}
@ -781,7 +781,7 @@ class Runtime extends EventEmitter {
if (packageObject.getHats) {
const packageHats = packageObject.getHats();
for (const hatName in packageHats) {
if (packageHats.hasOwnProperty(hatName)) {
if (Object.prototype.hasOwnProperty.call(packageHats, hatName)) {
this._hats[hatName] = packageHats[hatName];
}
}
@ -851,7 +851,7 @@ class Runtime extends EventEmitter {
this._fillExtensionCategory(categoryInfo, extensionInfo);
for (const fieldTypeName in categoryInfo.customFieldTypes) {
if (extensionInfo.customFieldTypes.hasOwnProperty(fieldTypeName)) {
if (Object.prototype.hasOwnProperty.call(extensionInfo.customFieldTypes, fieldTypeName)) {
const fieldTypeInfo = categoryInfo.customFieldTypes[fieldTypeName];
// Emit events for custom field types from extension
@ -894,7 +894,7 @@ class Runtime extends EventEmitter {
categoryInfo.menuInfo = {};
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 convertedMenu = this._buildMenuForScratchBlocks(menuName, menuInfo, categoryInfo);
categoryInfo.menus.push(convertedMenu);
@ -902,7 +902,7 @@ class Runtime extends EventEmitter {
}
}
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 fieldTypeInfo = this._buildCustomFieldInfo(
fieldTypeName,
@ -1138,7 +1138,7 @@ class Runtime extends EventEmitter {
break;
case BlockType.HAT:
case BlockType.EVENT:
if (!blockInfo.hasOwnProperty('isEdgeActivated')) {
if (!Object.prototype.hasOwnProperty.call(blockInfo, 'isEdgeActivated')) {
// if absent, this property defaults to true
blockInfo.isEdgeActivated = true;
}
@ -1584,7 +1584,7 @@ class Runtime extends EventEmitter {
* @return {boolean} True if the op is known to be a hat.
*/
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.
*/
getIsEdgeActivatedHat (opcode) {
return this._hats.hasOwnProperty(opcode) &&
return Object.prototype.hasOwnProperty.call(this._hats, opcode) &&
this._hats[opcode].edgeActivated;
}
@ -1817,7 +1817,7 @@ class Runtime extends EventEmitter {
*/
startHats (requestedHatOpcode,
optMatchFields, optTarget) {
if (!this._hats.hasOwnProperty(requestedHatOpcode)) {
if (!Object.prototype.hasOwnProperty.call(this._hats, requestedHatOpcode)) {
// No known hat with this opcode.
return;
}
@ -1827,7 +1827,7 @@ class Runtime extends EventEmitter {
const hatMeta = instance._hats[requestedHatOpcode];
for (const opts in optMatchFields) {
if (!optMatchFields.hasOwnProperty(opts)) continue;
if (!Object.prototype.hasOwnProperty.call(optMatchFields, opts)) continue;
optMatchFields[opts] = optMatchFields[opts].toUpperCase();
}
@ -2062,7 +2062,7 @@ class Runtime extends EventEmitter {
const newTargets = [];
for (let i = 0; i < this.targets.length; i++) {
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].dispose();
} else {
@ -2097,7 +2097,7 @@ class Runtime extends EventEmitter {
// Find all edge-activated hats, and add them to threads to be evaluated.
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];
if (hat.edgeActivated) {
this.startHats(hatType);
@ -2211,9 +2211,9 @@ class Runtime extends EventEmitter {
*/
_updateGlows (optExtraThreads) {
const searchThreads = [];
searchThreads.push.apply(searchThreads, this.threads);
searchThreads.push(...this.threads);
if (optExtraThreads) {
searchThreads.push.apply(searchThreads, optExtraThreads);
searchThreads.push(...optExtraThreads);
}
// Set of scripts that request a glow this frame.
const requestedGlowsThisFrame = [];

View file

@ -101,7 +101,7 @@ class Target extends EventEmitter {
}
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) {
// 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];
}
// If the stage has a global copy, return it.
if (this.runtime && !this.isStage) {
const stage = this.runtime.getTargetForStage();
if (stage && stage.variables.hasOwnProperty(id)) {
if (stage && Object.prototype.hasOwnProperty.call(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.
*/
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);
if (isCloud && this.isStage && this.runtime.canAddCloudVariable()) {
newVariable.isCloud = true;
@ -288,7 +288,7 @@ class Target extends EventEmitter {
* @param {boolean} minimized Whether the comment is 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,
width, height, minimized);
if (blockId) {
@ -311,7 +311,7 @@ class Target extends EventEmitter {
* @param {string} newName New name for the variable.
*/
renameVariable (id, newName) {
if (this.variables.hasOwnProperty(id)) {
if (Object.prototype.hasOwnProperty.call(this.variables, id)) {
const variable = this.variables[id];
if (variable.id === id) {
const oldName = variable.name;
@ -362,7 +362,7 @@ class Target extends EventEmitter {
* @param {string} id Id of variable to delete.
*/
deleteVariable (id) {
if (this.variables.hasOwnProperty(id)) {
if (Object.prototype.hasOwnProperty.call(this.variables, id)) {
// Get info about the variable before deleting it
const deletedVariableName = this.variables[id].name;
const deletedVariableWasCloud = this.variables[id].isCloud;
@ -408,7 +408,7 @@ class Target extends EventEmitter {
* the original variable was not found.
*/
duplicateVariable (id, optKeepOriginalId) {
if (this.variables.hasOwnProperty(id)) {
if (Object.prototype.hasOwnProperty.call(this.variables, id)) {
const originalVariable = this.variables[id];
const newVariable = new Variable(
optKeepOriginalId ? id : null, // conditionally keep original id or generate a new one
@ -695,7 +695,7 @@ class Target extends EventEmitter {
const unreferencedLocalVarIds = [];
if (Object.keys(this.variables).length > 0) {
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);
}
}
@ -720,7 +720,7 @@ class Target extends EventEmitter {
if (this.lookupVariableById(varId)) {
// Found a variable with the id in either the target or the stage,
// 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
// has one with the same name and type. If it does, then rename
// this target specific variable so that there is a distinction.

View file

@ -353,7 +353,7 @@ class Thread {
if (frame.params === null) {
continue;
}
if (frame.params.hasOwnProperty(paramName)) {
if (Object.prototype.hasOwnProperty.call(frame.params, paramName)) {
return frame.params[paramName];
}
return null;

View file

@ -116,7 +116,7 @@ class ExtensionManager {
* @param {string} extensionId - the ID of an internal extension
*/
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.`);
return;
}
@ -140,7 +140,7 @@ class ExtensionManager {
* @returns {Promise} resolved once the extension is loaded and initialized or rejected on failure
*/
loadExtensionURL (extensionURL) {
if (builtinExtensions.hasOwnProperty(extensionURL)) {
if (Object.prototype.hasOwnProperty.call(builtinExtensions, extensionURL)) {
/** @TODO dupe handling for non-builtin extensions. See commit 670e51d33580e8a2e852b3b038bb3afc282f81b9 */
if (this.isExtensionLoaded(extensionURL)) {
const message = `Rejecting attempt to load a second extension with ID ${extensionURL}`;

View file

@ -368,7 +368,7 @@ class Scratch3MakeyMakeyBlocks {
*/
addSequence (sequenceString, sequenceArray) {
// If we already have this sequence string, return.
if (this.sequences.hasOwnProperty(sequenceString)) {
if (Object.prototype.hasOwnProperty.call(this.sequences, sequenceString)) {
return;
}
this.sequences[sequenceString] = {

View file

@ -569,7 +569,7 @@ class Scratch3PenBlocks {
penState.color = (hsv.h / 360) * 100;
penState.saturation = hsv.s * 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));
} else {
penState.transparency = 0;

View file

@ -222,11 +222,11 @@ class Scratch3TranslateBlocks {
getLanguageCodeFromArg (arg) {
const languageArg = Cast.toString(arg).toLowerCase();
// 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;
}
// 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];
}

View file

@ -167,7 +167,6 @@ class Scratch3VideoSensingBlocks {
if (stage) {
stage.videoTransparency = transparency;
}
return transparency;
}
/**
@ -191,7 +190,6 @@ class Scratch3VideoSensingBlocks {
if (stage) {
stage.videoState = state;
}
return state;
}
/**

View file

@ -10,7 +10,7 @@ const loadVector_ = function (costume, runtime, rotationCenter, optVersion) {
// scratch-svg-renderer fixes syntax that causes loading issues,
// and if optVersion is 2, fixes "quirks" associated with Scratch 2 SVGs,
const fixedSvgString = serializeSvgToString(loadSvgString(svgString, true /* fromVersion2 */));
// If the string changed, put back into storage
if (svgString !== fixedSvgString) {
svgString = fixedSvgString;
@ -100,9 +100,13 @@ const canvasPool = (function () {
*/
const fetchBitmapCanvas_ = function (costume, runtime, rotationCenter) {
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.');
}
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.');
}
@ -125,6 +129,8 @@ const fetchBitmapCanvas_ = function (costume, runtime, rotationCenter) {
image.onerror = null;
};
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.');
image.onload = null;
image.onerror = null;
@ -194,6 +200,8 @@ const loadBitmap_ = function (costume, runtime, _rotationCenter) {
// somewhere and act on that error (like logging).
//
// 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.');
}
@ -261,14 +269,14 @@ const handleCostumeLoadError = function (costume, runtime) {
const AssetType = runtime.storage.AssetType;
const isVector = costume.dataFormat === AssetType.ImageVector.runtimeFormat;
// Use default asset if original fails to load
costume.assetId = isVector ?
runtime.storage.defaultAssetId.ImageVector :
runtime.storage.defaultAssetId.ImageBitmap;
costume.asset = runtime.storage.get(costume.assetId);
costume.md5 = `${costume.assetId}.${costume.asset.dataFormat}`;
const defaultCostumePromise = (isVector) ?
loadVector_(costume, runtime) : loadBitmap_(costume, runtime);
@ -280,7 +288,7 @@ const handleCostumeLoadError = function (costume, runtime) {
// Should be null if we got here because the costume was missing
loadedCostume.broken.asset = oldAsset;
loadedCostume.broken.dataFormat = oldDataFormat;
loadedCostume.broken.rotationCenterX = oldRotationX;
loadedCostume.broken.rotationCenterY = oldRotationY;
loadedCostume.broken.bitmapResolution = oldBitmapResolution;
@ -322,7 +330,7 @@ const loadCostumeFromAsset = function (costume, runtime, optVersion) {
.catch(error => {
log.warn(`Error loading vector image: ${error}`);
return handleCostumeLoadError(costume, runtime);
});
}
return loadBitmap_(costume, runtime, rotationCenter, optVersion)

View file

@ -42,7 +42,7 @@ class Mouse {
const drawableID = this.runtime.renderer.pick(x, y);
for (let i = 0; i < this.runtime.targets.length; i++) {
const target = this.runtime.targets[i];
if (target.hasOwnProperty('drawableID') &&
if (Object.prototype.hasOwnProperty.call(target, 'drawableID') &&
target.drawableID === drawableID) {
return target;
}

View file

@ -288,7 +288,7 @@ const parseMonitorObject = (object, runtime, targets, extensions) => {
let target = null;
// List blocks don't come in with their target name set.
// 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++) {
const currTarget = targets[i];
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);
} else if (object.cmd === 'contentsOfList:') {
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);
} else {
// If the opcode can't be found in the runtime monitorBlockInfo,
@ -405,7 +405,7 @@ const parseMonitorObject = (object, runtime, targets, extensions) => {
* objects.
*/
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.
return null;
}
@ -419,7 +419,7 @@ const parseScratchAssets = function (object, runtime, topLevel, zip) {
// Costumes from JSON.
const costumePromises = assets.costumePromises;
if (object.hasOwnProperty('costumes')) {
if (Object.prototype.hasOwnProperty.call(object, 'costumes')) {
for (let i = 0; i < object.costumes.length; i++) {
const costumeSource = object.costumes[i];
const bitmapResolution = costumeSource.bitmapResolution || 1;
@ -464,7 +464,7 @@ const parseScratchAssets = function (object, runtime, topLevel, zip) {
}
// Sounds from JSON
const {soundBank, soundPromises} = assets;
if (object.hasOwnProperty('sounds')) {
if (Object.prototype.hasOwnProperty.call(object, 'sounds')) {
for (let s = 0; s < object.sounds.length; s++) {
const soundSource = object.sounds[s];
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.
*/
const parseScratchObject = function (object, runtime, extensions, topLevel, zip, assets) {
if (!object.hasOwnProperty('objName')) {
if (object.hasOwnProperty('listName')) {
if (!Object.prototype.hasOwnProperty.call(object, 'objName')) {
if (Object.prototype.hasOwnProperty.call(object, 'listName')) {
// Shim these objects so they can be processed as monitors
object.cmd = 'contentsOfList:';
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.
const sprite = new Sprite(blocks, runtime);
// Sprite/stage name from JSON.
if (object.hasOwnProperty('objName')) {
if (Object.prototype.hasOwnProperty.call(object, 'objName')) {
if (topLevel && object.objName !== 'Stage') {
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';
}
}
@ -566,7 +566,7 @@ const parseScratchObject = function (object, runtime, extensions, topLevel, zip,
const addBroadcastMsg = globalBroadcastMsgObj.broadcastMsgMapUpdater;
// 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++) {
const variable = object.variables[j];
// 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
// workspace comments as well as comments attached to specific blocks)
const blockComments = {};
if (object.hasOwnProperty('scriptComments')) {
if (Object.prototype.hasOwnProperty.call(object, 'scriptComments')) {
const comments = object.scriptComments.map(commentDesc => {
const [
commentX,
@ -624,7 +624,7 @@ const parseScratchObject = function (object, runtime, extensions, topLevel, zip,
newComment.blockId = flattenedBlockIndex;
// Add this comment to the block comments object with its script index
// as the key
if (blockComments.hasOwnProperty(flattenedBlockIndex)) {
if (Object.prototype.hasOwnProperty.call(blockComments, flattenedBlockIndex)) {
blockComments[flattenedBlockIndex].push(newComment);
} else {
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 (object.hasOwnProperty('scripts')) {
if (Object.prototype.hasOwnProperty.call(object, 'scripts')) {
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)
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++) {
const list = object.lists[k];
const newVariable = new Variable(
@ -677,34 +677,34 @@ const parseScratchObject = function (object, runtime, extensions, topLevel, zip,
target.variables[newVariable.id] = newVariable;
}
}
if (object.hasOwnProperty('scratchX')) {
if (Object.prototype.hasOwnProperty.call(object, 'scratchX')) {
target.x = object.scratchX;
}
if (object.hasOwnProperty('scratchY')) {
if (Object.prototype.hasOwnProperty.call(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
// wrapClamp it (like we do on RenderedTarget.setDirection)
target.direction = MathUtil.wrapClamp(object.direction, -179, 180);
}
if (object.hasOwnProperty('isDraggable')) {
if (Object.prototype.hasOwnProperty.call(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.
target.size = object.scale * 100;
}
if (object.hasOwnProperty('visible')) {
if (Object.prototype.hasOwnProperty.call(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
// 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.
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') {
target.rotationStyle = RenderedTarget.ROTATION_STYLE_NONE;
} else if (object.rotationStyle === 'leftRight') {
@ -713,16 +713,16 @@ const parseScratchObject = function (object, runtime, extensions, topLevel, zip,
target.rotationStyle = RenderedTarget.ROTATION_STYLE_ALL_AROUND;
}
}
if (object.hasOwnProperty('tempoBPM')) {
if (Object.prototype.hasOwnProperty.call(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.
// We convert to a percentage, and invert it so 100% is full transparency.
target.videoTransparency = 100 - (100 * object.videoAlpha);
}
if (object.hasOwnProperty('info')) {
if (object.info.hasOwnProperty('videoOn')) {
if (Object.prototype.hasOwnProperty.call(object, 'info')) {
if (Object.prototype.hasOwnProperty.call(object.info, 'videoOn')) {
if (object.info.videoOn) {
target.videoState = RenderedTarget.VIDEO_STATE.ON;
} 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
// 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.

View file

@ -173,7 +173,7 @@ const serializeFields = function (fields) {
for (const fieldName in fields) {
if (!hasOwnProperty.call(fields, fieldName)) continue;
obj[fieldName] = [fields[fieldName].value];
if (fields[fieldName].hasOwnProperty('id')) {
if (Object.prototype.hasOwnProperty.call(fields[fieldName], 'id')) {
obj[fieldName].push(fields[fieldName].id);
}
}
@ -301,7 +301,7 @@ const serializeBlocks = function (blocks) {
const obj = Object.create(null);
const extensionIDs = new Set();
for (const blockID in blocks) {
if (!blocks.hasOwnProperty(blockID)) continue;
if (!Object.prototype.hasOwnProperty.call(blocks, blockID)) continue;
obj[blockID] = serializeBlock(blocks[blockID], blocks);
const extensionID = getExtensionIdForOpcode(blocks[blockID].opcode);
if (extensionID) {
@ -428,7 +428,7 @@ const serializeVariables = function (variables) {
const serializeComments = function (comments) {
const obj = Object.create(null);
for (const commentId in comments) {
if (!comments.hasOwnProperty(commentId)) continue;
if (!Object.prototype.hasOwnProperty.call(comments, commentId)) continue;
const comment = comments[commentId];
const serializedComment = Object.create(null);
@ -473,13 +473,21 @@ const serializeTarget = function (target, extensions) {
obj.currentCostume = target.currentCostume;
obj.costumes = target.costumes.map(serializeCostume);
obj.sounds = target.sounds.map(serializeSound);
if (target.hasOwnProperty('volume')) obj.volume = target.volume;
if (target.hasOwnProperty('layerOrder')) obj.layerOrder = target.layerOrder;
if (Object.prototype.hasOwnProperty.call(target, 'volume')) obj.volume = target.volume;
if (Object.prototype.hasOwnProperty.call(target, 'layerOrder')) obj.layerOrder = target.layerOrder;
if (obj.isStage) { // Only the stage should have these properties
if (target.hasOwnProperty('tempo')) obj.tempo = target.tempo;
if (target.hasOwnProperty('videoTransparency')) obj.videoTransparency = target.videoTransparency;
if (target.hasOwnProperty('videoState')) obj.videoState = target.videoState;
if (target.hasOwnProperty('textToSpeechLanguage')) obj.textToSpeechLanguage = target.textToSpeechLanguage;
if (Object.prototype.hasOwnProperty.call(target, 'tempo')) {
obj.tempo = target.tempo;
}
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
obj.visible = target.visible;
obj.x = target.x;
@ -852,7 +860,7 @@ const deserializeBlocks = function (blocks) {
* SoundBank for the sound assets. null for unsupported objects.
*/
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.
// @todo
return Promise.resolve(null);
@ -882,7 +890,7 @@ const parseScratchAssets = function (object, runtime, zip) {
costumeSource.dataFormat ||
(costumeSource.assetType && costumeSource.assetType.runtimeFormat) || // older format
'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}`;
costume.md5 = costumeMd5Ext;
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.
*/
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.
// @todo
return Promise.resolve(null);
@ -948,14 +956,14 @@ const parseScratchObject = function (object, runtime, extensions, zip, assets) {
const sprite = new Sprite(blocks, runtime);
// Sprite/stage name from JSON.
if (object.hasOwnProperty('name')) {
if (Object.prototype.hasOwnProperty.call(object, 'name')) {
sprite.name = object.name;
}
if (object.hasOwnProperty('blocks')) {
if (Object.prototype.hasOwnProperty.call(object, 'blocks')) {
deserializeBlocks(object.blocks);
// Take a second pass to create objects and add extensions
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];
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.
const target = sprite.createClone(object.isStage ? StageLayering.BACKGROUND_LAYER : StageLayering.SPRITE_LAYER);
// Load target properties from JSON.
if (object.hasOwnProperty('tempo')) {
if (Object.prototype.hasOwnProperty.call(object, 'tempo')) {
target.tempo = object.tempo;
}
if (object.hasOwnProperty('volume')) {
if (Object.prototype.hasOwnProperty.call(object, 'volume')) {
target.volume = object.volume;
}
if (object.hasOwnProperty('videoTransparency')) {
if (Object.prototype.hasOwnProperty.call(object, 'videoTransparency')) {
target.videoTransparency = object.videoTransparency;
}
if (object.hasOwnProperty('videoState')) {
if (Object.prototype.hasOwnProperty.call(object, 'videoState')) {
target.videoState = object.videoState;
}
if (object.hasOwnProperty('textToSpeechLanguage')) {
if (Object.prototype.hasOwnProperty.call(object, 'textToSpeechLanguage')) {
target.textToSpeechLanguage = object.textToSpeechLanguage;
}
if (object.hasOwnProperty('variables')) {
if (Object.prototype.hasOwnProperty.call(object, 'variables')) {
for (const varId in object.variables) {
const variable = object.variables[varId];
// A variable is a cloud variable if:
@ -1008,7 +1016,7 @@ const parseScratchObject = function (object, runtime, extensions, zip, assets) {
target.variables[newVariable.id] = newVariable;
}
}
if (object.hasOwnProperty('lists')) {
if (Object.prototype.hasOwnProperty.call(object, 'lists')) {
for (const listId in object.lists) {
const list = object.lists[listId];
const newList = new Variable(
@ -1021,7 +1029,7 @@ const parseScratchObject = function (object, runtime, extensions, zip, assets) {
target.variables[newList.id] = newList;
}
}
if (object.hasOwnProperty('broadcasts')) {
if (Object.prototype.hasOwnProperty.call(object, 'broadcasts')) {
for (const broadcastId in object.broadcasts) {
const broadcast = object.broadcasts[broadcastId];
const newBroadcast = new Variable(
@ -1035,7 +1043,7 @@ const parseScratchObject = function (object, runtime, extensions, zip, assets) {
target.variables[newBroadcast.id] = newBroadcast;
}
}
if (object.hasOwnProperty('comments')) {
if (Object.prototype.hasOwnProperty.call(object, 'comments')) {
for (const commentId in object.comments) {
const comment = object.comments[commentId];
const newComment = new Comment(
@ -1053,39 +1061,39 @@ const parseScratchObject = function (object, runtime, extensions, zip, assets) {
target.comments[newComment.id] = newComment;
}
}
if (object.hasOwnProperty('x')) {
if (Object.prototype.hasOwnProperty.call(object, 'x')) {
target.x = object.x;
}
if (object.hasOwnProperty('y')) {
if (Object.prototype.hasOwnProperty.call(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
// wrapClamp it (like we do on RenderedTarget.setDirection)
target.direction = MathUtil.wrapClamp(object.direction, -179, 180);
}
if (object.hasOwnProperty('size')) {
if (Object.prototype.hasOwnProperty.call(object, 'size')) {
target.size = object.size;
}
if (object.hasOwnProperty('visible')) {
if (Object.prototype.hasOwnProperty.call(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);
}
if (object.hasOwnProperty('rotationStyle')) {
if (Object.prototype.hasOwnProperty.call(object, 'rotationStyle')) {
target.rotationStyle = object.rotationStyle;
}
if (object.hasOwnProperty('isStage')) {
if (Object.prototype.hasOwnProperty.call(object, 'isStage')) {
target.isStage = object.isStage;
}
if (object.hasOwnProperty('targetPaneOrder')) {
if (Object.prototype.hasOwnProperty.call(object, 'targetPaneOrder')) {
// Temporarily store the 'targetPaneOrder' property
// 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.
target.targetPaneOrder = object.targetPaneOrder;
}
if (object.hasOwnProperty('draggable')) {
if (Object.prototype.hasOwnProperty.call(object, 'draggable')) {
target.draggable = object.draggable;
}
Promise.all(costumePromises).then(costumes => {

View file

@ -395,7 +395,7 @@ class RenderedTarget extends Target {
* @param {!number} value Numerical magnitude of effect.
*/
setEffect (effectName, value) {
if (!this.effects.hasOwnProperty(effectName)) return;
if (!Object.prototype.hasOwnProperty.call(this.effects, effectName)) return;
this.effects[effectName] = value;
if (this.renderer) {
this.renderer.updateDrawableEffect(this.drawableID, effectName, value);
@ -411,12 +411,12 @@ class RenderedTarget extends Target {
*/
clearEffects () {
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;
}
if (this.renderer) {
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);
}
if (this.visible) {
@ -682,7 +682,7 @@ class RenderedTarget extends Target {
this.renderer.updateDrawableSkinId(this.drawableID, costume.skinId);
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]);
}
@ -1020,25 +1020,25 @@ class RenderedTarget extends Target {
* @param {object} data An object with sprite info data to set.
*/
postSpriteInfo (data) {
const force = data.hasOwnProperty('force') ? data.force : null;
const isXChanged = data.hasOwnProperty('x');
const isYChanged = data.hasOwnProperty('y');
const force = Object.prototype.hasOwnProperty.call(data, 'force') ? data.force : null;
const isXChanged = Object.prototype.hasOwnProperty.call(data, 'x');
const isYChanged = Object.prototype.hasOwnProperty.call(data, 'y');
if (isXChanged || isYChanged) {
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);
}
if (data.hasOwnProperty('draggable')) {
if (Object.prototype.hasOwnProperty.call(data, 'draggable')) {
this.setDraggable(data.draggable);
}
if (data.hasOwnProperty('rotationStyle')) {
if (Object.prototype.hasOwnProperty.call(data, 'rotationStyle')) {
this.setRotationStyle(data.rotationStyle);
}
if (data.hasOwnProperty('visible')) {
if (Object.prototype.hasOwnProperty.call(data, 'visible')) {
this.setVisible(data.visible);
}
if (data.hasOwnProperty('size')) {
if (Object.prototype.hasOwnProperty.call(data, 'size')) {
this.setSize(data.size);
}
}

View file

@ -62,7 +62,7 @@ class JSONRPC {
if (json.jsonrpc !== '2.0') {
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);
} else {
this._handleResponse(json);

View file

@ -21,8 +21,10 @@ class TaskQueue {
this._maxTokens = maxTokens;
this._refillRate = refillRate;
this._pendingTaskRecords = [];
this._tokenCount = options.hasOwnProperty('startingTokens') ? options.startingTokens : maxTokens;
this._maxTotalCost = options.hasOwnProperty('maxTotalCost') ? options.maxTotalCost : Infinity;
this._tokenCount = Object.prototype.hasOwnProperty.call(options, 'startingTokens') ?
options.startingTokens : maxTokens;
this._maxTotalCost = Object.prototype.hasOwnProperty.call(options, 'maxTotalCost') ?
options.maxTotalCost : Infinity;
this._timer = new Timer();
this._timer.start();
this._timeout = null;
@ -53,7 +55,7 @@ class TaskQueue {
if (this._maxTotalCost < Infinity) {
const currentTotalCost = this._pendingTaskRecords.reduce((t, r) => t + r.cost, 0);
if (currentTotalCost + cost > this._maxTotalCost) {
return Promise.reject('Maximum total cost exceeded');
return Promise.reject(new Error('Maximum total cost exceeded'));
}
}
const newRecord = {

View file

@ -2,7 +2,6 @@ let _TextEncoder;
if (typeof TextEncoder === 'undefined') {
_TextEncoder = require('text-encoding').TextEncoder;
} else {
/* global TextEncoder */
_TextEncoder = TextEncoder;
}
const EventEmitter = require('events');
@ -354,7 +353,7 @@ class VirtualMachine extends EventEmitter {
.then(() => this.runtime.handleProjectLoaded())
.catch(error => {
// 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(error);
@ -503,6 +502,8 @@ class VirtualMachine extends EventEmitter {
const sb3 = require('./serialization/sb3');
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 deserializePromise()
@ -607,14 +608,18 @@ class VirtualMachine extends EventEmitter {
if (projectVersion === 3) {
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.`);
})
.then(() => this.runtime.emitProjectChanged())
.catch(error => {
// 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));
}
// TODO: reject with an Error (possible breaking API change!)
// eslint-disable-next-line prefer-promise-reject-errors
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
// TODO: reject with an Error (possible breaking API change!)
// eslint-disable-next-line prefer-promise-reject-errors
return Promise.reject();
}
@ -687,6 +694,8 @@ class VirtualMachine extends EventEmitter {
* @returns {?Promise} - a promise that resolves when the costume has been added
*/
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();
return this.addCostume(md5ext, costumeObject, this.editingTarget.id, 2 /* optVersion */);
}
@ -1338,7 +1347,7 @@ class VirtualMachine extends EventEmitter {
targetList: this.runtime.targets
.filter(
// Don't report clones.
target => !target.hasOwnProperty('isOriginal') || target.isOriginal
target => !Object.prototype.hasOwnProperty.call(target, 'isOriginal') || target.isOriginal
).map(
target => target.toJSON()
),
@ -1414,7 +1423,10 @@ class VirtualMachine extends EventEmitter {
*/
getTargetIdForDrawableId (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 null;

View file

@ -6,6 +6,8 @@ const path = require('path');
const oldRequire = Module.prototype.require;
Module.prototype.require = function (target) {
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);
}

View file

@ -57,7 +57,9 @@ test('importing sb2 project with special chars in message names', t => {
t.equal(allBroadcastFields[ltPerfectMessageId].length, 1);
t.equal(allBroadcastFields[abMessageId].length, 1);
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[0].fields.BROADCAST_OPTION.id, ltPerfectMessageId);
t.equal(catMessageBlocks[1].fields.BROADCAST_OPTION.id, abMessageId);

View file

@ -57,7 +57,9 @@ test('importing sb3 project with special chars in message names', t => {
t.equal(allBroadcastFields[ltPerfectMessageId].length, 1);
t.equal(allBroadcastFields[abMessageId].length, 1);
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[0].fields.BROADCAST_OPTION.id, ltPerfectMessageId);
t.equal(catMessageBlocks[1].fields.BROADCAST_OPTION.id, abMessageId);

View file

@ -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
t.equal(allVarListFields[abVarId].length, 3);
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[0].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 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[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
// There should be only two, one on the stage and one on bananas
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[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[0].fields.VARIABLE.id, fooVarId);
@ -110,7 +112,9 @@ test('importing sb2 project with special chars in variable names', t => {
// There should be one
t.equal(allVarListFields[ltPerfectVarId].length, 1);
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[0].fields.VARIABLE.id, ltPerfectVarId);

View file

@ -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
t.equal(allVarListFields[abVarId].length, 3);
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[0].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 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[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
// There should be only two, one on the stage and one on bananas
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[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[0].fields.VARIABLE.id, fooVarId);
@ -110,7 +114,9 @@ test('importing sb3 project with special chars in variable names', t => {
// There should be one
t.equal(allVarListFields[ltPerfectVarId].length, 1);
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[0].fields.VARIABLE.id, ltPerfectVarId);

View file

@ -290,8 +290,8 @@ test('wait', t => {
t.equal(yields, 1, 'Second call after timeElapsed does not yield');
t.equal(waitTime, mockUtil.stackFrame.duration);
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),
'Wait block ended too late: ${timeElapsed} > ${waitTime} + ${thresholdLarge}');
`Wait block ended too late: ${timeElapsed} > ${waitTime} + ${thresholdLarge}`);
t.end();
});

View file

@ -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
// the duplicate variables since a blocks container was not specified.
t.equal(target.variables.hasOwnProperty('var ID 1'), true);
t.equal(target.variables.hasOwnProperty('var ID 2'), true);
t.equal(duplicateVariables.hasOwnProperty('var ID 1'), true);
t.equal(duplicateVariables.hasOwnProperty('var ID 1'), true);
t.equal(Object.prototype.hasOwnProperty.call(target.variables, 'var ID 1'), true);
t.equal(Object.prototype.hasOwnProperty.call(target.variables, 'var ID 2'), true);
t.equal(Object.prototype.hasOwnProperty.call(duplicateVariables, '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
t.equal(target.variables['var ID 1'].value, duplicateVariables['var ID 1'].value);

View file

@ -142,11 +142,11 @@ const testReporter = function (t, reporter) {
t.equal(reporter.json.checkboxInFlyout, true);
t.equal(reporter.json.outputShape, ScratchBlocksConstants.OUTPUT_SHAPE_ROUND);
t.equal(reporter.json.output, 'String');
t.notOk(reporter.json.hasOwnProperty('previousStatement'));
t.notOk(reporter.json.hasOwnProperty('nextStatement'));
t.notOk(Object.prototype.hasOwnProperty.call(reporter.json, 'previousStatement'));
t.notOk(Object.prototype.hasOwnProperty.call(reporter.json, 'nextStatement'));
t.same(reporter.json.extensions, ['scratch_extension']);
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, [
// %1 in message0: the block icon
{
@ -160,7 +160,7 @@ const testReporter = function (t, reporter) {
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>');
};
@ -170,11 +170,11 @@ const testInlineImage = function (t, inlineImage) {
t.equal(inlineImage.json.checkboxInFlyout, true);
t.equal(inlineImage.json.outputShape, ScratchBlocksConstants.OUTPUT_SHAPE_ROUND);
t.equal(inlineImage.json.output, 'String');
t.notOk(inlineImage.json.hasOwnProperty('previousStatement'));
t.notOk(inlineImage.json.hasOwnProperty('nextStatement'));
t.notOk(Object.prototype.hasOwnProperty.call(inlineImage.json, 'previousStatement'));
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.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, [
// %1 in message0: the block icon
{
@ -185,7 +185,7 @@ const testInlineImage = function (t, inlineImage) {
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>');
};
@ -198,16 +198,16 @@ const testCommand = function (t, command) {
t.equal(command.json.type, 'test_command');
testCategoryInfo(t, command);
t.equal(command.json.outputShape, ScratchBlocksConstants.OUTPUT_SHAPE_SQUARE);
t.assert(command.json.hasOwnProperty('previousStatement'));
t.assert(command.json.hasOwnProperty('nextStatement'));
t.assert(Object.prototype.hasOwnProperty.call(command.json, 'previousStatement'));
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.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], {
type: 'input_value',
name: 'ARG'
});
t.notOk(command.json.hasOwnProperty('args1'));
t.notOk(Object.prototype.hasOwnProperty.call(command.json, 'args1'));
t.equal(command.xml,
'<block type="test_command"><value name="ARG"><shadow type="text"></shadow></value>' +
'<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');
testCategoryInfo(t, conditional);
t.equal(conditional.json.outputShape, ScratchBlocksConstants.OUTPUT_SHAPE_SQUARE);
t.ok(conditional.json.hasOwnProperty('previousStatement'));
t.ok(conditional.json.hasOwnProperty('nextStatement'));
t.ok(Object.prototype.hasOwnProperty.call(conditional.json, 'previousStatement'));
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.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.message2, 'or elsewise');
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], {
type: 'input_value',
name: 'THING',
@ -235,12 +235,12 @@ const testConditional = function (t, conditional) {
type: 'input_statement',
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], {
type: 'input_statement',
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>');
};
@ -248,13 +248,13 @@ const testLoop = function (t, loop) {
t.equal(loop.json.type, 'test_loop');
testCategoryInfo(t, loop);
t.equal(loop.json.outputShape, ScratchBlocksConstants.OUTPUT_SHAPE_SQUARE);
t.ok(loop.json.hasOwnProperty('previousStatement'));
t.notOk(loop.json.hasOwnProperty('nextStatement')); // isTerminal is set on this block
t.ok(Object.prototype.hasOwnProperty.call(loop.json, 'previousStatement'));
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.equal(loop.json.message0, 'loopty %1 loops');
t.equal(loop.json.message1, '%1'); // placeholder for substack
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], {
type: 'input_value',
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.args2[0].type, 'field_image');
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,
'<block type="test_loop"><value name="MANY"><shadow type="math_number"></shadow></value></block>');
};

View file

@ -40,7 +40,7 @@ test('blocks get new id on duplicate', t => {
rt.blocks.createBlock(block);
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();
});
});