Skip to content

Commit

Permalink
Deopt Underscore methods that change on arguments
Browse files Browse the repository at this point in the history
All of our currently deoptimized Underscore methods (`pick`, `omit`,
`invoke`, `without`, and `difference`) change behavior based on the
number of arguments pass to the call. This both adds `reduce` (and
friends), and explicitly deopts any method that depends on `arguments`
from falling through the cracks.

Supersedes (and incorporates) #3810.
  • Loading branch information
jridgewell committed Oct 7, 2015
1 parent 345dd7b commit 2d555ca
Showing 1 changed file with 9 additions and 5 deletions.
14 changes: 9 additions & 5 deletions backbone.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
// form param named `model`.
Backbone.emulateJSON = false;

// A cached regex to detect if the Underscore function contains the `arguments`
// keyword.
var containsArguments = /\barguments\b/;
// Proxy Backbone class methods to Underscore functions, wrapping the model's
// `attributes` object or collection's `models` array behind the scenes.
//
Expand All @@ -76,6 +79,10 @@
//
// `Function#apply` can be slow so we use the method's arg count, if we know it.
var addMethod = function(length, method, attribute) {
// In case we don't catch it, deopt Underscore functions that contain
// the arguments keyword.
if (length > 0 && containsArguments.test(_[method])) length = 0;

switch (length) {
case 1: return function() {
return _[method](this[attribute]);
Expand All @@ -87,9 +94,6 @@
return _[method](this[attribute], cb(iteratee, this), context);
};
case 4: return function(iteratee, defaultVal, context) {
if(arguments.length < 2) {
return _[method](this[attribute], cb(iteratee, this));
}
return _[method](this[attribute], cb(iteratee, this), defaultVal, context);
};
default: return function() {
Expand Down Expand Up @@ -1169,8 +1173,8 @@
// Underscore methods that we want to implement on the Collection.
// 90% of the core usefulness of Backbone Collections is actually implemented
// right here:
var collectionMethods = { forEach: 3, each: 3, map: 3, collect: 3, reduce: 4,
foldl: 4, inject: 4, reduceRight: 4, foldr: 4, find: 3, detect: 3, filter: 3,
var collectionMethods = { forEach: 3, each: 3, map: 3, collect: 3, reduce: 0,
foldl: 0, inject: 0, reduceRight: 0, foldr: 0, find: 3, detect: 3, filter: 3,
select: 3, reject: 3, every: 3, all: 3, some: 3, any: 3, include: 3, includes: 3,
contains: 3, invoke: 0, max: 3, min: 3, toArray: 1, size: 1, first: 3,
head: 3, take: 3, initial: 3, rest: 3, tail: 3, drop: 3, last: 3,
Expand Down

0 comments on commit 2d555ca

Please sign in to comment.