@angular-wave/angular.ts 0.0.1

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 (231) hide show
  1. package/.eslintignore +1 -0
  2. package/.eslintrc.cjs +29 -0
  3. package/.github/workflows/playwright.yml +27 -0
  4. package/CHANGELOG.md +17974 -0
  5. package/CODE_OF_CONDUCT.md +3 -0
  6. package/CONTRIBUTING.md +246 -0
  7. package/DEVELOPERS.md +488 -0
  8. package/LICENSE +22 -0
  9. package/Makefile +31 -0
  10. package/README.md +115 -0
  11. package/RELEASE.md +98 -0
  12. package/SECURITY.md +16 -0
  13. package/TRIAGING.md +135 -0
  14. package/css/angular.css +22 -0
  15. package/dist/angular-ts.cjs.js +36843 -0
  16. package/dist/angular-ts.esm.js +36841 -0
  17. package/dist/angular-ts.umd.js +36848 -0
  18. package/dist/build/angular-animate.js +4272 -0
  19. package/dist/build/angular-aria.js +426 -0
  20. package/dist/build/angular-message-format.js +1072 -0
  21. package/dist/build/angular-messages.js +829 -0
  22. package/dist/build/angular-mocks.js +3757 -0
  23. package/dist/build/angular-parse-ext.js +1275 -0
  24. package/dist/build/angular-resource.js +911 -0
  25. package/dist/build/angular-route.js +1266 -0
  26. package/dist/build/angular-sanitize.js +891 -0
  27. package/dist/build/angular-touch.js +368 -0
  28. package/dist/build/angular.js +36600 -0
  29. package/e2e/unit.spec.ts +15 -0
  30. package/images/android-chrome-192x192.png +0 -0
  31. package/images/android-chrome-512x512.png +0 -0
  32. package/images/apple-touch-icon.png +0 -0
  33. package/images/favicon-16x16.png +0 -0
  34. package/images/favicon-32x32.png +0 -0
  35. package/images/favicon.ico +0 -0
  36. package/images/site.webmanifest +1 -0
  37. package/index.html +104 -0
  38. package/package.json +47 -0
  39. package/playwright.config.ts +78 -0
  40. package/public/circle.html +1 -0
  41. package/public/my_child_directive.html +1 -0
  42. package/public/my_directive.html +1 -0
  43. package/public/my_other_directive.html +1 -0
  44. package/public/test.html +1 -0
  45. package/rollup.config.js +31 -0
  46. package/src/animations/animateCache.js +55 -0
  47. package/src/animations/animateChildrenDirective.js +105 -0
  48. package/src/animations/animateCss.js +1139 -0
  49. package/src/animations/animateCssDriver.js +291 -0
  50. package/src/animations/animateJs.js +367 -0
  51. package/src/animations/animateJsDriver.js +67 -0
  52. package/src/animations/animateQueue.js +851 -0
  53. package/src/animations/animation.js +506 -0
  54. package/src/animations/module.js +779 -0
  55. package/src/animations/ngAnimateSwap.js +119 -0
  56. package/src/animations/rafScheduler.js +50 -0
  57. package/src/animations/shared.js +378 -0
  58. package/src/constants.js +20 -0
  59. package/src/core/animate.js +845 -0
  60. package/src/core/animateCss.js +73 -0
  61. package/src/core/animateRunner.js +195 -0
  62. package/src/core/attributes.js +199 -0
  63. package/src/core/cache.js +45 -0
  64. package/src/core/compile.js +4727 -0
  65. package/src/core/controller.js +225 -0
  66. package/src/core/exceptionHandler.js +63 -0
  67. package/src/core/filter.js +146 -0
  68. package/src/core/interpolate.js +442 -0
  69. package/src/core/interval.js +188 -0
  70. package/src/core/intervalFactory.js +57 -0
  71. package/src/core/location.js +1086 -0
  72. package/src/core/parser/parse.js +2562 -0
  73. package/src/core/parser/parse.md +13 -0
  74. package/src/core/q.js +746 -0
  75. package/src/core/rootScope.js +1596 -0
  76. package/src/core/sanitizeUri.js +85 -0
  77. package/src/core/sce.js +1161 -0
  78. package/src/core/taskTrackerFactory.js +125 -0
  79. package/src/core/timeout.js +121 -0
  80. package/src/core/urlUtils.js +187 -0
  81. package/src/core/utils.js +1349 -0
  82. package/src/directive/a.js +37 -0
  83. package/src/directive/attrs.js +283 -0
  84. package/src/directive/bind.js +51 -0
  85. package/src/directive/bind.md +142 -0
  86. package/src/directive/change.js +12 -0
  87. package/src/directive/change.md +25 -0
  88. package/src/directive/cloak.js +12 -0
  89. package/src/directive/cloak.md +24 -0
  90. package/src/directive/events.js +75 -0
  91. package/src/directive/events.md +166 -0
  92. package/src/directive/form.js +725 -0
  93. package/src/directive/init.js +15 -0
  94. package/src/directive/init.md +41 -0
  95. package/src/directive/input.js +1783 -0
  96. package/src/directive/list.js +46 -0
  97. package/src/directive/list.md +22 -0
  98. package/src/directive/ngClass.js +249 -0
  99. package/src/directive/ngController.js +64 -0
  100. package/src/directive/ngCsp.js +82 -0
  101. package/src/directive/ngIf.js +134 -0
  102. package/src/directive/ngInclude.js +217 -0
  103. package/src/directive/ngModel.js +1356 -0
  104. package/src/directive/ngModelOptions.js +509 -0
  105. package/src/directive/ngOptions.js +670 -0
  106. package/src/directive/ngRef.js +90 -0
  107. package/src/directive/ngRepeat.js +650 -0
  108. package/src/directive/ngShowHide.js +255 -0
  109. package/src/directive/ngSwitch.js +178 -0
  110. package/src/directive/ngTransclude.js +98 -0
  111. package/src/directive/non-bindable.js +11 -0
  112. package/src/directive/non-bindable.md +17 -0
  113. package/src/directive/script.js +30 -0
  114. package/src/directive/select.js +624 -0
  115. package/src/directive/style.js +25 -0
  116. package/src/directive/style.md +23 -0
  117. package/src/directive/validators.js +329 -0
  118. package/src/exts/aria.js +544 -0
  119. package/src/exts/messages.js +852 -0
  120. package/src/filters/filter.js +207 -0
  121. package/src/filters/filter.md +69 -0
  122. package/src/filters/filters.js +239 -0
  123. package/src/filters/json.md +16 -0
  124. package/src/filters/limit-to.js +43 -0
  125. package/src/filters/limit-to.md +19 -0
  126. package/src/filters/order-by.js +183 -0
  127. package/src/filters/order-by.md +83 -0
  128. package/src/index.js +13 -0
  129. package/src/injector.js +1034 -0
  130. package/src/jqLite.js +1117 -0
  131. package/src/loader.js +1320 -0
  132. package/src/public.js +215 -0
  133. package/src/routeToRegExp.js +41 -0
  134. package/src/services/anchorScroll.js +135 -0
  135. package/src/services/browser.js +321 -0
  136. package/src/services/cacheFactory.js +398 -0
  137. package/src/services/cookieReader.js +72 -0
  138. package/src/services/document.js +64 -0
  139. package/src/services/http.js +1537 -0
  140. package/src/services/httpBackend.js +206 -0
  141. package/src/services/log.js +160 -0
  142. package/src/services/templateRequest.js +139 -0
  143. package/test/angular.spec.js +2153 -0
  144. package/test/aria/aria.spec.js +1245 -0
  145. package/test/binding.spec.js +504 -0
  146. package/test/build-test.html +14 -0
  147. package/test/injector.spec.js +2327 -0
  148. package/test/jasmine/jasmine-5.1.2/boot0.js +65 -0
  149. package/test/jasmine/jasmine-5.1.2/boot1.js +133 -0
  150. package/test/jasmine/jasmine-5.1.2/jasmine-html.js +963 -0
  151. package/test/jasmine/jasmine-5.1.2/jasmine.css +320 -0
  152. package/test/jasmine/jasmine-5.1.2/jasmine.js +10824 -0
  153. package/test/jasmine/jasmine-5.1.2/jasmine_favicon.png +0 -0
  154. package/test/jasmine/jasmine-browser.json +17 -0
  155. package/test/jasmine/jasmine.json +9 -0
  156. package/test/jqlite.spec.js +2133 -0
  157. package/test/loader.spec.js +219 -0
  158. package/test/messages/messages.spec.js +1146 -0
  159. package/test/min-err.spec.js +174 -0
  160. package/test/mock-test.html +13 -0
  161. package/test/module-test.html +15 -0
  162. package/test/ng/anomate.spec.js +606 -0
  163. package/test/ng/cache-factor.spec.js +334 -0
  164. package/test/ng/compile.spec.js +17956 -0
  165. package/test/ng/controller-provider.spec.js +227 -0
  166. package/test/ng/cookie-reader.spec.js +98 -0
  167. package/test/ng/directive/a.spec.js +192 -0
  168. package/test/ng/directive/bind.spec.js +334 -0
  169. package/test/ng/directive/boolean.spec.js +136 -0
  170. package/test/ng/directive/change.spec.js +71 -0
  171. package/test/ng/directive/class.spec.js +858 -0
  172. package/test/ng/directive/click.spec.js +38 -0
  173. package/test/ng/directive/cloak.spec.js +44 -0
  174. package/test/ng/directive/constoller.spec.js +194 -0
  175. package/test/ng/directive/element-style.spec.js +92 -0
  176. package/test/ng/directive/event.spec.js +282 -0
  177. package/test/ng/directive/form.spec.js +1518 -0
  178. package/test/ng/directive/href.spec.js +143 -0
  179. package/test/ng/directive/if.spec.js +402 -0
  180. package/test/ng/directive/include.spec.js +828 -0
  181. package/test/ng/directive/init.spec.js +68 -0
  182. package/test/ng/directive/input.spec.js +3810 -0
  183. package/test/ng/directive/list.spec.js +170 -0
  184. package/test/ng/directive/model-options.spec.js +1008 -0
  185. package/test/ng/directive/model.spec.js +1905 -0
  186. package/test/ng/directive/non-bindable.spec.js +55 -0
  187. package/test/ng/directive/options.spec.js +3583 -0
  188. package/test/ng/directive/ref.spec.js +575 -0
  189. package/test/ng/directive/repeat.spec.js +1675 -0
  190. package/test/ng/directive/script.spec.js +52 -0
  191. package/test/ng/directive/scrset.spec.js +67 -0
  192. package/test/ng/directive/select.spec.js +2541 -0
  193. package/test/ng/directive/show-hide.spec.js +253 -0
  194. package/test/ng/directive/src.spec.js +157 -0
  195. package/test/ng/directive/style.spec.js +178 -0
  196. package/test/ng/directive/switch.spec.js +647 -0
  197. package/test/ng/directive/validators.spec.js +717 -0
  198. package/test/ng/document.spec.js +52 -0
  199. package/test/ng/filter/filter.spec.js +714 -0
  200. package/test/ng/filter/filters.spec.js +35 -0
  201. package/test/ng/filter/limit-to.spec.js +251 -0
  202. package/test/ng/filter/order-by.spec.js +891 -0
  203. package/test/ng/filter.spec.js +149 -0
  204. package/test/ng/http-backend.spec.js +398 -0
  205. package/test/ng/http.spec.js +4071 -0
  206. package/test/ng/interpolate.spec.js +642 -0
  207. package/test/ng/interval.spec.js +343 -0
  208. package/test/ng/location.spec.js +3488 -0
  209. package/test/ng/on.spec.js +229 -0
  210. package/test/ng/parse.spec.js +4655 -0
  211. package/test/ng/prop.spec.js +805 -0
  212. package/test/ng/q.spec.js +2904 -0
  213. package/test/ng/root-element.spec.js +16 -0
  214. package/test/ng/sanitize-uri.spec.js +249 -0
  215. package/test/ng/sce.spec.js +660 -0
  216. package/test/ng/scope.spec.js +3442 -0
  217. package/test/ng/template-request.spec.js +236 -0
  218. package/test/ng/timeout.spec.js +351 -0
  219. package/test/ng/url-utils.spec.js +156 -0
  220. package/test/ng/utils.spec.js +144 -0
  221. package/test/original-test.html +21 -0
  222. package/test/public.spec.js +34 -0
  223. package/test/sanitize/bing-html.spec.js +36 -0
  224. package/test/server/express.js +158 -0
  225. package/test/test-utils.js +11 -0
  226. package/tsconfig.json +17 -0
  227. package/types/angular.d.ts +138 -0
  228. package/types/global.d.ts +9 -0
  229. package/types/index.d.ts +2357 -0
  230. package/types/jqlite.d.ts +558 -0
  231. package/vite.config.js +14 -0
@@ -0,0 +1,442 @@
1
+ import {
2
+ minErr,
3
+ isDefined,
4
+ isUndefined,
5
+ stringify,
6
+ valueFn,
7
+ extend,
8
+ } from "./utils";
9
+
10
+ const $interpolateMinErr = minErr("$interpolate");
11
+ $interpolateMinErr.throwNoconcat = function (text) {
12
+ throw $interpolateMinErr(
13
+ "noconcat",
14
+ "Error while interpolating: {0}\nStrict Contextual Escaping disallows " +
15
+ "interpolations that concatenate multiple expressions when a trusted value is " +
16
+ "required. See http://docs.angularjs.org/api/ng.$sce",
17
+ text,
18
+ );
19
+ };
20
+
21
+ $interpolateMinErr.interr = function (text, err) {
22
+ throw $interpolateMinErr(
23
+ "interr",
24
+ "Can't interpolate: {0}\n{1}",
25
+ text,
26
+ err.toString(),
27
+ );
28
+ };
29
+
30
+ /**
31
+ * @ngdoc provider
32
+ * @name $interpolateProvider
33
+ *
34
+ *
35
+ * @description
36
+ *
37
+ * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.
38
+ *
39
+ * <div class="alert alert-danger">
40
+ * This feature is sometimes used to mix different markup languages, e.g. to wrap an AngularJS
41
+ * template within a Python Jinja template (or any other template language). Mixing templating
42
+ * languages is **very dangerous**. The embedding template language will not safely escape AngularJS
43
+ * expressions, so any user-controlled values in the template will cause Cross Site Scripting (XSS)
44
+ * security bugs!
45
+ * </div>
46
+ */
47
+ export function $InterpolateProvider() {
48
+ let startSymbol = "{{";
49
+ let endSymbol = "}}";
50
+
51
+ /**
52
+ * @ngdoc method
53
+ * @name $interpolateProvider#startSymbol
54
+ * @description
55
+ * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.
56
+ *
57
+ * @param {string=} value new value to set the starting symbol to.
58
+ * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
59
+ */
60
+ this.startSymbol = function (value) {
61
+ if (value) {
62
+ startSymbol = value;
63
+ return this;
64
+ }
65
+ return startSymbol;
66
+ };
67
+
68
+ /**
69
+ * @ngdoc method
70
+ * @name $interpolateProvider#endSymbol
71
+ * @description
72
+ * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
73
+ *
74
+ * @param {string=} value new value to set the ending symbol to.
75
+ * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
76
+ */
77
+ this.endSymbol = function (value) {
78
+ if (value) {
79
+ endSymbol = value;
80
+ return this;
81
+ }
82
+ return endSymbol;
83
+ };
84
+
85
+ this.$get = [
86
+ "$parse",
87
+ "$exceptionHandler",
88
+ "$sce",
89
+ function ($parse, $exceptionHandler, $sce) {
90
+ const startSymbolLength = startSymbol.length;
91
+ const endSymbolLength = endSymbol.length;
92
+ const escapedStartRegexp = new RegExp(
93
+ startSymbol.replace(/./g, escape),
94
+ "g",
95
+ );
96
+ const escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), "g");
97
+
98
+ function escape(ch) {
99
+ return `\\\\\\${ch}`;
100
+ }
101
+
102
+ function unescapeText(text) {
103
+ return text
104
+ .replace(escapedStartRegexp, startSymbol)
105
+ .replace(escapedEndRegexp, endSymbol);
106
+ }
107
+
108
+ // TODO: this is the same as the constantWatchDelegate in parse.js
109
+ function constantWatchDelegate(
110
+ scope,
111
+ listener,
112
+ objectEquality,
113
+ constantInterp,
114
+ ) {
115
+ const unwatch = scope.$watch(
116
+ (scope) => {
117
+ unwatch();
118
+ return constantInterp(scope);
119
+ },
120
+ listener,
121
+ objectEquality,
122
+ );
123
+ return unwatch;
124
+ }
125
+
126
+ /**
127
+ * @ngdoc service
128
+ * @name $interpolate
129
+ * @kind function
130
+ *
131
+ * @requires $parse
132
+ * @requires $sce
133
+ *
134
+ * @description
135
+ *
136
+ * Compiles a string with markup into an interpolation function. This service is used by the
137
+ * HTML {@link ng.$compile $compile} service for data binding. See
138
+ * {@link ng.$interpolateProvider $interpolateProvider} for configuring the
139
+ * interpolation markup.
140
+ *
141
+ *
142
+ * ```js
143
+ * let $interpolate = ...; // injected
144
+ * let exp = $interpolate('Hello {{name | uppercase}}!');
145
+ * expect(exp({name:'AngularJS'})).toEqual('Hello ANGULARJS!');
146
+ * ```
147
+ *
148
+ * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is
149
+ * `true`, the interpolation function will return `undefined` unless all embedded expressions
150
+ * evaluate to a value other than `undefined`.
151
+ *
152
+ * ```js
153
+ * let $interpolate = ...; // injected
154
+ * let context = {greeting: 'Hello', name: undefined };
155
+ *
156
+ * // default "forgiving" mode
157
+ * let exp = $interpolate('{{greeting}} {{name}}!');
158
+ * expect(exp(context)).toEqual('Hello !');
159
+ *
160
+ * // "allOrNothing" mode
161
+ * exp = $interpolate('{{greeting}} {{name}}!', false, null, true);
162
+ * expect(exp(context)).toBeUndefined();
163
+ * context.name = 'AngularJS';
164
+ * expect(exp(context)).toEqual('Hello AngularJS!');
165
+ * ```
166
+ *
167
+ * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior.
168
+ *
169
+ * #### Escaped Interpolation
170
+ * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers
171
+ * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash).
172
+ * It will be rendered as a regular start/end marker, and will not be interpreted as an expression
173
+ * or binding.
174
+ *
175
+ * This enables web-servers to prevent script injection attacks and defacing attacks, to some
176
+ * degree, while also enabling code examples to work without relying on the
177
+ * {@link ng.directive:ngNonBindable ngNonBindable} directive.
178
+ *
179
+ * **For security purposes, it is strongly encouraged that web servers escape user-supplied data,
180
+ * replacing angle brackets (&lt;, &gt;) with &amp;lt; and &amp;gt; respectively, and replacing all
181
+ * interpolation start/end markers with their escaped counterparts.**
182
+ *
183
+ * Escaped interpolation markers are only replaced with the actual interpolation markers in rendered
184
+ * output when the $interpolate service processes the text. So, for HTML elements interpolated
185
+ * by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter
186
+ * set to `true`, the interpolated text must contain an unescaped interpolation expression. As such,
187
+ * this is typically useful only when user-data is used in rendering a template from the server, or
188
+ * when otherwise untrusted data is used by a directive.
189
+ *
190
+ * <example name="interpolation">
191
+ * <file name="index.html">
192
+ * <div ng-init="username='A user'">
193
+ * <p ng-init="apptitle='Escaping demo'">{{apptitle}}: \{\{ username = "defaced value"; \}\}
194
+ * </p>
195
+ * <p><strong>{{username}}</strong> attempts to inject code which will deface the
196
+ * application, but fails to accomplish their task, because the server has correctly
197
+ * escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash)
198
+ * characters.</p>
199
+ * <p>Instead, the result of the attempted script injection is visible, and can be removed
200
+ * from the database by an administrator.</p>
201
+ * </div>
202
+ * </file>
203
+ * </example>
204
+ *
205
+ * @knownIssue
206
+ * It is currently not possible for an interpolated expression to contain the interpolation end
207
+ * symbol. For example, `{{ '}}' }}` will be incorrectly interpreted as `{{ ' }}` + `' }}`, i.e.
208
+ * an interpolated expression consisting of a single-quote (`'`) and the `' }}` string.
209
+ *
210
+ * @knownIssue
211
+ * All directives and components must use the standard `{{` `}}` interpolation symbols
212
+ * in their templates. If you change the application interpolation symbols the {@link $compile}
213
+ * service will attempt to denormalize the standard symbols to the custom symbols.
214
+ * The denormalization process is not clever enough to know not to replace instances of the standard
215
+ * symbols where they would not normally be treated as interpolation symbols. For example in the following
216
+ * code snippet the closing braces of the literal object will get incorrectly denormalized:
217
+ *
218
+ * ```
219
+ * <div data-context='{"context":{"id":3,"type":"page"}}">
220
+ * ```
221
+ *
222
+ * The workaround is to ensure that such instances are separated by whitespace:
223
+ * ```
224
+ * <div data-context='{"context":{"id":3,"type":"page"} }">
225
+ * ```
226
+ *
227
+ * See https://github.com/angular/angular.js/pull/14610#issuecomment-219401099 for more information.
228
+ *
229
+ * @param {string} text The text with markup to interpolate.
230
+ * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have
231
+ * embedded expression in order to return an interpolation function. Strings with no
232
+ * embedded expression will return null for the interpolation function.
233
+ * @param {string=} trustedContext when provided, the returned function passes the interpolated
234
+ * result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,
235
+ * trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that
236
+ * provides Strict Contextual Escaping for details.
237
+ * @param {boolean=} allOrNothing if `true`, then the returned function returns undefined
238
+ * unless all embedded expressions evaluate to a value other than `undefined`.
239
+ * @returns {function(context)} an interpolation function which is used to compute the
240
+ * interpolated string. The function has these parameters:
241
+ *
242
+ * - `context`: evaluation context for all expressions embedded in the interpolated text
243
+ */
244
+ function $interpolate(
245
+ text,
246
+ mustHaveExpression,
247
+ trustedContext,
248
+ allOrNothing,
249
+ ) {
250
+ const contextAllowsConcatenation =
251
+ trustedContext === $sce.URL || trustedContext === $sce.MEDIA_URL;
252
+
253
+ // Provide a quick exit and simplified result function for text with no interpolation
254
+ if (!text.length || text.indexOf(startSymbol) === -1) {
255
+ if (mustHaveExpression) return;
256
+
257
+ let unescapedText = unescapeText(text);
258
+ if (contextAllowsConcatenation) {
259
+ unescapedText = $sce.getTrusted(trustedContext, unescapedText);
260
+ }
261
+ const constantInterp = valueFn(unescapedText);
262
+ constantInterp.exp = text;
263
+ constantInterp.expressions = [];
264
+ constantInterp.$$watchDelegate = constantWatchDelegate;
265
+
266
+ return constantInterp;
267
+ }
268
+
269
+ allOrNothing = !!allOrNothing;
270
+ let startIndex;
271
+ let endIndex;
272
+ let index = 0;
273
+ const expressions = [];
274
+ let parseFns;
275
+ const textLength = text.length;
276
+ let exp;
277
+ const concat = [];
278
+ const expressionPositions = [];
279
+ let singleExpression;
280
+
281
+ while (index < textLength) {
282
+ if (
283
+ (startIndex = text.indexOf(startSymbol, index)) !== -1 &&
284
+ (endIndex = text.indexOf(
285
+ endSymbol,
286
+ startIndex + startSymbolLength,
287
+ )) !== -1
288
+ ) {
289
+ if (index !== startIndex) {
290
+ concat.push(unescapeText(text.substring(index, startIndex)));
291
+ }
292
+ exp = text.substring(startIndex + startSymbolLength, endIndex);
293
+ expressions.push(exp);
294
+ index = endIndex + endSymbolLength;
295
+ expressionPositions.push(concat.length);
296
+ concat.push(""); // Placeholder that will get replaced with the evaluated expression.
297
+ } else {
298
+ // we did not find an interpolation, so we have to add the remainder to the separators array
299
+ if (index !== textLength) {
300
+ concat.push(unescapeText(text.substring(index)));
301
+ }
302
+ break;
303
+ }
304
+ }
305
+
306
+ singleExpression =
307
+ concat.length === 1 && expressionPositions.length === 1;
308
+ // Intercept expression if we need to stringify concatenated inputs, which may be SCE trusted
309
+ // objects rather than simple strings
310
+ // (we don't modify the expression if the input consists of only a single trusted input)
311
+ const interceptor =
312
+ contextAllowsConcatenation && singleExpression
313
+ ? undefined
314
+ : parseStringifyInterceptor;
315
+ parseFns = expressions.map((exp) => $parse(exp, interceptor));
316
+
317
+ // Concatenating expressions makes it hard to reason about whether some combination of
318
+ // concatenated values are unsafe to use and could easily lead to XSS. By requiring that a
319
+ // single expression be used for some $sce-managed secure contexts (RESOURCE_URLs mostly),
320
+ // we ensure that the value that's used is assigned or constructed by some JS code somewhere
321
+ // that is more testable or make it obvious that you bound the value to some user controlled
322
+ // value. This helps reduce the load when auditing for XSS issues.
323
+
324
+ // Note that URL and MEDIA_URL $sce contexts do not need this, since `$sce` can sanitize the values
325
+ // passed to it. In that case, `$sce.getTrusted` will be called on either the single expression
326
+ // or on the overall concatenated string (losing trusted types used in the mix, by design).
327
+ // Both these methods will sanitize plain strings. Also, HTML could be included, but since it's
328
+ // only used in srcdoc attributes, this would not be very useful.
329
+
330
+ if (!mustHaveExpression || expressions.length) {
331
+ const compute = function (values) {
332
+ for (let i = 0, ii = expressions.length; i < ii; i++) {
333
+ if (allOrNothing && isUndefined(values[i])) return;
334
+ concat[expressionPositions[i]] = values[i];
335
+ }
336
+
337
+ if (contextAllowsConcatenation) {
338
+ // If `singleExpression` then `concat[0]` might be a "trusted" value or `null`, rather than a string
339
+ return $sce.getTrusted(
340
+ trustedContext,
341
+ singleExpression ? concat[0] : concat.join(""),
342
+ );
343
+ }
344
+ if (trustedContext && concat.length > 1) {
345
+ // This context does not allow more than one part, e.g. expr + string or exp + exp.
346
+ $interpolateMinErr.throwNoconcat(text);
347
+ }
348
+ // In an unprivileged context or only one part: just concatenate and return.
349
+ return concat.join("");
350
+ };
351
+
352
+ return extend(
353
+ (context) => {
354
+ let i = 0;
355
+ const ii = expressions.length;
356
+ const values = new Array(ii);
357
+
358
+ try {
359
+ for (; i < ii; i++) {
360
+ values[i] = parseFns[i](context);
361
+ }
362
+
363
+ return compute(values);
364
+ } catch (err) {
365
+ $exceptionHandler($interpolateMinErr.interr(text, err));
366
+ }
367
+ },
368
+ {
369
+ // all of these properties are undocumented for now
370
+ exp: text, // just for compatibility with regular watchers created via $watch
371
+ expressions,
372
+ $$watchDelegate(scope, listener) {
373
+ let lastValue;
374
+ return scope.$watchGroup(
375
+ parseFns,
376
+ function interpolateFnWatcher(values, oldValues) {
377
+ const currValue = compute(values);
378
+ listener.call(
379
+ this,
380
+ currValue,
381
+ values !== oldValues ? lastValue : currValue,
382
+ scope,
383
+ );
384
+ lastValue = currValue;
385
+ },
386
+ );
387
+ },
388
+ },
389
+ );
390
+ }
391
+
392
+ function parseStringifyInterceptor(value) {
393
+ try {
394
+ // In concatenable contexts, getTrusted comes at the end, to avoid sanitizing individual
395
+ // parts of a full URL. We don't care about losing the trustedness here.
396
+ // In non-concatenable contexts, where there is only one expression, this interceptor is
397
+ // not applied to the expression.
398
+ value =
399
+ trustedContext && !contextAllowsConcatenation
400
+ ? $sce.getTrusted(trustedContext, value)
401
+ : $sce.valueOf(value);
402
+ return allOrNothing && !isDefined(value) ? value : stringify(value);
403
+ } catch (err) {
404
+ $exceptionHandler($interpolateMinErr.interr(text, err));
405
+ }
406
+ }
407
+ }
408
+
409
+ /**
410
+ * @ngdoc method
411
+ * @name $interpolate#startSymbol
412
+ * @description
413
+ * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.
414
+ *
415
+ * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change
416
+ * the symbol.
417
+ *
418
+ * @returns {string} start symbol.
419
+ */
420
+ $interpolate.startSymbol = function () {
421
+ return startSymbol;
422
+ };
423
+
424
+ /**
425
+ * @ngdoc method
426
+ * @name $interpolate#endSymbol
427
+ * @description
428
+ * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
429
+ *
430
+ * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change
431
+ * the symbol.
432
+ *
433
+ * @returns {string} end symbol.
434
+ */
435
+ $interpolate.endSymbol = function () {
436
+ return endSymbol;
437
+ };
438
+
439
+ return $interpolate;
440
+ },
441
+ ];
442
+ }
@@ -0,0 +1,188 @@
1
+ import { markQExceptionHandled } from "./q";
2
+ import { minErr } from "./utils";
3
+
4
+ const $intervalMinErr = minErr("$interval");
5
+
6
+ export function $IntervalProvider() {
7
+ this.$get = [
8
+ "$$intervalFactory",
9
+ function ($$intervalFactory) {
10
+ const intervals = {};
11
+ const setIntervalFn = function (tick, delay, deferred) {
12
+ const id = window.setInterval(tick, delay);
13
+ intervals[id] = deferred;
14
+ return id;
15
+ };
16
+ const clearIntervalFn = function (id) {
17
+ window.clearInterval(id);
18
+ delete intervals[id];
19
+ };
20
+
21
+ /**
22
+ * @ngdoc service
23
+ * @name $interval
24
+ *
25
+ * @description
26
+ * AngularJS's wrapper for `window.setInterval`. The `fn` function is executed every `delay`
27
+ * milliseconds.
28
+ *
29
+ * The return value of registering an interval function is a promise. This promise will be
30
+ * notified upon each tick of the interval, and will be resolved after `count` iterations, or
31
+ * run indefinitely if `count` is not defined. The value of the notification will be the
32
+ * number of iterations that have run.
33
+ * To cancel an interval, call `$interval.cancel(promise)`.
34
+ *
35
+ * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to
36
+ * move forward by `millis` milliseconds and trigger any functions scheduled to run in that
37
+ * time.
38
+ *
39
+ * <div class="alert alert-warning">
40
+ * **Note**: Intervals created by this service must be explicitly destroyed when you are finished
41
+ * with them. In particular they are not automatically destroyed when a controller's scope or a
42
+ * directive's element are destroyed.
43
+ * You should take this into consideration and make sure to always cancel the interval at the
44
+ * appropriate moment. See the example below for more details on how and when to do this.
45
+ * </div>
46
+ *
47
+ * @param {function()} fn A function that should be called repeatedly. If no additional arguments
48
+ * are passed (see below), the function is called with the current iteration count.
49
+ * @param {number} delay Number of milliseconds between each function call.
50
+ * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat
51
+ * indefinitely.
52
+ * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
53
+ * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
54
+ * @param {...*=} Pass additional parameters to the executed function.
55
+ * @returns {promise} A promise which will be notified on each iteration. It will resolve once all iterations of the interval complete.
56
+ *
57
+ * @example
58
+ * <example module="intervalExample" name="interval-service">
59
+ * <file name="index.html">
60
+ * <script>
61
+ * angular.module('intervalExample', [])
62
+ * .controller('ExampleController', ['$scope', '$interval',
63
+ * function($scope, $interval) {
64
+ * $scope.format = 'M/d/yy h:mm:ss a';
65
+ * $scope.blood_1 = 100;
66
+ * $scope.blood_2 = 120;
67
+ *
68
+ * let stop;
69
+ * $scope.fight = function() {
70
+ * // Don't start a new fight if we are already fighting
71
+ * if ( angular.isDefined(stop) ) return;
72
+ *
73
+ * stop = $interval(function() {
74
+ * if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
75
+ * $scope.blood_1 = $scope.blood_1 - 3;
76
+ * $scope.blood_2 = $scope.blood_2 - 4;
77
+ * } else {
78
+ * $scope.stopFight();
79
+ * }
80
+ * }, 100);
81
+ * };
82
+ *
83
+ * $scope.stopFight = function() {
84
+ * if (angular.isDefined(stop)) {
85
+ * $interval.cancel(stop);
86
+ * stop = undefined;
87
+ * }
88
+ * };
89
+ *
90
+ * $scope.resetFight = function() {
91
+ * $scope.blood_1 = 100;
92
+ * $scope.blood_2 = 120;
93
+ * };
94
+ *
95
+ * $scope.$on('$destroy', function() {
96
+ * // Make sure that the interval is destroyed too
97
+ * $scope.stopFight();
98
+ * });
99
+ * }])
100
+ * // Register the 'myCurrentTime' directive factory method.
101
+ * // We inject $interval and dateFilter service since the factory method is DI.
102
+ * .directive('myCurrentTime', ['$interval', 'dateFilter',
103
+ * function($interval, dateFilter) {
104
+ * // return the directive link function. (compile function not needed)
105
+ * return function(scope, element, attrs) {
106
+ * let format, // date format
107
+ * stopTime; // so that we can cancel the time updates
108
+ *
109
+ * // used to update the UI
110
+ * function updateTime() {
111
+ * element.text(dateFilter(new Date(), format));
112
+ * }
113
+ *
114
+ * // watch the expression, and update the UI on change.
115
+ * scope.$watch(attrs.myCurrentTime, function(value) {
116
+ * format = value;
117
+ * updateTime();
118
+ * });
119
+ *
120
+ * stopTime = $interval(updateTime, 1000);
121
+ *
122
+ * // listen on DOM destroy (removal) event, and cancel the next UI update
123
+ * // to prevent updating time after the DOM element was removed.
124
+ * element.on('$destroy', function() {
125
+ * $interval.cancel(stopTime);
126
+ * });
127
+ * }
128
+ * }]);
129
+ * </script>
130
+ *
131
+ * <div>
132
+ * <div ng-controller="ExampleController">
133
+ * <label>Date format: <input ng-model="format"></label> <hr/>
134
+ * Current time is: <span my-current-time="format"></span>
135
+ * <hr/>
136
+ * Blood 1 : <font color='red'>{{blood_1}}</font>
137
+ * Blood 2 : <font color='red'>{{blood_2}}</font>
138
+ * <button type="button" data-ng-click="fight()">Fight</button>
139
+ * <button type="button" data-ng-click="stopFight()">StopFight</button>
140
+ * <button type="button" data-ng-click="resetFight()">resetFight</button>
141
+ * </div>
142
+ * </div>
143
+ *
144
+ * </file>
145
+ * </example>
146
+ */
147
+ const interval = $$intervalFactory(setIntervalFn, clearIntervalFn);
148
+
149
+ /**
150
+ * @ngdoc method
151
+ * @name $interval#cancel
152
+ *
153
+ * @description
154
+ * Cancels a task associated with the `promise`.
155
+ *
156
+ * @param {Promise=} promise returned by the `$interval` function.
157
+ * @returns {boolean} Returns `true` if the task was successfully canceled.
158
+ */
159
+ interval.cancel = function (promise) {
160
+ if (!promise) return false;
161
+
162
+ if (!Object.prototype.hasOwnProperty.call(promise, "$$intervalId")) {
163
+ throw $intervalMinErr(
164
+ "badprom",
165
+ "`$interval.cancel()` called with a promise that was not generated by `$interval()`.",
166
+ );
167
+ }
168
+
169
+ if (
170
+ !Object.prototype.hasOwnProperty.call(intervals, promise.$$intervalId)
171
+ )
172
+ return false;
173
+
174
+ const id = promise.$$intervalId;
175
+ const deferred = intervals[id];
176
+
177
+ // Interval cancels should not report an unhandled promise.
178
+ markQExceptionHandled(deferred.promise);
179
+ deferred.reject("canceled");
180
+ clearIntervalFn(id);
181
+
182
+ return true;
183
+ };
184
+
185
+ return interval;
186
+ },
187
+ ];
188
+ }
@@ -0,0 +1,57 @@
1
+ import { isDefined, sliceArgs } from "./utils";
2
+
3
+ export function $$IntervalFactoryProvider() {
4
+ this.$get = [
5
+ "$browser",
6
+ "$q",
7
+ "$$q",
8
+ "$rootScope",
9
+ function ($browser, $q, $$q, $rootScope) {
10
+ return function intervalFactory(setIntervalFn, clearIntervalFn) {
11
+ return function intervalFn(fn, delay, count, invokeApply) {
12
+ const hasParams = arguments.length > 4;
13
+ const args = hasParams ? sliceArgs(arguments, 4) : [];
14
+ let iteration = 0;
15
+ const skipApply = isDefined(invokeApply) && !invokeApply;
16
+ const deferred = (skipApply ? $$q : $q).defer();
17
+ const { promise } = deferred;
18
+
19
+ count = isDefined(count) ? count : 0;
20
+
21
+ function callback() {
22
+ if (!hasParams) {
23
+ fn(iteration);
24
+ } else {
25
+ fn.apply(null, args);
26
+ }
27
+ }
28
+
29
+ function tick() {
30
+ if (skipApply) {
31
+ $browser.defer(callback);
32
+ } else {
33
+ $rootScope.$evalAsync(callback);
34
+ }
35
+ deferred.notify(iteration++);
36
+
37
+ if (count > 0 && iteration >= count) {
38
+ deferred.resolve(iteration);
39
+ clearIntervalFn(promise.$$intervalId);
40
+ }
41
+
42
+ if (!skipApply) $rootScope.$apply();
43
+ }
44
+
45
+ promise.$$intervalId = setIntervalFn(
46
+ tick,
47
+ delay,
48
+ deferred,
49
+ skipApply,
50
+ );
51
+
52
+ return promise;
53
+ };
54
+ };
55
+ },
56
+ ];
57
+ }