@angular-wave/angular.ts 0.10.0 → 0.12.0

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 (62) hide show
  1. package/@types/angular.d.ts +84 -58
  2. package/@types/animations/animate-css-driver.d.ts +0 -1
  3. package/@types/animations/animate-css.d.ts +0 -1
  4. package/@types/animations/animate-js-driver.d.ts +1 -7
  5. package/@types/animations/animate-js.d.ts +1 -4
  6. package/@types/animations/animate.d.ts +5 -355
  7. package/@types/animations/animation.d.ts +4 -4
  8. package/@types/animations/interface.d.ts +84 -0
  9. package/@types/animations/queue/animate-queue.d.ts +21 -0
  10. package/@types/animations/queue/interface.d.ts +50 -0
  11. package/@types/animations/runner/animate-runner.d.ts +99 -0
  12. package/@types/core/compile/attributes.d.ts +5 -5
  13. package/@types/core/compile/compile.d.ts +4 -4
  14. package/@types/core/controller/controller.d.ts +1 -1
  15. package/@types/core/di/di.d.ts +26 -0
  16. package/@types/core/di/injector.d.ts +0 -11
  17. package/@types/core/di/internal-injector.d.ts +2 -2
  18. package/@types/core/di/ng-module/ng-module.d.ts +197 -0
  19. package/@types/core/filter/filter.d.ts +2 -2
  20. package/@types/core/sanitize/interface.d.ts +8 -0
  21. package/@types/core/sanitize/sanitize-uri.d.ts +5 -2
  22. package/@types/core/scope/interface.d.ts +2 -2
  23. package/@types/core/scope/scope.d.ts +10 -2
  24. package/@types/directive/class/class.d.ts +3 -3
  25. package/@types/directive/form/form.d.ts +7 -7
  26. package/@types/directive/if/if.d.ts +2 -2
  27. package/@types/directive/include/include.d.ts +4 -4
  28. package/@types/directive/inject/inject.d.ts +2 -2
  29. package/@types/directive/input/input.d.ts +10 -10
  30. package/@types/directive/messages/messages.d.ts +19 -23
  31. package/@types/directive/model/model.d.ts +3 -3
  32. package/@types/directive/scope/scope.d.ts +4 -0
  33. package/@types/directive/show-hide/show-hide.d.ts +3 -4
  34. package/@types/directive/switch/switch.d.ts +3 -5
  35. package/@types/directive/wasm/wasm.d.ts +4 -0
  36. package/@types/{services → directive}/worker/interface.d.ts +1 -0
  37. package/@types/directive/worker/worker.d.ts +18 -8
  38. package/@types/interface.d.ts +49 -21
  39. package/@types/namespace.d.ts +29 -4
  40. package/@types/ng.d.ts +3 -5
  41. package/@types/router/params/interface.d.ts +0 -25
  42. package/@types/router/state/interface.d.ts +0 -9
  43. package/@types/router/template-factory.d.ts +1 -1
  44. package/@types/router/transition/interface.d.ts +0 -33
  45. package/@types/services/log/log.d.ts +2 -2
  46. package/@types/services/sce/sce.d.ts +4 -82
  47. package/@types/services/sse/sse.d.ts +1 -5
  48. package/@types/services/storage/interface.d.ts +5 -0
  49. package/@types/services/storage/storage.d.ts +19 -0
  50. package/@types/services/stream/interface.d.ts +18 -0
  51. package/@types/shared/dom.d.ts +25 -10
  52. package/@types/shared/strings.d.ts +0 -6
  53. package/@types/shared/utils.d.ts +24 -14
  54. package/dist/angular-ts.esm.js +1867 -1506
  55. package/dist/angular-ts.umd.js +1867 -1506
  56. package/dist/angular-ts.umd.min.js +1 -1
  57. package/dist/angular.css +1 -1
  58. package/package.json +1 -2
  59. package/@types/animations/animate-queue.d.ts +0 -27
  60. package/@types/animations/animate-runner.d.ts +0 -31
  61. package/@types/core/di/ng-module.d.ts +0 -156
  62. package/@types/services/worker/worker.d.ts +0 -31
@@ -1,4 +1,4 @@
1
- /* Version: 0.10.0 - November 8, 2025 10:37:13 */
1
+ /* Version: 0.12.0 - November 29, 2025 19:42:34 */
2
2
  (function (global, factory) {
3
3
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
4
4
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
@@ -38,7 +38,7 @@
38
38
  return !!(value && value[isProxySymbol]);
39
39
  }
40
40
 
41
- const ngMinErr$2 = minErr("ng");
41
+ const ngMinErr$1 = minErr("ng");
42
42
 
43
43
  /**
44
44
  * @type {number}
@@ -376,26 +376,6 @@
376
376
  return isFunction(obj.toString) && obj.toString !== toString;
377
377
  }
378
378
 
379
- /**
380
- * @module angular
381
- * @function isElement
382
-
383
- * @function
384
- *
385
- * @description
386
- * Determines if a reference is a DOM element (or wrapped jQuery element).
387
- *
388
- * @param {*} node Reference to check.
389
- * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).
390
- */
391
- function isElement(node) {
392
- return !!(
393
- node &&
394
- (node.nodeName || // We are a direct element.
395
- (node.attr && node.find))
396
- ); // We have an on and find method part of jQuery API.
397
- }
398
-
399
379
  /**
400
380
  * Returns a string appropriate for the type of node.
401
381
  *
@@ -553,7 +533,7 @@
553
533
  */
554
534
  function assertNotHasOwnProperty(name, context) {
555
535
  if (name === "hasOwnProperty") {
556
- throw ngMinErr$2(
536
+ throw ngMinErr$1(
557
537
  "badname",
558
538
  "hasOwnProperty is not a valid {0} name",
559
539
  context,
@@ -883,9 +863,9 @@
883
863
  /**
884
864
  * Throw error if the argument is falsy.
885
865
  */
886
- function assertArg$1(arg, name, reason) {
866
+ function assertArg(arg, name, reason) {
887
867
  if (!arg) {
888
- throw ngMinErr$2(
868
+ throw ngMinErr$1(
889
869
  "areq",
890
870
  "Argument '{0}' is {1}",
891
871
  name || "?",
@@ -900,7 +880,7 @@
900
880
  arg = arg[arg.length - 1];
901
881
  }
902
882
 
903
- assertArg$1(
883
+ assertArg(
904
884
  isFunction(arg),
905
885
  name,
906
886
  `not a function, got ${
@@ -1048,13 +1028,38 @@
1048
1028
  return `${objType}:${obj}`;
1049
1029
  }
1050
1030
 
1051
- function mergeClasses$1(a, b) {
1031
+ /**
1032
+ * Merges two class name values into a single space-separated string.
1033
+ * Accepts strings, arrays of strings, or null/undefined values.
1034
+ *
1035
+ * @param {string | string[] | null | undefined} a - The first class name(s).
1036
+ * @param {string | string[] | null | undefined} b - The second class name(s).
1037
+ * @returns {string} A single string containing all class names separated by spaces.
1038
+ */
1039
+ function mergeClasses(a, b) {
1052
1040
  if (!a && !b) return "";
1053
- if (!a) return b;
1054
- if (!b) return a;
1055
- if (Array.isArray(a)) a = a.join(" ");
1056
- if (Array.isArray(b)) b = b.join(" ");
1057
- return a + " " + b;
1041
+ if (!a) return Array.isArray(b) ? b.join(" ").trim() : b;
1042
+ if (!b) return Array.isArray(a) ? a.join(" ").trim() : a;
1043
+ if (Array.isArray(a)) a = normalizeStringArray(a);
1044
+ if (Array.isArray(b)) b = normalizeStringArray(b);
1045
+ return `${a.trim()} ${b.trim()}`.trim();
1046
+ }
1047
+
1048
+ /**
1049
+ * Joins an array of strings into a single string, trimming each
1050
+ * element and ignoring empty strings, null, and undefined
1051
+ * @param {any[]} arr
1052
+ * @returns {string}
1053
+ */
1054
+ function normalizeStringArray(arr) {
1055
+ const cleaned = [];
1056
+ for (const item of arr) {
1057
+ if (item) {
1058
+ const trimmed = item.trim();
1059
+ if (trimmed) cleaned.push(trimmed);
1060
+ }
1061
+ }
1062
+ return cleaned.join(" ");
1058
1063
  }
1059
1064
 
1060
1065
  /**
@@ -1196,6 +1201,30 @@
1196
1201
  return str.slice(0, search.length) === search;
1197
1202
  }
1198
1203
 
1204
+ /**
1205
+ * Loads and instantiates a WebAssembly module.
1206
+ * Tries streaming first, then falls back.
1207
+ */
1208
+ async function instantiateWasm(src, imports = {}) {
1209
+ const res = await fetch(src);
1210
+ if (!res.ok) throw new Error("fetch failed");
1211
+
1212
+ try {
1213
+ const { instance, module } = await WebAssembly.instantiateStreaming(
1214
+ res.clone(),
1215
+ imports,
1216
+ );
1217
+ return { instance, exports: instance.exports, module };
1218
+ } catch {
1219
+ /* empty */
1220
+ }
1221
+
1222
+ const bytes = await res.arrayBuffer();
1223
+ const { instance, module } = await WebAssembly.instantiate(bytes, imports);
1224
+
1225
+ return { instance, exports: instance.exports, module };
1226
+ }
1227
+
1199
1228
  /**
1200
1229
  * Expando cache for adding properties to DOM nodes with JavaScript.
1201
1230
  * This used to be an Object in JQLite decorator, but swapped out for a Map
@@ -1285,19 +1314,6 @@
1285
1314
  const TRANSITION_DELAY_PROP = TRANSITION_PROP + DELAY_KEY;
1286
1315
  const TRANSITION_DURATION_PROP = TRANSITION_PROP + DURATION_KEY;
1287
1316
 
1288
- const ngMinErr$1 = minErr("ng");
1289
- function assertArg(arg, name, reason) {
1290
- if (!arg) {
1291
- throw ngMinErr$1(
1292
- "areq",
1293
- "Argument '{0}' is {1}",
1294
- name || "?",
1295
- reason,
1296
- );
1297
- }
1298
- return arg;
1299
- }
1300
-
1301
1317
  function packageStyles(options) {
1302
1318
  const styles = {};
1303
1319
  if (options && (options.to || options.from)) {
@@ -1338,7 +1354,7 @@
1338
1354
  */
1339
1355
  function stripCommentsFromElement(element) {
1340
1356
  if (element instanceof NodeList) {
1341
- return Array.from(element).filter((x) => x.nodeType == Node.ELEMENT_NODE);
1357
+ return Array.from(element).filter((x) => x.nodeType === Node.ELEMENT_NODE);
1342
1358
  } else if (element.nodeType === Node.ELEMENT_NODE) {
1343
1359
  return /** @type {Node} */ (element);
1344
1360
  } else {
@@ -1581,7 +1597,7 @@
1581
1597
  }
1582
1598
 
1583
1599
  /** @type {number} */
1584
- let jqId = 1;
1600
+ let elId = 1;
1585
1601
 
1586
1602
  /**
1587
1603
  * Key for storing isolate scope data, attached to an element
@@ -1633,8 +1649,8 @@
1633
1649
  *
1634
1650
  * @returns {number} Next unique JQInstance id
1635
1651
  */
1636
- function jqNextId() {
1637
- return ++jqId;
1652
+ function elemNextId() {
1653
+ return ++elId;
1638
1654
  }
1639
1655
 
1640
1656
  /**
@@ -1700,7 +1716,7 @@
1700
1716
  let expandoStore = expandoId && Cache.get(expandoId);
1701
1717
 
1702
1718
  if (createIfNecessary && !expandoStore) {
1703
- element[EXPANDO] = expandoId = jqNextId();
1719
+ element[EXPANDO] = expandoId = elemNextId();
1704
1720
  expandoStore = {
1705
1721
  data: {},
1706
1722
  };
@@ -1873,7 +1889,7 @@
1873
1889
  * Gets scope for a given element.
1874
1890
  *
1875
1891
  * @param {Element} element - The DOM element to get data from.
1876
- * @returns {*} - The retrieved data for the given key or all data if no key is provided.
1892
+ * @returns {ng.Scope} - The retrieved data for the given key or all data if no key is provided.
1877
1893
  */
1878
1894
  function getScope(element) {
1879
1895
  return getCacheData(element, SCOPE_KEY);
@@ -1903,7 +1919,7 @@
1903
1919
  * Gets the controller instance for a given element, if exists. Defaults to "ngControllerController"
1904
1920
  *
1905
1921
  * @param {Element} element - The DOM element to get data from.
1906
- * @param {string} [name] - The DOM element to get data from.
1922
+ * @param {string} [name] - Controller name.
1907
1923
  * @returns {import("../core/scope/scope.js").Scope|undefined} - The retrieved data
1908
1924
  */
1909
1925
  function getController(element, name) {
@@ -2053,7 +2069,7 @@
2053
2069
  /**
2054
2070
  * Return instance of InjectorService attached to element
2055
2071
  * @param {Element} element
2056
- * @returns {import('../core/di/internal-injector.js').InjectorService}
2072
+ * @returns {ng.InjectorService}
2057
2073
  */
2058
2074
  function getInjector(element) {
2059
2075
  return getInheritedData(element, "$injector");
@@ -2096,6 +2112,22 @@
2096
2112
  }
2097
2113
  }
2098
2114
 
2115
+ /**
2116
+ * Inserts a DOM element before or at the beginning of a parent element.
2117
+ *
2118
+ * @param {HTMLElement | Element} element
2119
+ * The element to insert into the DOM.
2120
+ *
2121
+ * @param {HTMLElement | Element} parentElement
2122
+ * The parent element that will receive the inserted element.
2123
+ *
2124
+ * @param {HTMLElement | Element | null} [afterElement]
2125
+ * An optional sibling element — if present and valid, `element`
2126
+ * will be inserted after it. If omitted or invalid, `element`
2127
+ * is prepended to `parentElement`.
2128
+ *
2129
+ * @returns {void}
2130
+ */
2099
2131
  function domInsert(element, parentElement, afterElement) {
2100
2132
  // if for some reason the previous element was removed
2101
2133
  // from the dom sometime before this code runs then let's
@@ -2113,6 +2145,26 @@
2113
2145
  }
2114
2146
  }
2115
2147
 
2148
+ function animatedomInsert(element, parent, after) {
2149
+ const originalVisibility = element.style.visibility;
2150
+ const originalPosition = element.style.position;
2151
+ const originalPointerEvents = element.style.pointerEvents;
2152
+
2153
+ Object.assign(element.style, {
2154
+ visibility: "hidden",
2155
+ position: "absolute",
2156
+ pointerEvents: "none",
2157
+ });
2158
+
2159
+ domInsert(element, parent, after);
2160
+
2161
+ requestAnimationFrame(() => {
2162
+ element.style.visibility = originalVisibility;
2163
+ element.style.position = originalPosition;
2164
+ element.style.pointerEvents = originalPointerEvents;
2165
+ });
2166
+ }
2167
+
2116
2168
  /**
2117
2169
  * Returns the base href of the document.
2118
2170
  *
@@ -2144,8 +2196,6 @@
2144
2196
  $attrs: "$attrs",
2145
2197
  $scope: "$scope",
2146
2198
  $element: "$element",
2147
- $$AnimateRunner: "$$AnimateRunner",
2148
- $$animateAsyncRun: "$$animateAsyncRun",
2149
2199
  $$animateCache: "$$animateCache",
2150
2200
  $$animateCssDriver: "$$animateCssDriver",
2151
2201
  $$animateJs: "$$animateJs",
@@ -2206,6 +2256,706 @@
2206
2256
  return services.map((x) => x + "Provider");
2207
2257
  }
2208
2258
 
2259
+ /**
2260
+ * @param {"get" | "delete" | "post" | "put"} method - HTTP method applied to request
2261
+ * @param {string} [attrOverride] - Custom name to use for the attribute
2262
+ * @returns {ng.DirectiveFactory}
2263
+ */
2264
+ function defineDirective(method, attrOverride) {
2265
+ const attrName =
2266
+ attrOverride || "ng" + method.charAt(0).toUpperCase() + method.slice(1);
2267
+ const directive = createHttpDirective(method, attrName);
2268
+ directive["$inject"] = [
2269
+ $injectTokens.$http,
2270
+ $injectTokens.$compile,
2271
+ $injectTokens.$log,
2272
+ $injectTokens.$parse,
2273
+ $injectTokens.$state,
2274
+ $injectTokens.$sse,
2275
+ $injectTokens.$animate,
2276
+ ];
2277
+ return directive;
2278
+ }
2279
+
2280
+ /** @type {ng.DirectiveFactory} */
2281
+ const ngGetDirective = defineDirective("get");
2282
+
2283
+ /** @type {ng.DirectiveFactory} */
2284
+ const ngDeleteDirective = defineDirective("delete");
2285
+
2286
+ /** @type {ng.DirectiveFactory} */
2287
+ const ngPostDirective = defineDirective("post");
2288
+
2289
+ /** @type {ng.DirectiveFactory} */
2290
+ const ngPutDirective = defineDirective("put");
2291
+
2292
+ /** @type {ng.DirectiveFactory} */
2293
+ const ngSseDirective = defineDirective("get", "ngSse");
2294
+
2295
+ /**
2296
+ * Selects DOM event to listen for based on the element type.
2297
+ *
2298
+ * @param {Element} element - The DOM element to inspect.
2299
+ * @returns {"click" | "change" | "submit"} The name of the event to listen for.
2300
+ */
2301
+ function getEventNameForElement(element) {
2302
+ const tag = element.tagName.toLowerCase();
2303
+ if (["input", "textarea", "select"].includes(tag)) {
2304
+ return "change";
2305
+ } else if (tag === "form") {
2306
+ return "submit";
2307
+ }
2308
+ return "click";
2309
+ }
2310
+
2311
+ /**
2312
+ * Creates an HTTP directive factory that supports GET, DELETE, POST, PUT.
2313
+ *
2314
+ * @param {"get" | "delete" | "post" | "put"} method - HTTP method to use.
2315
+ * @param {string} attrName - Attribute name containing the URL.
2316
+ * @returns {ng.DirectiveFactory}
2317
+ */
2318
+ function createHttpDirective(method, attrName) {
2319
+ /**
2320
+ * @param {ng.HttpService} $http
2321
+ * @param {ng.CompileService} $compile
2322
+ * @param {ng.LogService} $log
2323
+ * @param {ng.ParseService} $parse
2324
+ * @param {ng.StateService} $state
2325
+ * @param {ng.SseService} $sse
2326
+ * @param {ng.AnimateService} $animate
2327
+ * @returns {ng.Directive}
2328
+ */
2329
+ return function ($http, $compile, $log, $parse, $state, $sse, $animate) {
2330
+ /**
2331
+ * Collects form data from the element or its associated form.
2332
+ *
2333
+ * @param {HTMLElement} element
2334
+ * @returns {Object<string, any>}
2335
+ */
2336
+ function collectFormData(element) {
2337
+ /** @type {HTMLFormElement | null} */
2338
+ let form = null;
2339
+
2340
+ const tag = element.tagName.toLowerCase();
2341
+
2342
+ if (tag === "form") {
2343
+ form = /** @type {HTMLFormElement} */ (element);
2344
+ } else if ("form" in element && element.form) {
2345
+ form = /** @type {HTMLFormElement} */ (element.form);
2346
+ } else if (element.hasAttribute("form")) {
2347
+ const formId = element.getAttribute("form");
2348
+ if (formId) {
2349
+ const maybeForm = document.getElementById(formId);
2350
+ if (maybeForm && maybeForm.tagName.toLowerCase() === "form") {
2351
+ form = /** @type {HTMLFormElement} */ (maybeForm);
2352
+ }
2353
+ }
2354
+ }
2355
+
2356
+ if (!form) {
2357
+ if (
2358
+ "name" in element &&
2359
+ typeof element.name === "string" &&
2360
+ element.name.length > 0
2361
+ ) {
2362
+ if (
2363
+ element instanceof HTMLInputElement ||
2364
+ element instanceof HTMLTextAreaElement ||
2365
+ element instanceof HTMLSelectElement
2366
+ ) {
2367
+ const key = element.name;
2368
+ const value = element.value;
2369
+ return { [key]: value };
2370
+ }
2371
+ }
2372
+ return {};
2373
+ }
2374
+
2375
+ const formData = new FormData(form);
2376
+ const data = {};
2377
+ formData.forEach((value, key) => {
2378
+ data[key] = value;
2379
+ });
2380
+ return data;
2381
+ }
2382
+
2383
+ return {
2384
+ restrict: "A",
2385
+ link(scope, element, attrs) {
2386
+ const eventName = attrs.trigger || getEventNameForElement(element);
2387
+ const tag = element.tagName.toLowerCase();
2388
+ let content = undefined;
2389
+
2390
+ if (isDefined(attrs.latch)) {
2391
+ attrs.$observe(
2392
+ "latch",
2393
+ callBackAfterFirst(() =>
2394
+ element.dispatchEvent(new Event(eventName)),
2395
+ ),
2396
+ );
2397
+ }
2398
+
2399
+ let throttled = false;
2400
+ let intervalId;
2401
+
2402
+ if (isDefined(attrs["interval"])) {
2403
+ element.dispatchEvent(new Event(eventName));
2404
+ intervalId = setInterval(
2405
+ () => element.dispatchEvent(new Event(eventName)),
2406
+ parseInt(attrs.interval) || 1000,
2407
+ );
2408
+ }
2409
+
2410
+ /**
2411
+ * Handles DOM manipulation based on a swap strategy and server-rendered HTML.
2412
+ *
2413
+ * @param {string | Object} html - The HTML string or object returned from the server.
2414
+ * @param {import("./interface.ts").SwapModeType} swap
2415
+ * @param {ng.Scope} scope
2416
+ * @param {ng.Attributes} attrs
2417
+ * @param {Element} element
2418
+ */
2419
+ function handleSwapResponse(html, swap, scope, attrs, element) {
2420
+ let animationEnabled = false;
2421
+ if (attrs.animate) {
2422
+ animationEnabled = true;
2423
+ }
2424
+ let nodes = [];
2425
+ if (!["textcontent", "delete", "none"].includes(swap)) {
2426
+ if (!html) return;
2427
+ const compiled = $compile(html)(scope);
2428
+ nodes =
2429
+ compiled instanceof DocumentFragment
2430
+ ? Array.from(compiled.childNodes)
2431
+ : [compiled];
2432
+ }
2433
+
2434
+ const targetSelector = attrs.target;
2435
+ const target = targetSelector
2436
+ ? document.querySelector(targetSelector)
2437
+ : element;
2438
+
2439
+ if (!target) {
2440
+ $log.warn(`${attrName}: target "${targetSelector}" not found`);
2441
+ return;
2442
+ }
2443
+
2444
+ switch (swap) {
2445
+ case "outerHTML": {
2446
+ const parent = target.parentNode;
2447
+ if (!parent) return;
2448
+
2449
+ // Build fragment for static replacement OR a list for animation
2450
+ const frag = document.createDocumentFragment();
2451
+ nodes.forEach((n) => frag.appendChild(n));
2452
+
2453
+ if (!animationEnabled) {
2454
+ parent.replaceChild(frag, target);
2455
+ break;
2456
+ }
2457
+
2458
+ const placeholder = document.createElement("span");
2459
+ placeholder.style.display = "none";
2460
+ parent.insertBefore(placeholder, target.nextSibling);
2461
+
2462
+ $animate.leave(target).done(() => {
2463
+ const insertedNodes = Array.from(frag.childNodes);
2464
+
2465
+ // Insert each node in order
2466
+ for (const n of insertedNodes) {
2467
+ if (n.nodeType === Node.ELEMENT_NODE) {
2468
+ // Animate elements
2469
+ $animate.enter(
2470
+ /** @type {Element} */ (n),
2471
+ parent,
2472
+ placeholder,
2473
+ );
2474
+ } else {
2475
+ // Insert text nodes statically
2476
+ parent.insertBefore(n, placeholder);
2477
+ }
2478
+ }
2479
+
2480
+ content = insertedNodes;
2481
+ scope.$flushQueue(); // flush once after all insertions
2482
+ });
2483
+
2484
+ scope.$flushQueue(); // flush leave animation
2485
+ break;
2486
+ }
2487
+
2488
+ case "textContent":
2489
+ if (animationEnabled) {
2490
+ $animate.leave(target).done(() => {
2491
+ target.textContent = html;
2492
+ $animate.enter(target, target.parentNode);
2493
+ scope.$flushQueue();
2494
+ });
2495
+
2496
+ scope.$flushQueue();
2497
+ } else {
2498
+ target.textContent = html;
2499
+ }
2500
+ break;
2501
+
2502
+ case "beforebegin": {
2503
+ const parent = target.parentNode;
2504
+ if (!parent) break;
2505
+
2506
+ nodes.forEach((node) => {
2507
+ if (animationEnabled && node.nodeType === Node.ELEMENT_NODE) {
2508
+ $animate.enter(node, parent, target); // insert before target
2509
+ } else {
2510
+ parent.insertBefore(node, target);
2511
+ }
2512
+ });
2513
+
2514
+ if (animationEnabled) scope.$flushQueue();
2515
+ break;
2516
+ }
2517
+
2518
+ case "afterbegin": {
2519
+ const firstChild = target.firstChild;
2520
+ [...nodes].reverse().forEach((node) => {
2521
+ if (animationEnabled && node.nodeType === Node.ELEMENT_NODE) {
2522
+ $animate.enter(node, target, firstChild); // insert before first child
2523
+ } else {
2524
+ target.insertBefore(node, firstChild);
2525
+ }
2526
+ });
2527
+
2528
+ if (animationEnabled) scope.$flushQueue();
2529
+ break;
2530
+ }
2531
+
2532
+ case "beforeend": {
2533
+ nodes.forEach((node) => {
2534
+ if (animationEnabled && node.nodeType === Node.ELEMENT_NODE) {
2535
+ $animate.enter(node, target, null); // append at end
2536
+ } else {
2537
+ target.appendChild(node);
2538
+ }
2539
+ });
2540
+
2541
+ if (animationEnabled) scope.$flushQueue();
2542
+ break;
2543
+ }
2544
+
2545
+ case "afterend": {
2546
+ const parent = target.parentNode;
2547
+ if (!parent) break;
2548
+ const nextSibling = target.nextSibling;
2549
+
2550
+ [...nodes].reverse().forEach((node) => {
2551
+ if (animationEnabled && node.nodeType === Node.ELEMENT_NODE) {
2552
+ $animate.enter(node, parent, nextSibling); // insert after target
2553
+ } else {
2554
+ parent.insertBefore(node, nextSibling);
2555
+ }
2556
+ });
2557
+
2558
+ if (animationEnabled) scope.$flushQueue();
2559
+ break;
2560
+ }
2561
+
2562
+ case "delete":
2563
+ if (animationEnabled) {
2564
+ $animate.leave(target).done(() => {
2565
+ target.remove(); // safety: actually remove in case $animate.leave didn't
2566
+ scope.$flushQueue();
2567
+ });
2568
+ scope.$flushQueue();
2569
+ } else {
2570
+ target.remove();
2571
+ }
2572
+ break;
2573
+
2574
+ case "none":
2575
+ break;
2576
+
2577
+ case "innerHTML":
2578
+ default:
2579
+ if (animationEnabled) {
2580
+ if (content && content.nodeType !== Node.TEXT_NODE) {
2581
+ $animate.leave(content).done(() => {
2582
+ content = nodes[0];
2583
+ $animate.enter(nodes[0], target);
2584
+ scope.$flushQueue();
2585
+ });
2586
+ scope.$flushQueue();
2587
+ } else {
2588
+ content = nodes[0];
2589
+ if (content.nodeType === Node.TEXT_NODE) {
2590
+ target.replaceChildren(...nodes);
2591
+ } else {
2592
+ $animate.enter(nodes[0], target);
2593
+ scope.$flushQueue();
2594
+ }
2595
+ }
2596
+ } else {
2597
+ target.replaceChildren(...nodes);
2598
+ }
2599
+ break;
2600
+ }
2601
+ }
2602
+
2603
+ element.addEventListener(eventName, async (event) => {
2604
+ if (/** @type {HTMLButtonElement} */ (element).disabled) return;
2605
+ if (tag === "form") event.preventDefault();
2606
+ const swap = attrs.swap || "innerHTML";
2607
+ const url = attrs[attrName];
2608
+ if (!url) {
2609
+ $log.warn(`${attrName}: no URL specified`);
2610
+ return;
2611
+ }
2612
+
2613
+ const handler = (res) => {
2614
+ if (isDefined(attrs.loading)) {
2615
+ attrs.$set("loading", false);
2616
+ }
2617
+
2618
+ if (isDefined(attrs.loadingClass)) {
2619
+ attrs.$removeClass(attrs.loadingClass);
2620
+ }
2621
+
2622
+ const html = res.data;
2623
+ if (200 <= res.status && res.status <= 299) {
2624
+ if (isDefined(attrs.success)) {
2625
+ $parse(attrs.success)(scope, { $res: html });
2626
+ }
2627
+
2628
+ if (isDefined(attrs.stateSuccess)) {
2629
+ $state.go(attrs.stateSuccess);
2630
+ }
2631
+ } else if (400 <= res.status && res.status <= 599) {
2632
+ if (isDefined(attrs.error)) {
2633
+ $parse(attrs.error)(scope, { $res: html });
2634
+ }
2635
+
2636
+ if (isDefined(attrs.stateError)) {
2637
+ $state.go(attrs.stateError);
2638
+ }
2639
+ }
2640
+
2641
+ if (isObject(html)) {
2642
+ if (attrs.target) {
2643
+ scope.$eval(`${attrs.target} = ${JSON.stringify(html)}`);
2644
+ } else {
2645
+ scope.$merge(html);
2646
+ }
2647
+ } else if (isString(html)) {
2648
+ handleSwapResponse(html, swap, scope, attrs, element);
2649
+ }
2650
+ };
2651
+
2652
+ if (isDefined(attrs.delay)) {
2653
+ await wait(parseInt(attrs.delay) | 0);
2654
+ }
2655
+
2656
+ if (throttled) return;
2657
+
2658
+ if (isDefined(attrs.throttle)) {
2659
+ throttled = true;
2660
+ attrs.$set("throttled", true);
2661
+ setTimeout(() => {
2662
+ attrs.$set("throttled", false);
2663
+ throttled = false;
2664
+ }, parseInt(attrs.throttle));
2665
+ }
2666
+
2667
+ if (isDefined(attrs["loading"])) {
2668
+ attrs.$set("loading", true);
2669
+ }
2670
+
2671
+ if (isDefined(attrs["loadingClass"])) {
2672
+ attrs.$addClass(attrs.loadingClass);
2673
+ }
2674
+
2675
+ if (method === "post" || method === "put") {
2676
+ let data;
2677
+ const config = {};
2678
+ if (attrs.enctype) {
2679
+ config.headers = {
2680
+ "Content-Type": attrs["enctype"],
2681
+ };
2682
+ data = toKeyValue(collectFormData(element));
2683
+ } else {
2684
+ data = collectFormData(element);
2685
+ }
2686
+ $http[method](url, data, config).then(handler).catch(handler);
2687
+ } else {
2688
+ if (method === "get" && attrs.ngSse) {
2689
+ const sseUrl = url;
2690
+ const config = {
2691
+ withCredentials: attrs.withCredentials === "true",
2692
+ transformMessage: (data) => {
2693
+ try {
2694
+ return JSON.parse(data);
2695
+ } catch {
2696
+ return data;
2697
+ }
2698
+ },
2699
+ onOpen: () => {
2700
+ $log.info(`${attrName}: SSE connection opened to ${sseUrl}`);
2701
+ if (isDefined(attrs.loading)) attrs.$set("loading", false);
2702
+ if (isDefined(attrs.loadingClass))
2703
+ attrs.$removeClass(attrs.loadingClass);
2704
+ },
2705
+ onMessage: (data) => {
2706
+ const res = { status: 200, data };
2707
+ handler(res);
2708
+ },
2709
+ onError: (err) => {
2710
+ $log.error(`${attrName}: SSE error`, err);
2711
+ const res = { status: 500, data: err };
2712
+ handler(res);
2713
+ },
2714
+ onReconnect: (count) => {
2715
+ $log.info(`ngSse: reconnected ${count} time(s)`);
2716
+ if (attrs.onReconnect)
2717
+ $parse(attrs.onReconnect)(scope, { $count: count });
2718
+ },
2719
+ };
2720
+
2721
+ const source = $sse(sseUrl, config);
2722
+
2723
+ scope.$on("$destroy", () => {
2724
+ $log.info(`${attrName}: closing SSE connection`);
2725
+ source.close();
2726
+ });
2727
+ } else {
2728
+ $http[method](url).then(handler).catch(handler);
2729
+ }
2730
+ }
2731
+ });
2732
+
2733
+ if (intervalId) {
2734
+ scope.$on("$destroy", () => clearInterval(intervalId));
2735
+ }
2736
+
2737
+ if (eventName == "load") {
2738
+ element.dispatchEvent(new Event("load"));
2739
+ }
2740
+ },
2741
+ };
2742
+ };
2743
+ }
2744
+
2745
+ ngWorkerDirective.$inject = [$injectTokens.$parse, $injectTokens.$log];
2746
+ /**
2747
+ * Usage: <div ng-worker="workerName" data-params="{{ expression }}" data-on-result="callback($result)"></div>
2748
+ *
2749
+ * @param {ng.ParseService} $parse
2750
+ * @param {ng.LogService} $log
2751
+ * @returns {ng.Directive}
2752
+ */
2753
+ function ngWorkerDirective($parse, $log) {
2754
+ return {
2755
+ restrict: "A",
2756
+ link(scope, element, attrs) {
2757
+ const workerName = attrs.ngWorker;
2758
+ if (!workerName) {
2759
+ $log.warn("ngWorker: missing worker name");
2760
+ return;
2761
+ }
2762
+
2763
+ /** @type {string} */
2764
+ const eventName = attrs.trigger || getEventNameForElement(element);
2765
+
2766
+ let throttled = false;
2767
+ let intervalId;
2768
+
2769
+ if (isDefined(attrs.latch)) {
2770
+ attrs.$observe(
2771
+ "latch",
2772
+ callBackAfterFirst(() => element.dispatchEvent(new Event(eventName))),
2773
+ );
2774
+ }
2775
+
2776
+ if (isDefined(attrs.interval)) {
2777
+ element.dispatchEvent(new Event(eventName));
2778
+ intervalId = setInterval(
2779
+ () => element.dispatchEvent(new Event(eventName)),
2780
+ parseInt(attrs.interval) || 1000,
2781
+ );
2782
+ }
2783
+
2784
+ const worker = createWorkerConnection(workerName, {
2785
+ onMessage: (result) => {
2786
+ if (isDefined(attrs.dataOnResult)) {
2787
+ $parse(attrs.dataOnResult)(scope, { $result: result });
2788
+ } else {
2789
+ const swap = attrs.swap || "innerHTML";
2790
+ handleSwap(result, swap, element);
2791
+ }
2792
+ },
2793
+ onError: (err) => {
2794
+ $log.error(`[ng-worker:${workerName}]`, err);
2795
+ if (isDefined(attrs.dataOnError)) {
2796
+ $parse(attrs.dataOnError)(scope, { $error: err });
2797
+ } else {
2798
+ element.textContent = "Error";
2799
+ }
2800
+ },
2801
+ });
2802
+
2803
+ element.addEventListener(eventName, async () => {
2804
+ if (element["disabled"]) return;
2805
+
2806
+ if (isDefined(attrs.delay)) {
2807
+ await wait(parseInt(attrs.delay) || 0);
2808
+ }
2809
+
2810
+ if (throttled) return;
2811
+
2812
+ if (isDefined(attrs.throttle)) {
2813
+ throttled = true;
2814
+ attrs.$set("throttled", true);
2815
+ setTimeout(() => {
2816
+ attrs.$set("throttled", false);
2817
+ throttled = false;
2818
+ }, parseInt(attrs.throttle));
2819
+ }
2820
+
2821
+ let params;
2822
+ try {
2823
+ params = attrs.params ? scope.$eval(attrs.params) : undefined;
2824
+ } catch (err) {
2825
+ $log.error("ngWorker: failed to evaluate data-params", err);
2826
+ params = undefined;
2827
+ }
2828
+
2829
+ worker.post(params);
2830
+ });
2831
+
2832
+ if (intervalId) {
2833
+ scope.$on("$destroy", () => clearInterval(intervalId));
2834
+ }
2835
+
2836
+ if (eventName === "load") {
2837
+ element.dispatchEvent(new Event("load"));
2838
+ }
2839
+ },
2840
+ };
2841
+ }
2842
+
2843
+ /**
2844
+ * Swap result into DOM based on strategy
2845
+ */
2846
+ function handleSwap(result, swap, element) {
2847
+ switch (swap) {
2848
+ case "outerHTML": {
2849
+ const parent = element.parentNode;
2850
+ if (!parent) return;
2851
+ const temp = document.createElement("div");
2852
+ temp.innerHTML = result;
2853
+ parent.replaceChild(temp.firstChild, element);
2854
+ break;
2855
+ }
2856
+ case "textContent":
2857
+ element.textContent = result;
2858
+ break;
2859
+ case "beforebegin":
2860
+ element.insertAdjacentHTML("beforebegin", result);
2861
+ break;
2862
+ case "afterbegin":
2863
+ element.insertAdjacentHTML("afterbegin", result);
2864
+ break;
2865
+ case "beforeend":
2866
+ element.insertAdjacentHTML("beforeend", result);
2867
+ break;
2868
+ case "afterend":
2869
+ element.insertAdjacentHTML("afterend", result);
2870
+ break;
2871
+ case "innerHTML":
2872
+ default:
2873
+ element.innerHTML = result;
2874
+ break;
2875
+ }
2876
+ }
2877
+
2878
+ /**
2879
+ * Creates a managed Web Worker connection.
2880
+ *
2881
+ * @param {string | URL} scriptPath
2882
+ * @param {ng.WorkerConfig} [config]
2883
+ * @returns {ng.WorkerConnection}
2884
+ */
2885
+ function createWorkerConnection(scriptPath, config) {
2886
+ if (!scriptPath) throw new Error("Worker script path required");
2887
+
2888
+ const defaults = {
2889
+ autoRestart: false,
2890
+ autoTerminate: false,
2891
+ onMessage: function () {},
2892
+ onError: function () {},
2893
+ transformMessage: function (data) {
2894
+ try {
2895
+ return JSON.parse(data);
2896
+ } catch {
2897
+ return data;
2898
+ }
2899
+ },
2900
+ };
2901
+
2902
+ /** @type {ng.WorkerConfig} */
2903
+ const cfg = Object.assign({}, defaults, config);
2904
+ let worker = new Worker(scriptPath, { type: "module" });
2905
+ let terminated = false;
2906
+
2907
+ const reconnect = function () {
2908
+ if (terminated) return;
2909
+ console.info("Worker: restarting...");
2910
+ worker.terminate();
2911
+ worker = new Worker(scriptPath, { type: "module" });
2912
+ wire(worker);
2913
+ };
2914
+
2915
+ const wire = function (w) {
2916
+ w.onmessage = function (e) {
2917
+ let data = e.data;
2918
+ try {
2919
+ data = cfg.transformMessage(data);
2920
+ } catch {
2921
+ /* no-op */
2922
+ }
2923
+ cfg.onMessage(data, e); // always provide both args
2924
+ };
2925
+
2926
+ w.onerror = function (err) {
2927
+ cfg.onError(err);
2928
+ if (cfg.autoRestart) reconnect();
2929
+ };
2930
+ };
2931
+
2932
+ wire(worker);
2933
+
2934
+ return {
2935
+ post: function (data) {
2936
+ if (terminated) return console.warn("Worker already terminated");
2937
+ try {
2938
+ worker.postMessage(data);
2939
+ } catch (err) {
2940
+ console.error("Worker post failed", err);
2941
+ }
2942
+ },
2943
+
2944
+ terminate: function () {
2945
+ terminated = true;
2946
+ worker.terminate();
2947
+ },
2948
+
2949
+ restart: function () {
2950
+ if (terminated)
2951
+ return console.warn("Worker cannot restart after terminate");
2952
+ reconnect();
2953
+ },
2954
+
2955
+ config: cfg,
2956
+ };
2957
+ }
2958
+
2209
2959
  /** @private */
2210
2960
  const INJECTOR_LITERAL = "$injector";
2211
2961
  /** @private */
@@ -2231,7 +2981,7 @@
2231
2981
  /**
2232
2982
  * @param {string} name - Name of the module
2233
2983
  * @param {Array<string>} requires - List of modules which the injector will load before the current module
2234
- * @param {import("../../interface.ts").Injectable<any>} [configFn]
2984
+ * @param {ng.Injectable<any>} [configFn]
2235
2985
  */
2236
2986
  constructor(name, requires, configFn) {
2237
2987
  assert(isString(name), "name required");
@@ -2257,7 +3007,7 @@
2257
3007
  /** @type {!Array<Array<*>>} */
2258
3008
  this.configBlocks = [];
2259
3009
 
2260
- /** @type {!Array.<import("../../interface.ts").Injectable<any>>} */
3010
+ /** @type {!Array.<ng.Injectable<any>>} */
2261
3011
  this.runBlocks = [];
2262
3012
 
2263
3013
  if (configFn) {
@@ -2265,6 +3015,8 @@
2265
3015
  }
2266
3016
 
2267
3017
  this.services = [];
3018
+
3019
+ this.wasmModules = [];
2268
3020
  }
2269
3021
 
2270
3022
  /**
@@ -2289,7 +3041,7 @@
2289
3041
 
2290
3042
  /**
2291
3043
  *
2292
- * @param {import("../../interface.ts").Injectable<any>} configFn
3044
+ * @param {ng.Injectable<any>} configFn
2293
3045
  * @returns {NgModule}
2294
3046
  */
2295
3047
  config(configFn) {
@@ -2298,7 +3050,7 @@
2298
3050
  }
2299
3051
 
2300
3052
  /**
2301
- * @param {import("../../interface.ts").Injectable<any>} block
3053
+ * @param {ng.Injectable<any>} block
2302
3054
  * @returns {NgModule}
2303
3055
  */
2304
3056
  run(block) {
@@ -2308,7 +3060,7 @@
2308
3060
 
2309
3061
  /**
2310
3062
  * @param {string} name
2311
- * @param {import("../../interface.ts").Component} options
3063
+ * @param {ng.Component} options
2312
3064
  * @returns {NgModule}
2313
3065
  */
2314
3066
  component(name, options) {
@@ -2321,7 +3073,7 @@
2321
3073
 
2322
3074
  /**
2323
3075
  * @param {string} name
2324
- * @param {import("../../interface.ts").Injectable<any>} providerFunction
3076
+ * @param {ng.Injectable<any>} providerFunction
2325
3077
  * @returns {NgModule}
2326
3078
  */
2327
3079
  factory(name, providerFunction) {
@@ -2334,7 +3086,7 @@
2334
3086
 
2335
3087
  /**
2336
3088
  * @param {string} name
2337
- * @param {import("../../interface.ts").Injectable<any>} serviceFunction
3089
+ * @param {ng.Injectable<any>} serviceFunction
2338
3090
  * @returns {NgModule}
2339
3091
  */
2340
3092
  service(name, serviceFunction) {
@@ -2348,7 +3100,7 @@
2348
3100
 
2349
3101
  /**
2350
3102
  * @param {string} name
2351
- * @param {import("../../interface.ts").Injectable<any>} providerType
3103
+ * @param {ng.Injectable<any>} providerType
2352
3104
  * @returns {NgModule}
2353
3105
  */
2354
3106
  provider(name, providerType) {
@@ -2361,7 +3113,7 @@
2361
3113
 
2362
3114
  /**
2363
3115
  * @param {string} name
2364
- * @param {import("../../interface.ts").Injectable<any>} decorFn
3116
+ * @param {ng.Injectable<any>} decorFn
2365
3117
  * @returns {NgModule}
2366
3118
  */
2367
3119
  decorator(name, decorFn) {
@@ -2374,7 +3126,7 @@
2374
3126
 
2375
3127
  /**
2376
3128
  * @param {string} name
2377
- * @param {import("../../interface.ts").Injectable<any>} directiveFactory
3129
+ * @param {ng.Injectable<any>} directiveFactory
2378
3130
  * @returns {NgModule}
2379
3131
  */
2380
3132
  directive(name, directiveFactory) {
@@ -2391,7 +3143,7 @@
2391
3143
 
2392
3144
  /**
2393
3145
  * @param {string} name
2394
- * @param {import("../../interface.ts").Injectable<any>} animationFactory
3146
+ * @param {ng.Injectable<any>} animationFactory
2395
3147
  * @returns {NgModule}
2396
3148
  */
2397
3149
  animation(name, animationFactory) {
@@ -2408,7 +3160,7 @@
2408
3160
 
2409
3161
  /**
2410
3162
  * @param {string} name
2411
- * @param {import("../../interface.ts").Injectable<any>} filterFn
3163
+ * @param {ng.Injectable<any>} filterFn
2412
3164
  * @return {NgModule}
2413
3165
  */
2414
3166
  filter(name, filterFn) {
@@ -2421,7 +3173,7 @@
2421
3173
 
2422
3174
  /**
2423
3175
  * @param {string} name
2424
- * @param {import("../../interface.ts").Injectable<any>} ctlFn
3176
+ * @param {ng.Injectable<any>} ctlFn
2425
3177
  * @returns {NgModule}
2426
3178
  */
2427
3179
  controller(name, ctlFn) {
@@ -2431,12 +3183,192 @@
2431
3183
  this.invokeQueue.push([CONTROLLER_LITERAL, "register", [name, ctlFn]]);
2432
3184
  return this;
2433
3185
  }
3186
+
3187
+ /**
3188
+ * Register a named WebAssembly module that will be instantiated via $provide.
3189
+ *
3190
+ * @param {string} name - The injectable name used to access the instantiated WebAssembly module.
3191
+ *
3192
+ * @param {string} src - URL of the `.wasm` file to fetch and instantiate.
3193
+ *
3194
+ * @param {Object<string, any>} [imports] WebAssembly import object, passed to `WebAssembly.instantiate` or `WebAssembly.instantiateStreaming`.
3195
+ *
3196
+ * @param {Object<string, any>} [opts] - Configuration object.
3197
+ *
3198
+ * Supported keys:
3199
+ * - **raw**: `boolean`
3200
+ * - `false` (default): the injectable resolves to `instance.exports`
3201
+ * (ideal for plain WASM modules).
3202
+ * - `true`: the injectable resolves to the full instantiation result:
3203
+ * `{ instance, exports, module }`
3204
+ * (required for runtimes such as Go, Emscripten, wasm-bindgen, etc).
3205
+ *
3206
+ * @returns {NgModule}
3207
+ */
3208
+ wasm(name, src, imports = {}, opts = {}) {
3209
+ const raw = !!opts.raw;
3210
+
3211
+ this.invokeQueue.push([
3212
+ $injectTokens.$provide,
3213
+ "provider",
3214
+ [
3215
+ name,
3216
+ function () {
3217
+ this.$get = () => {
3218
+ return instantiateWasm(src, imports).then((result) =>
3219
+ raw ? result : result.exports,
3220
+ );
3221
+ };
3222
+ },
3223
+ ],
3224
+ ]);
3225
+
3226
+ return this;
3227
+ }
3228
+
3229
+ /**
3230
+ * Register a named worker that will be instantiated via $provide.
3231
+ *
3232
+ * @param {string} name
3233
+ * @param {string | URL} scriptPath
3234
+ * @param {ng.WorkerConfig} [config]
3235
+ * @returns {NgModule}
3236
+ */
3237
+ worker(name, scriptPath, config = {}) {
3238
+ this.invokeQueue.push([
3239
+ $injectTokens.$provide,
3240
+ "provider",
3241
+ [
3242
+ name,
3243
+ function () {
3244
+ this.$get = function () {
3245
+ return createWorkerConnection(scriptPath, config);
3246
+ };
3247
+ },
3248
+ ],
3249
+ ]);
3250
+ return this;
3251
+ }
3252
+
3253
+ /**
3254
+ * @param {string} name
3255
+ * @param {Function} ctor
3256
+ * @returns {NgModule}
3257
+ */
3258
+ session(name, ctor) {
3259
+ if (ctor && isFunction(ctor)) {
3260
+ ctor["$$moduleName"] = name;
3261
+ }
3262
+ this.invokeQueue.push([$injectTokens.$provide, "session", [name, ctor]]);
3263
+ return this;
3264
+ }
3265
+
3266
+ /**
3267
+ * @param {string} name
3268
+ * @param {Function} ctor
3269
+ * @returns {NgModule}
3270
+ */
3271
+ local(name, ctor) {
3272
+ if (ctor && isFunction(ctor)) {
3273
+ ctor["$$moduleName"] = name;
3274
+ }
3275
+ this.invokeQueue.push([$injectTokens.$provide, "local", [name, ctor]]);
3276
+ return this;
3277
+ }
3278
+
3279
+ /**
3280
+ * @param {string} name
3281
+ * @param {Function} ctor
3282
+ * @param {ng.StorageBackend} backendOrConfig
3283
+ * @returns {NgModule}
3284
+ */
3285
+ store(name, ctor, backendOrConfig) {
3286
+ if (ctor && isFunction(ctor)) {
3287
+ ctor["$$moduleName"] = name;
3288
+ }
3289
+ this.invokeQueue.push([
3290
+ $injectTokens.$provide,
3291
+ "store",
3292
+ [name, ctor, backendOrConfig],
3293
+ ]);
3294
+ return this;
3295
+ }
3296
+ }
3297
+
3298
+ /**
3299
+ * Shared utility functions
3300
+ */
3301
+
3302
+ const $injectorMinErr$3 = minErr(INJECTOR_LITERAL);
3303
+ const ARROW_ARG = /^([^(]+?)=>/;
3304
+ const FN_ARGS = /^[^(]*\(\s*([^)]*)\)/m;
3305
+ const FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
3306
+ const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;
3307
+
3308
+ /**
3309
+ * @param {Function} fn
3310
+ * @returns {string}
3311
+ */
3312
+ function stringifyFn(fn) {
3313
+ return Function.prototype.toString.call(fn);
3314
+ }
3315
+
3316
+ /**
3317
+ * @param {Function} fn
3318
+ * @returns {Array<any>}
3319
+ */
3320
+ function extractArgs(fn) {
3321
+ const fnText = stringifyFn(fn).replace(STRIP_COMMENTS, "");
3322
+ return fnText.match(ARROW_ARG) || fnText.match(FN_ARGS);
3323
+ }
3324
+
3325
+ /**
3326
+ * @param {Function} func
3327
+ * @returns {boolean}
3328
+ */
3329
+ function isClass(func) {
3330
+ return /^class\b/.test(stringifyFn(func));
3331
+ }
3332
+
3333
+ /**
3334
+ * @param {any} fn
3335
+ * @param {boolean} [strictDi]
3336
+ * @param {string} [name]
3337
+ * @returns {Array<string>}
3338
+ */
3339
+ function annotate(fn, strictDi, name) {
3340
+ let $inject, argDecl, last;
3341
+
3342
+ if (typeof fn === "function") {
3343
+ if (!($inject = fn.$inject)) {
3344
+ $inject = [];
3345
+ if (fn.length) {
3346
+ if (strictDi) {
3347
+ throw $injectorMinErr$3(
3348
+ "strictdi",
3349
+ "{0} is not using explicit annotation and cannot be invoked in strict mode",
3350
+ name,
3351
+ );
3352
+ }
3353
+ argDecl = extractArgs(fn);
3354
+ argDecl[1].split(/,/).forEach(function (arg) {
3355
+ arg.replace(FN_ARG, function (_all, _underscore, name) {
3356
+ $inject.push(name);
3357
+ });
3358
+ });
3359
+ }
3360
+ fn.$inject = $inject;
3361
+ }
3362
+ } else if (Array.isArray(fn)) {
3363
+ last = /** @type {Array} */ (fn).length - 1;
3364
+ assertArgFn(fn[last], "fn");
3365
+ $inject = /** @type {Array} */ (fn).slice(0, last);
3366
+ } else {
3367
+ assertArgFn(fn, "fn", true);
3368
+ }
3369
+ return $inject;
2434
3370
  }
2435
3371
 
2436
- const ARROW_ARG$1 = /^([^(]+?)=>/;
2437
- const FN_ARGS$1 = /^[^(]*\(\s*([^)]*)\)/m;
2438
- const FN_ARG$1 = /^\s*(_?)(\S+?)\1\s*$/;
2439
- const STRIP_COMMENTS$1 = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;
2440
3372
  const $injectorMinErr$2 = minErr(INJECTOR_LITERAL);
2441
3373
 
2442
3374
  const providerSuffix$1 = "Provider";
@@ -2455,7 +3387,7 @@
2455
3387
  this.strictDi = strictDi;
2456
3388
  /** @type {string[]} */
2457
3389
  this.path = [];
2458
- /** @type {Object.<string, import("./ng-module.js").NgModule>} */
3390
+ /** @type {Object.<string, ng.NgModule>} */
2459
3391
  this.modules = {};
2460
3392
  }
2461
3393
 
@@ -2499,7 +3431,7 @@
2499
3431
  */
2500
3432
  injectionArgs(fn, locals, serviceName) {
2501
3433
  const args = [];
2502
- const $inject = annotate$1(fn, this.strictDi, serviceName);
3434
+ const $inject = annotate(fn, this.strictDi, serviceName);
2503
3435
 
2504
3436
  for (let i = 0, { length } = $inject; i < length; i++) {
2505
3437
  const key = $inject[i];
@@ -2622,7 +3554,7 @@
2622
3554
 
2623
3555
  /** @type {ProviderInjector} */
2624
3556
  this.providerInjector = providerInjector;
2625
- /** @type {Object.<string, import("./ng-module.js").NgModule>} */
3557
+ /** @type {Object.<string, ng.NgModule>} */
2626
3558
  this.modules = providerInjector.modules;
2627
3559
  }
2628
3560
 
@@ -2648,80 +3580,56 @@
2648
3580
  const hasCache = hasOwn(this.cache, name);
2649
3581
  return hasProvider || hasCache;
2650
3582
  }
2651
- }
2652
-
2653
- // Helpers
2654
-
2655
- /**
2656
- * @param {Function} fn
2657
- * @returns {string}
2658
- */
2659
- function stringifyFn$1(fn) {
2660
- return Function.prototype.toString.call(fn);
2661
- }
2662
3583
 
2663
- /**
2664
- * @param {Function} fn
2665
- * @returns {Array<any>}
2666
- */
2667
- function extractArgs$1(fn) {
2668
- const fnText = stringifyFn$1(fn).replace(STRIP_COMMENTS$1, "");
2669
- return fnText.match(ARROW_ARG$1) || fnText.match(FN_ARGS$1);
2670
- }
2671
-
2672
- /**
2673
- * @param {Function} func
2674
- * @returns {boolean}
2675
- */
2676
- function isClass(func) {
2677
- return /^class\b/.test(stringifyFn$1(func));
3584
+ loadNewModules() {}
2678
3585
  }
2679
3586
 
2680
3587
  /**
3588
+ * Creates a proxy that automatically persists an object's state
3589
+ * into a storage backend whenever a property is set.
2681
3590
  *
2682
- * @param {any} fn
2683
- * @param {boolean} strictDi
2684
- * @param {string} name
2685
- * @returns {Array<string>}
3591
+ * @param {object} target - The object to wrap
3592
+ * @param {string} key - The storage key
3593
+ * @param {object} storage - Any storage-like object with getItem/setItem/removeItem
3594
+ * @param {{serialize?: function, deserialize?: function}} [options] - Optional custom (de)serialization
3595
+ * @returns {Proxy}
2686
3596
  */
2687
- function annotate$1(fn, strictDi, name) {
2688
- let $inject, argDecl, last;
3597
+ function createPersistentProxy(target, key, storage, options = {}) {
3598
+ const serialize = options.serialize || JSON.stringify;
3599
+ const deserialize = options.deserialize || JSON.parse;
2689
3600
 
2690
- if (typeof fn === "function") {
2691
- if (!($inject = fn.$inject)) {
2692
- $inject = [];
2693
- if (fn.length) {
2694
- if (strictDi) {
2695
- throw $injectorMinErr$2(
2696
- "strictdi",
2697
- "{0} is not using explicit annotation and cannot be invoked in strict mode",
2698
- name,
2699
- );
2700
- }
2701
- argDecl = extractArgs$1(fn);
2702
- argDecl[1].split(/,/).forEach(function (arg) {
2703
- arg.replace(FN_ARG$1, function (_all, _underscore, name) {
2704
- $inject.push(name);
2705
- });
2706
- });
2707
- }
2708
- fn.$inject = $inject;
3601
+ // Restore saved state
3602
+ const saved = storage.getItem(key);
3603
+ if (saved) {
3604
+ try {
3605
+ Object.assign(target, deserialize(saved));
3606
+ } catch {
3607
+ console.warn(`Failed to deserialize persisted data for key "${key}"`);
2709
3608
  }
2710
- } else if (Array.isArray(fn)) {
2711
- last = /** @type {Array} */ (fn).length - 1;
2712
- assertArgFn(fn[last], "fn");
2713
- $inject = /** @type {Array} */ (fn).slice(0, last);
2714
- } else {
2715
- assertArgFn(fn, "fn", true);
2716
3609
  }
2717
- return $inject;
3610
+
3611
+ return new Proxy(target, {
3612
+ set(obj, prop, value) {
3613
+ obj[prop] = value;
3614
+ try {
3615
+ storage.setItem(key, serialize(obj));
3616
+ } catch {
3617
+ console.warn(`Failed to persist data for key "${key}"`);
3618
+ }
3619
+ return true;
3620
+ },
3621
+ deleteProperty(obj, prop) {
3622
+ const deleted = delete obj[prop];
3623
+ try {
3624
+ storage.setItem(key, serialize(obj));
3625
+ } catch {
3626
+ console.warn(`Failed to persist data for key "${key}"`);
3627
+ }
3628
+ return deleted;
3629
+ },
3630
+ });
2718
3631
  }
2719
3632
 
2720
- const ARROW_ARG = /^([^(]+?)=>/;
2721
- const FN_ARGS = /^[^(]*\(\s*([^)]*)\)/m;
2722
- const FN_ARG_SPLIT = /,/;
2723
- const FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
2724
- const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;
2725
3633
  const $injectorMinErr$1 = minErr(INJECTOR_LITERAL);
2726
3634
  const providerSuffix = "Provider";
2727
3635
 
@@ -2744,6 +3652,9 @@
2744
3652
  service: supportObject(service),
2745
3653
  value: supportObject(value),
2746
3654
  constant: supportObject(constant),
3655
+ session: supportObject(session),
3656
+ local: supportObject(local),
3657
+ store: supportObject(store),
2747
3658
  decorator,
2748
3659
  },
2749
3660
  };
@@ -2877,13 +3788,78 @@
2877
3788
  };
2878
3789
  }
2879
3790
 
3791
+ /**
3792
+ * Registers a session-persistent service
3793
+ */
3794
+ function session(name, ctor) {
3795
+ return provider(name, {
3796
+ $get: ($injector) => {
3797
+ const instance = $injector.instantiate(ctor);
3798
+ return createPersistentProxy(instance, name, sessionStorage);
3799
+ },
3800
+ });
3801
+ }
3802
+
3803
+ /**
3804
+ * Registers a localStorage-persistent service
3805
+ */
3806
+ function local(name, ctor) {
3807
+ return provider(name, {
3808
+ $get: ($injector) => {
3809
+ const instance = $injector.instantiate(ctor);
3810
+ return createPersistentProxy(instance, name, localStorage);
3811
+ },
3812
+ });
3813
+ }
3814
+
3815
+ /**
3816
+ * Registers a service persisted in a custom storage
3817
+ *
3818
+ * @param {string} name - Service name
3819
+ * @param {Function} ctor - Constructor for the service
3820
+ * @param {Storage|Object} backendOrConfig - Either a Storage-like object (getItem/setItem) or a config object
3821
+ * with { backend, serialize, deserialize }
3822
+ */
3823
+ function store(name, ctor, backendOrConfig) {
3824
+ return provider(name, {
3825
+ $get: ($injector) => {
3826
+ const instance = $injector.instantiate(ctor);
3827
+
3828
+ let backend;
3829
+ let serialize = JSON.stringify;
3830
+ let deserialize = JSON.parse;
3831
+
3832
+ if (backendOrConfig) {
3833
+ if (typeof backendOrConfig.getItem === "function") {
3834
+ // raw Storage object
3835
+ backend = backendOrConfig;
3836
+ } else if (isObject(backendOrConfig)) {
3837
+ backend = backendOrConfig.backend || localStorage;
3838
+ if (backendOrConfig.serialize)
3839
+ serialize = backendOrConfig.serialize;
3840
+ if (backendOrConfig.deserialize)
3841
+ deserialize = backendOrConfig.deserialize;
3842
+ }
3843
+ } else {
3844
+ // fallback default
3845
+ backend = localStorage;
3846
+ }
3847
+
3848
+ return createPersistentProxy(instance, name, backend, {
3849
+ serialize,
3850
+ deserialize,
3851
+ });
3852
+ },
3853
+ });
3854
+ }
3855
+
2880
3856
  /**
2881
3857
  *
2882
3858
  * @param {Array<String|Function>} modulesToLoad
2883
3859
  * @returns
2884
3860
  */
2885
3861
  function loadModules(modulesToLoad) {
2886
- assertArg$1(
3862
+ assertArg(
2887
3863
  isUndefined(modulesToLoad) || Array.isArray(modulesToLoad),
2888
3864
  "modulesToLoad",
2889
3865
  "not an array",
@@ -2896,8 +3872,10 @@
2896
3872
 
2897
3873
  try {
2898
3874
  if (isString(module)) {
2899
- /** @type {import('./ng-module.js').NgModule} */
2900
- const moduleFn = window["angular"].module(module);
3875
+ /** @type {ng.NgModule} */
3876
+ const moduleFn = window["angular"].module(
3877
+ /** @type {string} */ (module),
3878
+ );
2901
3879
  instanceInjector.modules[/** @type {string } */ (module)] = moduleFn;
2902
3880
  runBlocks = runBlocks
2903
3881
  .concat(loadModules(moduleFn.requires))
@@ -2941,64 +3919,6 @@
2941
3919
  }
2942
3920
  }
2943
3921
 
2944
- // Helpers
2945
-
2946
- /**
2947
- * @param {String} fn
2948
- * @returns {String}
2949
- */
2950
- function stringifyFn(fn) {
2951
- return Function.prototype.toString.call(fn);
2952
- }
2953
-
2954
- /**
2955
- * @param {String} fn
2956
- * @returns {Array<any>}
2957
- */
2958
- function extractArgs(fn) {
2959
- const fnText = stringifyFn(fn).replace(STRIP_COMMENTS, "");
2960
- return fnText.match(ARROW_ARG) || fnText.match(FN_ARGS);
2961
- }
2962
-
2963
- /**
2964
- * @param {any} fn
2965
- * @param {boolean} [strictDi]
2966
- * @param {String} [name]
2967
- * @returns {Array<string>}
2968
- */
2969
- function annotate(fn, strictDi, name) {
2970
- let $inject, argDecl, last;
2971
-
2972
- if (typeof fn === "function") {
2973
- if (!($inject = fn.$inject)) {
2974
- $inject = [];
2975
- if (fn.length) {
2976
- if (strictDi) {
2977
- throw $injectorMinErr$1(
2978
- "strictdi",
2979
- "{0} is not using explicit annotation and cannot be invoked in strict mode",
2980
- name,
2981
- );
2982
- }
2983
- argDecl = extractArgs(/** @type {String} */ (fn));
2984
- argDecl[1].split(FN_ARG_SPLIT).forEach(function (arg) {
2985
- arg.replace(FN_ARG, function (all, underscore, name) {
2986
- $inject.push(name);
2987
- });
2988
- });
2989
- }
2990
- fn.$inject = $inject;
2991
- }
2992
- } else if (Array.isArray(fn)) {
2993
- last = /** @type {Array} */ (fn).length - 1;
2994
- assertArgFn(fn[last], "fn");
2995
- $inject = /** @type {Array} */ (fn).slice(0, last);
2996
- } else {
2997
- assertArgFn(fn, "fn", true);
2998
- }
2999
- return $inject;
3000
- }
3001
-
3002
3922
  function supportObject(delegate) {
3003
3923
  return function (key, value) {
3004
3924
  if (isObject(key)) {
@@ -3021,7 +3941,7 @@
3021
3941
  * @throws {Error} If the argument is invalid or cannot be wrapped properly.
3022
3942
  */
3023
3943
  constructor(element) {
3024
- assertArg$1(element, "element");
3944
+ assertArg(element, "element");
3025
3945
  this.initial = null;
3026
3946
 
3027
3947
  /** @private @type {Node | ChildNode | null} */
@@ -3077,8 +3997,8 @@
3077
3997
  }
3078
3998
 
3079
3999
  // Handle array of elements
3080
- else if (element instanceof Array) {
3081
- if (element.length == 1) {
4000
+ else if (Array.isArray(element)) {
4001
+ if (element.length === 1) {
3082
4002
  this.initial = element[0].cloneNode(true);
3083
4003
  this.node = element[0];
3084
4004
  } else {
@@ -3092,13 +4012,13 @@
3092
4012
 
3093
4013
  /** @returns {Element} */
3094
4014
  get element() {
3095
- assertArg$1(this._element, "element");
4015
+ assertArg(this._element, "element");
3096
4016
  return this._element;
3097
4017
  }
3098
4018
 
3099
4019
  /** @param {Element} el */
3100
4020
  set element(el) {
3101
- assertArg$1(el instanceof Element, "element");
4021
+ assertArg(el instanceof Element, "element");
3102
4022
  this._element = el;
3103
4023
  this._nodes = undefined;
3104
4024
  this.isList = false;
@@ -3106,13 +4026,13 @@
3106
4026
 
3107
4027
  /** @returns {Node | ChildNode} */
3108
4028
  get node() {
3109
- assertArg$1(this._node || this._element, "node");
4029
+ assertArg(this._node || this._element, "node");
3110
4030
  return this._node || this._element;
3111
4031
  }
3112
4032
 
3113
4033
  /** @param {Node | ChildNode} node */
3114
4034
  set node(node) {
3115
- assertArg$1(node instanceof Node, "node");
4035
+ assertArg(node instanceof Node, "node");
3116
4036
  this._node = node;
3117
4037
  if (node.nodeType === Node.ELEMENT_NODE) {
3118
4038
  this._element = /** @type {Element} */ (node);
@@ -3123,7 +4043,7 @@
3123
4043
 
3124
4044
  /** @param {Array<Node>} nodes */
3125
4045
  set nodes(nodes) {
3126
- assertArg$1(
4046
+ assertArg(
3127
4047
  Array.isArray(nodes) && nodes.every((n) => n instanceof Node),
3128
4048
  "nodes",
3129
4049
  );
@@ -3133,25 +4053,18 @@
3133
4053
 
3134
4054
  /** @returns {Array<Node>} */
3135
4055
  get nodes() {
3136
- assertArg$1(this._nodes, "nodes");
4056
+ assertArg(this._nodes, "nodes");
3137
4057
  return this._nodes;
3138
4058
  }
3139
4059
 
3140
4060
  /** @returns {NodeList|Node[]} */
3141
4061
  get nodelist() {
3142
- assertArg$1(this.isList, "nodes");
3143
- if (this._nodes.length === 0) {
3144
- return this._nodes;
3145
- }
3146
- if (this._nodes[0].parentElement) {
4062
+ if (this._nodes.length === 0) return [];
4063
+ if (this._nodes[0].parentElement)
3147
4064
  return this._nodes[0].parentElement.childNodes;
3148
- } else {
3149
- const fragment = document.createDocumentFragment();
3150
- this._nodes.forEach((el) => {
3151
- fragment.appendChild(el);
3152
- });
3153
- return fragment.childNodes;
3154
- }
4065
+ const fragment = document.createDocumentFragment();
4066
+ this._nodes.forEach((el) => fragment.appendChild(el));
4067
+ return fragment.childNodes;
3155
4068
  }
3156
4069
 
3157
4070
  /** @returns {Element | Node | ChildNode | NodeList | Node[]} */
@@ -3209,8 +4122,8 @@
3209
4122
  * @param {Element | Node | ChildNode} node
3210
4123
  */
3211
4124
  setIndex(index, node) {
3212
- assertArg$1(index !== null, "index");
3213
- assertArg$1(node, "node");
4125
+ assertArg(index !== null, "index");
4126
+ assertArg(node, "node");
3214
4127
  if (this.isList) {
3215
4128
  this._nodes[index] = node;
3216
4129
  } else {
@@ -3296,7 +4209,7 @@
3296
4209
  "$injector",
3297
4210
 
3298
4211
  /**
3299
- * @param {import("../../core/di/internal-injector.js").InjectorService} $injector
4212
+ * @param {ng.InjectorService} $injector
3300
4213
  * @returns {import("./interface.ts").ControllerService} A service function that creates controllers.
3301
4214
  */
3302
4215
  ($injector) => {
@@ -3349,6 +4262,10 @@
3349
4262
  );
3350
4263
  }
3351
4264
 
4265
+ if (instance?.constructor?.$scopename) {
4266
+ locals.$scope.$scopename = instance.constructor.$scopename;
4267
+ }
4268
+
3352
4269
  return function () {
3353
4270
  const result = $injector.invoke(
3354
4271
  expression,
@@ -3611,7 +4528,7 @@
3611
4528
  * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict
3612
4529
  * Contextual Escaping (SCE)} services to AngularTS.
3613
4530
  *
3614
- * For an overview of this service and the functionnality it provides in AngularTS, see the main
4531
+ * For an overview of this service and the functionality it provides in AngularTS, see the main
3615
4532
  * page for {@link ng.$sce SCE}. The current page is targeted for developers who need to alter how
3616
4533
  * SCE works in their application, which shouldn't be needed in most cases.
3617
4534
  *
@@ -3638,85 +4555,6 @@
3638
4555
  * ng.$sceDelegateProvider#bannedResourceUrlList $sceDelegateProvider.bannedResourceUrlList}
3639
4556
  */
3640
4557
 
3641
- /**
3642
- *
3643
- * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate
3644
- * $sceDelegate service}, used as a delegate for {@link ng.$sce Strict Contextual Escaping (SCE)}.
3645
- *
3646
- * The `$sceDelegateProvider` allows one to get/set the `trustedResourceUrlList` and
3647
- * `bannedResourceUrlList` used to ensure that the URLs used for sourcing AngularTS templates and
3648
- * other script-running URLs are safe (all places that use the `$sce.RESOURCE_URL` context). See
3649
- * {@link ng.$sceDelegateProvider#trustedResourceUrlList
3650
- * $sceDelegateProvider.trustedResourceUrlList} and
3651
- * {@link ng.$sceDelegateProvider#bannedResourceUrlList $sceDelegateProvider.bannedResourceUrlList},
3652
- *
3653
- * For the general details about this service in AngularTS, read the main page for {@link ng.$sce
3654
- * Strict Contextual Escaping (SCE)}.
3655
- *
3656
- * **Example**: Consider the following case. <a name="example"></a>
3657
- *
3658
- * - your app is hosted at url `http://myapp.example.com/`
3659
- * - but some of your templates are hosted on other domains you control such as
3660
- * `http://srv01.assets.example.com/`, `http://srv02.assets.example.com/`, etc.
3661
- * - and you have an open redirect at `http://myapp.example.com/clickThru?...`.
3662
- *
3663
- * Here is what a secure configuration for this scenario might look like:
3664
- *
3665
- * ```
3666
- * angular.module('myApp', []).config(function($sceDelegateProvider) {
3667
- * $sceDelegateProvider.trustedResourceUrlList([
3668
- * // Allow same origin resource loads.
3669
- * 'self',
3670
- * // Allow loading from our assets domain. Notice the difference between * and **.
3671
- * 'http://srv*.assets.example.com/**'
3672
- * ]);
3673
- *
3674
- * // The banned resource URL list overrides the trusted resource URL list so the open redirect
3675
- * // here is blocked.
3676
- * $sceDelegateProvider.bannedResourceUrlList([
3677
- * 'http://myapp.example.com/clickThru**'
3678
- * ]);
3679
- * });
3680
- * ```
3681
- * Note that an empty trusted resource URL list will block every resource URL from being loaded, and will require
3682
- * you to manually mark each one as trusted with `$sce.trustAsResourceUrl`. However, templates
3683
- * requested by {@link ng.$templateRequest $templateRequest} that are present in
3684
- * {@link ng.$templateCache $templateCache} will not go through this check. If you have a mechanism
3685
- * to populate your templates in that cache at config time, then it is a good idea to remove 'self'
3686
- * from the trusted resource URL lsit. This helps to mitigate the security impact of certain types
3687
- * of issues, like for instance attacker-controlled `ng-includes`.
3688
- */
3689
-
3690
- /**
3691
- * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict
3692
- * Contextual Escaping (SCE)} services to AngularTS.
3693
- *
3694
- * For an overview of this service and the functionnality it provides in AngularTS, see the main
3695
- * page for {@link ng.$sce SCE}. The current page is targeted for developers who need to alter how
3696
- * SCE works in their application, which shouldn't be needed in most cases.
3697
- *
3698
- * <div class="alert alert-danger">
3699
- * AngularTS strongly relies on contextual escaping for the security of bindings: disabling or
3700
- * modifying this might cause cross site scripting (XSS) vulnerabilities. For libraries owners,
3701
- * changes to this service will also influence users, so be extra careful and document your changes.
3702
- * </div>
3703
- *
3704
- * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of
3705
- * the `$sce` service to customize the way Strict Contextual Escaping works in AngularTS. This is
3706
- * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to
3707
- * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things
3708
- * work because `$sce` delegates to `$sceDelegate` for these operations.
3709
- *
3710
- * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service.
3711
- *
3712
- * The default instance of `$sceDelegate` should work out of the box with little pain. While you
3713
- * can override it completely to change the behavior of `$sce`, the common case would
3714
- * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting
3715
- * your own trusted and banned resource lists for trusting URLs used for loading AngularTS resources
3716
- * such as templates. Refer {@link ng.$sceDelegateProvider#trustedResourceUrlList
3717
- * $sceDelegateProvider.trustedResourceUrlList} and {@link
3718
- * ng.$sceDelegateProvider#bannedResourceUrlList $sceDelegateProvider.bannedResourceUrlList}
3719
- */
3720
4558
  /**
3721
4559
  *
3722
4560
  * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate
@@ -3773,7 +4611,7 @@
3773
4611
 
3774
4612
  /**
3775
4613
  *
3776
- * @param {Array=} trustedResourceUrlList When provided, replaces the trustedResourceUrlList with
4614
+ * @param {Array=} value When provided, replaces the trustedResourceUrlList with
3777
4615
  * the value provided. This must be an array or null. A snapshot of this array is used so
3778
4616
  * further changes to the array are ignored.
3779
4617
  * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
@@ -3835,7 +4673,7 @@
3835
4673
  /**
3836
4674
  *
3837
4675
  * @param {ng.InjectorService} $injector
3838
- * @param {*} $$sanitizeUri
4676
+ * @param {import("../../core/sanitize/interface.ts").SanitizerFn} $$sanitizeUri
3839
4677
  * @param {ng.ExceptionHandlerService} $exceptionHandler
3840
4678
  * @returns
3841
4679
  */
@@ -4357,7 +5195,7 @@
4357
5195
  const { trustAs } = sce;
4358
5196
 
4359
5197
  Object.entries(SCE_CONTEXTS).forEach(([name, enumValue]) => {
4360
- const lName = lowercase(name);
5198
+ const lName = name.toLowerCase();
4361
5199
  sce[snakeToCamel(`parse_as_${lName}`)] = function (expr) {
4362
5200
  return parse(enumValue, expr);
4363
5201
  };
@@ -4491,8 +5329,8 @@
4491
5329
  static $nonscope = true;
4492
5330
 
4493
5331
  /**
4494
- * @param {ng.Scope} $rootScope
4495
- * @param {*} $animate
5332
+ * @param {ng.RootScopeService} $rootScope
5333
+ * @param {ng.AnimateService} $animate
4496
5334
  * @param {ng.ExceptionHandlerService} $exceptionHandler
4497
5335
  * @param {*} $sce
4498
5336
  * @param {import("../../shared/noderef.js").NodeRef} [nodeRef]
@@ -4550,7 +5388,10 @@
4550
5388
  $addClass(classVal) {
4551
5389
  if (classVal && classVal.length > 0) {
4552
5390
  if (hasAnimate(this.$$element)) {
4553
- this.$animate.addClass(this.$$element, classVal);
5391
+ this.$animate.addClass(
5392
+ /** @type {Element} */ (this.$$element),
5393
+ classVal,
5394
+ );
4554
5395
  } else {
4555
5396
  this.$nodeRef.element.classList.add(classVal);
4556
5397
  }
@@ -4566,7 +5407,10 @@
4566
5407
  $removeClass(classVal) {
4567
5408
  if (classVal && classVal.length > 0) {
4568
5409
  if (hasAnimate(this.$$element)) {
4569
- this.$animate.removeClass(this.$$element, classVal);
5410
+ this.$animate.removeClass(
5411
+ /** @type {Element} */ (this.$$element),
5412
+ classVal,
5413
+ );
4570
5414
  } else {
4571
5415
  this.$nodeRef.element.classList.remove(classVal);
4572
5416
  }
@@ -4584,7 +5428,7 @@
4584
5428
  const toAdd = tokenDifference(newClasses, oldClasses);
4585
5429
  if (toAdd && toAdd.length) {
4586
5430
  if (hasAnimate(this.$$element)) {
4587
- this.$animate.addClass(this.$$element, toAdd);
5431
+ this.$animate.addClass(/** @type {Element }*/ (this.$$element), toAdd);
4588
5432
  } else {
4589
5433
  this.$nodeRef.element.classList.add(...toAdd.trim().split(/\s+/));
4590
5434
  }
@@ -4592,7 +5436,10 @@
4592
5436
  const toRemove = tokenDifference(oldClasses, newClasses);
4593
5437
  if (toRemove && toRemove.length) {
4594
5438
  if (hasAnimate(this.$$element)) {
4595
- this.$animate.removeClass(this.$$element, toRemove);
5439
+ this.$animate.removeClass(
5440
+ /** @type {Element }*/ (this.$$element),
5441
+ toRemove,
5442
+ );
4596
5443
  } else {
4597
5444
  this.$nodeRef.element.classList.remove(...toRemove.trim().split(/\s+/));
4598
5445
  }
@@ -4783,7 +5630,8 @@
4783
5630
  if (lastTuple.length === 2) {
4784
5631
  result += " " + trim(lastTuple[1]);
4785
5632
  }
4786
- return result;
5633
+
5634
+ return result.replace(/unsafe:unsafe/g, "unsafe");
4787
5635
  }
4788
5636
  }
4789
5637
 
@@ -4992,11 +5840,11 @@
4992
5840
  * @returns {CompileProvider} Self for chaining.
4993
5841
  */
4994
5842
  this.directive = function registerDirective(name, directiveFactory) {
4995
- assertArg$1(name, "name");
5843
+ assertArg(name, "name");
4996
5844
  assertNotHasOwnProperty(name, "directive");
4997
5845
  if (isString(name)) {
4998
5846
  assertValidDirectiveName(name);
4999
- assertArg$1(directiveFactory, "directiveFactory");
5847
+ assertArg(directiveFactory, "directiveFactory");
5000
5848
  if (!hasOwn(hasDirectives, name)) {
5001
5849
  hasDirectives[name] = [];
5002
5850
  $provide.factory(name + DirectiveSuffix, [
@@ -5330,15 +6178,15 @@
5330
6178
  "$sce",
5331
6179
  "$animate",
5332
6180
  /**
5333
- * @param {import("../../core/di/internal-injector.js").InjectorService} $injector
6181
+ * @param {ng.InjectorService} $injector
5334
6182
  * @param {*} $interpolate
5335
6183
  * @param {import("../../services/exception/exception-handler.js").ErrorHandler} $exceptionHandler
5336
- * @param {*} $templateRequest
5337
- * @param {import("../parse/interface.ts").ParseService} $parse
6184
+ * @param {ng.TemplateRequestService} $templateRequest
6185
+ * @param {ng.ParseService} $parse
5338
6186
  * @param {*} $controller
5339
6187
  * @param {import('../scope/scope.js').Scope} $rootScope
5340
6188
  * @param {*} $sce
5341
- * @param {*} $animate
6189
+ * @param {ng.AnimateService} $animate
5342
6190
  * @returns
5343
6191
  */
5344
6192
  function (
@@ -5417,7 +6265,7 @@
5417
6265
  );
5418
6266
  }
5419
6267
 
5420
- assertArg$1(scope, "scope");
6268
+ assertArg(scope, "scope");
5421
6269
  // could be empty nodelist
5422
6270
  if (nodeRef.getAny()) {
5423
6271
  setScope(nodeRef.getAny(), scope);
@@ -5480,7 +6328,7 @@
5480
6328
 
5481
6329
  if (transcludeControllers) {
5482
6330
  for (const controllerName in transcludeControllers) {
5483
- assertArg$1($linkNode.element, "element");
6331
+ assertArg($linkNode.element, "element");
5484
6332
  setCacheData(
5485
6333
  $linkNode.element,
5486
6334
  `$${controllerName}Controller`,
@@ -5628,7 +6476,7 @@
5628
6476
  * @param {*} [parentBoundTranscludeFn]
5629
6477
  */
5630
6478
  function compositeLinkFn(scope, nodeRef, parentBoundTranscludeFn) {
5631
- assertArg$1(nodeRef, "nodeRef");
6479
+ assertArg(nodeRef, "nodeRef");
5632
6480
  let stableNodeList = [];
5633
6481
  if (nodeLinkFnFound) {
5634
6482
  // create a stable copy of the nodeList, only copying elements with linkFns
@@ -7035,11 +7883,19 @@
7035
7883
  replace: null,
7036
7884
  $$originalDirective: origAsyncDirective,
7037
7885
  });
7038
- const templateUrl = isFunction(origAsyncDirective.templateUrl)
7039
- ? /** @type { ((element: Element, tAttrs: Attributes) => string) } */ (
7886
+ /** @type {string} */
7887
+ let templateUrl;
7888
+
7889
+ if (isFunction(origAsyncDirective.templateUrl)) {
7890
+ templateUrl =
7891
+ /** @type { ((element: Element, tAttrs: Attributes) => string) } */ (
7040
7892
  origAsyncDirective.templateUrl
7041
- )($compileNode.element, tAttrs)
7042
- : origAsyncDirective.templateUrl;
7893
+ )($compileNode.element, tAttrs);
7894
+ } else {
7895
+ templateUrl = /** @type {string} */ (
7896
+ origAsyncDirective.templateUrl
7897
+ );
7898
+ }
7043
7899
  const { templateNamespace } = origAsyncDirective;
7044
7900
 
7045
7901
  emptyElement($compileNode.element);
@@ -7560,14 +8416,23 @@
7560
8416
  attr.$$element.classList.value,
7561
8417
  );
7562
8418
  } else {
7563
- attr.$set(name, newValue);
8419
+ attr.$set(
8420
+ name,
8421
+ name === "srcset"
8422
+ ? $sce.getTrustedMediaUrl(newValue)
8423
+ : newValue,
8424
+ );
7564
8425
  }
7565
8426
  });
7566
8427
  });
7567
8428
 
7568
8429
  if (interpolateFn.expressions.length == 0) {
7569
- // if there is nothing to watch, its a constant
7570
- attr.$set(name, newValue);
8430
+ attr.$set(
8431
+ name,
8432
+ name === "srcset"
8433
+ ? $sce.getTrustedMediaUrl(newValue)
8434
+ : newValue,
8435
+ );
7571
8436
  }
7572
8437
  },
7573
8438
  };
@@ -7976,7 +8841,7 @@
7976
8841
  */
7977
8842
  function assertValidDirectiveName(name) {
7978
8843
  const letter = name.charAt(0);
7979
- if (!letter || letter !== lowercase(letter)) {
8844
+ if (!letter || letter !== letter.toLowerCase()) {
7980
8845
  throw $compileMinErr(
7981
8846
  "baddir",
7982
8847
  "Directive/Component name '{0}' is invalid. The first character must be a lowercase letter",
@@ -8082,9 +8947,9 @@
8082
8947
 
8083
8948
  /**
8084
8949
  * @param {Element} $element
8085
- * @param {import("../../core/compile/attributes.js").Attributes} $attrs
8086
- * @param {import("../../core/scope/scope.js").Scope} $scope
8087
- * @param {*} $animate
8950
+ * @param {ng.Attributes} $attrs
8951
+ * @param {ng.Scope} $scope
8952
+ * @param {ng.AnimateService} $animate
8088
8953
  * @param {*} $interpolate
8089
8954
  */
8090
8955
  constructor($element, $attrs, $scope, $animate, $interpolate) {
@@ -8850,7 +9715,7 @@
8850
9715
  * @param {import('../../core/compile/attributes.js').Attributes} $attr
8851
9716
  * @param {Element} $element
8852
9717
  * @param {import("../../core/parse/interface.ts").ParseService} $parse
8853
- * @param {*} $animate
9718
+ * @param {ng.AnimateService} $animate
8854
9719
  * @param {*} $interpolate
8855
9720
  */
8856
9721
  constructor(
@@ -10874,9 +11739,9 @@
10874
11739
  inputDirective.$inject = ["$filter", "$parse"];
10875
11740
 
10876
11741
  /**
10877
- * @param {*} $filter
10878
- * @param {*} $parse
10879
- * @returns {import('../../interface.ts').Directive}
11742
+ * @param {ng.FilterService} $filter
11743
+ * @param {ng.ParseService} $parse
11744
+ * @returns {ng.Directive}
10880
11745
  */
10881
11746
  function inputDirective($filter, $parse) {
10882
11747
  return {
@@ -10885,7 +11750,7 @@
10885
11750
  link: {
10886
11751
  pre(scope, element, attr, ctrls) {
10887
11752
  if (ctrls[0]) {
10888
- (inputType[lowercase(attr["type"])] || inputType.text)(
11753
+ (inputType[attr.type?.toLowerCase()] || inputType.text)(
10889
11754
  scope,
10890
11755
  element,
10891
11756
  attr,
@@ -10900,7 +11765,7 @@
10900
11765
  }
10901
11766
 
10902
11767
  /**
10903
- * @returns {import('../../interface.ts').Directive}
11768
+ * @returns {ng.Directive}
10904
11769
  */
10905
11770
  function hiddenInputBrowserCacheDirective() {
10906
11771
  const valueProperty = {
@@ -10918,7 +11783,7 @@
10918
11783
  restrict: "E",
10919
11784
  priority: 200,
10920
11785
  compile(_, attr) {
10921
- if (lowercase(attr["type"]) !== "hidden") {
11786
+ if (attr.type?.toLowerCase() !== "hidden") {
10922
11787
  return;
10923
11788
  }
10924
11789
 
@@ -10946,7 +11811,7 @@
10946
11811
  const CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
10947
11812
 
10948
11813
  /**
10949
- * @returns {import('../../interface.ts').Directive}
11814
+ * @returns {ng.Directive}
10950
11815
  */
10951
11816
  function ngValueDirective() {
10952
11817
  /**
@@ -10970,15 +11835,15 @@
10970
11835
  return {
10971
11836
  restrict: "A",
10972
11837
  priority: 100,
10973
- compile(tpl, tplAttr) {
10974
- if (CONSTANT_VALUE_REGEXP.test(tplAttr["ngValue"])) {
10975
- return function ngValueConstantLink(scope, elm, attr) {
10976
- const value = scope.$eval(attr["ngValue"]);
11838
+ compile(_, tplAttr) {
11839
+ if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {
11840
+ return function (scope, elm, attr) {
11841
+ const value = scope.$eval(attr.ngValue);
10977
11842
  updateElementValue(elm, attr, value);
10978
11843
  };
10979
11844
  }
10980
- return function ngValueLink(scope, elm, attr) {
10981
- scope.$watch(attr["ngValue"], (value) => {
11845
+ return function (scope, elm, attr) {
11846
+ scope.$watch(attr.ngValue, (value) => {
10982
11847
  updateElementValue(elm, attr, value);
10983
11848
  });
10984
11849
  };
@@ -11659,17 +12524,20 @@
11659
12524
  /**
11660
12525
  * @param {string} name
11661
12526
  * @param {boolean|number} selector
11662
- * @returns {() => import("../../interface.ts").Directive}
12527
+ * @returns {ng.DirectiveFactory}
11663
12528
  */
11664
12529
  function classDirective(name, selector) {
11665
12530
  name = `ngClass${name}`;
11666
12531
 
12532
+ /**
12533
+ * @returns {ng.Directive}
12534
+ */
11667
12535
  return function () {
11668
12536
  return {
11669
12537
  /**
11670
- * @param {import("../../core/scope/scope.js").Scope} scope
11671
- * @param {Element} element
11672
- * @param {import("../../core/compile/attributes").Attributes} attr
12538
+ * @param {ng.Scope} scope
12539
+ * @param {HTMLElement} element
12540
+ * @param {ng.Attributes} attr
11673
12541
  */
11674
12542
  link(scope, element, attr) {
11675
12543
  let classCounts = getCacheData(element, "$classCounts");
@@ -11843,9 +12711,8 @@
11843
12711
  */
11844
12712
  function ngCloakDirective() {
11845
12713
  return {
11846
- compile(element, attr) {
12714
+ compile(_, attr) {
11847
12715
  attr.$set("ngCloak", undefined);
11848
- element.classList.remove("ng-cloak");
11849
12716
  },
11850
12717
  };
11851
12718
  }
@@ -11867,7 +12734,8 @@
11867
12734
 
11868
12735
  ngShowDirective.$inject = ["$animate"];
11869
12736
  /**
11870
- * @returns {import('../../interface.ts').Directive}
12737
+ * @param {ng.AnimateService} $animate
12738
+ * @returns {ng.Directive}
11871
12739
  */
11872
12740
  function ngShowDirective($animate) {
11873
12741
  return {
@@ -11878,7 +12746,7 @@
11878
12746
  * @param $attr
11879
12747
  */
11880
12748
  link(scope, element, $attr) {
11881
- scope.$watch($attr["ngShow"], (value) => {
12749
+ scope.$watch($attr.ngShow, (value) => {
11882
12750
  // we're adding a temporary, animation-specific class for ng-hide since this way
11883
12751
  // we can control when the element is actually displayed on screen without having
11884
12752
  // to have a global/greedy CSS selector that breaks when other animations are run.
@@ -11928,7 +12796,7 @@
11928
12796
 
11929
12797
  ngIfDirective.$inject = ["$animate"];
11930
12798
  /**
11931
- * @param {*} $animate
12799
+ * @param {ng.AnimateService} $animate
11932
12800
  * @returns {ng.Directive}
11933
12801
  */
11934
12802
  function ngIfDirective($animate) {
@@ -11949,7 +12817,7 @@
11949
12817
  /** @type {Element} */
11950
12818
  let block;
11951
12819
 
11952
- /** @type {import('../../core/scope/scope.js').Scope} */
12820
+ /** @type {ng.Scope} */
11953
12821
  let childScope;
11954
12822
 
11955
12823
  let previousElements;
@@ -12005,9 +12873,9 @@
12005
12873
 
12006
12874
  /**
12007
12875
  *
12008
- * @param {*} $templateRequest
12876
+ * @param {ng.TemplateRequestService} $templateRequest
12009
12877
  * @param {import("../../services/anchor-scroll/anchor-scroll.js").AnchorScrollFunction} $anchorScroll
12010
- * @param {*} $animate
12878
+ * @param {ng.AnimateService} $animate
12011
12879
  * @param {import('../../services/exception/interface.ts').ErrorHandler} $exceptionHandler
12012
12880
  * @returns {import('../../interface.ts').Directive}
12013
12881
  */
@@ -12609,8 +13477,8 @@
12609
13477
  ngSwitchDirective.$inject = ["$animate"];
12610
13478
 
12611
13479
  /**
12612
- * @param {*} $animate
12613
- * @returns {import('../../interface.ts').Directive}
13480
+ * @param {ng.AnimateService} $animate
13481
+ * @returns {ng.Directive}
12614
13482
  */
12615
13483
  function ngSwitchDirective($animate) {
12616
13484
  return {
@@ -12626,7 +13494,7 @@
12626
13494
  },
12627
13495
  ],
12628
13496
  link(scope, _element, attr, ngSwitchController) {
12629
- const watchExpr = attr["ngSwitch"] || attr["on"];
13497
+ const watchExpr = attr.ngSwitch || attr.on;
12630
13498
  let selectedTranscludes = [];
12631
13499
  const selectedElements = [];
12632
13500
  const previousLeaveAnimations = [];
@@ -13099,7 +13967,7 @@
13099
13967
  if (providedEmptyOption) {
13100
13968
  // compile the element since there might be bindings in it
13101
13969
  const linkFn = $compile(selectCtrl.emptyOption);
13102
- assertArg$1(linkFn, "LinkFn required");
13970
+ assertArg(linkFn, "LinkFn required");
13103
13971
  selectElement.prepend(selectCtrl.emptyOption);
13104
13972
  linkFn(scope);
13105
13973
 
@@ -13873,7 +14741,7 @@
13873
14741
 
13874
14742
  if (isFunction(offset)) {
13875
14743
  offset = /** @type {Function} */ (offset)();
13876
- } else if (isElement(offset)) {
14744
+ } else if (offset instanceof Element) {
13877
14745
  const elem = offset[0];
13878
14746
  const style = window.getComputedStyle(elem);
13879
14747
  if (style.position !== "fixed") {
@@ -13964,27 +14832,8 @@
13964
14832
  ];
13965
14833
  }
13966
14834
 
13967
- /** @typedef {"enter"|"leave"|"move"|"addClass"|"setClass"|"removeClass"} AnimationMethod */
13968
-
13969
- /**
13970
- * @typedef {Object} AnimationOptions
13971
- * @property {string} addClass - space-separated CSS classes to add to element
13972
- * @property {Object} from - CSS properties & values at the beginning of animation. Must have matching `to`
13973
- * @property {string} removeClass - space-separated CSS classes to remove from element
13974
- * @property {string} to - CSS properties & values at end of animation. Must have matching `from`
13975
- */
13976
-
13977
14835
  const $animateMinErr = minErr("$animate");
13978
14836
 
13979
- function mergeClasses(a, b) {
13980
- if (!a && !b) return "";
13981
- if (!a) return b;
13982
- if (!b) return a;
13983
- if (Array.isArray(a)) a = a.join(" ");
13984
- if (Array.isArray(b)) b = b.join(" ");
13985
- return `${a} ${b}`;
13986
- }
13987
-
13988
14837
  // if any other type of options value besides an Object value is
13989
14838
  // passed into the $animate.method() animation then this helper code
13990
14839
  // will be run which will ignore it. While this patch is not the
@@ -13998,7 +14847,7 @@
13998
14847
 
13999
14848
  AnimateProvider.$inject = ["$provide"];
14000
14849
 
14001
- /** @param {import('../interface.ts').Provider} $provide */
14850
+ /** @param {ng.ProvideService} $provide */
14002
14851
  function AnimateProvider($provide) {
14003
14852
  const provider = this;
14004
14853
  let classNameFilter = null;
@@ -14132,7 +14981,11 @@
14132
14981
  };
14133
14982
 
14134
14983
  this.$get = [
14135
- "$$animateQueue",
14984
+ $injectTokens.$$animateQueue,
14985
+ /**
14986
+ * @param {import("./queue/interface.ts").AnimateQueueService} $$animateQueue
14987
+ * @returns {ng.AnimateService}
14988
+ */
14136
14989
  function ($$animateQueue) {
14137
14990
  /**
14138
14991
  * The $animate service exposes a series of DOM utility methods that provide support
@@ -14266,77 +15119,21 @@
14266
15119
  *
14267
15120
  * @return {boolean} whether or not animations are enabled
14268
15121
  */
14269
- enabled: $$animateQueue.enabled,
15122
+ enabled: (element, enabled) => {
15123
+ if (enabled !== undefined) {
15124
+ return hasAnimate(element);
15125
+ } else {
15126
+ element.setAttribute("animate", `${enabled}`);
15127
+ }
15128
+ },
14270
15129
 
14271
15130
  /**
14272
- * Cancels the provided animation and applies the end state of the animation.
14273
- * Note that this does not cancel the underlying operation, e.g. the setting of classes or
14274
- * adding the element to the DOM.
14275
- *
14276
- * @param {import('./animate-runner.js').AnimateRunner} runner An animation runner returned by an $animate function.
14277
- *
14278
- * @example
14279
- <example module="animationExample" deps="angular-animate.js" animations="true" name="animate-cancel">
14280
- <file name="app.js">
14281
- angular.module('animationExample', []).component('cancelExample', {
14282
- templateUrl: 'template.html',
14283
- controller: function($element, $animate) {
14284
- this.runner = null;
14285
-
14286
- this.addClass = function() {
14287
- this.runner = $animate.addClass($element.querySelectorAll('div'), 'red');
14288
- let ctrl = this;
14289
- this.runner.finally(function() {
14290
- ctrl.runner = null;
14291
- });
14292
- };
14293
-
14294
- this.removeClass = function() {
14295
- this.runner = $animate.removeClass($element.querySelectorAll('div'), 'red');
14296
- let ctrl = this;
14297
- this.runner.finally(function() {
14298
- ctrl.runner = null;
14299
- });
14300
- };
14301
-
14302
- this.cancel = function() {
14303
- $animate.cancel(this.runner);
14304
- };
14305
- }
14306
- });
14307
- </file>
14308
- <file name="template.html">
14309
- <p>
14310
- <button id="add" ng-click="$ctrl.addClass()">Add</button>
14311
- <button ng-click="$ctrl.removeClass()">Remove</button>
14312
- <br>
14313
- <button id="cancel" ng-click="$ctrl.cancel()" ng-disabled="!$ctrl.runner">Cancel</button>
14314
- <br>
14315
- <div id="target">CSS-Animated Text</div>
14316
- </p>
14317
- </file>
14318
- <file name="index.html">
14319
- <cancel-example></cancel-example>
14320
- </file>
14321
- <file name="style.css">
14322
- .red-add, .red-remove {
14323
- transition: all 4s cubic-bezier(0.250, 0.460, 0.450, 0.940);
14324
- }
14325
-
14326
- .red,
14327
- .red-add.red-add-active {
14328
- color: #FF0000;
14329
- font-size: 40px;
14330
- }
14331
-
14332
- .red-remove.red-remove-active {
14333
- font-size: 10px;
14334
- color: black;
14335
- }
14336
-
14337
- </file>
14338
- </example>
14339
- */
15131
+ * Cancels the provided animation and applies the end state of the animation.
15132
+ * Note that this does not cancel the underlying operation, e.g. the setting of classes or
15133
+ * adding the element to the DOM.
15134
+ *
15135
+ * @param {import('./runner/animate-runner.js').AnimateRunner} runner An animation runner returned by an $animate function.
15136
+ */
14340
15137
  cancel(runner) {
14341
15138
  if (runner.cancel) {
14342
15139
  runner.cancel();
@@ -14352,12 +15149,12 @@
14352
15149
  * @param {Element} element - the element which will be inserted into the DOM
14353
15150
  * @param {Element} parent - the parent element which will append the element as a child (so long as the after element is not present)
14354
15151
  * @param {Element} [after] - after the sibling element after which the element will be appended
14355
- * @param {AnimationOptions} [options] - an optional collection of options/styles that will be applied to the element.
14356
- * @returns {import('./animate-runner.js').AnimateRunner} the animation runner
15152
+ * @param {import("./interface.ts").AnimationOptions} [options] - an optional collection of options/styles that will be applied to the element.
15153
+ * @returns {import('./runner/animate-runner.js').AnimateRunner} the animation runner
14357
15154
  */
14358
15155
  enter(element, parent, after, options) {
14359
15156
  parent = parent || after.parentElement;
14360
- domInsert(element, parent, after);
15157
+ animatedomInsert(element, parent, after);
14361
15158
  return $$animateQueue.push(
14362
15159
  element,
14363
15160
  "enter",
@@ -14374,12 +15171,12 @@
14374
15171
  * @param {Element} element - the element which will be inserted into the DOM
14375
15172
  * @param {Element} parent - the parent element which will append the element as a child (so long as the after element is not present)
14376
15173
  * @param {Element} after - after the sibling element after which the element will be appended
14377
- * @param {AnimationOptions} [options] - an optional collection of options/styles that will be applied to the element.
14378
- * @returns {import('./animate-runner.js').AnimateRunner} the animation runner
15174
+ * @param {import("./interface.ts").AnimationOptions} [options] - an optional collection of options/styles that will be applied to the element.
15175
+ * @returns {import('./runner/animate-runner.js').AnimateRunner} the animation runner
14379
15176
  */
14380
15177
  move(element, parent, after, options) {
14381
15178
  parent = parent || after.parentElement;
14382
- domInsert(element, parent, after);
15179
+ animatedomInsert(element, parent, after);
14383
15180
  return $$animateQueue.push(
14384
15181
  element,
14385
15182
  "move",
@@ -14393,8 +15190,8 @@
14393
15190
  * digest once the animation has completed.
14394
15191
  *
14395
15192
  * @param {Element} element the element which will be removed from the DOM
14396
- * @param {AnimationOptions} [options] an optional collection of options/styles that will be applied to the element.
14397
- * @returns {import('./animate-runner.js').AnimateRunner} the animation runner
15193
+ * @param {import("./interface.ts").AnimationOptions} [options] an optional collection of options/styles that will be applied to the element.
15194
+ * @returns {import('./runner/animate-runner.js').AnimateRunner} the animation runner
14398
15195
  */
14399
15196
  leave(element, options) {
14400
15197
  return $$animateQueue.push(
@@ -14422,8 +15219,8 @@
14422
15219
  *
14423
15220
  * @param {Element} element the element which the CSS classes will be applied to
14424
15221
  * @param {string} className the CSS class(es) that will be added (multiple classes are separated via spaces)
14425
- * @param {AnimationOptions} [options] an optional collection of options/styles that will be applied to the element.
14426
- * @return {import('./animate-runner.js').AnimateRunner}} animationRunner the animation runner
15222
+ * @param {import("./interface").AnimationOptions} [options] an optional collection of options/styles that will be applied to the element.
15223
+ * @return {import('./runner/animate-runner.js').AnimateRunner}} animationRunner the animation runner
14427
15224
  */
14428
15225
  addClass(element, className, options) {
14429
15226
  options = prepareAnimateOptions(options);
@@ -14441,8 +15238,8 @@
14441
15238
  *
14442
15239
  * @param {Element} element the element which the CSS classes will be applied to
14443
15240
  * @param {string} className the CSS class(es) that will be removed (multiple classes are separated via spaces)
14444
- * @param {AnimationOptions} [options] an optional collection of options/styles that will be applied to the element. *
14445
- * @return {import('./animate-runner.js').AnimateRunner} animationRunner the animation runner
15241
+ * @param {import("./interface").AnimationOptions} [options] an optional collection of options/styles that will be applied to the element. *
15242
+ * @return {import('./runner/animate-runner.js').AnimateRunner} animationRunner the animation runner
14446
15243
  */
14447
15244
  removeClass(element, className, options) {
14448
15245
  options = prepareAnimateOptions(options);
@@ -14463,7 +15260,7 @@
14463
15260
  * @param {string} remove the CSS class(es) that will be removed (multiple classes are separated via spaces)
14464
15261
  * @param {object=} options an optional collection of options/styles that will be applied to the element.
14465
15262
  *
14466
- * @return {import('./animate-runner.js').AnimateRunner} the animation runner
15263
+ * @return {import('./runner/animate-runner.js').AnimateRunner} the animation runner
14467
15264
  */
14468
15265
  setClass(element, add, remove, options) {
14469
15266
  options = prepareAnimateOptions(options);
@@ -14491,7 +15288,7 @@
14491
15288
  * }
14492
15289
  * });
14493
15290
  * ```
14494
- * @return {import('./animate-runner.js').AnimateRunner} the animation runner
15291
+ * @return {import('./runner/animate-runner.js').AnimateRunner} the animation runner
14495
15292
  */
14496
15293
  animate(element, from, to, className, options) {
14497
15294
  options = prepareAnimateOptions(options);
@@ -14507,200 +15304,6 @@
14507
15304
  ];
14508
15305
  }
14509
15306
 
14510
- function AnimateAsyncRunFactoryProvider() {
14511
- this.$get = [
14512
- function () {
14513
- let waitQueue = [];
14514
-
14515
- function waitForTick(fn) {
14516
- waitQueue.push(fn);
14517
- if (waitQueue.length > 1) return;
14518
- window.requestAnimationFrame(function () {
14519
- for (let i = 0; i < waitQueue.length; i++) {
14520
- waitQueue[i]();
14521
- }
14522
- waitQueue = [];
14523
- });
14524
- }
14525
-
14526
- return function () {
14527
- let passed = false;
14528
- waitForTick(function () {
14529
- passed = true;
14530
- });
14531
- return function (callback) {
14532
- if (passed) {
14533
- callback();
14534
- } else {
14535
- waitForTick(callback);
14536
- }
14537
- };
14538
- };
14539
- },
14540
- ];
14541
- }
14542
-
14543
- const INITIAL_STATE = 0;
14544
- const DONE_PENDING_STATE = 1;
14545
- const DONE_COMPLETE_STATE = 2;
14546
- let $$animateAsyncRun;
14547
-
14548
- function AnimateRunnerFactoryProvider() {
14549
- this.$get = [
14550
- "$$animateAsyncRun",
14551
- function (animateAsyncRun) {
14552
- $$animateAsyncRun = animateAsyncRun;
14553
- return AnimateRunner;
14554
- },
14555
- ];
14556
- }
14557
-
14558
- class AnimateRunner {
14559
- static chain(chain, callback) {
14560
- let index = 0;
14561
-
14562
- function next() {
14563
- if (index === chain.length) {
14564
- callback(true);
14565
- return;
14566
- }
14567
-
14568
- chain[index]((response) => {
14569
- if (response === false) {
14570
- callback(false);
14571
- return;
14572
- }
14573
- index++;
14574
- next();
14575
- });
14576
- }
14577
-
14578
- next();
14579
- }
14580
-
14581
- static all(runners, callback) {
14582
- let count = 0;
14583
- let status = true;
14584
-
14585
- runners.forEach((runner) => {
14586
- runner.done(onProgress);
14587
- });
14588
-
14589
- function onProgress(response) {
14590
- status = status && response;
14591
- if (++count === runners.length) {
14592
- callback(status);
14593
- }
14594
- }
14595
- }
14596
-
14597
- constructor(host) {
14598
- this.setHost(host);
14599
-
14600
- const rafTick = $$animateAsyncRun();
14601
- const timeoutTick = (fn) => {
14602
- setTimeout(fn, 0, false);
14603
- };
14604
-
14605
- this._doneCallbacks = [];
14606
- this._tick = (fn) => {
14607
- if (document.hidden) {
14608
- timeoutTick(fn);
14609
- } else {
14610
- rafTick(fn);
14611
- }
14612
- };
14613
- this._state = 0;
14614
- }
14615
-
14616
- setHost(host) {
14617
- this.host = host || {};
14618
- }
14619
-
14620
- done(fn) {
14621
- if (this._state === DONE_COMPLETE_STATE) {
14622
- fn();
14623
- } else {
14624
- this._doneCallbacks.push(fn);
14625
- }
14626
- }
14627
-
14628
- progress() {}
14629
-
14630
- getPromise() {
14631
- if (!this.promise) {
14632
- const self = this;
14633
- this.promise = new Promise((resolve, reject) => {
14634
- self.done((status) => {
14635
- if (status === false) {
14636
- reject();
14637
- } else {
14638
- resolve();
14639
- }
14640
- });
14641
- });
14642
- }
14643
- return this.promise;
14644
- }
14645
-
14646
- then(resolveHandler, rejectHandler) {
14647
- return this.getPromise().then(resolveHandler, rejectHandler);
14648
- }
14649
-
14650
- catch(handler) {
14651
- return this.getPromise().catch(handler);
14652
- }
14653
-
14654
- finally(handler) {
14655
- return this.getPromise().finally(handler);
14656
- }
14657
-
14658
- pause() {
14659
- if (this.host.pause) {
14660
- this.host.pause();
14661
- }
14662
- }
14663
-
14664
- resume() {
14665
- if (this.host.resume) {
14666
- this.host.resume();
14667
- }
14668
- }
14669
-
14670
- end() {
14671
- if (this.host.end) {
14672
- this.host.end();
14673
- }
14674
- this._resolve(true);
14675
- }
14676
-
14677
- cancel() {
14678
- if (this.host.cancel) {
14679
- this.host.cancel();
14680
- }
14681
- this._resolve(false);
14682
- }
14683
-
14684
- complete(response) {
14685
- if (this._state === INITIAL_STATE) {
14686
- this._state = DONE_PENDING_STATE;
14687
- this._tick(() => {
14688
- this._resolve(response);
14689
- });
14690
- }
14691
- }
14692
-
14693
- _resolve(response) {
14694
- if (this._state !== DONE_COMPLETE_STATE) {
14695
- this._doneCallbacks.forEach((fn) => {
14696
- fn(response);
14697
- });
14698
- this._doneCallbacks.length = 0;
14699
- this._state = DONE_COMPLETE_STATE;
14700
- }
14701
- }
14702
- }
14703
-
14704
15307
  /**
14705
15308
  * Provides an instance of a cache that can be used to store and retrieve template content.
14706
15309
  */
@@ -15280,7 +15883,7 @@
15280
15883
  /* @ignore */ static $inject = [$injectTokens.$provide];
15281
15884
 
15282
15885
  /**
15283
- * @param {import('../../interface.ts').Provider} $provide
15886
+ * @param {ng.ProvideService} $provide
15284
15887
  */
15285
15888
  constructor($provide) {
15286
15889
  this.$provide = $provide;
@@ -18059,7 +18662,7 @@
18059
18662
  );
18060
18663
  } else if (isObject(headers)) {
18061
18664
  Object.entries(headers).forEach(([headerKey, headerVal]) => {
18062
- fillInParsed(lowercase(headerKey), trim(headerVal));
18665
+ fillInParsed(headerKey.toLowerCase(), trim(headerVal));
18063
18666
  });
18064
18667
  }
18065
18668
 
@@ -18085,7 +18688,7 @@
18085
18688
  if (!headersObj) headersObj = parseHeaders(headers);
18086
18689
 
18087
18690
  if (name) {
18088
- let value = headersObj[lowercase(name)];
18691
+ let value = headersObj[name.toLowerCase()];
18089
18692
  if (value === undefined) {
18090
18693
  value = null;
18091
18694
  }
@@ -19525,8 +20128,6 @@
19525
20128
  * @returns {Location}
19526
20129
  */
19527
20130
  ($rootScope, $rootElement) => {
19528
- /** @type {Location} */
19529
- let $location;
19530
20131
  const baseHref = getBaseHref(); // if base[href] is undefined, it defaults to ''
19531
20132
  const initialUrl = trimEmptyHash(window.location.href);
19532
20133
  let appBase;
@@ -19544,7 +20145,7 @@
19544
20145
  }
19545
20146
  const appBaseNoFile = stripFile(appBase);
19546
20147
 
19547
- $location = new Location(
20148
+ const $location = new Location(
19548
20149
  appBase,
19549
20150
  appBaseNoFile,
19550
20151
  this.html5ModeConf.enabled,
@@ -20052,7 +20653,7 @@
20052
20653
  }
20053
20654
 
20054
20655
  /**
20055
- * @returns {import("./interface.ts").LogService}
20656
+ * @returns {ng.LogService}
20056
20657
  */
20057
20658
  $get() {
20058
20659
  if (this._override) {
@@ -20134,6 +20735,9 @@
20134
20735
  }
20135
20736
 
20136
20737
  if (typeof target === "object") {
20738
+ if (isUnsafeGlobal(target)) {
20739
+ return target;
20740
+ }
20137
20741
  const proxy = new Proxy(target, context || new Scope());
20138
20742
  for (const key in target) {
20139
20743
  if (hasOwn(target, key)) {
@@ -20151,7 +20755,7 @@
20151
20755
  target[key] = createScope(target[key], proxy.$handler);
20152
20756
  }
20153
20757
  } catch {
20154
- // convert only what we can
20758
+ /* empty */
20155
20759
  }
20156
20760
  }
20157
20761
  }
@@ -20162,6 +20766,54 @@
20162
20766
  }
20163
20767
  }
20164
20768
 
20769
+ /**
20770
+ * @param {any} target
20771
+ * @returns {boolean}
20772
+ */
20773
+ function isUnsafeGlobal(target) {
20774
+ if (target == null) return false;
20775
+ const t = typeof target;
20776
+ if (t !== "object" && t !== "function") return false;
20777
+
20778
+ const g = globalThis;
20779
+ if (
20780
+ target === g ||
20781
+ target === g.window ||
20782
+ target === g.document ||
20783
+ target === g.self ||
20784
+ target === g.frames
20785
+ ) {
20786
+ return true;
20787
+ }
20788
+
20789
+ // DOM / browser host object checks
20790
+ if (
20791
+ (typeof Window !== "undefined" && target instanceof Window) ||
20792
+ (typeof Document !== "undefined" && target instanceof Document) ||
20793
+ (typeof Element !== "undefined" && target instanceof Element) ||
20794
+ (typeof Node !== "undefined" && target instanceof Node) ||
20795
+ (typeof EventTarget !== "undefined" && target instanceof EventTarget)
20796
+ ) {
20797
+ return true;
20798
+ }
20799
+
20800
+ if (target instanceof Promise) {
20801
+ return true;
20802
+ }
20803
+
20804
+ // Events
20805
+ if (typeof Event !== "undefined" && target instanceof Event) {
20806
+ return true;
20807
+ }
20808
+
20809
+ // Cross-origin or non-enumerable window objects
20810
+ try {
20811
+ return Object.prototype.toString.call(target) === "[object Window]";
20812
+ } catch {
20813
+ return true;
20814
+ }
20815
+ }
20816
+
20165
20817
  /**
20166
20818
  * Decorator for excluding objects from scope observability
20167
20819
  */
@@ -20248,6 +20900,8 @@
20248
20900
 
20249
20901
  this.scheduled = [];
20250
20902
 
20903
+ this.$scopename = undefined;
20904
+
20251
20905
  /** @private */
20252
20906
  this.propertyMap = {
20253
20907
  $watch: this.$watch.bind(this),
@@ -20259,18 +20913,20 @@
20259
20913
  $apply: this.$apply.bind(this),
20260
20914
  $postUpdate: this.$postUpdate.bind(this),
20261
20915
  $isRoot: this.#isRoot.bind(this),
20262
- $proxy: this.$proxy,
20263
20916
  $on: this.$on.bind(this),
20264
20917
  $emit: this.$emit.bind(this),
20265
20918
  $broadcast: this.$broadcast.bind(this),
20266
20919
  $transcluded: this.$transcluded.bind(this),
20267
20920
  $handler: /** @type {Scope} */ (this),
20921
+ $merge: this.$merge.bind(this),
20922
+ $getById: this.$getById.bind(this),
20923
+ $searchByName: this.$searchByName.bind(this),
20924
+ $proxy: this.$proxy,
20268
20925
  $parent: this.$parent,
20269
20926
  $root: this.$root,
20270
20927
  $children: this.$children,
20271
20928
  $id: this.$id,
20272
- $merge: this.$merge.bind(this),
20273
- $getById: this.$getById.bind(this),
20929
+ $scopename: this.$scopename,
20274
20930
  };
20275
20931
  }
20276
20932
 
@@ -20286,8 +20942,14 @@
20286
20942
  */
20287
20943
  set(target, property, value, proxy) {
20288
20944
  if (property === "undefined") {
20289
- throw new Error("Attempting to set undefined property");
20945
+ return false;
20946
+ }
20947
+
20948
+ if (property === "$scopename") {
20949
+ this.$scopename = value;
20950
+ return true;
20290
20951
  }
20952
+
20291
20953
  if (
20292
20954
  (target.constructor?.$nonscope &&
20293
20955
  Array.isArray(target.constructor.$nonscope) &&
@@ -20504,9 +21166,9 @@
20504
21166
  * @returns {*} - The value of the property or a method if accessing `watch` or `sync`.
20505
21167
  */
20506
21168
  get(target, property, proxy) {
21169
+ if (property === "$scopename" && this.$scopename) return this.$scopename;
20507
21170
  if (property === "$$watchersCount") return calculateWatcherCount(this);
20508
21171
  if (property === isProxySymbol) return true;
20509
-
20510
21172
  if (target[property] && isProxy(target[property])) {
20511
21173
  this.$proxy = target[property];
20512
21174
  } else {
@@ -20535,7 +21197,6 @@
20535
21197
  this.#scheduleListener(this.scheduled);
20536
21198
  }
20537
21199
  }
20538
-
20539
21200
  if (hasOwn(this.propertyMap, property)) {
20540
21201
  this.$target = target;
20541
21202
  return this.propertyMap[property];
@@ -20633,7 +21294,7 @@
20633
21294
  * function is invoked when changes to that property are detected.
20634
21295
  *
20635
21296
  * @param {string} watchProp - An expression to be watched in the context of this model.
20636
- * @param {import('./interface.ts').ListenerFunction} [listenerFn] - A function to execute when changes are detected on watched context.
21297
+ * @param {ng.ListenerFn} [listenerFn] - A function to execute when changes are detected on watched context.
20637
21298
  * @param {boolean} [lazy] - A flag to indicate if the listener should be invoked immediately. Defaults to false.
20638
21299
  */
20639
21300
  $watch(watchProp, listenerFn, lazy = false) {
@@ -20655,7 +21316,7 @@
20655
21316
  return () => {};
20656
21317
  }
20657
21318
 
20658
- /** @type {import('./interface.ts').Listener} */
21319
+ /** @type {ng.Listener} */
20659
21320
  const listener = {
20660
21321
  originalTarget: this.$target,
20661
21322
  listenerFn: listenerFn,
@@ -20713,13 +21374,34 @@
20713
21374
  }
20714
21375
  // 6
20715
21376
  case ASTType.BinaryExpression: {
20716
- let expr = get.decoratedNode.body[0].expression.toWatch[0];
20717
- key = expr.property ? expr.property.name : expr.name;
20718
- if (!key) {
20719
- throw new Error("Unable to determine key");
21377
+ if (get.decoratedNode.body[0].expression.isPure) {
21378
+ let expr = get.decoratedNode.body[0].expression.toWatch[0];
21379
+ key = expr.property ? expr.property.name : expr.name;
21380
+ if (!key) {
21381
+ throw new Error("Unable to determine key");
21382
+ }
21383
+ listener.property.push(key);
21384
+ break;
21385
+ } else {
21386
+ let keys = [];
21387
+ get.decoratedNode.body[0].expression.toWatch.forEach((x) => {
21388
+ const k = x.property ? x.property.name : x.name;
21389
+ if (!k) {
21390
+ throw new Error("Unable to determine key");
21391
+ }
21392
+ keys.push(k);
21393
+ });
21394
+ keys.forEach((key) => {
21395
+ this.#registerKey(key, listener);
21396
+ this.#scheduleListener([listener]);
21397
+ });
21398
+
21399
+ return () => {
21400
+ keys.forEach((key) => {
21401
+ this.#deregisterKey(key, listener.id);
21402
+ });
21403
+ };
20720
21404
  }
20721
- listener.property.push(key);
20722
- break;
20723
21405
  }
20724
21406
  // 7
20725
21407
  case ASTType.UnaryExpression: {
@@ -21259,6 +21941,26 @@
21259
21941
  return res;
21260
21942
  }
21261
21943
  }
21944
+
21945
+ $searchByName(name) {
21946
+ const getByName = (scope, name) => {
21947
+ if (scope.$scopename === name) {
21948
+ return scope;
21949
+ } else {
21950
+ let res = undefined;
21951
+ for (const child of scope.$children) {
21952
+ let found = getByName(child, name);
21953
+ if (found) {
21954
+ res = found;
21955
+ break;
21956
+ }
21957
+ }
21958
+ return res;
21959
+ }
21960
+ };
21961
+
21962
+ return getByName(this.$root, name);
21963
+ }
21262
21964
  }
21263
21965
 
21264
21966
  /*------------- Private helpers -------------*/
@@ -21486,25 +22188,31 @@
21486
22188
  }
21487
22189
 
21488
22190
  /**
21489
- * @returns {import("./interface").SanitizerFn}
22191
+ * @returns {import("./interface.ts").SanitizerFn}
21490
22192
  */
21491
- $get() {
21492
- return (uri, isMediaUrl) => {
21493
- if (!uri) return uri;
22193
+ $get = [
22194
+ $injectTokens.$window,
22195
+ /** @param {ng.WindowService} $window */
22196
+ ($window) => {
22197
+ return /** @type {import("./interface.ts").SanitizerFn} */ (
22198
+ (uri, isMediaUrl) => {
22199
+ if (!uri) return uri;
21494
22200
 
21495
- /** @type {RegExp} */
21496
- const regex = isMediaUrl
21497
- ? this._imgSrcSanitizationTrustedUrlList
21498
- : this._aHrefSanitizationTrustedUrlList;
22201
+ /** @type {RegExp} */
22202
+ const regex = isMediaUrl
22203
+ ? this._imgSrcSanitizationTrustedUrlList
22204
+ : this._aHrefSanitizationTrustedUrlList;
21499
22205
 
21500
- const normalizedVal = urlResolve(uri.trim()).href;
22206
+ const normalizedVal = new URL(uri.trim(), $window.location.href).href;
21501
22207
 
21502
- if (normalizedVal !== "" && !normalizedVal.match(regex)) {
21503
- return `unsafe:${normalizedVal}`;
21504
- }
21505
- return uri;
21506
- };
21507
- }
22208
+ if (normalizedVal !== "" && !normalizedVal.match(regex)) {
22209
+ return `unsafe:${normalizedVal}`;
22210
+ }
22211
+ return uri;
22212
+ }
22213
+ );
22214
+ },
22215
+ ];
21508
22216
  }
21509
22217
 
21510
22218
  const ACTIVE_CLASS = "ng-active";
@@ -21513,9 +22221,9 @@
21513
22221
  class NgMessageCtrl {
21514
22222
  /**
21515
22223
  * @param {Element} $element
21516
- * @param {import('../../core/scope/scope.js').Scope} $scope
21517
- * @param {import('../../core/compile/attributes').Attributes} $attrs
21518
- * @param {*} $animate
22224
+ * @param {ng.Scope} $scope
22225
+ * @param {ng.Attributes} $attrs
22226
+ * @param {ng.AnimateService} $animate
21519
22227
  */
21520
22228
  constructor($element, $scope, $attrs, $animate) {
21521
22229
  this.$element = $element;
@@ -21699,6 +22407,10 @@
21699
22407
  }
21700
22408
 
21701
22409
  ngMessagesDirective.$inject = ["$animate"];
22410
+ /**
22411
+ * @param {ng.AnimateService} $animate
22412
+ * @returns {ng.Directive<NgMessageCtrl>}
22413
+ */
21702
22414
  function ngMessagesDirective($animate) {
21703
22415
  return {
21704
22416
  require: "ngMessages",
@@ -21745,10 +22457,14 @@
21745
22457
 
21746
22458
  /**
21747
22459
  * @param {boolean} isDefault
21748
- * @returns {(any) => import("../../interface.ts").Directive}
22460
+ * @returns {(any) => ng.Directive}
21749
22461
  */
21750
22462
  function ngMessageDirectiveFactory(isDefault) {
21751
22463
  ngMessageDirective.$inject = ["$animate"];
22464
+ /**
22465
+ * @param {ng.AnimateService} $animate
22466
+ * @returns {ng.Directive}
22467
+ */
21752
22468
  function ngMessageDirective($animate) {
21753
22469
  return {
21754
22470
  restrict: "AE",
@@ -22235,6 +22951,231 @@
22235
22951
  };
22236
22952
  }
22237
22953
 
22954
+ /**
22955
+ * @fileoverview
22956
+ * Frame-synchronized animation runner and scheduler.
22957
+ * Provides async batching of animation callbacks using requestAnimationFrame.
22958
+ * In AngularJS, this used to be implemented as `$$AnimateRunner`
22959
+ */
22960
+
22961
+ /**
22962
+ * Internal runner states.
22963
+ * @readonly
22964
+ * @enum {number}
22965
+ */
22966
+ const RunnerState = {
22967
+ INITIAL: 0,
22968
+ PENDING: 1,
22969
+ DONE: 2,
22970
+ };
22971
+
22972
+ /** @type {VoidFunction[]} */
22973
+ let queue = [];
22974
+
22975
+ /** @type {boolean} */
22976
+ let scheduled = false;
22977
+
22978
+ /**
22979
+ * Flush all queued callbacks.
22980
+ * @private
22981
+ */
22982
+ function flush() {
22983
+ const tasks = queue;
22984
+ queue = [];
22985
+ scheduled = false;
22986
+ for (let i = 0; i < tasks.length; i++) {
22987
+ tasks[i]();
22988
+ }
22989
+ }
22990
+
22991
+ /**
22992
+ * Schedule a callback to run on the next animation frame.
22993
+ * Multiple calls within the same frame are batched together.
22994
+ *
22995
+ * @param {VoidFunction} fn - The callback to execute.
22996
+ */
22997
+ function schedule(fn) {
22998
+ queue.push(fn);
22999
+ if (!scheduled) {
23000
+ scheduled = true;
23001
+ (typeof requestAnimationFrame === "function"
23002
+ ? requestAnimationFrame
23003
+ : setTimeout)(flush, 0);
23004
+ }
23005
+ }
23006
+
23007
+ /**
23008
+ * Represents an asynchronous animation operation.
23009
+ * Provides both callback-based and promise-based completion APIs.
23010
+ */
23011
+ class AnimateRunner {
23012
+ /**
23013
+ * Run an array of animation runners in sequence.
23014
+ * Each runner waits for the previous one to complete.
23015
+ *
23016
+ * @param {AnimateRunner[]} runners - Runners to execute in order.
23017
+ * @param {(ok: boolean) => void} callback - Invoked when all complete or one fails.
23018
+ */
23019
+ static chain(runners, callback) {
23020
+ let i = 0;
23021
+ const next = (ok = true) => {
23022
+ if (!ok || i >= runners.length) {
23023
+ callback(ok);
23024
+ return;
23025
+ }
23026
+ runners[i++].done(next);
23027
+ };
23028
+ next();
23029
+ }
23030
+
23031
+ /**
23032
+ * Waits for all animation runners to complete before invoking the callback.
23033
+ *
23034
+ * @param {AnimateRunner[]} runners - Active runners to wait for.
23035
+ * @param {(ok: boolean) => void} callback - Called when all runners complete.
23036
+ */
23037
+ static all(runners, callback) {
23038
+ let remaining = runners.length;
23039
+ let status = true;
23040
+ for (const r of runners) {
23041
+ r.done((result) => {
23042
+ status = status && result !== false;
23043
+ if (--remaining === 0) callback(status);
23044
+ });
23045
+ }
23046
+ }
23047
+
23048
+ /**
23049
+ * @param {import("../interface.ts").AnimationHost} [host] - Optional animation host.
23050
+ */
23051
+ constructor(host) {
23052
+ /** @type {import("../interface.ts").AnimationHost} */
23053
+ this.host = host || {};
23054
+
23055
+ /** @type {Array<(ok: boolean) => void>} */
23056
+ this._doneCallbacks = [];
23057
+
23058
+ /** @type {RunnerState} */
23059
+ this._state = RunnerState.INITIAL;
23060
+
23061
+ /** @type {Promise<void>|null} */
23062
+ this._promise = null;
23063
+
23064
+ /** @type {(fn: VoidFunction) => void} */
23065
+ this._schedule = schedule;
23066
+ }
23067
+
23068
+ /**
23069
+ * Sets or updates the animation host.
23070
+ * @param {import("../interface.ts").AnimationHost} host - The host object.
23071
+ */
23072
+ setHost(host) {
23073
+ this.host = host || {};
23074
+ }
23075
+
23076
+ /**
23077
+ * Registers a callback to be called once the animation completes.
23078
+ * If the animation is already complete, it's called immediately.
23079
+ *
23080
+ * @param {(ok: boolean) => void} fn - Completion callback.
23081
+ */
23082
+ done(fn) {
23083
+ if (this._state === RunnerState.DONE) {
23084
+ fn(true);
23085
+ } else {
23086
+ this._doneCallbacks.push(fn);
23087
+ }
23088
+ }
23089
+
23090
+ /**
23091
+ * Notifies the host of animation progress.
23092
+ * @param {...any} args - Progress arguments.
23093
+ */
23094
+ progress(...args) {
23095
+ this.host.progress?.(...args);
23096
+ }
23097
+
23098
+ /** Pauses the animation, if supported by the host. */
23099
+ pause() {
23100
+ this.host.pause?.();
23101
+ }
23102
+
23103
+ /** Resumes the animation, if supported by the host. */
23104
+ resume() {
23105
+ this.host.resume?.();
23106
+ }
23107
+
23108
+ /** Ends the animation successfully. */
23109
+ end() {
23110
+ this.host.end?.();
23111
+ this._finish(true);
23112
+ }
23113
+
23114
+ /** Cancels the animation. */
23115
+ cancel() {
23116
+ this.host.cancel?.();
23117
+ this._finish(false);
23118
+ }
23119
+
23120
+ /**
23121
+ * Marks the animation as complete on the next animation frame.
23122
+ * @param {boolean} [status=true] - True if successful, false if canceled.
23123
+ */
23124
+ complete(status = true) {
23125
+ if (this._state === RunnerState.INITIAL) {
23126
+ this._state = RunnerState.PENDING;
23127
+ this._schedule(() => this._finish(status));
23128
+ }
23129
+ }
23130
+
23131
+ /**
23132
+ * Returns a promise that resolves or rejects when the animation completes.
23133
+ * @returns {Promise<void>} Promise resolved on success or rejected on cancel.
23134
+ */
23135
+ getPromise() {
23136
+ if (!this._promise) {
23137
+ this._promise = new Promise((resolve, reject) => {
23138
+ this.done((success) => {
23139
+ if (success === false) reject();
23140
+ else resolve();
23141
+ });
23142
+ });
23143
+ }
23144
+ return this._promise;
23145
+ }
23146
+
23147
+ /** @inheritdoc */
23148
+ then(onFulfilled, onRejected) {
23149
+ return this.getPromise().then(onFulfilled, onRejected);
23150
+ }
23151
+
23152
+ /** @inheritdoc */
23153
+ catch(onRejected) {
23154
+ return this.getPromise().catch(onRejected);
23155
+ }
23156
+
23157
+ /** @inheritdoc */
23158
+ finally(onFinally) {
23159
+ return this.getPromise().finally(onFinally);
23160
+ }
23161
+
23162
+ /**
23163
+ * Completes the animation and invokes all done callbacks.
23164
+ * @private
23165
+ * @param {boolean} status - True if completed successfully, false if canceled.
23166
+ */
23167
+ _finish(status) {
23168
+ if (this._state === RunnerState.DONE) return;
23169
+ this._state = RunnerState.DONE;
23170
+
23171
+ const callbacks = this._doneCallbacks;
23172
+ for (let i = 0; i < callbacks.length; i++) {
23173
+ callbacks[i](status);
23174
+ }
23175
+ callbacks.length = 0;
23176
+ }
23177
+ }
23178
+
22238
23179
  const ANIMATE_TIMER_KEY = "$$animateCss";
22239
23180
 
22240
23181
  const ONE_SECOND = 1000;
@@ -22344,18 +23285,16 @@
22344
23285
  function AnimateCssProvider() {
22345
23286
  let activeClasses;
22346
23287
  this.$get = [
22347
- "$$AnimateRunner",
22348
23288
  "$$animateCache",
22349
23289
  "$$rAFScheduler",
22350
23290
 
22351
23291
  /**
22352
23292
  *
22353
- * @param {*} $$AnimateRunner
22354
23293
  * @param {*} $$animateCache
22355
23294
  * @param {import("./raf-scheduler").RafScheduler} $$rAFScheduler
22356
23295
  * @returns
22357
23296
  */
22358
- function ($$AnimateRunner, $$animateCache, $$rAFScheduler) {
23297
+ function ($$animateCache, $$rAFScheduler) {
22359
23298
  const applyAnimationClasses = applyAnimationClassesFactory();
22360
23299
 
22361
23300
  function computeCachedCssStyles(
@@ -22753,7 +23692,7 @@
22753
23692
  pause: null,
22754
23693
  };
22755
23694
 
22756
- runner = new $$AnimateRunner(runnerHost);
23695
+ runner = new AnimateRunner(runnerHost);
22757
23696
 
22758
23697
  waitUntilQuiet(start);
22759
23698
 
@@ -22852,7 +23791,7 @@
22852
23791
  }
22853
23792
 
22854
23793
  function closeAndReturnNoopAnimator() {
22855
- runner = new $$AnimateRunner({
23794
+ runner = new AnimateRunner({
22856
23795
  end: endFn,
22857
23796
  cancel: cancelFn,
22858
23797
  });
@@ -23117,6 +24056,7 @@
23117
24056
 
23118
24057
  const NG_ANIMATE_ATTR_NAME = "data-ng-animate";
23119
24058
  const NG_ANIMATE_PIN_DATA = "$ngAnimatePin";
24059
+
23120
24060
  AnimateQueueProvider.$inject = ["$animateProvider"];
23121
24061
  function AnimateQueueProvider($animateProvider) {
23122
24062
  const PRE_DIGEST_STATE = 1;
@@ -23240,24 +24180,16 @@
23240
24180
  $injectTokens.$rootScope,
23241
24181
  $injectTokens.$injector,
23242
24182
  $injectTokens.$$animation,
23243
- $injectTokens.$$AnimateRunner,
23244
24183
  $injectTokens.$templateRequest,
23245
24184
  /**
23246
24185
  *
23247
- * @param {import('../core/scope/scope.js').Scope} $rootScope
23248
- * @param {import('../core/di/internal-injector.js').InjectorService} $injector
24186
+ * @param {ng.RootScopeService} $rootScope
24187
+ * @param {ng.InjectorService} $injector
23249
24188
  * @param {*} $$animation
23250
- * @param {*} $$AnimateRunner
23251
- * @param {*} $templateRequest
23252
- * @returns
24189
+ * @param {ng.TemplateRequestService} $templateRequest
24190
+ * @returns {import("../queue/interface.ts").AnimateQueueService}
23253
24191
  */
23254
- function (
23255
- $rootScope,
23256
- $injector,
23257
- $$animation,
23258
- $$AnimateRunner,
23259
- $templateRequest,
23260
- ) {
24192
+ function ($rootScope, $injector, $$animation, $templateRequest) {
23261
24193
  const activeAnimationsLookup = new Map();
23262
24194
  const disabledElementsLookup = new Map();
23263
24195
 
@@ -23423,12 +24355,6 @@
23423
24355
  },
23424
24356
 
23425
24357
  pin(element, parentElement) {
23426
- assertArg(isElement(element), "element", "not an element");
23427
- assertArg(
23428
- isElement(parentElement),
23429
- "parentElement",
23430
- "not an element",
23431
- );
23432
24358
  setCacheData(element, NG_ANIMATE_PIN_DATA, parentElement);
23433
24359
  },
23434
24360
 
@@ -23465,7 +24391,7 @@
23465
24391
 
23466
24392
  // we create a fake runner with a working promise.
23467
24393
  // These methods will become available after the digest has passed
23468
- const runner = new $$AnimateRunner();
24394
+ const runner = new AnimateRunner();
23469
24395
 
23470
24396
  // this is used to trigger callbacks in postDigest mode
23471
24397
  const runInNextPostDigestOrNow = postDigestTaskFactory();
@@ -23769,6 +24695,18 @@
23769
24695
  }
23770
24696
  }
23771
24697
 
24698
+ /**
24699
+ * Closes and cleans up any child animations found under the given node.
24700
+ *
24701
+ * Looks for elements that have the NG_ANIMATE_ATTR_NAME attribute, checks their
24702
+ * animation state, ends running animations, and removes them from the
24703
+ * activeAnimationsLookup if appropriate.
24704
+ *
24705
+ * @param {Element | ParentNode} node
24706
+ * The DOM node whose descendant animations should be closed.
24707
+ *
24708
+ * @returns {void}
24709
+ */
23772
24710
  function closeChildAnimations(node) {
23773
24711
  const children = node.querySelectorAll(`[${NG_ANIMATE_ATTR_NAME}]`);
23774
24712
  children.forEach((child) => {
@@ -23910,14 +24848,12 @@
23910
24848
  function AnimateJsProvider($animateProvider) {
23911
24849
  this.$get = [
23912
24850
  $injectTokens.$injector,
23913
- "$$AnimateRunner",
23914
24851
  /**
23915
24852
  *
23916
24853
  * @param {ng.InjectorService} $injector
23917
- * @param {*} $$AnimateRunner
23918
24854
  * @returns
23919
24855
  */
23920
- function ($injector, $$AnimateRunner) {
24856
+ function ($injector) {
23921
24857
  const applyAnimationClasses = applyAnimationClassesFactory();
23922
24858
  // $animateJs(element, 'enter');
23923
24859
  return function (element, event, classes, options) {
@@ -24004,7 +24940,7 @@
24004
24940
  runner.end();
24005
24941
  } else {
24006
24942
  close();
24007
- runner = new $$AnimateRunner();
24943
+ runner = new AnimateRunner();
24008
24944
  runner.complete(true);
24009
24945
  }
24010
24946
  return runner;
@@ -24014,31 +24950,53 @@
24014
24950
  return runner;
24015
24951
  }
24016
24952
 
24017
- runner = new $$AnimateRunner();
24018
- let closeActiveAnimations;
24953
+ runner = new AnimateRunner();
24954
+
24019
24955
  const chain = [];
24020
24956
 
24021
24957
  if (before) {
24022
- chain.push((fn) => {
24023
- closeActiveAnimations = before(fn);
24958
+ const runnerBefore = new AnimateRunner({
24959
+ end(fn) {
24960
+ // call the before animation function, then mark runner done
24961
+ const endFn = before(fn) || (() => {});
24962
+ endFn();
24963
+ },
24964
+ cancel() {
24965
+ (before(true) || (() => {}))();
24966
+ },
24024
24967
  });
24968
+ chain.push(runnerBefore);
24025
24969
  }
24026
24970
 
24027
24971
  if (chain.length) {
24028
- chain.push((fn) => {
24029
- applyOptions();
24030
- fn(true);
24972
+ const runnerApplyOptions = new AnimateRunner({
24973
+ end(fn) {
24974
+ applyOptions();
24975
+ fn(true);
24976
+ },
24977
+ cancel() {
24978
+ applyOptions();
24979
+ },
24031
24980
  });
24981
+ chain.push(runnerApplyOptions);
24032
24982
  } else {
24033
24983
  applyOptions();
24034
24984
  }
24035
24985
 
24036
24986
  if (after) {
24037
- chain.push((fn) => {
24038
- closeActiveAnimations = after(fn);
24987
+ const runnerAfter = new AnimateRunner({
24988
+ end(fn) {
24989
+ const endFn = after(fn) || (() => {});
24990
+ endFn();
24991
+ },
24992
+ cancel() {
24993
+ (after(true) || (() => {}))();
24994
+ },
24039
24995
  });
24996
+ chain.push(runnerAfter);
24040
24997
  }
24041
24998
 
24999
+ // finally, set host for overall runner
24042
25000
  runner.setHost({
24043
25001
  end() {
24044
25002
  endAnimations();
@@ -24048,7 +25006,7 @@
24048
25006
  },
24049
25007
  });
24050
25008
 
24051
- $$AnimateRunner.chain(chain, onComplete);
25009
+ AnimateRunner.chain(chain, onComplete);
24052
25010
  return runner;
24053
25011
 
24054
25012
  function onComplete(success) {
@@ -24058,7 +25016,6 @@
24058
25016
 
24059
25017
  function endAnimations(cancelled) {
24060
25018
  if (!animationClosed) {
24061
- (closeActiveAnimations || (() => {}))(cancelled);
24062
25019
  onComplete(cancelled);
24063
25020
  }
24064
25021
  }
@@ -24097,7 +25054,7 @@
24097
25054
  value = value.start();
24098
25055
  }
24099
25056
 
24100
- if (value instanceof $$AnimateRunner) {
25057
+ if (value instanceof AnimateRunner) {
24101
25058
  value.done(onDone);
24102
25059
  } else if (isFunction(value)) {
24103
25060
  // optional onEnd / onCancel callback
@@ -24134,7 +25091,7 @@
24134
25091
  }
24135
25092
  };
24136
25093
 
24137
- runner = new $$AnimateRunner({
25094
+ runner = new AnimateRunner({
24138
25095
  end() {
24139
25096
  onAnimationComplete();
24140
25097
  },
@@ -24230,7 +25187,7 @@
24230
25187
  }
24231
25188
 
24232
25189
  if (runners.length) {
24233
- $$AnimateRunner.all(runners, callback);
25190
+ AnimateRunner.all(runners, callback);
24234
25191
  } else {
24235
25192
  callback();
24236
25193
  }
@@ -24290,25 +25247,17 @@
24290
25247
  this.$get = [
24291
25248
  $injectTokens.$rootScope,
24292
25249
  $injectTokens.$injector,
24293
- $injectTokens.$$AnimateRunner,
24294
25250
  $injectTokens.$$rAFScheduler,
24295
25251
  $injectTokens.$$animateCache,
24296
25252
  /**
24297
25253
  *
24298
25254
  * @param {ng.RootScopeService} $rootScope
24299
- * @param {import("../core/di/internal-injector").InjectorService} $injector
24300
- * @param {*} $$AnimateRunner
24301
- * @param {import("./raf-scheduler").RafScheduler} $$rAFScheduler
25255
+ * @param {ng.InjectorService} $injector
25256
+ * @param {import("./raf-scheduler.js").RafScheduler} $$rAFScheduler
24302
25257
  * @param {*} $$animateCache
24303
25258
  * @returns
24304
25259
  */
24305
- function (
24306
- $rootScope,
24307
- $injector,
24308
- $$AnimateRunner,
24309
- $$rAFScheduler,
24310
- $$animateCache,
24311
- ) {
25260
+ function ($rootScope, $injector, $$rAFScheduler, $$animateCache) {
24312
25261
  const animationQueue = [];
24313
25262
  const applyAnimationClasses = applyAnimationClassesFactory();
24314
25263
 
@@ -24409,7 +25358,7 @@
24409
25358
  // these runner methods will get later updated with the
24410
25359
  // methods leading into the driver's end/cancel methods
24411
25360
  // for now they just stop the animation from starting
24412
- const runner = new $$AnimateRunner({
25361
+ const runner = new AnimateRunner({
24413
25362
  end() {
24414
25363
  close();
24415
25364
  },
@@ -24423,9 +25372,9 @@
24423
25372
  return runner;
24424
25373
  }
24425
25374
 
24426
- let classes = mergeClasses$1(
25375
+ let classes = mergeClasses(
24427
25376
  element.getAttribute("class"),
24428
- mergeClasses$1(options.addClass, options.removeClass),
25377
+ mergeClasses(options.addClass, options.removeClass),
24429
25378
  );
24430
25379
  let { tempClasses } = options;
24431
25380
  if (tempClasses) {
@@ -24964,16 +25913,14 @@
24964
25913
  */
24965
25914
  this.$get = [
24966
25915
  "$animateCss",
24967
- "$$AnimateRunner",
24968
25916
  "$rootElement",
24969
25917
  /**
24970
25918
  *
24971
25919
  * @param {*} $animateCss
24972
- * @param {typeof import('./animate-runner.js').AnimateRunner} $$AnimateRunner
24973
25920
  * @param {Element} $rootElement
24974
25921
  * @returns
24975
25922
  */
24976
- function ($animateCss, $$AnimateRunner, $rootElement) {
25923
+ function ($animateCss, $rootElement) {
24977
25924
  const bodyNode = document.body;
24978
25925
  const rootNode = $rootElement;
24979
25926
 
@@ -25046,7 +25993,7 @@
25046
25993
  runner.complete();
25047
25994
  });
25048
25995
 
25049
- runner = new $$AnimateRunner({
25996
+ runner = new AnimateRunner({
25050
25997
  end: endFn,
25051
25998
  cancel: endFn,
25052
25999
  });
@@ -25157,12 +26104,12 @@
25157
26104
  animationRunners.push(animation.start());
25158
26105
  });
25159
26106
 
25160
- const runner = new $$AnimateRunner({
26107
+ const runner = new AnimateRunner({
25161
26108
  end: endFn,
25162
26109
  cancel: endFn, // CSS-driven animations cannot be cancelled, only ended
25163
26110
  });
25164
26111
 
25165
- $$AnimateRunner.all(animationRunners, (status) => {
26112
+ AnimateRunner.all(animationRunners, (status) => {
25166
26113
  runner.complete(status);
25167
26114
  });
25168
26115
 
@@ -25232,8 +26179,11 @@
25232
26179
  $$animationProvider.drivers.push("$$animateJsDriver");
25233
26180
  this.$get = [
25234
26181
  "$$animateJs",
25235
- "$$AnimateRunner",
25236
- function ($$animateJs, $$AnimateRunner) {
26182
+ /**
26183
+ *
26184
+ * @param {*} $$animateJs
26185
+ */
26186
+ function ($$animateJs) {
25237
26187
  return function initDriverFn(animationDetails) {
25238
26188
  if (animationDetails.from && animationDetails.to) {
25239
26189
  const fromAnimation = prepareAnimation(animationDetails.from);
@@ -25252,9 +26202,9 @@
25252
26202
  animationRunners.push(toAnimation.start());
25253
26203
  }
25254
26204
 
25255
- $$AnimateRunner.all(animationRunners, done);
26205
+ AnimateRunner.all(animationRunners, done);
25256
26206
 
25257
- const runner = new $$AnimateRunner({
26207
+ const runner = new AnimateRunner({
25258
26208
  end: endFnFactory(),
25259
26209
  cancel: endFnFactory(),
25260
26210
  });
@@ -26581,6 +27531,7 @@
26581
27531
  }
26582
27532
  return JSON.stringify(o, (key, value) => format(value)).replace(/\\"/g, '"');
26583
27533
  }
27534
+
26584
27535
  const stripLastPathElement = (str) => str.replace(/\/[^/]*$/, "");
26585
27536
  /**
26586
27537
  * Splits on a delimiter, but returns the delimiters in the array
@@ -34616,7 +35567,7 @@
34616
35567
  "$interpolate",
34617
35568
  /**
34618
35569
  * @param {*} $view
34619
- * @param {*} $animate
35570
+ * @param {ng.AnimateService} $animate
34620
35571
  * @param {*} $viewScroll
34621
35572
  * @param {*} $interpolate
34622
35573
  * @returns {import("../../interface.ts").Directive}
@@ -35044,447 +35995,31 @@
35044
35995
  };
35045
35996
  }
35046
35997
 
35047
- /**
35048
- * @param {"get" | "delete" | "post" | "put"} method - HTTP method applied to request
35049
- * @param {string} [attrOverride] - Custom name to use for the attribute
35050
- * @returns {ng.DirectiveFactory}
35051
- */
35052
- function defineDirective(method, attrOverride) {
35053
- const attrName =
35054
- attrOverride || "ng" + method.charAt(0).toUpperCase() + method.slice(1);
35055
- const directive = createHttpDirective(method, attrName);
35056
- directive["$inject"] = [
35057
- $injectTokens.$http,
35058
- $injectTokens.$compile,
35059
- $injectTokens.$log,
35060
- $injectTokens.$parse,
35061
- $injectTokens.$state,
35062
- $injectTokens.$sse,
35063
- $injectTokens.$animate,
35064
- ];
35065
- return directive;
35066
- }
35067
-
35068
- /** @type {ng.DirectiveFactory} */
35069
- const ngGetDirective = defineDirective("get");
35070
-
35071
- /** @type {ng.DirectiveFactory} */
35072
- const ngDeleteDirective = defineDirective("delete");
35073
-
35074
- /** @type {ng.DirectiveFactory} */
35075
- const ngPostDirective = defineDirective("post");
35076
-
35077
- /** @type {ng.DirectiveFactory} */
35078
- const ngPutDirective = defineDirective("put");
35079
-
35080
- /** @type {ng.DirectiveFactory} */
35081
- const ngSseDirective = defineDirective("get", "ngSse");
35082
-
35083
- /**
35084
- * Selects DOM event to listen for based on the element type.
35085
- *
35086
- * @param {Element} element - The DOM element to inspect.
35087
- * @returns {"click" | "change" | "submit"} The name of the event to listen for.
35088
- */
35089
- function getEventNameForElement(element) {
35090
- const tag = element.tagName.toLowerCase();
35091
- if (["input", "textarea", "select"].includes(tag)) {
35092
- return "change";
35093
- } else if (tag === "form") {
35094
- return "submit";
35095
- }
35096
- return "click";
35097
- }
35098
-
35099
- /**
35100
- * Creates an HTTP directive factory that supports GET, DELETE, POST, PUT.
35101
- *
35102
- * @param {"get" | "delete" | "post" | "put"} method - HTTP method to use.
35103
- * @param {string} attrName - Attribute name containing the URL.
35104
- * @returns {ng.DirectiveFactory}
35105
- */
35106
- function createHttpDirective(method, attrName) {
35107
- let content = undefined;
35108
-
35109
- /**
35110
- * @param {ng.HttpService} $http
35111
- * @param {ng.CompileService} $compile
35112
- * @param {ng.LogService} $log
35113
- * @param {ng.ParseService} $parse
35114
- * @param {ng.StateService} $state
35115
- * @param {ng.SseService} $sse
35116
- * @returns {ng.Directive}
35117
- */
35118
- return function ($http, $compile, $log, $parse, $state, $sse, $animate) {
35119
- /**
35120
- * Handles DOM manipulation based on a swap strategy and server-rendered HTML.
35121
- *
35122
- * @param {string | Object} html - The HTML string or object returned from the server.
35123
- * @param {import("./interface.ts").SwapModeType} swap
35124
- * @param {ng.Scope} scope
35125
- * @param {ng.Attributes} attrs
35126
- * @param {Element} element
35127
- */
35128
- function handleSwapResponse(html, swap, scope, attrs, element) {
35129
- let animationEnabled = false;
35130
- if (attrs.animate) {
35131
- animationEnabled = true;
35132
- }
35133
- let nodes = [];
35134
- if (!["textcontent", "delete", "none"].includes(swap)) {
35135
- if (!html) return;
35136
- const compiled = $compile(html)(scope);
35137
- nodes =
35138
- compiled instanceof DocumentFragment
35139
- ? Array.from(compiled.childNodes)
35140
- : [compiled];
35141
- }
35142
-
35143
- const targetSelector = attrs["target"];
35144
- const target = targetSelector
35145
- ? document.querySelector(targetSelector)
35146
- : element;
35147
-
35148
- if (!target) {
35149
- $log.warn(`${attrName}: target "${targetSelector}" not found`);
35150
- return;
35151
- }
35152
-
35153
- switch (swap) {
35154
- case "innerHTML":
35155
- if (animationEnabled) {
35156
- if (content) {
35157
- $animate.leave(content).done(() => {
35158
- content = nodes[0];
35159
- $animate.enter(nodes[0], target);
35160
- scope.$flushQueue();
35161
- });
35162
- scope.$flushQueue();
35163
- } else {
35164
- content = nodes[0];
35165
- $animate.enter(nodes[0], target);
35166
- scope.$flushQueue();
35167
- }
35168
- } else {
35169
- target.replaceChildren(...nodes);
35170
- }
35171
- break;
35172
-
35173
- case "outerHTML": {
35174
- const parent = target.parentNode;
35175
- if (!parent) return;
35176
- const frag = document.createDocumentFragment();
35177
- nodes.forEach((n) => frag.appendChild(n));
35178
- if (animationEnabled) {
35179
- const placeholder = document.createComment("placeholder");
35180
- target.parentNode.insertBefore(placeholder, target.nextSibling);
35181
- $animate.leave(target).done(() => {
35182
- const insertedNodes = Array.from(frag.childNodes);
35183
- insertedNodes.forEach((n) =>
35184
- $animate.enter(n, parent, placeholder),
35185
- );
35186
- content = insertedNodes;
35187
- scope.$flushQueue();
35188
- });
35189
- scope.$flushQueue();
35190
- } else {
35191
- parent.replaceChild(frag, target);
35192
- }
35193
- break;
35194
- }
35195
-
35196
- case "textContent":
35197
- target.textContent = html;
35198
- break;
35199
-
35200
- case "beforebegin":
35201
- nodes.forEach((node) => target.parentNode.insertBefore(node, target));
35202
- break;
35203
-
35204
- case "afterbegin":
35205
- nodes
35206
- .slice()
35207
- .reverse()
35208
- .forEach((node) => target.insertBefore(node, target.firstChild));
35209
- break;
35210
-
35211
- case "beforeend":
35212
- nodes.forEach((node) => target.appendChild(node));
35213
- break;
35214
-
35215
- case "afterend":
35216
- nodes
35217
- .slice()
35218
- .reverse()
35219
- .forEach((node) =>
35220
- target.parentNode.insertBefore(node, target.nextSibling),
35221
- );
35222
- break;
35223
-
35224
- case "delete":
35225
- target.remove();
35226
- break;
35227
-
35228
- case "none":
35229
- break;
35230
-
35231
- default:
35232
- target.replaceChildren(...nodes);
35233
- break;
35234
- }
35235
- }
35236
-
35237
- /**
35238
- * Collects form data from the element or its associated form.
35239
- *
35240
- * @param {HTMLElement} element
35241
- * @returns {Object<string, any>}
35242
- */
35243
- function collectFormData(element) {
35244
- /** @type {HTMLFormElement | null} */
35245
- let form = null;
35246
-
35247
- const tag = element.tagName.toLowerCase();
35248
-
35249
- if (tag === "form") {
35250
- form = /** @type {HTMLFormElement} */ (element);
35251
- } else if ("form" in element && element.form) {
35252
- form = /** @type {HTMLFormElement} */ (element.form);
35253
- } else if (element.hasAttribute("form")) {
35254
- const formId = element.getAttribute("form");
35255
- if (formId) {
35256
- const maybeForm = document.getElementById(formId);
35257
- if (maybeForm && maybeForm.tagName.toLowerCase() === "form") {
35258
- form = /** @type {HTMLFormElement} */ (maybeForm);
35259
- }
35260
- }
35261
- }
35262
-
35263
- if (!form) {
35264
- if (
35265
- "name" in element &&
35266
- typeof element.name === "string" &&
35267
- element.name.length > 0
35268
- ) {
35269
- if (
35270
- element instanceof HTMLInputElement ||
35271
- element instanceof HTMLTextAreaElement ||
35272
- element instanceof HTMLSelectElement
35273
- ) {
35274
- const key = element.name;
35275
- const value = element.value;
35276
- return { [key]: value };
35277
- }
35278
- }
35279
- return {};
35280
- }
35281
-
35282
- const formData = new FormData(form);
35283
- const data = {};
35284
- formData.forEach((value, key) => {
35285
- data[key] = value;
35286
- });
35287
- return data;
35288
- }
35289
-
35290
- return {
35291
- restrict: "A",
35292
- link(scope, element, attrs) {
35293
- const eventName = attrs.trigger || getEventNameForElement(element);
35294
- const tag = element.tagName.toLowerCase();
35295
-
35296
- if (isDefined(attrs.latch)) {
35297
- attrs.$observe(
35298
- "latch",
35299
- callBackAfterFirst(() =>
35300
- element.dispatchEvent(new Event(eventName)),
35301
- ),
35302
- );
35303
- }
35304
-
35305
- let throttled = false;
35306
- let intervalId;
35307
-
35308
- if (isDefined(attrs["interval"])) {
35309
- element.dispatchEvent(new Event(eventName));
35310
- intervalId = setInterval(
35311
- () => element.dispatchEvent(new Event(eventName)),
35312
- parseInt(attrs.interval) || 1000,
35313
- );
35314
- }
35315
-
35316
- element.addEventListener(eventName, async (event) => {
35317
- if (/** @type {HTMLButtonElement} */ (element).disabled) return;
35318
- if (tag === "form") event.preventDefault();
35319
- const swap = attrs.swap || "innerHTML";
35320
- const url = attrs[attrName];
35321
- if (!url) {
35322
- $log.warn(`${attrName}: no URL specified`);
35323
- return;
35324
- }
35325
-
35326
- const handler = (res) => {
35327
- if (isDefined(attrs.loading)) {
35328
- attrs.$set("loading", false);
35329
- }
35330
-
35331
- if (isDefined(attrs.loadingClass)) {
35332
- attrs.$removeClass(attrs.loadingClass);
35333
- }
35334
-
35335
- const html = res.data;
35336
- if (200 <= res.status && res.status <= 299) {
35337
- if (isDefined(attrs.success)) {
35338
- $parse(attrs.success)(scope, { $res: html });
35339
- }
35340
-
35341
- if (isDefined(attrs.stateSuccess)) {
35342
- $state.go(attrs.stateSuccess);
35343
- }
35344
- } else if (400 <= res.status && res.status <= 599) {
35345
- if (isDefined(attrs.error)) {
35346
- $parse(attrs.error)(scope, { $res: html });
35347
- }
35348
-
35349
- if (isDefined(attrs.stateError)) {
35350
- $state.go(attrs.stateError);
35351
- }
35352
- }
35353
-
35354
- if (isObject(html)) {
35355
- if (attrs.target) {
35356
- scope.$eval(`${attrs.target} = ${JSON.stringify(html)}`);
35357
- } else {
35358
- scope.$merge(html);
35359
- }
35360
- } else if (isString(html)) {
35361
- handleSwapResponse(html, swap, scope, attrs, element);
35362
- }
35363
- };
35364
-
35365
- if (isDefined(attrs.delay)) {
35366
- await wait(parseInt(attrs.delay) | 0);
35367
- }
35368
-
35369
- if (throttled) return;
35370
-
35371
- if (isDefined(attrs.throttle)) {
35372
- throttled = true;
35373
- attrs.$set("throttled", true);
35374
- setTimeout(() => {
35375
- attrs.$set("throttled", false);
35376
- throttled = false;
35377
- }, parseInt(attrs.throttle));
35378
- }
35379
-
35380
- if (isDefined(attrs["loading"])) {
35381
- attrs.$set("loading", true);
35382
- }
35383
-
35384
- if (isDefined(attrs["loadingClass"])) {
35385
- attrs.$addClass(attrs.loadingClass);
35386
- }
35387
-
35388
- if (method === "post" || method === "put") {
35389
- let data;
35390
- const config = {};
35391
- if (attrs.enctype) {
35392
- config.headers = {
35393
- "Content-Type": attrs["enctype"],
35394
- };
35395
- data = toKeyValue(collectFormData(element));
35396
- } else {
35397
- data = collectFormData(element);
35398
- }
35399
- $http[method](url, data, config).then(handler).catch(handler);
35400
- } else {
35401
- if (method === "get" && attrs.ngSse) {
35402
- const sseUrl = url;
35403
- const config = {
35404
- withCredentials: attrs.withCredentials === "true",
35405
- transformMessage: (data) => {
35406
- try {
35407
- return JSON.parse(data);
35408
- } catch {
35409
- return data;
35410
- }
35411
- },
35412
- onOpen: () => {
35413
- $log.info(`${attrName}: SSE connection opened to ${sseUrl}`);
35414
- if (isDefined(attrs.loading)) attrs.$set("loading", false);
35415
- if (isDefined(attrs.loadingClass))
35416
- attrs.$removeClass(attrs.loadingClass);
35417
- },
35418
- onMessage: (data) => {
35419
- const res = { status: 200, data };
35420
- handler(res);
35421
- },
35422
- onError: (err) => {
35423
- $log.error(`${attrName}: SSE error`, err);
35424
- const res = { status: 500, data: err };
35425
- handler(res);
35426
- },
35427
- onReconnect: (count) => {
35428
- $log.info(`ngSse: reconnected ${count} time(s)`);
35429
- if (attrs.onReconnect)
35430
- $parse(attrs.onReconnect)(scope, { $count: count });
35431
- },
35432
- };
35433
-
35434
- const source = $sse(sseUrl, config);
35435
-
35436
- scope.$on("$destroy", () => {
35437
- $log.info(`${attrName}: closing SSE connection`);
35438
- source.close();
35439
- });
35440
- } else {
35441
- $http[method](url).then(handler).catch(handler);
35442
- }
35443
- }
35444
- });
35445
-
35446
- if (intervalId) {
35447
- scope.$on("$destroy", () => clearInterval(intervalId));
35448
- }
35449
-
35450
- if (eventName == "load") {
35451
- element.dispatchEvent(new Event("load"));
35452
- }
35453
- },
35454
- };
35455
- };
35456
- }
35457
-
35458
35998
  ngInjectDirective.$inject = [$injectTokens.$log, $injectTokens.$injector];
35459
35999
 
35460
36000
  /**
35461
36001
  * @param {ng.LogService} $log
35462
36002
  * @param {ng.InjectorService} $injector
35463
- * @returns {import('interface.ts').Directive}
36003
+ * @returns {ng.Directive}
35464
36004
  */
35465
36005
  function ngInjectDirective($log, $injector) {
35466
36006
  return {
35467
36007
  restrict: "A",
35468
36008
  link(scope, _element, attrs) {
35469
- const expr = attrs["ngInject"];
35470
-
36009
+ const expr = attrs.ngInject;
35471
36010
  if (!expr) return;
35472
- // Match any identifier that starts with $, or ends with Service/Factory
35473
- // Example matches: $http, userService, authFactory
35474
- const replacedExpr = expr.replace(
35475
- /(\$[\w]+|[\w]+(?:Service|Factory))/g,
35476
- (match, name) => {
35477
- try {
35478
- const service = $injector.get(name);
35479
- scope.$target[name] = service;
35480
- return name;
35481
- } catch {
35482
- $log.warn(`Injectable ${name} not found in $injector`);
35483
- return match;
35484
- }
35485
- },
35486
- );
35487
- scope.$apply(replacedExpr);
36011
+ const tokens = expr
36012
+ .split(";")
36013
+ .map((s) => s.trim())
36014
+ .filter(Boolean);
36015
+
36016
+ for (const name of tokens) {
36017
+ if ($injector.has(name)) {
36018
+ scope[name] = $injector.get(name);
36019
+ } else {
36020
+ $log.warn(`Injectable ${name} not found in $injector`);
36021
+ }
36022
+ }
35488
36023
  },
35489
36024
  };
35490
36025
  }
@@ -35553,13 +36088,13 @@
35553
36088
  };
35554
36089
  }
35555
36090
 
35556
- /**
35557
- * Returns the $sse service function
35558
- * @returns {ng.SseService}
35559
- */
35560
36091
  $get = [
35561
36092
  $injectTokens.$log,
35562
- /** @param {ng.LogService} log */
36093
+ /**
36094
+ * Returns the $sse service function
36095
+ * @param {ng.LogService} log
36096
+ * @returns {ng.SseService}
36097
+ */
35563
36098
  (log) => {
35564
36099
  this.$log = log;
35565
36100
  return (url, config = {}) => {
@@ -35654,7 +36189,7 @@
35654
36189
  es.close();
35655
36190
  },
35656
36191
  connect() {
35657
- if (closed == false) {
36192
+ if (closed === false) {
35658
36193
  close();
35659
36194
  }
35660
36195
  connect();
@@ -35716,252 +36251,35 @@
35716
36251
  };
35717
36252
  }
35718
36253
 
35719
- ngWorkerDirective.$inject = ["$worker", $injectTokens.$parse, $injectTokens.$log];
35720
36254
  /**
35721
- * ngWorker directive factory
35722
- * Usage: <div ng-worker="workerName" data-params="{{ expression }}" data-on-result="callback($result)"></div>
36255
+ * @return {ng.Directive}
35723
36256
  */
35724
- function ngWorkerDirective($worker, $parse, $log) {
36257
+ function ngWasmDirective() {
35725
36258
  return {
35726
- restrict: "A",
35727
- link(scope, element, attrs) {
35728
- const workerName = attrs.ngWorker;
35729
- if (!workerName) {
35730
- $log.warn("ngWorker: missing worker name");
35731
- return;
35732
- }
35733
-
35734
- const eventName = attrs.trigger || getEventNameForElement(element);
35735
-
35736
- let throttled = false;
35737
- let intervalId;
35738
-
35739
- if (isDefined(attrs.latch)) {
35740
- attrs.$observe(
35741
- "latch",
35742
- callBackAfterFirst(() => element.dispatchEvent(new Event(eventName))),
35743
- );
35744
- }
35745
-
35746
- if (isDefined(attrs.interval)) {
35747
- element.dispatchEvent(new Event(eventName));
35748
- intervalId = setInterval(
35749
- () => element.dispatchEvent(new Event(eventName)),
35750
- parseInt(attrs.interval) || 1000,
35751
- );
35752
- }
35753
-
35754
- const worker = $worker(workerName, {
35755
- onMessage: (result) => {
35756
- if (isDefined(attrs.dataOnResult)) {
35757
- $parse(attrs.dataOnResult)(scope, { $result: result });
35758
- } else {
35759
- const swap = attrs.swap || "innerHTML";
35760
- handleSwap(result, swap, element);
35761
- }
35762
- },
35763
- onError: (err) => {
35764
- $log.error(`[ng-worker:${workerName}]`, err);
35765
- if (isDefined(attrs.dataOnError)) {
35766
- $parse(attrs.dataOnError)(scope, { $error: err });
35767
- } else {
35768
- element.textContent = "Error";
35769
- }
35770
- },
35771
- });
35772
-
35773
- element.addEventListener(eventName, async () => {
35774
- if (element.disabled) return;
35775
-
35776
- if (isDefined(attrs.delay)) {
35777
- await wait(parseInt(attrs.delay) || 0);
35778
- }
35779
-
35780
- if (throttled) return;
35781
-
35782
- if (isDefined(attrs.throttle)) {
35783
- throttled = true;
35784
- attrs.$set("throttled", true);
35785
- setTimeout(() => {
35786
- attrs.$set("throttled", false);
35787
- throttled = false;
35788
- }, parseInt(attrs.throttle));
35789
- }
35790
-
35791
- let params;
35792
- try {
35793
- params = attrs.params ? scope.$eval(attrs.params) : undefined;
35794
- } catch (err) {
35795
- $log.error("ngWorker: failed to evaluate data-params", err);
35796
- params = undefined;
35797
- }
35798
-
35799
- worker.post(params);
35800
- });
35801
-
35802
- if (intervalId) {
35803
- scope.$on("$destroy", () => clearInterval(intervalId));
35804
- }
35805
-
35806
- if (eventName === "load") {
35807
- element.dispatchEvent(new Event("load"));
35808
- }
36259
+ async link($scope, _, $attrs) {
36260
+ $scope.$target[$attrs.as || "wasm"] = (
36261
+ await instantiateWasm($attrs.src)
36262
+ ).exports;
35809
36263
  },
35810
36264
  };
35811
36265
  }
35812
36266
 
35813
36267
  /**
35814
- * Swap result into DOM based on strategy
35815
- */
35816
- function handleSwap(result, swap, element) {
35817
- switch (swap) {
35818
- case "outerHTML": {
35819
- const parent = element.parentNode;
35820
- if (!parent) return;
35821
- const temp = document.createElement("div");
35822
- temp.innerHTML = result;
35823
- parent.replaceChild(temp.firstChild, element);
35824
- break;
35825
- }
35826
- case "textContent":
35827
- element.textContent = result;
35828
- break;
35829
- case "beforebegin":
35830
- element.insertAdjacentHTML("beforebegin", result);
35831
- break;
35832
- case "afterbegin":
35833
- element.insertAdjacentHTML("afterbegin", result);
35834
- break;
35835
- case "beforeend":
35836
- element.insertAdjacentHTML("beforeend", result);
35837
- break;
35838
- case "afterend":
35839
- element.insertAdjacentHTML("afterend", result);
35840
- break;
35841
- case "innerHTML":
35842
- default:
35843
- element.innerHTML = result;
35844
- break;
35845
- }
35846
- }
35847
-
35848
- /**
35849
- * Worker Provider
35850
- *
35851
- * Usage:
35852
- * const worker = $worker('./math.worker.js', {
35853
- * onMessage: (data) => console.log('Result:', data),
35854
- * onError: (err) => console.error('Worker error:', err),
35855
- * autoTerminate: false,
35856
- * transformMessage: (d) => d,
35857
- * });
35858
- *
35859
- * worker.post({ action: 'fib', n: 20 });
35860
- * worker.terminate();
36268
+ * @return {ng.Directive}
35861
36269
  */
35862
- class WorkerProvider {
35863
- /**
35864
- * @type {ng.LogService}
35865
- */
35866
- $log;
35867
- constructor() {
35868
- /**
35869
- * Optional provider-level defaults
35870
- * @type {ng.WorkerConfig}
35871
- */
35872
- this.defaults = {
35873
- autoTerminate: false,
35874
- transformMessage(data) {
35875
- try {
35876
- return JSON.parse(data);
35877
- } catch {
35878
- return data;
35879
- }
35880
- },
35881
- };
35882
- }
35883
-
35884
- /**
35885
- * Returns the $worker service function
35886
- * @returns {ng.WorkerService}
35887
- */
35888
- $get = [
35889
- $injectTokens.$log,
35890
- /** @param {ng.LogService} log */
35891
- (log) => {
35892
- this.$log = log;
35893
- return (scriptPath, config = {}) => {
35894
- const merged = { ...this.defaults, ...config };
35895
- return this.#createWorker(scriptPath, merged);
35896
- };
36270
+ function ngScopeDirective() {
36271
+ return {
36272
+ scope: false,
36273
+ async link($scope, _, $attrs) {
36274
+ $scope.$scopename = $attrs.ngScope;
35897
36275
  },
35898
- ];
35899
-
35900
- /**
35901
- * Creates a managed Web Worker instance
35902
- * @param {string | URL} scriptPath
35903
- * @param {ng.WorkerConfig} config
35904
- * @returns {import("./interface.ts").WorkerConnection}
35905
- */
35906
- #createWorker(scriptPath, config) {
35907
- if (!scriptPath) throw new Error("Worker script path required");
35908
-
35909
- let worker = new Worker(scriptPath, { type: "module" });
35910
- let terminated = false;
35911
-
35912
- const reconnect = () => {
35913
- if (terminated) return;
35914
- this.$log.info("Worker: restarting...");
35915
- worker.terminate();
35916
- worker = new Worker(scriptPath, { type: "module" });
35917
- wire(worker);
35918
- };
35919
-
35920
- const wire = (w) => {
35921
- w.onmessage = (e) => {
35922
- let data = e.data;
35923
- try {
35924
- data = config.transformMessage ? config.transformMessage(data) : data;
35925
- } catch {
35926
- /* no-op */
35927
- }
35928
- config.onMessage?.(data, e);
35929
- };
35930
-
35931
- w.onerror = (err) => {
35932
- config.onError?.(err);
35933
- if (config.autoRestart) reconnect();
35934
- };
35935
- };
35936
-
35937
- wire(worker);
35938
- let that = this;
35939
- return {
35940
- post(data) {
35941
- if (terminated) return that.$log.warn("Worker already terminated");
35942
- try {
35943
- worker.postMessage(data);
35944
- } catch (err) {
35945
- that.$log.error("Worker post failed", err);
35946
- }
35947
- },
35948
- terminate() {
35949
- terminated = true;
35950
- worker.terminate();
35951
- },
35952
- restart() {
35953
- if (terminated)
35954
- return that.$log.warn("Worker cannot restart after terminate");
35955
- reconnect();
35956
- },
35957
- };
35958
- }
36276
+ };
35959
36277
  }
35960
36278
 
35961
36279
  /**
35962
36280
  * Initializes core `ng` module.
35963
- * @param {import('./angular.js').Angular} angular
35964
- * @returns {import('./core/di/ng-module.js').NgModule} `ng` module
36281
+ * @param {ng.Angular} angular
36282
+ * @returns {ng.NgModule} `ng` module
35965
36283
  */
35966
36284
  function registerNgModule(angular) {
35967
36285
  return angular
@@ -35970,14 +36288,14 @@
35970
36288
  [],
35971
36289
  [
35972
36290
  $injectTokens.$provide,
35973
- /** @param {import("./interface.ts").Provider} $provide */
36291
+ /** @param {ng.ProvideService} $provide */
35974
36292
  ($provide) => {
35975
36293
  // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
35976
36294
  $provide.provider({
35977
36295
  $$sanitizeUri: SanitizeUriProvider,
35978
36296
  });
35979
- $provide.value("$window", window);
35980
- $provide.value("$document", document);
36297
+ $provide.value($injectTokens.$window, window);
36298
+ $provide.value($injectTokens.$document, document);
35981
36299
  $provide
35982
36300
  .provider($injectTokens.$compile, CompileProvider)
35983
36301
  .directive({
@@ -35990,6 +36308,7 @@
35990
36308
  ngBind: ngBindDirective,
35991
36309
  ngBindHtml: ngBindHtmlDirective,
35992
36310
  ngBindTemplate: ngBindTemplateDirective,
36311
+ ngChannel: ngChannelDirective,
35993
36312
  ngClass: ngClassDirective,
35994
36313
  ngClassEven: ngClassEvenDirective,
35995
36314
  ngClassOdd: ngClassOddDirective,
@@ -36036,12 +36355,15 @@
36036
36355
  ngValue: ngValueDirective,
36037
36356
  ngModelOptions: ngModelOptionsDirective,
36038
36357
  ngViewport: ngViewportDirective,
36358
+ ngWasm: ngWasmDirective,
36039
36359
  ngWorker: ngWorkerDirective,
36360
+ ngScope: ngScopeDirective,
36040
36361
  })
36041
36362
  .directive({
36042
36363
  input: hiddenInputBrowserCacheDirective,
36043
36364
  ngAnimateSwap: ngAnimateSwapDirective,
36044
36365
  ngAnimateChildren: $$AnimateChildrenDirective,
36366
+ // aria directives
36045
36367
  ngChecked: ngCheckedAriaDirective,
36046
36368
  ngClick: ngClickAriaDirective,
36047
36369
  ngDblclick: ngDblclickAriaDirective,
@@ -36053,12 +36375,12 @@
36053
36375
  ngReadonly: ngReadonlyAriaDirective,
36054
36376
  ngRequired: ngRequiredAriaDirective,
36055
36377
  ngValue: ngValueAriaDirective,
36378
+ // router directives
36056
36379
  ngSref: $StateRefDirective,
36057
36380
  ngSrefActive: $StateRefActiveDirective,
36058
36381
  ngSrefActiveEq: $StateRefActiveDirective,
36059
36382
  ngState: $StateRefDynamicDirective,
36060
36383
  ngView: ngView,
36061
- ngChannel: ngChannelDirective,
36062
36384
  })
36063
36385
  .directive({
36064
36386
  ngView: $ViewDirectiveFill,
@@ -36076,8 +36398,6 @@
36076
36398
  $$animateJsDriver: AnimateJsDriverProvider,
36077
36399
  $$animateCache: AnimateCacheProvider,
36078
36400
  $$animateQueue: AnimateQueueProvider,
36079
- $$AnimateRunner: AnimateRunnerFactoryProvider,
36080
- $$animateAsyncRun: AnimateAsyncRunFactoryProvider,
36081
36401
  $controller: ControllerProvider,
36082
36402
  $exceptionHandler: ExceptionHandlerProvider,
36083
36403
  $filter: FilterProvider,
@@ -36104,7 +36424,6 @@
36104
36424
  $url: UrlService,
36105
36425
  $stateRegistry: StateRegistryProvider,
36106
36426
  $eventBus: PubSubProvider,
36107
- $worker: WorkerProvider,
36108
36427
  });
36109
36428
  },
36110
36429
  ],
@@ -36130,20 +36449,36 @@
36130
36449
  constructor() {
36131
36450
  this.$cache = Cache;
36132
36451
 
36133
- /** @type {import('./services/pubsub/pubsub.js').PubSub} */
36452
+ /** @type {ng.PubSubService} */
36134
36453
  this.$eventBus = EventBus;
36135
36454
 
36136
36455
  /**
36137
36456
  * @type {string} `version` from `package.json`
36138
36457
  */
36139
- this.version = "0.10.0"; //inserted via rollup plugin
36458
+ this.version = "0.12.0"; //inserted via rollup plugin
36140
36459
 
36141
36460
  /** @type {!Array<string|any>} */
36142
36461
  this.bootsrappedModules = [];
36143
36462
 
36463
+ /**
36464
+ * Gets the controller instance for a given element, if exists. Defaults to "ngControllerController"
36465
+ *
36466
+ * @type {(element: Element, name: string?) => ng.Scope|undefined}
36467
+ */
36144
36468
  this.getController = getController;
36469
+
36470
+ /**
36471
+ * Return instance of InjectorService attached to element
36472
+ * @type {(Element) => ng.InjectorService}
36473
+ */
36145
36474
  this.getInjector = getInjector;
36475
+
36476
+ /**
36477
+ * Gets scope for a given element.
36478
+ * @type {(Element) => ng.Scope}
36479
+ */
36146
36480
  this.getScope = getScope;
36481
+
36147
36482
  this.errorHandlingConfig = errorHandlingConfig;
36148
36483
  this.$t = $injectTokens;
36149
36484
 
@@ -36151,6 +36486,70 @@
36151
36486
  registerNgModule(this);
36152
36487
  }
36153
36488
 
36489
+ /**
36490
+ *
36491
+ * The `angular.module` is a global place for creating, registering and retrieving AngularTS
36492
+ * modules.
36493
+ * All modules (AngularTS core or 3rd party) that should be available to an application must be
36494
+ * registered using this mechanism.
36495
+ *
36496
+ * Passing one argument retrieves an existing {@link ng.NgModule},
36497
+ * whereas passing more than one argument creates a new {@link ng.NgModule}
36498
+ *
36499
+ *
36500
+ * # Module
36501
+ *
36502
+ * A module is a collection of services, directives, controllers, filters, workers, WebAssembly modules, and configuration information.
36503
+ * `angular.module` is used to configure the {@link auto.$injector $injector}.
36504
+ *
36505
+ * ```js
36506
+ * // Create a new module
36507
+ * let myModule = angular.module('myModule', []);
36508
+ *
36509
+ * // register a new service
36510
+ * myModule.value('appName', 'MyCoolApp');
36511
+ *
36512
+ * // configure existing services inside initialization blocks.
36513
+ * myModule.config(['$locationProvider', function($locationProvider) {
36514
+ * // Configure existing providers
36515
+ * $locationProvider.hashPrefix('!');
36516
+ * }]);
36517
+ * ```
36518
+ *
36519
+ * Then you can create an injector and load your modules like this:
36520
+ *
36521
+ * ```js
36522
+ * let injector = angular.injector(['ng', 'myModule'])
36523
+ * ```
36524
+ *
36525
+ * However it's more likely that you'll just use
36526
+ * `ng-app` directive or
36527
+ * {@link bootstrap} to simplify this process for you.
36528
+ *
36529
+ * @param {string} name The name of the module to create or retrieve.
36530
+ * @param {Array.<string>} [requires] If specified then new module is being created. If
36531
+ * unspecified then the module is being retrieved for further configuration.
36532
+ * @param {ng.Injectable<any>} [configFn] Optional configuration function for the module that gets
36533
+ * passed to {@link NgModule.config NgModule.config()}.
36534
+ * @returns {NgModule} A newly registered module.
36535
+ */
36536
+ module(name, requires, configFn) {
36537
+ assertNotHasOwnProperty(name, "module");
36538
+ if (requires && hasOwn(modules, name)) {
36539
+ modules[name] = null; // force ensure to recreate the module
36540
+ }
36541
+ return ensure(modules, name, () => {
36542
+ if (!requires) {
36543
+ throw $injectorMinErr(
36544
+ "nomod",
36545
+ "Module '{0}' is not available. Possibly misspelled or not loaded",
36546
+ name,
36547
+ );
36548
+ }
36549
+ return new NgModule(name, requires, configFn);
36550
+ });
36551
+ }
36552
+
36154
36553
  /**
36155
36554
  * Use this function to manually start up AngularTS application.
36156
36555
  *
@@ -36235,8 +36634,10 @@
36235
36634
  * @param {ng.InjectorService} $injector
36236
36635
  */
36237
36636
  (scope, el, compile, $injector) => {
36637
+ this.$rootScope = scope;
36238
36638
  // ng-route deps
36239
- this.$injector = $injector;
36639
+ this.$injector = $injector; // TODO refactor away as this as this prevents multiple apps from being used
36640
+
36240
36641
  setCacheData(el, "$injector", $injector);
36241
36642
 
36242
36643
  const compileFn = compile(el);
@@ -36317,70 +36718,30 @@
36317
36718
  }
36318
36719
 
36319
36720
  /**
36721
+ * Retrieves a scope by its registered name and returns its Proxy wrapper.
36320
36722
  *
36321
- * The `angular.module` is a global place for creating, registering and retrieving AngularTS
36322
- * modules.
36323
- * All modules (AngularTS core or 3rd party) that should be available to an application must be
36324
- * registered using this mechanism.
36325
- *
36326
- * Passing one argument retrieves an existing {@link import('./interface.ts').Module},
36327
- * whereas passing more than one argument creates a new {@link import('./interface.ts').Module}
36723
+ * Internally, this walks down the `Scope` tree starting from `$rootScope`
36724
+ * and checks for a matching `$scopename` property. The `$scopename` property
36725
+ * may be defined statically on controllers using `as` syntax, assigned via the `ngScope` directive,
36726
+ * or defined on `$scope` injectable.
36328
36727
  *
36329
- *
36330
- * # Module
36331
- *
36332
- * A module is a collection of services, directives, controllers, filters, and configuration information.
36333
- * `angular.module` is used to configure the {@link auto.$injector $injector}.
36334
- *
36335
- * ```js
36336
- * // Create a new module
36337
- * let myModule = angular.module('myModule', []);
36338
- *
36339
- * // register a new service
36340
- * myModule.value('appName', 'MyCoolApp');
36341
- *
36342
- * // configure existing services inside initialization blocks.
36343
- * myModule.config(['$locationProvider', function($locationProvider) {
36344
- * // Configure existing providers
36345
- * $locationProvider.hashPrefix('!');
36346
- * }]);
36347
- * ```
36348
- *
36349
- * Then you can create an injector and load your modules like this:
36350
- *
36351
- * ```js
36352
- * let injector = angular.injector(['ng', 'myModule'])
36353
- * ```
36354
- *
36355
- * However it's more likely that you'll just use
36356
- * {@link ng.directive:ngApp ngApp} or
36357
- * {@link angular.bootstrap} to simplify this process for you.
36358
- *
36359
- * @param {string} name The name of the module to create or retrieve.
36360
- * @param {Array.<string>} [requires] If specified then new module is being created. If
36361
- * unspecified then the module is being retrieved for further configuration.
36362
- * @param {import("./interface.ts").Injectable<any>} [configFn] Optional configuration function for the module that gets
36363
- * passed to {@link NgModule.config NgModule.config()}.
36364
- * @returns {NgModule} A newly registered module.
36728
+ * @param {string} name
36729
+ * @returns {ProxyHandler<ng.Scope>|undefined}
36365
36730
  */
36366
- module(name, requires, configFn) {
36367
- assertNotHasOwnProperty(name, "module");
36368
- if (requires && hasOwn(modules, name)) {
36369
- modules[name] = null;
36731
+ getScopeByName(name) {
36732
+ const scope = this.$rootScope.$searchByName(name);
36733
+ if (scope) {
36734
+ return scope.$proxy;
36370
36735
  }
36371
- return ensure(modules, name, () => {
36372
- if (!requires) {
36373
- throw $injectorMinErr(
36374
- "nomod",
36375
- "Module '{0}' is not available. Possibly misspelled or not loaded",
36376
- name,
36377
- );
36378
- }
36379
- return new NgModule(name, requires, configFn);
36380
- });
36381
36736
  }
36382
36737
  }
36383
36738
 
36739
+ /**
36740
+ * @param {Object.<string, NgModule>} obj
36741
+ * @param {string} name
36742
+ * @param {Function} factory
36743
+ * @returns {NgModule}
36744
+ */
36384
36745
  function ensure(obj, name, factory) {
36385
36746
  return obj[name] || (obj[name] = factory());
36386
36747
  }