diff --git a/modules/angular2/src/transform/template_compiler/change_detector_codegen.dart b/modules/angular2/src/transform/template_compiler/change_detector_codegen.dart index 86beb32010..17184336cd 100644 --- a/modules/angular2/src/transform/template_compiler/change_detector_codegen.dart +++ b/modules/angular2/src/transform/template_compiler/change_detector_codegen.dart @@ -142,7 +142,7 @@ class _CodegenState { $_changeDetectorTypeName( this.$_DISPATCHER_ACCESSOR, this.$_PROTOS_ACCESSOR, - this.$_DIRECTIVES_ACCESSOR) : super(${JSON.encode(_changeDetectorDefId)}); + this.$_DIRECTIVES_ACCESSOR) : super(${_encodeValue(_changeDetectorDefId)}); void detectChangesInRecords(throwOnChange) { if (!hydrated()) { @@ -383,7 +383,7 @@ class _CodegenState { break; case RecordType.CONST: - rhs = JSON.encode(r.funcOrValue); + rhs = _encodeValue(r.funcOrValue); break; case RecordType.PROPERTY: @@ -435,9 +435,9 @@ class _CodegenState { for (var i = 0; i < r.args.length; ++i) { var name = _localNames[r.args[i]]; 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'; } @@ -523,6 +523,9 @@ class _CodegenState { } '''; } + + String _encodeValue(funcOrValue) => + JSON.encode(funcOrValue).replaceAll(r'$', r'\$'); } const PROTO_CHANGE_DETECTOR_FACTORY_METHOD = 'newProtoChangeDetector'; diff --git a/modules/angular2/test/change_detection/change_detector_config.ts b/modules/angular2/test/change_detection/change_detector_config.ts index 394ab340e3..9c52bc882f 100644 --- a/modules/angular2/test/change_detection/change_detector_config.ts +++ b/modules/angular2/test/change_detection/change_detector_config.ts @@ -263,6 +263,7 @@ class _DirectiveUpdating { * equivalent to their ids. */ var _availableDefinitions = [ + '"$"', '10', '"str"', '"a\n\nb"', diff --git a/modules/angular2/test/change_detection/change_detector_spec.ts b/modules/angular2/test/change_detection/change_detector_spec.ts index cc888847c4..da119ffa90 100644 --- a/modules/angular2/test/change_detection/change_detector_spec.ts +++ b/modules/angular2/test/change_detection/change_detector_spec.ts @@ -302,6 +302,9 @@ export function main() { expect(val.dispatcher.log).toEqual(['propName=BvalueA']); }); + it('should escape values in literals that indicate interpolation', + () => { expect(_bindSimpleValue('"$"')).toEqual(['propName=$']); }); + describe('pure functions', () => { it('should preserve memoized result', () => { var person = new Person('bob'); diff --git a/modules/angular2/test/change_detection/generator/gen_change_detectors.dart b/modules/angular2/test/change_detection/generator/gen_change_detectors.dart index ae88f9f8d3..3b197be0ca 100644 --- a/modules/angular2/test/change_detection/generator/gen_change_detectors.dart +++ b/modules/angular2/test/change_detection/generator/gen_change_detectors.dart @@ -21,7 +21,7 @@ void main(List args) { if (i > 0) { buf.write(','); } - buf.write(" '''${allDefs[i].cdDef.id}''': " + buf.write(" '''${_escape(allDefs[i].cdDef.id)}''': " "$className.$PROTO_CHANGE_DETECTOR_FACTORY_METHOD"); } buf.write('};'); @@ -37,4 +37,6 @@ void main(List args) { ''')); } +String _escape(String id) => id.replaceAll(r'$', r'\$'); + const _MAP_NAME = '_idToProtoMap';