Skip to content

Commit 24f6814

Browse files
committed
Fix 8.5.17 visitor regression
1 parent f2fa53f commit 24f6814

2 files changed

Lines changed: 67 additions & 2 deletions

File tree

‎lib/lazy-result.js‎

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -503,14 +503,24 @@ class LazyResult {
503503

504504
if (visit.iterator !== 0) {
505505
let iterator = visit.iterator
506+
// Advance past the child we just finished visiting. Like
507+
// `Container#each`, the index is incremented only after a child has
508+
// been fully processed, so a node inserted right after the current
509+
// child is not skipped by the `existIndex < index` adjustment in
510+
// `Container#insertAfter()` (which would fire exit events too early).
511+
if (visit.descending) {
512+
visit.descending = false
513+
node.indexes[iterator] += 1
514+
}
506515
let child
507516
while ((child = node.nodes[node.indexes[iterator]])) {
508-
node.indexes[iterator] += 1
509517
if (!child[isClean]) {
510518
child[isClean] = true
519+
visit.descending = true
511520
stack.push(toStack(child))
512521
return
513522
}
523+
node.indexes[iterator] += 1
514524
}
515525
visit.iterator = 0
516526
delete node.indexes[iterator]
@@ -548,12 +558,22 @@ class LazyResult {
548558

549559
if (visit.iterator !== 0) {
550560
let iterator = visit.iterator
561+
// Advance past the child we just finished visiting. Like
562+
// `Container#each`, the index is incremented only after a child has
563+
// been fully processed. Incrementing before (as this loop used to)
564+
// makes a node inserted right after the current child get skipped by
565+
// the `existIndex < index` adjustment in `Container#insertAfter()`,
566+
// which fires exit events before those new siblings are visited.
567+
if (visit.descending) {
568+
visit.descending = false
569+
visitNode.indexes[iterator] += 1
570+
}
551571
let child
552572
let descended = false
553573
while ((child = visitNode.nodes[visitNode.indexes[iterator]])) {
554-
visitNode.indexes[iterator] += 1
555574
if (!child[isClean]) {
556575
child[isClean] = true
576+
visit.descending = true
557577
stack.push({
558578
eventIndex: 0,
559579
events: getEvents(child),
@@ -563,6 +583,7 @@ class LazyResult {
563583
descended = true
564584
break
565585
}
586+
visitNode.indexes[iterator] += 1
566587
}
567588
if (descended) continue
568589
visit.iterator = 0

‎test/visitor.test.ts‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,50 @@ test('works with at-rule params', () => {
324324
is(css, '@media (mobile) {}')
325325
})
326326

327+
function trackUnwrap(): [string[], Plugin] {
328+
let order: string[] = []
329+
let plugin: Plugin = {
330+
postcssPlugin: 'unwrap-nested',
331+
Rule(rule) {
332+
order.push('Rule ' + rule.selector)
333+
rule.each(child => {
334+
if (child.type === 'rule') {
335+
child.selector = rule.selector + ' ' + child.selector
336+
rule.after(child)
337+
}
338+
})
339+
},
340+
RootExit() {
341+
order.push('RootExit')
342+
}
343+
}
344+
return [order, plugin]
345+
}
346+
347+
test('visits nodes inserted after the current one before exit events', () => {
348+
let [order, plugin] = trackUnwrap()
349+
postcss([plugin]).process('a { b { c {} } }', { from: 'a.css' }).css
350+
equal(order, [
351+
'Rule a',
352+
'Rule a b',
353+
'Rule a b c',
354+
'RootExit',
355+
'Rule a',
356+
'Rule a b',
357+
'RootExit'
358+
])
359+
})
360+
361+
test('visits inserted siblings equally in sync and async walks', async () => {
362+
let [syncOrder, syncPlugin] = trackUnwrap()
363+
postcss([syncPlugin]).process('a { b { c {} } }', { from: 'a.css' }).css
364+
365+
let [asyncOrder, asyncPlugin] = trackUnwrap()
366+
await postcss([asyncPlugin]).process('a { b { c {} } }', { from: 'a.css' })
367+
368+
equal(asyncOrder, syncOrder)
369+
})
370+
327371
test('wraps node to proxies', () => {
328372
let proxy: any
329373
let root: Root | undefined

0 commit comments

Comments
 (0)