@angular-wave/angular.ts 0.0.48 → 0.0.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/Makefile +3 -0
  2. package/README.md +1 -1
  3. package/css/angular.css +0 -6
  4. package/dist/angular-ts.esm.js +2 -2
  5. package/dist/angular-ts.umd.js +2 -2
  6. package/jsdoc.json +24 -0
  7. package/package.json +6 -2
  8. package/src/core/compile/compile.md +1 -1
  9. package/src/core/compile/compile.spec.js +50 -48
  10. package/src/core/interpolate/interpolate.js +1 -18
  11. package/src/core/on.spec.js +7 -12
  12. package/src/core/parser/ast.js +234 -69
  13. package/src/core/parser/interpreter.js +246 -50
  14. package/src/core/parser/lexer.js +144 -57
  15. package/src/core/parser/parse.js +38 -278
  16. package/src/core/parser/parse.md +44 -0
  17. package/src/core/parser/parser.js +32 -6
  18. package/src/core/parser/shared.js +7 -1
  19. package/src/core/prop.spec.js +4 -4
  20. package/src/core/scope/scope.js +14 -10
  21. package/src/directive/csp.md +0 -26
  22. package/src/directive/form/form.spec.js +18 -18
  23. package/src/directive/include/include.spec.js +18 -18
  24. package/src/directive/switch/switch.spec.js +4 -4
  25. package/src/shared/constants.js +3 -2
  26. package/src/shared/jqlite/jqlite.js +2 -2
  27. package/src/types.js +4 -1
  28. package/types/core/parser/ast.d.ts +269 -67
  29. package/types/core/parser/interpreter.d.ts +202 -53
  30. package/types/core/parser/lexer.d.ts +153 -0
  31. package/types/core/parser/parse.d.ts +23 -34
  32. package/types/core/parser/parser.d.ts +43 -14
  33. package/types/core/parser/shared.d.ts +7 -1
  34. package/types/core/scope/scope.d.ts +11 -11
  35. package/types/shared/jqlite/jqlite.d.ts +4 -4
  36. package/types/types.d.ts +1 -1
  37. package/src/core/parser/compiler.js +0 -561
  38. package/types/core/parser/compiler.d.ts +0 -49
@@ -1,62 +1,27 @@
1
- import {
2
- csp,
3
- forEach,
4
- isDefined,
5
- isFunction,
6
- minErr,
7
- } from "../../shared/utils";
1
+ import { forEach, isDefined, isFunction, minErr } from "../../shared/utils";
8
2
  import { getValueOf, PURITY_RELATIVE } from "./shared";
9
3
  import { Lexer } from "./lexer";
10
4
  import { Parser } from "./parser";
11
5
 
12
- export const $parseMinErr = minErr("$parse");
13
-
14
- /// ////////////////////////////////
15
-
16
6
  /**
17
- * @typedef {function(string|function(import('../scope/scope').Scope):any, function(any, Scope, any):any=, boolean=): import('../../types').CompiledExpression} ParseService
7
+ * @typedef {function} CompiledExpression
8
+ * @param {import('../scope/scope').Scope} context - An object against which any expressions embedded in the strings are evaluated against (typically a scope object).
9
+ * @param {object} [locals] - local variables context object, useful for overriding values in `context`.
10
+ * @returns {any}
11
+ * @property {boolean} literal - Indicates if the expression is a literal.
12
+ * @property {boolean} constant - Indicates if the expression is constant.
13
+ * @property {function(any, any): any} assign - Assigns a value to a context. If value is not provided,
14
+ * undefined is gonna be used since the implementation
15
+ * does not check the parameter. Let's force a value for consistency. If consumer
16
+ * wants to undefine it, pass the undefined value explicitly.
18
17
  */
19
18
 
20
19
  /**
21
- * @ngdoc service
22
- * @name $parse
23
- * @kind function
24
- *
25
- * @description
26
- *
27
- * Converts AngularJS {@link guide/expression expression} into a function.
28
- *
29
- * ```js
30
- * let getter = $parse('user.name');
31
- * let setter = getter.assign;
32
- * let context = {user:{name:'AngularJS'}};
33
- * let locals = {user:{name:'local'}};
34
- *
35
- * expect(getter(context)).toEqual('AngularJS');
36
- * setter(context, 'newValue');
37
- * expect(context.user.name).toEqual('newValue');
38
- * expect(getter(context, locals)).toEqual('local');
39
- * ```
40
- *
41
- *
42
- * @param {string} expression String expression to compile.
43
- * @returns {function(context, locals)} a function which represents the compiled expression:
44
- *
45
- * * `context` – `{object}` – an object against which any expressions embedded in the strings
46
- * are evaluated against (typically a scope object).
47
- * * `locals` – `{object=}` – local variables context object, useful for overriding values in
48
- * `context`.
49
- *
50
- * The returned function also has the following properties:
51
- * * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript
52
- * literal.
53
- * * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript
54
- * constant literals.
55
- * * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be
56
- * set to a function to change its value on the given context.
57
- *
20
+ * @typedef {function(string|function(import('../scope/scope').Scope):any, function(any, import('../scope/scope').Scope, any):any=, boolean=): CompiledExpression} ParseService
58
21
  */
59
22
 
23
+ export const $parseMinErr = minErr("$parse");
24
+
60
25
  export const literals = {
61
26
  true: true,
62
27
  false: false,
@@ -64,15 +29,6 @@ export const literals = {
64
29
  undefined,
65
30
  };
66
31
 
67
- /**
68
- * @ngdoc provider
69
- * @name $parseProvider
70
- *
71
- *
72
- * @description
73
- * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}
74
- * service.
75
- */
76
32
  export function $ParseProvider() {
77
33
  const cache = Object.create(null);
78
34
  const literals = {
@@ -81,7 +37,11 @@ export function $ParseProvider() {
81
37
  null: null,
82
38
  undefined: undefined,
83
39
  };
84
- var identStart, identContinue;
40
+ /** @type {function(any):boolean?} */
41
+ var identStart;
42
+
43
+ /** @type {function(any):boolean?} */
44
+ var identContinue;
85
45
 
86
46
  /**
87
47
  * @ngdoc method
@@ -99,11 +59,6 @@ export function $ParseProvider() {
99
59
  };
100
60
 
101
61
  /**
102
- * @ngdoc method
103
- * @name $parseProvider#setIdentifierFns
104
- *
105
- * @description
106
- *
107
62
  * Allows defining the set of characters that are allowed in AngularJS expressions. The function
108
63
  * `identifierStart` will get called to know if a given character is a valid character to be the
109
64
  * first character for an identifier. The function `identifierContinue` will get called to know if
@@ -117,10 +72,11 @@ export function $ParseProvider() {
117
72
  * Since this function will be called extensively, keep the implementation of these functions fast,
118
73
  * as the performance of these functions have a direct impact on the expressions parsing speed.
119
74
  *
120
- * @param {function=} identifierStart The function that will decide whether the given character is
75
+ * @param {function(any):boolean} [identifierStart] The function that will decide whether the given character is
121
76
  * a valid identifier start character.
122
- * @param {function=} identifierContinue The function that will decide whether the given character is
77
+ * @param {function(any):boolean} [identifierContinue] The function that will decide whether the given character is
123
78
  * a valid identifier continue character.
79
+ * @returns {$ParseProvider}
124
80
  */
125
81
  this.setIdentifierFns = function (identifierStart, identifierContinue) {
126
82
  identStart = identifierStart;
@@ -131,9 +87,7 @@ export function $ParseProvider() {
131
87
  this.$get = [
132
88
  "$filter",
133
89
  function ($filter) {
134
- var noUnsafeEval = csp().noUnsafeEval;
135
90
  var $parseOptions = {
136
- csp: noUnsafeEval,
137
91
  literals: structuredClone(literals),
138
92
  isIdentifierStart: isFunction(identStart) && identStart,
139
93
  isIdentifierContinue: isFunction(identContinue) && identContinue,
@@ -152,7 +106,10 @@ export function $ParseProvider() {
152
106
  parsedExpression = cache[cacheKey];
153
107
 
154
108
  if (!parsedExpression) {
155
- var lexer = new Lexer($parseOptions);
109
+ var lexer = new Lexer({
110
+ isIdentifierContinue: $parseOptions.isIdentifierContinue,
111
+ isIdentifierStart: $parseOptions.isIdentifierStart,
112
+ });
156
113
  var parser = new Parser(lexer, $filter, $parseOptions);
157
114
  parsedExpression = parser.parse(exp);
158
115
 
@@ -168,213 +125,16 @@ export function $ParseProvider() {
168
125
  }
169
126
  }
170
127
 
128
+ /**
129
+ * @param {string} exp
130
+ * @returns {import("./ast").ASTNode}
131
+ */
171
132
  function $$getAst(exp) {
172
133
  var lexer = new Lexer($parseOptions);
173
134
  var parser = new Parser(lexer, $filter, $parseOptions);
174
135
  return parser.getAst(exp).ast;
175
136
  }
176
137
 
177
- function expressionInputDirtyCheck(
178
- newValue,
179
- oldValueOfValue,
180
- compareObjectIdentity,
181
- ) {
182
- if (newValue == null || oldValueOfValue == null) {
183
- // null/undefined
184
- return newValue === oldValueOfValue;
185
- }
186
-
187
- if (typeof newValue === "object") {
188
- // attempt to convert the value to a primitive type
189
- // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can
190
- // be cheaply dirty-checked
191
- newValue = getValueOf(newValue);
192
-
193
- if (typeof newValue === "object" && !compareObjectIdentity) {
194
- // objects/arrays are not supported - deep-watching them would be too expensive
195
- return false;
196
- }
197
-
198
- // fall-through to the primitive equality check
199
- }
200
-
201
- //Primitive or NaN
202
-
203
- return (
204
- newValue === oldValueOfValue ||
205
- (newValue !== newValue && oldValueOfValue !== oldValueOfValue)
206
- );
207
- }
208
-
209
- function inputsWatchDelegate(
210
- scope,
211
- listener,
212
- objectEquality,
213
- parsedExpression,
214
- ) {
215
- var inputExpressions = parsedExpression.inputs;
216
- var lastResult;
217
-
218
- if (inputExpressions.length === 1) {
219
- var oldInputValueOf = expressionInputDirtyCheck; // init to something unique so that equals check fails
220
- inputExpressions = inputExpressions[0];
221
- return scope.$watch(
222
- function expressionInputWatch(scope) {
223
- var newInputValue = inputExpressions(scope);
224
- if (
225
- !expressionInputDirtyCheck(
226
- newInputValue,
227
- oldInputValueOf,
228
- inputExpressions.isPure,
229
- )
230
- ) {
231
- lastResult = parsedExpression(scope, undefined, undefined, [
232
- newInputValue,
233
- ]);
234
- oldInputValueOf = newInputValue && getValueOf(newInputValue);
235
- }
236
- return lastResult;
237
- },
238
- listener,
239
- objectEquality,
240
- );
241
- }
242
-
243
- var oldInputValueOfValues = [];
244
- var oldInputValues = [];
245
- for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
246
- oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails
247
- oldInputValues[i] = null;
248
- }
249
-
250
- return scope.$watch(
251
- function expressionInputsWatch(scope) {
252
- var changed = false;
253
-
254
- for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
255
- var newInputValue = inputExpressions[i](scope);
256
- if (
257
- changed ||
258
- (changed = !expressionInputDirtyCheck(
259
- newInputValue,
260
- oldInputValueOfValues[i],
261
- inputExpressions[i].isPure,
262
- ))
263
- ) {
264
- oldInputValues[i] = newInputValue;
265
- oldInputValueOfValues[i] =
266
- newInputValue && getValueOf(newInputValue);
267
- }
268
- }
269
-
270
- if (changed) {
271
- lastResult = parsedExpression(
272
- scope,
273
- undefined,
274
- undefined,
275
- oldInputValues,
276
- );
277
- }
278
-
279
- return lastResult;
280
- },
281
- listener,
282
- objectEquality,
283
- );
284
- }
285
-
286
- function oneTimeWatchDelegate(
287
- scope,
288
- listener,
289
- objectEquality,
290
- parsedExpression,
291
- ) {
292
- var isDone = parsedExpression.literal ? isAllDefined : isDefined;
293
- var unwatch, lastValue;
294
-
295
- var exp = parsedExpression.$$intercepted || parsedExpression;
296
- var post = parsedExpression.$$interceptor || ((x) => x);
297
-
298
- var useInputs = parsedExpression.inputs && !exp.inputs;
299
-
300
- // Propagate the literal/inputs/constant attributes
301
- // ... but not oneTime since we are handling it
302
- oneTimeWatch.literal = parsedExpression.literal;
303
- oneTimeWatch.constant = parsedExpression.constant;
304
- oneTimeWatch.inputs = parsedExpression.inputs;
305
-
306
- // Allow other delegates to run on this wrapped expression
307
- addWatchDelegate(oneTimeWatch);
308
-
309
- unwatch = scope.$watch(oneTimeWatch, listener, objectEquality);
310
-
311
- return unwatch;
312
-
313
- function unwatchIfDone() {
314
- if (isDone(lastValue)) {
315
- unwatch();
316
- }
317
- }
318
-
319
- function oneTimeWatch(scope, locals, assign, inputs) {
320
- lastValue =
321
- useInputs && inputs
322
- ? inputs[0]
323
- : exp(scope, locals, assign, inputs);
324
- if (isDone(lastValue)) {
325
- scope.$$postDigest(unwatchIfDone);
326
- }
327
- return post(lastValue);
328
- }
329
- }
330
-
331
- function isAllDefined(value) {
332
- var allDefined = true;
333
- forEach(value, function (val) {
334
- if (!isDefined(val)) allDefined = false;
335
- });
336
- return allDefined;
337
- }
338
-
339
- function constantWatchDelegate(
340
- scope,
341
- listener,
342
- objectEquality,
343
- parsedExpression,
344
- ) {
345
- var unwatch = scope.$watch(
346
- function constantWatch(scope) {
347
- unwatch();
348
- return parsedExpression(scope);
349
- },
350
- listener,
351
- objectEquality,
352
- );
353
- return unwatch;
354
- }
355
-
356
- function addWatchDelegate(parsedExpression) {
357
- if (parsedExpression.constant) {
358
- parsedExpression.$$watchDelegate = constantWatchDelegate;
359
- } else if (parsedExpression.oneTime) {
360
- parsedExpression.$$watchDelegate = oneTimeWatchDelegate;
361
- } else if (parsedExpression.inputs) {
362
- parsedExpression.$$watchDelegate = inputsWatchDelegate;
363
- }
364
-
365
- return parsedExpression;
366
- }
367
-
368
- function chainInterceptors(first, second) {
369
- function chainedInterceptor(value) {
370
- return second(first(value));
371
- }
372
- chainedInterceptor.$stateful = first.$stateful || second.$stateful;
373
- chainedInterceptor.$$pure = first.$$pure && second.$$pure;
374
-
375
- return chainedInterceptor;
376
- }
377
-
378
138
  function addInterceptor(parsedExpression, interceptorFn) {
379
139
  if (!interceptorFn) return parsedExpression;
380
140
 
@@ -436,16 +196,16 @@ export function $ParseProvider() {
436
196
  ];
437
197
  }
438
198
 
439
- function constantWatchDelegate(
199
+ export function constantWatchDelegate(
440
200
  scope,
441
201
  listener,
442
202
  objectEquality,
443
203
  parsedExpression,
444
204
  ) {
445
205
  const unwatch = scope.$watch(
446
- ($scope) => {
206
+ () => {
447
207
  unwatch();
448
- return parsedExpression($scope);
208
+ return parsedExpression(scope);
449
209
  },
450
210
  listener,
451
211
  objectEquality,
@@ -465,7 +225,7 @@ function addWatchDelegate(parsedExpression) {
465
225
  return parsedExpression;
466
226
  }
467
227
 
468
- export function inputsWatchDelegate(
228
+ function inputsWatchDelegate(
469
229
  scope,
470
230
  listener,
471
231
  objectEquality,
@@ -542,7 +302,7 @@ export function inputsWatchDelegate(
542
302
  );
543
303
  }
544
304
 
545
- export function oneTimeWatchDelegate(
305
+ function oneTimeWatchDelegate(
546
306
  scope,
547
307
  listener,
548
308
  objectEquality,
@@ -587,7 +347,7 @@ export function oneTimeWatchDelegate(
587
347
  return unwatch;
588
348
  }
589
349
 
590
- export function chainInterceptors(first, second) {
350
+ function chainInterceptors(first, second) {
591
351
  function chainedInterceptor(value) {
592
352
  return second(first(value));
593
353
  }
@@ -597,7 +357,7 @@ export function chainInterceptors(first, second) {
597
357
  return chainedInterceptor;
598
358
  }
599
359
 
600
- export function expressionInputDirtyCheck(
360
+ function expressionInputDirtyCheck(
601
361
  newValue,
602
362
  oldValueOfValue,
603
363
  compareObjectIdentity,
@@ -629,7 +389,7 @@ export function expressionInputDirtyCheck(
629
389
  );
630
390
  }
631
391
 
632
- export function isAllDefined(value) {
392
+ function isAllDefined(value) {
633
393
  let allDefined = true;
634
394
  forEach(value, (val) => {
635
395
  if (!isDefined(val)) allDefined = false;
@@ -11,3 +11,47 @@
11
11
  // content then it is possible that your application contains a security vulnerability to an XSS style attack.
12
12
  //
13
13
  // See https://docs.angularjs.org/guide/security
14
+
15
+ /\*\*
16
+
17
+ - @ngdoc service
18
+ - @name $parse
19
+ - @kind function
20
+ -
21
+ - @description
22
+ -
23
+ - Converts AngularJS {@link guide/expression expression} into a function.
24
+ -
25
+ - let getter = $parse('user.name');
26
+ - let setter = getter.assign;
27
+ - let context = {user:{name:'AngularJS'}};
28
+ - let locals = {user:{name:'local'}};
29
+ -
30
+ - expect(getter(context)).toEqual('AngularJS');
31
+ - setter(context, 'newValue');
32
+ - expect(context.user.name).toEqual('newValue');
33
+ - expect(getter(context, locals)).toEqual('local');
34
+ -
35
+ - @param {string} expression String expression to compile.
36
+ - @returns {function(context, locals)} a function which represents the compiled expression:
37
+ -
38
+ - - `context` – `{object}` – an object against which any expressions embedded in the strings
39
+ - are evaluated against (typically a scope object).
40
+ - - `locals` – `{object=}` – local variables context object, useful for overriding values in
41
+ - `context`.
42
+ -
43
+ - The returned function also has the following properties:
44
+ - * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript
45
+ - literal.
46
+ - * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript
47
+ - constant literals.
48
+ - * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be
49
+ - set to a function to change its value on the given context.
50
+ - @ngdoc provider
51
+ - @name $parseProvider
52
+ -
53
+ -
54
+ - @description
55
+ - `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}
56
+ - service.
57
+ \*/
@@ -1,21 +1,43 @@
1
1
  import { AST } from "./ast";
2
2
  import { isLiteral, isConstant } from "./shared";
3
3
  import { ASTInterpreter } from "./interpreter";
4
- import { ASTCompiler } from "./compiler";
4
+
5
+ /**
6
+ * @typedef {Object} ParsedAST
7
+ * @property {import("./ast").ASTNode} ast - AST representation of expression
8
+ * @property {boolean} oneTime - True if expression should be evaluated only once
9
+ */
10
+
11
+ /**
12
+ * @typedef {Object} ParserOptions
13
+ * @property {function(string):any} literals
14
+ */
5
15
 
6
16
  /**
7
17
  * @constructor
8
18
  */
9
19
  export class Parser {
20
+ /**
21
+ *
22
+ * @param {import('./lexer').Lexer} lexer
23
+ * @param {function(any):any} $filter
24
+ * @param {ParserOptions} options
25
+ */
10
26
  constructor(lexer, $filter, options) {
27
+ /** @type {AST} */
11
28
  this.ast = new AST(lexer, options);
12
- this.astCompiler = options.csp
13
- ? new ASTInterpreter($filter)
14
- : new ASTCompiler($filter);
29
+
30
+ /** @type {ASTInterpreter} */
31
+ this.astCompiler = new ASTInterpreter($filter);
15
32
  }
16
33
 
17
- parse(text) {
18
- const { ast, oneTime } = this.getAst(text);
34
+ /**
35
+ *
36
+ * @param {string} exp - Expression to be parsed
37
+ * @returns
38
+ */
39
+ parse(exp) {
40
+ const { ast, oneTime } = this.getAst(exp);
19
41
  const fn = this.astCompiler.compile(ast);
20
42
  fn.literal = isLiteral(ast);
21
43
  fn.constant = isConstant(ast);
@@ -23,6 +45,10 @@ export class Parser {
23
45
  return fn;
24
46
  }
25
47
 
48
+ /**
49
+ * @param {string} exp - Expression to be parsed
50
+ * @returns {ParsedAST}
51
+ */
26
52
  getAst(exp) {
27
53
  let oneTime = false;
28
54
  exp = exp.trim();
@@ -61,6 +61,12 @@ export function isPure(node, parentIsPure) {
61
61
  return undefined === parentIsPure ? PURITY_RELATIVE : parentIsPure;
62
62
  }
63
63
 
64
+ /**
65
+ * Decorates ast with constant, toWatch, and isPure properties
66
+ * @param {import("./ast").ASTNode} ast
67
+ * @param {function(any):any} $filter
68
+ * @param {*} parentIsPure
69
+ */
64
70
  export function findConstantAndWatchExpressions(ast, $filter, parentIsPure) {
65
71
  let allConstants;
66
72
  let argsToWatch;
@@ -71,7 +77,7 @@ export function findConstantAndWatchExpressions(ast, $filter, parentIsPure) {
71
77
  switch (ast.type) {
72
78
  case ASTType.Program:
73
79
  allConstants = true;
74
- /** @type {[any]} */ (ast.body).forEach((expr) => {
80
+ /** @type {[import("./ast").ASTNode]} */ (ast.body).forEach((expr) => {
75
81
  findConstantAndWatchExpressions(expr.expression, $filter, astIsPure);
76
82
  allConstants = allConstants && expr.expression.constant;
77
83
  });
@@ -119,7 +119,7 @@ describe("ngProp*", () => {
119
119
  it("should work with different prefixes", () => {
120
120
  $rootScope.name = "Misko";
121
121
  const element = $compile(
122
- '<span ng:prop:test="name" ng-Prop-test2="name" ng_Prop_test3="name"></span>',
122
+ '<span ng-prop-test="name" ng-Prop-test2="name" ng-Prop-test3="name"></span>',
123
123
  )($rootScope);
124
124
  expect(element[0].test).toBe("Misko");
125
125
  expect(element[0].test2).toBe("Misko");
@@ -138,7 +138,7 @@ describe("ngProp*", () => {
138
138
  it("should work if they are prefixed with x- or data- and different prefixes", () => {
139
139
  $rootScope.name = "Misko";
140
140
  const element = $compile(
141
- '<span data-ng-prop-test2="name" ng-prop-test3="name" data-ng:prop-test4="name" ' +
141
+ '<span data-ng-prop-test2="name" ng-prop-test3="name" data-ng-prop-test4="name" ' +
142
142
  'ng-prop-test5="name" ng-prop-test6="name"></span>',
143
143
  )($rootScope);
144
144
  expect(element[0].test2).toBe("Misko");
@@ -179,7 +179,7 @@ describe("ngProp*", () => {
179
179
  }),
180
180
  );
181
181
  $compile(
182
- '<div attr-exposer ng-prop-title="12" ng-prop-super-title="34" ng-prop-my-camel_title="56">',
182
+ '<div attr-exposer ng-prop-title="12" ng-prop-super-title="34" ng-prop-my-camel-title="56">',
183
183
  )($rootScope);
184
184
 
185
185
  expect(attrs.title).toBeUndefined();
@@ -195,7 +195,7 @@ describe("ngProp*", () => {
195
195
  expect(attrs.myCamelTitle).toBeUndefined();
196
196
  expect(attrs.$attr.myCamelTitle).toBeUndefined();
197
197
  expect(attrs.ngPropMyCamelTitle).toBe("56");
198
- expect(attrs.$attr.ngPropMyCamelTitle).toBe("ng-prop-my-camel_title");
198
+ expect(attrs.$attr.ngPropMyCamelTitle).toBe("ng-prop-my-camel-title");
199
199
  });
200
200
 
201
201
  it("should not conflict with (ng-attr-)attribute mappings of the same name", () => {