@bablr/bablr-vm 0.21.0 → 0.22.0

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/lib/context.js CHANGED
@@ -7,6 +7,7 @@ import { PathFacade as Path } from '@bablr/agast-vm';
7
7
  import { sourceTextFor } from '@bablr/agast-helpers/stream';
8
8
  import { streamFromTree } from '@bablr/agast-helpers/tree';
9
9
  import { allTagsFor } from '@bablr/agast-helpers/path-facade';
10
+ import { buildEmbeddedNode } from '@bablr/agast-vm-helpers/builders';
10
11
 
11
12
  export const ContextFacade = class BABLRContextFacade {
12
13
  constructor(actual) {
@@ -39,16 +40,16 @@ export const ContextFacade = class BABLRContextFacade {
39
40
  fragmentStream = streamFromTree(node);
40
41
  } else if (nodeStates.has(node)) {
41
42
  let state = nodeStates.get(node);
42
- let { childrenIndexRange } = state;
43
+ let { tagsIndexRange } = state;
43
44
  let path = Path.from(state.fragmentNode);
44
45
 
45
- if (!childrenIndexRange) {
46
+ if (!tagsIndexRange) {
46
47
  let nodePath = Path.from(state.node);
47
- childrenIndexRange = [nodePath.tagPathAt(0), nodePath.tagPathAt(-1)];
48
+ tagsIndexRange = [0, nodePath.tagPathAt(-1).tagsIndex];
48
49
  }
49
50
 
50
51
  fragmentStream = allTagsFor(
51
- [path.tagPathAt(childrenIndexRange[0]), path.tagPathAt(childrenIndexRange[1])],
52
+ [path.tagPathAt(tagsIndexRange[0], 0), path.tagPathAt(tagsIndexRange[1], -1)],
52
53
  { unshift: true },
53
54
  );
54
55
  } else {
package/lib/evaluate.js CHANGED
@@ -18,7 +18,6 @@ import {
18
18
  BindingTag,
19
19
  LiteralTag,
20
20
  ReferenceTag,
21
- DoctypeTag,
22
21
  NullTag,
23
22
  ShiftTag,
24
23
  InitializerTag,
@@ -70,7 +69,6 @@ function* __bablr(ctx, rootSource, strategy, options) {
70
69
  let m = null;
71
70
  let language = null;
72
71
  let finishedMatch = null;
73
- let doctype = null;
74
72
 
75
73
  let co = new Coroutine(getStreamIterator(strategy(facades.get(ctx))));
76
74
 
@@ -115,7 +113,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
115
113
  case 'match': {
116
114
  let { arguments: { 0: pattern } = [] } = instr;
117
115
 
118
- let result = s.guardedMatch(pattern);
116
+ let result = s.guardedMatch(pattern, pattern.attributes);
119
117
 
120
118
  if (result instanceof Promise) {
121
119
  result = yield result;
@@ -145,33 +143,28 @@ function* __bablr(ctx, rootSource, strategy, options) {
145
143
  }
146
144
 
147
145
  switch (tag.type) {
148
- case DoctypeTag: {
149
- doctype = tag;
150
- break;
151
- }
152
-
153
146
  case ReferenceTag: {
154
147
  if (s.node.type && tag.value.type === '.') throw new Error();
155
- if (s.held && s.node.children.at(2)?.type === InitializerTag) {
156
- if (!referencesAreEqual(s.node.children.at(1), tag) || s.node.children.size > 3) {
148
+ if (s.held && s.node.tags.at(2)?.type === InitializerTag) {
149
+ if (!referencesAreEqual(s.node.tags.at(1).value, tag.value) || s.node.tags.size > 3) {
157
150
  throw new Error();
158
151
  }
159
152
  }
160
153
 
161
154
  m.advance(tag, s);
162
155
 
163
- s.referenceTagPath = TagPath.fromNode(s.node, -1);
156
+ s.referenceTagPath = TagPath.from(s.path, -1, 0);
164
157
  if (s.referenceTagPath.tag.type === BindingTag) throw new Error();
165
158
  break;
166
159
  }
167
160
 
168
161
  case ShiftTag: {
169
162
  let { index, height } = tag.value;
170
- let refTag = s.node.children.at(-3);
163
+ let refTag = s.node.tags.at(-1, 0);
171
164
  let lastShiftTag = refTag;
172
165
 
173
166
  if (refTag.type === ShiftTag) {
174
- refTag = s.node.children.at(-3 - refTag.value.index * 3);
167
+ refTag = s.node.tags.at(-refTag.value.index - 1, 0);
175
168
  }
176
169
 
177
170
  if (refTag.type !== ReferenceTag) throw new Error();
@@ -191,7 +184,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
191
184
  );
192
185
 
193
186
  m.advance(tag, s);
194
- s.referenceTagPath = TagPath.fromNode(s.node, -1);
187
+ s.referenceTagPath = TagPath.from(s.path, 0);
195
188
  break;
196
189
  }
197
190
 
@@ -210,6 +203,8 @@ function* __bablr(ctx, rootSource, strategy, options) {
210
203
  }
211
204
 
212
205
  case OpenNodeTag: {
206
+ let { literalValue, selfClosing } = tag.value;
207
+
213
208
  s.depths.path++;
214
209
  s.depths.nodeShift = 0;
215
210
 
@@ -219,18 +214,58 @@ function* __bablr(ctx, rootSource, strategy, options) {
219
214
 
220
215
  s.agast = m.agast;
221
216
 
222
- if (s.depths.path === 0) {
223
- m.advance(doctype);
224
- }
225
-
226
217
  m.advance(tag, s);
218
+ const refPath = m.referencePath;
219
+
220
+ if (selfClosing) {
221
+ if (literalValue) {
222
+ let result;
223
+ if (
224
+ s.resultPath.tag.type === OpenNodeTag &&
225
+ s.resultPath.tag.value.attributes.balancer &&
226
+ s.balanced.value?.attributes.balanced === literalValue
227
+ ) {
228
+ result = s.match(literalValue, tag.value.attributes);
229
+ } else {
230
+ result = s.guardedMatch(literalValue, tag.value.attributes);
231
+ }
232
+
233
+ if (result instanceof Promise) {
234
+ result = yield result;
235
+ }
236
+
237
+ if (result) {
238
+ let sourceStep = s.source.advance(getSourceLength(result));
239
+
240
+ if (sourceStep instanceof Promise) {
241
+ sourceStep = yield sourceStep;
242
+ }
243
+ } else {
244
+ throw new Error('Failed to advance literal');
245
+ }
246
+ }
247
+
248
+ s.depths.path--;
249
+ s.depths.nodeShift = 0;
250
+ s.depths.shift = 0;
251
+
252
+ s.agast = m.agastFragment;
253
+ s.held = Object.freeze({
254
+ reference: refPath.tag.value,
255
+ binding: null,
256
+ node: s.resultPath.node,
257
+ });
258
+ }
227
259
 
228
260
  if (s.depths.path === 0) {
229
- m.setRangePreviousIndex(1);
261
+ m.setRangePreviousIndex(0);
230
262
  }
231
263
 
232
264
  if (tag.value.type) {
233
- updateSpans(m, s.node, 'open');
265
+ updateSpans(m, s.resultPath.node, 'open');
266
+ }
267
+ if (literalValue) {
268
+ updateSpans(m, s.resultPath.node, 'close');
234
269
  }
235
270
 
236
271
  break;
@@ -243,12 +278,12 @@ function* __bablr(ctx, rootSource, strategy, options) {
243
278
  s.depths.nodeShift = 0;
244
279
  s.depths.shift = 0;
245
280
 
246
- if (m.rangeInitial.tag.type === ShiftTag) {
281
+ if (m.rangeInitial?.tag.type === ShiftTag) {
247
282
  s.depths.nodeShift = m.rangeInitial.tag.value.index;
248
283
  s.depths.shift = m.rangeInitial.tag.value.height;
249
284
  }
250
285
 
251
- if (node.children.at(0).value.type) {
286
+ if (node.tags.at(0).value.type) {
252
287
  const refPath = m.referencePath;
253
288
 
254
289
  m.advance(tag, s);
@@ -260,43 +295,32 @@ function* __bablr(ctx, rootSource, strategy, options) {
260
295
  let tagPath = PathFacade.from(node).tagPathAt(0);
261
296
 
262
297
  while (tagPath) {
263
- let vmReturn = null;
264
298
  if (tagPath.tag.type === GapTag) {
265
- break;
299
+ throw new Error();
266
300
  }
267
301
  if (tagPath.tag.type === OpenNodeTag) {
268
- let { flags, type, attributes } = tagPath.tag.value;
269
-
270
- if (tagPath.node.flags.hasGap) {
271
- vmReturn = escapeVm.next(
272
- buildOpenNodeTag(getFlagsWithGap(flags, false), type, attributes),
273
- );
274
- } else {
275
- vmReturn = escapeVm.next(
276
- buildChild(
277
- sym.Property,
278
- buildProperty(
279
- tagPath.path.reference.value,
280
- tagPath.path.referenceTagPath.nextSibling.tag.value,
281
- tagPath.node.node,
282
- ),
283
- ),
284
- );
285
- tagPath = tagPath.path.tagPathAt(-1).nextUnshifted;
286
- continue;
287
- }
302
+ let { flags, type, attributes, literalValue } = tagPath.tag.value;
303
+
304
+ escapeVm.next(
305
+ buildOpenNodeTag(
306
+ getFlagsWithGap(flags, false),
307
+ type,
308
+ attributes,
309
+ literalValue,
310
+ ),
311
+ );
288
312
  } else if (tagPath.tag.type === ReferenceTag && tagPath.tag.value.flags.hasGap) {
289
313
  let { flags, name, type, isArray, index } = tagPath.tag.value;
290
314
 
291
315
  flags = getFlagsWithGap(flags, false);
292
316
 
293
- vmReturn = escapeVm.next(buildReferenceTag(type, name, isArray, flags, index));
317
+ escapeVm.next(buildReferenceTag(type, name, isArray, flags, index));
294
318
  } else {
295
- vmReturn = escapeVm.next(tagPath.tag);
319
+ escapeVm.next(tagPath.tag);
296
320
  }
297
321
 
298
322
  if (tagPath.tag.type === CloseNodeTag && !tagPath.nextUnshifted) {
299
- gaplessNode = vmReturn.value;
323
+ gaplessNode = escapeState.resultPath.node;
300
324
  }
301
325
 
302
326
  tagPath = tagPath.nextUnshifted;
@@ -306,7 +330,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
306
330
  s.agast = m.agastFragment;
307
331
 
308
332
  s.held = Object.freeze({
309
- reference: refPath.tag.value,
333
+ reference: refPath?.tag.value,
310
334
  binding: null,
311
335
  node: gaplessNode || m.node,
312
336
  });
@@ -383,7 +407,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
383
407
  ),
384
408
  );
385
409
 
386
- s.resultPath = TagPath.fromNode(s.resultPath.node, -1);
410
+ s.resultPath = TagPath.from(s.resultPath.path, -1);
387
411
 
388
412
  s.held = null;
389
413
  break;
@@ -407,7 +431,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
407
431
  break;
408
432
  }
409
433
 
410
- if (s.node.children.size) {
434
+ if (s.node.tags.size) {
411
435
  m.advance(tag, s);
412
436
  } else {
413
437
  m.add(m.node);
@@ -425,7 +449,7 @@ function* __bablr(ctx, rootSource, strategy, options) {
425
449
  }
426
450
 
427
451
  case InitializerTag: {
428
- if (s.held && s.node.children.at(2)?.type === InitializerTag) {
452
+ if (s.held && s.node.tags.at(2)?.type === InitializerTag) {
429
453
  throw new Error();
430
454
  }
431
455
  m.advance(tag, s);
@@ -534,8 +558,6 @@ function* __bablr(ctx, rootSource, strategy, options) {
534
558
 
535
559
  finishedMatch = null;
536
560
 
537
- if (m.isNode && m.isCover) throw new Error();
538
-
539
561
  if (m.type !== sym.fragment && !getProduction(m.grammar, m.type))
540
562
  throw new Error(`Production {type: ${printType(m.type)}} does not exist`);
541
563
 
@@ -543,17 +565,17 @@ function* __bablr(ctx, rootSource, strategy, options) {
543
565
  throw new Error('tokens must be nodes');
544
566
  }
545
567
 
546
- if (parentMatch && parentMatch.cover && !m.isNode) {
568
+ if (parentMatch && parentMatch.cover && !parentMatch.isNode) {
547
569
  if (matcher_.refMatcher) {
548
570
  let m = matcher_.refMatcher;
549
- if (m.type !== '.' || m.flags.expression || m.flags.hasGap || m.isArray) {
571
+ if (!['.', '#'].includes(m.type) || m.flags.expression || m.flags.hasGap || m.isArray) {
550
572
  throw new Error('no references inside covers');
551
573
  }
552
574
  }
553
575
  }
554
576
 
555
577
  if (didShift) {
556
- if (s.node.children.at(-1)?.type !== ShiftTag) {
578
+ if (s.node.tags.at(-1, 0)?.type !== ShiftTag) {
557
579
  throw new Error('advance shift tag before starting new held frame');
558
580
  }
559
581
  }
@@ -569,16 +591,16 @@ function* __bablr(ctx, rootSource, strategy, options) {
569
591
 
570
592
  ({ language } = m);
571
593
 
572
- let offset = m.isNode ? -1 : 0;
594
+ let offset = [ReferenceTag, ShiftTag].includes(s.resultPath?.tag.type) ? -1 : 0;
573
595
 
574
596
  if (!broken) {
575
597
  let previousIndex = [CloseNodeTag, NullTag, GapTag].includes(s.resultPath.tag.type)
576
- ? m.fragmentNode.children.size - 1
577
- : s.resultPath.childrenIndex;
598
+ ? m.fragmentNode.tags.size - 1
599
+ : s.resultPath.tagsIndex;
578
600
 
579
601
  m.setRangePreviousIndex(previousIndex + offset);
580
602
  } else if (parentMatch) {
581
- m.setRangePreviousIndex(m.fragmentNode.children.size - 1 + offset);
603
+ m.setRangePreviousIndex(m.fragmentNode.tags.size - 1 + offset);
582
604
  }
583
605
 
584
606
  returnValue = facades.get(m);
package/lib/match.js CHANGED
@@ -5,9 +5,9 @@ import { agast, TagPathFacade as TagPath, PathFacade as Path } from '@bablr/agas
5
5
  import {
6
6
  buildOpenNodeTag,
7
7
  buildProperty,
8
- buildReferenceTag,
8
+ buildReference,
9
9
  fragmentFlags,
10
- mergeReferenceTags,
10
+ mergeReferences,
11
11
  } from '@bablr/agast-helpers/tree';
12
12
  import { effectsFor } from '@bablr/agast-vm-helpers';
13
13
  import { FragmentFacade } from './node.js';
@@ -20,10 +20,12 @@ import {
20
20
  ShiftTag,
21
21
  AttributeDefinition,
22
22
  Property,
23
+ PropertyWrapper,
23
24
  InitializerTag,
24
25
  BindingTag,
25
26
  LiteralTag,
26
27
  } from '@bablr/agast-helpers/symbols';
28
+ import { offsetForTag } from '@bablr/agast-helpers/path';
27
29
 
28
30
  export class MatchFacade {
29
31
  constructor(match) {
@@ -59,15 +61,10 @@ export class MatchFacade {
59
61
  return actuals.get(this).path;
60
62
  }
61
63
 
62
- get inner() {
63
- return actuals.get(this).inner;
64
- }
65
-
66
64
  get fragment() {
67
65
  const {
68
66
  ctx,
69
67
  effects,
70
- path,
71
68
  isCoverBoundary,
72
69
  isNode,
73
70
  fragmentNode,
@@ -77,11 +74,11 @@ export class MatchFacade {
77
74
  rangeFinalIndex,
78
75
  } = actuals.get(this);
79
76
 
80
- const { name, isArray } = mergedReference.value;
77
+ const { name, isArray } = mergedReference;
81
78
 
82
79
  let prev =
83
80
  rangePreviousIndex != null
84
- ? (fragmentNode || node).children.at(rangePreviousIndex)
81
+ ? (fragmentNode || node).tags.at(rangePreviousIndex)
85
82
  : rangePreviousIndex;
86
83
 
87
84
  let offset = [ReferenceTag, ShiftTag].includes(prev?.type) ? 0 : 1;
@@ -93,11 +90,11 @@ export class MatchFacade {
93
90
  false,
94
91
  true,
95
92
  [rangePreviousIndex + offset, rangeFinalIndex],
96
- mergedReference.value,
93
+ mergedReference,
97
94
  isArray ? fragmentNode.getChildPropertyIndex(rangePreviousIndex + offset) : null,
98
95
  );
99
96
  } else {
100
- return new FragmentFacade(fragmentNode || path.node, ctx, false, true, [
97
+ return new FragmentFacade(fragmentNode || node, ctx, false, true, [
101
98
  rangePreviousIndex + offset,
102
99
  rangeFinalIndex,
103
100
  ]);
@@ -249,11 +246,15 @@ export class Match extends WeakStackFrame {
249
246
  this.agast = isNode ? null : state.agast ?? null;
250
247
  this.node = isNode ? null : parent?.node;
251
248
  this.cover =
252
- isNode || effects.success === 'none' ? null : parent?.cover || (isCover ? this : null);
253
-
254
- let isCoverBoundary = ((isNode || isCover) && !this.cover) || !parent;
255
-
256
- if (isCoverBoundary) {
249
+ effects.success === 'none'
250
+ ? null
251
+ : !parent?.isNode && parent?.cover
252
+ ? parent.cover
253
+ : isCover && parent
254
+ ? this
255
+ : null;
256
+
257
+ if (isNode || !parent?.node) {
257
258
  let held = null;
258
259
  // TODO wat
259
260
  if (this.coveredBoundary.shiftMatch) {
@@ -277,7 +278,8 @@ export class Match extends WeakStackFrame {
277
278
  }
278
279
 
279
280
  get isCoverBoundary() {
280
- return (this.isNode && this.parent && !this.parent.cover) || this.cover === this;
281
+ let { cover } = this;
282
+ return cover === this;
281
283
  }
282
284
 
283
285
  get matcher() {
@@ -289,7 +291,7 @@ export class Match extends WeakStackFrame {
289
291
  }
290
292
 
291
293
  get mergedReference() {
292
- let ref = buildReferenceTag('.');
294
+ let ref = buildReference('.');
293
295
 
294
296
  let first = true;
295
297
  let m = this;
@@ -298,10 +300,11 @@ export class Match extends WeakStackFrame {
298
300
  do {
299
301
  if (m.isNode && !first) break;
300
302
  if (m.propertyMatcher.refMatcher) {
301
- const { type: refType, name, isArray, flags } = m.propertyMatcher.refMatcher;
302
- const parentRef = buildReferenceTag(refType, name, isArray, flags);
303
+ const parentRef = m.propertyMatcher.refMatcher;
304
+ const { type: refType, name } = parentRef;
305
+
303
306
  if (lastName && (lastName !== name || lastRefType !== refType)) break;
304
- ref = ['#', '@'].includes(ref.value.type) ? ref : mergeReferenceTags(ref, parentRef);
307
+ ref = ['#', '@'].includes(ref.type) ? ref : mergeReferences(ref, parentRef);
305
308
  if (refType !== '.') {
306
309
  lastName = name;
307
310
  lastRefType = refType;
@@ -330,11 +333,11 @@ export class Match extends WeakStackFrame {
330
333
  }
331
334
 
332
335
  get pathName() {
333
- return this.mergedReference.value.name;
336
+ return this.mergedReference.name;
334
337
  }
335
338
 
336
339
  get path() {
337
- let { agast } = this.coveredBoundary.parent ?? this;
340
+ let { agast } = this;
338
341
 
339
342
  return agast.state.path || agast.state.resultPath?.path;
340
343
  }
@@ -349,7 +352,7 @@ export class Match extends WeakStackFrame {
349
352
  }
350
353
 
351
354
  get coveredBoundary() {
352
- return this.isNode ? this.parent?.cover || this : this.cover || this;
355
+ return this.cover || this;
353
356
  }
354
357
 
355
358
  get parentPath() {
@@ -391,12 +394,19 @@ export class Match extends WeakStackFrame {
391
394
  return resultPath?.tag.type === CloseNodeTag ? resultPath.node : node;
392
395
  }
393
396
 
397
+ get fragmentPath() {
398
+ if (!this.agastFragment) return null;
399
+
400
+ let { path, resultPath } = this.agastFragment.state;
401
+ return resultPath?.tag.type === CloseNodeTag ? resultPath.path : path;
402
+ }
403
+
394
404
  get rangePrevious() {
395
- let node = this.fragmentNode || this.node;
405
+ let path = this.fragmentPath || this.path;
396
406
 
397
- return this.rangePreviousIndex == null || node == null
407
+ return this.rangePreviousIndex == null || path == null
398
408
  ? null
399
- : TagPath.fromNode(node, this.rangePreviousIndex);
409
+ : TagPath.from(path, this.rangePreviousIndex, -1);
400
410
  }
401
411
 
402
412
  setRangePreviousIndex(value) {
@@ -420,19 +430,19 @@ export class Match extends WeakStackFrame {
420
430
  }
421
431
 
422
432
  get rangeFinal() {
423
- let node = this.fragmentNode || this.node;
433
+ let path = this.fragmentPath || this.path;
424
434
 
425
- return this.rangeFinalIndex == null || node == null
435
+ return this.rangeFinalIndex == null || path == null
426
436
  ? null
427
- : TagPath.fromNode(node, this.rangeFinalIndex);
437
+ : TagPath.from(path, this.rangeFinalIndex, -1);
428
438
  }
429
439
 
430
440
  get rangeInitial() {
431
- const { rangePrevious, isNode, fragmentNode, node, rangePreviousIndex } = this;
441
+ const { rangePrevious, isNode, fragmentPath, path, rangePreviousIndex } = this;
432
442
 
433
443
  if (!rangePrevious) return rangePrevious;
434
444
 
435
- if (isNode) return TagPath.fromNode(fragmentNode || node, rangePreviousIndex + 1);
445
+ if (isNode) return TagPath.from(fragmentPath || path, rangePreviousIndex + 1, 0);
436
446
 
437
447
  return rangePrevious?.nextSibling;
438
448
  }
@@ -451,15 +461,15 @@ export class Match extends WeakStackFrame {
451
461
  return null;
452
462
  }
453
463
 
454
- let offset = this.isNode ? 1 : 0;
464
+ let parentPath = this.fragmentPath || this.path;
455
465
 
456
- let ref = TagPath.fromNode(this.fragmentNode || this.node, this.rangePreviousIndex + offset);
466
+ let ref = TagPath.from(parentPath, this.rangePreviousIndex + 1, 0);
457
467
 
458
468
  if (!ref) return null;
459
469
 
460
470
  if (ref.tag.type === ShiftTag) {
461
- let refIndex = ref.childrenIndex - ref.tag.value.index * 3;
462
- ref = ref.siblingAt(refIndex);
471
+ let refIndex = ref.tagsIndex - ref.tag.value.index;
472
+ ref = TagPath.from(ref.path, refIndex, 0);
463
473
  }
464
474
 
465
475
  if (ref && ref.tag.type !== ReferenceTag) throw new Error();
@@ -475,10 +485,6 @@ export class Match extends WeakStackFrame {
475
485
  return this.cover === this;
476
486
  }
477
487
 
478
- get inner() {
479
- return Path.from(this.node);
480
- }
481
-
482
488
  advance(tag, s = this.state) {
483
489
  let { vm, state: agastState } = s.agast;
484
490
 
@@ -486,14 +492,18 @@ export class Match extends WeakStackFrame {
486
492
 
487
493
  if (tag.type === OpenNodeTag) {
488
494
  s.depths.result++;
489
- this.node = s.node;
495
+ this.node = s.node || s.resultPath.node;
490
496
  } else if (tag.type === CloseNodeTag) {
491
497
  s.depths.result--;
492
498
  }
493
499
 
494
500
  s.resultPath =
495
- (agastState.node || agastState.resultPath?.node) &&
496
- TagPath.fromNode(agastState.node || agastState.resultPath?.node, -1);
501
+ (agastState.path || agastState.resultPath?.path) &&
502
+ TagPath.from(
503
+ agastState.path || agastState.resultPath?.path,
504
+ -1,
505
+ tag.type === PropertyWrapper ? -1 : offsetForTag(tag),
506
+ );
497
507
  return result.value;
498
508
  }
499
509
 
@@ -524,7 +534,7 @@ export class Match extends WeakStackFrame {
524
534
 
525
535
  if (!m) return m;
526
536
 
527
- finishedMatch.setRangeFinalIndex((finishedMatch.fragmentNode || m.node).children.size - 1);
537
+ finishedMatch.setRangeFinalIndex((finishedMatch.fragmentNode || m.node).tags.size - 1);
528
538
 
529
539
  m.running = null;
530
540
 
@@ -559,7 +569,7 @@ export class Match extends WeakStackFrame {
559
569
 
560
570
  let path = Path.from(node);
561
571
 
562
- let tagPath = emitted?.tagPath || (path.node.children.size ? TagPath.from(path, 0) : null);
572
+ let tagPath = emitted?.tagPath || (path.node.tags.size ? TagPath.from(path, 0) : null);
563
573
 
564
574
  while (tagPath) {
565
575
  if (
@@ -602,8 +612,12 @@ export class Match extends WeakStackFrame {
602
612
  }
603
613
  }
604
614
 
605
- if (tagPath.tag.type === CloseNodeTag && !tagPath.next) {
606
- tagPath = TagPath.fromNode(m.fragmentNode, m.rangeInitial.childrenIndex + 3);
615
+ if (
616
+ (tagPath.tag.type === CloseNodeTag ||
617
+ (tagPath.tag.type === OpenNodeTag && tagPath.tag.value.selfClosing)) &&
618
+ !tagPath.next
619
+ ) {
620
+ tagPath = TagPath.from(m.fragmentPath, m.rangeInitial.tagsIndex + 1, 0);
607
621
 
608
622
  do {
609
623
  m = m.parent;
@@ -631,7 +645,7 @@ export class Match extends WeakStackFrame {
631
645
  } else {
632
646
  break;
633
647
  }
634
- tagPath = TagPath.fromNode(m.node, 0);
648
+ tagPath = TagPath.from(m.path, 0);
635
649
  } else {
636
650
  if (holdShifted) {
637
651
  tagPath = tagPath.nextUnshifted;