@angular-wave/angular.ts 0.0.49 → 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.
@@ -1,22 +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
- /// ////////////////////////////////
6
+ /**
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.
17
+ */
15
18
 
16
19
  /**
17
- * @typedef {function(string|function(import('../scope/scope').Scope):any, function(any, import('../scope/scope').Scope, any):any=, boolean=): import('../../types').CompiledExpression} ParseService
20
+ * @typedef {function(string|function(import('../scope/scope').Scope):any, function(any, import('../scope/scope').Scope, any):any=, boolean=): CompiledExpression} ParseService
18
21
  */
19
22
 
23
+ export const $parseMinErr = minErr("$parse");
24
+
20
25
  export const literals = {
21
26
  true: true,
22
27
  false: false,
@@ -54,11 +59,6 @@ export function $ParseProvider() {
54
59
  };
55
60
 
56
61
  /**
57
- * @ngdoc method
58
- * @name $parseProvider#setIdentifierFns
59
- *
60
- * @description
61
- *
62
62
  * Allows defining the set of characters that are allowed in AngularJS expressions. The function
63
63
  * `identifierStart` will get called to know if a given character is a valid character to be the
64
64
  * first character for an identifier. The function `identifierContinue` will get called to know if
@@ -72,10 +72,11 @@ export function $ParseProvider() {
72
72
  * Since this function will be called extensively, keep the implementation of these functions fast,
73
73
  * as the performance of these functions have a direct impact on the expressions parsing speed.
74
74
  *
75
- * @param {function(any):boolean=} 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
76
76
  * a valid identifier start character.
77
- * @param {function(any):boolean=} 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
78
78
  * a valid identifier continue character.
79
+ * @returns {$ParseProvider}
79
80
  */
80
81
  this.setIdentifierFns = function (identifierStart, identifierContinue) {
81
82
  identStart = identifierStart;
@@ -86,9 +87,7 @@ export function $ParseProvider() {
86
87
  this.$get = [
87
88
  "$filter",
88
89
  function ($filter) {
89
- var noUnsafeEval = csp().noUnsafeEval;
90
90
  var $parseOptions = {
91
- csp: noUnsafeEval,
92
91
  literals: structuredClone(literals),
93
92
  isIdentifierStart: isFunction(identStart) && identStart,
94
93
  isIdentifierContinue: isFunction(identContinue) && identContinue,
@@ -126,213 +125,16 @@ export function $ParseProvider() {
126
125
  }
127
126
  }
128
127
 
128
+ /**
129
+ * @param {string} exp
130
+ * @returns {import("./ast").ASTNode}
131
+ */
129
132
  function $$getAst(exp) {
130
133
  var lexer = new Lexer($parseOptions);
131
134
  var parser = new Parser(lexer, $filter, $parseOptions);
132
135
  return parser.getAst(exp).ast;
133
136
  }
134
137
 
135
- function expressionInputDirtyCheck(
136
- newValue,
137
- oldValueOfValue,
138
- compareObjectIdentity,
139
- ) {
140
- if (newValue == null || oldValueOfValue == null) {
141
- // null/undefined
142
- return newValue === oldValueOfValue;
143
- }
144
-
145
- if (typeof newValue === "object") {
146
- // attempt to convert the value to a primitive type
147
- // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can
148
- // be cheaply dirty-checked
149
- newValue = getValueOf(newValue);
150
-
151
- if (typeof newValue === "object" && !compareObjectIdentity) {
152
- // objects/arrays are not supported - deep-watching them would be too expensive
153
- return false;
154
- }
155
-
156
- // fall-through to the primitive equality check
157
- }
158
-
159
- //Primitive or NaN
160
-
161
- return (
162
- newValue === oldValueOfValue ||
163
- (newValue !== newValue && oldValueOfValue !== oldValueOfValue)
164
- );
165
- }
166
-
167
- function inputsWatchDelegate(
168
- scope,
169
- listener,
170
- objectEquality,
171
- parsedExpression,
172
- ) {
173
- var inputExpressions = parsedExpression.inputs;
174
- var lastResult;
175
-
176
- if (inputExpressions.length === 1) {
177
- var oldInputValueOf = expressionInputDirtyCheck; // init to something unique so that equals check fails
178
- inputExpressions = inputExpressions[0];
179
- return scope.$watch(
180
- function expressionInputWatch(scope) {
181
- var newInputValue = inputExpressions(scope);
182
- if (
183
- !expressionInputDirtyCheck(
184
- newInputValue,
185
- oldInputValueOf,
186
- inputExpressions.isPure,
187
- )
188
- ) {
189
- lastResult = parsedExpression(scope, undefined, undefined, [
190
- newInputValue,
191
- ]);
192
- oldInputValueOf = newInputValue && getValueOf(newInputValue);
193
- }
194
- return lastResult;
195
- },
196
- listener,
197
- objectEquality,
198
- );
199
- }
200
-
201
- var oldInputValueOfValues = [];
202
- var oldInputValues = [];
203
- for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
204
- oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails
205
- oldInputValues[i] = null;
206
- }
207
-
208
- return scope.$watch(
209
- function expressionInputsWatch(scope) {
210
- var changed = false;
211
-
212
- for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
213
- var newInputValue = inputExpressions[i](scope);
214
- if (
215
- changed ||
216
- (changed = !expressionInputDirtyCheck(
217
- newInputValue,
218
- oldInputValueOfValues[i],
219
- inputExpressions[i].isPure,
220
- ))
221
- ) {
222
- oldInputValues[i] = newInputValue;
223
- oldInputValueOfValues[i] =
224
- newInputValue && getValueOf(newInputValue);
225
- }
226
- }
227
-
228
- if (changed) {
229
- lastResult = parsedExpression(
230
- scope,
231
- undefined,
232
- undefined,
233
- oldInputValues,
234
- );
235
- }
236
-
237
- return lastResult;
238
- },
239
- listener,
240
- objectEquality,
241
- );
242
- }
243
-
244
- function oneTimeWatchDelegate(
245
- scope,
246
- listener,
247
- objectEquality,
248
- parsedExpression,
249
- ) {
250
- var isDone = parsedExpression.literal ? isAllDefined : isDefined;
251
- var unwatch, lastValue;
252
-
253
- var exp = parsedExpression.$$intercepted || parsedExpression;
254
- var post = parsedExpression.$$interceptor || ((x) => x);
255
-
256
- var useInputs = parsedExpression.inputs && !exp.inputs;
257
-
258
- // Propagate the literal/inputs/constant attributes
259
- // ... but not oneTime since we are handling it
260
- oneTimeWatch.literal = parsedExpression.literal;
261
- oneTimeWatch.constant = parsedExpression.constant;
262
- oneTimeWatch.inputs = parsedExpression.inputs;
263
-
264
- // Allow other delegates to run on this wrapped expression
265
- addWatchDelegate(oneTimeWatch);
266
-
267
- unwatch = scope.$watch(oneTimeWatch, listener, objectEquality);
268
-
269
- return unwatch;
270
-
271
- function unwatchIfDone() {
272
- if (isDone(lastValue)) {
273
- unwatch();
274
- }
275
- }
276
-
277
- function oneTimeWatch(scope, locals, assign, inputs) {
278
- lastValue =
279
- useInputs && inputs
280
- ? inputs[0]
281
- : exp(scope, locals, assign, inputs);
282
- if (isDone(lastValue)) {
283
- scope.$$postDigest(unwatchIfDone);
284
- }
285
- return post(lastValue);
286
- }
287
- }
288
-
289
- function isAllDefined(value) {
290
- var allDefined = true;
291
- forEach(value, function (val) {
292
- if (!isDefined(val)) allDefined = false;
293
- });
294
- return allDefined;
295
- }
296
-
297
- function constantWatchDelegate(
298
- scope,
299
- listener,
300
- objectEquality,
301
- parsedExpression,
302
- ) {
303
- var unwatch = scope.$watch(
304
- function constantWatch(scope) {
305
- unwatch();
306
- return parsedExpression(scope);
307
- },
308
- listener,
309
- objectEquality,
310
- );
311
- return unwatch;
312
- }
313
-
314
- function addWatchDelegate(parsedExpression) {
315
- if (parsedExpression.constant) {
316
- parsedExpression.$$watchDelegate = constantWatchDelegate;
317
- } else if (parsedExpression.oneTime) {
318
- parsedExpression.$$watchDelegate = oneTimeWatchDelegate;
319
- } else if (parsedExpression.inputs) {
320
- parsedExpression.$$watchDelegate = inputsWatchDelegate;
321
- }
322
-
323
- return parsedExpression;
324
- }
325
-
326
- function chainInterceptors(first, second) {
327
- function chainedInterceptor(value) {
328
- return second(first(value));
329
- }
330
- chainedInterceptor.$stateful = first.$stateful || second.$stateful;
331
- chainedInterceptor.$$pure = first.$$pure && second.$$pure;
332
-
333
- return chainedInterceptor;
334
- }
335
-
336
138
  function addInterceptor(parsedExpression, interceptorFn) {
337
139
  if (!interceptorFn) return parsedExpression;
338
140
 
@@ -394,16 +196,16 @@ export function $ParseProvider() {
394
196
  ];
395
197
  }
396
198
 
397
- function constantWatchDelegate(
199
+ export function constantWatchDelegate(
398
200
  scope,
399
201
  listener,
400
202
  objectEquality,
401
203
  parsedExpression,
402
204
  ) {
403
205
  const unwatch = scope.$watch(
404
- ($scope) => {
206
+ () => {
405
207
  unwatch();
406
- return parsedExpression($scope);
208
+ return parsedExpression(scope);
407
209
  },
408
210
  listener,
409
211
  objectEquality,
@@ -423,7 +225,7 @@ function addWatchDelegate(parsedExpression) {
423
225
  return parsedExpression;
424
226
  }
425
227
 
426
- export function inputsWatchDelegate(
228
+ function inputsWatchDelegate(
427
229
  scope,
428
230
  listener,
429
231
  objectEquality,
@@ -500,7 +302,7 @@ export function inputsWatchDelegate(
500
302
  );
501
303
  }
502
304
 
503
- export function oneTimeWatchDelegate(
305
+ function oneTimeWatchDelegate(
504
306
  scope,
505
307
  listener,
506
308
  objectEquality,
@@ -545,7 +347,7 @@ export function oneTimeWatchDelegate(
545
347
  return unwatch;
546
348
  }
547
349
 
548
- export function chainInterceptors(first, second) {
350
+ function chainInterceptors(first, second) {
549
351
  function chainedInterceptor(value) {
550
352
  return second(first(value));
551
353
  }
@@ -555,7 +357,6 @@ export function chainInterceptors(first, second) {
555
357
  return chainedInterceptor;
556
358
  }
557
359
 
558
- /** @private */
559
360
  function expressionInputDirtyCheck(
560
361
  newValue,
561
362
  oldValueOfValue,
@@ -588,7 +389,6 @@ function expressionInputDirtyCheck(
588
389
  );
589
390
  }
590
391
 
591
- /** @private */
592
392
  function isAllDefined(value) {
593
393
  let allDefined = true;
594
394
  forEach(value, (val) => {
@@ -22,10 +22,6 @@
22
22
  -
23
23
  - Converts AngularJS {@link guide/expression expression} into a function.
24
24
  -
25
- - ```js
26
-
27
- ```
28
-
29
25
  - let getter = $parse('user.name');
30
26
  - let setter = getter.assign;
31
27
  - let context = {user:{name:'AngularJS'}};
@@ -35,11 +31,6 @@
35
31
  - setter(context, 'newValue');
36
32
  - expect(context.user.name).toEqual('newValue');
37
33
  - expect(getter(context, locals)).toEqual('local');
38
- - ```
39
-
40
- ```
41
-
42
- -
43
34
  -
44
35
  - @param {string} expression String expression to compile.
45
36
  - @returns {function(context, locals)} a function which represents the compiled expression:
@@ -56,10 +47,6 @@
56
47
  - constant literals.
57
48
  - * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be
58
49
  - set to a function to change its value on the given context.
59
- - \*/
60
-
61
- /\*\*
62
-
63
50
  - @ngdoc provider
64
51
  - @name $parseProvider
65
52
  -
@@ -1,7 +1,17 @@
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
@@ -10,18 +20,24 @@ export class Parser {
10
20
  /**
11
21
  *
12
22
  * @param {import('./lexer').Lexer} lexer
13
- * @param {*} $filter
14
- * @param {*} options
23
+ * @param {function(any):any} $filter
24
+ * @param {ParserOptions} options
15
25
  */
16
26
  constructor(lexer, $filter, options) {
27
+ /** @type {AST} */
17
28
  this.ast = new AST(lexer, options);
18
- this.astCompiler = options.csp
19
- ? new ASTInterpreter($filter)
20
- : new ASTCompiler($filter);
29
+
30
+ /** @type {ASTInterpreter} */
31
+ this.astCompiler = new ASTInterpreter($filter);
21
32
  }
22
33
 
23
- parse(text) {
24
- 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);
25
41
  const fn = this.astCompiler.compile(ast);
26
42
  fn.literal = isLiteral(ast);
27
43
  fn.constant = isConstant(ast);
@@ -29,6 +45,10 @@ export class Parser {
29
45
  return fn;
30
46
  }
31
47
 
48
+ /**
49
+ * @param {string} exp - Expression to be parsed
50
+ * @returns {ParsedAST}
51
+ */
32
52
  getAst(exp) {
33
53
  let oneTime = false;
34
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
  });
@@ -18,12 +18,6 @@
18
18
  -
19
19
  - The following default rules in CSP affect AngularJS:
20
20
  -
21
- - - The use of `eval()`, `Function(string)` and similar functions to dynamically create and execute
22
- - code from strings is forbidden. AngularJS makes use of this in the {@link $parse} service to
23
- - provide a 30% increase in the speed of evaluating AngularJS expressions. (This CSP rule can be
24
- - disabled with the CSP keyword `unsafe-eval`, but it is generally not recommended as it would
25
- - weaken the protections offered by CSP.)
26
- -
27
21
  - - The use of inline resources, such as inline `<script>` and `<style>` elements, are forbidden.
28
22
  - This prevents apps from injecting custom styles directly into the document. AngularJS makes use of
29
23
  - this to include some CSS rules (e.g. {@link ngCloak} and {@link ngHide}). To make these
@@ -31,22 +25,6 @@
31
25
  - in your HTML manually. (This CSP rule can be disabled with the CSP keyword `unsafe-inline`, but
32
26
  - it is generally not recommended as it would weaken the protections offered by CSP.)
33
27
  -
34
- - If you do not provide `ngCsp` then AngularJS tries to autodetect if CSP is blocking dynamic code
35
- - creation from strings (e.g., `unsafe-eval` not specified in CSP header) and automatically
36
- - deactivates this feature in the {@link $parse} service. This autodetection, however, triggers a
37
- - CSP error to be logged in the console:
38
- -
39
- - ```
40
-
41
- ```
42
-
43
- - Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of
44
- - script in the following Content Security Policy directive: "default-src 'self'". Note that
45
- - 'script-src' was not explicitly set, so 'default-src' is used as a fallback.
46
- - ```
47
-
48
- ```
49
-
50
28
  -
51
29
  - This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp`
52
30
  - directive on an element of the HTML document that appears before the `<script>` tag that loads
@@ -59,7 +37,6 @@
59
37
  -
60
38
  - - no-inline-style: this stops AngularJS from injecting CSS styles into the DOM
61
39
  -
62
- - - no-unsafe-eval: this stops AngularJS from optimizing $parse with unsafe eval of strings
63
40
  -
64
41
  - You can use these values in the following combinations:
65
42
  -
@@ -72,9 +49,6 @@
72
49
  - styles and unsafe eval. E.g. `<body ng-csp>`. This is backwardly compatible with previous
73
50
  - versions of AngularJS.
74
51
  -
75
- - - Specifying only `no-unsafe-eval` tells AngularJS that we must not use eval, but that we can
76
- - inject inline styles. E.g. `<body ng-csp="no-unsafe-eval">`.
77
- -
78
52
  - - Specifying only `no-inline-style` tells AngularJS that we must not inject styles, but that we can
79
53
  - run eval - no automatic check for unsafe eval will occur. E.g. `<body ng-csp="no-inline-style">`
80
54
  -
@@ -366,7 +366,7 @@ JQLite.prototype.removeData = function (name) {
366
366
  /**
367
367
  * Gets or sets data on a parent element
368
368
  * @param {string} name
369
- * @param {any} value
369
+ * @param {any} [value]
370
370
  * @returns {JQLite|any}
371
371
  */
372
372
  JQLite.prototype.inheritedData = function (name, value) {
@@ -383,7 +383,7 @@ JQLite.prototype.inheritedData = function (name, value) {
383
383
 
384
384
  /**
385
385
  * Gets or sets innerHTML on the first element in JQLite collection
386
- * @param {string} value
386
+ * @param {string} [value]
387
387
  * @returns {JQLite|any|undefined}
388
388
  */
389
389
  JQLite.prototype.html = function (value) {
package/src/types.js CHANGED
@@ -12,7 +12,10 @@
12
12
  */
13
13
 
14
14
  /**
15
- * @typedef {Object|function(any, any=): any} CompiledExpression
15
+ * @typedef {function} CompiledExpression
16
+ * @param {import('./core/scope/scope').Scope} context - An object against which any expressions embedded in the strings are evaluated against (typically a scope object).
17
+ * @param {object} [locals] - local variables context object, useful for overriding values in `context`.
18
+ * @returns {any}
16
19
  * @property {boolean} literal - Indicates if the expression is a literal.
17
20
  * @property {boolean} constant - Indicates if the expression is constant.
18
21
  * @property {function(any, any): any} assign - Assigns a value to a context. If value is not provided,