Search code examples
javascriptsamsung-smart-tvtizen-web-app

Regex validation returns false on Samsung Tizen TV


I am developing a SmartTV web app using JavaScript. I want to write a regular expression which validate the local mobile operator codes:

op_codes = [33, 50, 63, 66, 67, 68, 73, 93, 95, 96, 97, 98, 99]

My code works as it should in Chrome and LG webOS. But in Samsung Tizen RegExp.test returns false even though it should be true.

Code sample:

var val = '0985739341',
    op_codes = [33, 50, 63, 66, 67, 68, 73, 93, 95, 96, 97, 98, 99],
    pattern = new RegExp('^0'+'('+op_codes.join('|')+')'+'\\d{7}$');

console.log(pattern.test(val)); //Samsung Tizen output: false

Here is the screenshot of Tizen console:

Tizen console(Updated)

I can't figure out what is wrong with my code, how can I solve it?

Same code executed on Chrome and Tizen:
Tizen(left) Chrome(right) console

Same variable Chrome and Tizen:

How it can be?


Solution

  • New Answer

    Your latest screenshot (here) tells us that you have an invisible character in val. I really, really, really should have thought of that earlier. Apparently for whatever reason, whatever your source is for val, it's including an invisible character in it.

    You'll need to identify it and, ideally, figure out where it comes from and fix it; otherwise, strip it out.

    To figure out what it is, try this:

    console.log("val", val);
    Array.prototype.forEach.call(val, function(ch) {
        console.log(ch.charCodeAt(0).toString(16));
    });
    

    If it were the value it seems to be, you'd get

    val 0985739341
    30 39 38 35 37 33 39 33 34 31
    

    Live Copy:

    var val = "0985739341";
    console.log("val", val);
    console.log(Array.prototype.map.call(val, function(ch) {
        return ch.charCodeAt(0).toString(16);
    }).join(" "));

    ...but I bet you get something else. It could be any of several invisible characters — a zero-width space (U+200B), a zero-width non-joiner (U+200C), etc. Here's an example with both of those:

    var val = "0985\u200C\u200B739341";
    console.log("val", val);
    console.log(Array.prototype.map.call(val, function(ch) {
        return ch.charCodeAt(0).toString(16);
    }).join(" "));

    Once you know what it is, you can find out where it comes from and get rid of it (or strip it from the string afterward).

    Old, Probably-Incorrect Answer

    I can't figure out what is wrong with my code...

    If that screenshot is genuine, then there's nothing wrong with your code; there's a bug in the JavaScript engine being used on that device. This would appear to be one of the rare cases where the rule "select isn't broken" fails. (Would appear to be, keep being skeptical and keep double-checking yourself.)

    You'll have to experiment to see where it fails (and file an appropriate bug report) and work around it. For instance, maybe the implementation of test incorrectly ignores capture groups and so isn't applying | correctly, or new RegExp is just fundamentally broken, or... It'll take a lot of experimentation to figure it out.

    Below are your original validation (validate1) and three alternatives you might try. The second (validate2) uses a non-capturing group instead of a capturing group. They should be the same as far as test is concerned, but then again, your original code should work. :-)

    var val = '0985739341';
    var op_codes = [33, 50, 63, 66, 67, 68, 73, 93, 95, 96, 97, 98, 99];
    var val1PatternStr = '^0'+'('+op_codes.join('|')+')'+'\\d{7}$';
    var val1Pattern = new RegExp(val1PatternStr);
    var val2PatternStr = '^0'+'(?:'+op_codes.join('|')+')'+'\\d{7}$';
    var val2Pattern = new RegExp(val2PatternStr);
    
    console.log(1, validate1(val));
    console.log(2, validate2(val));
    console.log(3, validate3(val));
    console.log(4, validate4(val));
        
    function validate1(val) {
        return val1Pattern.test(val);
    }
    
    function validate2(val) {
        return val2Pattern.test(val);
    }
    
    function validate3(val) {
        return val.length === 10 &&
               val[0] == "0" &&
               op_codes.indexOf(+val.substring(1,3)) != -1 &&
               /^\d+$/.test(val.substring(3));
    }
    
    function validate4(val) {
        return val.length === 10 &&
               val[0] == "0" &&
               op_codes.indexOf(+val.substring(1,3)) != -1 &&
               sillyIsDigit(val[3]) &&
               sillyIsDigit(val[4]) &&
               sillyIsDigit(val[5]) &&
               sillyIsDigit(val[6]) &&
               sillyIsDigit(val[7]) &&
               sillyIsDigit(val[8]) &&
               sillyIsDigit(val[9]);
    }
    
    function sillyIsDigit(ch) {
        return ch >= "0" && ch <= "9";
    }

    If the JavaScript engine chokes on val[0], you'll have to change all of those [] on val to calls to charAt instead: val[0] => val.charAt(0).