Throwing an error when a variable is not defined
TonoFilth opened this issue · comments
These are my options:
const opts = {
"ifdef-verbose": true,
"ifdef-triple-slash": true
};
In some .js file I have:
/// #if STATS
console.log('stats defined');
/// #else
console.log('stats not defined');
/// #endif
And when I try running my project:
Module build failed: Error: ifdef-loader error: error evaluation #if condition(STATS): ReferenceError: STATS is not defined
Obviously I didn't defined STATS in the loader options. But, why throw an error if STATS is not defined? For me makes no sense to throw an error in this case, I would expect that the '#if STATS' part is removed and the '# else' part is kept.
Is this the desired behaviour, or am I missing something?
I would say it's desidered behaviour: what comes after the if
is evaluated as a plain JavaScript expression, so throwing ReferenceError
is expected to happen if STATS
is not defined at all (at least in strict mode).
I don't think that can be fixed easily since the loader doesn't have its own expression parser, it just uses something like eval()
to evaluate expressions.
And you can't just trap the error and resolve to false
because it wouldn't work if you write #if !STATS
.
Possible workarounds:
- initilize with
STATS: undefined
- check with
#if typeof STATS === 'undefined'
Just for clarification, what I was trying to achieve is to have two different configurations, one for development and other for production:
dev: {
DEVELOPMENT: true,
STATS: true,
},
prod: {
PRODUCTION: true,
}
Now I'm forced to duplicate the defines:
dev: {
DEVELOPMENT: true,
PRODUCTION: false,
STATS: true,
},
prod: {
DEVELOPMENT: false,
PRODUCTION: true,
STATS: false
}
I don't like this solution, so I will go with your workaround #if typeof STATS === 'undefined'
.
Thanks a lot for the quick response!
I've modified the beginning of the evaluate() function in preprocessor.js and added the following code:
function evaluate(condition, keyword, defs) {
condition = condition.replace(/defined\( *([a-z|A-Z|0-9|_]+) *\)/g, (match, p1) => {
return defs[p1] === true;
})
...
}
This allow me to write options in this way:
dev: {
DEVELOPMENT: true,
STATS: true,
},
prod: {
PRODUCTION: true,
}
and use the preprocessor defines in this way:
/// #if defined(STATS)
console.log('stats defined');
/// #endif
If STATS is not defined there is no error thrown. I don't like to modify library sources directly but I prefer to work in this way.
Thanks for your help.