From 8dbcc1fc8f8d8c4f1e40629fe8a388149d6dfd1c Mon Sep 17 00:00:00 2001
From: Christopher Willis-Ford <7019101+cwillisf@users.noreply.github.com>
Date: Fri, 15 Dec 2023 17:25:23 -0800
Subject: [PATCH] style: fix hasOwnProperty lint complaints

---
 src/blocks/scratch3_looks.js                  |  2 +-
 src/blocks/scratch3_procedures.js             |  2 +-
 src/blocks/scratch3_sound.js                  |  4 +-
 src/dispatch/central-dispatch.js              |  2 +-
 src/dispatch/worker-dispatch.js               |  2 +-
 src/engine/adapter.js                         |  2 +-
 src/engine/blocks-runtime-cache.js            |  2 +-
 src/engine/blocks.js                          | 45 +++++------
 src/engine/runtime.js                         | 26 +++----
 src/engine/target.js                          | 20 ++---
 src/engine/thread.js                          |  2 +-
 src/extension-support/extension-manager.js    |  4 +-
 src/extensions/scratch3_makeymakey/index.js   |  2 +-
 src/extensions/scratch3_pen/index.js          |  2 +-
 src/extensions/scratch3_translate/index.js    |  4 +-
 src/io/mouse.js                               |  2 +-
 src/serialization/sb2.js                      | 54 ++++++-------
 src/serialization/sb3.js                      | 76 ++++++++++---------
 src/sprites/rendered-target.js                | 24 +++---
 src/util/jsonrpc.js                           |  2 +-
 src/util/task-queue.js                        |  6 +-
 src/virtual-machine.js                        | 12 +--
 .../broadcast_special_chars_sb2.js            |  4 +-
 .../broadcast_special_chars_sb3.js            |  4 +-
 .../integration/variable_special_chars_sb2.js | 14 ++--
 .../integration/variable_special_chars_sb3.js | 16 ++--
 test/unit/engine_target.js                    |  8 +-
 test/unit/extension_conversion.js             | 42 +++++-----
 test/unit/sprites_rendered-target.js          |  2 +-
 29 files changed, 207 insertions(+), 180 deletions(-)

diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js
index c121df71d..18e163a9a 100644
--- a/src/blocks/scratch3_looks.js
+++ b/src/blocks/scratch3_looks.js
@@ -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);
diff --git a/src/blocks/scratch3_procedures.js b/src/blocks/scratch3_procedures.js
index 56d3f3e7c..0f2ec3642 100644
--- a/src/blocks/scratch3_procedures.js
+++ b/src/blocks/scratch3_procedures.js
@@ -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]);
diff --git a/src/blocks/scratch3_sound.js b/src/blocks/scratch3_sound.js
index 237db6123..26df698e6 100644
--- a/src/blocks/scratch3_sound.js
+++ b/src/blocks/scratch3_sound.js
@@ -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);
diff --git a/src/dispatch/central-dispatch.js b/src/dispatch/central-dispatch.js
index fe4987a6e..dde5c7c10 100644
--- a/src/dispatch/central-dispatch.js
+++ b/src/dispatch/central-dispatch.js
@@ -62,7 +62,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;
diff --git a/src/dispatch/worker-dispatch.js b/src/dispatch/worker-dispatch.js
index 10542af46..b93aac123 100644
--- a/src/dispatch/worker-dispatch.js
+++ b/src/dispatch/worker-dispatch.js
@@ -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;
diff --git a/src/engine/adapter.js b/src/engine/adapter.js
index 873974f8c..d10c6874a 100644
--- a/src/engine/adapter.js
+++ b/src/engine/adapter.js
@@ -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;
diff --git a/src/engine/blocks-runtime-cache.js b/src/engine/blocks-runtime-cache.js
index cc30e8345..3a3241e97 100644
--- a/src/engine/blocks-runtime-cache.js
+++ b/src/engine/blocks-runtime-cache.js
@@ -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);
diff --git a/src/engine/blocks.js b/src/engine/blocks.js
index c276564ed..cf1b2b7c4 100644
--- a/src/engine/blocks.js
+++ b/src/engine/blocks.js
@@ -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;
diff --git a/src/engine/runtime.js b/src/engine/runtime.js
index 29c14d3aa..f5a54d621 100644
--- a/src/engine/runtime.js
+++ b/src/engine/runtime.js
@@ -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);
diff --git a/src/engine/target.js b/src/engine/target.js
index 0f1895a3c..166e44369 100644
--- a/src/engine/target.js
+++ b/src/engine/target.js
@@ -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.
diff --git a/src/engine/thread.js b/src/engine/thread.js
index e381dd9bf..6094a8254 100644
--- a/src/engine/thread.js
+++ b/src/engine/thread.js
@@ -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;
diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js
index a5e2c4ec8..0ed3a3e89 100644
--- a/src/extension-support/extension-manager.js
+++ b/src/extension-support/extension-manager.js
@@ -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}`;
diff --git a/src/extensions/scratch3_makeymakey/index.js b/src/extensions/scratch3_makeymakey/index.js
index a83ca6616..e57bc76e8 100644
--- a/src/extensions/scratch3_makeymakey/index.js
+++ b/src/extensions/scratch3_makeymakey/index.js
@@ -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] = {
diff --git a/src/extensions/scratch3_pen/index.js b/src/extensions/scratch3_pen/index.js
index ec9aa0ac8..f6175f96f 100644
--- a/src/extensions/scratch3_pen/index.js
+++ b/src/extensions/scratch3_pen/index.js
@@ -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;
diff --git a/src/extensions/scratch3_translate/index.js b/src/extensions/scratch3_translate/index.js
index 3964711fc..1149a3b30 100644
--- a/src/extensions/scratch3_translate/index.js
+++ b/src/extensions/scratch3_translate/index.js
@@ -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];
         }
 
diff --git a/src/io/mouse.js b/src/io/mouse.js
index 1c7bb81e5..9ee3202e5 100644
--- a/src/io/mouse.js
+++ b/src/io/mouse.js
@@ -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;
                 }
diff --git a/src/serialization/sb2.js b/src/serialization/sb2.js
index 2f7556341..855723d6a 100644
--- a/src/serialization/sb2.js
+++ b/src/serialization/sb2.js
@@ -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.
diff --git a/src/serialization/sb3.js b/src/serialization/sb3.js
index 5eb60a5bf..c7db58d0b 100644
--- a/src/serialization/sb3.js
+++ b/src/serialization/sb3.js
@@ -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 => {
diff --git a/src/sprites/rendered-target.js b/src/sprites/rendered-target.js
index b0c1ebfed..e4a12e244 100644
--- a/src/sprites/rendered-target.js
+++ b/src/sprites/rendered-target.js
@@ -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);
         }
     }
diff --git a/src/util/jsonrpc.js b/src/util/jsonrpc.js
index ba23a0e8f..4ab1663c3 100644
--- a/src/util/jsonrpc.js
+++ b/src/util/jsonrpc.js
@@ -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);
diff --git a/src/util/task-queue.js b/src/util/task-queue.js
index 0b452ffb9..8a3b415ef 100644
--- a/src/util/task-queue.js
+++ b/src/util/task-queue.js
@@ -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;
diff --git a/src/virtual-machine.js b/src/virtual-machine.js
index 6693a1f3a..6d84523a0 100644
--- a/src/virtual-machine.js
+++ b/src/virtual-machine.js
@@ -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);
@@ -612,7 +611,7 @@ class VirtualMachine extends EventEmitter {
             .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));
                 }
                 return Promise.reject(`${errorPrefix} ${error}`);
@@ -1338,7 +1337,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 +1413,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;
diff --git a/test/integration/broadcast_special_chars_sb2.js b/test/integration/broadcast_special_chars_sb2.js
index 63a77df6c..24988f402 100644
--- a/test/integration/broadcast_special_chars_sb2.js
+++ b/test/integration/broadcast_special_chars_sb2.js
@@ -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);
diff --git a/test/integration/broadcast_special_chars_sb3.js b/test/integration/broadcast_special_chars_sb3.js
index 968e9fc52..91050e591 100644
--- a/test/integration/broadcast_special_chars_sb3.js
+++ b/test/integration/broadcast_special_chars_sb3.js
@@ -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);
diff --git a/test/integration/variable_special_chars_sb2.js b/test/integration/variable_special_chars_sb2.js
index b0c47bdd9..ba256b034 100644
--- a/test/integration/variable_special_chars_sb2.js
+++ b/test/integration/variable_special_chars_sb2.js
@@ -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);
 
diff --git a/test/integration/variable_special_chars_sb3.js b/test/integration/variable_special_chars_sb3.js
index 5fb7c7542..c4b0d0f51 100644
--- a/test/integration/variable_special_chars_sb3.js
+++ b/test/integration/variable_special_chars_sb3.js
@@ -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);
 
diff --git a/test/unit/engine_target.js b/test/unit/engine_target.js
index b1fb6e457..54f89e4c0 100644
--- a/test/unit/engine_target.js
+++ b/test/unit/engine_target.js
@@ -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);
diff --git a/test/unit/extension_conversion.js b/test/unit/extension_conversion.js
index e0d23b33e..876b01a62 100644
--- a/test/unit/extension_conversion.js
+++ b/test/unit/extension_conversion.js
@@ -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>');
 };
diff --git a/test/unit/sprites_rendered-target.js b/test/unit/sprites_rendered-target.js
index 681a10d86..a9823424a 100644
--- a/test/unit/sprites_rendered-target.js
+++ b/test/unit/sprites_rendered-target.js
@@ -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();
     });
 });