less.js: CSS min and max function calls that hold CSS variables fail with "Operation on an invalid type"

To reproduce:

With strict units enabled, perform a calc-like expression inside a min or max function and use a CSS variable. E.g.

prop : min(100% - var(--some-var), 10px);

Current behavior: Compiler will throw “Operation on an invalid type” error.

Expected behavior: Compiler knows the arguments to min and max can be calc-like and doesn’t throw, but retains the arguments as-is.

Environment information:

  • less version: 4.1.3
  • nodejs version: 14
  • operating system: any

Having dug around a bit, it appears that the root of the issue is the fact that Operation is visited and flattened before passing to min and max, which means the var() node trips the compiler error as it afaict does not implement an operate method.

This problem can be avoided by setting evalArgs : false for both functions and performing custom lazy evaluation inside the functions themselves, where it can be wrapped in a try-catch and cause the function to go inert (and be treated as the CSS function proper) when incompatible types are present.

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Comments: 24 (9 by maintainers)

Commits related to this issue

Most upvoted comments

@iChenLei the CI test that are failing are in accordance with the conversation with @matthew-dean , that’s why Matthew asked me to start a draft PR, please go through the conversation above. Thanks

One way to prevent having to do this several times in several places would be to, rather than creating a try / catch block within each function, would be to create an abstraction that outputs certain functions as-is.

In other words, a number of functions have had try / catch blocks added within the function statement, and outputs the nodes as-is instead of throwing an error if it can’t evaluate something, but that gets repetitive to add per function.

A downside of doing this is that if the stylesheet author intended Less to evaluate the statement, and there is an error in the expression, rather than showing an error, it will just output the function.