Skip to content

Commit 1475da5

Browse files
committed
fix(core): drop the toBoolean function
So far Angular have used the toBoolean function to decide if the parsed value is truthy. The function made more values falsy than regular JavaScript would, e.g. strings 'f' and 'no' were both treated as falsy. This creates suble bugs when backend sends a non-empty string with one of these values and something suddenly hides in the application BREAKING CHANGE: values 'f', '0', 'false', 'no', 'n', '[]' are no longer treated as falsy; only JavaScript falsy values are treated as falsy by the expression parser; there are six of them: false, null, undefined, NaN, o and "". Fixes angular#3969 Fixes angular#4277
1 parent e8e0750 commit 1475da5

File tree

8 files changed

+29
-34
lines changed

8 files changed

+29
-34
lines changed

src/.jshintrc

-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@
8585
"toJsonReplacer": false,
8686
"toJson": false,
8787
"fromJson": false,
88-
"toBoolean": false,
8988
"startingTag": false,
9089
"tryDecodeURIComponent": false,
9190
"parseKeyValue": false,

src/Angular.js

-13
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@
6666
-toJsonReplacer,
6767
-toJson,
6868
-fromJson,
69-
-toBoolean,
7069
-startingTag,
7170
-tryDecodeURIComponent,
7271
-parseKeyValue,
@@ -1028,18 +1027,6 @@ function fromJson(json) {
10281027
}
10291028

10301029

1031-
function toBoolean(value) {
1032-
if (typeof value === 'function') {
1033-
value = true;
1034-
} else if (value && value.length !== 0) {
1035-
var v = lowercase("" + value);
1036-
value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
1037-
} else {
1038-
value = false;
1039-
}
1040-
return value;
1041-
}
1042-
10431030
/**
10441031
* @returns {string} Returns the string representation of the element.
10451032
*/

src/ng/directive/input.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,7 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
917917
// By default we will trim the value
918918
// If the attribute ng-trim exists we will avoid trimming
919919
// e.g. <input ng-model="foo" ng-trim="false">
920-
if (toBoolean(attr.ngTrim || 'T')) {
920+
if (!attr.ngTrim || attr.ngTrim !== 'false') {
921921
value = trim(value);
922922
}
923923

src/ng/directive/ngIf.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ var ngIfDirective = ['$animate', function($animate) {
8787
var block, childScope, previousElements;
8888
$scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
8989

90-
if (toBoolean(value)) {
90+
if (!!value) {
9191
if (!childScope) {
9292
$transclude(function (clone, newScope) {
9393
childScope = newScope;

src/ng/directive/ngShowHide.js

+6-16
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,10 @@
1919
* <div ng-show="myValue" class="ng-hide"></div>
2020
* ```
2121
*
22-
* When the ngShow expression evaluates to false then the ng-hide CSS class is added to the class attribute
23-
* on the element causing it to become hidden. When true, the ng-hide CSS class is removed
22+
* When the ngShow expression evaluates to a falsy value then the ng-hide CSS class is added to the class
23+
* attribute on the element causing it to become hidden. When true, the ng-hide CSS class is removed
2424
* from the element causing the element not to appear hidden.
2525
*
26-
* <div class="alert alert-warning">
27-
* **Note:** Here is a list of values that ngShow will consider as a falsy value (case insensitive):<br />
28-
* "f" / "0" / "false" / "no" / "n" / "[]"
29-
* </div>
30-
*
3126
* ## Why is !important used?
3227
*
3328
* You may be wondering why !important is used for the .ng-hide CSS class. This is because the `.ng-hide` selector
@@ -163,7 +158,7 @@
163158
var ngShowDirective = ['$animate', function($animate) {
164159
return function(scope, element, attr) {
165160
scope.$watch(attr.ngShow, function ngShowWatchAction(value){
166-
$animate[toBoolean(value) ? 'removeClass' : 'addClass'](element, 'ng-hide');
161+
$animate[!!value ? 'removeClass' : 'addClass'](element, 'ng-hide');
167162
});
168163
};
169164
}];
@@ -188,15 +183,10 @@ var ngShowDirective = ['$animate', function($animate) {
188183
* <div ng-hide="myValue"></div>
189184
* ```
190185
*
191-
* When the ngHide expression evaluates to true then the .ng-hide CSS class is added to the class attribute
192-
* on the element causing it to become hidden. When false, the ng-hide CSS class is removed
186+
* When the ngHide expression evaluates to a truthy value then the .ng-hide CSS class is added to the class
187+
* attribute on the element causing it to become hidden. When false, the ng-hide CSS class is removed
193188
* from the element causing the element not to appear hidden.
194189
*
195-
* <div class="alert alert-warning">
196-
* **Note:** Here is a list of values that ngHide will consider as a falsy value (case insensitive):<br />
197-
* "f" / "0" / "false" / "no" / "n" / "[]"
198-
* </div>
199-
*
200190
* ## Why is !important used?
201191
*
202192
* You may be wondering why !important is used for the .ng-hide CSS class. This is because the `.ng-hide` selector
@@ -319,7 +309,7 @@ var ngShowDirective = ['$animate', function($animate) {
319309
var ngHideDirective = ['$animate', function($animate) {
320310
return function(scope, element, attr) {
321311
scope.$watch(attr.ngHide, function ngHideWatchAction(value){
322-
$animate[toBoolean(value) ? 'addClass' : 'removeClass'](element, 'ng-hide');
312+
$animate[!!value ? 'addClass' : 'removeClass'](element, 'ng-hide');
323313
});
324314
};
325315
}];

src/ng/filter/orderBy.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ function orderByFilter($parse){
144144
return 0;
145145
}
146146
function reverseComparator(comp, descending) {
147-
return toBoolean(descending)
147+
return descending
148148
? function(a,b){return comp(b,a);}
149149
: comp;
150150
}

test/.jshintrc

-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@
8585
"toJsonReplacer": false,
8686
"toJson": false,
8787
"fromJson": false,
88-
"toBoolean": false,
8988
"startingTag": false,
9089
"tryDecodeURIComponent": false,
9190
"parseKeyValue": false,

test/BinderSpec.js

+20
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,16 @@ describe('Binder', function() {
248248
$rootScope.hidden = 'false';
249249
$rootScope.$apply();
250250

251+
assertHidden(element);
252+
253+
$rootScope.hidden = 0;
254+
$rootScope.$apply();
255+
256+
assertVisible(element);
257+
258+
$rootScope.hidden = false;
259+
$rootScope.$apply();
260+
251261
assertVisible(element);
252262

253263
$rootScope.hidden = '';
@@ -267,6 +277,16 @@ describe('Binder', function() {
267277
$rootScope.show = 'false';
268278
$rootScope.$apply();
269279

280+
assertVisible(element);
281+
282+
$rootScope.show = false;
283+
$rootScope.$apply();
284+
285+
assertHidden(element);
286+
287+
$rootScope.show = false;
288+
$rootScope.$apply();
289+
270290
assertHidden(element);
271291

272292
$rootScope.show = '';

0 commit comments

Comments
 (0)