Recently I wrote a simple javascript code, but got a very weird behavior in Firefox and Chrome, code lists bellow:
console.log(
"sap.ui.widget.Progressbar"
.replace(/\./g, '/')
.replace("", "./resources/css/")
);
In Chrome (version 69.0.3497.100) I got expected result: "./resources/css/sap/ui/widget/Progressbar", but in Firefox (version 63.0) I get a totally different result: "sap/ui/widget/Progressbar".
Can some explain this? Is it a bug for Firefox? Thanks.
Yes, this is a bug in Spidermonkey. It has been reported and will be fixed in FF 65 if all goes well. (The bug does not occur on any other Javascript engine)
The problem is that intermediate strings (such as those resulting from calling String.prototype.replace on a string literal) more than 24 characters long are represented in Spidermonkey as ropes, while those 23 or fewer characters long are not ropes. Spidermonkey did not properly replace ropes when called with replace(''. (see function BuildFlatRopeReplacement in js/src/builtin/String.cpp)
You can reproduce the problem by calling .replace and replacing at least one character in a 24+ character string, and then calling .replace again with the empty string:
// Run on FF 64 or lower to reproduce:
// Second replacement at the beginning of the string fails:
console.log(
"a".repeat(24).replace('a', 'b').replace("", "foo")
);
// Works as expected:
console.log(
"a".repeat(23).replace('a', 'b').replace("", "foo")
);
Related
I've run into an issue of regex match not evaluating in Internet Explorer and in Firefox. It works fine in Chrome and Opera. I know Chrome is generally much more tolerant of mistakes so I suspect I've dropped the ball somewhere along the way - yet none of the online evaluation tools seem to find any errors in my expression. I'm sorry that it's such a convoluted expression but hopefully something will be easily obvious as the culprit. The expression is as follows:
keyData = data.match(/\w+\u0009\w+\u0009[\u0009]?\w+\u0009([-]?\w+|%%)[#]?\u0009([-]?\w+|%%)[#]?\u0009([-]?\w+|%%)[#]?(\u0009([-]?\w+|%%)[#]?)?(\u0009([-]?\w+|%%)[#]?)?(\u0009([-]?\w+|%%)[#]?)?\u0009\u0009\/\//g);
'data' is a text file which I am parsing with no errors. I wont post the whole file here but what I am hoping to match is something such as the following:
10 Q 1 0439 0419 -1 // CYRILLIC SMALL LETTER SHORT I, CYRILLIC CAPITAL LETTER SHORT I, <none>
I believe that when I post the string here it removes the 'u0009' characters so if you'd like to see one of the full files, I've linked one here. If there is anything more I can clarify, please let me know!
Edit:
My goal in this post is understanding not only why this is failing, but also if this expression well-formatted. After further review, it seems that it's an issue with how Internet Explorer and Firefox parse the text file. They seem to strip out the tabs and replace them with spaces. I tried to update the expression and it matches with no problems in an online validator but it still fails in IE/FF.
Edit 2
I have since updated my expression to a clearer form taking into account feedback. The issue still is persisting in IE and Firefox. It seems to be an issue with the string itself. IE won't let me match more than a single character, no matter what my expression is. For example, if the character string of the file is KEYBOARD and I try to match with /\w+/, it will just return K.
/[0-9](\w)?(\t+|\s+)\w+(\t+|\s+)[0-9](\t+|\s+)(-1|\w+#?|%%)(\t+|\s+)(-1|\w+#?|%%)(\t+|\s+)(-1|\w+#?|%%)((\t+|\s+)(-1|\w+#?|%%))?((\t+|\s+)(-1|\w+#?|%%))?((\t+|\s+)(-1|\w+#?|%%))?(\t+|\s+)\/\//g
After poking around with my regex for a while, I suspected something was wrong with the way IE was actually reading the text file as compared to Chrome. Specifically, if I had the string KEYBOARDwithin the text file and I tried to match it using /\w+/, it would simply return K in IE but in Chrome it would match the whole string KEYBOARD. I suspected IE was inserting some dead space between characters so I stepped through the first few characters of the file and printed their unicode equivalent.
for (i = 0; i < 30; i++) {
console.log(data.charCodeAt(i) + ' ' + data[i]);
}
This confirmed my suspicion and I saw u0000 pop up between each character. I'm not sure why there are NULL characters between each character but to resolve my issue I simply performed:
data = data.replace(/\u0000+/g, '');
This completely resolved my issue and I was able to parse my string like normal using the expression:
keyData = data.match(/[0-9](\w)?(\t+|\s+)\w+(\t+|\s+)[0-9](\t+|\s+)(-1|\w+#?|%%)(\t+|\s+)(-1|\w+#?|%%)(\t+|\s+)(-1|\w+#?|%%)((\t+|\s+)(-1|\w+#?|%%))?((\t+|\s+)(-1|\w+#?|%%))?((\t+|\s+)(-1|\w+#?|%%))?(\t+|\s+)\/\//g);
I'm having some javascript issues with some legacy code, since my company is attempting to upgrade to IE11 from IE8. I have a piece of javascript that finds all commas in a field and replaces it with a couple characters, it is as follows:
document.frm.txt_fieldValue[1].value =
document.frm.txt_fieldValue[1].value.replace(/,/gi, "$0");
In my code this is all on one line, however. This code works in IE8, Chrome, and Firefox. However, in IE9+, specifically IE11 (since this is what my company is upgrading to), this code doesn't replace any commas. I can get it to replace a single comma by using the following code:
document.frm.txt_fieldValue[1].value =
document.frm.txt_fieldValue[1].value.replace(",", "$0");
Because I replaced a single comma, I know my code is reached. But I have searched around and I have yet to find a solid answer. Does anyone else have this problem? If so, has anyone found a solution?
Thanks!
You need to replace it with "$$0", which after escaping will turn into a real $0. I doubt if this code ever worked properly, on any browser.
I recently fixed a bug that might help.
If your value that you were replacing was 0 -- as a value, not a string -- IE11 would only append the replacement string instead of actually replacing it.
Here's what I was working with:
buf = buf.replace( /%%TOTALAMOUNT%%/gim, "$" + parseFloat( g_UserPurchases[LCV].CurrencyValue.val() ).toFixed(2) );
This printed: "%%TOTALAMOUNT%%.00"
I fixed it by checking:
if( ( g_UserPurchases[LCV].CurrencyValue.val() == 0 ) || ( g_UserPurchases[LCV].CurrencyValue.val() === 0 ) ){
//IE fix: IE did not like the $ character and didn't replace if val = 0
buf = buf.replace( /%%TOTALAMOUNT%%/gim, "$0.00"); }
Please note: IE11 didn't replace the the dollar sign character, $. So, I used the character code instead:
$
Hope this helps!
As expected I need to encode a URI component before I call an API using it but when it hits our server somewhere along the line our backend framework (tapestry) converts spaces too early: Java URLEncoding / Decoding URL Spaces with dashes
I figured out that if I changed the URI %20 to $0020 it works. So the code below works in Chrome and Firefox and converts the % to a $00.
function furtherEncode(uriComp) {
var nonSafe = encodeURIComponent(uriComp);
return nonSafe.replace(/%/g, "$00");
}
In Internet Explorer 11 (and IE10) it doesn't do the replacement.
I have tried /\x25/g and /%/g as well as "$00" and '$00' but to no avail.
Any help would be greatly appreciated.
You need to have two dollar signs like here (tested in IE and Chrome):
"%".replace(/%/g, "$$00") /// returns "$00"
See docs here: docs
Relevant parts are defined under "Specifying a string as a parameter":
$$ | Inserts a "$".
$n | Where n or nn are decimal digits, inserts the nth parenthesized submatch string, provided the first argument was a RegExp object
This code behaves funny on Chrome (fiddle here):
try {
open('6:-=');
} catch(e) {}
First, despite the code being wrapped in a try-catch, an error is thrown:
Unable to open a window with invalid URL '%36:%04-='.
Second, extraneous characters are inserted in the URL, namely %3 and %04.
Why doesn't the try-catch intercept the error, and why does the URL have those extra characters?
The try/catch doesn't have any effect because it's not an exception. It's merely an error message printed to the console. You can proof that:
open('6:-=');
console.log(1); // logged as usual
Basically, it's just like console.error() doesn't throw an exception either, yet it prints an exception-like message to the console.
Your fiddle contains a non-printable character with ASCII code 4 in the 6:-= string after the colon, which is URL-encoded as %04 in the displayed error. In addition, the 6: part of the provided URL is interpreted as an URL scheme, which cannot start with a digit, so apparently Chrome URL-quotes the 6 as %36 as well, although such behavior is not prescribed by the RFC.
First: As pimvdb said, it's because it isn't actually an exception.
Second: %04 is an invisible character inserted by JSFiddle. %36 is the number 6 which Chrome converts to %36 when encoding it for URL scheme. Updated fiddle without %04
The following needs to remove url(' portion of string, previously returned from .css('background-image') on an element object in the DOM, which works perfectly well in Firefox, but not in Chrome.
// example value of artworkURL: url('http://somewebsite/picture.jpg')
artworkURL = artworkURL.replace(/url\(\'/g,'');
I discovered this was because Chrome removes the '' from url('picture.jpg') however, removing \' from the regular expression causes Firefox to then break, because Firefox replaced '' with "" but still understands the regular expression. Even the removal of parenthesis in the CSS causes Firefox to render "" back in.
How do I keep both browsers and their various compliance happy?
Try:
artworkURL = artworkURL.replace(/url\(['"]?/g,'');
This will remove the ' if it it present, and even takes into account browsers that might use " instead. A similar regex can be used for removing the end:
artworkURL = artworkURL.replace(/['"]?)/g,'');