prosemirror-view 1.31.6 → 1.31.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,13 @@
1
+ ## 1.31.7 (2023-07-28)
2
+
3
+ ### Bug fixes
4
+
5
+ Fix a bug where, when a compositionend event was received before the composition's final changes were processed, the resulting transaction didn't have its composition metadata set.
6
+
7
+ Fix an issue that caused cursor motion to stop at uneditable nodes that aren't widget decorations.
8
+
9
+ When scrolling an element higher than the viewport into view, make sure its top is visible.
10
+
1
11
  ## 1.31.6 (2023-07-14)
2
12
 
3
13
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -216,7 +216,7 @@ function scrollRectIntoView(view, rect, startDOM) {
216
216
  var bounding = atTop ? windowRect(doc) : clientRect(elt);
217
217
  var moveX = 0,
218
218
  moveY = 0;
219
- if (rect.top < bounding.top + getSide(scrollThreshold, "top")) moveY = -(bounding.top - rect.top + getSide(scrollMargin, "top"));else if (rect.bottom > bounding.bottom - getSide(scrollThreshold, "bottom")) moveY = rect.bottom - bounding.bottom + getSide(scrollMargin, "bottom");
219
+ if (rect.top < bounding.top + getSide(scrollThreshold, "top")) moveY = -(bounding.top - rect.top + getSide(scrollMargin, "top"));else if (rect.bottom > bounding.bottom - getSide(scrollThreshold, "bottom")) moveY = rect.bottom - rect.top > bounding.bottom - bounding.top ? rect.top + getSide(scrollMargin, "top") - bounding.top : rect.bottom - bounding.bottom + getSide(scrollMargin, "bottom");
220
220
  if (rect.left < bounding.left + getSide(scrollThreshold, "left")) moveX = -(bounding.left - rect.left + getSide(scrollMargin, "left"));else if (rect.right > bounding.right - getSide(scrollThreshold, "right")) moveX = rect.right - bounding.right + getSide(scrollMargin, "right");
221
221
 
222
222
  if (moveX || moveY) {
@@ -2774,6 +2774,7 @@ function nodeLen(node) {
2774
2774
  }
2775
2775
 
2776
2776
  function isIgnorable(dom) {
2777
+ if (dom.contentEditable == "false") return true;
2777
2778
  var desc = dom.pmViewDesc;
2778
2779
  return desc && desc.size == 0 && (dom.nextSibling || dom.nodeName != "BR");
2779
2780
  }
@@ -2880,7 +2881,45 @@ function isBlockNode(dom) {
2880
2881
  return desc && desc.node && desc.node.isBlock;
2881
2882
  }
2882
2883
 
2884
+ function textNodeAfter(node, offset) {
2885
+ while (node && offset == node.childNodes.length && !hasBlockDesc(node)) {
2886
+ offset = domIndex(node) + 1;
2887
+ node = node.parentNode;
2888
+ }
2889
+
2890
+ while (node && offset < node.childNodes.length) {
2891
+ node = node.childNodes[offset];
2892
+ if (node.nodeType == 3) return node;
2893
+ offset = 0;
2894
+ }
2895
+ }
2896
+
2897
+ function textNodeBefore(node, offset) {
2898
+ while (node && !offset && !hasBlockDesc(node)) {
2899
+ offset = domIndex(node);
2900
+ node = node.parentNode;
2901
+ }
2902
+
2903
+ while (node && offset) {
2904
+ node = node.childNodes[offset - 1];
2905
+ if (node.nodeType == 3) return node;
2906
+ offset = node.childNodes.length;
2907
+ }
2908
+ }
2909
+
2883
2910
  function setSelFocus(view, node, offset) {
2911
+ if (node.nodeType != 3) {
2912
+ var before, after;
2913
+
2914
+ if (after = textNodeAfter(node, offset)) {
2915
+ node = after;
2916
+ offset = 0;
2917
+ } else if (before = textNodeBefore(node, offset)) {
2918
+ node = before;
2919
+ offset = before.nodeValue.length;
2920
+ }
2921
+ }
2922
+
2884
2923
  var sel = view.domSelection();
2885
2924
 
2886
2925
  if (selectionCollapsed(sel)) {
@@ -3349,6 +3388,7 @@ var InputState = _createClass(function InputState() {
3349
3388
  this.compositionNodes = [];
3350
3389
  this.compositionEndedAt = -2e8;
3351
3390
  this.compositionID = 1;
3391
+ this.compositionPendingChanges = 0;
3352
3392
  this.domChangeCount = 0;
3353
3393
  this.eventHandlers = Object.create(null);
3354
3394
  this.hideSelectionGuard = null;
@@ -3812,6 +3852,10 @@ editHandlers.compositionend = function (view, event) {
3812
3852
  if (view.composing) {
3813
3853
  view.input.composing = false;
3814
3854
  view.input.compositionEndedAt = event.timeStamp;
3855
+ view.input.compositionPendingChanges = view.domObserver.pendingRecords().length ? view.input.compositionID : 0;
3856
+ if (view.input.compositionPendingChanges) Promise.resolve().then(function () {
3857
+ return view.domObserver.flush();
3858
+ });
3815
3859
  view.input.compositionID++;
3816
3860
  scheduleComposeEnd(view, 20);
3817
3861
  }
@@ -5018,18 +5062,34 @@ var DOMObserver = function () {
5018
5062
  return true;
5019
5063
  }
5020
5064
  }
5065
+ }, {
5066
+ key: "pendingRecords",
5067
+ value: function pendingRecords() {
5068
+ if (this.observer) {
5069
+ var _iterator2 = _createForOfIteratorHelper(this.observer.takeRecords()),
5070
+ _step2;
5071
+
5072
+ try {
5073
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
5074
+ var mut = _step2.value;
5075
+ this.queue.push(mut);
5076
+ }
5077
+ } catch (err) {
5078
+ _iterator2.e(err);
5079
+ } finally {
5080
+ _iterator2.f();
5081
+ }
5082
+ }
5083
+
5084
+ return this.queue;
5085
+ }
5021
5086
  }, {
5022
5087
  key: "flush",
5023
5088
  value: function flush() {
5024
5089
  var view = this.view;
5025
5090
  if (!view.docView || this.flushingSoon > -1) return;
5026
- var mutations = this.observer ? this.observer.takeRecords() : [];
5027
-
5028
- if (this.queue.length) {
5029
- mutations = this.queue.concat(mutations);
5030
- this.queue.length = 0;
5031
- }
5032
-
5091
+ var mutations = this.pendingRecords();
5092
+ if (mutations.length) this.queue = [];
5033
5093
  var sel = view.domSelectionRange();
5034
5094
  var newSel = !this.suppressingSelectionUpdates && !this.currentSelection.eq(sel) && hasFocusAndSelection(view) && !this.ignoreSelectionChange(sel);
5035
5095
  var from = -1,
@@ -5284,6 +5344,9 @@ function ruleFromNode(dom) {
5284
5344
  var isInline = /^(a|abbr|acronym|b|bd[io]|big|br|button|cite|code|data(list)?|del|dfn|em|i|ins|kbd|label|map|mark|meter|output|q|ruby|s|samp|small|span|strong|su[bp]|time|u|tt|var)$/i;
5285
5345
 
5286
5346
  function readDOMChange(view, from, to, typeOver, addedNodes) {
5347
+ var compositionID = view.input.compositionPendingChanges || (view.composing ? view.input.compositionID : 0);
5348
+ view.input.compositionPendingChanges = 0;
5349
+
5287
5350
  if (from < 0) {
5288
5351
  var origin = view.input.lastSelectionTime > Date.now() - 50 ? view.input.lastSelectionOrigin : null;
5289
5352
  var newSel = selectionFromDOM(view, origin);
@@ -5296,7 +5359,7 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
5296
5359
  var _tr = view.state.tr.setSelection(newSel);
5297
5360
 
5298
5361
  if (origin == "pointer") _tr.setMeta("pointer", true);else if (origin == "key") _tr.scrollIntoView();
5299
- if (view.composing) _tr.setMeta("composition", view.input.compositionID);
5362
+ if (compositionID) _tr.setMeta("composition", compositionID);
5300
5363
  view.dispatch(_tr);
5301
5364
  }
5302
5365
 
@@ -5347,7 +5410,7 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
5347
5410
  if (_sel && !_sel.eq(view.state.selection)) {
5348
5411
  var _tr2 = view.state.tr.setSelection(_sel);
5349
5412
 
5350
- if (view.composing) _tr2.setMeta("composition", view.input.compositionID);
5413
+ if (compositionID) _tr2.setMeta("composition", compositionID);
5351
5414
  view.dispatch(_tr2);
5352
5415
  }
5353
5416
  }
@@ -5451,7 +5514,7 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
5451
5514
  }
5452
5515
 
5453
5516
  if (storedMarks) tr.ensureMarks(storedMarks);
5454
- if (view.composing) tr.setMeta("composition", view.input.compositionID);
5517
+ if (compositionID) tr.setMeta("composition", compositionID);
5455
5518
  view.dispatch(tr.scrollIntoView());
5456
5519
  }
5457
5520
 
package/dist/index.js CHANGED
@@ -163,7 +163,9 @@ function scrollRectIntoView(view, rect, startDOM) {
163
163
  if (rect.top < bounding.top + getSide(scrollThreshold, "top"))
164
164
  moveY = -(bounding.top - rect.top + getSide(scrollMargin, "top"));
165
165
  else if (rect.bottom > bounding.bottom - getSide(scrollThreshold, "bottom"))
166
- moveY = rect.bottom - bounding.bottom + getSide(scrollMargin, "bottom");
166
+ moveY = rect.bottom - rect.top > bounding.bottom - bounding.top
167
+ ? rect.top + getSide(scrollMargin, "top") - bounding.top
168
+ : rect.bottom - bounding.bottom + getSide(scrollMargin, "bottom");
167
169
  if (rect.left < bounding.left + getSide(scrollThreshold, "left"))
168
170
  moveX = -(bounding.left - rect.left + getSide(scrollMargin, "left"));
169
171
  else if (rect.right > bounding.right - getSide(scrollThreshold, "right"))
@@ -2354,6 +2356,8 @@ function nodeLen(node) {
2354
2356
  return node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length;
2355
2357
  }
2356
2358
  function isIgnorable(dom) {
2359
+ if (dom.contentEditable == "false")
2360
+ return true;
2357
2361
  let desc = dom.pmViewDesc;
2358
2362
  return desc && desc.size == 0 && (dom.nextSibling || dom.nodeName != "BR");
2359
2363
  }
@@ -2470,7 +2474,42 @@ function isBlockNode(dom) {
2470
2474
  let desc = dom.pmViewDesc;
2471
2475
  return desc && desc.node && desc.node.isBlock;
2472
2476
  }
2477
+ function textNodeAfter(node, offset) {
2478
+ while (node && offset == node.childNodes.length && !hasBlockDesc(node)) {
2479
+ offset = domIndex(node) + 1;
2480
+ node = node.parentNode;
2481
+ }
2482
+ while (node && offset < node.childNodes.length) {
2483
+ node = node.childNodes[offset];
2484
+ if (node.nodeType == 3)
2485
+ return node;
2486
+ offset = 0;
2487
+ }
2488
+ }
2489
+ function textNodeBefore(node, offset) {
2490
+ while (node && !offset && !hasBlockDesc(node)) {
2491
+ offset = domIndex(node);
2492
+ node = node.parentNode;
2493
+ }
2494
+ while (node && offset) {
2495
+ node = node.childNodes[offset - 1];
2496
+ if (node.nodeType == 3)
2497
+ return node;
2498
+ offset = node.childNodes.length;
2499
+ }
2500
+ }
2473
2501
  function setSelFocus(view, node, offset) {
2502
+ if (node.nodeType != 3) {
2503
+ let before, after;
2504
+ if (after = textNodeAfter(node, offset)) {
2505
+ node = after;
2506
+ offset = 0;
2507
+ }
2508
+ else if (before = textNodeBefore(node, offset)) {
2509
+ node = before;
2510
+ offset = before.nodeValue.length;
2511
+ }
2512
+ }
2474
2513
  let sel = view.domSelection();
2475
2514
  if (selectionCollapsed(sel)) {
2476
2515
  let range = document.createRange();
@@ -2899,6 +2938,8 @@ class InputState {
2899
2938
  this.compositionNodes = [];
2900
2939
  this.compositionEndedAt = -2e8;
2901
2940
  this.compositionID = 1;
2941
+ // Set to a composition ID when there are pending changes at compositionend
2942
+ this.compositionPendingChanges = 0;
2902
2943
  this.domChangeCount = 0;
2903
2944
  this.eventHandlers = Object.create(null);
2904
2945
  this.hideSelectionGuard = null;
@@ -3328,6 +3369,9 @@ editHandlers.compositionend = (view, event) => {
3328
3369
  if (view.composing) {
3329
3370
  view.input.composing = false;
3330
3371
  view.input.compositionEndedAt = event.timeStamp;
3372
+ view.input.compositionPendingChanges = view.domObserver.pendingRecords().length ? view.input.compositionID : 0;
3373
+ if (view.input.compositionPendingChanges)
3374
+ Promise.resolve().then(() => view.domObserver.flush());
3331
3375
  view.input.compositionID++;
3332
3376
  scheduleComposeEnd(view, 20);
3333
3377
  }
@@ -4432,15 +4476,19 @@ class DOMObserver {
4432
4476
  return true;
4433
4477
  }
4434
4478
  }
4479
+ pendingRecords() {
4480
+ if (this.observer)
4481
+ for (let mut of this.observer.takeRecords())
4482
+ this.queue.push(mut);
4483
+ return this.queue;
4484
+ }
4435
4485
  flush() {
4436
4486
  let { view } = this;
4437
4487
  if (!view.docView || this.flushingSoon > -1)
4438
4488
  return;
4439
- let mutations = this.observer ? this.observer.takeRecords() : [];
4440
- if (this.queue.length) {
4441
- mutations = this.queue.concat(mutations);
4442
- this.queue.length = 0;
4443
- }
4489
+ let mutations = this.pendingRecords();
4490
+ if (mutations.length)
4491
+ this.queue = [];
4444
4492
  let sel = view.domSelectionRange();
4445
4493
  let newSel = !this.suppressingSelectionUpdates && !this.currentSelection.eq(sel) && hasFocusAndSelection(view) && !this.ignoreSelectionChange(sel);
4446
4494
  let from = -1, to = -1, typeOver = false, added = [];
@@ -4661,6 +4709,8 @@ function ruleFromNode(dom) {
4661
4709
  }
4662
4710
  const isInline = /^(a|abbr|acronym|b|bd[io]|big|br|button|cite|code|data(list)?|del|dfn|em|i|ins|kbd|label|map|mark|meter|output|q|ruby|s|samp|small|span|strong|su[bp]|time|u|tt|var)$/i;
4663
4711
  function readDOMChange(view, from, to, typeOver, addedNodes) {
4712
+ let compositionID = view.input.compositionPendingChanges || (view.composing ? view.input.compositionID : 0);
4713
+ view.input.compositionPendingChanges = 0;
4664
4714
  if (from < 0) {
4665
4715
  let origin = view.input.lastSelectionTime > Date.now() - 50 ? view.input.lastSelectionOrigin : null;
4666
4716
  let newSel = selectionFromDOM(view, origin);
@@ -4674,8 +4724,8 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
4674
4724
  tr.setMeta("pointer", true);
4675
4725
  else if (origin == "key")
4676
4726
  tr.scrollIntoView();
4677
- if (view.composing)
4678
- tr.setMeta("composition", view.input.compositionID);
4727
+ if (compositionID)
4728
+ tr.setMeta("composition", compositionID);
4679
4729
  view.dispatch(tr);
4680
4730
  }
4681
4731
  return;
@@ -4716,8 +4766,8 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
4716
4766
  let sel = resolveSelection(view, view.state.doc, parse.sel);
4717
4767
  if (sel && !sel.eq(view.state.selection)) {
4718
4768
  let tr = view.state.tr.setSelection(sel);
4719
- if (view.composing)
4720
- tr.setMeta("composition", view.input.compositionID);
4769
+ if (compositionID)
4770
+ tr.setMeta("composition", compositionID);
4721
4771
  view.dispatch(tr);
4722
4772
  }
4723
4773
  }
@@ -4850,8 +4900,8 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
4850
4900
  }
4851
4901
  if (storedMarks)
4852
4902
  tr.ensureMarks(storedMarks);
4853
- if (view.composing)
4854
- tr.setMeta("composition", view.input.compositionID);
4903
+ if (compositionID)
4904
+ tr.setMeta("composition", compositionID);
4855
4905
  view.dispatch(tr.scrollIntoView());
4856
4906
  }
4857
4907
  function resolveSelection(view, doc, parsedSel) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prosemirror-view",
3
- "version": "1.31.6",
3
+ "version": "1.31.7",
4
4
  "description": "ProseMirror's view component",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -1,7 +1,7 @@
1
1
  import {Selection, NodeSelection, TextSelection, AllSelection, EditorState} from "prosemirror-state"
2
2
  import {EditorView} from "./index"
3
3
  import * as browser from "./browser"
4
- import {domIndex, selectionCollapsed} from "./dom"
4
+ import {domIndex, selectionCollapsed, hasBlockDesc} from "./dom"
5
5
  import {selectionToDOM} from "./selection"
6
6
 
7
7
  function moveSelectionBlock(state: EditorState, dir: number) {
@@ -55,6 +55,7 @@ function nodeLen(node: Node) {
55
55
  }
56
56
 
57
57
  function isIgnorable(dom: Node) {
58
+ if ((dom as HTMLElement).contentEditable == "false") return true
58
59
  let desc = dom.pmViewDesc
59
60
  return desc && desc.size == 0 && (dom.nextSibling || dom.nodeName != "BR")
60
61
  }
@@ -156,7 +157,42 @@ function isBlockNode(dom: Node) {
156
157
  return desc && desc.node && desc.node.isBlock
157
158
  }
158
159
 
160
+ function textNodeAfter(node: Node | null, offset: number): Text | undefined {
161
+ while (node && offset == node.childNodes.length && !hasBlockDesc(node)) {
162
+ offset = domIndex(node) + 1
163
+ node = node.parentNode
164
+ }
165
+ while (node && offset < node.childNodes.length) {
166
+ node = node.childNodes[offset]
167
+ if (node.nodeType == 3) return node as Text
168
+ offset = 0
169
+ }
170
+ }
171
+
172
+ function textNodeBefore(node: Node | null, offset: number): Text | undefined {
173
+ while (node && !offset && !hasBlockDesc(node)) {
174
+ offset = domIndex(node)
175
+ node = node.parentNode
176
+ }
177
+ while (node && offset) {
178
+ node = node.childNodes[offset - 1]
179
+ if (node.nodeType == 3) return node as Text
180
+ offset = node.childNodes.length
181
+ }
182
+ }
183
+
159
184
  function setSelFocus(view: EditorView, node: Node, offset: number) {
185
+ if (node.nodeType != 3) {
186
+ let before, after
187
+ if (after = textNodeAfter(node, offset)) {
188
+ node = after
189
+ offset = 0
190
+ } else if (before = textNodeBefore(node, offset)) {
191
+ node = before
192
+ offset = before.nodeValue!.length
193
+ }
194
+ }
195
+
160
196
  let sel = view.domSelection()
161
197
  if (selectionCollapsed(sel)) {
162
198
  let range = document.createRange()
package/src/dom.ts CHANGED
@@ -74,7 +74,7 @@ export function isOnEdge(node: Node, offset: number, parent: Node) {
74
74
  }
75
75
  }
76
76
 
77
- function hasBlockDesc(dom: Node) {
77
+ export function hasBlockDesc(dom: Node) {
78
78
  let desc
79
79
  for (let cur: Node | null = dom; cur; cur = cur.parentNode) if (desc = cur.pmViewDesc) break
80
80
  return desc && desc.node && desc.node.isBlock && (desc.dom == dom || desc.contentDOM == dom)
package/src/domchange.ts CHANGED
@@ -79,6 +79,9 @@ function ruleFromNode(dom: DOMNode): ParseRule | null {
79
79
  const isInline = /^(a|abbr|acronym|b|bd[io]|big|br|button|cite|code|data(list)?|del|dfn|em|i|ins|kbd|label|map|mark|meter|output|q|ruby|s|samp|small|span|strong|su[bp]|time|u|tt|var)$/i
80
80
 
81
81
  export function readDOMChange(view: EditorView, from: number, to: number, typeOver: boolean, addedNodes: readonly DOMNode[]) {
82
+ let compositionID = view.input.compositionPendingChanges || (view.composing ? view.input.compositionID : 0)
83
+ view.input.compositionPendingChanges = 0
84
+
82
85
  if (from < 0) {
83
86
  let origin = view.input.lastSelectionTime > Date.now() - 50 ? view.input.lastSelectionOrigin : null
84
87
  let newSel = selectionFromDOM(view, origin)
@@ -90,7 +93,7 @@ export function readDOMChange(view: EditorView, from: number, to: number, typeOv
90
93
  let tr = view.state.tr.setSelection(newSel)
91
94
  if (origin == "pointer") tr.setMeta("pointer", true)
92
95
  else if (origin == "key") tr.scrollIntoView()
93
- if (view.composing) tr.setMeta("composition", view.input.compositionID)
96
+ if (compositionID) tr.setMeta("composition", compositionID)
94
97
  view.dispatch(tr)
95
98
  }
96
99
  return
@@ -133,7 +136,7 @@ export function readDOMChange(view: EditorView, from: number, to: number, typeOv
133
136
  let sel = resolveSelection(view, view.state.doc, parse.sel)
134
137
  if (sel && !sel.eq(view.state.selection)) {
135
138
  let tr = view.state.tr.setSelection(sel)
136
- if (view.composing) tr.setMeta("composition", view.input.compositionID)
139
+ if (compositionID) tr.setMeta("composition", compositionID)
137
140
  view.dispatch(tr)
138
141
  }
139
142
  }
@@ -268,7 +271,7 @@ export function readDOMChange(view: EditorView, from: number, to: number, typeOv
268
271
  tr.setSelection(sel)
269
272
  }
270
273
  if (storedMarks) tr.ensureMarks(storedMarks)
271
- if (view.composing) tr.setMeta("composition", view.input.compositionID)
274
+ if (compositionID) tr.setMeta("composition", compositionID)
272
275
  view.dispatch(tr.scrollIntoView())
273
276
  }
274
277
 
package/src/domcoords.ts CHANGED
@@ -37,7 +37,9 @@ export function scrollRectIntoView(view: EditorView, rect: Rect, startDOM: Node)
37
37
  if (rect.top < bounding.top + getSide(scrollThreshold, "top"))
38
38
  moveY = -(bounding.top - rect.top + getSide(scrollMargin, "top"))
39
39
  else if (rect.bottom > bounding.bottom - getSide(scrollThreshold, "bottom"))
40
- moveY = rect.bottom - bounding.bottom + getSide(scrollMargin, "bottom")
40
+ moveY = rect.bottom - rect.top > bounding.bottom - bounding.top
41
+ ? rect.top + getSide(scrollMargin, "top") - bounding.top
42
+ : rect.bottom - bounding.bottom + getSide(scrollMargin, "bottom")
41
43
  if (rect.left < bounding.left + getSide(scrollThreshold, "left"))
42
44
  moveX = -(bounding.left - rect.left + getSide(scrollMargin, "left"))
43
45
  else if (rect.right > bounding.right - getSide(scrollThreshold, "right"))
@@ -157,14 +157,16 @@ export class DOMObserver {
157
157
  }
158
158
  }
159
159
 
160
+ pendingRecords() {
161
+ if (this.observer) for (let mut of this.observer.takeRecords()) this.queue.push(mut)
162
+ return this.queue
163
+ }
164
+
160
165
  flush() {
161
166
  let {view} = this
162
167
  if (!view.docView || this.flushingSoon > -1) return
163
- let mutations = this.observer ? this.observer.takeRecords() : []
164
- if (this.queue.length) {
165
- mutations = this.queue.concat(mutations)
166
- this.queue.length = 0
167
- }
168
+ let mutations = this.pendingRecords()
169
+ if (mutations.length) this.queue = []
168
170
 
169
171
  let sel = view.domSelectionRange()
170
172
  let newSel = !this.suppressingSelectionUpdates && !this.currentSelection.eq(sel) && hasFocusAndSelection(view) && !this.ignoreSelectionChange(sel)
package/src/input.ts CHANGED
@@ -34,6 +34,8 @@ export class InputState {
34
34
  compositionNodes: ViewDesc[] = []
35
35
  compositionEndedAt = -2e8
36
36
  compositionID = 1
37
+ // Set to a composition ID when there are pending changes at compositionend
38
+ compositionPendingChanges = 0
37
39
  domChangeCount = 0
38
40
  eventHandlers: {[event: string]: (event: Event) => void} = Object.create(null)
39
41
  hideSelectionGuard: (() => void) | null = null
@@ -487,6 +489,8 @@ editHandlers.compositionend = (view, event) => {
487
489
  if (view.composing) {
488
490
  view.input.composing = false
489
491
  view.input.compositionEndedAt = event.timeStamp
492
+ view.input.compositionPendingChanges = view.domObserver.pendingRecords().length ? view.input.compositionID : 0
493
+ if (view.input.compositionPendingChanges) Promise.resolve().then(() => view.domObserver.flush())
490
494
  view.input.compositionID++
491
495
  scheduleComposeEnd(view, 20)
492
496
  }