@angular-wave/angular.ts 0.11.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 (45) hide show
  1. package/@types/angular.d.ts +64 -51
  2. package/@types/animations/animate.d.ts +1 -351
  3. package/@types/animations/animation.d.ts +2 -2
  4. package/@types/animations/interface.d.ts +72 -0
  5. package/@types/animations/{animate-queue.d.ts → queue/animate-queue.d.ts} +2 -7
  6. package/@types/animations/queue/interface.d.ts +50 -0
  7. package/@types/core/compile/attributes.d.ts +5 -5
  8. package/@types/core/compile/compile.d.ts +4 -4
  9. package/@types/core/controller/controller.d.ts +1 -1
  10. package/@types/core/di/di.d.ts +26 -0
  11. package/@types/core/di/injector.d.ts +0 -11
  12. package/@types/core/di/internal-injector.d.ts +2 -2
  13. package/@types/core/di/ng-module/ng-module.d.ts +197 -0
  14. package/@types/core/sanitize/interface.d.ts +8 -0
  15. package/@types/core/sanitize/sanitize-uri.d.ts +5 -2
  16. package/@types/core/scope/interface.d.ts +2 -2
  17. package/@types/core/scope/scope.d.ts +5 -2
  18. package/@types/directive/form/form.d.ts +7 -7
  19. package/@types/directive/if/if.d.ts +2 -2
  20. package/@types/directive/include/include.d.ts +4 -4
  21. package/@types/directive/messages/messages.d.ts +18 -22
  22. package/@types/directive/model/model.d.ts +3 -3
  23. package/@types/directive/scope/scope.d.ts +4 -0
  24. package/@types/directive/show-hide/show-hide.d.ts +3 -4
  25. package/@types/directive/switch/switch.d.ts +3 -5
  26. package/@types/directive/wasm/wasm.d.ts +4 -0
  27. package/@types/{services → directive}/worker/interface.d.ts +1 -0
  28. package/@types/directive/worker/worker.d.ts +18 -8
  29. package/@types/interface.d.ts +14 -15
  30. package/@types/namespace.d.ts +25 -4
  31. package/@types/services/log/log.d.ts +2 -2
  32. package/@types/services/sce/sce.d.ts +4 -82
  33. package/@types/services/sse/sse.d.ts +1 -5
  34. package/@types/services/storage/interface.d.ts +5 -0
  35. package/@types/services/storage/storage.d.ts +19 -0
  36. package/@types/services/stream/interface.d.ts +18 -0
  37. package/@types/shared/dom.d.ts +21 -5
  38. package/@types/shared/strings.d.ts +0 -6
  39. package/@types/shared/utils.d.ts +24 -14
  40. package/dist/angular-ts.esm.js +1448 -1194
  41. package/dist/angular-ts.umd.js +1448 -1194
  42. package/dist/angular-ts.umd.min.js +1 -1
  43. package/package.json +1 -1
  44. package/@types/core/di/ng-module.d.ts +0 -156
  45. package/@types/services/worker/worker.d.ts +0 -31
@@ -1,4 +1,4 @@
1
- /* Version: 0.11.0 - November 11, 2025 21:55:55 */
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);
@@ -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
@@ -2224,6 +2256,706 @@
2224
2256
  return services.map((x) => x + "Provider");
2225
2257
  }
2226
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
+
2227
2959
  /** @private */
2228
2960
  const INJECTOR_LITERAL = "$injector";
2229
2961
  /** @private */
@@ -2249,7 +2981,7 @@
2249
2981
  /**
2250
2982
  * @param {string} name - Name of the module
2251
2983
  * @param {Array<string>} requires - List of modules which the injector will load before the current module
2252
- * @param {import("../../interface.ts").Injectable<any>} [configFn]
2984
+ * @param {ng.Injectable<any>} [configFn]
2253
2985
  */
2254
2986
  constructor(name, requires, configFn) {
2255
2987
  assert(isString(name), "name required");
@@ -2275,7 +3007,7 @@
2275
3007
  /** @type {!Array<Array<*>>} */
2276
3008
  this.configBlocks = [];
2277
3009
 
2278
- /** @type {!Array.<import("../../interface.ts").Injectable<any>>} */
3010
+ /** @type {!Array.<ng.Injectable<any>>} */
2279
3011
  this.runBlocks = [];
2280
3012
 
2281
3013
  if (configFn) {
@@ -2283,6 +3015,8 @@
2283
3015
  }
2284
3016
 
2285
3017
  this.services = [];
3018
+
3019
+ this.wasmModules = [];
2286
3020
  }
2287
3021
 
2288
3022
  /**
@@ -2307,7 +3041,7 @@
2307
3041
 
2308
3042
  /**
2309
3043
  *
2310
- * @param {import("../../interface.ts").Injectable<any>} configFn
3044
+ * @param {ng.Injectable<any>} configFn
2311
3045
  * @returns {NgModule}
2312
3046
  */
2313
3047
  config(configFn) {
@@ -2316,7 +3050,7 @@
2316
3050
  }
2317
3051
 
2318
3052
  /**
2319
- * @param {import("../../interface.ts").Injectable<any>} block
3053
+ * @param {ng.Injectable<any>} block
2320
3054
  * @returns {NgModule}
2321
3055
  */
2322
3056
  run(block) {
@@ -2326,7 +3060,7 @@
2326
3060
 
2327
3061
  /**
2328
3062
  * @param {string} name
2329
- * @param {import("../../interface.ts").Component} options
3063
+ * @param {ng.Component} options
2330
3064
  * @returns {NgModule}
2331
3065
  */
2332
3066
  component(name, options) {
@@ -2339,7 +3073,7 @@
2339
3073
 
2340
3074
  /**
2341
3075
  * @param {string} name
2342
- * @param {import("../../interface.ts").Injectable<any>} providerFunction
3076
+ * @param {ng.Injectable<any>} providerFunction
2343
3077
  * @returns {NgModule}
2344
3078
  */
2345
3079
  factory(name, providerFunction) {
@@ -2352,7 +3086,7 @@
2352
3086
 
2353
3087
  /**
2354
3088
  * @param {string} name
2355
- * @param {import("../../interface.ts").Injectable<any>} serviceFunction
3089
+ * @param {ng.Injectable<any>} serviceFunction
2356
3090
  * @returns {NgModule}
2357
3091
  */
2358
3092
  service(name, serviceFunction) {
@@ -2366,7 +3100,7 @@
2366
3100
 
2367
3101
  /**
2368
3102
  * @param {string} name
2369
- * @param {import("../../interface.ts").Injectable<any>} providerType
3103
+ * @param {ng.Injectable<any>} providerType
2370
3104
  * @returns {NgModule}
2371
3105
  */
2372
3106
  provider(name, providerType) {
@@ -2379,7 +3113,7 @@
2379
3113
 
2380
3114
  /**
2381
3115
  * @param {string} name
2382
- * @param {import("../../interface.ts").Injectable<any>} decorFn
3116
+ * @param {ng.Injectable<any>} decorFn
2383
3117
  * @returns {NgModule}
2384
3118
  */
2385
3119
  decorator(name, decorFn) {
@@ -2392,7 +3126,7 @@
2392
3126
 
2393
3127
  /**
2394
3128
  * @param {string} name
2395
- * @param {import("../../interface.ts").Injectable<any>} directiveFactory
3129
+ * @param {ng.Injectable<any>} directiveFactory
2396
3130
  * @returns {NgModule}
2397
3131
  */
2398
3132
  directive(name, directiveFactory) {
@@ -2409,7 +3143,7 @@
2409
3143
 
2410
3144
  /**
2411
3145
  * @param {string} name
2412
- * @param {import("../../interface.ts").Injectable<any>} animationFactory
3146
+ * @param {ng.Injectable<any>} animationFactory
2413
3147
  * @returns {NgModule}
2414
3148
  */
2415
3149
  animation(name, animationFactory) {
@@ -2426,7 +3160,7 @@
2426
3160
 
2427
3161
  /**
2428
3162
  * @param {string} name
2429
- * @param {import("../../interface.ts").Injectable<any>} filterFn
3163
+ * @param {ng.Injectable<any>} filterFn
2430
3164
  * @return {NgModule}
2431
3165
  */
2432
3166
  filter(name, filterFn) {
@@ -2439,7 +3173,7 @@
2439
3173
 
2440
3174
  /**
2441
3175
  * @param {string} name
2442
- * @param {import("../../interface.ts").Injectable<any>} ctlFn
3176
+ * @param {ng.Injectable<any>} ctlFn
2443
3177
  * @returns {NgModule}
2444
3178
  */
2445
3179
  controller(name, ctlFn) {
@@ -2449,12 +3183,192 @@
2449
3183
  this.invokeQueue.push([CONTROLLER_LITERAL, "register", [name, ctlFn]]);
2450
3184
  return this;
2451
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;
2452
3370
  }
2453
3371
 
2454
- const ARROW_ARG$1 = /^([^(]+?)=>/;
2455
- const FN_ARGS$1 = /^[^(]*\(\s*([^)]*)\)/m;
2456
- const FN_ARG$1 = /^\s*(_?)(\S+?)\1\s*$/;
2457
- const STRIP_COMMENTS$1 = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;
2458
3372
  const $injectorMinErr$2 = minErr(INJECTOR_LITERAL);
2459
3373
 
2460
3374
  const providerSuffix$1 = "Provider";
@@ -2473,7 +3387,7 @@
2473
3387
  this.strictDi = strictDi;
2474
3388
  /** @type {string[]} */
2475
3389
  this.path = [];
2476
- /** @type {Object.<string, import("./ng-module.js").NgModule>} */
3390
+ /** @type {Object.<string, ng.NgModule>} */
2477
3391
  this.modules = {};
2478
3392
  }
2479
3393
 
@@ -2517,7 +3431,7 @@
2517
3431
  */
2518
3432
  injectionArgs(fn, locals, serviceName) {
2519
3433
  const args = [];
2520
- const $inject = annotate$1(fn, this.strictDi, serviceName);
3434
+ const $inject = annotate(fn, this.strictDi, serviceName);
2521
3435
 
2522
3436
  for (let i = 0, { length } = $inject; i < length; i++) {
2523
3437
  const key = $inject[i];
@@ -2640,7 +3554,7 @@
2640
3554
 
2641
3555
  /** @type {ProviderInjector} */
2642
3556
  this.providerInjector = providerInjector;
2643
- /** @type {Object.<string, import("./ng-module.js").NgModule>} */
3557
+ /** @type {Object.<string, ng.NgModule>} */
2644
3558
  this.modules = providerInjector.modules;
2645
3559
  }
2646
3560
 
@@ -2670,78 +3584,52 @@
2670
3584
  loadNewModules() {}
2671
3585
  }
2672
3586
 
2673
- // Helpers
2674
-
2675
- /**
2676
- * @param {Function} fn
2677
- * @returns {string}
2678
- */
2679
- function stringifyFn$1(fn) {
2680
- return Function.prototype.toString.call(fn);
2681
- }
2682
-
2683
- /**
2684
- * @param {Function} fn
2685
- * @returns {Array<any>}
2686
- */
2687
- function extractArgs$1(fn) {
2688
- const fnText = stringifyFn$1(fn).replace(STRIP_COMMENTS$1, "");
2689
- return fnText.match(ARROW_ARG$1) || fnText.match(FN_ARGS$1);
2690
- }
2691
-
2692
- /**
2693
- * @param {Function} func
2694
- * @returns {boolean}
2695
- */
2696
- function isClass(func) {
2697
- return /^class\b/.test(stringifyFn$1(func));
2698
- }
2699
-
2700
3587
  /**
3588
+ * Creates a proxy that automatically persists an object's state
3589
+ * into a storage backend whenever a property is set.
2701
3590
  *
2702
- * @param {any} fn
2703
- * @param {boolean} strictDi
2704
- * @param {string} name
2705
- * @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}
2706
3596
  */
2707
- function annotate$1(fn, strictDi, name) {
2708
- 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;
2709
3600
 
2710
- if (typeof fn === "function") {
2711
- if (!($inject = fn.$inject)) {
2712
- $inject = [];
2713
- if (fn.length) {
2714
- if (strictDi) {
2715
- throw $injectorMinErr$2(
2716
- "strictdi",
2717
- "{0} is not using explicit annotation and cannot be invoked in strict mode",
2718
- name,
2719
- );
2720
- }
2721
- argDecl = extractArgs$1(fn);
2722
- argDecl[1].split(/,/).forEach(function (arg) {
2723
- arg.replace(FN_ARG$1, function (_all, _underscore, name) {
2724
- $inject.push(name);
2725
- });
2726
- });
2727
- }
2728
- 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}"`);
2729
3608
  }
2730
- } else if (Array.isArray(fn)) {
2731
- last = /** @type {Array} */ (fn).length - 1;
2732
- assertArgFn(fn[last], "fn");
2733
- $inject = /** @type {Array} */ (fn).slice(0, last);
2734
- } else {
2735
- assertArgFn(fn, "fn", true);
2736
3609
  }
2737
- 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
+ });
2738
3631
  }
2739
3632
 
2740
- const ARROW_ARG = /^([^(]+?)=>/;
2741
- const FN_ARGS = /^[^(]*\(\s*([^)]*)\)/m;
2742
- const FN_ARG_SPLIT = /,/;
2743
- const FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
2744
- const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;
2745
3633
  const $injectorMinErr$1 = minErr(INJECTOR_LITERAL);
2746
3634
  const providerSuffix = "Provider";
2747
3635
 
@@ -2764,6 +3652,9 @@
2764
3652
  service: supportObject(service),
2765
3653
  value: supportObject(value),
2766
3654
  constant: supportObject(constant),
3655
+ session: supportObject(session),
3656
+ local: supportObject(local),
3657
+ store: supportObject(store),
2767
3658
  decorator,
2768
3659
  },
2769
3660
  };
@@ -2897,13 +3788,78 @@
2897
3788
  };
2898
3789
  }
2899
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
+
2900
3856
  /**
2901
3857
  *
2902
3858
  * @param {Array<String|Function>} modulesToLoad
2903
3859
  * @returns
2904
3860
  */
2905
3861
  function loadModules(modulesToLoad) {
2906
- assertArg$1(
3862
+ assertArg(
2907
3863
  isUndefined(modulesToLoad) || Array.isArray(modulesToLoad),
2908
3864
  "modulesToLoad",
2909
3865
  "not an array",
@@ -2916,8 +3872,10 @@
2916
3872
 
2917
3873
  try {
2918
3874
  if (isString(module)) {
2919
- /** @type {import('./ng-module.js').NgModule} */
2920
- const moduleFn = window["angular"].module(module);
3875
+ /** @type {ng.NgModule} */
3876
+ const moduleFn = window["angular"].module(
3877
+ /** @type {string} */ (module),
3878
+ );
2921
3879
  instanceInjector.modules[/** @type {string } */ (module)] = moduleFn;
2922
3880
  runBlocks = runBlocks
2923
3881
  .concat(loadModules(moduleFn.requires))
@@ -2961,64 +3919,6 @@
2961
3919
  }
2962
3920
  }
2963
3921
 
2964
- // Helpers
2965
-
2966
- /**
2967
- * @param {String} fn
2968
- * @returns {String}
2969
- */
2970
- function stringifyFn(fn) {
2971
- return Function.prototype.toString.call(fn);
2972
- }
2973
-
2974
- /**
2975
- * @param {String} fn
2976
- * @returns {Array<any>}
2977
- */
2978
- function extractArgs(fn) {
2979
- const fnText = stringifyFn(fn).replace(STRIP_COMMENTS, "");
2980
- return fnText.match(ARROW_ARG) || fnText.match(FN_ARGS);
2981
- }
2982
-
2983
- /**
2984
- * @param {any} fn
2985
- * @param {boolean} [strictDi]
2986
- * @param {String} [name]
2987
- * @returns {Array<string>}
2988
- */
2989
- function annotate(fn, strictDi, name) {
2990
- let $inject, argDecl, last;
2991
-
2992
- if (typeof fn === "function") {
2993
- if (!($inject = fn.$inject)) {
2994
- $inject = [];
2995
- if (fn.length) {
2996
- if (strictDi) {
2997
- throw $injectorMinErr$1(
2998
- "strictdi",
2999
- "{0} is not using explicit annotation and cannot be invoked in strict mode",
3000
- name,
3001
- );
3002
- }
3003
- argDecl = extractArgs(/** @type {String} */ (fn));
3004
- argDecl[1].split(FN_ARG_SPLIT).forEach(function (arg) {
3005
- arg.replace(FN_ARG, function (all, underscore, name) {
3006
- $inject.push(name);
3007
- });
3008
- });
3009
- }
3010
- fn.$inject = $inject;
3011
- }
3012
- } else if (Array.isArray(fn)) {
3013
- last = /** @type {Array} */ (fn).length - 1;
3014
- assertArgFn(fn[last], "fn");
3015
- $inject = /** @type {Array} */ (fn).slice(0, last);
3016
- } else {
3017
- assertArgFn(fn, "fn", true);
3018
- }
3019
- return $inject;
3020
- }
3021
-
3022
3922
  function supportObject(delegate) {
3023
3923
  return function (key, value) {
3024
3924
  if (isObject(key)) {
@@ -3041,7 +3941,7 @@
3041
3941
  * @throws {Error} If the argument is invalid or cannot be wrapped properly.
3042
3942
  */
3043
3943
  constructor(element) {
3044
- assertArg$1(element, "element");
3944
+ assertArg(element, "element");
3045
3945
  this.initial = null;
3046
3946
 
3047
3947
  /** @private @type {Node | ChildNode | null} */
@@ -3097,8 +3997,8 @@
3097
3997
  }
3098
3998
 
3099
3999
  // Handle array of elements
3100
- else if (element instanceof Array) {
3101
- if (element.length == 1) {
4000
+ else if (Array.isArray(element)) {
4001
+ if (element.length === 1) {
3102
4002
  this.initial = element[0].cloneNode(true);
3103
4003
  this.node = element[0];
3104
4004
  } else {
@@ -3112,13 +4012,13 @@
3112
4012
 
3113
4013
  /** @returns {Element} */
3114
4014
  get element() {
3115
- assertArg$1(this._element, "element");
4015
+ assertArg(this._element, "element");
3116
4016
  return this._element;
3117
4017
  }
3118
4018
 
3119
4019
  /** @param {Element} el */
3120
4020
  set element(el) {
3121
- assertArg$1(el instanceof Element, "element");
4021
+ assertArg(el instanceof Element, "element");
3122
4022
  this._element = el;
3123
4023
  this._nodes = undefined;
3124
4024
  this.isList = false;
@@ -3126,13 +4026,13 @@
3126
4026
 
3127
4027
  /** @returns {Node | ChildNode} */
3128
4028
  get node() {
3129
- assertArg$1(this._node || this._element, "node");
4029
+ assertArg(this._node || this._element, "node");
3130
4030
  return this._node || this._element;
3131
4031
  }
3132
4032
 
3133
4033
  /** @param {Node | ChildNode} node */
3134
4034
  set node(node) {
3135
- assertArg$1(node instanceof Node, "node");
4035
+ assertArg(node instanceof Node, "node");
3136
4036
  this._node = node;
3137
4037
  if (node.nodeType === Node.ELEMENT_NODE) {
3138
4038
  this._element = /** @type {Element} */ (node);
@@ -3143,7 +4043,7 @@
3143
4043
 
3144
4044
  /** @param {Array<Node>} nodes */
3145
4045
  set nodes(nodes) {
3146
- assertArg$1(
4046
+ assertArg(
3147
4047
  Array.isArray(nodes) && nodes.every((n) => n instanceof Node),
3148
4048
  "nodes",
3149
4049
  );
@@ -3153,25 +4053,18 @@
3153
4053
 
3154
4054
  /** @returns {Array<Node>} */
3155
4055
  get nodes() {
3156
- assertArg$1(this._nodes, "nodes");
4056
+ assertArg(this._nodes, "nodes");
3157
4057
  return this._nodes;
3158
4058
  }
3159
4059
 
3160
4060
  /** @returns {NodeList|Node[]} */
3161
4061
  get nodelist() {
3162
- assertArg$1(this.isList, "nodes");
3163
- if (this._nodes.length === 0) {
3164
- return this._nodes;
3165
- }
3166
- if (this._nodes[0].parentElement) {
4062
+ if (this._nodes.length === 0) return [];
4063
+ if (this._nodes[0].parentElement)
3167
4064
  return this._nodes[0].parentElement.childNodes;
3168
- } else {
3169
- const fragment = document.createDocumentFragment();
3170
- this._nodes.forEach((el) => {
3171
- fragment.appendChild(el);
3172
- });
3173
- return fragment.childNodes;
3174
- }
4065
+ const fragment = document.createDocumentFragment();
4066
+ this._nodes.forEach((el) => fragment.appendChild(el));
4067
+ return fragment.childNodes;
3175
4068
  }
3176
4069
 
3177
4070
  /** @returns {Element | Node | ChildNode | NodeList | Node[]} */
@@ -3229,8 +4122,8 @@
3229
4122
  * @param {Element | Node | ChildNode} node
3230
4123
  */
3231
4124
  setIndex(index, node) {
3232
- assertArg$1(index !== null, "index");
3233
- assertArg$1(node, "node");
4125
+ assertArg(index !== null, "index");
4126
+ assertArg(node, "node");
3234
4127
  if (this.isList) {
3235
4128
  this._nodes[index] = node;
3236
4129
  } else {
@@ -3316,7 +4209,7 @@
3316
4209
  "$injector",
3317
4210
 
3318
4211
  /**
3319
- * @param {import("../../core/di/internal-injector.js").InjectorService} $injector
4212
+ * @param {ng.InjectorService} $injector
3320
4213
  * @returns {import("./interface.ts").ControllerService} A service function that creates controllers.
3321
4214
  */
3322
4215
  ($injector) => {
@@ -3369,6 +4262,10 @@
3369
4262
  );
3370
4263
  }
3371
4264
 
4265
+ if (instance?.constructor?.$scopename) {
4266
+ locals.$scope.$scopename = instance.constructor.$scopename;
4267
+ }
4268
+
3372
4269
  return function () {
3373
4270
  const result = $injector.invoke(
3374
4271
  expression,
@@ -3631,7 +4528,7 @@
3631
4528
  * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict
3632
4529
  * Contextual Escaping (SCE)} services to AngularTS.
3633
4530
  *
3634
- * 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
3635
4532
  * page for {@link ng.$sce SCE}. The current page is targeted for developers who need to alter how
3636
4533
  * SCE works in their application, which shouldn't be needed in most cases.
3637
4534
  *
@@ -3658,85 +4555,6 @@
3658
4555
  * ng.$sceDelegateProvider#bannedResourceUrlList $sceDelegateProvider.bannedResourceUrlList}
3659
4556
  */
3660
4557
 
3661
- /**
3662
- *
3663
- * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate
3664
- * $sceDelegate service}, used as a delegate for {@link ng.$sce Strict Contextual Escaping (SCE)}.
3665
- *
3666
- * The `$sceDelegateProvider` allows one to get/set the `trustedResourceUrlList` and
3667
- * `bannedResourceUrlList` used to ensure that the URLs used for sourcing AngularTS templates and
3668
- * other script-running URLs are safe (all places that use the `$sce.RESOURCE_URL` context). See
3669
- * {@link ng.$sceDelegateProvider#trustedResourceUrlList
3670
- * $sceDelegateProvider.trustedResourceUrlList} and
3671
- * {@link ng.$sceDelegateProvider#bannedResourceUrlList $sceDelegateProvider.bannedResourceUrlList},
3672
- *
3673
- * For the general details about this service in AngularTS, read the main page for {@link ng.$sce
3674
- * Strict Contextual Escaping (SCE)}.
3675
- *
3676
- * **Example**: Consider the following case. <a name="example"></a>
3677
- *
3678
- * - your app is hosted at url `http://myapp.example.com/`
3679
- * - but some of your templates are hosted on other domains you control such as
3680
- * `http://srv01.assets.example.com/`, `http://srv02.assets.example.com/`, etc.
3681
- * - and you have an open redirect at `http://myapp.example.com/clickThru?...`.
3682
- *
3683
- * Here is what a secure configuration for this scenario might look like:
3684
- *
3685
- * ```
3686
- * angular.module('myApp', []).config(function($sceDelegateProvider) {
3687
- * $sceDelegateProvider.trustedResourceUrlList([
3688
- * // Allow same origin resource loads.
3689
- * 'self',
3690
- * // Allow loading from our assets domain. Notice the difference between * and **.
3691
- * 'http://srv*.assets.example.com/**'
3692
- * ]);
3693
- *
3694
- * // The banned resource URL list overrides the trusted resource URL list so the open redirect
3695
- * // here is blocked.
3696
- * $sceDelegateProvider.bannedResourceUrlList([
3697
- * 'http://myapp.example.com/clickThru**'
3698
- * ]);
3699
- * });
3700
- * ```
3701
- * Note that an empty trusted resource URL list will block every resource URL from being loaded, and will require
3702
- * you to manually mark each one as trusted with `$sce.trustAsResourceUrl`. However, templates
3703
- * requested by {@link ng.$templateRequest $templateRequest} that are present in
3704
- * {@link ng.$templateCache $templateCache} will not go through this check. If you have a mechanism
3705
- * to populate your templates in that cache at config time, then it is a good idea to remove 'self'
3706
- * from the trusted resource URL lsit. This helps to mitigate the security impact of certain types
3707
- * of issues, like for instance attacker-controlled `ng-includes`.
3708
- */
3709
-
3710
- /**
3711
- * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict
3712
- * Contextual Escaping (SCE)} services to AngularTS.
3713
- *
3714
- * For an overview of this service and the functionnality it provides in AngularTS, see the main
3715
- * page for {@link ng.$sce SCE}. The current page is targeted for developers who need to alter how
3716
- * SCE works in their application, which shouldn't be needed in most cases.
3717
- *
3718
- * <div class="alert alert-danger">
3719
- * AngularTS strongly relies on contextual escaping for the security of bindings: disabling or
3720
- * modifying this might cause cross site scripting (XSS) vulnerabilities. For libraries owners,
3721
- * changes to this service will also influence users, so be extra careful and document your changes.
3722
- * </div>
3723
- *
3724
- * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of
3725
- * the `$sce` service to customize the way Strict Contextual Escaping works in AngularTS. This is
3726
- * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to
3727
- * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things
3728
- * work because `$sce` delegates to `$sceDelegate` for these operations.
3729
- *
3730
- * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service.
3731
- *
3732
- * The default instance of `$sceDelegate` should work out of the box with little pain. While you
3733
- * can override it completely to change the behavior of `$sce`, the common case would
3734
- * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting
3735
- * your own trusted and banned resource lists for trusting URLs used for loading AngularTS resources
3736
- * such as templates. Refer {@link ng.$sceDelegateProvider#trustedResourceUrlList
3737
- * $sceDelegateProvider.trustedResourceUrlList} and {@link
3738
- * ng.$sceDelegateProvider#bannedResourceUrlList $sceDelegateProvider.bannedResourceUrlList}
3739
- */
3740
4558
  /**
3741
4559
  *
3742
4560
  * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate
@@ -3793,7 +4611,7 @@
3793
4611
 
3794
4612
  /**
3795
4613
  *
3796
- * @param {Array=} trustedResourceUrlList When provided, replaces the trustedResourceUrlList with
4614
+ * @param {Array=} value When provided, replaces the trustedResourceUrlList with
3797
4615
  * the value provided. This must be an array or null. A snapshot of this array is used so
3798
4616
  * further changes to the array are ignored.
3799
4617
  * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
@@ -3855,7 +4673,7 @@
3855
4673
  /**
3856
4674
  *
3857
4675
  * @param {ng.InjectorService} $injector
3858
- * @param {*} $$sanitizeUri
4676
+ * @param {import("../../core/sanitize/interface.ts").SanitizerFn} $$sanitizeUri
3859
4677
  * @param {ng.ExceptionHandlerService} $exceptionHandler
3860
4678
  * @returns
3861
4679
  */
@@ -4377,7 +5195,7 @@
4377
5195
  const { trustAs } = sce;
4378
5196
 
4379
5197
  Object.entries(SCE_CONTEXTS).forEach(([name, enumValue]) => {
4380
- const lName = lowercase(name);
5198
+ const lName = name.toLowerCase();
4381
5199
  sce[snakeToCamel(`parse_as_${lName}`)] = function (expr) {
4382
5200
  return parse(enumValue, expr);
4383
5201
  };
@@ -4511,8 +5329,8 @@
4511
5329
  static $nonscope = true;
4512
5330
 
4513
5331
  /**
4514
- * @param {ng.Scope} $rootScope
4515
- * @param {*} $animate
5332
+ * @param {ng.RootScopeService} $rootScope
5333
+ * @param {ng.AnimateService} $animate
4516
5334
  * @param {ng.ExceptionHandlerService} $exceptionHandler
4517
5335
  * @param {*} $sce
4518
5336
  * @param {import("../../shared/noderef.js").NodeRef} [nodeRef]
@@ -4570,7 +5388,10 @@
4570
5388
  $addClass(classVal) {
4571
5389
  if (classVal && classVal.length > 0) {
4572
5390
  if (hasAnimate(this.$$element)) {
4573
- this.$animate.addClass(this.$$element, classVal);
5391
+ this.$animate.addClass(
5392
+ /** @type {Element} */ (this.$$element),
5393
+ classVal,
5394
+ );
4574
5395
  } else {
4575
5396
  this.$nodeRef.element.classList.add(classVal);
4576
5397
  }
@@ -4586,7 +5407,10 @@
4586
5407
  $removeClass(classVal) {
4587
5408
  if (classVal && classVal.length > 0) {
4588
5409
  if (hasAnimate(this.$$element)) {
4589
- this.$animate.removeClass(this.$$element, classVal);
5410
+ this.$animate.removeClass(
5411
+ /** @type {Element} */ (this.$$element),
5412
+ classVal,
5413
+ );
4590
5414
  } else {
4591
5415
  this.$nodeRef.element.classList.remove(classVal);
4592
5416
  }
@@ -4604,7 +5428,7 @@
4604
5428
  const toAdd = tokenDifference(newClasses, oldClasses);
4605
5429
  if (toAdd && toAdd.length) {
4606
5430
  if (hasAnimate(this.$$element)) {
4607
- this.$animate.addClass(this.$$element, toAdd);
5431
+ this.$animate.addClass(/** @type {Element }*/ (this.$$element), toAdd);
4608
5432
  } else {
4609
5433
  this.$nodeRef.element.classList.add(...toAdd.trim().split(/\s+/));
4610
5434
  }
@@ -4612,7 +5436,10 @@
4612
5436
  const toRemove = tokenDifference(oldClasses, newClasses);
4613
5437
  if (toRemove && toRemove.length) {
4614
5438
  if (hasAnimate(this.$$element)) {
4615
- this.$animate.removeClass(this.$$element, toRemove);
5439
+ this.$animate.removeClass(
5440
+ /** @type {Element }*/ (this.$$element),
5441
+ toRemove,
5442
+ );
4616
5443
  } else {
4617
5444
  this.$nodeRef.element.classList.remove(...toRemove.trim().split(/\s+/));
4618
5445
  }
@@ -4803,7 +5630,8 @@
4803
5630
  if (lastTuple.length === 2) {
4804
5631
  result += " " + trim(lastTuple[1]);
4805
5632
  }
4806
- return result;
5633
+
5634
+ return result.replace(/unsafe:unsafe/g, "unsafe");
4807
5635
  }
4808
5636
  }
4809
5637
 
@@ -5012,11 +5840,11 @@
5012
5840
  * @returns {CompileProvider} Self for chaining.
5013
5841
  */
5014
5842
  this.directive = function registerDirective(name, directiveFactory) {
5015
- assertArg$1(name, "name");
5843
+ assertArg(name, "name");
5016
5844
  assertNotHasOwnProperty(name, "directive");
5017
5845
  if (isString(name)) {
5018
5846
  assertValidDirectiveName(name);
5019
- assertArg$1(directiveFactory, "directiveFactory");
5847
+ assertArg(directiveFactory, "directiveFactory");
5020
5848
  if (!hasOwn(hasDirectives, name)) {
5021
5849
  hasDirectives[name] = [];
5022
5850
  $provide.factory(name + DirectiveSuffix, [
@@ -5350,15 +6178,15 @@
5350
6178
  "$sce",
5351
6179
  "$animate",
5352
6180
  /**
5353
- * @param {import("../../core/di/internal-injector.js").InjectorService} $injector
6181
+ * @param {ng.InjectorService} $injector
5354
6182
  * @param {*} $interpolate
5355
6183
  * @param {import("../../services/exception/exception-handler.js").ErrorHandler} $exceptionHandler
5356
- * @param {*} $templateRequest
5357
- * @param {import("../parse/interface.ts").ParseService} $parse
6184
+ * @param {ng.TemplateRequestService} $templateRequest
6185
+ * @param {ng.ParseService} $parse
5358
6186
  * @param {*} $controller
5359
6187
  * @param {import('../scope/scope.js').Scope} $rootScope
5360
6188
  * @param {*} $sce
5361
- * @param {*} $animate
6189
+ * @param {ng.AnimateService} $animate
5362
6190
  * @returns
5363
6191
  */
5364
6192
  function (
@@ -5437,7 +6265,7 @@
5437
6265
  );
5438
6266
  }
5439
6267
 
5440
- assertArg$1(scope, "scope");
6268
+ assertArg(scope, "scope");
5441
6269
  // could be empty nodelist
5442
6270
  if (nodeRef.getAny()) {
5443
6271
  setScope(nodeRef.getAny(), scope);
@@ -5500,7 +6328,7 @@
5500
6328
 
5501
6329
  if (transcludeControllers) {
5502
6330
  for (const controllerName in transcludeControllers) {
5503
- assertArg$1($linkNode.element, "element");
6331
+ assertArg($linkNode.element, "element");
5504
6332
  setCacheData(
5505
6333
  $linkNode.element,
5506
6334
  `$${controllerName}Controller`,
@@ -5648,7 +6476,7 @@
5648
6476
  * @param {*} [parentBoundTranscludeFn]
5649
6477
  */
5650
6478
  function compositeLinkFn(scope, nodeRef, parentBoundTranscludeFn) {
5651
- assertArg$1(nodeRef, "nodeRef");
6479
+ assertArg(nodeRef, "nodeRef");
5652
6480
  let stableNodeList = [];
5653
6481
  if (nodeLinkFnFound) {
5654
6482
  // create a stable copy of the nodeList, only copying elements with linkFns
@@ -7055,11 +7883,19 @@
7055
7883
  replace: null,
7056
7884
  $$originalDirective: origAsyncDirective,
7057
7885
  });
7058
- const templateUrl = isFunction(origAsyncDirective.templateUrl)
7059
- ? /** @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) } */ (
7060
7892
  origAsyncDirective.templateUrl
7061
- )($compileNode.element, tAttrs)
7062
- : origAsyncDirective.templateUrl;
7893
+ )($compileNode.element, tAttrs);
7894
+ } else {
7895
+ templateUrl = /** @type {string} */ (
7896
+ origAsyncDirective.templateUrl
7897
+ );
7898
+ }
7063
7899
  const { templateNamespace } = origAsyncDirective;
7064
7900
 
7065
7901
  emptyElement($compileNode.element);
@@ -7580,14 +8416,23 @@
7580
8416
  attr.$$element.classList.value,
7581
8417
  );
7582
8418
  } else {
7583
- attr.$set(name, newValue);
8419
+ attr.$set(
8420
+ name,
8421
+ name === "srcset"
8422
+ ? $sce.getTrustedMediaUrl(newValue)
8423
+ : newValue,
8424
+ );
7584
8425
  }
7585
8426
  });
7586
8427
  });
7587
8428
 
7588
8429
  if (interpolateFn.expressions.length == 0) {
7589
- // if there is nothing to watch, its a constant
7590
- attr.$set(name, newValue);
8430
+ attr.$set(
8431
+ name,
8432
+ name === "srcset"
8433
+ ? $sce.getTrustedMediaUrl(newValue)
8434
+ : newValue,
8435
+ );
7591
8436
  }
7592
8437
  },
7593
8438
  };
@@ -7996,7 +8841,7 @@
7996
8841
  */
7997
8842
  function assertValidDirectiveName(name) {
7998
8843
  const letter = name.charAt(0);
7999
- if (!letter || letter !== lowercase(letter)) {
8844
+ if (!letter || letter !== letter.toLowerCase()) {
8000
8845
  throw $compileMinErr(
8001
8846
  "baddir",
8002
8847
  "Directive/Component name '{0}' is invalid. The first character must be a lowercase letter",
@@ -8102,9 +8947,9 @@
8102
8947
 
8103
8948
  /**
8104
8949
  * @param {Element} $element
8105
- * @param {import("../../core/compile/attributes.js").Attributes} $attrs
8106
- * @param {import("../../core/scope/scope.js").Scope} $scope
8107
- * @param {*} $animate
8950
+ * @param {ng.Attributes} $attrs
8951
+ * @param {ng.Scope} $scope
8952
+ * @param {ng.AnimateService} $animate
8108
8953
  * @param {*} $interpolate
8109
8954
  */
8110
8955
  constructor($element, $attrs, $scope, $animate, $interpolate) {
@@ -8870,7 +9715,7 @@
8870
9715
  * @param {import('../../core/compile/attributes.js').Attributes} $attr
8871
9716
  * @param {Element} $element
8872
9717
  * @param {import("../../core/parse/interface.ts").ParseService} $parse
8873
- * @param {*} $animate
9718
+ * @param {ng.AnimateService} $animate
8874
9719
  * @param {*} $interpolate
8875
9720
  */
8876
9721
  constructor(
@@ -10905,7 +11750,7 @@
10905
11750
  link: {
10906
11751
  pre(scope, element, attr, ctrls) {
10907
11752
  if (ctrls[0]) {
10908
- (inputType[lowercase(attr["type"])] || inputType.text)(
11753
+ (inputType[attr.type?.toLowerCase()] || inputType.text)(
10909
11754
  scope,
10910
11755
  element,
10911
11756
  attr,
@@ -10938,7 +11783,7 @@
10938
11783
  restrict: "E",
10939
11784
  priority: 200,
10940
11785
  compile(_, attr) {
10941
- if (lowercase(attr["type"]) !== "hidden") {
11786
+ if (attr.type?.toLowerCase() !== "hidden") {
10942
11787
  return;
10943
11788
  }
10944
11789
 
@@ -11889,7 +12734,8 @@
11889
12734
 
11890
12735
  ngShowDirective.$inject = ["$animate"];
11891
12736
  /**
11892
- * @returns {import('../../interface.ts').Directive}
12737
+ * @param {ng.AnimateService} $animate
12738
+ * @returns {ng.Directive}
11893
12739
  */
11894
12740
  function ngShowDirective($animate) {
11895
12741
  return {
@@ -11900,7 +12746,7 @@
11900
12746
  * @param $attr
11901
12747
  */
11902
12748
  link(scope, element, $attr) {
11903
- scope.$watch($attr["ngShow"], (value) => {
12749
+ scope.$watch($attr.ngShow, (value) => {
11904
12750
  // we're adding a temporary, animation-specific class for ng-hide since this way
11905
12751
  // we can control when the element is actually displayed on screen without having
11906
12752
  // to have a global/greedy CSS selector that breaks when other animations are run.
@@ -11950,7 +12796,7 @@
11950
12796
 
11951
12797
  ngIfDirective.$inject = ["$animate"];
11952
12798
  /**
11953
- * @param {*} $animate
12799
+ * @param {ng.AnimateService} $animate
11954
12800
  * @returns {ng.Directive}
11955
12801
  */
11956
12802
  function ngIfDirective($animate) {
@@ -12027,9 +12873,9 @@
12027
12873
 
12028
12874
  /**
12029
12875
  *
12030
- * @param {*} $templateRequest
12876
+ * @param {ng.TemplateRequestService} $templateRequest
12031
12877
  * @param {import("../../services/anchor-scroll/anchor-scroll.js").AnchorScrollFunction} $anchorScroll
12032
- * @param {*} $animate
12878
+ * @param {ng.AnimateService} $animate
12033
12879
  * @param {import('../../services/exception/interface.ts').ErrorHandler} $exceptionHandler
12034
12880
  * @returns {import('../../interface.ts').Directive}
12035
12881
  */
@@ -12631,8 +13477,8 @@
12631
13477
  ngSwitchDirective.$inject = ["$animate"];
12632
13478
 
12633
13479
  /**
12634
- * @param {*} $animate
12635
- * @returns {import('../../interface.ts').Directive}
13480
+ * @param {ng.AnimateService} $animate
13481
+ * @returns {ng.Directive}
12636
13482
  */
12637
13483
  function ngSwitchDirective($animate) {
12638
13484
  return {
@@ -12648,7 +13494,7 @@
12648
13494
  },
12649
13495
  ],
12650
13496
  link(scope, _element, attr, ngSwitchController) {
12651
- const watchExpr = attr["ngSwitch"] || attr["on"];
13497
+ const watchExpr = attr.ngSwitch || attr.on;
12652
13498
  let selectedTranscludes = [];
12653
13499
  const selectedElements = [];
12654
13500
  const previousLeaveAnimations = [];
@@ -13121,7 +13967,7 @@
13121
13967
  if (providedEmptyOption) {
13122
13968
  // compile the element since there might be bindings in it
13123
13969
  const linkFn = $compile(selectCtrl.emptyOption);
13124
- assertArg$1(linkFn, "LinkFn required");
13970
+ assertArg(linkFn, "LinkFn required");
13125
13971
  selectElement.prepend(selectCtrl.emptyOption);
13126
13972
  linkFn(scope);
13127
13973
 
@@ -13895,7 +14741,7 @@
13895
14741
 
13896
14742
  if (isFunction(offset)) {
13897
14743
  offset = /** @type {Function} */ (offset)();
13898
- } else if (isElement(offset)) {
14744
+ } else if (offset instanceof Element) {
13899
14745
  const elem = offset[0];
13900
14746
  const style = window.getComputedStyle(elem);
13901
14747
  if (style.position !== "fixed") {
@@ -13986,27 +14832,8 @@
13986
14832
  ];
13987
14833
  }
13988
14834
 
13989
- /** @typedef {"enter"|"leave"|"move"|"addClass"|"setClass"|"removeClass"} AnimationMethod */
13990
-
13991
- /**
13992
- * @typedef {Object} AnimationOptions
13993
- * @property {string} addClass - space-separated CSS classes to add to element
13994
- * @property {Object} from - CSS properties & values at the beginning of animation. Must have matching `to`
13995
- * @property {string} removeClass - space-separated CSS classes to remove from element
13996
- * @property {string} to - CSS properties & values at end of animation. Must have matching `from`
13997
- */
13998
-
13999
14835
  const $animateMinErr = minErr("$animate");
14000
14836
 
14001
- function mergeClasses(a, b) {
14002
- if (!a && !b) return "";
14003
- if (!a) return b;
14004
- if (!b) return a;
14005
- if (Array.isArray(a)) a = a.join(" ");
14006
- if (Array.isArray(b)) b = b.join(" ");
14007
- return `${a} ${b}`;
14008
- }
14009
-
14010
14837
  // if any other type of options value besides an Object value is
14011
14838
  // passed into the $animate.method() animation then this helper code
14012
14839
  // will be run which will ignore it. While this patch is not the
@@ -14154,7 +14981,11 @@
14154
14981
  };
14155
14982
 
14156
14983
  this.$get = [
14157
- "$$animateQueue",
14984
+ $injectTokens.$$animateQueue,
14985
+ /**
14986
+ * @param {import("./queue/interface.ts").AnimateQueueService} $$animateQueue
14987
+ * @returns {ng.AnimateService}
14988
+ */
14158
14989
  function ($$animateQueue) {
14159
14990
  /**
14160
14991
  * The $animate service exposes a series of DOM utility methods that provide support
@@ -14288,77 +15119,21 @@
14288
15119
  *
14289
15120
  * @return {boolean} whether or not animations are enabled
14290
15121
  */
14291
- enabled: $$animateQueue.enabled,
15122
+ enabled: (element, enabled) => {
15123
+ if (enabled !== undefined) {
15124
+ return hasAnimate(element);
15125
+ } else {
15126
+ element.setAttribute("animate", `${enabled}`);
15127
+ }
15128
+ },
14292
15129
 
14293
15130
  /**
14294
- * Cancels the provided animation and applies the end state of the animation.
14295
- * Note that this does not cancel the underlying operation, e.g. the setting of classes or
14296
- * adding the element to the DOM.
14297
- *
14298
- * @param {import('./runner/animate-runner.js').AnimateRunner} runner An animation runner returned by an $animate function.
14299
- *
14300
- * @example
14301
- <example module="animationExample" deps="angular-animate.js" animations="true" name="animate-cancel">
14302
- <file name="app.js">
14303
- angular.module('animationExample', []).component('cancelExample', {
14304
- templateUrl: 'template.html',
14305
- controller: function($element, $animate) {
14306
- this.runner = null;
14307
-
14308
- this.addClass = function() {
14309
- this.runner = $animate.addClass($element.querySelectorAll('div'), 'red');
14310
- let ctrl = this;
14311
- this.runner.finally(function() {
14312
- ctrl.runner = null;
14313
- });
14314
- };
14315
-
14316
- this.removeClass = function() {
14317
- this.runner = $animate.removeClass($element.querySelectorAll('div'), 'red');
14318
- let ctrl = this;
14319
- this.runner.finally(function() {
14320
- ctrl.runner = null;
14321
- });
14322
- };
14323
-
14324
- this.cancel = function() {
14325
- $animate.cancel(this.runner);
14326
- };
14327
- }
14328
- });
14329
- </file>
14330
- <file name="template.html">
14331
- <p>
14332
- <button id="add" ng-click="$ctrl.addClass()">Add</button>
14333
- <button ng-click="$ctrl.removeClass()">Remove</button>
14334
- <br>
14335
- <button id="cancel" ng-click="$ctrl.cancel()" ng-disabled="!$ctrl.runner">Cancel</button>
14336
- <br>
14337
- <div id="target">CSS-Animated Text</div>
14338
- </p>
14339
- </file>
14340
- <file name="index.html">
14341
- <cancel-example></cancel-example>
14342
- </file>
14343
- <file name="style.css">
14344
- .red-add, .red-remove {
14345
- transition: all 4s cubic-bezier(0.250, 0.460, 0.450, 0.940);
14346
- }
14347
-
14348
- .red,
14349
- .red-add.red-add-active {
14350
- color: #FF0000;
14351
- font-size: 40px;
14352
- }
14353
-
14354
- .red-remove.red-remove-active {
14355
- font-size: 10px;
14356
- color: black;
14357
- }
14358
-
14359
- </file>
14360
- </example>
14361
- */
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
+ */
14362
15137
  cancel(runner) {
14363
15138
  if (runner.cancel) {
14364
15139
  runner.cancel();
@@ -14374,7 +15149,7 @@
14374
15149
  * @param {Element} element - the element which will be inserted into the DOM
14375
15150
  * @param {Element} parent - the parent element which will append the element as a child (so long as the after element is not present)
14376
15151
  * @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.
15152
+ * @param {import("./interface.ts").AnimationOptions} [options] - an optional collection of options/styles that will be applied to the element.
14378
15153
  * @returns {import('./runner/animate-runner.js').AnimateRunner} the animation runner
14379
15154
  */
14380
15155
  enter(element, parent, after, options) {
@@ -14396,7 +15171,7 @@
14396
15171
  * @param {Element} element - the element which will be inserted into the DOM
14397
15172
  * @param {Element} parent - the parent element which will append the element as a child (so long as the after element is not present)
14398
15173
  * @param {Element} after - after the sibling element after which the element will be appended
14399
- * @param {AnimationOptions} [options] - an optional collection of options/styles that will be applied to the element.
15174
+ * @param {import("./interface.ts").AnimationOptions} [options] - an optional collection of options/styles that will be applied to the element.
14400
15175
  * @returns {import('./runner/animate-runner.js').AnimateRunner} the animation runner
14401
15176
  */
14402
15177
  move(element, parent, after, options) {
@@ -14415,7 +15190,7 @@
14415
15190
  * digest once the animation has completed.
14416
15191
  *
14417
15192
  * @param {Element} element the element which will be removed from the DOM
14418
- * @param {AnimationOptions} [options] an optional collection of options/styles that will be applied to the element.
15193
+ * @param {import("./interface.ts").AnimationOptions} [options] an optional collection of options/styles that will be applied to the element.
14419
15194
  * @returns {import('./runner/animate-runner.js').AnimateRunner} the animation runner
14420
15195
  */
14421
15196
  leave(element, options) {
@@ -14444,7 +15219,7 @@
14444
15219
  *
14445
15220
  * @param {Element} element the element which the CSS classes will be applied to
14446
15221
  * @param {string} className the CSS class(es) that will be added (multiple classes are separated via spaces)
14447
- * @param {AnimationOptions} [options] an optional collection of options/styles that will be applied to the element.
15222
+ * @param {import("./interface").AnimationOptions} [options] an optional collection of options/styles that will be applied to the element.
14448
15223
  * @return {import('./runner/animate-runner.js').AnimateRunner}} animationRunner the animation runner
14449
15224
  */
14450
15225
  addClass(element, className, options) {
@@ -14463,7 +15238,7 @@
14463
15238
  *
14464
15239
  * @param {Element} element the element which the CSS classes will be applied to
14465
15240
  * @param {string} className the CSS class(es) that will be removed (multiple classes are separated via spaces)
14466
- * @param {AnimationOptions} [options] an optional collection of options/styles that will be applied to the element. *
15241
+ * @param {import("./interface").AnimationOptions} [options] an optional collection of options/styles that will be applied to the element. *
14467
15242
  * @return {import('./runner/animate-runner.js').AnimateRunner} animationRunner the animation runner
14468
15243
  */
14469
15244
  removeClass(element, className, options) {
@@ -17887,7 +18662,7 @@
17887
18662
  );
17888
18663
  } else if (isObject(headers)) {
17889
18664
  Object.entries(headers).forEach(([headerKey, headerVal]) => {
17890
- fillInParsed(lowercase(headerKey), trim(headerVal));
18665
+ fillInParsed(headerKey.toLowerCase(), trim(headerVal));
17891
18666
  });
17892
18667
  }
17893
18668
 
@@ -17913,7 +18688,7 @@
17913
18688
  if (!headersObj) headersObj = parseHeaders(headers);
17914
18689
 
17915
18690
  if (name) {
17916
- let value = headersObj[lowercase(name)];
18691
+ let value = headersObj[name.toLowerCase()];
17917
18692
  if (value === undefined) {
17918
18693
  value = null;
17919
18694
  }
@@ -19878,7 +20653,7 @@
19878
20653
  }
19879
20654
 
19880
20655
  /**
19881
- * @returns {import("./interface.ts").LogService}
20656
+ * @returns {ng.LogService}
19882
20657
  */
19883
20658
  $get() {
19884
20659
  if (this._override) {
@@ -20022,6 +20797,15 @@
20022
20797
  return true;
20023
20798
  }
20024
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
+
20025
20809
  // Cross-origin or non-enumerable window objects
20026
20810
  try {
20027
20811
  return Object.prototype.toString.call(target) === "[object Window]";
@@ -20116,6 +20900,8 @@
20116
20900
 
20117
20901
  this.scheduled = [];
20118
20902
 
20903
+ this.$scopename = undefined;
20904
+
20119
20905
  /** @private */
20120
20906
  this.propertyMap = {
20121
20907
  $watch: this.$watch.bind(this),
@@ -20127,18 +20913,20 @@
20127
20913
  $apply: this.$apply.bind(this),
20128
20914
  $postUpdate: this.$postUpdate.bind(this),
20129
20915
  $isRoot: this.#isRoot.bind(this),
20130
- $proxy: this.$proxy,
20131
20916
  $on: this.$on.bind(this),
20132
20917
  $emit: this.$emit.bind(this),
20133
20918
  $broadcast: this.$broadcast.bind(this),
20134
20919
  $transcluded: this.$transcluded.bind(this),
20135
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,
20136
20925
  $parent: this.$parent,
20137
20926
  $root: this.$root,
20138
20927
  $children: this.$children,
20139
20928
  $id: this.$id,
20140
- $merge: this.$merge.bind(this),
20141
- $getById: this.$getById.bind(this),
20929
+ $scopename: this.$scopename,
20142
20930
  };
20143
20931
  }
20144
20932
 
@@ -20154,8 +20942,14 @@
20154
20942
  */
20155
20943
  set(target, property, value, proxy) {
20156
20944
  if (property === "undefined") {
20157
- throw new Error("Attempting to set undefined property");
20945
+ return false;
20946
+ }
20947
+
20948
+ if (property === "$scopename") {
20949
+ this.$scopename = value;
20950
+ return true;
20158
20951
  }
20952
+
20159
20953
  if (
20160
20954
  (target.constructor?.$nonscope &&
20161
20955
  Array.isArray(target.constructor.$nonscope) &&
@@ -20372,9 +21166,9 @@
20372
21166
  * @returns {*} - The value of the property or a method if accessing `watch` or `sync`.
20373
21167
  */
20374
21168
  get(target, property, proxy) {
21169
+ if (property === "$scopename" && this.$scopename) return this.$scopename;
20375
21170
  if (property === "$$watchersCount") return calculateWatcherCount(this);
20376
21171
  if (property === isProxySymbol) return true;
20377
-
20378
21172
  if (target[property] && isProxy(target[property])) {
20379
21173
  this.$proxy = target[property];
20380
21174
  } else {
@@ -20403,7 +21197,6 @@
20403
21197
  this.#scheduleListener(this.scheduled);
20404
21198
  }
20405
21199
  }
20406
-
20407
21200
  if (hasOwn(this.propertyMap, property)) {
20408
21201
  this.$target = target;
20409
21202
  return this.propertyMap[property];
@@ -20501,7 +21294,7 @@
20501
21294
  * function is invoked when changes to that property are detected.
20502
21295
  *
20503
21296
  * @param {string} watchProp - An expression to be watched in the context of this model.
20504
- * @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.
20505
21298
  * @param {boolean} [lazy] - A flag to indicate if the listener should be invoked immediately. Defaults to false.
20506
21299
  */
20507
21300
  $watch(watchProp, listenerFn, lazy = false) {
@@ -20523,7 +21316,7 @@
20523
21316
  return () => {};
20524
21317
  }
20525
21318
 
20526
- /** @type {import('./interface.ts').Listener} */
21319
+ /** @type {ng.Listener} */
20527
21320
  const listener = {
20528
21321
  originalTarget: this.$target,
20529
21322
  listenerFn: listenerFn,
@@ -20581,13 +21374,34 @@
20581
21374
  }
20582
21375
  // 6
20583
21376
  case ASTType.BinaryExpression: {
20584
- let expr = get.decoratedNode.body[0].expression.toWatch[0];
20585
- key = expr.property ? expr.property.name : expr.name;
20586
- if (!key) {
20587
- 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
+ };
20588
21404
  }
20589
- listener.property.push(key);
20590
- break;
20591
21405
  }
20592
21406
  // 7
20593
21407
  case ASTType.UnaryExpression: {
@@ -21127,6 +21941,26 @@
21127
21941
  return res;
21128
21942
  }
21129
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
+ }
21130
21964
  }
21131
21965
 
21132
21966
  /*------------- Private helpers -------------*/
@@ -21354,25 +22188,31 @@
21354
22188
  }
21355
22189
 
21356
22190
  /**
21357
- * @returns {import("./interface").SanitizerFn}
22191
+ * @returns {import("./interface.ts").SanitizerFn}
21358
22192
  */
21359
- $get() {
21360
- return (uri, isMediaUrl) => {
21361
- 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;
21362
22200
 
21363
- /** @type {RegExp} */
21364
- const regex = isMediaUrl
21365
- ? this._imgSrcSanitizationTrustedUrlList
21366
- : this._aHrefSanitizationTrustedUrlList;
22201
+ /** @type {RegExp} */
22202
+ const regex = isMediaUrl
22203
+ ? this._imgSrcSanitizationTrustedUrlList
22204
+ : this._aHrefSanitizationTrustedUrlList;
21367
22205
 
21368
- const normalizedVal = urlResolve(uri.trim()).href;
22206
+ const normalizedVal = new URL(uri.trim(), $window.location.href).href;
21369
22207
 
21370
- if (normalizedVal !== "" && !normalizedVal.match(regex)) {
21371
- return `unsafe:${normalizedVal}`;
21372
- }
21373
- return uri;
21374
- };
21375
- }
22208
+ if (normalizedVal !== "" && !normalizedVal.match(regex)) {
22209
+ return `unsafe:${normalizedVal}`;
22210
+ }
22211
+ return uri;
22212
+ }
22213
+ );
22214
+ },
22215
+ ];
21376
22216
  }
21377
22217
 
21378
22218
  const ACTIVE_CLASS = "ng-active";
@@ -21381,9 +22221,9 @@
21381
22221
  class NgMessageCtrl {
21382
22222
  /**
21383
22223
  * @param {Element} $element
21384
- * @param {import('../../core/scope/scope.js').Scope} $scope
21385
- * @param {import('../../core/compile/attributes').Attributes} $attrs
21386
- * @param {*} $animate
22224
+ * @param {ng.Scope} $scope
22225
+ * @param {ng.Attributes} $attrs
22226
+ * @param {ng.AnimateService} $animate
21387
22227
  */
21388
22228
  constructor($element, $scope, $attrs, $animate) {
21389
22229
  this.$element = $element;
@@ -21567,6 +22407,10 @@
21567
22407
  }
21568
22408
 
21569
22409
  ngMessagesDirective.$inject = ["$animate"];
22410
+ /**
22411
+ * @param {ng.AnimateService} $animate
22412
+ * @returns {ng.Directive<NgMessageCtrl>}
22413
+ */
21570
22414
  function ngMessagesDirective($animate) {
21571
22415
  return {
21572
22416
  require: "ngMessages",
@@ -21613,10 +22457,14 @@
21613
22457
 
21614
22458
  /**
21615
22459
  * @param {boolean} isDefault
21616
- * @returns {(any) => import("../../interface.ts").Directive}
22460
+ * @returns {(any) => ng.Directive}
21617
22461
  */
21618
22462
  function ngMessageDirectiveFactory(isDefault) {
21619
22463
  ngMessageDirective.$inject = ["$animate"];
22464
+ /**
22465
+ * @param {ng.AnimateService} $animate
22466
+ * @returns {ng.Directive}
22467
+ */
21620
22468
  function ngMessageDirective($animate) {
21621
22469
  return {
21622
22470
  restrict: "AE",
@@ -22107,7 +22955,7 @@
22107
22955
  * @fileoverview
22108
22956
  * Frame-synchronized animation runner and scheduler.
22109
22957
  * Provides async batching of animation callbacks using requestAnimationFrame.
22110
- * In AngularJS, this user to be implemented as `$$AnimateRunner`
22958
+ * In AngularJS, this used to be implemented as `$$AnimateRunner`
22111
22959
  */
22112
22960
 
22113
22961
  /**
@@ -23208,6 +24056,7 @@
23208
24056
 
23209
24057
  const NG_ANIMATE_ATTR_NAME = "data-ng-animate";
23210
24058
  const NG_ANIMATE_PIN_DATA = "$ngAnimatePin";
24059
+
23211
24060
  AnimateQueueProvider.$inject = ["$animateProvider"];
23212
24061
  function AnimateQueueProvider($animateProvider) {
23213
24062
  const PRE_DIGEST_STATE = 1;
@@ -23337,8 +24186,8 @@
23337
24186
  * @param {ng.RootScopeService} $rootScope
23338
24187
  * @param {ng.InjectorService} $injector
23339
24188
  * @param {*} $$animation
23340
- * @param {*} $templateRequest
23341
- * @returns
24189
+ * @param {ng.TemplateRequestService} $templateRequest
24190
+ * @returns {import("../queue/interface.ts").AnimateQueueService}
23342
24191
  */
23343
24192
  function ($rootScope, $injector, $$animation, $templateRequest) {
23344
24193
  const activeAnimationsLookup = new Map();
@@ -23506,12 +24355,6 @@
23506
24355
  },
23507
24356
 
23508
24357
  pin(element, parentElement) {
23509
- assertArg(isElement(element), "element", "not an element");
23510
- assertArg(
23511
- isElement(parentElement),
23512
- "parentElement",
23513
- "not an element",
23514
- );
23515
24358
  setCacheData(element, NG_ANIMATE_PIN_DATA, parentElement);
23516
24359
  },
23517
24360
 
@@ -23852,6 +24695,18 @@
23852
24695
  }
23853
24696
  }
23854
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
+ */
23855
24710
  function closeChildAnimations(node) {
23856
24711
  const children = node.querySelectorAll(`[${NG_ANIMATE_ATTR_NAME}]`);
23857
24712
  children.forEach((child) => {
@@ -24397,8 +25252,8 @@
24397
25252
  /**
24398
25253
  *
24399
25254
  * @param {ng.RootScopeService} $rootScope
24400
- * @param {import("../core/di/internal-injector").InjectorService} $injector
24401
- * @param {import("./raf-scheduler").RafScheduler} $$rAFScheduler
25255
+ * @param {ng.InjectorService} $injector
25256
+ * @param {import("./raf-scheduler.js").RafScheduler} $$rAFScheduler
24402
25257
  * @param {*} $$animateCache
24403
25258
  * @returns
24404
25259
  */
@@ -24517,9 +25372,9 @@
24517
25372
  return runner;
24518
25373
  }
24519
25374
 
24520
- let classes = mergeClasses$1(
25375
+ let classes = mergeClasses(
24521
25376
  element.getAttribute("class"),
24522
- mergeClasses$1(options.addClass, options.removeClass),
25377
+ mergeClasses(options.addClass, options.removeClass),
24523
25378
  );
24524
25379
  let { tempClasses } = options;
24525
25380
  if (tempClasses) {
@@ -26676,6 +27531,7 @@
26676
27531
  }
26677
27532
  return JSON.stringify(o, (key, value) => format(value)).replace(/\\"/g, '"');
26678
27533
  }
27534
+
26679
27535
  const stripLastPathElement = (str) => str.replace(/\/[^/]*$/, "");
26680
27536
  /**
26681
27537
  * Splits on a delimiter, but returns the delimiters in the array
@@ -34711,7 +35567,7 @@
34711
35567
  "$interpolate",
34712
35568
  /**
34713
35569
  * @param {*} $view
34714
- * @param {*} $animate
35570
+ * @param {ng.AnimateService} $animate
34715
35571
  * @param {*} $viewScroll
34716
35572
  * @param {*} $interpolate
34717
35573
  * @returns {import("../../interface.ts").Directive}
@@ -35139,417 +35995,6 @@
35139
35995
  };
35140
35996
  }
35141
35997
 
35142
- /**
35143
- * @param {"get" | "delete" | "post" | "put"} method - HTTP method applied to request
35144
- * @param {string} [attrOverride] - Custom name to use for the attribute
35145
- * @returns {ng.DirectiveFactory}
35146
- */
35147
- function defineDirective(method, attrOverride) {
35148
- const attrName =
35149
- attrOverride || "ng" + method.charAt(0).toUpperCase() + method.slice(1);
35150
- const directive = createHttpDirective(method, attrName);
35151
- directive["$inject"] = [
35152
- $injectTokens.$http,
35153
- $injectTokens.$compile,
35154
- $injectTokens.$log,
35155
- $injectTokens.$parse,
35156
- $injectTokens.$state,
35157
- $injectTokens.$sse,
35158
- $injectTokens.$animate,
35159
- ];
35160
- return directive;
35161
- }
35162
-
35163
- /** @type {ng.DirectiveFactory} */
35164
- const ngGetDirective = defineDirective("get");
35165
-
35166
- /** @type {ng.DirectiveFactory} */
35167
- const ngDeleteDirective = defineDirective("delete");
35168
-
35169
- /** @type {ng.DirectiveFactory} */
35170
- const ngPostDirective = defineDirective("post");
35171
-
35172
- /** @type {ng.DirectiveFactory} */
35173
- const ngPutDirective = defineDirective("put");
35174
-
35175
- /** @type {ng.DirectiveFactory} */
35176
- const ngSseDirective = defineDirective("get", "ngSse");
35177
-
35178
- /**
35179
- * Selects DOM event to listen for based on the element type.
35180
- *
35181
- * @param {Element} element - The DOM element to inspect.
35182
- * @returns {"click" | "change" | "submit"} The name of the event to listen for.
35183
- */
35184
- function getEventNameForElement(element) {
35185
- const tag = element.tagName.toLowerCase();
35186
- if (["input", "textarea", "select"].includes(tag)) {
35187
- return "change";
35188
- } else if (tag === "form") {
35189
- return "submit";
35190
- }
35191
- return "click";
35192
- }
35193
-
35194
- /**
35195
- * Creates an HTTP directive factory that supports GET, DELETE, POST, PUT.
35196
- *
35197
- * @param {"get" | "delete" | "post" | "put"} method - HTTP method to use.
35198
- * @param {string} attrName - Attribute name containing the URL.
35199
- * @returns {ng.DirectiveFactory}
35200
- */
35201
- function createHttpDirective(method, attrName) {
35202
- let content = undefined;
35203
-
35204
- /**
35205
- * @param {ng.HttpService} $http
35206
- * @param {ng.CompileService} $compile
35207
- * @param {ng.LogService} $log
35208
- * @param {ng.ParseService} $parse
35209
- * @param {ng.StateService} $state
35210
- * @param {ng.SseService} $sse
35211
- * @returns {ng.Directive}
35212
- */
35213
- return function ($http, $compile, $log, $parse, $state, $sse, $animate) {
35214
- /**
35215
- * Handles DOM manipulation based on a swap strategy and server-rendered HTML.
35216
- *
35217
- * @param {string | Object} html - The HTML string or object returned from the server.
35218
- * @param {import("./interface.ts").SwapModeType} swap
35219
- * @param {ng.Scope} scope
35220
- * @param {ng.Attributes} attrs
35221
- * @param {Element} element
35222
- */
35223
- function handleSwapResponse(html, swap, scope, attrs, element) {
35224
- let animationEnabled = false;
35225
- if (attrs.animate) {
35226
- animationEnabled = true;
35227
- }
35228
- let nodes = [];
35229
- if (!["textcontent", "delete", "none"].includes(swap)) {
35230
- if (!html) return;
35231
- const compiled = $compile(html)(scope);
35232
- nodes =
35233
- compiled instanceof DocumentFragment
35234
- ? Array.from(compiled.childNodes)
35235
- : [compiled];
35236
- }
35237
-
35238
- const targetSelector = attrs["target"];
35239
- const target = targetSelector
35240
- ? document.querySelector(targetSelector)
35241
- : element;
35242
-
35243
- if (!target) {
35244
- $log.warn(`${attrName}: target "${targetSelector}" not found`);
35245
- return;
35246
- }
35247
-
35248
- switch (swap) {
35249
- case "innerHTML":
35250
- if (animationEnabled) {
35251
- if (content) {
35252
- $animate.leave(content).done(() => {
35253
- content = nodes[0];
35254
- $animate.enter(nodes[0], target);
35255
- scope.$flushQueue();
35256
- });
35257
- scope.$flushQueue();
35258
- } else {
35259
- content = nodes[0];
35260
- $animate.enter(nodes[0], target);
35261
- scope.$flushQueue();
35262
- }
35263
- } else {
35264
- target.replaceChildren(...nodes);
35265
- }
35266
- break;
35267
-
35268
- case "outerHTML": {
35269
- const parent = target.parentNode;
35270
- if (!parent) return;
35271
- const frag = document.createDocumentFragment();
35272
- nodes.forEach((n) => frag.appendChild(n));
35273
- if (animationEnabled) {
35274
- const placeholder = document.createComment("placeholder");
35275
- target.parentNode.insertBefore(placeholder, target.nextSibling);
35276
- $animate.leave(target).done(() => {
35277
- const insertedNodes = Array.from(frag.childNodes);
35278
- insertedNodes.forEach((n) =>
35279
- $animate.enter(n, parent, placeholder),
35280
- );
35281
- content = insertedNodes;
35282
- scope.$flushQueue();
35283
- });
35284
- scope.$flushQueue();
35285
- } else {
35286
- parent.replaceChild(frag, target);
35287
- }
35288
- break;
35289
- }
35290
-
35291
- case "textContent":
35292
- target.textContent = html;
35293
- break;
35294
-
35295
- case "beforebegin":
35296
- nodes.forEach((node) => target.parentNode.insertBefore(node, target));
35297
- break;
35298
-
35299
- case "afterbegin":
35300
- nodes
35301
- .slice()
35302
- .reverse()
35303
- .forEach((node) => target.insertBefore(node, target.firstChild));
35304
- break;
35305
-
35306
- case "beforeend":
35307
- nodes.forEach((node) => target.appendChild(node));
35308
- break;
35309
-
35310
- case "afterend":
35311
- nodes
35312
- .slice()
35313
- .reverse()
35314
- .forEach((node) =>
35315
- target.parentNode.insertBefore(node, target.nextSibling),
35316
- );
35317
- break;
35318
-
35319
- case "delete":
35320
- target.remove();
35321
- break;
35322
-
35323
- case "none":
35324
- break;
35325
-
35326
- default:
35327
- target.replaceChildren(...nodes);
35328
- break;
35329
- }
35330
- }
35331
-
35332
- /**
35333
- * Collects form data from the element or its associated form.
35334
- *
35335
- * @param {HTMLElement} element
35336
- * @returns {Object<string, any>}
35337
- */
35338
- function collectFormData(element) {
35339
- /** @type {HTMLFormElement | null} */
35340
- let form = null;
35341
-
35342
- const tag = element.tagName.toLowerCase();
35343
-
35344
- if (tag === "form") {
35345
- form = /** @type {HTMLFormElement} */ (element);
35346
- } else if ("form" in element && element.form) {
35347
- form = /** @type {HTMLFormElement} */ (element.form);
35348
- } else if (element.hasAttribute("form")) {
35349
- const formId = element.getAttribute("form");
35350
- if (formId) {
35351
- const maybeForm = document.getElementById(formId);
35352
- if (maybeForm && maybeForm.tagName.toLowerCase() === "form") {
35353
- form = /** @type {HTMLFormElement} */ (maybeForm);
35354
- }
35355
- }
35356
- }
35357
-
35358
- if (!form) {
35359
- if (
35360
- "name" in element &&
35361
- typeof element.name === "string" &&
35362
- element.name.length > 0
35363
- ) {
35364
- if (
35365
- element instanceof HTMLInputElement ||
35366
- element instanceof HTMLTextAreaElement ||
35367
- element instanceof HTMLSelectElement
35368
- ) {
35369
- const key = element.name;
35370
- const value = element.value;
35371
- return { [key]: value };
35372
- }
35373
- }
35374
- return {};
35375
- }
35376
-
35377
- const formData = new FormData(form);
35378
- const data = {};
35379
- formData.forEach((value, key) => {
35380
- data[key] = value;
35381
- });
35382
- return data;
35383
- }
35384
-
35385
- return {
35386
- restrict: "A",
35387
- link(scope, element, attrs) {
35388
- const eventName = attrs.trigger || getEventNameForElement(element);
35389
- const tag = element.tagName.toLowerCase();
35390
-
35391
- if (isDefined(attrs.latch)) {
35392
- attrs.$observe(
35393
- "latch",
35394
- callBackAfterFirst(() =>
35395
- element.dispatchEvent(new Event(eventName)),
35396
- ),
35397
- );
35398
- }
35399
-
35400
- let throttled = false;
35401
- let intervalId;
35402
-
35403
- if (isDefined(attrs["interval"])) {
35404
- element.dispatchEvent(new Event(eventName));
35405
- intervalId = setInterval(
35406
- () => element.dispatchEvent(new Event(eventName)),
35407
- parseInt(attrs.interval) || 1000,
35408
- );
35409
- }
35410
-
35411
- element.addEventListener(eventName, async (event) => {
35412
- if (/** @type {HTMLButtonElement} */ (element).disabled) return;
35413
- if (tag === "form") event.preventDefault();
35414
- const swap = attrs.swap || "innerHTML";
35415
- const url = attrs[attrName];
35416
- if (!url) {
35417
- $log.warn(`${attrName}: no URL specified`);
35418
- return;
35419
- }
35420
-
35421
- const handler = (res) => {
35422
- if (isDefined(attrs.loading)) {
35423
- attrs.$set("loading", false);
35424
- }
35425
-
35426
- if (isDefined(attrs.loadingClass)) {
35427
- attrs.$removeClass(attrs.loadingClass);
35428
- }
35429
-
35430
- const html = res.data;
35431
- if (200 <= res.status && res.status <= 299) {
35432
- if (isDefined(attrs.success)) {
35433
- $parse(attrs.success)(scope, { $res: html });
35434
- }
35435
-
35436
- if (isDefined(attrs.stateSuccess)) {
35437
- $state.go(attrs.stateSuccess);
35438
- }
35439
- } else if (400 <= res.status && res.status <= 599) {
35440
- if (isDefined(attrs.error)) {
35441
- $parse(attrs.error)(scope, { $res: html });
35442
- }
35443
-
35444
- if (isDefined(attrs.stateError)) {
35445
- $state.go(attrs.stateError);
35446
- }
35447
- }
35448
-
35449
- if (isObject(html)) {
35450
- if (attrs.target) {
35451
- scope.$eval(`${attrs.target} = ${JSON.stringify(html)}`);
35452
- } else {
35453
- scope.$merge(html);
35454
- }
35455
- } else if (isString(html)) {
35456
- handleSwapResponse(html, swap, scope, attrs, element);
35457
- }
35458
- };
35459
-
35460
- if (isDefined(attrs.delay)) {
35461
- await wait(parseInt(attrs.delay) | 0);
35462
- }
35463
-
35464
- if (throttled) return;
35465
-
35466
- if (isDefined(attrs.throttle)) {
35467
- throttled = true;
35468
- attrs.$set("throttled", true);
35469
- setTimeout(() => {
35470
- attrs.$set("throttled", false);
35471
- throttled = false;
35472
- }, parseInt(attrs.throttle));
35473
- }
35474
-
35475
- if (isDefined(attrs["loading"])) {
35476
- attrs.$set("loading", true);
35477
- }
35478
-
35479
- if (isDefined(attrs["loadingClass"])) {
35480
- attrs.$addClass(attrs.loadingClass);
35481
- }
35482
-
35483
- if (method === "post" || method === "put") {
35484
- let data;
35485
- const config = {};
35486
- if (attrs.enctype) {
35487
- config.headers = {
35488
- "Content-Type": attrs["enctype"],
35489
- };
35490
- data = toKeyValue(collectFormData(element));
35491
- } else {
35492
- data = collectFormData(element);
35493
- }
35494
- $http[method](url, data, config).then(handler).catch(handler);
35495
- } else {
35496
- if (method === "get" && attrs.ngSse) {
35497
- const sseUrl = url;
35498
- const config = {
35499
- withCredentials: attrs.withCredentials === "true",
35500
- transformMessage: (data) => {
35501
- try {
35502
- return JSON.parse(data);
35503
- } catch {
35504
- return data;
35505
- }
35506
- },
35507
- onOpen: () => {
35508
- $log.info(`${attrName}: SSE connection opened to ${sseUrl}`);
35509
- if (isDefined(attrs.loading)) attrs.$set("loading", false);
35510
- if (isDefined(attrs.loadingClass))
35511
- attrs.$removeClass(attrs.loadingClass);
35512
- },
35513
- onMessage: (data) => {
35514
- const res = { status: 200, data };
35515
- handler(res);
35516
- },
35517
- onError: (err) => {
35518
- $log.error(`${attrName}: SSE error`, err);
35519
- const res = { status: 500, data: err };
35520
- handler(res);
35521
- },
35522
- onReconnect: (count) => {
35523
- $log.info(`ngSse: reconnected ${count} time(s)`);
35524
- if (attrs.onReconnect)
35525
- $parse(attrs.onReconnect)(scope, { $count: count });
35526
- },
35527
- };
35528
-
35529
- const source = $sse(sseUrl, config);
35530
-
35531
- scope.$on("$destroy", () => {
35532
- $log.info(`${attrName}: closing SSE connection`);
35533
- source.close();
35534
- });
35535
- } else {
35536
- $http[method](url).then(handler).catch(handler);
35537
- }
35538
- }
35539
- });
35540
-
35541
- if (intervalId) {
35542
- scope.$on("$destroy", () => clearInterval(intervalId));
35543
- }
35544
-
35545
- if (eventName == "load") {
35546
- element.dispatchEvent(new Event("load"));
35547
- }
35548
- },
35549
- };
35550
- };
35551
- }
35552
-
35553
35998
  ngInjectDirective.$inject = [$injectTokens.$log, $injectTokens.$injector];
35554
35999
 
35555
36000
  /**
@@ -35643,13 +36088,13 @@
35643
36088
  };
35644
36089
  }
35645
36090
 
35646
- /**
35647
- * Returns the $sse service function
35648
- * @returns {ng.SseService}
35649
- */
35650
36091
  $get = [
35651
36092
  $injectTokens.$log,
35652
- /** @param {ng.LogService} log */
36093
+ /**
36094
+ * Returns the $sse service function
36095
+ * @param {ng.LogService} log
36096
+ * @returns {ng.SseService}
36097
+ */
35653
36098
  (log) => {
35654
36099
  this.$log = log;
35655
36100
  return (url, config = {}) => {
@@ -35744,7 +36189,7 @@
35744
36189
  es.close();
35745
36190
  },
35746
36191
  connect() {
35747
- if (closed == false) {
36192
+ if (closed === false) {
35748
36193
  close();
35749
36194
  }
35750
36195
  connect();
@@ -35806,246 +36251,29 @@
35806
36251
  };
35807
36252
  }
35808
36253
 
35809
- ngWorkerDirective.$inject = ["$worker", $injectTokens.$parse, $injectTokens.$log];
35810
36254
  /**
35811
- * ngWorker directive factory
35812
- * Usage: <div ng-worker="workerName" data-params="{{ expression }}" data-on-result="callback($result)"></div>
36255
+ * @return {ng.Directive}
35813
36256
  */
35814
- function ngWorkerDirective($worker, $parse, $log) {
36257
+ function ngWasmDirective() {
35815
36258
  return {
35816
- restrict: "A",
35817
- link(scope, element, attrs) {
35818
- const workerName = attrs.ngWorker;
35819
- if (!workerName) {
35820
- $log.warn("ngWorker: missing worker name");
35821
- return;
35822
- }
35823
-
35824
- const eventName = attrs.trigger || getEventNameForElement(element);
35825
-
35826
- let throttled = false;
35827
- let intervalId;
35828
-
35829
- if (isDefined(attrs.latch)) {
35830
- attrs.$observe(
35831
- "latch",
35832
- callBackAfterFirst(() => element.dispatchEvent(new Event(eventName))),
35833
- );
35834
- }
35835
-
35836
- if (isDefined(attrs.interval)) {
35837
- element.dispatchEvent(new Event(eventName));
35838
- intervalId = setInterval(
35839
- () => element.dispatchEvent(new Event(eventName)),
35840
- parseInt(attrs.interval) || 1000,
35841
- );
35842
- }
35843
-
35844
- const worker = $worker(workerName, {
35845
- onMessage: (result) => {
35846
- if (isDefined(attrs.dataOnResult)) {
35847
- $parse(attrs.dataOnResult)(scope, { $result: result });
35848
- } else {
35849
- const swap = attrs.swap || "innerHTML";
35850
- handleSwap(result, swap, element);
35851
- }
35852
- },
35853
- onError: (err) => {
35854
- $log.error(`[ng-worker:${workerName}]`, err);
35855
- if (isDefined(attrs.dataOnError)) {
35856
- $parse(attrs.dataOnError)(scope, { $error: err });
35857
- } else {
35858
- element.textContent = "Error";
35859
- }
35860
- },
35861
- });
35862
-
35863
- element.addEventListener(eventName, async () => {
35864
- if (element.disabled) return;
35865
-
35866
- if (isDefined(attrs.delay)) {
35867
- await wait(parseInt(attrs.delay) || 0);
35868
- }
35869
-
35870
- if (throttled) return;
35871
-
35872
- if (isDefined(attrs.throttle)) {
35873
- throttled = true;
35874
- attrs.$set("throttled", true);
35875
- setTimeout(() => {
35876
- attrs.$set("throttled", false);
35877
- throttled = false;
35878
- }, parseInt(attrs.throttle));
35879
- }
35880
-
35881
- let params;
35882
- try {
35883
- params = attrs.params ? scope.$eval(attrs.params) : undefined;
35884
- } catch (err) {
35885
- $log.error("ngWorker: failed to evaluate data-params", err);
35886
- params = undefined;
35887
- }
35888
-
35889
- worker.post(params);
35890
- });
35891
-
35892
- if (intervalId) {
35893
- scope.$on("$destroy", () => clearInterval(intervalId));
35894
- }
35895
-
35896
- if (eventName === "load") {
35897
- element.dispatchEvent(new Event("load"));
35898
- }
36259
+ async link($scope, _, $attrs) {
36260
+ $scope.$target[$attrs.as || "wasm"] = (
36261
+ await instantiateWasm($attrs.src)
36262
+ ).exports;
35899
36263
  },
35900
36264
  };
35901
36265
  }
35902
36266
 
35903
36267
  /**
35904
- * Swap result into DOM based on strategy
35905
- */
35906
- function handleSwap(result, swap, element) {
35907
- switch (swap) {
35908
- case "outerHTML": {
35909
- const parent = element.parentNode;
35910
- if (!parent) return;
35911
- const temp = document.createElement("div");
35912
- temp.innerHTML = result;
35913
- parent.replaceChild(temp.firstChild, element);
35914
- break;
35915
- }
35916
- case "textContent":
35917
- element.textContent = result;
35918
- break;
35919
- case "beforebegin":
35920
- element.insertAdjacentHTML("beforebegin", result);
35921
- break;
35922
- case "afterbegin":
35923
- element.insertAdjacentHTML("afterbegin", result);
35924
- break;
35925
- case "beforeend":
35926
- element.insertAdjacentHTML("beforeend", result);
35927
- break;
35928
- case "afterend":
35929
- element.insertAdjacentHTML("afterend", result);
35930
- break;
35931
- case "innerHTML":
35932
- default:
35933
- element.innerHTML = result;
35934
- break;
35935
- }
35936
- }
35937
-
35938
- /**
35939
- * Worker Provider
35940
- *
35941
- * Usage:
35942
- * const worker = $worker('./math.worker.js', {
35943
- * onMessage: (data) => console.log('Result:', data),
35944
- * onError: (err) => console.error('Worker error:', err),
35945
- * autoTerminate: false,
35946
- * transformMessage: (d) => d,
35947
- * });
35948
- *
35949
- * worker.post({ action: 'fib', n: 20 });
35950
- * worker.terminate();
36268
+ * @return {ng.Directive}
35951
36269
  */
35952
- class WorkerProvider {
35953
- /**
35954
- * @type {ng.LogService}
35955
- */
35956
- $log;
35957
- constructor() {
35958
- /**
35959
- * Optional provider-level defaults
35960
- * @type {ng.WorkerConfig}
35961
- */
35962
- this.defaults = {
35963
- autoTerminate: false,
35964
- transformMessage(data) {
35965
- try {
35966
- return JSON.parse(data);
35967
- } catch {
35968
- return data;
35969
- }
35970
- },
35971
- };
35972
- }
35973
-
35974
- /**
35975
- * Returns the $worker service function
35976
- * @returns {ng.WorkerService}
35977
- */
35978
- $get = [
35979
- $injectTokens.$log,
35980
- /** @param {ng.LogService} log */
35981
- (log) => {
35982
- this.$log = log;
35983
- return (scriptPath, config = {}) => {
35984
- const merged = { ...this.defaults, ...config };
35985
- return this.#createWorker(scriptPath, merged);
35986
- };
36270
+ function ngScopeDirective() {
36271
+ return {
36272
+ scope: false,
36273
+ async link($scope, _, $attrs) {
36274
+ $scope.$scopename = $attrs.ngScope;
35987
36275
  },
35988
- ];
35989
-
35990
- /**
35991
- * Creates a managed Web Worker instance
35992
- * @param {string | URL} scriptPath
35993
- * @param {ng.WorkerConfig} config
35994
- * @returns {import("./interface.ts").WorkerConnection}
35995
- */
35996
- #createWorker(scriptPath, config) {
35997
- if (!scriptPath) throw new Error("Worker script path required");
35998
-
35999
- let worker = new Worker(scriptPath, { type: "module" });
36000
- let terminated = false;
36001
-
36002
- const reconnect = () => {
36003
- if (terminated) return;
36004
- this.$log.info("Worker: restarting...");
36005
- worker.terminate();
36006
- worker = new Worker(scriptPath, { type: "module" });
36007
- wire(worker);
36008
- };
36009
-
36010
- const wire = (w) => {
36011
- w.onmessage = (e) => {
36012
- let data = e.data;
36013
- try {
36014
- data = config.transformMessage ? config.transformMessage(data) : data;
36015
- } catch {
36016
- /* no-op */
36017
- }
36018
- config.onMessage?.(data, e);
36019
- };
36020
-
36021
- w.onerror = (err) => {
36022
- config.onError?.(err);
36023
- if (config.autoRestart) reconnect();
36024
- };
36025
- };
36026
-
36027
- wire(worker);
36028
- let that = this;
36029
- return {
36030
- post(data) {
36031
- if (terminated) return that.$log.warn("Worker already terminated");
36032
- try {
36033
- worker.postMessage(data);
36034
- } catch (err) {
36035
- that.$log.error("Worker post failed", err);
36036
- }
36037
- },
36038
- terminate() {
36039
- terminated = true;
36040
- worker.terminate();
36041
- },
36042
- restart() {
36043
- if (terminated)
36044
- return that.$log.warn("Worker cannot restart after terminate");
36045
- reconnect();
36046
- },
36047
- };
36048
- }
36276
+ };
36049
36277
  }
36050
36278
 
36051
36279
  /**
@@ -36127,7 +36355,9 @@
36127
36355
  ngValue: ngValueDirective,
36128
36356
  ngModelOptions: ngModelOptionsDirective,
36129
36357
  ngViewport: ngViewportDirective,
36358
+ ngWasm: ngWasmDirective,
36130
36359
  ngWorker: ngWorkerDirective,
36360
+ ngScope: ngScopeDirective,
36131
36361
  })
36132
36362
  .directive({
36133
36363
  input: hiddenInputBrowserCacheDirective,
@@ -36194,7 +36424,6 @@
36194
36424
  $url: UrlService,
36195
36425
  $stateRegistry: StateRegistryProvider,
36196
36426
  $eventBus: PubSubProvider,
36197
- $worker: WorkerProvider,
36198
36427
  });
36199
36428
  },
36200
36429
  ],
@@ -36226,7 +36455,7 @@
36226
36455
  /**
36227
36456
  * @type {string} `version` from `package.json`
36228
36457
  */
36229
- this.version = "0.11.0"; //inserted via rollup plugin
36458
+ this.version = "0.12.0"; //inserted via rollup plugin
36230
36459
 
36231
36460
  /** @type {!Array<string|any>} */
36232
36461
  this.bootsrappedModules = [];
@@ -36246,7 +36475,7 @@
36246
36475
 
36247
36476
  /**
36248
36477
  * Gets scope for a given element.
36249
- * @type {(Element) => *}
36478
+ * @type {(Element) => ng.Scope}
36250
36479
  */
36251
36480
  this.getScope = getScope;
36252
36481
 
@@ -36257,6 +36486,70 @@
36257
36486
  registerNgModule(this);
36258
36487
  }
36259
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
+
36260
36553
  /**
36261
36554
  * Use this function to manually start up AngularTS application.
36262
36555
  *
@@ -36341,6 +36634,7 @@
36341
36634
  * @param {ng.InjectorService} $injector
36342
36635
  */
36343
36636
  (scope, el, compile, $injector) => {
36637
+ this.$rootScope = scope;
36344
36638
  // ng-route deps
36345
36639
  this.$injector = $injector; // TODO refactor away as this as this prevents multiple apps from being used
36346
36640
 
@@ -36424,70 +36718,30 @@
36424
36718
  }
36425
36719
 
36426
36720
  /**
36721
+ * Retrieves a scope by its registered name and returns its Proxy wrapper.
36427
36722
  *
36428
- * The `angular.module` is a global place for creating, registering and retrieving AngularTS
36429
- * modules.
36430
- * All modules (AngularTS core or 3rd party) that should be available to an application must be
36431
- * registered using this mechanism.
36432
- *
36433
- * Passing one argument retrieves an existing {@link import('./interface.ts').Module},
36434
- * whereas passing more than one argument creates a new {@link import('./interface.ts').Module}
36435
- *
36436
- *
36437
- * # Module
36438
- *
36439
- * A module is a collection of services, directives, controllers, filters, and configuration information.
36440
- * `angular.module` is used to configure the {@link auto.$injector $injector}.
36441
- *
36442
- * ```js
36443
- * // Create a new module
36444
- * let myModule = angular.module('myModule', []);
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.
36445
36727
  *
36446
- * // register a new service
36447
- * myModule.value('appName', 'MyCoolApp');
36448
- *
36449
- * // configure existing services inside initialization blocks.
36450
- * myModule.config(['$locationProvider', function($locationProvider) {
36451
- * // Configure existing providers
36452
- * $locationProvider.hashPrefix('!');
36453
- * }]);
36454
- * ```
36455
- *
36456
- * Then you can create an injector and load your modules like this:
36457
- *
36458
- * ```js
36459
- * let injector = angular.injector(['ng', 'myModule'])
36460
- * ```
36461
- *
36462
- * However it's more likely that you'll just use
36463
- * {@link ng.directive:ngApp ngApp} or
36464
- * {@link angular.bootstrap} to simplify this process for you.
36465
- *
36466
- * @param {string} name The name of the module to create or retrieve.
36467
- * @param {Array.<string>} [requires] If specified then new module is being created. If
36468
- * unspecified then the module is being retrieved for further configuration.
36469
- * @param {import("./interface.ts").Injectable<any>} [configFn] Optional configuration function for the module that gets
36470
- * passed to {@link NgModule.config NgModule.config()}.
36471
- * @returns {NgModule} A newly registered module.
36728
+ * @param {string} name
36729
+ * @returns {ProxyHandler<ng.Scope>|undefined}
36472
36730
  */
36473
- module(name, requires, configFn) {
36474
- assertNotHasOwnProperty(name, "module");
36475
- if (requires && hasOwn(modules, name)) {
36476
- modules[name] = null;
36731
+ getScopeByName(name) {
36732
+ const scope = this.$rootScope.$searchByName(name);
36733
+ if (scope) {
36734
+ return scope.$proxy;
36477
36735
  }
36478
- return ensure(modules, name, () => {
36479
- if (!requires) {
36480
- throw $injectorMinErr(
36481
- "nomod",
36482
- "Module '{0}' is not available. Possibly misspelled or not loaded",
36483
- name,
36484
- );
36485
- }
36486
- return new NgModule(name, requires, configFn);
36487
- });
36488
36736
  }
36489
36737
  }
36490
36738
 
36739
+ /**
36740
+ * @param {Object.<string, NgModule>} obj
36741
+ * @param {string} name
36742
+ * @param {Function} factory
36743
+ * @returns {NgModule}
36744
+ */
36491
36745
  function ensure(obj, name, factory) {
36492
36746
  return obj[name] || (obj[name] = factory());
36493
36747
  }