Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

fix($compile): correctly denormalize templates that do not use standard interpolation symbols #14610

Closed
wants to merge 2 commits into from

Conversation

petebacondarwin
Copy link
Contributor

What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)

FIX

What is the current behavior? (You can also link to an open issue here)

See #6493

What is the new behavior (if this is a feature change)?

Fixed

Does this PR introduce a breaking change?

No

Please check if the PR fulfills these requirements

Other information:

** STILL NEED TO ADD DOCS **

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

…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 angular#6493
Closes angular#6453
});

module('symbol-test', function($interpolateProvider, $compileProvider) {
$interpolateProvider.startSymbol('##');
Copy link
Contributor

Choose a reason for hiding this comment

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

these two lines should not be there, as with them, the test makes no sense.

@lgalfaso
Copy link
Contributor

I see this as a feature. @petebacondarwin would it be possible to know why you think it is a fix?

@petebacondarwin
Copy link
Contributor Author

petebacondarwin commented May 14, 2016

To clarify this a bit more. If I change my interpolation symbols (in my app) to [[ and ]] then I would expect that a component with this template

<div>{a:{b:42}}</div>

to output

<div>{a:{b:42}}</div>

But it doesn’t. See http://plnkr.co/edit/s9KVOZ9srU0JfkQYPrCf?p=preview

@lgalfaso
Copy link
Contributor

Ok, but then I think that should be true in the test even without the
configuration changes to $interpolateProvider

On Saturday, May 14, 2016, Pete Bacon Darwin notifications@github.com
wrote:

To clarify this a bit more. If I change my interpolation symbols (in my
app) to [[ and ]] then I would expect that a component with this template

{a:{b:42}}

should output

{a:{b:42}}

But it doesn’t. See http://plnkr.co/edit/s9KVOZ9srU0JfkQYPrCf?p=preview


You are receiving this because you commented.
Reply to this email directly or view it on GitHub
#14610 (comment)

@petebacondarwin
Copy link
Contributor Author

Without the changes to the interpolate provider then no denormalisation occurs so the bug doesn't occur in the same way. If we have not changed the symbols when we accept that we should escape }} ourselves if they appear in the template as content.

@lgalfaso
Copy link
Contributor

Without the changes to the interpolate provider then no denormalisation occurs so the bug doesn't occur in the same way. If we have not changed the symbols when we accept that we should escape }} ourselves if they appear in the template as content.

Agree, but then $compileProvider.moduleSymbols('symbol-test', '##', ']]'); does not mean "The interpolation symbols for all templates in this module are ## and ]]" that is what most people would expect.

@petebacondarwin
Copy link
Contributor Author

petebacondarwin commented May 14, 2016

Ahah! @lgalfaso so what you are saying is that we have another issue:
if the symbols in a template do not match those in the application, then we need to escape any instance of the application symbols, in the templates, too, before we denormalise. Right?

@lgalfaso
Copy link
Contributor

implementation details a side, yes, the issue is the one stated.

@petebacondarwin
Copy link
Contributor Author

@lgalfaso here are better tests:

    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}}\'>[[1 + 2]]</span>'
          };
        });

      module('symbol-test', function($compileProvider) {
        $compileProvider.moduleSymbols('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');
      });
    });


    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>'
          };
        });

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

      inject(function($compile) {
        element = $compile('<div><div my-directive></div></div>')($rootScope);
        expect(element.text()).toEqual('\\{\\[1 + 2\\]\\}{[3 + 4]}');
        $rootScope.$apply();
        expect(element.text()).toEqual('3');
      });
    });

The second one fails at the moment.

…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 angular#6493
Closes angular#6453
@petebacondarwin
Copy link
Contributor Author

I added these tests and updated the code to make them pass.

@lgalfaso
Copy link
Contributor

@petebacondarwin I think that the solution will have to be somehow more complex. Eg

it('this works', function() {
  angular.module('symbol-test', [])
    .directive('myDirective', function() {
      return {
        template: '<span foo=\'{"ctx":{"id":3}}\'>Hi</span>'
      };
    });

  module('symbol-test');
  inject(function($compile) {
    element = $compile('<div><div my-directive></div></div>')($rootScope);
    $rootScope.$apply();
    expect(element.find('span').attr('foo')).toEqual('{"ctx":{"id":3}}');
  });
});

it('so this should work too', function() {
  angular.module('symbol-test', [])
    .directive('myDirective', function() {
      return {
        template: '<span foo=\'{"ctx":{"id":3}}\'>Hi</span>'
      };
    })
    .config(function($compileProvider) {
      $compileProvider.moduleSymbols('symbol-test', '[[', ']]');
    });

  module('symbol-test');
  inject(function($compile) {
    element = $compile('<div><div my-directive></div></div>')($rootScope);
    $rootScope.$apply();
    expect(element.find('span').attr('foo')).toEqual('{"ctx":{"id":3}}');
  });
});

@gkalpak
Copy link
Member

gkalpak commented May 16, 2016

I just realized there is another issue with template denormalization: We are not taking [ng-non-bindable] into account - we still replace the interpolation symbols 😞
(Or is this a feature ?)

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)

:-(

@petebacondarwin
Copy link
Contributor Author

Hmm looks like this could be more painful than it is worth...

@lgalfaso
Copy link
Contributor

Hmm looks like this could be more painful than it is worth...

yep

@petebacondarwin
Copy link
Contributor Author

Perhaps another one for the "known issues" pile?

@gkalpak
Copy link
Member

gkalpak commented May 16, 2016

another one

More like "a couple more" 😛

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants