@codemirror/state 0.19.6 → 0.19.7

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/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 0.19.7 (2022-02-11)
2
+
3
+ ### Bug fixes
4
+
5
+ Avoid recomputing facets on state reconfiguration if that facet's inputs stayed precisely the same.
6
+
7
+ Selection ranges created with `EditorSelection.range` will now have an assoc pointing at their anchor, when non-empty.
8
+
1
9
  ## 0.19.6 (2021-11-19)
2
10
 
3
11
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -265,7 +265,9 @@ class ChangeSet extends ChangeDesc {
265
265
  map(other, before = false) { return other.empty ? this : mapSet(this, other, before, true); }
266
266
  /**
267
267
  Iterate over the changed ranges in the document, calling `f` for
268
- each.
268
+ each, with the range in the original document (`fromA`-`toA`)
269
+ and the range that replaces it in the new document
270
+ (`fromB`-`toB`).
269
271
 
270
272
  When `individual` is true, adjacent changes are reported
271
273
  separately.
@@ -835,7 +837,8 @@ class EditorSelection {
835
837
  */
836
838
  static range(anchor, head, goalColumn) {
837
839
  let goal = (goalColumn !== null && goalColumn !== void 0 ? goalColumn : 33554431 /* NoGoalColumn */) << 5 /* GoalColumnOffset */;
838
- return head < anchor ? new SelectionRange(head, anchor, 16 /* Inverted */ | goal) : new SelectionRange(anchor, head, goal);
840
+ return head < anchor ? new SelectionRange(head, anchor, 16 /* Inverted */ | goal | 8 /* AssocAfter */)
841
+ : new SelectionRange(anchor, head, goal | (head > anchor ? 4 /* AssocBefore */ : 0));
839
842
  }
840
843
  }
841
844
  function normalized(ranges, mainIndex = 0) {
@@ -1001,7 +1004,7 @@ function dynamicFacetSlot(addresses, facet, providers) {
1001
1004
  let dynamic = providerAddrs.filter(p => !(p & 1));
1002
1005
  let idx = addresses[facet.id] >> 1;
1003
1006
  return (state, tr) => {
1004
- let oldVal = state.values[idx], changed = oldVal === Uninitialized || !tr;
1007
+ let oldVal = state.values[idx], changed = oldVal === Uninitialized;
1005
1008
  for (let dynAddr of dynamic) {
1006
1009
  if (ensureAddr(state, dynAddr) & 1 /* Changed */)
1007
1010
  changed = true;
@@ -1192,12 +1195,13 @@ class CompartmentInstance {
1192
1195
  }
1193
1196
  }
1194
1197
  class Configuration {
1195
- constructor(base, compartments, dynamicSlots, address, staticValues) {
1198
+ constructor(base, compartments, dynamicSlots, address, staticValues, facets) {
1196
1199
  this.base = base;
1197
1200
  this.compartments = compartments;
1198
1201
  this.dynamicSlots = dynamicSlots;
1199
1202
  this.address = address;
1200
1203
  this.staticValues = staticValues;
1204
+ this.facets = facets;
1201
1205
  this.statusTemplate = [];
1202
1206
  while (this.statusTemplate.length < dynamicSlots.length)
1203
1207
  this.statusTemplate.push(0 /* Unresolved */);
@@ -1219,27 +1223,44 @@ class Configuration {
1219
1223
  let address = Object.create(null);
1220
1224
  let staticValues = [];
1221
1225
  let dynamicSlots = [];
1222
- let dynamicDeps = [];
1226
+ let dynamicValues = [];
1223
1227
  for (let field of fields) {
1224
1228
  address[field.id] = dynamicSlots.length << 1;
1225
1229
  dynamicSlots.push(a => field.slot(a));
1226
- dynamicDeps.push([]);
1230
+ dynamicValues.push(oldState && oldState.config.address[field.id] != null ? oldState.field(field) : Uninitialized);
1227
1231
  }
1232
+ let canReuseCache = new Map;
1233
+ let canReuseDep = (dep) => {
1234
+ if (!(dep instanceof Facet))
1235
+ return true;
1236
+ let cached = canReuseCache.get(dep);
1237
+ if (cached != null)
1238
+ return cached;
1239
+ canReuseCache.set(dep, false);
1240
+ if (!oldFacets || !sameArray(oldFacets[dep.id] || [], facets[dep.id] || []))
1241
+ return;
1242
+ for (let input of facets[dep.id] || [])
1243
+ if (!input.dependencies.every(canReuseDep))
1244
+ return;
1245
+ canReuseCache.set(dep, true);
1246
+ };
1247
+ let oldFacets = oldState === null || oldState === void 0 ? void 0 : oldState.config.facets;
1228
1248
  for (let id in facets) {
1229
1249
  let providers = facets[id], facet = providers[0].facet;
1250
+ let oldProviders = oldFacets && oldFacets[id] || [];
1251
+ let canReuse = sameArray(providers, oldProviders);
1230
1252
  if (providers.every(p => p.type == 0 /* Static */)) {
1231
1253
  address[facet.id] = (staticValues.length << 1) | 1;
1232
- let value = facet.combine(providers.map(p => p.value));
1233
- let oldAddr = oldState ? oldState.config.address[facet.id] : null;
1234
- if (oldAddr != null) {
1235
- let oldVal = getAddr(oldState, oldAddr);
1236
- if (facet.compare(value, oldVal))
1237
- value = oldVal;
1238
- }
1254
+ let value = canReuse ? oldState.facet(facet) : facet.combine(providers.map(p => p.value)), oldValue;
1255
+ if (!canReuse && oldState && facet.compare(value, oldValue = oldState.facet(facet)))
1256
+ value = oldValue;
1239
1257
  staticValues.push(value);
1240
1258
  }
1241
1259
  else {
1242
1260
  for (let p of providers) {
1261
+ let canReuseThis = p.dependencies.every(canReuseDep);
1262
+ if (!canReuseThis)
1263
+ canReuse = false;
1243
1264
  if (p.type == 0 /* Static */) {
1244
1265
  address[p.id] = (staticValues.length << 1) | 1;
1245
1266
  staticValues.push(p.value);
@@ -1247,35 +1268,18 @@ class Configuration {
1247
1268
  else {
1248
1269
  address[p.id] = dynamicSlots.length << 1;
1249
1270
  dynamicSlots.push(a => p.dynamicSlot(a));
1250
- dynamicDeps.push(p.dependencies.filter(d => typeof d != "string").map(d => d.id));
1271
+ let oldAddr = oldState && canReuseThis ? oldState.config.address[p.id] : null;
1272
+ dynamicValues.push(oldAddr != null ? getAddr(oldState, oldAddr) : Uninitialized);
1251
1273
  }
1252
1274
  }
1253
1275
  address[facet.id] = dynamicSlots.length << 1;
1254
1276
  dynamicSlots.push(a => dynamicFacetSlot(a, facet, providers));
1255
- dynamicDeps.push(providers.filter(p => p.type != 0 /* Static */).map(d => d.id));
1256
- }
1257
- }
1258
- let dynamicValues = dynamicSlots.map(_ => Uninitialized);
1259
- if (oldState) {
1260
- let canReuse = (id, depth) => {
1261
- if (depth > 7)
1262
- return false;
1263
- let addr = address[id];
1264
- if (!(addr & 1))
1265
- return dynamicDeps[addr >> 1].every(id => canReuse(id, depth + 1));
1266
- let oldAddr = oldState.config.address[id];
1267
- return oldAddr != null && getAddr(oldState, oldAddr) == staticValues[addr >> 1];
1268
- };
1269
- // Copy over old values for shared facets/fields, if we can
1270
- // prove that they don't need to be recomputed.
1271
- for (let id in address) {
1272
- let cur = address[id], prev = oldState.config.address[id];
1273
- if (prev != null && (cur & 1) == 0 && canReuse(+id, 0))
1274
- dynamicValues[cur >> 1] = getAddr(oldState, prev);
1277
+ dynamicValues.push(canReuse || oldProviders.length ? oldState.facet(facet) : Uninitialized);
1275
1278
  }
1276
1279
  }
1280
+ let dynamic = dynamicSlots.map(f => f(address));
1277
1281
  return {
1278
- configuration: new Configuration(base, newCompartments, dynamicSlots.map(f => f(address)), address, staticValues),
1282
+ configuration: new Configuration(base, newCompartments, dynamic, address, staticValues, facets),
1279
1283
  values: dynamicValues
1280
1284
  };
1281
1285
  }
@@ -2285,9 +2289,7 @@ combine = {}) {
2285
2289
 
2286
2290
  Object.defineProperty(exports, 'Text', {
2287
2291
  enumerable: true,
2288
- get: function () {
2289
- return text.Text;
2290
- }
2292
+ get: function () { return text.Text; }
2291
2293
  });
2292
2294
  exports.Annotation = Annotation;
2293
2295
  exports.AnnotationType = AnnotationType;
package/dist/index.d.ts CHANGED
@@ -163,7 +163,9 @@ declare class ChangeSet extends ChangeDesc {
163
163
  map(other: ChangeDesc, before?: boolean): ChangeSet;
164
164
  /**
165
165
  Iterate over the changed ranges in the document, calling `f` for
166
- each.
166
+ each, with the range in the original document (`fromA`-`toA`)
167
+ and the range that replaces it in the new document
168
+ (`fromB`-`toB`).
167
169
 
168
170
  When `individual` is true, adjacent changes are reported
169
171
  separately.
package/dist/index.js CHANGED
@@ -261,7 +261,9 @@ class ChangeSet extends ChangeDesc {
261
261
  map(other, before = false) { return other.empty ? this : mapSet(this, other, before, true); }
262
262
  /**
263
263
  Iterate over the changed ranges in the document, calling `f` for
264
- each.
264
+ each, with the range in the original document (`fromA`-`toA`)
265
+ and the range that replaces it in the new document
266
+ (`fromB`-`toB`).
265
267
 
266
268
  When `individual` is true, adjacent changes are reported
267
269
  separately.
@@ -831,7 +833,8 @@ class EditorSelection {
831
833
  */
832
834
  static range(anchor, head, goalColumn) {
833
835
  let goal = (goalColumn !== null && goalColumn !== void 0 ? goalColumn : 33554431 /* NoGoalColumn */) << 5 /* GoalColumnOffset */;
834
- return head < anchor ? new SelectionRange(head, anchor, 16 /* Inverted */ | goal) : new SelectionRange(anchor, head, goal);
836
+ return head < anchor ? new SelectionRange(head, anchor, 16 /* Inverted */ | goal | 8 /* AssocAfter */)
837
+ : new SelectionRange(anchor, head, goal | (head > anchor ? 4 /* AssocBefore */ : 0));
835
838
  }
836
839
  }
837
840
  function normalized(ranges, mainIndex = 0) {
@@ -997,7 +1000,7 @@ function dynamicFacetSlot(addresses, facet, providers) {
997
1000
  let dynamic = providerAddrs.filter(p => !(p & 1));
998
1001
  let idx = addresses[facet.id] >> 1;
999
1002
  return (state, tr) => {
1000
- let oldVal = state.values[idx], changed = oldVal === Uninitialized || !tr;
1003
+ let oldVal = state.values[idx], changed = oldVal === Uninitialized;
1001
1004
  for (let dynAddr of dynamic) {
1002
1005
  if (ensureAddr(state, dynAddr) & 1 /* Changed */)
1003
1006
  changed = true;
@@ -1188,12 +1191,13 @@ class CompartmentInstance {
1188
1191
  }
1189
1192
  }
1190
1193
  class Configuration {
1191
- constructor(base, compartments, dynamicSlots, address, staticValues) {
1194
+ constructor(base, compartments, dynamicSlots, address, staticValues, facets) {
1192
1195
  this.base = base;
1193
1196
  this.compartments = compartments;
1194
1197
  this.dynamicSlots = dynamicSlots;
1195
1198
  this.address = address;
1196
1199
  this.staticValues = staticValues;
1200
+ this.facets = facets;
1197
1201
  this.statusTemplate = [];
1198
1202
  while (this.statusTemplate.length < dynamicSlots.length)
1199
1203
  this.statusTemplate.push(0 /* Unresolved */);
@@ -1215,27 +1219,44 @@ class Configuration {
1215
1219
  let address = Object.create(null);
1216
1220
  let staticValues = [];
1217
1221
  let dynamicSlots = [];
1218
- let dynamicDeps = [];
1222
+ let dynamicValues = [];
1219
1223
  for (let field of fields) {
1220
1224
  address[field.id] = dynamicSlots.length << 1;
1221
1225
  dynamicSlots.push(a => field.slot(a));
1222
- dynamicDeps.push([]);
1226
+ dynamicValues.push(oldState && oldState.config.address[field.id] != null ? oldState.field(field) : Uninitialized);
1223
1227
  }
1228
+ let canReuseCache = new Map;
1229
+ let canReuseDep = (dep) => {
1230
+ if (!(dep instanceof Facet))
1231
+ return true;
1232
+ let cached = canReuseCache.get(dep);
1233
+ if (cached != null)
1234
+ return cached;
1235
+ canReuseCache.set(dep, false);
1236
+ if (!oldFacets || !sameArray(oldFacets[dep.id] || [], facets[dep.id] || []))
1237
+ return;
1238
+ for (let input of facets[dep.id] || [])
1239
+ if (!input.dependencies.every(canReuseDep))
1240
+ return;
1241
+ canReuseCache.set(dep, true);
1242
+ };
1243
+ let oldFacets = oldState === null || oldState === void 0 ? void 0 : oldState.config.facets;
1224
1244
  for (let id in facets) {
1225
1245
  let providers = facets[id], facet = providers[0].facet;
1246
+ let oldProviders = oldFacets && oldFacets[id] || [];
1247
+ let canReuse = sameArray(providers, oldProviders);
1226
1248
  if (providers.every(p => p.type == 0 /* Static */)) {
1227
1249
  address[facet.id] = (staticValues.length << 1) | 1;
1228
- let value = facet.combine(providers.map(p => p.value));
1229
- let oldAddr = oldState ? oldState.config.address[facet.id] : null;
1230
- if (oldAddr != null) {
1231
- let oldVal = getAddr(oldState, oldAddr);
1232
- if (facet.compare(value, oldVal))
1233
- value = oldVal;
1234
- }
1250
+ let value = canReuse ? oldState.facet(facet) : facet.combine(providers.map(p => p.value)), oldValue;
1251
+ if (!canReuse && oldState && facet.compare(value, oldValue = oldState.facet(facet)))
1252
+ value = oldValue;
1235
1253
  staticValues.push(value);
1236
1254
  }
1237
1255
  else {
1238
1256
  for (let p of providers) {
1257
+ let canReuseThis = p.dependencies.every(canReuseDep);
1258
+ if (!canReuseThis)
1259
+ canReuse = false;
1239
1260
  if (p.type == 0 /* Static */) {
1240
1261
  address[p.id] = (staticValues.length << 1) | 1;
1241
1262
  staticValues.push(p.value);
@@ -1243,35 +1264,18 @@ class Configuration {
1243
1264
  else {
1244
1265
  address[p.id] = dynamicSlots.length << 1;
1245
1266
  dynamicSlots.push(a => p.dynamicSlot(a));
1246
- dynamicDeps.push(p.dependencies.filter(d => typeof d != "string").map(d => d.id));
1267
+ let oldAddr = oldState && canReuseThis ? oldState.config.address[p.id] : null;
1268
+ dynamicValues.push(oldAddr != null ? getAddr(oldState, oldAddr) : Uninitialized);
1247
1269
  }
1248
1270
  }
1249
1271
  address[facet.id] = dynamicSlots.length << 1;
1250
1272
  dynamicSlots.push(a => dynamicFacetSlot(a, facet, providers));
1251
- dynamicDeps.push(providers.filter(p => p.type != 0 /* Static */).map(d => d.id));
1252
- }
1253
- }
1254
- let dynamicValues = dynamicSlots.map(_ => Uninitialized);
1255
- if (oldState) {
1256
- let canReuse = (id, depth) => {
1257
- if (depth > 7)
1258
- return false;
1259
- let addr = address[id];
1260
- if (!(addr & 1))
1261
- return dynamicDeps[addr >> 1].every(id => canReuse(id, depth + 1));
1262
- let oldAddr = oldState.config.address[id];
1263
- return oldAddr != null && getAddr(oldState, oldAddr) == staticValues[addr >> 1];
1264
- };
1265
- // Copy over old values for shared facets/fields, if we can
1266
- // prove that they don't need to be recomputed.
1267
- for (let id in address) {
1268
- let cur = address[id], prev = oldState.config.address[id];
1269
- if (prev != null && (cur & 1) == 0 && canReuse(+id, 0))
1270
- dynamicValues[cur >> 1] = getAddr(oldState, prev);
1273
+ dynamicValues.push(canReuse || oldProviders.length ? oldState.facet(facet) : Uninitialized);
1271
1274
  }
1272
1275
  }
1276
+ let dynamic = dynamicSlots.map(f => f(address));
1273
1277
  return {
1274
- configuration: new Configuration(base, newCompartments, dynamicSlots.map(f => f(address)), address, staticValues),
1278
+ configuration: new Configuration(base, newCompartments, dynamic, address, staticValues, facets),
1275
1279
  values: dynamicValues
1276
1280
  };
1277
1281
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/state",
3
- "version": "0.19.6",
3
+ "version": "0.19.7",
4
4
  "description": "Editor state data structures for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",