Skip to content
This repository has been archived by the owner on Feb 22, 2018. It is now read-only.

Commit

Permalink
fix(parser): Makes the setter code more robust.
Browse files Browse the repository at this point in the history
  • Loading branch information
jbdeboer committed Jul 31, 2013
1 parent 4932b3f commit 7ee8934
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 11 deletions.
24 changes: 13 additions & 11 deletions lib/parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -216,22 +216,18 @@ setterChild(obj, childKey, value) {

InstanceMirror instanceMirror = reflect(obj);
Symbol curSym = new Symbol(childKey);
try {
// maybe it is a member field?
return instanceMirror.setField(curSym, value).reflectee;
} catch (e) {
throw "$e \n\n${e.stacktrace}";
}
// maybe it is a member field?
return instanceMirror.setField(curSym, value).reflectee;
}

setter(obj, path, setValue) {
var element = path.split('.');
for (var i = 0; element.length > 1; i++) {
var key = element.removeAt(0);
var propertyObj = obj[key];
var propertyObj = getterChild(obj, key)[1];
if (propertyObj == null) {
propertyObj = {};
obj[key] = propertyObj;
setterChild(obj, key, propertyObj);
}
obj = propertyObj;
}
Expand Down Expand Up @@ -494,7 +490,8 @@ class Parser {
'at column ${t.index + 1} in';
return 'Parser Error: $s $location [$text]';
}
evalError(String s) => 'Eval Error: $s while evaling [$text]';
evalError(String s, [stack]) => 'Eval Error: $s while evaling [$text]' +
(stack != null ? '\n\nFROM:\n$stack' : '');

Token peekToken() {
if (tokens.length == 0)
Expand Down Expand Up @@ -680,8 +677,13 @@ class Parser {
throw parserError('Expression ${tokensText(ts)} is not assignable', token);
}
right = logicalOR();
return new ParsedFn((scope, locals) =>
left.assign(scope, right(scope, locals), locals));
return new ParsedFn((scope, locals) {
try {
return left.assign(scope, right(scope, locals), locals);
} catch (e, s) {
throw evalError('Caught $e', s);
}
});
} else {
return left;
}
Expand Down
95 changes: 95 additions & 0 deletions test/parser_spec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,82 @@ main() {
});
});

describe('setters', () {
it('should set a field in a map', () {
scope['map'] = {};
eval('map["square"] = 6');
eval('map.dot = 7');

expect(scope['map']['square']).toEqual(6);
expect(scope['map']['dot']).toEqual(7);
});


it('should set a field in a list', () {
scope['list'] = [];
eval('list[3] = 2');

expect(scope['list'].length).toEqual(4);
expect(scope['list'][3]).toEqual(2);
});


it('should set a field on an object', () {
scope['obj'] = new SetterObject();
eval('obj.field = 1');

expect(scope['obj'].field).toEqual(1);
});


it('should set a setter on an object', () {
scope['obj'] = new SetterObject();
eval('obj.setter = 2');

expect(scope['obj'].setterValue).toEqual(2);
});


it('should set a []= on an object', () {
scope['obj'] = new OverloadObject();
eval('obj.overload = 7');

expect(scope['obj'].overloadValue).toEqual(7);
});


it('should set a field in a nested map on an object', () {
scope['obj'] = new SetterObject();
eval('obj.map.mapKey = 3');

expect(scope['obj'].map['mapKey']).toEqual(3);
});


it('should set a field in a nested object on an object', () {
scope['obj'] = new SetterObject();
eval('obj.nested.field = 1');

expect(scope['obj'].nested.field).toEqual(1);
});


it('should create a map for dotted acces', () {
scope['obj'] = new SetterObject();
eval('obj.field.key = 4');

expect(scope['obj'].field['key']).toEqual(4);
});


it('should throw a nice error for type mismatch', () {
scope['obj'] = new SetterObject();
expect(() {
eval('obj.integer = "hello"');
}).toThrow("Eval Error: Caught type 'String' is not a subtype of type 'int' of 'value'. while evaling [obj.integer = \"hello\"]");
});
});

describe('test cases imported from AngularJS', () {
//// ==== IMPORTED ITs
it('should parse expressions', () {
Expand Down Expand Up @@ -809,6 +885,25 @@ main() {
});
}

class SetterObject {
var field;
int integer;
var map = {};

var nest;
SetterObject get nested => nest != null ? nest : (nest = new SetterObject());

var setterValue;
void set setter(x) { setterValue = x; }
}

class OverloadObject {
var overloadValue;
operator []=(String name, var value) {
overloadValue = value;
}
}

class ScopeWithErrors {
String get boo { dump("got a boo"); throw "boo to you"; }
String foo() { dump("got a foo"); throw "foo to you"; }
Expand Down

0 comments on commit 7ee8934

Please sign in to comment.