Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
fix($compile): correctly denormalize templates that do not use standa…
…rd interpolation symbols

In order to support third party modules that do not use the same interpolation
symbols as the main app, we implemented denormalization (see dfe9983).

This required that 3rd party modules always used the standad `{{` and `}}`
interpolation symbols, so that we could correctly denormalise them to the
current app's symbols.

The problem with this became apparent when an app template using new symbols
inadvertently contained one of the standard interpolation symbols.

E.g. `<div data-context='{"context":{"id":3,"type":"page"}}">`

The double closing curly braces were being incorrectly denormalised.

This commit fixes this by allowing the compiler to be configured to know
what symbols are being used in templates from a given module.

Now modules can specify that what interpolation symbols they use and the
compiler will denormalize appropriately.

Closes #6493
Closes #6453
  • Loading branch information
petebacondarwin committed May 14, 2016
commit 16682ef0cea2fdab4e081f5206dc0a7588c196a9
7 changes: 7 additions & 0 deletions src/ng/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -1292,6 +1292,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
function createGlobalRegexMatcher(str) {
return new RegExp(escapeRegExp(str), 'g');
}
function escapeSymbol(str) {
return str.replace(/./g, '\\$&');
}
var moduleSymbolMap = createMap();
var defaultSymbols = {
startSymbol: '{{',
Expand Down Expand Up @@ -1607,13 +1610,17 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {


var startSymbol = $interpolate.startSymbol(),
startSymbolRegex = createGlobalRegexMatcher(startSymbol),
endSymbol = $interpolate.endSymbol(),
endSymbolRegex = createGlobalRegexMatcher(endSymbol),
denormalizeTemplate = function(moduleName, template) {
var moduleSymbols = moduleSymbolMap[moduleName] || defaultSymbols;
if (moduleSymbols.startSymbol !== startSymbol) {
template = template.replace(startSymbolRegex, escapeSymbol);
template = template.replace(moduleSymbols.startRegex, startSymbol);
}
if (moduleSymbols.endSymbol !== endSymbol) {
template = template.replace(endSymbolRegex, escapeSymbol);
template = template.replace(moduleSymbols.endRegex, endSymbol);
}
return template;
Expand Down
43 changes: 36 additions & 7 deletions test/ng/compileSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3155,23 +3155,52 @@ describe('$compile', function() {
});
});

it('should allow modules to specify what interpolation symbol is used in templates', function() {
it('should denormalise interpolation symbols in templates correctly, if different to the current symbols', function() {
angular.module('symbol-test', [])
.directive('myDirective', function() {
return {
template: '<span foo=\'{"ctx":{"id":3}}\'></span>'
template: '<span foo=\'{"ctx":{"id":3}}\'>[[1 + 2]]</span>'
};
})
.config(function($compileProvider) {
$compileProvider.moduleSymbols('symbol-test', '[[', ']]');
});

module('symbol-test', function($interpolateProvider, $compileProvider) {
$interpolateProvider.startSymbol('##');
$interpolateProvider.endSymbol(']]');
$compileProvider.moduleSymbols('symbol-test', '##', ']]');
module('symbol-test');

inject(function($compile) {
element = $compile('<div><div my-directive></div></div>')($rootScope);
expect(element.children('div').children('span').attr('foo')).toBe('{"ctx":{"id":3\\}\\}');
expect(element.text()).toEqual('{{1 + 2}}');
$rootScope.$apply();
expect(element.text()).toEqual('3');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about .attr('foo') ? I believe it is still escaped and I think this is not what we want...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is what @lgalfaso was referring to in his test: #14610 (comment)

:-(

});
});


it('should escape the current interpolation symbols in templates, before denormalising, if the template module symbols are different', function() {
angular.module('symbol-test', [])
.directive('myDirective', function() {
return {
template: '<span>{[1 + 2]}[[3 + 4]]</span>'
};
})
.config(function($compileProvider) {
// Specify that the templates in this module use `[[` and `]]` interpolation symbols
$compileProvider.moduleSymbols('symbol-test', '[[', ']]');
});

module('symbol-test', function($interpolateProvider) {
// Specify that this app uses `{[` and `]}` as interpolation symbols
$interpolateProvider.startSymbol('{[');
$interpolateProvider.endSymbol(']}');
});

inject(function($compile) {
element = $compile('<div><div my-directive></div></div>')($rootScope);
expect(element.children('div').children('span').attr('foo')).toBe('{"ctx":{"id":3}}');
expect(element.text()).toEqual('\\{\\[1 + 2\\]\\}{[3 + 4]}');
$rootScope.$apply();
expect(element.text()).toEqual('{[1 + 2]}7');
});
});

Expand Down