Forum Discussion

Manfred_F's avatar
Manfred_F
Regular Contributor
8 years ago

surprising effect of casesensivity using JScript in vbScript module

in my vbScript test porject, I apply a script Extension implemented in JScript: an object is created with a .Value field.

The JScript implementation is case sensitive.

 

Everything is fine, as Long as in my vbScript Standard test module using the JScript ext., only "Value" properyt names occur. As soon as I use a "value" (LCase) one, I get an error when I use my object from JScript: "[objname].value not supported", eventhough this string does not occur that way in the module.

In my example, using RegEx .value property was the Trigger, changing it to .Value solved the issue.

 

4 Replies

  • tristaanogre's avatar
    tristaanogre
    Esteemed Contributor

    Very interesting...  Supposedly, the Runtime Objects created by script extensions translate pretty seemlessly to any language.  This appears to be an exception.  Can you share a sample code of how this is happening?  Would be interesting to play around with a sample extension and VBScript code to see what is happening.

    • Manfred_F's avatar
      Manfred_F
      Regular Contributor

      This is the JScript Code:

       

      //***************   Wrapper um globale Variablen für vbScript Standard-Module   *******
      
      // define a globalVariable class
      function globalVariable() {
         // initialize the member variables for this instance
         this.ClassName = "globalVariable";
         this.Value = null //Util.GetNothing()
            
         // ScriptLang als Funktion, damit einfacher erkennbar in CallSvcClass
         globalVariable.prototype.ScriptLang = function() {
            return "JavaScript";
         }
         
         // in lokalem Kontext freigeben, damit Speicher frei wird
         globalVariable.prototype.ShutDown = function() {
            if (Util.ObjectIsSet(this.Value)) {
               // Unterobjekte..
               //if (Util.IsSupportedStd(this.Value, "ShutDown", this.ClassName)) this.Value.ShutDown()
               this.Value = null //Util.GetNothing();
            }
         }
         
         // Objekte zählen lassen
         //this._Counter = PVA_0.Debug.CounterProxy_New(this.ClassName, "")
      }
      
      
      function globalVariableCreate()
      {
         return new globalVariable()
      }
      		  

      I use the globalVariable objects as wrappers to store vbScript Objects in a module context in a way, that their Memory is released when garbageCollect is called in JScript.

       

       

      This would be the Content of description.XML:

      <?xml version="1.0" encoding="UTF-8"?>
      <ScriptExtensionGroup Name = "DMS ScriptExtensions">
      
        <Category Name="Runtime Objects">
      
          <ScriptExtension Name = "PVA_Basis" Author = "DMS AG" Version = "1.0" HomePage = "">
       	  
            <Script Name = "BasisJs.sj">
      		  <RuntimeObject Name = "Util">
      			  <Method Name="globalVariableCreate" Routine="globalVariableCreate">
      				Globalvariable anlegen zur Ablage in vbs Modul.
      			  </Method>
      			  
      			  <Description>
      				Basisfunktionen für Skripterweiterungen, JavaScript.
      			  </Description>
      		  </RuntimeObject>
            </Script>
       	  
      	  <Description>
              DMS Basisfunktionen für Skripterweiterungen.
            </Description>
          </ScriptExtension>
      
        </Category>
      
      </ScriptExtensionGroup>
      
      

       

      So, You can create the JScript Extension and use it.

       

      In a vbScript module, create a global variable object and assign it to a variable defined in module context.

      Then You set its value in a Routine by "Set myVar.Value = objVar".

      This should work, You can try it with the Debugger.

       

      Then, in another Routine, You add the following Code:

      Dim RegEx, Matches, myKey
               Set regEx = New RegExp
               regEx.Pattern = "\.[G|V]\d{1,2}"
               regEx.IgnoreCase = True 
               regEx.Global = True
               Set Matches = RegEx.Execute(myKey)
               If Matches.Count > 0 Then myKey = Matches(0).value

       

      'Then, when You retry Routine1, You should get an error at "Set myVar.Value = objVar"

      • HKosova's avatar
        HKosova
        SmartBear Alumni (Retired)

        This issue can only happen in VBScript projects and is caused by specifics of the Microsoft VBScript engine. It is mentioned in VBScript Specifics here:
        https://support.smartbear.com/testcomplete/docs/scripting/specifics/vbscript.html#working-with-extensions

         

        Before VBScript starts running the script, Microsoft's parser prepares a list of all identifiers found in the script - variable names, function names, property names, etc. VBScript itself is case-insensitive, so when it encounters identifiers that only differ in the letter case, such as value and VALUE, it only stores the first found instance, in this case value.

         

        During runtime, the engine will use the "cached" spelling in place of all variations of that identifier. For example, in this script:

        Sub Test
          value = 1
          obj.Value = 2
          anotherobj.VALUE = 3
        End Sub

        all statements will actually use the spelling value.

         

        This may cause issues if the script uses some case-sensitive APIs, such as objects added by script extensions.

         

        The easiest way to see the issue is to use this script:

        Sub Test
          POSTprocessorINFO = 4
        
          WMI.PostProcessorInfo
          ' Error!
          '     Object doesn't support this property or method: 'WMI.POSTprocessorINFO'
        ' Note that the error says 'WMI.POSTprocessorINFO' even though
        ' the script uses 'WMI.PostProcessorInfo' End Sub

         

        Bottom line: If you use VBScript, use unique names or the same letter case for all your identifiers. (Or better yet, use Python or JavaScript instead. ;))