Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 26d43ca

Browse files
Caitlin PotterIgorMinar
Caitlin Potter
authored andcommitted
fix($parse): return 'undefined' if a middle key's value is null
Prior to this fix, $parse/$eval would return 'null' if a middle key in an expression's value is null, when it should be expected to be undefined. This patch tries to remedy this by returning undefined for middle values in expressions, when fetching a child of that null value. For example: ```js // Given the following object: $scope.a = { b: null }; // $scope.$eval('a.b.c') returns undefined, whereas previously it would return null ``` Closes #5480
1 parent 4f5758e commit 26d43ca

File tree

2 files changed

+61
-13
lines changed

2 files changed

+61
-13
lines changed

src/ng/parse.js

+12-13
Original file line numberDiff line numberDiff line change
@@ -894,16 +894,16 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
894894
if (pathVal == null) return pathVal;
895895
pathVal = pathVal[key0];
896896

897-
if (!key1 || pathVal == null) return pathVal;
897+
if (pathVal == null) return key1 ? undefined : pathVal;
898898
pathVal = pathVal[key1];
899899

900-
if (!key2 || pathVal == null) return pathVal;
900+
if (pathVal == null) return key2 ? undefined : pathVal;
901901
pathVal = pathVal[key2];
902902

903-
if (!key3 || pathVal == null) return pathVal;
903+
if (pathVal == null) return key3 ? undefined : pathVal;
904904
pathVal = pathVal[key3];
905905

906-
if (!key4 || pathVal == null) return pathVal;
906+
if (pathVal == null) return key4 ? undefined : pathVal;
907907
pathVal = pathVal[key4];
908908

909909
return pathVal;
@@ -924,7 +924,7 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
924924
}
925925
pathVal = pathVal.$$v;
926926
}
927-
if (!key1 || pathVal == null) return pathVal;
927+
if (pathVal == null) return key1 ? undefined : pathVal;
928928

929929
pathVal = pathVal[key1];
930930
if (pathVal && pathVal.then) {
@@ -936,7 +936,7 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
936936
}
937937
pathVal = pathVal.$$v;
938938
}
939-
if (!key2 || pathVal == null) return pathVal;
939+
if (pathVal == null) return key2 ? undefined : pathVal;
940940

941941
pathVal = pathVal[key2];
942942
if (pathVal && pathVal.then) {
@@ -948,7 +948,7 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
948948
}
949949
pathVal = pathVal.$$v;
950950
}
951-
if (!key3 || pathVal == null) return pathVal;
951+
if (pathVal == null) return key3 ? undefined : pathVal;
952952

953953
pathVal = pathVal[key3];
954954
if (pathVal && pathVal.then) {
@@ -960,7 +960,7 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
960960
}
961961
pathVal = pathVal.$$v;
962962
}
963-
if (!key4 || pathVal == null) return pathVal;
963+
if (pathVal == null) return key4 ? undefined : pathVal;
964964

965965
pathVal = pathVal[key4];
966966
if (pathVal && pathVal.then) {
@@ -980,7 +980,7 @@ function simpleGetterFn1(key0, fullExp) {
980980
ensureSafeMemberName(key0, fullExp);
981981

982982
return function simpleGetterFn1(scope, locals) {
983-
if (scope == null) return scope;
983+
if (scope == null) return undefined;
984984
return ((locals && locals.hasOwnProperty(key0)) ? locals : scope)[key0];
985985
};
986986
}
@@ -990,10 +990,9 @@ function simpleGetterFn2(key0, key1, fullExp) {
990990
ensureSafeMemberName(key1, fullExp);
991991

992992
return function simpleGetterFn2(scope, locals) {
993-
if (scope == null) return scope;
993+
if (scope == null) return undefined;
994994
scope = ((locals && locals.hasOwnProperty(key0)) ? locals : scope)[key0];
995-
996-
return scope == null ? scope : scope[key1];
995+
return scope == null ? undefined : scope[key1];
997996
};
998997
}
999998

@@ -1036,7 +1035,7 @@ function getterFn(path, options, fullExp) {
10361035
var code = 'var p;\n';
10371036
forEach(pathKeys, function(key, index) {
10381037
ensureSafeMemberName(key, fullExp);
1039-
code += 'if(s == null) return s;\n' +
1038+
code += 'if(s == null) return undefined;\n' +
10401039
's='+ (index
10411040
// we simply dereference 's' on any .dot notation
10421041
? 's'

test/ng/parseSpec.js

+49
Original file line numberDiff line numberDiff line change
@@ -977,6 +977,55 @@ describe('parser', function() {
977977
expect($parse('"name" + id').constant).toBe(false);
978978
}));
979979
});
980+
981+
describe('nulls in expressions', function() {
982+
// simpleGetterFn1
983+
it('should return null for `a` where `a` is null', inject(function($rootScope) {
984+
$rootScope.a = null;
985+
expect($rootScope.$eval('a')).toBe(null);
986+
}));
987+
988+
it('should return undefined for `a` where `a` is undefined', inject(function($rootScope) {
989+
expect($rootScope.$eval('a')).toBeUndefined();
990+
}));
991+
992+
// simpleGetterFn2
993+
it('should return undefined for properties of `null` constant', inject(function($rootScope) {
994+
expect($rootScope.$eval('null.a')).toBeUndefined();
995+
}));
996+
997+
it('should return undefined for properties of `null` values', inject(function($rootScope) {
998+
$rootScope.a = null;
999+
expect($rootScope.$eval('a.b')).toBeUndefined();
1000+
}));
1001+
1002+
it('should return null for `a.b` where `b` is null', inject(function($rootScope) {
1003+
$rootScope.a = { b: null };
1004+
expect($rootScope.$eval('a.b')).toBe(null);
1005+
}));
1006+
1007+
// cspSafeGetter && pathKeys.length < 6 || pathKeys.length > 2
1008+
it('should return null for `a.b.c.d.e` where `e` is null', inject(function($rootScope) {
1009+
$rootScope.a = { b: { c: { d: { e: null } } } };
1010+
expect($rootScope.$eval('a.b.c.d.e')).toBe(null);
1011+
}));
1012+
1013+
it('should return undefined for `a.b.c.d.e` where `d` is null', inject(function($rootScope) {
1014+
$rootScope.a = { b: { c: { d: null } } };
1015+
expect($rootScope.$eval('a.b.c.d.e')).toBeUndefined();
1016+
}));
1017+
1018+
// cspSafeGetter || pathKeys.length > 6
1019+
it('should return null for `a.b.c.d.e.f.g` where `g` is null', inject(function($rootScope) {
1020+
$rootScope.a = { b: { c: { d: { e: { f: { g: null } } } } } };
1021+
expect($rootScope.$eval('a.b.c.d.e.f.g')).toBe(null);
1022+
}));
1023+
1024+
it('should return undefined for `a.b.c.d.e.f.g` where `f` is null', inject(function($rootScope) {
1025+
$rootScope.a = { b: { c: { d: { e: { f: null } } } } };
1026+
expect($rootScope.$eval('a.b.c.d.e.f.g')).toBeUndefined();
1027+
}));
1028+
});
9801029
});
9811030
});
9821031
});

0 commit comments

Comments
 (0)