fix(change_detect): Handle '$' in change detector strings

In Dart, '$' indicates the beginning of an interpolation.
- Escapes '$' in strings when generating change detector classes.
- Adds a unit test to cover this case.
This commit is contained in:
Tim Blasi 2015-07-16 11:08:47 -07:00
parent 621604dc66
commit f1e8176995
4 changed files with 14 additions and 5 deletions

View File

@ -142,7 +142,7 @@ class _CodegenState {
$_changeDetectorTypeName( $_changeDetectorTypeName(
this.$_DISPATCHER_ACCESSOR, this.$_DISPATCHER_ACCESSOR,
this.$_PROTOS_ACCESSOR, this.$_PROTOS_ACCESSOR,
this.$_DIRECTIVES_ACCESSOR) : super(${JSON.encode(_changeDetectorDefId)}); this.$_DIRECTIVES_ACCESSOR) : super(${_encodeValue(_changeDetectorDefId)});
void detectChangesInRecords(throwOnChange) { void detectChangesInRecords(throwOnChange) {
if (!hydrated()) { if (!hydrated()) {
@ -383,7 +383,7 @@ class _CodegenState {
break; break;
case RecordType.CONST: case RecordType.CONST:
rhs = JSON.encode(r.funcOrValue); rhs = _encodeValue(r.funcOrValue);
break; break;
case RecordType.PROPERTY: case RecordType.PROPERTY:
@ -435,9 +435,9 @@ class _CodegenState {
for (var i = 0; i < r.args.length; ++i) { for (var i = 0; i < r.args.length; ++i) {
var name = _localNames[r.args[i]]; var name = _localNames[r.args[i]];
res.write( res.write(
'${JSON.encode(r.fixedArgs[i])} "\$\{$name == null ? "" : $name\}" '); '${_encodeValue(r.fixedArgs[i])} "\$\{$name == null ? "" : $name\}" ');
} }
res.write(JSON.encode(r.fixedArgs[r.args.length])); res.write(_encodeValue(r.fixedArgs[r.args.length]));
return '$res'; return '$res';
} }
@ -523,6 +523,9 @@ class _CodegenState {
} }
'''; ''';
} }
String _encodeValue(funcOrValue) =>
JSON.encode(funcOrValue).replaceAll(r'$', r'\$');
} }
const PROTO_CHANGE_DETECTOR_FACTORY_METHOD = 'newProtoChangeDetector'; const PROTO_CHANGE_DETECTOR_FACTORY_METHOD = 'newProtoChangeDetector';

View File

@ -263,6 +263,7 @@ class _DirectiveUpdating {
* equivalent to their ids. * equivalent to their ids.
*/ */
var _availableDefinitions = [ var _availableDefinitions = [
'"$"',
'10', '10',
'"str"', '"str"',
'"a\n\nb"', '"a\n\nb"',

View File

@ -302,6 +302,9 @@ export function main() {
expect(val.dispatcher.log).toEqual(['propName=BvalueA']); expect(val.dispatcher.log).toEqual(['propName=BvalueA']);
}); });
it('should escape values in literals that indicate interpolation',
() => { expect(_bindSimpleValue('"$"')).toEqual(['propName=$']); });
describe('pure functions', () => { describe('pure functions', () => {
it('should preserve memoized result', () => { it('should preserve memoized result', () => {
var person = new Person('bob'); var person = new Person('bob');

View File

@ -21,7 +21,7 @@ void main(List<String> args) {
if (i > 0) { if (i > 0) {
buf.write(','); buf.write(',');
} }
buf.write(" '''${allDefs[i].cdDef.id}''': " buf.write(" '''${_escape(allDefs[i].cdDef.id)}''': "
"$className.$PROTO_CHANGE_DETECTOR_FACTORY_METHOD"); "$className.$PROTO_CHANGE_DETECTOR_FACTORY_METHOD");
} }
buf.write('};'); buf.write('};');
@ -37,4 +37,6 @@ void main(List<String> args) {
''')); '''));
} }
String _escape(String id) => id.replaceAll(r'$', r'\$');
const _MAP_NAME = '_idToProtoMap'; const _MAP_NAME = '_idToProtoMap';