@angular-wave/angular.ts 0.0.49 → 0.0.51
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.
- package/README.md +3 -1
- package/dist/angular-ts.esm.js +2 -2
- package/dist/angular-ts.umd.js +2 -2
- package/package.json +1 -1
- package/src/animations/shared.js +2 -1
- package/src/core/interpolate/interpolate.js +1 -18
- package/src/core/parser/ast-type.js +21 -20
- package/src/core/parser/ast.js +253 -93
- package/src/core/parser/interpreter.js +639 -174
- package/src/core/parser/lexer.js +22 -22
- package/src/core/parser/parse.js +51 -265
- package/src/core/parser/parse.md +0 -13
- package/src/core/parser/parse.spec.js +429 -444
- package/src/core/parser/parser.js +39 -11
- package/src/directive/csp.md +0 -26
- package/src/loader.js +5 -1
- package/src/shared/jqlite/jqlite.js +2 -2
- package/src/types.js +0 -10
- package/types/animations/shared.d.ts +1 -1
- package/types/core/parser/ast-type.d.ts +24 -20
- package/types/core/parser/ast.d.ts +266 -73
- package/types/core/parser/interpreter.d.ts +207 -53
- package/types/core/parser/lexer.d.ts +23 -19
- package/types/core/parser/parse.d.ts +50 -44
- package/types/core/parser/parser.d.ts +31 -16
- package/types/loader.d.ts +397 -0
- package/types/shared/jqlite/jqlite.d.ts +4 -4
- package/types/types.d.ts +0 -1
- package/src/core/parser/compiler.js +0 -561
- package/src/core/parser/shared.js +0 -228
- package/types/core/parser/compiler.d.ts +0 -49
- package/types/core/parser/shared.d.ts +0 -29
package/src/core/parser/lexer.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isDefined, minErr } from "../../shared/utils";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const $parseMinErr = minErr("$parse");
|
|
4
4
|
|
|
5
5
|
const ESCAPE = {
|
|
6
6
|
n: "\n",
|
|
@@ -18,19 +18,19 @@ const OPERATORS = new Set(
|
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* @typedef {Object} LexerOptions
|
|
21
|
-
* @property {(ch: string, codePoint: number) => boolean} [isIdentifierStart] Custom function to determine if a character is a valid identifier start.
|
|
22
|
-
* @property {(ch: string, codePoint: number) => boolean} [isIdentifierContinue] Custom function to determine if a character is a valid identifier continuation.
|
|
21
|
+
* @property {(ch: string, codePoint: number) => boolean} [isIdentifierStart] - Custom function to determine if a character is a valid identifier start.
|
|
22
|
+
* @property {(ch: string, codePoint: number) => boolean} [isIdentifierContinue] - Custom function to determine if a character is a valid identifier continuation.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
|
-
* Represents a token produced by the lexer.
|
|
26
|
+
* Represents a token produced by the lexer, which will be used by the AST to construct an abstract syntax tree.
|
|
27
27
|
* @typedef {Object} Token
|
|
28
|
-
* @property {number} index Index of the token.
|
|
29
|
-
* @property {string} text Text of the token.
|
|
30
|
-
* @property {boolean} [identifier] Indicates if token is an identifier.
|
|
31
|
-
* @property {boolean} [constant] Indicates if token is a constant.
|
|
32
|
-
* @property {string|number} [value] Value of the token if it's a constant.
|
|
33
|
-
* @property {boolean} [operator] Indicates if token is an operator.
|
|
28
|
+
* @property {number} index - Index of the token.
|
|
29
|
+
* @property {string} text - Text of the token.
|
|
30
|
+
* @property {boolean} [identifier] - Indicates if token is an identifier.
|
|
31
|
+
* @property {boolean} [constant] - Indicates if token is a constant.
|
|
32
|
+
* @property {string|number} [value] - Value of the token if it's a constant.
|
|
33
|
+
* @property {boolean} [operator] - Indicates if token is an operator.
|
|
34
34
|
*/
|
|
35
35
|
|
|
36
36
|
/**
|
|
@@ -40,7 +40,7 @@ const OPERATORS = new Set(
|
|
|
40
40
|
export class Lexer {
|
|
41
41
|
/**
|
|
42
42
|
* Creates an instance of Lexer.
|
|
43
|
-
* @param {LexerOptions} options Lexer options.
|
|
43
|
+
* @param {LexerOptions} options - Lexer options.
|
|
44
44
|
*/
|
|
45
45
|
constructor(options) {
|
|
46
46
|
/** @type {LexerOptions} */
|
|
@@ -67,7 +67,10 @@ export class Lexer {
|
|
|
67
67
|
(ch === "." && this.isNumber(/** @type {string} */ (this.peek())))
|
|
68
68
|
) {
|
|
69
69
|
this.readNumber();
|
|
70
|
-
} else if (
|
|
70
|
+
} else if (
|
|
71
|
+
this.isIdentifierStart &&
|
|
72
|
+
this.isIdentifierStart(this.peekMultichar())
|
|
73
|
+
) {
|
|
71
74
|
this.readIdent();
|
|
72
75
|
} else if (this.is(ch, "(){}[].,;:?")) {
|
|
73
76
|
this.tokens.push({ index: this.index, text: ch });
|
|
@@ -133,14 +136,8 @@ export class Lexer {
|
|
|
133
136
|
* @returns {boolean} True if character is whitespace, false otherwise.
|
|
134
137
|
*/
|
|
135
138
|
isWhitespace(ch) {
|
|
136
|
-
// IE treats non-breaking space as \u00A0
|
|
137
139
|
return (
|
|
138
|
-
ch === " " ||
|
|
139
|
-
ch === "\r" ||
|
|
140
|
-
ch === "\t" ||
|
|
141
|
-
ch === "\n" ||
|
|
142
|
-
ch === "\v" ||
|
|
143
|
-
ch === "\u00A0"
|
|
140
|
+
ch === " " || ch === "\r" || ch === "\t" || ch === "\n" || ch === "\v"
|
|
144
141
|
);
|
|
145
142
|
}
|
|
146
143
|
|
|
@@ -180,7 +177,6 @@ export class Lexer {
|
|
|
180
177
|
*/
|
|
181
178
|
codePointAt(ch) {
|
|
182
179
|
if (ch.length === 1) return ch.charCodeAt(0);
|
|
183
|
-
|
|
184
180
|
return (ch.charCodeAt(0) << 10) + ch.charCodeAt(1) - 0x35fdc00;
|
|
185
181
|
}
|
|
186
182
|
|
|
@@ -231,6 +227,7 @@ export class Lexer {
|
|
|
231
227
|
|
|
232
228
|
/**
|
|
233
229
|
* Reads and tokenizes a number from the text.
|
|
230
|
+
* @return {void}
|
|
234
231
|
*/
|
|
235
232
|
readNumber() {
|
|
236
233
|
let number = "";
|
|
@@ -278,7 +275,7 @@ export class Lexer {
|
|
|
278
275
|
this.index += this.peekMultichar().length;
|
|
279
276
|
while (this.index < this.text.length) {
|
|
280
277
|
const ch = this.peekMultichar();
|
|
281
|
-
if (!this.isIdentifierContinue(ch)) {
|
|
278
|
+
if (this.isIdentifierContinue && !this.isIdentifierContinue(ch)) {
|
|
282
279
|
break;
|
|
283
280
|
}
|
|
284
281
|
this.index += ch.length;
|
|
@@ -334,6 +331,9 @@ export class Lexer {
|
|
|
334
331
|
this.throwError("Unterminated quote", start);
|
|
335
332
|
}
|
|
336
333
|
|
|
334
|
+
/**
|
|
335
|
+
* @returns {string}
|
|
336
|
+
*/
|
|
337
337
|
handleUnicodeEscape() {
|
|
338
338
|
const hex = this.text.substring(this.index + 1, this.index + 5);
|
|
339
339
|
if (!hex.match(/[\da-f]{4}/i)) {
|
package/src/core/parser/parse.js
CHANGED
|
@@ -1,37 +1,40 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
forEach,
|
|
4
|
-
isDefined,
|
|
5
|
-
isFunction,
|
|
6
|
-
minErr,
|
|
7
|
-
} from "../../shared/utils";
|
|
8
|
-
import { getValueOf, PURITY_RELATIVE } from "./shared";
|
|
1
|
+
import { forEach, isDefined, isFunction } from "../../shared/utils";
|
|
2
|
+
import { PURITY_RELATIVE } from "./interpreter";
|
|
9
3
|
import { Lexer } from "./lexer";
|
|
10
4
|
import { Parser } from "./parser";
|
|
11
5
|
|
|
12
|
-
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {Object} CompiledExpressionProps
|
|
8
|
+
* @property {boolean} literal - Indicates if the expression is a literal.
|
|
9
|
+
* @property {boolean} constant - Indicates if the expression is constant.
|
|
10
|
+
* @property {boolean} isPure
|
|
11
|
+
* @property {boolean} oneTime
|
|
12
|
+
* @property {any[]} inputs
|
|
13
|
+
* @property {function(any, any): any} assign - Assigns a value to a context. If value is not provided,
|
|
14
|
+
*/
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {function } CompiledExpressionFunction
|
|
18
|
+
* @param {import('../scope/scope').Scope} context - An object against which any expressions embedded in the strings are evaluated against (typically a scope object).
|
|
19
|
+
* @param {object} [locals] - local variables context object, useful for overriding values in `context`.
|
|
20
|
+
* @param {any} [assign]
|
|
21
|
+
* @returns {any}
|
|
22
|
+
* undefined is gonna be used since the implementation
|
|
23
|
+
* does not check the parameter. Let's force a value for consistency. If consumer
|
|
24
|
+
* wants to undefine it, pass the undefined value explicitly.
|
|
25
|
+
*/
|
|
15
26
|
|
|
16
27
|
/**
|
|
17
|
-
* @typedef {
|
|
28
|
+
* @typedef {CompiledExpressionFunction & CompiledExpressionProps} CompiledExpression
|
|
18
29
|
*/
|
|
19
30
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
null: null,
|
|
24
|
-
undefined,
|
|
25
|
-
};
|
|
31
|
+
/**
|
|
32
|
+
* @typedef {function(string|function(import('../scope/scope').Scope):any, function(any, import('../scope/scope').Scope, any):any=, boolean=): CompiledExpression} ParseService
|
|
33
|
+
*/
|
|
26
34
|
|
|
27
35
|
export function $ParseProvider() {
|
|
28
36
|
const cache = Object.create(null);
|
|
29
|
-
|
|
30
|
-
true: true,
|
|
31
|
-
false: false,
|
|
32
|
-
null: null,
|
|
33
|
-
undefined: undefined,
|
|
34
|
-
};
|
|
37
|
+
|
|
35
38
|
/** @type {function(any):boolean?} */
|
|
36
39
|
var identStart;
|
|
37
40
|
|
|
@@ -39,26 +42,6 @@ export function $ParseProvider() {
|
|
|
39
42
|
var identContinue;
|
|
40
43
|
|
|
41
44
|
/**
|
|
42
|
-
* @ngdoc method
|
|
43
|
-
* @name $parseProvider#addLiteral
|
|
44
|
-
* @description
|
|
45
|
-
*
|
|
46
|
-
* Configure $parse service to add literal values that will be present as literal at expressions.
|
|
47
|
-
*
|
|
48
|
-
* @param {string} literalName Token for the literal value. The literal name value must be a valid literal name.
|
|
49
|
-
* @param {*} literalValue Value for this literal. All literal values must be primitives or `undefined`.
|
|
50
|
-
*
|
|
51
|
-
**/
|
|
52
|
-
this.addLiteral = function (literalName, literalValue) {
|
|
53
|
-
literals[literalName] = literalValue;
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* @ngdoc method
|
|
58
|
-
* @name $parseProvider#setIdentifierFns
|
|
59
|
-
*
|
|
60
|
-
* @description
|
|
61
|
-
*
|
|
62
45
|
* Allows defining the set of characters that are allowed in AngularJS expressions. The function
|
|
63
46
|
* `identifierStart` will get called to know if a given character is a valid character to be the
|
|
64
47
|
* first character for an identifier. The function `identifierContinue` will get called to know if
|
|
@@ -72,10 +55,11 @@ export function $ParseProvider() {
|
|
|
72
55
|
* Since this function will be called extensively, keep the implementation of these functions fast,
|
|
73
56
|
* as the performance of these functions have a direct impact on the expressions parsing speed.
|
|
74
57
|
*
|
|
75
|
-
* @param {function(any):boolean
|
|
58
|
+
* @param {function(any):boolean} [identifierStart] The function that will decide whether the given character is
|
|
76
59
|
* a valid identifier start character.
|
|
77
|
-
* @param {function(any):boolean
|
|
60
|
+
* @param {function(any):boolean} [identifierContinue] The function that will decide whether the given character is
|
|
78
61
|
* a valid identifier continue character.
|
|
62
|
+
* @returns {$ParseProvider}
|
|
79
63
|
*/
|
|
80
64
|
this.setIdentifierFns = function (identifierStart, identifierContinue) {
|
|
81
65
|
identStart = identifierStart;
|
|
@@ -86,10 +70,8 @@ export function $ParseProvider() {
|
|
|
86
70
|
this.$get = [
|
|
87
71
|
"$filter",
|
|
88
72
|
function ($filter) {
|
|
89
|
-
|
|
90
|
-
var $
|
|
91
|
-
csp: noUnsafeEval,
|
|
92
|
-
literals: structuredClone(literals),
|
|
73
|
+
/** @type {import("./lexer").LexerOptions} */
|
|
74
|
+
var $lexerOptions = {
|
|
93
75
|
isIdentifierStart: isFunction(identStart) && identStart,
|
|
94
76
|
isIdentifierContinue: isFunction(identContinue) && identContinue,
|
|
95
77
|
};
|
|
@@ -107,11 +89,8 @@ export function $ParseProvider() {
|
|
|
107
89
|
parsedExpression = cache[cacheKey];
|
|
108
90
|
|
|
109
91
|
if (!parsedExpression) {
|
|
110
|
-
var lexer = new Lexer(
|
|
111
|
-
|
|
112
|
-
isIdentifierStart: $parseOptions.isIdentifierStart,
|
|
113
|
-
});
|
|
114
|
-
var parser = new Parser(lexer, $filter, $parseOptions);
|
|
92
|
+
var lexer = new Lexer($lexerOptions);
|
|
93
|
+
var parser = new Parser(lexer, $filter);
|
|
115
94
|
parsedExpression = parser.parse(exp);
|
|
116
95
|
|
|
117
96
|
cache[cacheKey] = addWatchDelegate(parsedExpression);
|
|
@@ -126,213 +105,16 @@ export function $ParseProvider() {
|
|
|
126
105
|
}
|
|
127
106
|
}
|
|
128
107
|
|
|
108
|
+
/**
|
|
109
|
+
* @param {string} exp
|
|
110
|
+
* @returns {import("./ast").ASTNode}
|
|
111
|
+
*/
|
|
129
112
|
function $$getAst(exp) {
|
|
130
|
-
var lexer = new Lexer($
|
|
131
|
-
var parser = new Parser(lexer, $filter
|
|
113
|
+
var lexer = new Lexer($lexerOptions);
|
|
114
|
+
var parser = new Parser(lexer, $filter);
|
|
132
115
|
return parser.getAst(exp).ast;
|
|
133
116
|
}
|
|
134
117
|
|
|
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
118
|
function addInterceptor(parsedExpression, interceptorFn) {
|
|
337
119
|
if (!interceptorFn) return parsedExpression;
|
|
338
120
|
|
|
@@ -394,16 +176,16 @@ export function $ParseProvider() {
|
|
|
394
176
|
];
|
|
395
177
|
}
|
|
396
178
|
|
|
397
|
-
function constantWatchDelegate(
|
|
179
|
+
export function constantWatchDelegate(
|
|
398
180
|
scope,
|
|
399
181
|
listener,
|
|
400
182
|
objectEquality,
|
|
401
183
|
parsedExpression,
|
|
402
184
|
) {
|
|
403
185
|
const unwatch = scope.$watch(
|
|
404
|
-
(
|
|
186
|
+
() => {
|
|
405
187
|
unwatch();
|
|
406
|
-
return parsedExpression(
|
|
188
|
+
return parsedExpression(scope);
|
|
407
189
|
},
|
|
408
190
|
listener,
|
|
409
191
|
objectEquality,
|
|
@@ -423,7 +205,7 @@ function addWatchDelegate(parsedExpression) {
|
|
|
423
205
|
return parsedExpression;
|
|
424
206
|
}
|
|
425
207
|
|
|
426
|
-
|
|
208
|
+
function inputsWatchDelegate(
|
|
427
209
|
scope,
|
|
428
210
|
listener,
|
|
429
211
|
objectEquality,
|
|
@@ -500,7 +282,7 @@ export function inputsWatchDelegate(
|
|
|
500
282
|
);
|
|
501
283
|
}
|
|
502
284
|
|
|
503
|
-
|
|
285
|
+
function oneTimeWatchDelegate(
|
|
504
286
|
scope,
|
|
505
287
|
listener,
|
|
506
288
|
objectEquality,
|
|
@@ -545,7 +327,7 @@ export function oneTimeWatchDelegate(
|
|
|
545
327
|
return unwatch;
|
|
546
328
|
}
|
|
547
329
|
|
|
548
|
-
|
|
330
|
+
function chainInterceptors(first, second) {
|
|
549
331
|
function chainedInterceptor(value) {
|
|
550
332
|
return second(first(value));
|
|
551
333
|
}
|
|
@@ -555,7 +337,6 @@ export function chainInterceptors(first, second) {
|
|
|
555
337
|
return chainedInterceptor;
|
|
556
338
|
}
|
|
557
339
|
|
|
558
|
-
/** @private */
|
|
559
340
|
function expressionInputDirtyCheck(
|
|
560
341
|
newValue,
|
|
561
342
|
oldValueOfValue,
|
|
@@ -588,7 +369,6 @@ function expressionInputDirtyCheck(
|
|
|
588
369
|
);
|
|
589
370
|
}
|
|
590
371
|
|
|
591
|
-
/** @private */
|
|
592
372
|
function isAllDefined(value) {
|
|
593
373
|
let allDefined = true;
|
|
594
374
|
forEach(value, (val) => {
|
|
@@ -596,3 +376,9 @@ function isAllDefined(value) {
|
|
|
596
376
|
});
|
|
597
377
|
return allDefined;
|
|
598
378
|
}
|
|
379
|
+
|
|
380
|
+
function getValueOf(value) {
|
|
381
|
+
return isFunction(value.valueOf)
|
|
382
|
+
? value.valueOf()
|
|
383
|
+
: {}.constructor.prototype.valueOf.call(value);
|
|
384
|
+
}
|
package/src/core/parser/parse.md
CHANGED
|
@@ -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
|
-
|