Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CRIT ISSUE with LESS4J scope #342

Open
twhoff opened this issue Apr 7, 2016 · 1 comment
Open

CRIT ISSUE with LESS4J scope #342

twhoff opened this issue Apr 7, 2016 · 1 comment

Comments

@twhoff
Copy link

twhoff commented Apr 7, 2016

Scope inheritance in LESS4J is not working as intended in LESS.

Basically, child mixins inherit global scope OR parent scope before any operations on variables take place.

Simple example

In the following code @width is inherited from the global scope in .fluid-col().

The .calculate() mixin then converts the number to a valid percentage, and as @width is not explicitly set within the scope of .fluid-col(), the unlocked @width variable should override the inherited one, as is specified in LESS documentation:

Variables and mixins defined in a mixin are visible and can be used in caller's scope. There is only one exception, a variable is not copied if the caller contains a variable with the same name (that includes variables defined by another mixin call). Only variables present in callers local scope are protected. Variables inherited from parent scopes are overridden.

The overridden @width variable should now be inherited by the .inner-scope-test() mixin, however, in LESS4J this is not the case.

/* Scope test */

// Global scope
@width: 1/3;

// Caller
.test {
    .fluid-col();
}

// Mixin
.fluid-col() {
    // @width should be changed to 33.33333333%
    .calculate(@width);
    width: @width;

    .inner-scope-test();
    .inner-scope-test() {
        width2: @width;
    }
}

// Operator
.calculate(@arg) {
    @width: unit(@arg * 100, %);
}

Correct output from LESS compiler

  • width2 shows % value
/* Scope test */
.test {
  width: 33.33333333%;
  width2: 33.33333333%;
}

Incorrect output from LESS4J compiler

  • width2 shows numeric value
  • should also note precision of decimal places is 16 vs 8 in LESS
  • further, comment is not visible in LESS4J output
.test {
  width: 33.33333333333333%;
  width2: 0.3333333333333333;
}

Workaround
Passing the operated variable as a parameter to the inner mixin produces the correct result, however, this is less than ideal when you are dealing with multiple parameters which you then need to keep track of manually.

/* Scope test */

// Global scope
@width: 1/3;

// Caller
.test {
    .fluid-col();
}

// Mixin
.fluid-col() {
    // @width should be changed to 33.33333333%
    .calculate(@width);
    width: @width;

    .inner-scope-test(@width);
    .inner-scope-test(@width) {
        width2: @width;
    }
}

// Operator
.calculate(@arg) {
    @width: unit(@arg * 100, %);
}

Output

.test {
  width: 33.33333333333333%;
  width2: 33.33333333333333%;
}
@SomMeri
Copy link
Owner

SomMeri commented Apr 10, 2016

Note to self: The issue is caused by these lines:

ScopeView mixinWorkingScope = scopeManipulation.joinIfIndependent(callerScope, mixinScope);
// it the mixin calls itself recursively, each copy should work on
// independent copy of local data
// that is matters mostly for scope placeholders - if both close
// placeholders in same copy error happen
mixinWorkingScope.toIndependentWorkingCopy();

The toIndependentWorkingCopy ensures that second call does not see imported variables. Solution: the joinIfIndependent method needs to work differently for local calls.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants