@mintjamsinc/ichigojs 0.1.85 → 0.1.86

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.
@@ -6760,28 +6760,29 @@ class ExpressionUtils {
6760
6760
  }
6761
6761
  }
6762
6762
  else if (node.type === 'MemberExpression') {
6763
- // Reconstruct chain parts from a MemberExpression (e.g. a.b.c)
6763
+ // Reconstruct chain parts from a MemberExpression (e.g. a.b.c). Each part
6764
+ // carries its own separator so that the chain is spelled the way the reactive
6765
+ // proxy reports changes: array indices in brackets, properties after a dot
6766
+ // (e.g. "items[0].name").
6764
6767
  const parts = [];
6765
6768
  let cur = node;
6766
- let stop = false;
6767
- while (cur && !stop) {
6769
+ while (cur) {
6768
6770
  // property part (right side)
6769
6771
  if (cur.property) {
6770
6772
  if (!cur.computed && cur.property.type === 'Identifier') {
6771
- parts.unshift(cur.property.name);
6773
+ parts.unshift(`.${cur.property.name}`);
6772
6774
  }
6773
- else if (cur.computed && cur.property.type === 'Literal') {
6774
- parts.unshift(String(cur.property.value));
6775
+ else if (cur.computed && cur.property.type === 'Literal' && typeof cur.property.value === 'number') {
6776
+ parts.unshift(`[${cur.property.value}]`);
6775
6777
  }
6776
- else if (cur.computed && cur.property.type === 'Identifier') {
6777
- // e.g. obj[prop] -> include the prop identifier (it will also be added separately)
6778
- parts.unshift(cur.property.name);
6778
+ else if (cur.computed && cur.property.type === 'Literal') {
6779
+ parts.unshift(`.${String(cur.property.value)}`);
6779
6780
  }
6780
- else {
6781
- // unknown property shape (e.g. expression) — stop adding chain here
6782
- // inner expressions will be visited separately by walk.full
6783
- stop = true;
6784
- break;
6781
+ else if (cur.computed) {
6782
+ // e.g. items[i] or items[i + 1]: the index is only known when the
6783
+ // expression runs, so "[*]" stands for any index or key. Identifiers
6784
+ // inside the index expression are visited separately by walk.full.
6785
+ parts.unshift('[*]');
6785
6786
  }
6786
6787
  }
6787
6788
  // object part (left side)
@@ -6801,7 +6802,6 @@ class ExpressionUtils {
6801
6802
  }
6802
6803
  else {
6803
6804
  // other object types (CallExpression, etc.) — stop here
6804
- stop = true;
6805
6805
  break;
6806
6806
  }
6807
6807
  }
@@ -6809,10 +6809,15 @@ class ExpressionUtils {
6809
6809
  break;
6810
6810
  }
6811
6811
  }
6812
- if (parts.length > 0) {
6813
- // Add progressive chains: 'a', 'a.b', 'a.b.c'
6812
+ // A chain that does not start at a name (e.g. `this.a.b` or `f().b`) begins
6813
+ // with its first property; one that begins with an index names no binding.
6814
+ if (parts.length > 0 && parts[0].startsWith('.')) {
6815
+ parts[0] = parts[0].substring(1);
6816
+ }
6817
+ if (parts.length > 0 && !parts[0].startsWith('[')) {
6818
+ // Add progressive chains: 'a', 'a.b', 'a.b[0]', 'a.b[0].c'
6814
6819
  for (let i = 0; i < parts.length; i++) {
6815
- const chain = parts.slice(0, i + 1).join('.');
6820
+ const chain = parts.slice(0, i + 1).join('');
6816
6821
  identifiers.add(chain);
6817
6822
  // Also apply functionDependencies lookup for the chain key
6818
6823
  if (functionDependencies[chain]) {
@@ -6826,6 +6831,16 @@ class ExpressionUtils {
6826
6831
  });
6827
6832
  return Array.from(identifiers);
6828
6833
  }
6834
+ /**
6835
+ * Returns the binding name an identifier chain starts with
6836
+ * (e.g. "items" for "items[0].name" or "user.name").
6837
+ * @param identifier An identifier or member chain returned by extractIdentifiers.
6838
+ * @returns The left-most name of the chain.
6839
+ */
6840
+ static baseIdentifier(identifier) {
6841
+ const end = identifier.search(/[.[]/);
6842
+ return end === -1 ? identifier : identifier.substring(0, end);
6843
+ }
6829
6844
  /**
6830
6845
  * Analyzes the dependencies of functions in the provided dictionary.
6831
6846
  * @param functions A dictionary mapping function names to their implementations.
@@ -7240,7 +7255,7 @@ class ExpressionEvaluator {
7240
7255
  // Use the base (left-most) segment of member chains and preserve order.
7241
7256
  const baseIdentifiers = [];
7242
7257
  for (const id of extractedIdentifiers) {
7243
- const base = id.split('.')[0];
7258
+ const base = ExpressionUtils.baseIdentifier(id);
7244
7259
  if (!baseIdentifiers.includes(base)) {
7245
7260
  baseIdentifiers.push(base);
7246
7261
  }
@@ -8034,6 +8049,11 @@ class ReactiveProxy {
8034
8049
  * This allows mapping variable names to their actual source paths for dependency tracking.
8035
8050
  */
8036
8051
  static pathAliases = new Map();
8052
+ /**
8053
+ * Compiled patterns for identifiers that contain a "[*]" index, keyed by the
8054
+ * identifier and whether descendants of the path also match.
8055
+ */
8056
+ static pathPatterns = new Map();
8037
8057
  /**
8038
8058
  * The `Object.prototype.toString` tags of the *only* value types we deeply
8039
8059
  * proxy. Everything else is returned untouched (raw).
@@ -8396,24 +8416,47 @@ class ReactiveProxy {
8396
8416
  */
8397
8417
  static doesChangeMatchIdentifier(changePath, identifier) {
8398
8418
  // Direct match
8399
- if (changePath === identifier) {
8419
+ if (this.pathMatches(changePath, identifier)) {
8400
8420
  return true;
8401
8421
  }
8402
- // Check if the identifier has an alias that matches
8422
+ // Check if the change path is the resolved identifier or lies below it
8423
+ // (handles cases like array item changes)
8403
8424
  const resolvedIdentifier = this.resolvePathAlias(identifier);
8404
- if (resolvedIdentifier && changePath === resolvedIdentifier) {
8425
+ if (resolvedIdentifier && this.pathMatches(changePath, resolvedIdentifier, true)) {
8405
8426
  return true;
8406
8427
  }
8407
- // Check if change path starts with the resolved identifier
8408
- // (handles cases like array item changes)
8409
- if (resolvedIdentifier) {
8410
- if (changePath.startsWith(resolvedIdentifier + '.') ||
8411
- changePath.startsWith(resolvedIdentifier + '[')) {
8412
- return true;
8413
- }
8414
- }
8415
8428
  return false;
8416
8429
  }
8430
+ /**
8431
+ * Checks whether a change path names the location an identifier refers to.
8432
+ * A "[*]" index in the identifier (e.g. "items[*].name" for `items[i].name`)
8433
+ * stands for an index known only when the expression runs and matches any
8434
+ * one index or key.
8435
+ *
8436
+ * @param changePath The path that was changed (e.g., "items[2].name")
8437
+ * @param identifier The identifier to check (e.g., "items[*].name")
8438
+ * @param descendants Whether a change below the identifier also matches
8439
+ * @returns True if the change path matches the identifier
8440
+ */
8441
+ static pathMatches(changePath, identifier, descendants = false) {
8442
+ if (changePath === identifier) {
8443
+ return true;
8444
+ }
8445
+ if (!identifier.includes('[*]')) {
8446
+ return descendants && (changePath.startsWith(identifier + '.') || changePath.startsWith(identifier + '['));
8447
+ }
8448
+ const cacheKey = descendants ? identifier + ' ' : identifier;
8449
+ let pattern = this.pathPatterns.get(cacheKey);
8450
+ if (!pattern) {
8451
+ const source = identifier
8452
+ .split('[*]')
8453
+ .map(part => part.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
8454
+ .join('(?:\\[[^\\]]*\\]|\\.[^.[]+)');
8455
+ pattern = new RegExp(`^${source}${descendants ? '(?:[.[].*)?' : ''}$`);
8456
+ this.pathPatterns.set(cacheKey, pattern);
8457
+ }
8458
+ return pattern.test(changePath);
8459
+ }
8417
8460
  }
8418
8461
 
8419
8462
  // Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
@@ -8909,18 +8952,15 @@ class VBindings {
8909
8952
  * global aliases (computed properties etc.).
8910
8953
  */
8911
8954
  doesChangeMatchIdentifier(changePath, identifier) {
8912
- // Direct match
8913
- if (changePath === identifier) {
8955
+ // Direct match (an index "[*]" in the identifier matches any index)
8956
+ if (ReactiveProxy.pathMatches(changePath, identifier)) {
8914
8957
  return true;
8915
8958
  }
8916
8959
  // Resolve via local (scoped) alias chain
8917
8960
  const resolved = this.resolveAlias(identifier);
8918
8961
  if (resolved) {
8919
- if (changePath === resolved) {
8920
- return true;
8921
- }
8922
- // changePath is a descendant of resolved (e.g. "files[0].isModified" for resolved "files[0]")
8923
- if (changePath.startsWith(resolved + '.') || changePath.startsWith(resolved + '[')) {
8962
+ // changePath is resolved itself or a descendant of it (e.g. "files[0].isModified" for resolved "files[0]")
8963
+ if (ReactiveProxy.pathMatches(changePath, resolved, true)) {
8924
8964
  return true;
8925
8965
  }
8926
8966
  // changePath is an ancestor of resolved (e.g. "files" for resolved "files[0].isModified")
@@ -9985,7 +10025,7 @@ class VTextEvaluator {
9985
10025
  // Build base parameter names (no dots), preserving order of first appearance
9986
10026
  const baseArgs = [];
9987
10027
  for (const id of ids) {
9988
- const base = id.split('.')[0];
10028
+ const base = ExpressionUtils.baseIdentifier(id);
9989
10029
  if (!baseArgs.includes(base)) {
9990
10030
  baseArgs.push(base);
9991
10031
  }
@@ -12330,7 +12370,7 @@ class VIntersectionDirective {
12330
12370
  const identifiers = optionsDirective.dependentIdentifiers;
12331
12371
  const baseArgs = [];
12332
12372
  for (const id of identifiers) {
12333
- const base = id.split('.')[0];
12373
+ const base = ExpressionUtils.baseIdentifier(id);
12334
12374
  if (!baseArgs.includes(base))
12335
12375
  baseArgs.push(base);
12336
12376
  }
@@ -12410,7 +12450,7 @@ class VIntersectionDirective {
12410
12450
  // Note: inline expressions receive entries and $ctx as parameters
12411
12451
  const baseArgs = [];
12412
12452
  for (const id of identifiers) {
12413
- const base = id.split('.')[0];
12453
+ const base = ExpressionUtils.baseIdentifier(id);
12414
12454
  if (!baseArgs.includes(base))
12415
12455
  baseArgs.push(base);
12416
12456
  }
@@ -13548,7 +13588,7 @@ class VPerformanceDirective {
13548
13588
  const identifiers = optionsDirective.dependentIdentifiers;
13549
13589
  const baseArgs = [];
13550
13590
  for (const id of identifiers) {
13551
- const base = id.split('.')[0];
13591
+ const base = ExpressionUtils.baseIdentifier(id);
13552
13592
  if (!baseArgs.includes(base))
13553
13593
  baseArgs.push(base);
13554
13594
  }
@@ -13636,7 +13676,7 @@ class VPerformanceDirective {
13636
13676
  // Note: inline expressions receive entries, observer, options, and $ctx as parameters
13637
13677
  const baseArgs = [];
13638
13678
  for (const id of identifiers) {
13639
- const base = id.split('.')[0];
13679
+ const base = ExpressionUtils.baseIdentifier(id);
13640
13680
  if (!baseArgs.includes(base))
13641
13681
  baseArgs.push(base);
13642
13682
  }
@@ -13769,7 +13809,7 @@ class VResizeDirective {
13769
13809
  const identifiers = optionsDirective.dependentIdentifiers;
13770
13810
  const baseArgs = [];
13771
13811
  for (const id of identifiers) {
13772
- const base = id.split('.')[0];
13812
+ const base = ExpressionUtils.baseIdentifier(id);
13773
13813
  if (!baseArgs.includes(base))
13774
13814
  baseArgs.push(base);
13775
13815
  }
@@ -13849,7 +13889,7 @@ class VResizeDirective {
13849
13889
  // Note: inline expressions receive entries and $ctx as parameters
13850
13890
  const baseArgs = [];
13851
13891
  for (const id of identifiers) {
13852
- const base = id.split('.')[0];
13892
+ const base = ExpressionUtils.baseIdentifier(id);
13853
13893
  if (!baseArgs.includes(base))
13854
13894
  baseArgs.push(base);
13855
13895
  }