4

I'm using JavaScript - via <scriptdef> - in my project.xml to compose a property name from multiple property values. I need to compare two strings in my script: One that is passed in as an expansion of one or more property values. The other is passed in as a quoted literal string . . .

<ac:var name="buildVariant" unset="true"/>
<property name="buildVariant" value="Debug"/>
<unStrung propstring="${buildVariant}" altifmatch="Debug"/>

. . . But the string comparison in the script is not working as I expect. A character-by-character comparison of identical strings evaluates to "true". An AND of a pair of negated ">" and "<" comparisons evaluates to "true". But simply comparing string1 == string2 evaluates to "false". Here is a simplified script that illustrates the problem (and shows a few work-arounds I tried) . . .

<scriptdef name="unStrung" language="javascript">
    <attribute name="propstring"/>
    <attribute name="altifmatch"/>
<![CDATA[
var propstring = attributes.get("propstring");
var propvalue = project.getProperty(propstring);
var altifmatch = attributes.get("altifmatch");
var debugTheDebug = "Debug";

if ( altifmatch != null && propstring != null )
{
    var alen = 0;
    var plen = 0;
    alen = altifmatch.length();
    plen = propstring.length();

    print(' ');
    print('    altifmatch = [' + altifmatch + '] and propstring = [' + propstring + ']');
    print('    so naturally (altifmatch == propstring) = [' + (altifmatch == propstring) + '],');
    print('    just like ("Debug" == "Debug") = [' + ("Debug" == "Debug") + '].');
    print(' ');

    print(' ');
    print('    altifmatch.length() = [' + alen + '] and propstring.length() = [' + plen + ']');
    print('    altifmatch.substring(0,alen) = [' + altifmatch.substring(0,alen)
        + '] and propstring.substring(0,plen) = [' + altifmatch.substring(0,alen) + ']');
    print('    so naturally ( propstring.substring(0,plen) == propstring.substring(0,plen) ) = ['
                + (altifmatch.substring(0,alen) == propstring.substring(0,plen)) + '].');
    print(' ');

    for (var c=0; c<plen; c++)
    {
        print('    char['+c+']: altifmatch['+c+']="'+altifmatch.charCodeAt(c)+'";  propstring['+c+']="'+propstring.charCodeAt(c)
            +'".  So ... a == p = "' + (altifmatch.charCodeAt(c) == propstring.charCodeAt(c)) + '"');
    }

    print(' ');
    print('    typeof(altifmatch) = "' + typeof(altifmatch) + '", and typeof(propstring) = "' + typeof(propstring) + '"');
    print('    altifmatch.toString() = "' + altifmatch.toString() + '" and propstring.toString() = "' + propstring.toString() + '"');
    print('    ...oddly enough... debugTheDebug = "' + debugTheDebug + '"');
    print('       (debugTheDebug == altifmatch.toString()) = "' + (debugTheDebug == altifmatch.toString()) + '"');
    print('       (debugTheDebug == propstring.toString()) = "' + (debugTheDebug == propstring.toString()) + '"');
    print('    ...and still... (altifmatch.toString() == propstring.toString()) = "' + (altifmatch.toString() == propstring.toString()) + '"');

    print(' ');
    print('       (debugTheDebug == altifmatch) = "' + (debugTheDebug == altifmatch) + '"');
    print('       (debugTheDebug == propstring) = "' + (debugTheDebug == propstring) + '"');
    print('    ...and still... (altifmatch == propstring) = "' + (altifmatch == propstring) + '"');
    print('       (altifmatch < propstring) = "' + (altifmatch < propstring) + '"');
    print('       (altifmatch > propstring) = "' + (altifmatch > propstring) + '"');
    print('          (!(altifmatch < propstring) && !(altifmatch > propstring)) = "'
            + (!(altifmatch < propstring) && !(altifmatch > propstring)) + '"');
    print('    ...and of course... ( (debugTheDebug == altifmatch) && (debugTheDebug == propstring) ) = "'
            + ( (debugTheDebug == altifmatch) && (debugTheDebug == propstring) ) + '"');

    print(' ');
}
]]>
</scriptdef>

The resulting output looks like this:

altifmatch = [Debug] and propstring = [Debug]
so naturally (altifmatch == propstring) = [false],
just like ("Debug" == "Debug") = [true].


altifmatch.length() = [5] and propstring.length() = [5]
altifmatch.substring(0,alen) = [Debug] and propstring.substring(0,plen) = [Debug]
so naturally ( propstring.substring(0,plen) == propstring.substring(0,plen) ) = [false].

char[0]: altifmatch[0]="68";  propstring[0]="68".  So ... a == p = "true"
char[1]: altifmatch[1]="101";  propstring[1]="101".  So ... a == p = "true"
char[2]: altifmatch[2]="98";  propstring[2]="98".  So ... a == p = "true"
char[3]: altifmatch[3]="117";  propstring[3]="117".  So ... a == p = "true"
char[4]: altifmatch[4]="103";  propstring[4]="103".  So ... a == p = "true"

typeof(altifmatch) = "object", and typeof(propstring) = "object"
altifmatch.toString() = "Debug" and propstring.toString() = "Debug"
...oddly enough... debugTheDebug = "Debug"
   (debugTheDebug == altifmatch.toString()) = "true"
   (debugTheDebug == propstring.toString()) = "true"
...and still... (altifmatch.toString() == propstring.toString()) = "false"

   (debugTheDebug == altifmatch) = "true"
   (debugTheDebug == propstring) = "true"
...and still... (altifmatch == propstring) = "false"
   (altifmatch < propstring) = "false"
   (altifmatch > propstring) = "false"
      (!(altifmatch < propstring) && !(altifmatch > propstring)) = "true"
...and of course... ( (debugTheDebug == altifmatch) && (debugTheDebug == propstring) ) = "true"

I suspect it is something simple or silly that I missed (I am not very experienced with Ant or JavaScript).

Ideas?

Kenigmatic
  • 448
  • 6
  • 16
  • See-also: Related and interesting, but not a direct answer to my question . . . [Why are there two kinds of JavaScript strings?](http://stackoverflow.com/questions/5514367/why-are-there-two-kinds-of-javascript-strings) – Kenigmatic May 19 '12 at 01:04
  • A friend just pointed me to a more-recent yet similar case worth looking at! https://stackoverflow.com/questions/48270127/can-a-1-a-2-a-3-ever-evaluate-to-true – Kenigmatic Oct 26 '18 at 20:02

1 Answers1

1

for string comparison you should use (String).equals()

http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Object.html

Brandt Solovij
  • 2,124
  • 13
  • 24
  • That worked perfectly! What I don't understand is why I didn't find that option with A LOT of searching . . . (okay, maybe because I'm not well versed in JavaScript), but I found MANY hits saying that == should just work (as long as no trailing blanks or hidden chars). THANKS! Also, I would up-vote your answer but I don't have enough rep, yet! – Kenigmatic May 19 '12 at 00:41
  • Well I admit im not an Ant pro - but as I understand it - Ant is a java build tool. Even though you are using the ` ` setting / directive - as i understand it, that simply invokes some intrinsic mechanism to "process script as java proper" - meaning, again as i understand it - that the Ant java engine "makes java work from script directives" --- TL:DR / Cool Story Bro - basically a "==" comparison will slide in pure javascript - but what you are doing is asking ant to build java directives from js. As such "==" fails due to the nature of that comparison - glad it worked&could help! – Brandt Solovij May 19 '12 at 04:41
  • I think something must be broken though, since many instances of `==` work correctly, and the ones that do not work correctly appear irrational, especially if mixed with the "working" cases . . . `(a==b)=true, (a==c)=true, (b==c)=false`??? . . . and . . . `(a>b)=false, (ab) && !(a – Kenigmatic May 19 '12 at 05:17
  • == works a little different from .equals() i must admit that I am not such an expert to list the variances between the two - but can attest to these variances in practice. – Brandt Solovij May 19 '12 at 05:27
  • `if ( "different" == "broken" ) JS_AiNT_JAVA = true;` ;-) – Kenigmatic May 19 '12 at 11:51