fix($parse): treat falsy values as defined in assignment expressions
Closes #14990 Closes #14994
This commit is contained in:
committed by
Lucas Mirelmann
parent
606ea5d23e
commit
4f44e01894
+8
-4
@@ -944,7 +944,7 @@ ASTCompiler.prototype = {
|
||||
self.if_(self.stage === 'inputs' || 's', function() {
|
||||
if (create && create !== 1) {
|
||||
self.if_(
|
||||
self.not(self.nonComputedMember('s', ast.name)),
|
||||
self.isNull(self.nonComputedMember('s', ast.name)),
|
||||
self.lazyAssign(self.nonComputedMember('s', ast.name), '{}'));
|
||||
}
|
||||
self.assign(intoId, self.nonComputedMember('s', ast.name));
|
||||
@@ -973,7 +973,7 @@ ASTCompiler.prototype = {
|
||||
}
|
||||
} else {
|
||||
if (create && create !== 1) {
|
||||
self.if_(self.not(self.nonComputedMember(left, ast.property.name)), self.lazyAssign(self.nonComputedMember(left, ast.property.name), '{}'));
|
||||
self.if_(self.isNull(self.nonComputedMember(left, ast.property.name)), self.lazyAssign(self.nonComputedMember(left, ast.property.name), '{}'));
|
||||
}
|
||||
expression = self.nonComputedMember(left, ast.property.name);
|
||||
self.assign(intoId, expression);
|
||||
@@ -1155,6 +1155,10 @@ ASTCompiler.prototype = {
|
||||
return '!(' + expression + ')';
|
||||
},
|
||||
|
||||
isNull: function(expression) {
|
||||
return expression + '==null';
|
||||
},
|
||||
|
||||
notNull: function(expression) {
|
||||
return expression + '!=null';
|
||||
},
|
||||
@@ -1546,7 +1550,7 @@ ASTInterpreter.prototype = {
|
||||
identifier: function(name, context, create, expression) {
|
||||
return function(scope, locals, assign, inputs) {
|
||||
var base = locals && (name in locals) ? locals : scope;
|
||||
if (create && create !== 1 && base && !(base[name])) {
|
||||
if (create && create !== 1 && base && base[name] == null) {
|
||||
base[name] = {};
|
||||
}
|
||||
var value = base ? base[name] : undefined;
|
||||
@@ -1583,7 +1587,7 @@ ASTInterpreter.prototype = {
|
||||
return function(scope, locals, assign, inputs) {
|
||||
var lhs = left(scope, locals, assign, inputs);
|
||||
if (create && create !== 1) {
|
||||
if (lhs && !(lhs[right])) {
|
||||
if (lhs && lhs[right] == null) {
|
||||
lhs[right] = {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3155,6 +3155,72 @@ describe('parser', function() {
|
||||
expect(isFunction(s.toString)).toBe(true);
|
||||
expect(l.toString).toBe(1);
|
||||
}));
|
||||
|
||||
it('should overwrite undefined / null scope properties when assigning', inject(function($parse) {
|
||||
var scope;
|
||||
|
||||
scope = {};
|
||||
$parse('a.b = 1')(scope);
|
||||
$parse('c["d"] = 2')(scope);
|
||||
expect(scope).toEqual({a: {b: 1}, c: {d: 2}});
|
||||
|
||||
scope = {a: {}};
|
||||
$parse('a.b.c = 1')(scope);
|
||||
$parse('a.c["d"] = 2')(scope);
|
||||
expect(scope).toEqual({a: {b: {c: 1}, c: {d: 2}}});
|
||||
|
||||
scope = {a: undefined, c: undefined};
|
||||
$parse('a.b = 1')(scope);
|
||||
$parse('c["d"] = 2')(scope);
|
||||
expect(scope).toEqual({a: {b: 1}, c: {d: 2}});
|
||||
|
||||
scope = {a: {b: undefined, c: undefined}};
|
||||
$parse('a.b.c = 1')(scope);
|
||||
$parse('a.c["d"] = 2')(scope);
|
||||
expect(scope).toEqual({a: {b: {c: 1}, c: {d: 2}}});
|
||||
|
||||
scope = {a: null, c: null};
|
||||
$parse('a.b = 1')(scope);
|
||||
$parse('c["d"] = 2')(scope);
|
||||
expect(scope).toEqual({a: {b: 1}, c: {d: 2}});
|
||||
|
||||
scope = {a: {b: null, c: null}};
|
||||
$parse('a.b.c = 1')(scope);
|
||||
$parse('a.c["d"] = 2')(scope);
|
||||
expect(scope).toEqual({a: {b: {c: 1}, c: {d: 2}}});
|
||||
}));
|
||||
|
||||
they('should not overwrite $prop scope properties when assigning', [0, false, '', NaN],
|
||||
function(falsyValue) {
|
||||
inject(function($parse) {
|
||||
var scope;
|
||||
|
||||
scope = {a: falsyValue, c: falsyValue};
|
||||
tryParseAndIgnoreException('a.b = 1');
|
||||
tryParseAndIgnoreException('c["d"] = 2');
|
||||
expect(scope).toEqual({a: falsyValue, c: falsyValue});
|
||||
|
||||
scope = {a: {b: falsyValue, c: falsyValue}};
|
||||
tryParseAndIgnoreException('a.b.c = 1');
|
||||
tryParseAndIgnoreException('a.c["d"] = 2');
|
||||
expect(scope).toEqual({a: {b: falsyValue, c: falsyValue}});
|
||||
|
||||
// Helpers
|
||||
//
|
||||
// Normally assigning property on a primitive should throw exception in strict mode
|
||||
// and silently fail in non-strict mode, IE seems to always have the non-strict-mode behavior,
|
||||
// so if we try to use 'expect(function() {$parse('a.b=1')({a:false});).toThrow()' for testing
|
||||
// the test will fail in case of IE because it will not throw exception, and if we just use
|
||||
// '$parse('a.b=1')({a:false})' the test will fail because it will throw exception in case of Chrome
|
||||
// so we use tryParseAndIgnoreException helper to catch the exception silently for all cases.
|
||||
//
|
||||
function tryParseAndIgnoreException(expression) {
|
||||
try {
|
||||
$parse(expression)(scope);
|
||||
} catch (error) {/* ignore exception */}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('literal', function() {
|
||||
|
||||
Reference in New Issue
Block a user