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

Commit 3bf86d2

Browse files
committed
fixup! feat($compile): add support for arbitrary property and event bindings
1 parent 2114037 commit 3bf86d2

File tree

3 files changed

+23
-28
lines changed

3 files changed

+23
-28
lines changed
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
@ngdoc error
22
@name $compile:ctxoverride
3-
@fullName Context Override
3+
@fullName DOM Property Security Context Overrid
44
@description
55

6-
This error occurs when the security context for a property is defined multiple times under different security contexts.
6+
This error occurs when the security context for a property is defined via {@link ng.$compilerProvider#addPropertySecurityContext addPropertySecurityContext()} multiple times under different security contexts.
77

88
For example:
99

10-
```
11-
$compileProvider.addPropertySecurityContext("my-element", "src", "mediaUrl");
12-
$compileProvider.addPropertySecurityContext("my-element", "src", "resourceUrl"); //throws
10+
```js
11+
$compileProvider.addPropertySecurityContext("my-element", "src", $sce.MEDIA_URL);
12+
$compileProvider.addPropertySecurityContext("my-element", "src", $sce.RESOURCE_URL); //throws
1313
```

src/ng/compile.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,19 +1592,19 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
15921592
* The security context of DOM Properties.
15931593
* @private
15941594
*/
1595-
var PROP_CONTEXTS = Object.create(null);
1595+
var PROP_CONTEXTS = createMap();
15961596

15971597
/**
15981598
* @ngdoc method
15991599
* @name $compileProvider#addPropertySecurityContext
16001600
* @description
16011601
*
1602-
* Defines the security context for DOM properties bound by ng-prop-*
1602+
* Defines the security context for DOM properties bound by ng-prop-*.
16031603
*
16041604
* @param {string} elementName The element name or '*' to match any element.
16051605
* @param {string} propertyName The DOM property name.
1606-
* @param {string} ctx The context in which this value is safe for use, e.g. $sce.URL,
1607-
* $sce.RESOURCE_URL, $sce.HTML, $sce.JS or $sce.CSS.
1606+
* @param {string} ctx The {@link $sce} security context in which this value is safe for use, e.g. `$sce.URL`
1607+
* @returns {object} `this` for chaining
16081608
*/
16091609
this.addPropertySecurityContext = function(elementName, propertyName, ctx) {
16101610
var key = (elementName.toLowerCase() + '|' + propertyName.toLowerCase());
@@ -1614,6 +1614,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16141614
}
16151615

16161616
PROP_CONTEXTS[key] = ctx;
1617+
return this;
16171618
};
16181619

16191620
/* Default property contexts.

test/ng/compileSpec.js

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11395,15 +11395,14 @@ describe('$compile', function() {
1139511395
}));
1139611396

1139711397
it('should use $$sanitizeUri', function() {
11398-
var $$sanitizeUri = jasmine.createSpy('$$sanitizeUri');
11398+
var $$sanitizeUri = jasmine.createSpy('$$sanitizeUri').and.returnValue('someSanitizedUrl');
1139911399
module(function($provide) {
1140011400
$provide.value('$$sanitizeUri', $$sanitizeUri);
1140111401
});
1140211402
inject(function($compile, $rootScope) {
1140311403
element = $compile('<img src="{{testUrl}}"></img>')($rootScope);
1140411404
$rootScope.testUrl = 'someUrl';
1140511405

11406-
$$sanitizeUri.and.returnValue('someSanitizedUrl');
1140711406
$rootScope.$apply();
1140811407
expect(element.attr('src')).toBe('someSanitizedUrl');
1140911408
expect($$sanitizeUri).toHaveBeenCalledWith($rootScope.testUrl, true);
@@ -11480,7 +11479,7 @@ describe('$compile', function() {
1148011479
expect(element.attr('srcset')).toEqual('http://example.com');
1148111480
}));
1148211481

11483-
it('does not work with trusted values', inject(function($rootScope, $compile, $sce) {
11482+
it('should NOT work with trusted values', inject(function($rootScope, $compile, $sce) {
1148411483
// A limitation of the approach used for srcset is that you cannot use `trustAsUrl`.
1148511484
// Use trustAsHtml and ng-bind-html to work around this.
1148611485
element = $compile('<img srcset="{{testUrl}}"></img>')($rootScope);
@@ -11830,7 +11829,7 @@ describe('$compile', function() {
1183011829
}));
1183111830

1183211831

11833-
it('should pass through $sce.trustAs() values in action attribute', inject(function($compile, $rootScope, $sce) {
11832+
it('should pass through $sce.trustAsResourceUrl() values in action attribute', inject(function($compile, $rootScope, $sce) {
1183411833
element = $compile('<form action="{{testUrl}}"></form>')($rootScope);
1183511834
$rootScope.testUrl = $sce.trustAsResourceUrl('javascript:doTrustedStuff()');
1183611835
$rootScope.$apply();
@@ -12046,7 +12045,7 @@ describe('$compile', function() {
1204612045
expect(attrs.ngAttrSuperTitle).toBeUndefined();
1204712046
expect(attrs.$attr.ngAttrSuperTitle).toBeUndefined();
1204812047

12049-
//Note the casing is incorrect: https://github.com/angular/angular.js/issues/16624
12048+
// Note the casing is incorrect: https://github.com/angular/angular.js/issues/16624
1205012049
expect(attrs.myCameltitle).toBe('56');
1205112050
expect(attrs.$attr.myCameltitle).toBe('my-camelTitle');
1205212051
expect(attrs.ngAttrMyCameltitle).toBeUndefined();
@@ -12163,14 +12162,11 @@ describe('$compile', function() {
1216312162

1216412163
it('should call the listener synchronously', inject(function($compile, $rootScope) {
1216512164
element = $compile('<span ng-on-foo="fooEvent()"></span>')($rootScope);
12166-
$rootScope.fooEvent = jasmine.createSpy('fooEvent').and.callFake(function() {
12167-
$rootScope.value = 'newValue';
12168-
});
12165+
$rootScope.fooEvent = jasmine.createSpy('fooEvent');
1216912166

1217012167
element.triggerHandler('foo');
1217112168

1217212169
expect($rootScope.fooEvent).toHaveBeenCalledOnce();
12173-
expect($rootScope.value).toBe('newValue');
1217412170
}));
1217512171

1217612172
it('should support multiple events on a single element', inject(function($compile, $rootScope) {
@@ -12262,7 +12258,7 @@ describe('$compile', function() {
1226212258
$rootScope.value = 'test';
1226312259
element = $compile('<a ng-prop-href="\'test/\' + value"></a>')($rootScope);
1226412260
$rootScope.$digest();
12265-
expect(element.prop('href').slice(-'/test/test'.length)).toBe('/test/test');
12261+
expect(element.prop('href')).toMatch(/\/test\/test$/);
1226612262
}));
1226712263

1226812264
it('should work if they are prefixed with x- or data- and different prefixes', inject(function($rootScope, $compile) {
@@ -12309,7 +12305,7 @@ describe('$compile', function() {
1230912305
});
1231012306
inject(function($compile, $rootScope) {
1231112307
$compile('<div attr-exposer ng-prop-title="12" ng-prop-super-title="34" ng-prop-my-camel_title="56">')($rootScope);
12312-
$rootScope.$apply();
12308+
$rootScope.$digest();
1231312309

1231412310
expect(attrs.title).toBeUndefined();
1231512311
expect(attrs.$attr.title).toBeUndefined();
@@ -12348,7 +12344,6 @@ describe('$compile', function() {
1234812344

1234912345
it('should disallow property binding to onclick', inject(function($compile, $rootScope) {
1235012346
// All event prop bindings are disallowed.
12351-
$rootScope.onClickJs = function() {};
1235212347
expect(function() {
1235312348
$compile('<button ng-prop-onclick="onClickJs"></script>');
1235412349
}).toThrowMinErr(
@@ -12491,15 +12486,14 @@ describe('$compile', function() {
1249112486
}));
1249212487

1249312488
it('should use $$sanitizeUri', function() {
12494-
var $$sanitizeUri = jasmine.createSpy('$$sanitizeUri');
12489+
var $$sanitizeUri = jasmine.createSpy('$$sanitizeUri').and.returnValue('someSanitizedUrl');
1249512490
module(function($provide) {
1249612491
$provide.value('$$sanitizeUri', $$sanitizeUri);
1249712492
});
1249812493
inject(function($compile, $rootScope) {
1249912494
element = $compile('<img ng-prop-src="testUrl"></img>')($rootScope);
1250012495
$rootScope.testUrl = 'someUrl';
1250112496

12502-
$$sanitizeUri.and.returnValue('someSanitizedUrl');
1250312497
$rootScope.$apply();
1250412498
expect(element.prop('src')).toMatch(/^http:\/\/.*\/someSanitizedUrl$/);
1250512499
expect($$sanitizeUri).toHaveBeenCalledWith($rootScope.testUrl, true);
@@ -12524,14 +12518,14 @@ describe('$compile', function() {
1252412518

1252512519
['img', 'source'].forEach(function(srcsetElement) {
1252612520
describe(srcsetElement + '[srcset] sanitization', function() {
12527-
it('should not error if srcset is undefined', inject(function($compile, $rootScope) {
12521+
it('should not error if srcset is blank', inject(function($compile, $rootScope) {
1252812522
element = $compile('<' + srcsetElement + ' ng-prop-srcset="testUrl"></' + srcsetElement + '>')($rootScope);
1252912523
// Set srcset to a value
1253012524
$rootScope.testUrl = 'http://example.com/';
1253112525
$rootScope.$digest();
1253212526
expect(element.prop('srcset')).toBe('http://example.com/');
1253312527

12534-
// Now set it to undefined
12528+
// Now set it to blank
1253512529
$rootScope.testUrl = '';
1253612530
$rootScope.$digest();
1253712531
expect(element.prop('srcset')).toBe('');
@@ -12551,7 +12545,7 @@ describe('$compile', function() {
1255112545
expect(element.prop('srcset')).toEqual('http://example.com');
1255212546
}));
1255312547

12554-
it('does not work with trusted values', inject(function($rootScope, $compile, $sce) {
12548+
it('should NOT work with trusted values', inject(function($rootScope, $compile, $sce) {
1255512549
// A limitation of the approach used for srcset is that you cannot use `trustAsUrl`.
1255612550
// Use trustAsHtml and ng-bind-html to work around this.
1255712551
element = $compile('<' + srcsetElement + ' ng-prop-srcset="testUrl"></' + srcsetElement + '>')($rootScope);
@@ -12806,7 +12800,7 @@ describe('$compile', function() {
1280612800
}));
1280712801

1280812802

12809-
it('should pass through $sce.trustAs() values in action property', inject(function($compile, $rootScope, $sce) {
12803+
it('should pass through $sce.trustAsResourceUrl() values in action property', inject(function($compile, $rootScope, $sce) {
1281012804
element = $compile('<form ng-prop-action="testUrl"></form>')($rootScope);
1281112805
$rootScope.testUrl = $sce.trustAsResourceUrl('javascript:doTrustedStuff()');
1281212806
$rootScope.$apply();
@@ -12983,7 +12977,7 @@ describe('$compile', function() {
1298312977
describe('addPropertySecurityContext', function() {
1298412978
function testProvider(provider) {
1298512979
module(provider);
12986-
inject(function($compile) { /* done! */});
12980+
inject(function($compile) { /* done! */ });
1298712981
}
1298812982

1298912983
it('should allow adding new properties', function() {

0 commit comments

Comments
 (0)