In a previous post I described how to realiably use Debug/Release build configurations in Visual Studio to selectively copy a debug or release file into your project at build time, offering a solution to JavaScript's lack of precomiler directives like #ifdef DEBUG as found in C# and C++. I wanted to expand on that post with additional options that I've seen discussed. [Thanks to Rob Paveza, Ginger Edighoffer, Howard Kapustein, Steve Bohlen, and Gearard Boland.]

In this context, people often suggest using the following structure for similar purposes:

if (Debug.debuggerEnabled) {
    // use debug settings
}
else {
    // use production
}

Although this works reasonably well, the downside is that having a debugger enabled says nothing about how the project was built. You can debug a Release build of a JavaScript app just fine, in which case debuggerEnabled will be true and you can still step through the code because JavaScript isn't compiled ahead of time. This means that stepping through the code above for a Release build will not hit the //use production block.

You can work around this, of course, by setting a breakpoint on the if statement and then setting the next statement to the //use production block. If you want to do this pervasively, then you can wrap a simple function around Debug.debuggerEnabled where you can set a single breakpoint:

function checkDebug() {
    if (Debug.debuggerEnabled) {
        return true;
    } else {
        return false;
    }
}

In here I've put in two return statements so there's an obvious place to set the next statement and control the return value.

Another suggestion I've seen for this matter is to create a simple C++ WinRT component that does something like this:

namespace WrcCpp
{
    public ref class ModeMonitor sealed
    {
        private:
            ModeMonitor() { };

        public:
            static property bool IsDebugMode {
                bool get() {
#ifdef _DEBUG
                    return true;
#else
                    return false;
#endif
                }
            }
    };
}

There's also a property in Windows.ApplicationModel.Package.current.isDevelopmentMode that you might come across but this reflects how the package was installed (that is, it was deployed from Visual Studio rather than the Store), and not how the package was built. That is, it describes the deployment mode, not the build target.

Here's another possibility: run your JavaScript code through a C++ preprocessor that can chew on the #ifdef statements to generate the JavaScript code you want to run. I imagine that this could be incorporated into a Visual Studio build process similar to my previous post. 

Along these same lines is the need to differentiate code in a universal Windows app project that's targeted specifically to Windows or Windows Phone when that code lives in the Shared folder. That is, although you can keep code for both targets separate in their own project structures, sometimes it's just easier to make a simple differentiation within some of the Shared code.

The compiled languages have the WINDOWS_APP and WINDOWS_PHONE_APP precompiler directives for this purpose, but not JavaScript. The options you have, then, are as follows [thanks to Steve Bohlen]. First is WinJS.Utilities.isPhone:

if (WinJS.Utilities.isPhone){
    // phone
}
else{
    // not phone
}

Second is using a feature detection pattern like you do with cross-browser JavaScript:

if (PhoneAPINamespace && PhoneAPINamespace.phoneAPI) {
   //  safely call phoneAPI()
}

The first option is more explicit, of course, whereas the second is more resiliant to changes in the available API (a consideration with continued convergence in WinRT).

 


Comments are closed