@codemirror/state 0.19.3 → 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,31 @@
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
+
9
+ ## 0.19.6 (2021-11-19)
10
+
11
+ ### Bug fixes
12
+
13
+ Fix a bug that caused facet compare functions to be called with an invalid value in some situations.
14
+
15
+ Fix a bug that caused dynamic facet values to be incorrectly kept unchanged when reconfiguration changed one of their dependencies.
16
+
17
+ ## 0.19.5 (2021-11-10)
18
+
19
+ ### Bug fixes
20
+
21
+ Fix a bug that would cause dynamic facet values influenced by a state reconfiguration to not properly recompute.
22
+
23
+ ## 0.19.4 (2021-11-05)
24
+
25
+ ### Bug fixes
26
+
27
+ When reconfiguring a state, effects from the reconfiguring transaction can now be seen by newly added state fields.
28
+
1
29
  ## 0.19.3 (2021-11-03)
2
30
 
3
31
  ### New features
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) {
@@ -967,21 +970,23 @@ class FacetProvider {
967
970
  depAddrs.push(addresses[dep.id]);
968
971
  }
969
972
  return (state, tr) => {
970
- if (!tr || tr.reconfigured) {
973
+ let oldVal = state.values[idx];
974
+ if (oldVal === Uninitialized) {
971
975
  state.values[idx] = getter(state);
972
976
  return 1 /* Changed */;
973
977
  }
974
- else {
978
+ if (tr) {
975
979
  let depChanged = (depDoc && tr.docChanged) || (depSel && (tr.docChanged || tr.selection)) ||
976
980
  depAddrs.some(addr => (ensureAddr(state, addr) & 1 /* Changed */) > 0);
977
- if (!depChanged)
978
- return 0;
979
- let newVal = getter(state), oldVal = tr.startState.values[idx];
980
- if (multi ? compareArray(newVal, oldVal, compare) : compare(newVal, oldVal))
981
- return 0;
982
- state.values[idx] = newVal;
983
- return 1 /* Changed */;
981
+ if (depChanged) {
982
+ let newVal = getter(state);
983
+ if (multi ? !compareArray(newVal, oldVal, compare) : !compare(newVal, oldVal)) {
984
+ state.values[idx] = newVal;
985
+ return 1 /* Changed */;
986
+ }
987
+ }
984
988
  }
989
+ return 0;
985
990
  };
986
991
  }
987
992
  }
@@ -999,8 +1004,7 @@ function dynamicFacetSlot(addresses, facet, providers) {
999
1004
  let dynamic = providerAddrs.filter(p => !(p & 1));
1000
1005
  let idx = addresses[facet.id] >> 1;
1001
1006
  return (state, tr) => {
1002
- let oldAddr = !tr ? null : tr.reconfigured ? tr.startState.config.address[facet.id] : idx << 1;
1003
- let changed = oldAddr == null;
1007
+ let oldVal = state.values[idx], changed = oldVal === Uninitialized;
1004
1008
  for (let dynAddr of dynamic) {
1005
1009
  if (ensureAddr(state, dynAddr) & 1 /* Changed */)
1006
1010
  changed = true;
@@ -1016,17 +1020,13 @@ function dynamicFacetSlot(addresses, facet, providers) {
1016
1020
  else
1017
1021
  values.push(value);
1018
1022
  }
1019
- let newVal = facet.combine(values);
1020
- if (oldAddr != null && facet.compare(newVal, getAddr(tr.startState, oldAddr)))
1023
+ let value = facet.combine(values);
1024
+ if (oldVal !== Uninitialized && facet.compare(value, oldVal))
1021
1025
  return 0;
1022
- state.values[idx] = newVal;
1026
+ state.values[idx] = value;
1023
1027
  return 1 /* Changed */;
1024
1028
  };
1025
1029
  }
1026
- function maybeIndex(state, id) {
1027
- let found = state.config.address[id];
1028
- return found == null ? null : found >> 1;
1029
- }
1030
1030
  const initField = Facet.define({ static: true });
1031
1031
  /**
1032
1032
  Fields can store additional information in an editor state, and
@@ -1071,24 +1071,19 @@ class StateField {
1071
1071
  slot(addresses) {
1072
1072
  let idx = addresses[this.id] >> 1;
1073
1073
  return (state, tr) => {
1074
- if (!tr || (tr.reconfigured && maybeIndex(tr.startState, this.id) == null)) {
1074
+ let oldVal = state.values[idx];
1075
+ if (oldVal === Uninitialized) {
1075
1076
  state.values[idx] = this.create(state);
1076
1077
  return 1 /* Changed */;
1077
1078
  }
1078
- let oldVal, changed = 0;
1079
- if (tr.reconfigured) {
1080
- oldVal = tr.startState.values[maybeIndex(tr.startState, this.id)];
1081
- changed = 1 /* Changed */;
1082
- }
1083
- else {
1084
- oldVal = tr.startState.values[idx];
1079
+ if (tr) {
1080
+ let value = this.updateF(oldVal, tr);
1081
+ if (!this.compareF(oldVal, value)) {
1082
+ state.values[idx] = value;
1083
+ return 1 /* Changed */;
1084
+ }
1085
1085
  }
1086
- let value = this.updateF(oldVal, tr);
1087
- if (!changed && !this.compareF(oldVal, value))
1088
- changed = 1 /* Changed */;
1089
- if (changed)
1090
- state.values[idx] = value;
1091
- return changed;
1086
+ return 0;
1092
1087
  };
1093
1088
  }
1094
1089
  /**
@@ -1200,15 +1195,16 @@ class CompartmentInstance {
1200
1195
  }
1201
1196
  }
1202
1197
  class Configuration {
1203
- constructor(base, compartments, dynamicSlots, address, staticValues) {
1198
+ constructor(base, compartments, dynamicSlots, address, staticValues, facets) {
1204
1199
  this.base = base;
1205
1200
  this.compartments = compartments;
1206
1201
  this.dynamicSlots = dynamicSlots;
1207
1202
  this.address = address;
1208
1203
  this.staticValues = staticValues;
1204
+ this.facets = facets;
1209
1205
  this.statusTemplate = [];
1210
1206
  while (this.statusTemplate.length < dynamicSlots.length)
1211
- this.statusTemplate.push(0 /* Uninitialized */);
1207
+ this.statusTemplate.push(0 /* Unresolved */);
1212
1208
  }
1213
1209
  staticFacet(facet) {
1214
1210
  let addr = this.address[facet.id];
@@ -1227,25 +1223,44 @@ class Configuration {
1227
1223
  let address = Object.create(null);
1228
1224
  let staticValues = [];
1229
1225
  let dynamicSlots = [];
1226
+ let dynamicValues = [];
1230
1227
  for (let field of fields) {
1231
1228
  address[field.id] = dynamicSlots.length << 1;
1232
1229
  dynamicSlots.push(a => field.slot(a));
1230
+ dynamicValues.push(oldState && oldState.config.address[field.id] != null ? oldState.field(field) : Uninitialized);
1233
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;
1234
1248
  for (let id in facets) {
1235
1249
  let providers = facets[id], facet = providers[0].facet;
1250
+ let oldProviders = oldFacets && oldFacets[id] || [];
1251
+ let canReuse = sameArray(providers, oldProviders);
1236
1252
  if (providers.every(p => p.type == 0 /* Static */)) {
1237
1253
  address[facet.id] = (staticValues.length << 1) | 1;
1238
- let value = facet.combine(providers.map(p => p.value));
1239
- let oldAddr = oldState ? oldState.config.address[facet.id] : null;
1240
- if (oldAddr != null) {
1241
- let oldVal = getAddr(oldState, oldAddr);
1242
- if (facet.compare(value, oldVal))
1243
- value = oldVal;
1244
- }
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;
1245
1257
  staticValues.push(value);
1246
1258
  }
1247
1259
  else {
1248
1260
  for (let p of providers) {
1261
+ let canReuseThis = p.dependencies.every(canReuseDep);
1262
+ if (!canReuseThis)
1263
+ canReuse = false;
1249
1264
  if (p.type == 0 /* Static */) {
1250
1265
  address[p.id] = (staticValues.length << 1) | 1;
1251
1266
  staticValues.push(p.value);
@@ -1253,13 +1268,20 @@ class Configuration {
1253
1268
  else {
1254
1269
  address[p.id] = dynamicSlots.length << 1;
1255
1270
  dynamicSlots.push(a => p.dynamicSlot(a));
1271
+ let oldAddr = oldState && canReuseThis ? oldState.config.address[p.id] : null;
1272
+ dynamicValues.push(oldAddr != null ? getAddr(oldState, oldAddr) : Uninitialized);
1256
1273
  }
1257
1274
  }
1258
1275
  address[facet.id] = dynamicSlots.length << 1;
1259
1276
  dynamicSlots.push(a => dynamicFacetSlot(a, facet, providers));
1277
+ dynamicValues.push(canReuse || oldProviders.length ? oldState.facet(facet) : Uninitialized);
1260
1278
  }
1261
1279
  }
1262
- return new Configuration(base, newCompartments, dynamicSlots.map(f => f(address)), address, staticValues);
1280
+ let dynamic = dynamicSlots.map(f => f(address));
1281
+ return {
1282
+ configuration: new Configuration(base, newCompartments, dynamic, address, staticValues, facets),
1283
+ values: dynamicValues
1284
+ };
1263
1285
  }
1264
1286
  }
1265
1287
  function flatten(extension, compartments, newCompartments) {
@@ -1311,6 +1333,7 @@ function flatten(extension, compartments, newCompartments) {
1311
1333
  inner(extension, Prec_.default);
1312
1334
  return result.reduce((a, b) => a.concat(b));
1313
1335
  }
1336
+ const Uninitialized = {};
1314
1337
  function ensureAddr(state, addr) {
1315
1338
  if (addr & 1)
1316
1339
  return 2 /* Computed */;
@@ -1836,28 +1859,20 @@ class EditorState {
1836
1859
  /**
1837
1860
  The current selection.
1838
1861
  */
1839
- selection, tr = null) {
1862
+ selection,
1863
+ /**
1864
+ @internal
1865
+ */
1866
+ values, tr = null) {
1840
1867
  this.config = config;
1841
1868
  this.doc = doc;
1842
1869
  this.selection = selection;
1870
+ this.values = values;
1843
1871
  /**
1844
1872
  @internal
1845
1873
  */
1846
1874
  this.applying = null;
1847
1875
  this.status = config.statusTemplate.slice();
1848
- if (tr && tr.startState.config == config) {
1849
- this.values = tr.startState.values.slice();
1850
- }
1851
- else {
1852
- this.values = config.dynamicSlots.map(_ => null);
1853
- // Copy over old values for shared facets/fields if this is a reconfigure
1854
- if (tr)
1855
- for (let id in config.address) {
1856
- let cur = config.address[id], prev = tr.startState.config.address[id];
1857
- if (prev != null && (cur & 1) == 0)
1858
- this.values[cur >> 1] = getAddr(tr.startState, prev);
1859
- }
1860
- }
1861
1876
  this.applying = tr;
1862
1877
  // Fill in the computed state immediately, so that further queries
1863
1878
  // for it made during the update return this state
@@ -1918,7 +1933,17 @@ class EditorState {
1918
1933
  base = asArray(base).concat(effect.value);
1919
1934
  }
1920
1935
  }
1921
- new EditorState(conf || Configuration.resolve(base, compartments, this), tr.newDoc, tr.newSelection, tr);
1936
+ let startValues;
1937
+ if (!conf) {
1938
+ let resolved = Configuration.resolve(base, compartments, this);
1939
+ conf = resolved.configuration;
1940
+ let intermediateState = new EditorState(conf, this.doc, this.selection, resolved.values, null);
1941
+ startValues = intermediateState.values;
1942
+ }
1943
+ else {
1944
+ startValues = tr.startState.values.slice();
1945
+ }
1946
+ new EditorState(conf, tr.newDoc, tr.newSelection, startValues, tr);
1922
1947
  }
1923
1948
  /**
1924
1949
  Create a [transaction spec](https://codemirror.net/6/docs/ref/#state.TransactionSpec) that
@@ -2042,7 +2067,7 @@ class EditorState {
2042
2067
  transactions.
2043
2068
  */
2044
2069
  static create(config = {}) {
2045
- let configuration = Configuration.resolve(config.extensions || [], new Map);
2070
+ let { configuration, values } = Configuration.resolve(config.extensions || [], new Map);
2046
2071
  let doc = config.doc instanceof text.Text ? config.doc
2047
2072
  : text.Text.of((config.doc || "").split(configuration.staticFacet(EditorState.lineSeparator) || DefaultSplit));
2048
2073
  let selection = !config.selection ? EditorSelection.single(0)
@@ -2051,7 +2076,7 @@ class EditorState {
2051
2076
  checkSelection(selection, doc.length);
2052
2077
  if (!configuration.staticFacet(allowMultipleSelections))
2053
2078
  selection = selection.asSingle();
2054
- return new EditorState(configuration, doc, selection);
2079
+ return new EditorState(configuration, doc, selection, values);
2055
2080
  }
2056
2081
  /**
2057
2082
  The size (in columns) of a tab in the document, determined by
@@ -2264,9 +2289,7 @@ combine = {}) {
2264
2289
 
2265
2290
  Object.defineProperty(exports, 'Text', {
2266
2291
  enumerable: true,
2267
- get: function () {
2268
- return text.Text;
2269
- }
2292
+ get: function () { return text.Text; }
2270
2293
  });
2271
2294
  exports.Annotation = Annotation;
2272
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) {
@@ -963,21 +966,23 @@ class FacetProvider {
963
966
  depAddrs.push(addresses[dep.id]);
964
967
  }
965
968
  return (state, tr) => {
966
- if (!tr || tr.reconfigured) {
969
+ let oldVal = state.values[idx];
970
+ if (oldVal === Uninitialized) {
967
971
  state.values[idx] = getter(state);
968
972
  return 1 /* Changed */;
969
973
  }
970
- else {
974
+ if (tr) {
971
975
  let depChanged = (depDoc && tr.docChanged) || (depSel && (tr.docChanged || tr.selection)) ||
972
976
  depAddrs.some(addr => (ensureAddr(state, addr) & 1 /* Changed */) > 0);
973
- if (!depChanged)
974
- return 0;
975
- let newVal = getter(state), oldVal = tr.startState.values[idx];
976
- if (multi ? compareArray(newVal, oldVal, compare) : compare(newVal, oldVal))
977
- return 0;
978
- state.values[idx] = newVal;
979
- return 1 /* Changed */;
977
+ if (depChanged) {
978
+ let newVal = getter(state);
979
+ if (multi ? !compareArray(newVal, oldVal, compare) : !compare(newVal, oldVal)) {
980
+ state.values[idx] = newVal;
981
+ return 1 /* Changed */;
982
+ }
983
+ }
980
984
  }
985
+ return 0;
981
986
  };
982
987
  }
983
988
  }
@@ -995,8 +1000,7 @@ function dynamicFacetSlot(addresses, facet, providers) {
995
1000
  let dynamic = providerAddrs.filter(p => !(p & 1));
996
1001
  let idx = addresses[facet.id] >> 1;
997
1002
  return (state, tr) => {
998
- let oldAddr = !tr ? null : tr.reconfigured ? tr.startState.config.address[facet.id] : idx << 1;
999
- let changed = oldAddr == null;
1003
+ let oldVal = state.values[idx], changed = oldVal === Uninitialized;
1000
1004
  for (let dynAddr of dynamic) {
1001
1005
  if (ensureAddr(state, dynAddr) & 1 /* Changed */)
1002
1006
  changed = true;
@@ -1012,17 +1016,13 @@ function dynamicFacetSlot(addresses, facet, providers) {
1012
1016
  else
1013
1017
  values.push(value);
1014
1018
  }
1015
- let newVal = facet.combine(values);
1016
- if (oldAddr != null && facet.compare(newVal, getAddr(tr.startState, oldAddr)))
1019
+ let value = facet.combine(values);
1020
+ if (oldVal !== Uninitialized && facet.compare(value, oldVal))
1017
1021
  return 0;
1018
- state.values[idx] = newVal;
1022
+ state.values[idx] = value;
1019
1023
  return 1 /* Changed */;
1020
1024
  };
1021
1025
  }
1022
- function maybeIndex(state, id) {
1023
- let found = state.config.address[id];
1024
- return found == null ? null : found >> 1;
1025
- }
1026
1026
  const initField = /*@__PURE__*/Facet.define({ static: true });
1027
1027
  /**
1028
1028
  Fields can store additional information in an editor state, and
@@ -1067,24 +1067,19 @@ class StateField {
1067
1067
  slot(addresses) {
1068
1068
  let idx = addresses[this.id] >> 1;
1069
1069
  return (state, tr) => {
1070
- if (!tr || (tr.reconfigured && maybeIndex(tr.startState, this.id) == null)) {
1070
+ let oldVal = state.values[idx];
1071
+ if (oldVal === Uninitialized) {
1071
1072
  state.values[idx] = this.create(state);
1072
1073
  return 1 /* Changed */;
1073
1074
  }
1074
- let oldVal, changed = 0;
1075
- if (tr.reconfigured) {
1076
- oldVal = tr.startState.values[maybeIndex(tr.startState, this.id)];
1077
- changed = 1 /* Changed */;
1078
- }
1079
- else {
1080
- oldVal = tr.startState.values[idx];
1075
+ if (tr) {
1076
+ let value = this.updateF(oldVal, tr);
1077
+ if (!this.compareF(oldVal, value)) {
1078
+ state.values[idx] = value;
1079
+ return 1 /* Changed */;
1080
+ }
1081
1081
  }
1082
- let value = this.updateF(oldVal, tr);
1083
- if (!changed && !this.compareF(oldVal, value))
1084
- changed = 1 /* Changed */;
1085
- if (changed)
1086
- state.values[idx] = value;
1087
- return changed;
1082
+ return 0;
1088
1083
  };
1089
1084
  }
1090
1085
  /**
@@ -1196,15 +1191,16 @@ class CompartmentInstance {
1196
1191
  }
1197
1192
  }
1198
1193
  class Configuration {
1199
- constructor(base, compartments, dynamicSlots, address, staticValues) {
1194
+ constructor(base, compartments, dynamicSlots, address, staticValues, facets) {
1200
1195
  this.base = base;
1201
1196
  this.compartments = compartments;
1202
1197
  this.dynamicSlots = dynamicSlots;
1203
1198
  this.address = address;
1204
1199
  this.staticValues = staticValues;
1200
+ this.facets = facets;
1205
1201
  this.statusTemplate = [];
1206
1202
  while (this.statusTemplate.length < dynamicSlots.length)
1207
- this.statusTemplate.push(0 /* Uninitialized */);
1203
+ this.statusTemplate.push(0 /* Unresolved */);
1208
1204
  }
1209
1205
  staticFacet(facet) {
1210
1206
  let addr = this.address[facet.id];
@@ -1223,25 +1219,44 @@ class Configuration {
1223
1219
  let address = Object.create(null);
1224
1220
  let staticValues = [];
1225
1221
  let dynamicSlots = [];
1222
+ let dynamicValues = [];
1226
1223
  for (let field of fields) {
1227
1224
  address[field.id] = dynamicSlots.length << 1;
1228
1225
  dynamicSlots.push(a => field.slot(a));
1226
+ dynamicValues.push(oldState && oldState.config.address[field.id] != null ? oldState.field(field) : Uninitialized);
1229
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;
1230
1244
  for (let id in facets) {
1231
1245
  let providers = facets[id], facet = providers[0].facet;
1246
+ let oldProviders = oldFacets && oldFacets[id] || [];
1247
+ let canReuse = sameArray(providers, oldProviders);
1232
1248
  if (providers.every(p => p.type == 0 /* Static */)) {
1233
1249
  address[facet.id] = (staticValues.length << 1) | 1;
1234
- let value = facet.combine(providers.map(p => p.value));
1235
- let oldAddr = oldState ? oldState.config.address[facet.id] : null;
1236
- if (oldAddr != null) {
1237
- let oldVal = getAddr(oldState, oldAddr);
1238
- if (facet.compare(value, oldVal))
1239
- value = oldVal;
1240
- }
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;
1241
1253
  staticValues.push(value);
1242
1254
  }
1243
1255
  else {
1244
1256
  for (let p of providers) {
1257
+ let canReuseThis = p.dependencies.every(canReuseDep);
1258
+ if (!canReuseThis)
1259
+ canReuse = false;
1245
1260
  if (p.type == 0 /* Static */) {
1246
1261
  address[p.id] = (staticValues.length << 1) | 1;
1247
1262
  staticValues.push(p.value);
@@ -1249,13 +1264,20 @@ class Configuration {
1249
1264
  else {
1250
1265
  address[p.id] = dynamicSlots.length << 1;
1251
1266
  dynamicSlots.push(a => p.dynamicSlot(a));
1267
+ let oldAddr = oldState && canReuseThis ? oldState.config.address[p.id] : null;
1268
+ dynamicValues.push(oldAddr != null ? getAddr(oldState, oldAddr) : Uninitialized);
1252
1269
  }
1253
1270
  }
1254
1271
  address[facet.id] = dynamicSlots.length << 1;
1255
1272
  dynamicSlots.push(a => dynamicFacetSlot(a, facet, providers));
1273
+ dynamicValues.push(canReuse || oldProviders.length ? oldState.facet(facet) : Uninitialized);
1256
1274
  }
1257
1275
  }
1258
- return new Configuration(base, newCompartments, dynamicSlots.map(f => f(address)), address, staticValues);
1276
+ let dynamic = dynamicSlots.map(f => f(address));
1277
+ return {
1278
+ configuration: new Configuration(base, newCompartments, dynamic, address, staticValues, facets),
1279
+ values: dynamicValues
1280
+ };
1259
1281
  }
1260
1282
  }
1261
1283
  function flatten(extension, compartments, newCompartments) {
@@ -1307,6 +1329,7 @@ function flatten(extension, compartments, newCompartments) {
1307
1329
  inner(extension, Prec_.default);
1308
1330
  return result.reduce((a, b) => a.concat(b));
1309
1331
  }
1332
+ const Uninitialized = {};
1310
1333
  function ensureAddr(state, addr) {
1311
1334
  if (addr & 1)
1312
1335
  return 2 /* Computed */;
@@ -1831,28 +1854,20 @@ class EditorState {
1831
1854
  /**
1832
1855
  The current selection.
1833
1856
  */
1834
- selection, tr = null) {
1857
+ selection,
1858
+ /**
1859
+ @internal
1860
+ */
1861
+ values, tr = null) {
1835
1862
  this.config = config;
1836
1863
  this.doc = doc;
1837
1864
  this.selection = selection;
1865
+ this.values = values;
1838
1866
  /**
1839
1867
  @internal
1840
1868
  */
1841
1869
  this.applying = null;
1842
1870
  this.status = config.statusTemplate.slice();
1843
- if (tr && tr.startState.config == config) {
1844
- this.values = tr.startState.values.slice();
1845
- }
1846
- else {
1847
- this.values = config.dynamicSlots.map(_ => null);
1848
- // Copy over old values for shared facets/fields if this is a reconfigure
1849
- if (tr)
1850
- for (let id in config.address) {
1851
- let cur = config.address[id], prev = tr.startState.config.address[id];
1852
- if (prev != null && (cur & 1) == 0)
1853
- this.values[cur >> 1] = getAddr(tr.startState, prev);
1854
- }
1855
- }
1856
1871
  this.applying = tr;
1857
1872
  // Fill in the computed state immediately, so that further queries
1858
1873
  // for it made during the update return this state
@@ -1913,7 +1928,17 @@ class EditorState {
1913
1928
  base = asArray(base).concat(effect.value);
1914
1929
  }
1915
1930
  }
1916
- new EditorState(conf || Configuration.resolve(base, compartments, this), tr.newDoc, tr.newSelection, tr);
1931
+ let startValues;
1932
+ if (!conf) {
1933
+ let resolved = Configuration.resolve(base, compartments, this);
1934
+ conf = resolved.configuration;
1935
+ let intermediateState = new EditorState(conf, this.doc, this.selection, resolved.values, null);
1936
+ startValues = intermediateState.values;
1937
+ }
1938
+ else {
1939
+ startValues = tr.startState.values.slice();
1940
+ }
1941
+ new EditorState(conf, tr.newDoc, tr.newSelection, startValues, tr);
1917
1942
  }
1918
1943
  /**
1919
1944
  Create a [transaction spec](https://codemirror.net/6/docs/ref/#state.TransactionSpec) that
@@ -2037,7 +2062,7 @@ class EditorState {
2037
2062
  transactions.
2038
2063
  */
2039
2064
  static create(config = {}) {
2040
- let configuration = Configuration.resolve(config.extensions || [], new Map);
2065
+ let { configuration, values } = Configuration.resolve(config.extensions || [], new Map);
2041
2066
  let doc = config.doc instanceof Text ? config.doc
2042
2067
  : Text.of((config.doc || "").split(configuration.staticFacet(EditorState.lineSeparator) || DefaultSplit));
2043
2068
  let selection = !config.selection ? EditorSelection.single(0)
@@ -2046,7 +2071,7 @@ class EditorState {
2046
2071
  checkSelection(selection, doc.length);
2047
2072
  if (!configuration.staticFacet(allowMultipleSelections))
2048
2073
  selection = selection.asSingle();
2049
- return new EditorState(configuration, doc, selection);
2074
+ return new EditorState(configuration, doc, selection, values);
2050
2075
  }
2051
2076
  /**
2052
2077
  The size (in columns) of a tab in the document, determined by
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/state",
3
- "version": "0.19.3",
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",