Skip to content

Commit d22ccd9

Browse files
Fix an issue where calling Function#bind with an empty string as the context produced the same behavior as calling it with a context of null or undefined.
1 parent 78f4139 commit d22ccd9

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed

src/prototype/lang/function.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,13 @@ Object.extend(Function.prototype, (function() {
120120
var a = merge(args, arguments), c = context;
121121
// Ignore the supplied context when the bound function is called with
122122
// the "new" keyword.
123-
var c = this instanceof bound ? this : context || window;
123+
var c = this instanceof bound ? this : context;
124124
return __method.apply(c, a);
125125
};
126126

127127
nop.prototype = this.prototype;
128128
bound.prototype = new nop();
129-
129+
130130
return bound;
131131
}
132132

test/unit/function_test.js

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,11 @@ new Test.Unit.Runner({
3030
},
3131

3232
testFunctionBind: function() {
33-
function methodWithoutArguments() { return this.hi };
34-
function methodWithArguments() { return this.hi + ',' + $A(arguments).join(',') };
33+
function methodWithoutArguments() { return this.hi; }
34+
function methodWithArguments() { return this.hi + ',' + $A(arguments).join(','); }
35+
function methodReturningContext() { return this; }
3536
var func = Prototype.emptyFunction;
37+
var u;
3638

3739
// We used to test that `bind` without a `context` argument simply
3840
// returns the original function, but this contradicts the ES5 spec.
@@ -45,6 +47,10 @@ new Test.Unit.Runner({
4547
methodWithArguments.bind({ hi: 'withBindArgs' }, 'arg1', 'arg2')());
4648
this.assertEqual('withBindArgsAndArgs,arg1,arg2,arg3,arg4',
4749
methodWithArguments.bind({ hi: 'withBindArgsAndArgs' }, 'arg1', 'arg2')('arg3', 'arg4'));
50+
51+
this.assertEqual(window, methodReturningContext.bind(null)(), 'null has window as its context');
52+
this.assertEqual(window, methodReturningContext.bind(u)(), 'undefined has window as its context');
53+
this.assertEqual('', methodReturningContext.bind('')(), 'other falsy values should not have window as their context');
4854

4955

5056
// Ensure that bound functions ignore their `context` when used as
@@ -133,8 +139,35 @@ new Test.Unit.Runner({
133139
deferredFunction2.defer('test');
134140
this.wait(50, function() {
135141
this.assertEqual('test', window.deferredValue);
142+
143+
window.deferBoundProperly = false;
144+
145+
var obj = { foo: 'bar' };
146+
var func = function() {
147+
if ('foo' in this) window.deferBoundProperly = true;
148+
};
149+
150+
func.bind(obj).defer();
151+
152+
this.wait(50, function() {
153+
this.assert(window.deferBoundProperly,
154+
"deferred bound functions should preserve original scope");
155+
156+
window.deferBoundProperlyOnString = false;
157+
var str = "<script>window.deferBoundProperlyOnString = true;</script>"
158+
159+
str.evalScripts.bind(str).defer();
160+
161+
this.wait(50, function() {
162+
this.assert(window.deferBoundProperlyOnString);
163+
});
164+
165+
});
166+
136167
});
137168
});
169+
170+
138171
},
139172

140173
testFunctionMethodize: function() {

0 commit comments

Comments
 (0)