@wavemaker/app-ng-runtime 11.14.2-1.6423 → 11.14.2-2.6435

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 (35) hide show
  1. package/components/base/bundles/index.umd.js +6 -12
  2. package/components/base/esm2022/widgets/common/base/base.component.mjs +8 -14
  3. package/components/base/fesm2022/index.mjs +7 -13
  4. package/components/base/fesm2022/index.mjs.map +1 -1
  5. package/components/data/table/bundles/index.umd.js +5 -5
  6. package/components/data/table/esm2022/table.component.mjs +7 -7
  7. package/components/data/table/fesm2022/index.mjs +6 -6
  8. package/components/data/table/fesm2022/index.mjs.map +1 -1
  9. package/components/prefab/bundles/index.umd.js +0 -4
  10. package/components/prefab/esm2022/prefab.directive.mjs +1 -5
  11. package/components/prefab/fesm2022/index.mjs +0 -4
  12. package/components/prefab/fesm2022/index.mjs.map +1 -1
  13. package/core/bundles/index.umd.js +187 -330
  14. package/core/esm2022/public_api.mjs +2 -2
  15. package/core/esm2022/utils/watcher.mjs +191 -327
  16. package/core/fesm2022/index.mjs +194 -330
  17. package/core/fesm2022/index.mjs.map +1 -1
  18. package/core/public_api.d.ts +1 -1
  19. package/core/utils/watcher.d.ts +5 -26
  20. package/npm-shrinkwrap.json +2 -2
  21. package/package-lock.json +2 -2
  22. package/package.json +1 -1
  23. package/runtime/base/bundles/index.umd.js +11 -171
  24. package/runtime/base/components/app-component/app.component.d.ts +0 -4
  25. package/runtime/base/esm2022/components/app-component/app.component.mjs +9 -40
  26. package/runtime/base/esm2022/components/base-page.component.mjs +3 -35
  27. package/runtime/base/esm2022/components/base-partial.component.mjs +3 -37
  28. package/runtime/base/esm2022/components/base-prefab.component.mjs +3 -32
  29. package/runtime/base/esm2022/components/base-spa-page.component.mjs +3 -37
  30. package/runtime/base/fesm2022/index.mjs +12 -172
  31. package/runtime/base/fesm2022/index.mjs.map +1 -1
  32. package/runtime/dynamic/bundles/index.umd.js +4 -0
  33. package/runtime/dynamic/esm2022/app/app.config.mjs +6 -2
  34. package/runtime/dynamic/fesm2022/index.mjs +5 -1
  35. package/runtime/dynamic/fesm2022/index.mjs.map +1 -1
@@ -1,5 +1,5 @@
1
1
  import { Attribute, ImplicitReceiver, PropertyRead, LiteralPrimitive, LiteralArray, LiteralMap, PropertyWrite, KeyedRead, PrefixNot, Unary, Binary, Conditional, Call, Chain, BindingPipe, Parser, Lexer } from '@angular/compiler';
2
- import { isArray, startsWith, includes, get, flatten, isEqual, clone, isObject as isObject$1, camelCase, split, map, attempt, isError, isFunction, isDate, isString, cloneDeep, identity, intersection, omit, keys, toLower, replace as replace$1, forEach, trim, isEqualWith, every, indexOf, isNumber, filter, isUndefined, isNull, noop as noop$2, toUpper, assign, merge, isEmpty, debounce as debounce$1, isNil } from 'lodash-es';
2
+ import { isArray, startsWith, includes, get, flatten, isEqual, isObject as isObject$1, clone, camelCase, split, map, attempt, isError, isFunction, isDate, isString, cloneDeep, identity, intersection, omit, keys, toLower, replace as replace$1, forEach, trim, isEqualWith, every, indexOf, isNumber, filter, isUndefined, isNull, noop as noop$2, toUpper, assign, merge, isEmpty, debounce as debounce$1, isNil } from 'lodash-es';
3
3
  import { Subject } from 'rxjs';
4
4
  import X2JS from 'x2js';
5
5
  import * as momentLib from 'moment-timezone/moment-timezone';
@@ -1432,11 +1432,11 @@ const CURRENCY_INFO = {
1432
1432
  }
1433
1433
  };
1434
1434
 
1435
- const $RAF = window.requestAnimationFrame;
1435
+ const $RAF$1 = window.requestAnimationFrame;
1436
1436
  const $RAFQueue = [];
1437
1437
  const invokeLater = fn => {
1438
1438
  if (!$RAFQueue.length) {
1439
- $RAF(() => {
1439
+ $RAF$1(() => {
1440
1440
  $RAFQueue.forEach(f => f());
1441
1441
  $RAFQueue.length = 0;
1442
1442
  });
@@ -2189,25 +2189,14 @@ const getFnForEventExpr = (expr) => {
2189
2189
  return fnExecutor(expr, ExpressionType.Action);
2190
2190
  };
2191
2191
 
2192
- // Constants
2193
- const WIDGET_ID_REGEX = /^(widget-[^_]+)/;
2194
- const WIDGET_PROPERTY_REGEX = /^widget-[^_]+_(.+)$/;
2195
- const ARRAY_INDEX_PLACEHOLDER = '[$i]';
2196
- const ARRAY_INDEX_ZERO = '[0]';
2197
- const DEBOUNCE_WAIT = 100;
2198
- const MAX_WATCH_CYCLES = 5;
2199
2192
  const registry = new Map();
2200
2193
  const watchIdGenerator = new IDGenerator('watch-id-');
2201
- const FIRST_TIME_WATCH = Object.freeze({});
2202
- // State
2194
+ const FIRST_TIME_WATCH = {};
2195
+ Object.freeze(FIRST_TIME_WATCH);
2196
+ const isFirstTimeChange = v => v === FIRST_TIME_WATCH;
2203
2197
  let muted = false;
2204
- let changedByWatch = false;
2205
- let skipWatchers = false;
2206
- let ngZone;
2207
2198
  let appRef;
2208
- // Utility functions
2209
- const isFirstTimeChange = (v) => v === FIRST_TIME_WATCH;
2210
- const debounce = (fn, wait = DEBOUNCE_WAIT) => {
2199
+ const debounce = (fn, wait = 50) => {
2211
2200
  let timeout;
2212
2201
  return (...args) => {
2213
2202
  window['__zone_symbol__clearTimeout'](timeout);
@@ -2219,362 +2208,232 @@ const muteWatchers = () => {
2219
2208
  };
2220
2209
  const unMuteWatchers = () => {
2221
2210
  muted = false;
2222
- triggerWatchers();
2223
- };
2224
- /**
2225
- * Extracts widget ID from identifier (e.g., "widget-id23_eventsource" -> "widget-id23")
2226
- */
2227
- const getWidgetId = (identifier) => {
2228
- if (!identifier || typeof identifier !== 'string') {
2229
- return null;
2230
- }
2231
- const match = identifier.match(WIDGET_ID_REGEX);
2232
- return match ? match[1] : null;
2233
- };
2234
- /**
2235
- * Extracts property name from identifier (e.g., "widget-id23_eventsource" -> "eventsource")
2236
- */
2237
- const getPropertyName = (identifier) => {
2238
- if (!identifier || typeof identifier !== 'string') {
2239
- return identifier;
2240
- }
2241
- const match = identifier.match(WIDGET_PROPERTY_REGEX);
2242
- return match ? match[1] : identifier;
2211
+ $invokeWatchers(true);
2243
2212
  };
2244
- /**
2245
- * Array consumer wrapper for array-based expressions
2246
- */
2247
2213
  const arrayConsumer = (listenerFn, restExpr, newVal, oldVal) => {
2248
- if (!isArray(newVal)) {
2249
- return;
2250
- }
2251
- let formattedData = newVal.map(datum => findValueOf(datum, restExpr));
2252
- // Flatten if result is array of arrays
2253
- if (isArray(formattedData[0])) {
2254
- formattedData = flatten(formattedData);
2214
+ let data = newVal, formattedData;
2215
+ if (isArray(data)) {
2216
+ formattedData = data.map(function (datum) {
2217
+ return findValueOf(datum, restExpr);
2218
+ });
2219
+ // If resulting structure is an array of array, flatten it
2220
+ if (isArray(formattedData[0])) {
2221
+ formattedData = flatten(formattedData);
2222
+ }
2223
+ listenerFn(formattedData, oldVal);
2255
2224
  }
2256
- listenerFn(formattedData, oldVal);
2257
2225
  };
2258
- /**
2259
- * Updates watch info for array expressions
2260
- */
2261
- const getUpdatedWatchInfo = (expr, acceptsArray, listener) => {
2262
- const regex = /\[\$i\]/g;
2226
+ const getUpdatedWatcInfo = (expr, acceptsArray, listener) => {
2227
+ // listener doesn't accept array
2228
+ // replace all `[$i]` with `[0]` and return the expression
2229
+ let regex = /\[\$i\]/g, $I = '[$i]', $0 = '[0]';
2263
2230
  if (!acceptsArray) {
2264
2231
  return {
2265
- expr: expr.replace(regex, ARRAY_INDEX_ZERO),
2266
- listener
2232
+ 'expr': expr.replace(regex, $0),
2233
+ 'listener': listener
2267
2234
  };
2268
2235
  }
2269
- const lastIndex = expr.lastIndexOf(ARRAY_INDEX_PLACEHOLDER);
2270
- const baseExpr = expr.substring(0, lastIndex).replace(ARRAY_INDEX_PLACEHOLDER, ARRAY_INDEX_ZERO);
2271
- const restExpr = expr.substring(lastIndex + 5);
2272
- const arrayConsumerFn = restExpr
2273
- ? arrayConsumer.bind(undefined, listener, restExpr)
2274
- : listener;
2236
+ // listener accepts array
2237
+ // replace all except the last `[$i]` with `[0]` and return the expression.
2238
+ var index = expr.lastIndexOf($I), _expr = expr.substr(0, index).replace($I, $0), restExpr = expr.substr(index + 5), arrayConsumerFn = listener;
2239
+ if (restExpr) {
2240
+ arrayConsumerFn = arrayConsumer.bind(undefined, listener, restExpr);
2241
+ }
2275
2242
  return {
2276
- expr: baseExpr,
2277
- listener: arrayConsumerFn
2243
+ 'expr': _expr,
2244
+ 'listener': arrayConsumerFn
2278
2245
  };
2279
2246
  };
2280
- /**
2281
- * Determines if an expression is static (doesn't need to be watched)
2282
- */
2283
- const STATIC_EXPRESSION_NAMES = [
2284
- "row.getProperty('investment')",
2285
- "row.getProperty('factsheetLink')",
2286
- "row.getProperty('isRebalanceEligible')"
2287
- ];
2288
- const isStaticExpression = (expr) => {
2289
- if (typeof expr !== 'string') {
2290
- return false;
2291
- }
2292
- const trimmedExpr = expr.trim();
2293
- // Expressions that always evaluate to localization strings
2294
- // if (trimmedExpr.includes('appLocale')) {
2295
- // return true;
2296
- // }
2297
- // Hard-coded static expression names
2298
- if (STATIC_EXPRESSION_NAMES.includes(trimmedExpr)) {
2299
- return true;
2300
- }
2301
- return false;
2302
- };
2303
- /**
2304
- * Gets the scope type from the scope object
2305
- */
2306
- const getScopeType = ($scope) => {
2307
- if (!$scope) {
2308
- return null;
2309
- }
2310
- if ($scope.pageName)
2311
- return 'Page';
2312
- if ($scope.prefabName)
2313
- return 'Prefab';
2314
- if ($scope.partialName)
2315
- return 'Partial';
2316
- // Check for App scope
2317
- if ($scope.Variables !== undefined &&
2318
- $scope.Actions !== undefined &&
2319
- !$scope.pageName &&
2320
- !$scope.prefabName &&
2321
- !$scope.partialName) {
2322
- return 'App';
2323
- }
2324
- if ($scope.constructor?.name === 'AppRef') {
2325
- return 'App';
2326
- }
2327
- return null;
2328
- };
2329
- /**
2330
- * Gets scope name based on scope type
2331
- */
2332
- const getScopeName = ($scope, scopeType) => {
2333
- if (!scopeType || !$scope) {
2334
- return null;
2335
- }
2336
- switch (scopeType) {
2337
- case 'Prefab': return $scope.prefabName || null;
2338
- case 'Partial': return $scope.partialName || null;
2339
- case 'Page': return $scope.pageName || null;
2340
- default: return null;
2341
- }
2342
- };
2343
- /**
2344
- * Main watch function
2345
- */
2346
2247
  const $watch = (expr, $scope, $locals, listener, identifier = watchIdGenerator.nextUid(), doNotClone = false, config = {}, isMuted) => {
2347
- // Handle array expressions
2348
- if (expr.includes(ARRAY_INDEX_PLACEHOLDER)) {
2349
- const watchInfo = getUpdatedWatchInfo(expr, config.arrayType || config.isList || false, listener);
2248
+ if (expr.indexOf('[$i]') !== -1) {
2249
+ let watchInfo = getUpdatedWatcInfo(expr, config && (config.arrayType || config.isList), listener);
2350
2250
  expr = watchInfo.expr;
2351
2251
  listener = watchInfo.listener;
2352
2252
  }
2353
- // Handle static expressions
2354
- if (isStaticExpression(expr)) {
2355
- try {
2356
- const fn = $parseExpr(expr);
2357
- const staticValue = fn($scope, $locals);
2358
- listener(staticValue, FIRST_TIME_WATCH);
2359
- }
2360
- catch (e) {
2361
- console.warn(`Error evaluating static expression '${expr}':`, e);
2362
- listener(undefined, FIRST_TIME_WATCH);
2363
- }
2364
- return () => { }; // No-op unsubscribe
2365
- }
2366
2253
  const fn = $parseExpr(expr);
2367
- const scopeType = getScopeType($scope);
2368
- const scopeName = getScopeName($scope, scopeType);
2369
- const watchInfo = {
2370
- fn: fn.bind(null, $scope, $locals),
2254
+ registry.set(identifier, {
2255
+ fn: fn.bind(expr, $scope, $locals),
2371
2256
  listener,
2372
2257
  expr,
2373
2258
  last: FIRST_TIME_WATCH,
2374
2259
  doNotClone,
2375
- isMuted,
2376
- scopeType,
2377
- scopeName
2378
- };
2379
- // Store in registry
2380
- const widgetId = getWidgetId(identifier);
2381
- if (widgetId) {
2382
- const propertyName = getPropertyName(identifier);
2383
- if (!registry.has(widgetId)) {
2384
- registry.set(widgetId, {});
2385
- }
2386
- const widgetGroup = registry.get(widgetId);
2387
- widgetGroup[propertyName] = watchInfo;
2388
- }
2389
- else {
2390
- registry.set(identifier, watchInfo);
2391
- }
2392
- return () => $unwatch(identifier);
2393
- };
2394
- /**
2395
- * Unwatches a single identifier
2396
- */
2397
- const $unwatch = (identifier) => {
2398
- const widgetId = getWidgetId(identifier);
2399
- if (widgetId) {
2400
- const propertyName = getPropertyName(identifier);
2401
- const widgetGroup = registry.get(widgetId);
2402
- if (widgetGroup && typeof widgetGroup === 'object' && !widgetGroup.fn) {
2403
- const watchInfo = widgetGroup[propertyName];
2404
- if (watchInfo) {
2405
- delete widgetGroup[propertyName];
2406
- // Clean up empty widget groups
2407
- if (Object.keys(widgetGroup).length === 0) {
2408
- registry.delete(widgetId);
2409
- }
2410
- return true;
2411
- }
2412
- }
2413
- }
2414
- // Fallback to direct lookup
2415
- if (registry.has(identifier)) {
2416
- registry.delete(identifier);
2417
- return true;
2418
- }
2419
- return false;
2420
- };
2421
- /**
2422
- * Unwatches all watchers for a specific widget ID
2423
- */
2424
- const $unwatchAll = (widgetId) => {
2425
- if (!widgetId || typeof widgetId !== 'string') {
2426
- return 0;
2427
- }
2428
- const widgetGroup = registry.get(widgetId);
2429
- if (widgetGroup && typeof widgetGroup === 'object' && !widgetGroup.fn) {
2430
- const count = Object.keys(widgetGroup).length;
2431
- registry.delete(widgetId);
2432
- return count;
2433
- }
2434
- // Fallback: find all identifiers starting with this widget ID
2435
- let removedCount = 0;
2436
- const identifiersToRemove = [];
2437
- registry.forEach((_, key) => {
2438
- if (key.startsWith(widgetId + '_')) {
2439
- identifiersToRemove.push(key);
2440
- }
2260
+ isMuted: isMuted
2441
2261
  });
2442
- identifiersToRemove.forEach(identifier => {
2443
- if ($unwatch(identifier)) {
2444
- removedCount++;
2445
- }
2446
- });
2447
- return removedCount;
2448
- };
2449
- /**
2450
- * Unwatches all watchers for a specific scope (Page, Prefab, Partial, or App)
2451
- * Now works directly with the main registry instead of separate scoped registries
2452
- */
2453
- const $unwatchAllByScope = (scopeType, scopeName) => {
2454
- if (!scopeType) {
2455
- return 0;
2456
- }
2457
- let removedCount = 0;
2458
- const identifiersToRemove = [];
2459
- registry.forEach((value, key) => {
2460
- // Handle grouped structure (widget groups)
2461
- if (value && typeof value === 'object' && !value.fn) {
2462
- Object.entries(value).forEach(([propertyName, watchInfo]) => {
2463
- if (watchInfo?.scopeType === scopeType &&
2464
- (!scopeName || watchInfo.scopeName === scopeName)) {
2465
- identifiersToRemove.push(`${key}_${propertyName}`);
2466
- }
2467
- });
2468
- }
2469
- else {
2470
- // Direct watchInfo
2471
- const watchInfo = value;
2472
- if (watchInfo?.scopeType === scopeType &&
2473
- (!scopeName || watchInfo.scopeName === scopeName)) {
2474
- identifiersToRemove.push(key);
2475
- }
2476
- }
2477
- });
2478
- // Unwatch all collected identifiers
2479
- identifiersToRemove.forEach(identifier => {
2480
- if ($unwatch(identifier)) {
2481
- removedCount++;
2482
- }
2483
- });
2484
- return removedCount;
2485
- };
2486
- /**
2487
- * Processes a single watch info during trigger cycle
2488
- */
2489
- const processWatchInfo = (watchInfo) => {
2490
- if (!watchInfo?.fn || (watchInfo.isMuted?.() ?? false)) {
2491
- return false;
2492
- }
2493
- let newValue;
2494
- try {
2495
- newValue = watchInfo.fn();
2496
- }
2497
- catch (e) {
2498
- console.warn(`Error executing expression: '${watchInfo.expr}'`, e);
2499
- return false;
2500
- }
2501
- if (isEqual(newValue, watchInfo.last)) {
2502
- return false;
2503
- }
2504
- // Change detected
2505
- changedByWatch = true;
2506
- watchInfo.last = isObject$1(newValue) && !watchInfo.doNotClone
2507
- ? clone(newValue)
2508
- : newValue;
2509
- watchInfo.listener(newValue, watchInfo.last === newValue ? FIRST_TIME_WATCH : watchInfo.last);
2510
- changedByWatch = false;
2511
- return true;
2262
+ return () => $unwatch(identifier);
2512
2263
  };
2513
- /**
2514
- * Triggers all watchers
2515
- */
2516
- const triggerWatchers = (ignoreMuted = false) => {
2264
+ const $unwatch = identifier => registry.delete(identifier);
2265
+ let changedByWatch = false;
2266
+ const $RAF = window.requestAnimationFrame;
2267
+ let ngZone;
2268
+ const triggerWatchers = (ignoreMuted) => {
2517
2269
  if (muted && !ignoreMuted) {
2518
2270
  return;
2519
2271
  }
2272
+ log(".......................triggerWatchers.................................");
2273
+ const limit = 5;
2520
2274
  let pass = 1;
2521
2275
  let changeDetected;
2522
2276
  do {
2523
2277
  changeDetected = false;
2524
- registry.forEach((value) => {
2525
- // Handle grouped structure
2526
- if (value && typeof value === 'object' && !value.fn) {
2527
- Object.values(value).forEach((watchInfo) => {
2528
- if (processWatchInfo(watchInfo)) {
2529
- changeDetected = true;
2530
- }
2531
- });
2278
+ registry.forEach(watchInfo => {
2279
+ if (watchInfo.isMuted && watchInfo.isMuted()) {
2280
+ return;
2532
2281
  }
2533
- else {
2534
- // Direct watchInfo
2535
- if (processWatchInfo(value)) {
2536
- changeDetected = true;
2282
+ const fn = watchInfo.fn;
2283
+ const listener = watchInfo.listener;
2284
+ const ov = watchInfo.last;
2285
+ let nv;
2286
+ try {
2287
+ nv = fn();
2288
+ }
2289
+ catch (e) {
2290
+ console.warn(`error in executing expression: '${watchInfo.expr}'`);
2291
+ }
2292
+ if (!isEqual(nv, ov)) {
2293
+ changeDetected = true;
2294
+ changedByWatch = true;
2295
+ watchInfo.last = nv;
2296
+ // @ts-ignore
2297
+ if (isObject$1(nv) && !watchInfo.doNotClone && nv.__cloneable__ !== false) {
2298
+ watchInfo.last = clone(nv);
2537
2299
  }
2300
+ listener(nv, ov);
2301
+ resetChangeFromWatch();
2538
2302
  }
2539
2303
  });
2540
2304
  pass++;
2541
- } while (changeDetected && pass < MAX_WATCH_CYCLES);
2542
- if (changeDetected && pass === MAX_WATCH_CYCLES) {
2543
- console.warn(`Watch cycles exceeded limit of ${MAX_WATCH_CYCLES}`);
2305
+ } while (changeDetected && pass < limit);
2306
+ if (changeDetected && pass === limit) {
2307
+ console.warn(`Number of watch cycles gone above set limit of: ${limit} `);
2544
2308
  }
2545
2309
  };
2546
- // Angular zone integration
2547
- const setNgZone = (zone) => {
2548
- ngZone = zone;
2549
- };
2550
- const setAppRef = (ref) => {
2310
+ const setNgZone = zone => ngZone = zone;
2311
+ const setAppRef = ref => {
2551
2312
  appRef = ref;
2552
2313
  };
2553
2314
  const isChangeFromWatch = () => changedByWatch;
2554
- const resetChangeFromWatch = () => {
2555
- changedByWatch = false;
2556
- };
2557
- // Debounced trigger
2558
- const debouncedTriggerWatchers = debounce(() => {
2559
- skipWatchers = true;
2560
- ngZone.run(() => triggerWatchers());
2561
- }, DEBOUNCE_WAIT);
2315
+ const resetChangeFromWatch = () => changedByWatch = false;
2316
+ window.watchRegistry = registry;
2317
+ let skipWatchers;
2318
+ let scheduled = false, rerunRequested = false, isRunning = false, consecutiveReruns = 0;
2319
+ const MAX_PASSES = 5, DEBOUNCE_TIME = 200, MAX_CONSECUTIVE_RERUNS = 3;
2320
+ window.__WM_DEBUG_WATCHERS__ = false;
2562
2321
  const $invokeWatchers = (force = false, ignoreMuted = false) => {
2563
2322
  if (force) {
2564
2323
  triggerWatchers(ignoreMuted);
2565
2324
  }
2566
2325
  else {
2326
+ scheduleExecution(ignoreMuted);
2327
+ }
2328
+ };
2329
+ function scheduleExecution(ignoreMuted) {
2330
+ if (scheduled) {
2331
+ rerunRequested = true;
2332
+ return;
2333
+ }
2334
+ scheduled = true;
2335
+ // Reset consecutive rerun counter when scheduling from outside
2336
+ // (not from within executeWatchers rerun logic)
2337
+ if (!isRunning) {
2338
+ consecutiveReruns = 0;
2339
+ }
2340
+ debouncedExecute(ignoreMuted);
2341
+ }
2342
+ const debouncedExecute = debounce((ignoreMuted) => {
2343
+ scheduled = false;
2344
+ executeWatchers(ignoreMuted);
2345
+ }, DEBOUNCE_TIME);
2346
+ function executeWatchers(ignoreMuted) {
2347
+ if (isRunning) {
2348
+ rerunRequested = true;
2349
+ return;
2350
+ }
2351
+ isRunning = true;
2352
+ let actuallyChanged = false;
2353
+ ngZone.runOutsideAngular(() => {
2354
+ let pass = 1;
2355
+ let changeDetected;
2356
+ do {
2357
+ changeDetected = false;
2358
+ log(`-------executeWatchers (run #${consecutiveReruns + 1})--------- `);
2359
+ registry.forEach(watchInfo => {
2360
+ if (watchInfo.isMuted && watchInfo.isMuted()) {
2361
+ return;
2362
+ }
2363
+ const fn = watchInfo.fn;
2364
+ const listener = watchInfo.listener;
2365
+ const ov = watchInfo.last;
2366
+ let nv;
2367
+ try {
2368
+ nv = fn();
2369
+ }
2370
+ catch (e) {
2371
+ console.warn(`error in executing expression: '${watchInfo.expr}'`);
2372
+ }
2373
+ if (!isEqual(nv, ov)) {
2374
+ changeDetected = true;
2375
+ actuallyChanged = true;
2376
+ changedByWatch = true;
2377
+ watchInfo.last = nv;
2378
+ // @ts-ignore
2379
+ if (isObject$1(nv) && !watchInfo.doNotClone && nv.__cloneable__ !== false) {
2380
+ watchInfo.last = clone(nv);
2381
+ }
2382
+ listener(nv, ov);
2383
+ resetChangeFromWatch();
2384
+ }
2385
+ });
2386
+ pass++;
2387
+ } while (changeDetected && pass < MAX_PASSES);
2388
+ });
2389
+ isRunning = false;
2390
+ // Trigger Angular change detection if watchers actually changed values
2391
+ if (actuallyChanged) {
2392
+ ngZone.run(() => {
2393
+ log(`-------DONE (changes detected)--------- `);
2394
+ });
2395
+ }
2396
+ else {
2397
+ log(`-------DONE (no changes)--------- `);
2398
+ }
2399
+ // 🔥 collapse ALL mid-run triggers into ONE rerun
2400
+ // BUT limit consecutive reruns to prevent infinite loops
2401
+ if (rerunRequested) {
2402
+ rerunRequested = false;
2403
+ if (consecutiveReruns < MAX_CONSECUTIVE_RERUNS) {
2404
+ consecutiveReruns++;
2405
+ log(`[Watcher] Scheduling rerun #${consecutiveReruns} (requested during execution)`);
2406
+ scheduleExecution(ignoreMuted);
2407
+ }
2408
+ else {
2409
+ consecutiveReruns = 0;
2410
+ log(`[Watcher] ⚠️ Stopped infinite loop! Max consecutive reruns (${MAX_CONSECUTIVE_RERUNS}) reached. This usually means watcher listeners are triggering more change detection.`);
2411
+ }
2412
+ }
2413
+ else {
2414
+ // No rerun requested - reset counter
2415
+ consecutiveReruns = 0;
2416
+ }
2417
+ }
2418
+ const debouncedTriggerWatchers = debounce(() => {
2419
+ skipWatchers = true;
2420
+ ngZone.runOutsideAngular(() => triggerWatchers());
2421
+ }, 100);
2422
+ /*export const $invokeWatchers = (force?: boolean, ignoreMuted?: boolean) => {
2423
+ if (force) {
2424
+ triggerWatchers(ignoreMuted);
2425
+ } else {
2426
+
2567
2427
  if (skipWatchers) {
2568
2428
  skipWatchers = false;
2569
2429
  return;
2570
2430
  }
2571
2431
  debouncedTriggerWatchers();
2572
2432
  }
2573
- };
2433
+ };*/
2574
2434
  const $appDigest = (() => {
2575
2435
  let queued = false;
2576
- const $RAF = window.requestAnimationFrame;
2577
- return (force = false) => {
2436
+ return (force) => {
2578
2437
  if (!appRef) {
2579
2438
  return;
2580
2439
  }
@@ -2586,16 +2445,21 @@ const $appDigest = (() => {
2586
2445
  if (queued) {
2587
2446
  return;
2588
2447
  }
2589
- queued = true;
2590
- $RAF(() => {
2591
- ngZone.run(() => appRef.tick());
2592
- queued = false;
2593
- });
2448
+ else {
2449
+ queued = true;
2450
+ $RAF(() => {
2451
+ ngZone.run(() => appRef.tick());
2452
+ queued = false;
2453
+ });
2454
+ }
2594
2455
  }
2595
2456
  };
2596
2457
  })();
2597
- // Export registry for debugging
2598
- window.watchRegistry = registry;
2458
+ function log(message) {
2459
+ if (window.__WM_DEBUG_WATCHERS__) {
2460
+ console.log(message);
2461
+ }
2462
+ }
2599
2463
 
2600
2464
  var ComponentType;
2601
2465
  (function (ComponentType) {
@@ -5471,5 +5335,5 @@ class LRUCache {
5471
5335
  * Generated bundle index. Do not edit.
5472
5336
  */
5473
5337
 
5474
- export { $appDigest, $invokeWatchers, $parseEvent, $parseExpr, $unwatch, $unwatchAll, $unwatchAllByScope, $watch, AbstractDialogService, AbstractHttpService, AbstractI18nService, AbstractNavigationService, AbstractSpinnerService, AbstractToasterService, App, AppConstants, AppDefaults, CURRENCY_INFO, ComponentType, ConstantService, CustomIconsLoaderService, CustomPipeManager, CustomWidgetRefProvider, DEFAULT_FORMATS, DataSource, DataType, DynamicComponentRefProvider, EventNotifier, FIRST_TIME_WATCH, FieldTypeService, FieldWidgetService, FormWidgetType, IDGenerator, IDataSource, LRUCache, MatchMode, PaginationService, PartialRefProvider, ScriptLoaderService, ScriptStore, StatePersistence, UserDefinedExecutionContext, UtilsService, VALIDATOR, Viewport, _WM_APP_PROJECT, addClass, addEventListenerOnElement, addForIdAttributes, adjustContainerPosition, adjustContainerRightEdges, appendNode, appendScriptToHead, checkIsCustomPipeExpression, closePopover, convertToBlob, createCSSRule, createElement, deHyphenate, debounce, defer, detectChanges, encodeUrl, encodeUrlParams, executePromiseChain, extendProto, extractCurrentItemExpr, extractType, fetchContent, findParent, findRootContainer, findValueOf, generateGUId, getAbortableDefer, getAndroidVersion, getAppSetting, getBlob, getClonedObject, getDatasourceFromExpr, getDateObj, getDisplayDateTimeFormat, getEvaluatedExprValue, getFiles, getFnByExpr, getFnForBindExpr, getFnForEventExpr, getFormWidgetTemplate, getFormattedDate, getMomentLocaleObject, getNativeDateObject, getNavClass, getNgModelAttr, getPreviewProperties, getRequiredFormWidget, getResourceURL, getRouteNameFromLink, getRowActionAttrs, getSessionStorageItem, getSheetPositionClass, getUrlParams, getValidDateObject, getValidJSON, getWebkitTraslationMatrix, getWmProjectProperties, hasOffsetStr, initCaps, insertAfter, insertBefore, isAndroid, isAndroidTablet, isAppleProduct, isAudioFile, isChangeFromWatch, isDataSourceEqual, isDateTimeType, isDefined, isElementInViewport, isEmptyObject, isEqualWithFields, isFirstTimeChange, isIE, isImageFile, isInsecureContentRequest, isIos, isIpad, isIphone, isIpod, isKitkatDevice, isLargeTabletLandscape, isLargeTabletPortrait, isMobile, isNumberType, isObject, isPageable, isSafari, isValidImageUrl, isValidWebURL, isVideoFile, loadScript, loadScripts, loadStyleSheet, loadStyleSheets, muteWatchers, noop, openLink, periodSeparate, prettifyLabel, prettifyLabels, processFilterExpBindNode, registerFnByExpr, removeAttr, removeClass, removeExtraSlashes, removeNode, replace, replaceAt, resetChangeFromWatch, retryIfFails, scrollToElement, setAppRef, setAttr, setCSS, setCSSFromObj, setHtml, setListClass, setNgZone, setPipeProvider, setPreviewProperties, setProperty, setSessionStorageItem, setTranslation3dPosition, setWmProjectProperties, spaceSeparate, stringStartsWith, switchClass, toBoolean, toDimension, toPromise, toggleClass, transformFileURI, triggerFn, triggerItemAction, unMuteWatchers, updateTemplateAttrs, validateAccessRoles, validateDataSourceCtx, xmlToJson };
5338
+ export { $appDigest, $invokeWatchers, $parseEvent, $parseExpr, $unwatch, $watch, AbstractDialogService, AbstractHttpService, AbstractI18nService, AbstractNavigationService, AbstractSpinnerService, AbstractToasterService, App, AppConstants, AppDefaults, CURRENCY_INFO, ComponentType, ConstantService, CustomIconsLoaderService, CustomPipeManager, CustomWidgetRefProvider, DEFAULT_FORMATS, DataSource, DataType, DynamicComponentRefProvider, EventNotifier, FIRST_TIME_WATCH, FieldTypeService, FieldWidgetService, FormWidgetType, IDGenerator, IDataSource, LRUCache, MatchMode, PaginationService, PartialRefProvider, ScriptLoaderService, ScriptStore, StatePersistence, UserDefinedExecutionContext, UtilsService, VALIDATOR, Viewport, _WM_APP_PROJECT, addClass, addEventListenerOnElement, addForIdAttributes, adjustContainerPosition, adjustContainerRightEdges, appendNode, appendScriptToHead, checkIsCustomPipeExpression, closePopover, convertToBlob, createCSSRule, createElement, deHyphenate, debounce, defer, detectChanges, encodeUrl, encodeUrlParams, executePromiseChain, extendProto, extractCurrentItemExpr, extractType, fetchContent, findParent, findRootContainer, findValueOf, generateGUId, getAbortableDefer, getAndroidVersion, getAppSetting, getBlob, getClonedObject, getDatasourceFromExpr, getDateObj, getDisplayDateTimeFormat, getEvaluatedExprValue, getFiles, getFnByExpr, getFnForBindExpr, getFnForEventExpr, getFormWidgetTemplate, getFormattedDate, getMomentLocaleObject, getNativeDateObject, getNavClass, getNgModelAttr, getPreviewProperties, getRequiredFormWidget, getResourceURL, getRouteNameFromLink, getRowActionAttrs, getSessionStorageItem, getSheetPositionClass, getUrlParams, getValidDateObject, getValidJSON, getWebkitTraslationMatrix, getWmProjectProperties, hasOffsetStr, initCaps, insertAfter, insertBefore, isAndroid, isAndroidTablet, isAppleProduct, isAudioFile, isChangeFromWatch, isDataSourceEqual, isDateTimeType, isDefined, isElementInViewport, isEmptyObject, isEqualWithFields, isFirstTimeChange, isIE, isImageFile, isInsecureContentRequest, isIos, isIpad, isIphone, isIpod, isKitkatDevice, isLargeTabletLandscape, isLargeTabletPortrait, isMobile, isNumberType, isObject, isPageable, isSafari, isValidImageUrl, isValidWebURL, isVideoFile, loadScript, loadScripts, loadStyleSheet, loadStyleSheets, muteWatchers, noop, openLink, periodSeparate, prettifyLabel, prettifyLabels, processFilterExpBindNode, registerFnByExpr, removeAttr, removeClass, removeExtraSlashes, removeNode, replace, replaceAt, resetChangeFromWatch, retryIfFails, scrollToElement, setAppRef, setAttr, setCSS, setCSSFromObj, setHtml, setListClass, setNgZone, setPipeProvider, setPreviewProperties, setProperty, setSessionStorageItem, setTranslation3dPosition, setWmProjectProperties, spaceSeparate, stringStartsWith, switchClass, toBoolean, toDimension, toPromise, toggleClass, transformFileURI, triggerFn, triggerItemAction, unMuteWatchers, updateTemplateAttrs, validateAccessRoles, validateDataSourceCtx, xmlToJson };
5475
5339
  //# sourceMappingURL=index.mjs.map