ES3.1 Draft: String generics
We should nail down the meaning of /\s/. Should it be the minimum (IE) or the maximum (Opera)?
The quote method needs more specification. It needs to escape a lot more characters than just single and double quotes. The basic rule is that String.prototype.quote should return a string that would be a valid string literal for that string.
For example:
"a\nb".quote() => ""a\nb""
One other way to express this is:
s == eval(s.quote())
for all strings.
Below is one implementation with unit tests
/**
- Character mappings used internally for goog.string.quote
- @private
- @type {Object} */ goog.string.jsEscapeCache_ = { '\b': '\b', '\f': '\f', '\n': '\n', '\r': '\r', '\t': '\t', '\x0B': '\x0B', // '\v' is not supported in JScript '"': '\"', ''': '\'', '\': '\\' };
/**
- Encloses the string in double quotes and escapes characters so that the
- string is a valid JS string.
- @param {string} s The string to quote.
- @return {string} The quoted string. */ goog.string.quote = function(s) { if (s.quote) { return s.quote(); } else { var sb = ['"']; for (var i = 0; i < s.length; i++) { sb[i + 1] = goog.string.escapeChar(s.charAt(i)); } sb.push('"'); return sb.join(''); } };
/**
- Takes a character and returns the escaped string for that character. For
- example escapeChar(String.fromCharCode(15)) -> "\x0E"
- @param {string} c The character to escape.
- @return {string} The escaped string for the given character. */ goog.string.escapeChar = function(c) { if (c in goog.string.jsEscapeCache_) { return goog.string.jsEscapeCache_[c]; } var rv = c; var cc = c.charCodeAt(0); if (cc > 31 && cc < 127) { rv = c; } else { // tab is 9 but handled above if (cc < 256) { rv = '\x'; if (cc < 16 || cc > 256) { rv += '0'; } } else { rv = '\u'; if (cc < 4096) { // \u1000 rv += '0'; } } rv += cc.toString(16).toUpperCase(); }
return goog.string.jsEscapeCache_[c] = rv; };
Below is a unit test for this (using JSUnit)
function testQuote() { var str = allChars(); var a; try { a = eval(goog.string.quote(str)); } catch (e) { fail('Quote failed: err ' + e.message); } assertEquals(str, a);
// empty string str = ''; try { a = eval(goog.string.quote(str)); } catch (e) { fail('Quote failed: err ' + e.message); } assertEquals(str, a);
// unicode str = allChars(0, 10000); try { a = eval(goog.string.quote(str)); } catch (e) { fail('Quote failed: err ' + e.message); } assertEquals(str, a); }
function allChars(opt_start, opt_end) { opt_start = opt_start || 0; opt_end = opt_end || 256; var rv = ''; for (var i = opt_start; i < opt_end; i++) { rv += String.fromCharCode(i); } return rv; }
2008/5/7 Pratap Lakshman (VJ#SDK) <pratapl at microsoft.com>:
On Wed, May 7, 2008 at 12:17 PM, Erik Arvidsson <erik.arvidsson at gmail.com> wrote:
The quote method needs more specification. It needs to escape a lot more characters than just single and double quotes. The basic rule is that String.prototype.quote should return a string that would be a valid string literal for that string.
For example:
"a\nb".quote() => ""a\nb""
I would expect that
"a\nb".quote()
would produce
"a\nb" (a string with 6 characters)
and that's what Firefox implements, along with a toplevel uneval that works on strings, arrays, objects, etc.. I think it would be very confusing for us to convert single newline characters to an escaped backslash and 'n'!
Having a way to escape metacharacters could be valuable, but I think much more valuable for the set of metacharacters that are meaningful to regular expressions. I think that's provided by more toolkits than .quoteQuotes, and is harder to get right.
Mike
Mike,
We are saying the same thing. Maybe it is my escaping that is confusing you. Mine also has the length 6. My example is using a JS string literal where yours does not.
I have uploaded to the wiki a draft proposales3.1:es31_stringobject.pdf to add a couple of generics to the String object. In order to retain the subset relationship with proposed ES4, these should be considered for addition to ES4 too.
I have extracted the String portion of the ES3 spec, added a rationale (with hyperlinks) at the beginning, and made relevant changes to the included section 15.5 text, with some comments added. I have tried to be mindful of compat.
pratap
From: Brendan Eich [mailto:brendan at mozilla.com] Sent: Thursday, May 01, 2008 5:21 AM To: Pratap Lakshman (VJ#SDK) Cc: es3.x-discuss at mozilla.org Subject: Re: Static generics on String
On Apr 30, 2008, at 8:58 AM, Pratap Lakshman (VJ#SDK) wrote: Yes, I did notice that these are already on String.prototype, and that they are generic. Is proposed-ES4 going to add a static method of the same name for each such prototype generic method?!
Yes.
The ES3 String.prototype methods generally specify that ToString is applied to "this" and to string arguments. Is it also the case for the String generics? If so, it would seen to limit their utility for string like wrappers or alternative string representations?
The ToString is ok if you are willing to tolerate the overhead of a copy. Alternative is to do length and indexed accesses to the wrapper, which forwards to the java.lang.String or similar. But that changes how ES1-3 are spec'ed and it's work -- and premature optimization is the root of all evil.
Is your experience that the static generic string methods have "carried their weight" in your implementations. In other words, based upon your experience would you recommend their inclusion in ES3.1?
Not for 3.1. They are cheap to implement but 3.1 has enough to do, and the String static generics are not big-bang-for-the-buck.
Is there a general rule for where we (proposed-ES4 & ES3.1) should add any new generic methods? In ES3.1 we are considering adding a "trim" and a "quote" method for Strings, and I was thinking of adding these on String.prototype (just like the other generic methods). However, the static generics proposal page suggests that they should then also be added as statics on String.
If you skip adding any static generics for 3.1, no worries.
Can you say more about quote? We've implemented it for years. Need to get it into both 3.1 and 4 to keep the subset relation.
To conform to the rest of the ES3, I shall propose adding these methods (trim and quote) to String.prototype only, and not create a parallel set of statics. Do you see any issues with this proposal? No, that sounds good. Let's just get quote on the ES4 radar. Is there a spec for it?