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

Commit 7f2af3f

Browse files
frederikprijckgkalpak
authored andcommitted
fix($compile): allow the usage of "$" in isolate scope property alias
Previously, when using an alias for an isolate scope or `bindings` property (e.g. `alias: '<attrName'` instead of `attrName: '<'`), a `$compile:iscp` error was thrown if the attribute name contained a "$". This commit removes the error by changing the regex to allow "$" characters in the attribute name when using a property alias. Fixes: #15586 Closes #15594
1 parent cce98ff commit 7f2af3f

File tree

2 files changed

+56
-15
lines changed

2 files changed

+56
-15
lines changed

src/ng/compile.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
983983
var bindingCache = createMap();
984984

985985
function parseIsolateBindings(scope, directiveName, isController) {
986-
var LOCAL_REGEXP = /^\s*([@&<]|=(\*?))(\??)\s*(\w*)\s*$/;
986+
var LOCAL_REGEXP = /^\s*([@&<]|=(\*?))(\??)\s*([\w$]*)\s*$/;
987987

988988
var bindings = createMap();
989989

test/ng/compileSpec.js

+55-14
Original file line numberDiff line numberDiff line change
@@ -4750,21 +4750,28 @@ describe('$compile', function() {
47504750
scope: {
47514751
attr: '@',
47524752
attrAlias: '@attr',
4753+
$attrAlias: '@$attr$',
47534754
ref: '=',
47544755
refAlias: '= ref',
4756+
$refAlias: '= $ref$',
47554757
reference: '=',
47564758
optref: '=?',
47574759
optrefAlias: '=? optref',
4760+
$optrefAlias: '=? $optref$',
47584761
optreference: '=?',
47594762
colref: '=*',
47604763
colrefAlias: '=* colref',
4764+
$colrefAlias: '=* $colref$',
47614765
owRef: '<',
47624766
owRefAlias: '< owRef',
4767+
$owRefAlias: '< $owRef$',
47634768
owOptref: '<?',
47644769
owOptrefAlias: '<? owOptref',
4770+
$owOptrefAlias: '<? $owOptref$',
47654771
expr: '&',
47664772
optExpr: '&?',
47674773
exprAlias: '&expr',
4774+
$exprAlias: '&$expr$',
47684775
constructor: '&?'
47694776
},
47704777
link: function(scope) {
@@ -5183,76 +5190,85 @@ describe('$compile', function() {
51835190

51845191
describe('attribute', function() {
51855192
it('should copy simple attribute', inject(function() {
5186-
compile('<div><span my-component attr="some text">');
5193+
compile('<div><span my-component attr="some text" $attr$="some other text">');
51875194

51885195
expect(componentScope.attr).toEqual('some text');
51895196
expect(componentScope.attrAlias).toEqual('some text');
5197+
expect(componentScope.$attrAlias).toEqual('some other text');
51905198
expect(componentScope.attrAlias).toEqual(componentScope.attr);
51915199
}));
51925200

51935201
it('should copy an attribute with spaces', inject(function() {
5194-
compile('<div><span my-component attr=" some text ">');
5202+
compile('<div><span my-component attr=" some text " $attr$=" some other text ">');
51955203

51965204
expect(componentScope.attr).toEqual(' some text ');
51975205
expect(componentScope.attrAlias).toEqual(' some text ');
5206+
expect(componentScope.$attrAlias).toEqual(' some other text ');
51985207
expect(componentScope.attrAlias).toEqual(componentScope.attr);
51995208
}));
52005209

52015210
it('should set up the interpolation before it reaches the link function', inject(function() {
52025211
$rootScope.name = 'misko';
5203-
compile('<div><span my-component attr="hello {{name}}">');
5212+
compile('<div><span my-component attr="hello {{name}}" $attr$="hi {{name}}">');
52045213
expect(componentScope.attr).toEqual('hello misko');
52055214
expect(componentScope.attrAlias).toEqual('hello misko');
5215+
expect(componentScope.$attrAlias).toEqual('hi misko');
52065216
}));
52075217

52085218
it('should update when interpolated attribute updates', inject(function() {
5209-
compile('<div><span my-component attr="hello {{name}}">');
5219+
compile('<div><span my-component attr="hello {{name}}" $attr$="hi {{name}}">');
52105220

52115221
$rootScope.name = 'igor';
52125222
$rootScope.$apply();
52135223

52145224
expect(componentScope.attr).toEqual('hello igor');
52155225
expect(componentScope.attrAlias).toEqual('hello igor');
5226+
expect(componentScope.$attrAlias).toEqual('hi igor');
52165227
}));
52175228
});
52185229

52195230

52205231
describe('object reference', function() {
52215232
it('should update local when origin changes', inject(function() {
5222-
compile('<div><span my-component ref="name">');
5233+
compile('<div><span my-component ref="name" $ref$="name">');
52235234
expect(componentScope.ref).toBeUndefined();
52245235
expect(componentScope.refAlias).toBe(componentScope.ref);
5236+
expect(componentScope.$refAlias).toBe(componentScope.ref);
52255237

52265238
$rootScope.name = 'misko';
52275239
$rootScope.$apply();
52285240

52295241
expect($rootScope.name).toBe('misko');
52305242
expect(componentScope.ref).toBe('misko');
52315243
expect(componentScope.refAlias).toBe('misko');
5244+
expect(componentScope.$refAlias).toBe('misko');
52325245

52335246
$rootScope.name = {};
52345247
$rootScope.$apply();
52355248
expect(componentScope.ref).toBe($rootScope.name);
52365249
expect(componentScope.refAlias).toBe($rootScope.name);
5250+
expect(componentScope.$refAlias).toBe($rootScope.name);
52375251
}));
52385252

52395253

52405254
it('should update local when both change', inject(function() {
5241-
compile('<div><span my-component ref="name">');
5255+
compile('<div><span my-component ref="name" $ref$="name">');
52425256
$rootScope.name = {mark:123};
52435257
componentScope.ref = 'misko';
52445258

52455259
$rootScope.$apply();
52465260
expect($rootScope.name).toEqual({mark:123});
52475261
expect(componentScope.ref).toBe($rootScope.name);
52485262
expect(componentScope.refAlias).toBe($rootScope.name);
5263+
expect(componentScope.$refAlias).toBe($rootScope.name);
52495264

52505265
$rootScope.name = 'igor';
52515266
componentScope.ref = {};
52525267
$rootScope.$apply();
52535268
expect($rootScope.name).toEqual('igor');
52545269
expect(componentScope.ref).toBe($rootScope.name);
52555270
expect(componentScope.refAlias).toBe($rootScope.name);
5271+
expect(componentScope.$refAlias).toBe($rootScope.name);
52565272
}));
52575273

52585274
it('should not break if local and origin both change to the same value', inject(function() {
@@ -5382,26 +5398,30 @@ describe('$compile', function() {
53825398

53835399
describe('optional object reference', function() {
53845400
it('should update local when origin changes', inject(function() {
5385-
compile('<div><span my-component optref="name">');
5401+
compile('<div><span my-component optref="name" $optref$="name">');
53865402
expect(componentScope.optRef).toBeUndefined();
53875403
expect(componentScope.optRefAlias).toBe(componentScope.optRef);
5404+
expect(componentScope.$optRefAlias).toBe(componentScope.optRef);
53885405

53895406
$rootScope.name = 'misko';
53905407
$rootScope.$apply();
53915408
expect(componentScope.optref).toBe($rootScope.name);
53925409
expect(componentScope.optrefAlias).toBe($rootScope.name);
5410+
expect(componentScope.$optrefAlias).toBe($rootScope.name);
53935411

53945412
$rootScope.name = {};
53955413
$rootScope.$apply();
53965414
expect(componentScope.optref).toBe($rootScope.name);
53975415
expect(componentScope.optrefAlias).toBe($rootScope.name);
5416+
expect(componentScope.$optrefAlias).toBe($rootScope.name);
53985417
}));
53995418

54005419
it('should not throw exception when reference does not exist', inject(function() {
54015420
compile('<div><span my-component>');
54025421

54035422
expect(componentScope.optref).toBeUndefined();
54045423
expect(componentScope.optrefAlias).toBeUndefined();
5424+
expect(componentScope.$optrefAlias).toBeUndefined();
54055425
expect(componentScope.optreference).toBeUndefined();
54065426
}));
54075427
});
@@ -5419,16 +5439,18 @@ describe('$compile', function() {
54195439
$rootScope.query = '';
54205440
$rootScope.$apply();
54215441

5422-
compile('<div><span my-component colref="collection | filter:query">');
5442+
compile('<div><span my-component colref="collection | filter:query" $colref$="collection | filter:query">');
54235443

54245444
expect(componentScope.colref).toEqual($rootScope.collection);
54255445
expect(componentScope.colrefAlias).toEqual(componentScope.colref);
5446+
expect(componentScope.$colrefAlias).toEqual(componentScope.colref);
54265447

54275448
$rootScope.query = 'Gab';
54285449
$rootScope.$apply();
54295450

54305451
expect(componentScope.colref).toEqual([$rootScope.collection[0]]);
54315452
expect(componentScope.colrefAlias).toEqual([$rootScope.collection[0]]);
5453+
expect(componentScope.$colrefAlias).toEqual([$rootScope.collection[0]]);
54325454
}));
54335455

54345456
it('should update origin scope when isolate scope changes', inject(function() {
@@ -5456,23 +5478,26 @@ describe('$compile', function() {
54565478

54575479
describe('one-way binding', function() {
54585480
it('should update isolate when the identity of origin changes', inject(function() {
5459-
compile('<div><span my-component ow-ref="obj">');
5481+
compile('<div><span my-component ow-ref="obj" $ow-ref$="obj">');
54605482

54615483
expect(componentScope.owRef).toBeUndefined();
54625484
expect(componentScope.owRefAlias).toBe(componentScope.owRef);
5485+
expect(componentScope.$owRefAlias).toBe(componentScope.owRef);
54635486

54645487
$rootScope.obj = {value: 'initial'};
54655488
$rootScope.$apply();
54665489

54675490
expect($rootScope.obj).toEqual({value: 'initial'});
54685491
expect(componentScope.owRef).toEqual({value: 'initial'});
54695492
expect(componentScope.owRefAlias).toBe(componentScope.owRef);
5493+
expect(componentScope.$owRefAlias).toBe(componentScope.owRef);
54705494

54715495
// This changes in both scopes because of reference
54725496
$rootScope.obj.value = 'origin1';
54735497
$rootScope.$apply();
54745498
expect(componentScope.owRef.value).toBe('origin1');
54755499
expect(componentScope.owRefAlias.value).toBe('origin1');
5500+
expect(componentScope.$owRefAlias.value).toBe('origin1');
54765501

54775502
componentScope.owRef = {value: 'isolate1'};
54785503
componentScope.$apply();
@@ -5483,17 +5508,19 @@ describe('$compile', function() {
54835508
$rootScope.$apply();
54845509
expect(componentScope.owRef.value).toBe('isolate1');
54855510
expect(componentScope.owRefAlias.value).toBe('origin2');
5511+
expect(componentScope.$owRefAlias.value).toBe('origin2');
54865512

54875513
// Change does propagate because object identity changes
54885514
$rootScope.obj = {value: 'origin3'};
54895515
$rootScope.$apply();
54905516
expect(componentScope.owRef.value).toBe('origin3');
54915517
expect(componentScope.owRef).toBe($rootScope.obj);
54925518
expect(componentScope.owRefAlias).toBe($rootScope.obj);
5519+
expect(componentScope.$owRefAlias).toBe($rootScope.obj);
54935520
}));
54945521

54955522
it('should update isolate when both change', inject(function() {
5496-
compile('<div><span my-component ow-ref="name">');
5523+
compile('<div><span my-component ow-ref="name" $ow-ref$="name">');
54975524

54985525
$rootScope.name = {mark:123};
54995526
componentScope.owRef = 'misko';
@@ -5502,13 +5529,15 @@ describe('$compile', function() {
55025529
expect($rootScope.name).toEqual({mark:123});
55035530
expect(componentScope.owRef).toBe($rootScope.name);
55045531
expect(componentScope.owRefAlias).toBe($rootScope.name);
5532+
expect(componentScope.$owRefAlias).toBe($rootScope.name);
55055533

55065534
$rootScope.name = 'igor';
55075535
componentScope.owRef = {};
55085536
$rootScope.$apply();
55095537
expect($rootScope.name).toEqual('igor');
55105538
expect(componentScope.owRef).toBe($rootScope.name);
55115539
expect(componentScope.owRefAlias).toBe($rootScope.name);
5540+
expect(componentScope.$owRefAlias).toBe($rootScope.name);
55125541
}));
55135542

55145543
describe('initialization', function() {
@@ -5705,17 +5734,19 @@ describe('$compile', function() {
57055734

57065735
it('should not update origin when identity of isolate changes', inject(function() {
57075736
$rootScope.name = {mark:123};
5708-
compile('<div><span my-component ow-ref="name">');
5737+
compile('<div><span my-component ow-ref="name" $ow-ref$="name">');
57095738

57105739
expect($rootScope.name).toEqual({mark:123});
57115740
expect(componentScope.owRef).toBe($rootScope.name);
57125741
expect(componentScope.owRefAlias).toBe($rootScope.name);
5742+
expect(componentScope.$owRefAlias).toBe($rootScope.name);
57135743

57145744
componentScope.owRef = 'martin';
57155745
$rootScope.$apply();
57165746
expect($rootScope.name).toEqual({mark: 123});
57175747
expect(componentScope.owRef).toBe('martin');
57185748
expect(componentScope.owRefAlias).toEqual({mark: 123});
5749+
expect(componentScope.$owRefAlias).toEqual({mark: 123});
57195750
}));
57205751

57215752

@@ -5862,45 +5893,51 @@ describe('$compile', function() {
58625893

58635894
describe('optional one-way binding', function() {
58645895
it('should update local when origin changes', inject(function() {
5865-
compile('<div><span my-component ow-optref="name">');
5896+
compile('<div><span my-component ow-optref="name" $ow-optref$="name">');
58665897

58675898
expect(componentScope.owOptref).toBeUndefined();
58685899
expect(componentScope.owOptrefAlias).toBe(componentScope.owOptref);
5900+
expect(componentScope.$owOptrefAlias).toBe(componentScope.owOptref);
58695901

58705902
$rootScope.name = 'misko';
58715903
$rootScope.$apply();
58725904
expect(componentScope.owOptref).toBe($rootScope.name);
58735905
expect(componentScope.owOptrefAlias).toBe($rootScope.name);
5906+
expect(componentScope.$owOptrefAlias).toBe($rootScope.name);
58745907

58755908
$rootScope.name = {};
58765909
$rootScope.$apply();
58775910
expect(componentScope.owOptref).toBe($rootScope.name);
58785911
expect(componentScope.owOptrefAlias).toBe($rootScope.name);
5912+
expect(componentScope.$owOptrefAlias).toBe($rootScope.name);
58795913
}));
58805914

58815915
it('should not throw exception when reference does not exist', inject(function() {
58825916
compile('<div><span my-component>');
58835917

58845918
expect(componentScope.owOptref).toBeUndefined();
58855919
expect(componentScope.owOptrefAlias).toBeUndefined();
5920+
expect(componentScope.$owOptrefAlias).toBeUndefined();
58865921
}));
58875922
});
58885923
});
58895924
});
58905925

58915926
describe('executable expression', function() {
58925927
it('should allow expression execution with locals', inject(function() {
5893-
compile('<div><span my-component expr="count = count + offset">');
5928+
compile('<div><span my-component expr="count = count + offset" $expr$="count = count + offset">');
58945929
$rootScope.count = 2;
58955930

58965931
expect(typeof componentScope.expr).toBe('function');
58975932
expect(typeof componentScope.exprAlias).toBe('function');
5933+
expect(typeof componentScope.$exprAlias).toBe('function');
58985934

58995935
expect(componentScope.expr({offset: 1})).toEqual(3);
59005936
expect($rootScope.count).toEqual(3);
59015937

59025938
expect(componentScope.exprAlias({offset: 10})).toEqual(13);
5903-
expect($rootScope.count).toEqual(13);
5939+
expect(componentScope.$exprAlias({offset: 10})).toEqual(23);
5940+
expect($rootScope.count).toEqual(23);
59045941
}));
59055942
});
59065943

@@ -5918,17 +5955,21 @@ describe('$compile', function() {
59185955
expect(componentScope.$$isolateBindings.attr.mode).toBe('@');
59195956
expect(componentScope.$$isolateBindings.attr.attrName).toBe('attr');
59205957
expect(componentScope.$$isolateBindings.attrAlias.attrName).toBe('attr');
5958+
expect(componentScope.$$isolateBindings.$attrAlias.attrName).toBe('$attr$');
59215959
expect(componentScope.$$isolateBindings.ref.mode).toBe('=');
59225960
expect(componentScope.$$isolateBindings.ref.attrName).toBe('ref');
59235961
expect(componentScope.$$isolateBindings.refAlias.attrName).toBe('ref');
5962+
expect(componentScope.$$isolateBindings.$refAlias.attrName).toBe('$ref$');
59245963
expect(componentScope.$$isolateBindings.reference.mode).toBe('=');
59255964
expect(componentScope.$$isolateBindings.reference.attrName).toBe('reference');
59265965
expect(componentScope.$$isolateBindings.owRef.mode).toBe('<');
59275966
expect(componentScope.$$isolateBindings.owRef.attrName).toBe('owRef');
59285967
expect(componentScope.$$isolateBindings.owRefAlias.attrName).toBe('owRef');
5968+
expect(componentScope.$$isolateBindings.$owRefAlias.attrName).toBe('$owRef$');
59295969
expect(componentScope.$$isolateBindings.expr.mode).toBe('&');
59305970
expect(componentScope.$$isolateBindings.expr.attrName).toBe('expr');
59315971
expect(componentScope.$$isolateBindings.exprAlias.attrName).toBe('expr');
5972+
expect(componentScope.$$isolateBindings.$exprAlias.attrName).toBe('$expr$');
59325973

59335974
var firstComponentScope = componentScope,
59345975
first$$isolateBindings = componentScope.$$isolateBindings;

0 commit comments

Comments
 (0)