From 3329f09ed0bb397a618a4d2ee7937b8da094e043 Mon Sep 17 00:00:00 2001 From: Sergio Arbeo Date: Fri, 8 Jun 2018 17:51:57 +0200 Subject: [PATCH] [BUGFIX beta] Throw error if run.bind receives no method This commit uses the same logic as backburner.join to know which method is being bound. Fixes #16652 --- packages/@ember/runloop/index.js | 25 ++++++++++++++++++- .../@ember/runloop/tests/run_bind_test.js | 19 ++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/packages/@ember/runloop/index.js b/packages/@ember/runloop/index.js index fdca2d426ca..b8abd69ff54 100644 --- a/packages/@ember/runloop/index.js +++ b/packages/@ember/runloop/index.js @@ -217,7 +217,30 @@ export function join() { @since 1.4.0 @public */ -export const bind = (...curried) => (...args) => join(...curried.concat(args)); +export const bind = (...curried) => { + assert( + 'could not find a suitable method to bind', + (function(methodOrTarget, methodOrArg) { + // Applies the same logic as backburner parseArgs for detecting if a method + // is actually being passed. + let length = arguments.length; + + if (length === 0) { + return false; + } else if (length === 1) { + return typeof methodOrTarget === 'function'; + } else { + let type = typeof methodOrArg; + return ( + type === 'function' || // second argument is a function + (methodOrTarget !== null && type === 'string' && methodOrArg in methodOrTarget) || // second argument is the name of a method in first argument + typeof methodOrTarget === 'function' //first argument is a function + ); + } + })(...curried) + ); + return (...args) => join(...curried.concat(args)); +}; /** Begins a new RunLoop. Any deferred actions invoked after the begin will diff --git a/packages/@ember/runloop/tests/run_bind_test.js b/packages/@ember/runloop/tests/run_bind_test.js index bd04427a6c4..51f4da6e236 100644 --- a/packages/@ember/runloop/tests/run_bind_test.js +++ b/packages/@ember/runloop/tests/run_bind_test.js @@ -36,5 +36,24 @@ moduleFor( asyncFunction(bind(asyncCallback, asyncCallback, 1)); } + + ['@test [GH#16652] bind throws an error if callback is undefined']() { + let assertBindThrows = (msg, ...args) => { + expectAssertion( + function() { + bind(...args); + }, + /could not find a suitable method to bind/, + msg + ); + }; + assertBindThrows('without arguments'); + assertBindThrows('with one arguments that is not a function', 'myMethod'); + assertBindThrows( + 'if second parameter is not a function and not a property in first parameter', + Object.create(null), + 'myMethod' + ); + } } );