Skip to content

Commit

Permalink
Fixes #3371 Allow conditional evaluation of function args (#3532)
Browse files Browse the repository at this point in the history
  • Loading branch information
matthew-dean committed Jul 13, 2020
1 parent a722237 commit d5aa9d1
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 11 deletions.
11 changes: 8 additions & 3 deletions packages/less/src/less/functions/boolean.js
Expand Up @@ -5,9 +5,14 @@ function boolean(condition) {
return condition ? Keyword.True : Keyword.False;
}

function If(condition, trueValue, falseValue) {
return condition ? trueValue
: (falseValue || new Anonymous);
/**
* Functions with evalArgs set to false are sent context
* as the first argument.
*/
function If(context, condition, trueValue, falseValue) {
return condition.eval(context) ? trueValue.eval(context)
: (falseValue ? falseValue.eval(context) : new Anonymous);
}
If.evalArgs = false

export default { boolean, 'if': If };
8 changes: 8 additions & 0 deletions packages/less/src/less/functions/function-caller.js
Expand Up @@ -15,6 +15,10 @@ class functionCaller {
}

call(args) {
const evalArgs = this.func.evalArgs;
if (evalArgs !== false) {
args = args.map(a => a.eval(this.context));
}
// This code is terrible and should be replaced as per this issue...
// https://github.com/less/less.js/issues/2477
if (Array.isArray(args)) {
Expand Down Expand Up @@ -42,6 +46,10 @@ class functionCaller {
});
}

if (evalArgs === false) {
return this.func(this.context, ...args);
}

return this.func(...args);
}
}
Expand Down
22 changes: 15 additions & 7 deletions packages/less/src/less/tree/call.js
Expand Up @@ -42,19 +42,25 @@ class Call extends Node {
if (this.calc || context.inCalc) {
context.enterCalc();
}
const args = this.args.map(a => a.eval(context));
if (this.calc || context.inCalc) {
context.exitCalc();
}
context.mathOn = currentMathContext;

const exitCalc = () => {
if (this.calc || context.inCalc) {
context.exitCalc();
}
context.mathOn = currentMathContext;
};

let result;
const funcCaller = new FunctionCaller(this.name, context, this.getIndex(), this.fileInfo());

if (funcCaller.isValid()) {
try {
result = funcCaller.call(args);
result = funcCaller.call(this.args);
exitCalc();
} catch (e) {
if (e.hasOwnProperty('line') && e.hasOwnProperty('column')) {
throw e
}
throw {
type: e.type || 'Runtime',
message: `error evaluating function \`${this.name}\`${e.message ? `: ${e.message}` : ''}`,
Expand All @@ -81,9 +87,11 @@ class Call extends Node {
result._fileInfo = this._fileInfo;
return result;
}

}

const args = this.args.map(a => a.eval(context));
exitCalc();

return new Call(this.name, args, this.getIndex(), this.fileInfo());
}

Expand Down
1 change: 1 addition & 0 deletions packages/test-data/css/_main/functions.css
Expand Up @@ -227,6 +227,7 @@ html {
i: 6;
j: 8;
k: 1;
l: black;
/* results in void */
color: green;
color: purple;
Expand Down
2 changes: 1 addition & 1 deletion packages/test-data/errors/eval/recursive-variable.txt
@@ -1,2 +1,2 @@
NameError: Recursive variable definition for @bodyColor in {path}recursive-variable.less on line 1, column 20:
NameError: error evaluating function `darken`: Recursive variable definition for @bodyColor in {path}recursive-variable.less on line 1, column 13:
1 @bodyColor: darken(@bodyColor, 30%);
5 changes: 5 additions & 0 deletions packages/test-data/less/_main/functions.less
Expand Up @@ -263,6 +263,11 @@ html {
j: if(not(true) and true, 6, 8);
k: if(true or true, 1);

// see: https://github.com/less/less.js/issues/3371
@some: foo;
l: if((iscolor(@some)), darken(@some, 10%), black);


if((false), {g: 7}); /* results in void */

@conditional: if((true), {
Expand Down

0 comments on commit d5aa9d1

Please sign in to comment.