nippur72 / ifdef-loader

Webpack loader for JavaScript/TypeScript conditional compilation.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.