Any issues executing RegExp objects in Jint?

Feb 5, 2010 at 6:19 PM

Hi all,

I'm unable to achieve the expected behavior from Javascript's RegExp.exec() function.  Specifically, take a look at the following C# unit test:

 

        [TestMethod]
        public void JintRegExpTest()
        {
            var jint = new JintEngine()
                .SetDebugMode(true)
                .DisableSecurity();
            jint.Step += (sender, info) =>
                             {
                                 Console.WriteLine(info.Locals["myRe"].Value);
                             };
            var run = jint.Run(@"var myRe = /d(b+)(d)/ig;
var myArray = myRe.exec(""cdbBdbsbz"");
return myArray");
            Console.WriteLine(run);
        }

 

 

        [TestMethod]
        public void JintRegExpTest()
        {
            var jint = new JintEngine()
                .SetDebugMode(true)
                .DisableSecurity();

            jint.Step += (sender, info) =>
                             {
// don't worry too much about this specific line Console.WriteLine(info.Locals["myRe"].Value); }; var run = jint.Run(@"var myRe = /d(b+)(d)/ig; var myArray = myRe.exec(""cdbBdbsbz""); return myArray"); Console.WriteLine(run); }

The sample javascript code can be found at the following url: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp/exec

Inspecting the "myArray" variable (by digging into its properties in QuickWatch upon a visual studio breakpoint in the anonymous function for the Step event) shows the array with the following properties:

- properties Count = 5 System.Collections.Generic.Dictionary<string,Jint.Native.Descriptor>
+ [0] {[prototype, ]} System.Collections.Generic.KeyValuePair<string,Jint.Native.Descriptor>
+ [1] {[constructor, function]} System.Collections.Generic.KeyValuePair<string,Jint.Native.Descriptor>
+ [2] {[index, 1]} System.Collections.Generic.KeyValuePair<string,Jint.Native.Descriptor>
+ [3] {[input, cdbBdbsbz]} System.Collections.Generic.KeyValuePair<string,Jint.Native.Descriptor>
+ [4] {[0, dbBd]} System.Collections.Generic.KeyValuePair<string,Jint.Native.Descriptor>

The array of matching parenthesis groups in the RegExp is missing in the myArray object.

I can access the last matching character string via the "0"-indexed value of myArray (ie: ((JsArray)info.Locals["myArray"])["0"]) but there are no array entries for the matching parenthesis groups in the RegExp.  In pure javascript, the above code would result with a myArray variable that also has the following values:

myArray[1] = "bB",
myArray[2] = "d"

Has anyone else seen such behavior?  Is it a bug in Jint or am I missing something?  I'm running larger library scripts that rely on this proper behavior of javascript's RegExp.exec() function.

Thanks for all help and I've been really impressed with what I've seen of Jint so far!!

 

 

 

Feb 5, 2010 at 8:26 PM

Me again!

Turns out the fix involved a change in JsRegExpConstructor.ExecImpl(regexp, parameters) { }

Specifically, once I replaced references to Match.Captures with Match.Groups, I achieved the correct behavior.  With brief testing on my local machine, it appeared to work as expected.

k

Feb 5, 2010 at 10:09 PM

And yet again!

So after I wrote the preceding post about the changes to correctly get the matching groups for a RegExp, I find that it's already been fixed in the svn repository located here: https://svn.evaluant.com:8443/svn/jint

During my work with achieving proper regular expression behavior, I've found a couple spots in code where I think changes are needed.  Because I'm not checking them in (I feel confident in the changes within my narrow functionality scope, do not feel confident enough in them for all use cases), I thought I'd at least chronicle places I think require changes.  I'll list them in issue/fix manner.

ISSUE:

regular expression options that are instantiated instead of created with a literal do NOT get their regexp options processed.
   ie: this worked --  var myRe = /d(b+)(d)/ig
       but not this --  var myRe = new RegExp("d(b+)(d)","ig") 

FIX:

in JsRegExpConstructor, public override JsInstance Execute(ExecutionVisitor, JsDictionaryObject, JsInstance[]), I changed the return line from:

return visitor.Return(New(parameters[0].ToString(), false, false, false));

to:

return visitor.Return(New(parameters[0].ToString(),
parameters[1].ToString().Contains("g"),
parameters[1].ToString().Contains("i"),
parameters[1].ToString().Contains("m")));

ISSUE:

The "global" behavior of regular expressions is not properly working.

FIX:

in JsRegExpConstructor, public JsInstance ExecImpl(JsRegExp, JsInstance[]), I changed the following lines:

from:

            if (regexp["global"].ToBoolean())
                i = 0;

to:

            if (!regexp["global"].ToBoolean())
                i = 0;

 

all assigments to local variable "lastIndex" after the initial assignment should be replaced with the assignment of the "lastIndex" property hanging off the regexp object:

from:

lastIndex = 0; and lastIndex = e;

to

regexp["lastIndex"] = Global.NumberClass.New(0); and regexp["lastIndex"] = Global.NumberClass.New(e);

 

Making these changes appeared to enable the global functionality of Regular Expressions.

 

            if (regexp["global"].ToBoolean())

                i = 0;

 

 

Feb 6, 2010 at 6:10 AM

K,

Thank you for this stuff. As you are working with the svn repository, could you send us two patches from your updates:
- one including the unit tests for demonstrating the issues, dor instance in the /Scripts/RegEx.js file
- one with the modifications to apply to make those unit tests pass 

Cheers,
Sebastien

Jan 3, 2012 at 7:32 PM

Any updates on this issue? Flags are not working when creating a new RegExp object.  Also the test() function for regular expressions always returns true.

Examples:

Using the regex 

var var1 = new RegExp('hi','i');

The following returns 0 as expected.

return 'hi'.search(var1);

But the following returns -1 when it should return 0.

return 'HI'.search(var1);

And the following returns true when it should return false.

var1.test('aaaa');

Mar 12, 2012 at 10:35 PM

bump on above post - I'm having trouble getting RegExp to function properly with flags - specifically case insentive and global. Any update on this one?

Mar 13, 2012 at 10:34 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Mar 26, 2012 at 2:37 PM

this bug has been fixed in 'dev' branch