less / less.js

Less. The dynamic stylesheet language.
http://lesscss.org
Apache License 2.0
17.02k stars 3.41k forks source link

Unexpected extracted variable in second looped ruleset #3647

Open Jazain opened 3 years ago

Jazain commented 3 years ago

A variable extracted from a list has a different value than expected, but not during the first mixin loop.

An example is:

@list: red, blue, green;

.loop(@rules, @index: length(@list)) when (@index > 0) {
  @el: extract(@list, @index);

  @rules();

  .loop(@rules, @index - 1);
}

.loop({
  .a { 
    color: @el;
  }
});

.loop({
  .b { 
    background-color: @el;
  }
});

I expect three .a and three .b with the three different colors but I get (https://lesscss.org/less-preview/ 2021-09-09):

.a {
  color: green;
}
.a {
  color: blue;
}
.a {
  color: red;
}
.b {
  background-color: green;
}
.b {
  background-color: green;
}
.b {
  background-color: green;
}

Checking the value before the @rules(); call, I get the expected color:

  .test {
    current: @el;
  }
  @rules();
.test {
  current: green;
}
.a {
  color: green;
}
.test {
  current: blue;
}
.a {
  color: blue;
}
.test {
  current: red;
}
.a {
  color: red;
}
.test {
  current: green;
}
.b {
  background-color: green;
}
.test {
  current: blue;
}
.b {
  background-color: green;
}
.test {
  current: red;
}
.b {
  background-color: green;
}

Adding index: @index; near current, color and background-color has always the expected values. Only the extracted @el is fixed in the second loop.

Since @list and @index are correct during the ruleset evaluation, if I extract the value inside the ruleset it works as expected:

.loop({
  @el: extract(@list, @index);
  .b {
    background-color: @el;
  }
});
.b {
  background-color: green;
}
.b {
  background-color: blue;
}
.b {
  background-color: red;
}