@mintjamsinc/ichigojs 0.1.50 → 0.1.51

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
@@ -8127,6 +8127,12 @@
8127
8127
  * Flag to suppress onChange callbacks temporarily.
8128
8128
  */
8129
8129
  #suppressOnChange = false;
8130
+ /**
8131
+ * Per-instance path aliases. Maps local variable names to their reactive source paths.
8132
+ * Scoped here instead of the global ReactiveProxy map so that v-for items each maintain
8133
+ * their own alias (e.g. "file" -> "files[0]") without overwriting each other.
8134
+ */
8135
+ #localAliases = new Map();
8130
8136
  /**
8131
8137
  * Creates a new instance of VBindings.
8132
8138
  * @param parent The parent bindings, if any.
@@ -8161,7 +8167,7 @@
8161
8167
  const existingPath = ReactiveProxy.getPath(value);
8162
8168
  if (existingPath) {
8163
8169
  // Register a path alias so changes to the source path will match this identifier
8164
- ReactiveProxy.registerPathAlias(key, existingPath);
8170
+ this.#localAliases.set(key, existingPath);
8165
8171
  this.#logger?.debug(`Path alias registered: ${key} -> ${existingPath}`);
8166
8172
  // Keep the existing proxy as-is to preserve reactivity chain
8167
8173
  newValue = value;
@@ -8176,7 +8182,7 @@
8176
8182
  const propPath = ReactiveProxy.getPath(propValue);
8177
8183
  if (propPath) {
8178
8184
  // Register alias: key.propKey -> propPath
8179
- ReactiveProxy.registerPathAlias(`${key}.${propKey}`, propPath);
8185
+ this.#localAliases.set(`${key}.${propKey}`, propPath);
8180
8186
  this.#logger?.debug(`Property path alias registered: ${key}.${propKey} -> ${propPath}`);
8181
8187
  }
8182
8188
  }
@@ -8197,8 +8203,14 @@
8197
8203
  }
8198
8204
  }
8199
8205
  else if (value === null || value === undefined) {
8200
- // When setting to null/undefined, unregister any path alias
8201
- ReactiveProxy.unregisterPathAlias(key);
8206
+ // When setting to null/undefined, remove local aliases for this key and nested paths
8207
+ for (const aliasKey of [...this.#localAliases.keys()]) {
8208
+ if (aliasKey === key ||
8209
+ aliasKey.startsWith(key + ".") ||
8210
+ aliasKey.startsWith(key + "[")) {
8211
+ this.#localAliases.delete(aliasKey);
8212
+ }
8213
+ }
8202
8214
  }
8203
8215
  const oldValue = Reflect.get(target, key);
8204
8216
  const result = Reflect.set(target, key, newValue);
@@ -8335,6 +8347,54 @@
8335
8347
  markChanged(key) {
8336
8348
  this.#changes.add(key);
8337
8349
  }
8350
+ /**
8351
+ * Resolves a local path alias for the given identifier by walking up the bindings chain.
8352
+ * Returns the resolved source path, or undefined if no alias is found.
8353
+ */
8354
+ resolveAlias(identifier) {
8355
+ // Direct match in local aliases
8356
+ if (this.#localAliases.has(identifier)) {
8357
+ return this.#localAliases.get(identifier);
8358
+ }
8359
+ // Check if this is a nested path of a locally aliased variable (e.g. "file.isModified")
8360
+ for (const [alias, source] of this.#localAliases.entries()) {
8361
+ if (identifier.startsWith(alias + '.') || identifier.startsWith(alias + '[')) {
8362
+ return source + identifier.substring(alias.length);
8363
+ }
8364
+ }
8365
+ // Walk up the parent chain
8366
+ return this.#parent?.resolveAlias(identifier);
8367
+ }
8368
+ /**
8369
+ * Checks whether a reactive change path matches a given identifier, taking local path
8370
+ * aliases into account. Falls back to ReactiveProxy.doesChangeMatchIdentifier for
8371
+ * global aliases (computed properties etc.).
8372
+ */
8373
+ doesChangeMatchIdentifier(changePath, identifier) {
8374
+ // Direct match
8375
+ if (changePath === identifier) {
8376
+ return true;
8377
+ }
8378
+ // Resolve via local (scoped) alias chain
8379
+ const resolved = this.resolveAlias(identifier);
8380
+ if (resolved) {
8381
+ if (changePath === resolved) {
8382
+ return true;
8383
+ }
8384
+ // changePath is a descendant of resolved (e.g. "files[0].isModified" for resolved "files[0]")
8385
+ if (changePath.startsWith(resolved + '.') || changePath.startsWith(resolved + '[')) {
8386
+ return true;
8387
+ }
8388
+ // changePath is an ancestor of resolved (e.g. "files" for resolved "files[0].isModified")
8389
+ // This handles raw objects: when the parent collection is replaced/spliced, all item
8390
+ // properties are considered changed.
8391
+ if (resolved.startsWith(changePath + '.') || resolved.startsWith(changePath + '[')) {
8392
+ return true;
8393
+ }
8394
+ }
8395
+ // Fall back to global alias resolution (computed properties, etc.)
8396
+ return ReactiveProxy.doesChangeMatchIdentifier(changePath, identifier);
8397
+ }
8338
8398
  }
8339
8399
 
8340
8400
  // Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
@@ -9051,7 +9111,7 @@
9051
9111
  if (this.#nodeType === Node.TEXT_NODE && this.#textEvaluator) {
9052
9112
  // If this is a text node with a text evaluator, update its content if needed
9053
9113
  // Check if any of the identifiers are in the changed identifiers (considering path aliases)
9054
- const changed = this.#textEvaluator.identifiers.some(id => changes.some(change => ReactiveProxy.doesChangeMatchIdentifier(change, id)));
9114
+ const changed = this.#textEvaluator.identifiers.some(id => changes.some(change => this.bindings.doesChangeMatchIdentifier(change, id)));
9055
9115
  // If the text node has changed, update its content
9056
9116
  if (changed) {
9057
9117
  const text = this.#node;
@@ -9074,7 +9134,7 @@
9074
9134
  }
9075
9135
  // Prepare bindings for each preparer if relevant identifiers have changed
9076
9136
  for (const preparer of this.#directiveManager.bindingsPreparers) {
9077
- const changed = preparer.dependentIdentifiers.some(id => changes.some(change => ReactiveProxy.doesChangeMatchIdentifier(change, id)));
9137
+ const changed = preparer.dependentIdentifiers.some(id => changes.some(change => this.bindings.doesChangeMatchIdentifier(change, id)));
9078
9138
  if (changed) {
9079
9139
  preparer.prepareBindings();
9080
9140
  }
@@ -9083,7 +9143,7 @@
9083
9143
  // Apply DOM updaters from directives, if any
9084
9144
  if (this.#directiveManager?.domUpdaters) {
9085
9145
  for (const updater of this.#directiveManager.domUpdaters) {
9086
- const changed = updater.dependentIdentifiers.some(id => changes.some(change => ReactiveProxy.doesChangeMatchIdentifier(change, id)));
9146
+ const changed = updater.dependentIdentifiers.some(id => changes.some(change => this.bindings.doesChangeMatchIdentifier(change, id)));
9087
9147
  if (changed) {
9088
9148
  updater.applyToDOM();
9089
9149
  }
@@ -9091,7 +9151,7 @@
9091
9151
  }
9092
9152
  // Recursively update dependent virtual nodes
9093
9153
  this.#dependents?.forEach(dependentNode => {
9094
- const changed = dependentNode.dependentIdentifiers.some(id => changes.some(change => ReactiveProxy.doesChangeMatchIdentifier(change, id)));
9154
+ const changed = dependentNode.dependentIdentifiers.some(id => changes.some(change => dependentNode.bindings.doesChangeMatchIdentifier(change, id)));
9095
9155
  if (changed) {
9096
9156
  dependentNode.update();
9097
9157
  }