diff --git a/src/dispatch/central-dispatch.js b/src/dispatch/central-dispatch.js index dde5c7c10..9d9728a52 100644 --- a/src/dispatch/central-dispatch.js +++ b/src/dispatch/central-dispatch.js @@ -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}`); diff --git a/src/dispatch/shared-dispatch.js b/src/dispatch/shared-dispatch.js index 8e665c1d9..a581676f0 100644 --- a/src/dispatch/shared-dispatch.js +++ b/src/dispatch/shared-dispatch.js @@ -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); } diff --git a/src/engine/block-utility.js b/src/engine/block-utility.js index cfe18a227..52384c5ec 100644 --- a/src/engine/block-utility.js +++ b/src/engine/block-utility.js @@ -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); } } diff --git a/src/engine/runtime.js b/src/engine/runtime.js index f5a54d621..452ff51c2 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -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 = []; diff --git a/src/extensions/scratch3_video_sensing/index.js b/src/extensions/scratch3_video_sensing/index.js index 008c15a4e..5f8380fe4 100644 --- a/src/extensions/scratch3_video_sensing/index.js +++ b/src/extensions/scratch3_video_sensing/index.js @@ -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; } /** diff --git a/src/import/load-costume.js b/src/import/load-costume.js index 4852399bd..55b1c69fc 100644 --- a/src/import/load-costume.js +++ b/src/import/load-costume.js @@ -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) diff --git a/src/util/task-queue.js b/src/util/task-queue.js index 8a3b415ef..7697104ae 100644 --- a/src/util/task-queue.js +++ b/src/util/task-queue.js @@ -55,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 = { diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 6d84523a0..64ad7934f 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -502,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() @@ -606,6 +608,8 @@ 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()) @@ -614,6 +618,8 @@ class VirtualMachine extends EventEmitter { 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}`); }); } @@ -672,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(); } @@ -686,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 */); } diff --git a/test/fixtures/dispatch-test-worker-shim.js b/test/fixtures/dispatch-test-worker-shim.js index ae11a4950..d0ef30ba4 100644 --- a/test/fixtures/dispatch-test-worker-shim.js +++ b/test/fixtures/dispatch-test-worker-shim.js @@ -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); } diff --git a/test/unit/blocks_control.js b/test/unit/blocks_control.js index 25f0c7584..b2943f887 100644 --- a/test/unit/blocks_control.js +++ b/test/unit/blocks_control.js @@ -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(); });