@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.
package/dist/ichigo.cjs CHANGED
@@ -6766,28 +6766,29 @@
6766
6766
  }
6767
6767
  }
6768
6768
  else if (node.type === 'MemberExpression') {
6769
- // Reconstruct chain parts from a MemberExpression (e.g. a.b.c)
6769
+ // Reconstruct chain parts from a MemberExpression (e.g. a.b.c). Each part
6770
+ // carries its own separator so that the chain is spelled the way the reactive
6771
+ // proxy reports changes: array indices in brackets, properties after a dot
6772
+ // (e.g. "items[0].name").
6770
6773
  const parts = [];
6771
6774
  let cur = node;
6772
- let stop = false;
6773
- while (cur && !stop) {
6775
+ while (cur) {
6774
6776
  // property part (right side)
6775
6777
  if (cur.property) {
6776
6778
  if (!cur.computed && cur.property.type === 'Identifier') {
6777
- parts.unshift(cur.property.name);
6779
+ parts.unshift(`.${cur.property.name}`);
6778
6780
  }
6779
- else if (cur.computed && cur.property.type === 'Literal') {
6780
- parts.unshift(String(cur.property.value));
6781
+ else if (cur.computed && cur.property.type === 'Literal' && typeof cur.property.value === 'number') {
6782
+ parts.unshift(`[${cur.property.value}]`);
6781
6783
  }
6782
- else if (cur.computed && cur.property.type === 'Identifier') {
6783
- // e.g. obj[prop] -> include the prop identifier (it will also be added separately)
6784
- parts.unshift(cur.property.name);
6784
+ else if (cur.computed && cur.property.type === 'Literal') {
6785
+ parts.unshift(`.${String(cur.property.value)}`);
6785
6786
  }
6786
- else {
6787
- // unknown property shape (e.g. expression) — stop adding chain here
6788
- // inner expressions will be visited separately by walk.full
6789
- stop = true;
6790
- break;
6787
+ else if (cur.computed) {
6788
+ // e.g. items[i] or items[i + 1]: the index is only known when the
6789
+ // expression runs, so "[*]" stands for any index or key. Identifiers
6790
+ // inside the index expression are visited separately by walk.full.
6791
+ parts.unshift('[*]');
6791
6792
  }
6792
6793
  }
6793
6794
  // object part (left side)
@@ -6807,7 +6808,6 @@
6807
6808
  }
6808
6809
  else {
6809
6810
  // other object types (CallExpression, etc.) — stop here
6810
- stop = true;
6811
6811
  break;
6812
6812
  }
6813
6813
  }
@@ -6815,10 +6815,15 @@
6815
6815
  break;
6816
6816
  }
6817
6817
  }
6818
- if (parts.length > 0) {
6819
- // Add progressive chains: 'a', 'a.b', 'a.b.c'
6818
+ // A chain that does not start at a name (e.g. `this.a.b` or `f().b`) begins
6819
+ // with its first property; one that begins with an index names no binding.
6820
+ if (parts.length > 0 && parts[0].startsWith('.')) {
6821
+ parts[0] = parts[0].substring(1);
6822
+ }
6823
+ if (parts.length > 0 && !parts[0].startsWith('[')) {
6824
+ // Add progressive chains: 'a', 'a.b', 'a.b[0]', 'a.b[0].c'
6820
6825
  for (let i = 0; i < parts.length; i++) {
6821
- const chain = parts.slice(0, i + 1).join('.');
6826
+ const chain = parts.slice(0, i + 1).join('');
6822
6827
  identifiers.add(chain);
6823
6828
  // Also apply functionDependencies lookup for the chain key
6824
6829
  if (functionDependencies[chain]) {
@@ -6832,6 +6837,16 @@
6832
6837
  });
6833
6838
  return Array.from(identifiers);
6834
6839
  }
6840
+ /**
6841
+ * Returns the binding name an identifier chain starts with
6842
+ * (e.g. "items" for "items[0].name" or "user.name").
6843
+ * @param identifier An identifier or member chain returned by extractIdentifiers.
6844
+ * @returns The left-most name of the chain.
6845
+ */
6846
+ static baseIdentifier(identifier) {
6847
+ const end = identifier.search(/[.[]/);
6848
+ return end === -1 ? identifier : identifier.substring(0, end);
6849
+ }
6835
6850
  /**
6836
6851
  * Analyzes the dependencies of functions in the provided dictionary.
6837
6852
  * @param functions A dictionary mapping function names to their implementations.
@@ -7246,7 +7261,7 @@
7246
7261
  // Use the base (left-most) segment of member chains and preserve order.
7247
7262
  const baseIdentifiers = [];
7248
7263
  for (const id of extractedIdentifiers) {
7249
- const base = id.split('.')[0];
7264
+ const base = ExpressionUtils.baseIdentifier(id);
7250
7265
  if (!baseIdentifiers.includes(base)) {
7251
7266
  baseIdentifiers.push(base);
7252
7267
  }
@@ -8040,6 +8055,11 @@
8040
8055
  * This allows mapping variable names to their actual source paths for dependency tracking.
8041
8056
  */
8042
8057
  static pathAliases = new Map();
8058
+ /**
8059
+ * Compiled patterns for identifiers that contain a "[*]" index, keyed by the
8060
+ * identifier and whether descendants of the path also match.
8061
+ */
8062
+ static pathPatterns = new Map();
8043
8063
  /**
8044
8064
  * The `Object.prototype.toString` tags of the *only* value types we deeply
8045
8065
  * proxy. Everything else is returned untouched (raw).
@@ -8402,24 +8422,47 @@
8402
8422
  */
8403
8423
  static doesChangeMatchIdentifier(changePath, identifier) {
8404
8424
  // Direct match
8405
- if (changePath === identifier) {
8425
+ if (this.pathMatches(changePath, identifier)) {
8406
8426
  return true;
8407
8427
  }
8408
- // Check if the identifier has an alias that matches
8428
+ // Check if the change path is the resolved identifier or lies below it
8429
+ // (handles cases like array item changes)
8409
8430
  const resolvedIdentifier = this.resolvePathAlias(identifier);
8410
- if (resolvedIdentifier && changePath === resolvedIdentifier) {
8431
+ if (resolvedIdentifier && this.pathMatches(changePath, resolvedIdentifier, true)) {
8411
8432
  return true;
8412
8433
  }
8413
- // Check if change path starts with the resolved identifier
8414
- // (handles cases like array item changes)
8415
- if (resolvedIdentifier) {
8416
- if (changePath.startsWith(resolvedIdentifier + '.') ||
8417
- changePath.startsWith(resolvedIdentifier + '[')) {
8418
- return true;
8419
- }
8420
- }
8421
8434
  return false;
8422
8435
  }
8436
+ /**
8437
+ * Checks whether a change path names the location an identifier refers to.
8438
+ * A "[*]" index in the identifier (e.g. "items[*].name" for `items[i].name`)
8439
+ * stands for an index known only when the expression runs and matches any
8440
+ * one index or key.
8441
+ *
8442
+ * @param changePath The path that was changed (e.g., "items[2].name")
8443
+ * @param identifier The identifier to check (e.g., "items[*].name")
8444
+ * @param descendants Whether a change below the identifier also matches
8445
+ * @returns True if the change path matches the identifier
8446
+ */
8447
+ static pathMatches(changePath, identifier, descendants = false) {
8448
+ if (changePath === identifier) {
8449
+ return true;
8450
+ }
8451
+ if (!identifier.includes('[*]')) {
8452
+ return descendants && (changePath.startsWith(identifier + '.') || changePath.startsWith(identifier + '['));
8453
+ }
8454
+ const cacheKey = descendants ? identifier + ' ' : identifier;
8455
+ let pattern = this.pathPatterns.get(cacheKey);
8456
+ if (!pattern) {
8457
+ const source = identifier
8458
+ .split('[*]')
8459
+ .map(part => part.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
8460
+ .join('(?:\\[[^\\]]*\\]|\\.[^.[]+)');
8461
+ pattern = new RegExp(`^${source}${descendants ? '(?:[.[].*)?' : ''}$`);
8462
+ this.pathPatterns.set(cacheKey, pattern);
8463
+ }
8464
+ return pattern.test(changePath);
8465
+ }
8423
8466
  }
8424
8467
 
8425
8468
  // Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
@@ -8915,18 +8958,15 @@
8915
8958
  * global aliases (computed properties etc.).
8916
8959
  */
8917
8960
  doesChangeMatchIdentifier(changePath, identifier) {
8918
- // Direct match
8919
- if (changePath === identifier) {
8961
+ // Direct match (an index "[*]" in the identifier matches any index)
8962
+ if (ReactiveProxy.pathMatches(changePath, identifier)) {
8920
8963
  return true;
8921
8964
  }
8922
8965
  // Resolve via local (scoped) alias chain
8923
8966
  const resolved = this.resolveAlias(identifier);
8924
8967
  if (resolved) {
8925
- if (changePath === resolved) {
8926
- return true;
8927
- }
8928
- // changePath is a descendant of resolved (e.g. "files[0].isModified" for resolved "files[0]")
8929
- if (changePath.startsWith(resolved + '.') || changePath.startsWith(resolved + '[')) {
8968
+ // changePath is resolved itself or a descendant of it (e.g. "files[0].isModified" for resolved "files[0]")
8969
+ if (ReactiveProxy.pathMatches(changePath, resolved, true)) {
8930
8970
  return true;
8931
8971
  }
8932
8972
  // changePath is an ancestor of resolved (e.g. "files" for resolved "files[0].isModified")
@@ -9991,7 +10031,7 @@
9991
10031
  // Build base parameter names (no dots), preserving order of first appearance
9992
10032
  const baseArgs = [];
9993
10033
  for (const id of ids) {
9994
- const base = id.split('.')[0];
10034
+ const base = ExpressionUtils.baseIdentifier(id);
9995
10035
  if (!baseArgs.includes(base)) {
9996
10036
  baseArgs.push(base);
9997
10037
  }
@@ -12336,7 +12376,7 @@
12336
12376
  const identifiers = optionsDirective.dependentIdentifiers;
12337
12377
  const baseArgs = [];
12338
12378
  for (const id of identifiers) {
12339
- const base = id.split('.')[0];
12379
+ const base = ExpressionUtils.baseIdentifier(id);
12340
12380
  if (!baseArgs.includes(base))
12341
12381
  baseArgs.push(base);
12342
12382
  }
@@ -12416,7 +12456,7 @@
12416
12456
  // Note: inline expressions receive entries and $ctx as parameters
12417
12457
  const baseArgs = [];
12418
12458
  for (const id of identifiers) {
12419
- const base = id.split('.')[0];
12459
+ const base = ExpressionUtils.baseIdentifier(id);
12420
12460
  if (!baseArgs.includes(base))
12421
12461
  baseArgs.push(base);
12422
12462
  }
@@ -13554,7 +13594,7 @@
13554
13594
  const identifiers = optionsDirective.dependentIdentifiers;
13555
13595
  const baseArgs = [];
13556
13596
  for (const id of identifiers) {
13557
- const base = id.split('.')[0];
13597
+ const base = ExpressionUtils.baseIdentifier(id);
13558
13598
  if (!baseArgs.includes(base))
13559
13599
  baseArgs.push(base);
13560
13600
  }
@@ -13642,7 +13682,7 @@
13642
13682
  // Note: inline expressions receive entries, observer, options, and $ctx as parameters
13643
13683
  const baseArgs = [];
13644
13684
  for (const id of identifiers) {
13645
- const base = id.split('.')[0];
13685
+ const base = ExpressionUtils.baseIdentifier(id);
13646
13686
  if (!baseArgs.includes(base))
13647
13687
  baseArgs.push(base);
13648
13688
  }
@@ -13775,7 +13815,7 @@
13775
13815
  const identifiers = optionsDirective.dependentIdentifiers;
13776
13816
  const baseArgs = [];
13777
13817
  for (const id of identifiers) {
13778
- const base = id.split('.')[0];
13818
+ const base = ExpressionUtils.baseIdentifier(id);
13779
13819
  if (!baseArgs.includes(base))
13780
13820
  baseArgs.push(base);
13781
13821
  }
@@ -13855,7 +13895,7 @@
13855
13895
  // Note: inline expressions receive entries and $ctx as parameters
13856
13896
  const baseArgs = [];
13857
13897
  for (const id of identifiers) {
13858
- const base = id.split('.')[0];
13898
+ const base = ExpressionUtils.baseIdentifier(id);
13859
13899
  if (!baseArgs.includes(base))
13860
13900
  baseArgs.push(base);
13861
13901
  }