2

Once again, I try to understand why SSJS in SFMC is acting differently compared to JS.

Based on the following sample: RegExp.prototype.exec()

SSJS Example:

<script runat=server>

var str = 'table football, foosball';
var test = [
    /foo*/g,
    new RegExp(/foo*/g),
    new RegExp(/foo*/, 'g'),
    new RegExp('foo*', 'g')
];

for (var i = 0; i < test.length; i++) {
    Platform.Response.Write(i + ': ' + Platform.Function.Stringify(test[i].exec(str)) + '<br/>');
}

</script>

Output:

0: ["foo", null, null]
1: null
2: null
3: ["foo", null, null]

This is wrong based on what we normally would expect from RegExp.exec()


JS sample:

var str = 'table football, foosball';
var test = [
    /foo*/g,
    new RegExp(/foo*/g),
    new RegExp(/foo*/, 'g'),
    new RegExp('foo*', 'g')
];

for (var i = 0; i < test.length; i++) {
    console.log(i + ':' + test[i].exec(str));
}

Output:

> "0:foo"
> "1:foo"
> "2:foo"
> "3:foo"

As RegExp is stateful we should be able to do the following:

JS

var reg = /foo*/g;
var str = 'table football, foosball';

console.log(reg.exec(str))
console.log(reg.exec(str))
console.log(reg.exec(str))

Output

> Array ["foo"]
> Array ["foo"]
> null

This is as expected because each call of exec will be starting on the lastIndex due to its stateful nature.


SSJS

<script runat=server>

    var str = 'table football, foosball';
    var reg = /foo*/g;

    Platform.Response.Write(Platform.Function.Stringify(reg.exec(str)) + '<br/>');
    Platform.Response.Write(Platform.Function.Stringify(reg.exec(str)) + '<br/>');
    Platform.Response.Write(Platform.Function.Stringify(reg.exec(str)) + '<br/>');
</script>

Output

["foo", null, null]
["foo", null, null]
["foo", null, null]

Question:

What am I missing here? Why is SSJS RegExp.exec() acting so different? How can I get the same result as from JS?

1
  • 1
    This is certainly interesting. I have found most differences are because the JS Parser is built on top of .Net so perhaps its due to the translation of SSJS to .Net then back to SSJS. So maybe VB match() doesn't translate exactly like exec() does in JS, causing discrepancies. Will try to investigate and ask around and see if I can find anything to add Jul 19, 2020 at 22:58

1 Answer 1

1

This is not an answer, I am doing a stream of conscious on my findings relating to this so far. Basically it seems like the issue is definitely coming from the VB.Net parser issue as it is not default behavior of JS at all. I have a couple inquiries in to SFMC people in the hopes to get more info. Will post more here if I hear back.

  1. Last Index is not saved or at least it is not saved in the same way as in Client-side JS:

test[i].lastIndex in SSJS returns 0 every time, where inside of JS, it will return 9 (based off your example) which is correct. I have no explanation on why this is no longer stateful inside of SSJS.


  1. The returned array, if changed to string then split, has the initial index of the match as the first value, the full input string, and the returned value. All the weird null values after it in original Stringify are now gone.

Stringify(test[i].exec(str)) returns ["foo", null, null] (as you showed), but if you set it to a var, turn it into a String, use split to turn it into an array and then output it with a Stringify, it returns an extra values like: ["6", "table football | foosball", "foo"] Where the "6" is the start index of the match. (to remove the split of the comma in the string, I changed the comma to a pipe.)

example to get the above array in SSJS:

var match = test[i].exec(str);
myArray= String(match).split(',');
Write(Stringify(myArray));

  1. Index and Input on the results do not work in SSJS.

They return the following error: "str" is null which is very much not true. The str variable is correctly set and works fine in all other places. No idea why it would say it is null now. If you push in the string directly into the exec call, it then returns "exec" is null". In all honesty, none of the 'result' properties work in SSJS. It works perfectly in JS though.

var index = test[i].exec(str).index;
var index = test[i].exec('table football, foosball').index;

var input = test[i].exec(str).input;
var input = test[i].exec('table football, foosball').input;

  1. It appears that RegExp() works differently in SSJS than it does in JS. Below are the outputs based on the test array used in example.
SSJS       |     JS
/foo*/g    |  /foo*/g 
//foo*/g/  |  /foo*/g 
//foo*//   |  /foo*/g 
/foo*/     |  /foo*/g 

This pretty much leads me to believe that the RegExp function inside SSJS is pretty useless and in fact can cause more issues than benefits due to assumptions associated with it. It seems to ignore the second parameter passed in completely (g to set global, etc) and adds pre/post slashes to what you add in regardless of input...very odd behavior.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.