Skip to content

Commit

Permalink
[BUGFIX beta] Throw error if run.bind receives no method
Browse files Browse the repository at this point in the history
This commit uses the same logic as backburner.join to know
which method is being bound.

Fixes #16652
  • Loading branch information
Serabe committed Jun 8, 2018
1 parent ef2b440 commit ae7fef6
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 1 deletion.
34 changes: 33 additions & 1 deletion packages/@ember/runloop/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,39 @@ export function join() {
@since 1.4.0
@public
*/
export const bind = (...curried) => (...args) => join(...curried.concat(args));
export const bind = (...curried) => {
if (!bindMethodPresent(...curried)) {
throw new Error('could not find a suitable method to bind');
}
return (...args) => join(...curried.concat(args));
};

/**
Applies the same logic as backburner parseArgs for detecting if a method
is actually being passed.
@method bindMethodPresent
@private
@param {Object|Function} methodOrTarget Same as first argument for backburner.join
@param {Function|string} methodOrArg Same as second argument for backburner.join
@return {Boolean} whether there is a method present or not
*/
function bindMethodPresent(methodOrTarget, methodOrArg) {
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
);
}
}

/**
Begins a new RunLoop. Any deferred actions invoked after the begin will
Expand Down
19 changes: 19 additions & 0 deletions packages/@ember/runloop/tests/run_bind_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,24 @@ moduleFor(

asyncFunction(bind(asyncCallback, asyncCallback, 1));
}

['@test bind throws an error if callback is undefined'](assert) {
let assertBindThrows = (msg, ...args) => {
assert.throws(
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'
);
}
}
);

0 comments on commit ae7fef6

Please sign in to comment.