@angular-wave/angular.ts 0.0.58 → 0.0.60

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.
@@ -0,0 +1,300 @@
1
+ import { Lexer } from "./lexer";
2
+ import { publishExternalAPI } from "../../public";
3
+ import { createInjector } from "../../injector";
4
+
5
+ describe("lexer", () => {
6
+ let $rootScope;
7
+ let $parse;
8
+ let logs = [];
9
+
10
+ beforeEach(() => {
11
+ publishExternalAPI().decorator("$exceptionHandler", function () {
12
+ return (exception, cause) => {
13
+ logs.push(exception);
14
+ console.error(exception, cause);
15
+ };
16
+ });
17
+ let injector = createInjector(["ng"]);
18
+ $parse = injector.get("$parse");
19
+ $rootScope = injector.get("$rootScope");
20
+ });
21
+
22
+ describe("lexer", () => {
23
+ let lex;
24
+
25
+ beforeEach(() => {
26
+ lex = function () {
27
+ const lexer = new Lexer({});
28
+ return lexer.lex.apply(lexer, arguments);
29
+ };
30
+ });
31
+
32
+ it("should only match number chars with isNumber", () => {
33
+ expect(Lexer.prototype.isNumber("0")).toBe(true);
34
+ expect(Lexer.prototype.isNumber("")).toBeFalsy();
35
+ expect(Lexer.prototype.isNumber(" ")).toBeFalsy();
36
+ expect(Lexer.prototype.isNumber(0)).toBeFalsy();
37
+ expect(Lexer.prototype.isNumber(false)).toBeFalsy();
38
+ expect(Lexer.prototype.isNumber(true)).toBeFalsy();
39
+ expect(Lexer.prototype.isNumber(undefined)).toBeFalsy();
40
+ expect(Lexer.prototype.isNumber(null)).toBeFalsy();
41
+ });
42
+
43
+ it("should tokenize a string", () => {
44
+ const tokens = lex("a.bc[22]+1.3|f:'a\\'c':\"d\\\"e\"");
45
+ let i = 0;
46
+ expect(tokens[i].index).toEqual(0);
47
+ expect(tokens[i].text).toEqual("a");
48
+
49
+ i++;
50
+ expect(tokens[i].index).toEqual(1);
51
+ expect(tokens[i].text).toEqual(".");
52
+
53
+ i++;
54
+ expect(tokens[i].index).toEqual(2);
55
+ expect(tokens[i].text).toEqual("bc");
56
+
57
+ i++;
58
+ expect(tokens[i].index).toEqual(4);
59
+ expect(tokens[i].text).toEqual("[");
60
+
61
+ i++;
62
+ expect(tokens[i].index).toEqual(5);
63
+ expect(tokens[i].text).toEqual("22");
64
+ expect(tokens[i].value).toEqual(22);
65
+ expect(tokens[i].constant).toEqual(true);
66
+
67
+ i++;
68
+ expect(tokens[i].index).toEqual(7);
69
+ expect(tokens[i].text).toEqual("]");
70
+
71
+ i++;
72
+ expect(tokens[i].index).toEqual(8);
73
+ expect(tokens[i].text).toEqual("+");
74
+
75
+ i++;
76
+ expect(tokens[i].index).toEqual(9);
77
+ expect(tokens[i].text).toEqual("1.3");
78
+ expect(tokens[i].value).toEqual(1.3);
79
+ expect(tokens[i].constant).toEqual(true);
80
+
81
+ i++;
82
+ expect(tokens[i].index).toEqual(12);
83
+ expect(tokens[i].text).toEqual("|");
84
+
85
+ i++;
86
+ expect(tokens[i].index).toEqual(13);
87
+ expect(tokens[i].text).toEqual("f");
88
+
89
+ i++;
90
+ expect(tokens[i].index).toEqual(14);
91
+ expect(tokens[i].text).toEqual(":");
92
+
93
+ i++;
94
+ expect(tokens[i].index).toEqual(15);
95
+ expect(tokens[i].value).toEqual("a'c");
96
+
97
+ i++;
98
+ expect(tokens[i].index).toEqual(21);
99
+ expect(tokens[i].text).toEqual(":");
100
+
101
+ i++;
102
+ expect(tokens[i].index).toEqual(22);
103
+ expect(tokens[i].value).toEqual('d"e');
104
+ });
105
+
106
+ it("should tokenize identifiers with spaces around dots the same as without spaces", () => {
107
+ function getText(t) {
108
+ return t.text;
109
+ }
110
+ const spaces = lex("foo. bar . baz").map(getText);
111
+ const noSpaces = lex("foo.bar.baz").map(getText);
112
+
113
+ expect(spaces).toEqual(noSpaces);
114
+ });
115
+
116
+ it("should use callback functions to know when an identifier is valid", () => {
117
+ function getText(t) {
118
+ return t.text;
119
+ }
120
+ const isIdentifierStart = jasmine.createSpy("start");
121
+ const isIdentifierContinue = jasmine.createSpy("continue");
122
+ isIdentifierStart.and.returnValue(true);
123
+ const lex = new Lexer({
124
+ isIdentifierStart,
125
+ isIdentifierContinue,
126
+ });
127
+
128
+ isIdentifierContinue.and.returnValue(true);
129
+ let tokens = lex.lex("πΣε").map(getText);
130
+ expect(tokens).toEqual(["πΣε"]);
131
+
132
+ isIdentifierContinue.and.returnValue(false);
133
+ tokens = lex.lex("πΣε").map(getText);
134
+ expect(tokens).toEqual(["π", "Σ", "ε"]);
135
+ });
136
+
137
+ it("should send the unicode characters and code points", () => {
138
+ function getText(t) {
139
+ return t.text;
140
+ }
141
+ const isIdentifierStart = jasmine.createSpy("start");
142
+ const isIdentifierContinue = jasmine.createSpy("continue");
143
+ isIdentifierStart.and.returnValue(true);
144
+ isIdentifierContinue.and.returnValue(true);
145
+ const lex = new Lexer({
146
+ isIdentifierStart,
147
+ isIdentifierContinue,
148
+ });
149
+ const tokens = lex.lex("\uD801\uDC37\uD852\uDF62\uDBFF\uDFFF");
150
+ expect(isIdentifierStart).toHaveBeenCalledTimes(1);
151
+ expect(isIdentifierStart.calls.argsFor(0)).toEqual([
152
+ "\uD801\uDC37",
153
+ 0x10437,
154
+ ]);
155
+ expect(isIdentifierContinue).toHaveBeenCalledTimes(2);
156
+ expect(isIdentifierContinue.calls.argsFor(0)).toEqual([
157
+ "\uD852\uDF62",
158
+ 0x24b62,
159
+ ]);
160
+ expect(isIdentifierContinue.calls.argsFor(1)).toEqual([
161
+ "\uDBFF\uDFFF",
162
+ 0x10ffff,
163
+ ]);
164
+ });
165
+
166
+ it("should tokenize undefined", () => {
167
+ const tokens = lex("undefined");
168
+ const i = 0;
169
+ expect(tokens[i].index).toEqual(0);
170
+ expect(tokens[i].text).toEqual("undefined");
171
+ });
172
+
173
+ it("should tokenize quoted string", () => {
174
+ const str = "['\\'', \"\\\"\"]";
175
+ const tokens = lex(str);
176
+
177
+ expect(tokens[1].index).toEqual(1);
178
+ expect(tokens[1].value).toEqual("'");
179
+
180
+ expect(tokens[3].index).toEqual(7);
181
+ expect(tokens[3].value).toEqual('"');
182
+ });
183
+
184
+ it("should tokenize escaped quoted string", () => {
185
+ const str = '"\\"\\n\\f\\r\\t\\v\\u00A0"';
186
+ const tokens = lex(str);
187
+
188
+ expect(tokens[0].value).toEqual('"\n\f\r\t\v\u00A0');
189
+ });
190
+
191
+ it("should tokenize unicode", () => {
192
+ const tokens = lex('"\\u00A0"');
193
+ expect(tokens.length).toEqual(1);
194
+ expect(tokens[0].value).toEqual("\u00a0");
195
+ });
196
+
197
+ it("should ignore whitespace", () => {
198
+ const tokens = lex("a \t \n \r b");
199
+ expect(tokens[0].text).toEqual("a");
200
+ expect(tokens[1].text).toEqual("b");
201
+ });
202
+
203
+ it("should tokenize relation and equality", () => {
204
+ const tokens = lex("! == != < > <= >= === !==");
205
+ expect(tokens[0].text).toEqual("!");
206
+ expect(tokens[1].text).toEqual("==");
207
+ expect(tokens[2].text).toEqual("!=");
208
+ expect(tokens[3].text).toEqual("<");
209
+ expect(tokens[4].text).toEqual(">");
210
+ expect(tokens[5].text).toEqual("<=");
211
+ expect(tokens[6].text).toEqual(">=");
212
+ expect(tokens[7].text).toEqual("===");
213
+ expect(tokens[8].text).toEqual("!==");
214
+ });
215
+
216
+ it("should tokenize logical and ternary", () => {
217
+ const tokens = lex("&& || ? :");
218
+ expect(tokens[0].text).toEqual("&&");
219
+ expect(tokens[1].text).toEqual("||");
220
+ expect(tokens[2].text).toEqual("?");
221
+ expect(tokens[3].text).toEqual(":");
222
+ });
223
+
224
+ it("should tokenize statements", () => {
225
+ const tokens = lex("a;b;");
226
+ expect(tokens[0].text).toEqual("a");
227
+ expect(tokens[1].text).toEqual(";");
228
+ expect(tokens[2].text).toEqual("b");
229
+ expect(tokens[3].text).toEqual(";");
230
+ });
231
+
232
+ it("should tokenize function invocation", () => {
233
+ const tokens = lex("a()");
234
+ expect(tokens.map((t) => t.text)).toEqual(["a", "(", ")"]);
235
+ });
236
+
237
+ it("should tokenize method invocation", () => {
238
+ const tokens = lex("a.b.c (d) - e.f()");
239
+ expect(tokens.map((t) => t.text)).toEqual([
240
+ "a",
241
+ ".",
242
+ "b",
243
+ ".",
244
+ "c",
245
+ "(",
246
+ "d",
247
+ ")",
248
+ "-",
249
+ "e",
250
+ ".",
251
+ "f",
252
+ "(",
253
+ ")",
254
+ ]);
255
+ });
256
+
257
+ it("should tokenize number", () => {
258
+ const tokens = lex("0.5");
259
+ expect(tokens[0].value).toEqual(0.5);
260
+ });
261
+
262
+ it("should tokenize negative number", () => {
263
+ let value = $rootScope.$eval("-0.5");
264
+ expect(value).toEqual(-0.5);
265
+
266
+ value = $rootScope.$eval("{a:-0.5}");
267
+ expect(value).toEqual({ a: -0.5 });
268
+ });
269
+
270
+ it("should tokenize number with exponent", () => {
271
+ let tokens = lex("0.5E-10");
272
+ expect(tokens[0].value).toEqual(0.5e-10);
273
+ expect($rootScope.$eval("0.5E-10")).toEqual(0.5e-10);
274
+
275
+ tokens = lex("0.5E+10");
276
+ expect(tokens[0].value).toEqual(0.5e10);
277
+ });
278
+
279
+ it("should throws exception for invalid exponent", () => {
280
+ expect(() => {
281
+ lex("0.5E-");
282
+ }).toThrowError(/lexerr/);
283
+
284
+ expect(() => {
285
+ lex("0.5E-A");
286
+ }).toThrowError(/lexerr/);
287
+ });
288
+
289
+ it("should tokenize number starting with a dot", () => {
290
+ const tokens = lex(".5");
291
+ expect(tokens[0].value).toEqual(0.5);
292
+ });
293
+
294
+ it("should throw error on invalid unicode", () => {
295
+ expect(() => {
296
+ lex("'\\u1''bla'");
297
+ }).toThrowError(/lexerr/);
298
+ });
299
+ });
300
+ });
@@ -14,7 +14,7 @@ import { Parser } from "./parser";
14
14
  */
15
15
 
16
16
  /**
17
- * @typedef {function } CompiledExpressionFunction
17
+ * @typedef {function} CompiledExpressionFunction
18
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
19
  * @param {object} [locals] - local variables context object, useful for overriding values in `context`.
20
20
  * @param {any} [assign]
@@ -69,6 +69,11 @@ export function $ParseProvider() {
69
69
 
70
70
  this.$get = [
71
71
  "$filter",
72
+ /**
73
+ *
74
+ * @param {(any) => any} $filter
75
+ * @returns {ParseService}
76
+ */
72
77
  function ($filter) {
73
78
  /** @type {import("./lexer").LexerOptions} */
74
79
  var $lexerOptions = {
@@ -0,0 +1,19 @@
1
+ import { test, expect } from "@playwright/test";
2
+
3
+ test("lexer unit tests contain no errors", async ({ page }) => {
4
+ await page.goto("src/core/parser/lexer.html");
5
+ await page.content();
6
+ await page.waitForTimeout(100);
7
+ await expect(page.locator(".jasmine-overall-result")).toHaveText(
8
+ /0 failures/,
9
+ );
10
+ });
11
+
12
+ test("parser unit tests contain no errors", async ({ page }) => {
13
+ await page.goto("src/core/parser/parse.html");
14
+ await page.content();
15
+ await page.waitForTimeout(100);
16
+ await expect(page.locator(".jasmine-overall-result")).toHaveText(
17
+ /0 failures/,
18
+ );
19
+ });
@@ -1,6 +1,6 @@
1
1
  export function $AnimateCssProvider(): void;
2
2
  export class $AnimateCssProvider {
3
- $get: (string | (($$AnimateRunner: any, $timeout: any, $$animateCache: any, $$rAFScheduler: any, $$animateQueue: any) => (element: any, initialOptions: any) => {
3
+ $get: (string | (($$AnimateRunner: any, $timeout: any, $$animateCache: any, $$rAFScheduler: import("./raf-scheduler").RafScheduler, $$animateQueue: any) => (element: any, initialOptions: any) => {
4
4
  $$willAnimate: boolean;
5
5
  start(): any;
6
6
  end: () => void;
@@ -1,5 +1,5 @@
1
1
  export function $$AnimationProvider(): void;
2
2
  export class $$AnimationProvider {
3
3
  drivers: any[];
4
- $get: (string | (($rootScope: any, $injector: any, $$AnimateRunner: any, $$rAFScheduler: any, $$animateCache: any) => (element: any, event: any, options: any) => any))[];
4
+ $get: (string | (($rootScope: any, $injector: any, $$AnimateRunner: any, $$rAFScheduler: import("./raf-scheduler").RafScheduler, $$animateCache: any) => (element: any, event: any, options: any) => any))[];
5
5
  }
@@ -1,34 +1,19 @@
1
1
  /**
2
- * @typedef {Object} Scheduler
2
+ * @typedef {Function} RafSchedulerFunction
3
+ * @typedef {Object} RafSchedulerObject
3
4
  * @property {Function} waitUntilQuiet - Function to wait until the animation frame is quiet.
4
- * @property {Array<Function>} queue - The queue of tasks to be processed.
5
- * @property {Function} scheduler - The function to add tasks to the queue and schedule the next tick.
5
+ * @typedef {RafSchedulerObject & RafSchedulerFunction} RafScheduler
6
6
  */
7
7
  /**
8
8
  * Creates a requestAnimationFrame scheduler.
9
- * @returns {Scheduler} The scheduler object.
9
+ * @returns {RafScheduler} The scheduler object.
10
10
  */
11
- export const $$rAFSchedulerFactory: (() => {
12
- (tasks: Array<Function>): void;
13
- queue: any[];
14
- /**
15
- * Waits until the animation frame is quiet before running the provided function.
16
- * Cancels any previous animation frame requests.
17
- * @param {Function} fn - The function to run when the animation frame is quiet.
18
- */
19
- waitUntilQuiet(fn: Function): void;
20
- })[];
21
- export type Scheduler = {
11
+ export function $$rAFSchedulerFactory(): RafScheduler;
12
+ export type RafSchedulerFunction = Function;
13
+ export type RafSchedulerObject = {
22
14
  /**
23
15
  * - Function to wait until the animation frame is quiet.
24
16
  */
25
17
  waitUntilQuiet: Function;
26
- /**
27
- * - The queue of tasks to be processed.
28
- */
29
- queue: Array<Function>;
30
- /**
31
- * - The function to add tasks to the queue and schedule the next tick.
32
- */
33
- scheduler: Function;
34
18
  };
19
+ export type RafScheduler = RafSchedulerObject & RafSchedulerFunction;
@@ -8,7 +8,7 @@
8
8
  * @property {function(any, any): any} assign - Assigns a value to a context. If value is not provided,
9
9
  */
10
10
  /**
11
- * @typedef {function } CompiledExpressionFunction
11
+ * @typedef {function} CompiledExpressionFunction
12
12
  * @param {import('../scope/scope').Scope} context - An object against which any expressions embedded in the strings are evaluated against (typically a scope object).
13
13
  * @param {object} [locals] - local variables context object, useful for overriding values in `context`.
14
14
  * @param {any} [assign]