Title: [131356] trunk
Revision
131356
Author
jsb...@chromium.org
Date
2012-10-15 14:22:08 -0700 (Mon, 15 Oct 2012)

Log Message

IndexedDB: Key paths should support non-ASCII identifiers
https://bugs.webkit.org/show_bug.cgi?id=98814

Reviewed by Kentaro Hara.

Source/WebCore:

Update the parser for key paths to use the unicode classes from
the IdentifierName production in ECMA-262.

Test: storage/indexeddb/keypath-basics.html

* Modules/indexeddb/IDBKeyPath.cpp:
(WebCore):
(WebCore::IDBKeyPathLexer::lexIdentifier):

LayoutTests:

Test representative characters from various Unicode character classes
as valid (or invalid) identifier lead and trailing characters.

* storage/indexeddb/keypath-basics-expected.txt:
* storage/indexeddb/resources/keypath-basics.js:
(testValidKeyPaths):

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (131355 => 131356)


--- trunk/LayoutTests/ChangeLog	2012-10-15 21:20:06 UTC (rev 131355)
+++ trunk/LayoutTests/ChangeLog	2012-10-15 21:22:08 UTC (rev 131356)
@@ -1,3 +1,17 @@
+2012-10-15  Joshua Bell  <jsb...@chromium.org>
+
+        IndexedDB: Key paths should support non-ASCII identifiers
+        https://bugs.webkit.org/show_bug.cgi?id=98814
+
+        Reviewed by Kentaro Hara.
+
+        Test representative characters from various Unicode character classes
+        as valid (or invalid) identifier lead and trailing characters.
+
+        * storage/indexeddb/keypath-basics-expected.txt:
+        * storage/indexeddb/resources/keypath-basics.js:
+        (testValidKeyPaths):
+
 2012-10-15  Mike West  <mk...@chromium.org>
 
         Console messages containing long URLs should cut at some reasonable length.

Modified: trunk/LayoutTests/storage/indexeddb/keypath-basics-expected.txt (131355 => 131356)


--- trunk/LayoutTests/storage/indexeddb/keypath-basics-expected.txt	2012-10-15 21:20:06 UTC (rev 131355)
+++ trunk/LayoutTests/storage/indexeddb/keypath-basics-expected.txt	2012-10-15 21:22:08 UTC (rev 131356)
@@ -40,6 +40,116 @@
 index = store.createIndex('name', 'foo.bar.baz')
 PASS index.keyPath is 'foo.bar.baz'
 Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '$'})
+PASS store.keyPath is '$'
+index = store.createIndex('name', '$')
+PASS index.keyPath is '$'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '_'})
+PASS store.keyPath is '_'
+index = store.createIndex('name', '_')
+PASS index.keyPath is '_'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '\u0391'})
+PASS store.keyPath is '\u0391'
+index = store.createIndex('name', '\u0391')
+PASS index.keyPath is '\u0391'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '\u0371'})
+PASS store.keyPath is '\u0371'
+index = store.createIndex('name', '\u0371')
+PASS index.keyPath is '\u0371'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '\u01C5'})
+PASS store.keyPath is '\u01C5'
+index = store.createIndex('name', '\u01C5')
+PASS index.keyPath is '\u01C5'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '\u02B0'})
+PASS store.keyPath is '\u02B0'
+index = store.createIndex('name', '\u02B0')
+PASS index.keyPath is '\u02B0'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '\u00AA'})
+PASS store.keyPath is '\u00AA'
+index = store.createIndex('name', '\u00AA')
+PASS index.keyPath is '\u00AA'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '\u16EE'})
+PASS store.keyPath is '\u16EE'
+index = store.createIndex('name', '\u16EE')
+PASS index.keyPath is '\u16EE'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '_$'})
+PASS store.keyPath is '_$'
+index = store.createIndex('name', '_$')
+PASS index.keyPath is '_$'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '__'})
+PASS store.keyPath is '__'
+index = store.createIndex('name', '__')
+PASS index.keyPath is '__'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '_\u0391'})
+PASS store.keyPath is '_\u0391'
+index = store.createIndex('name', '_\u0391')
+PASS index.keyPath is '_\u0391'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '_\u0371'})
+PASS store.keyPath is '_\u0371'
+index = store.createIndex('name', '_\u0371')
+PASS index.keyPath is '_\u0371'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '_\u01C5'})
+PASS store.keyPath is '_\u01C5'
+index = store.createIndex('name', '_\u01C5')
+PASS index.keyPath is '_\u01C5'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '_\u02B0'})
+PASS store.keyPath is '_\u02B0'
+index = store.createIndex('name', '_\u02B0')
+PASS index.keyPath is '_\u02B0'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '_\u00AA'})
+PASS store.keyPath is '_\u00AA'
+index = store.createIndex('name', '_\u00AA')
+PASS index.keyPath is '_\u00AA'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '_\u16EE'})
+PASS store.keyPath is '_\u16EE'
+index = store.createIndex('name', '_\u16EE')
+PASS index.keyPath is '_\u16EE'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '_\u0300'})
+PASS store.keyPath is '_\u0300'
+index = store.createIndex('name', '_\u0300')
+PASS index.keyPath is '_\u0300'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '_\u0903'})
+PASS store.keyPath is '_\u0903'
+index = store.createIndex('name', '_\u0903')
+PASS index.keyPath is '_\u0903'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '_\u0300'})
+PASS store.keyPath is '_\u0300'
+index = store.createIndex('name', '_\u0300')
+PASS index.keyPath is '_\u0300'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '_\u203F'})
+PASS store.keyPath is '_\u203F'
+index = store.createIndex('name', '_\u203F')
+PASS index.keyPath is '_\u203F'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '_\u200C'})
+PASS store.keyPath is '_\u200C'
+index = store.createIndex('name', '_\u200C')
+PASS index.keyPath is '_\u200C'
+Deleted all object stores.
+store = db.createObjectStore('name', {keyPath: '_\u200D'})
+PASS store.keyPath is '_\u200D'
+index = store.createIndex('name', '_\u200D')
+PASS index.keyPath is '_\u200D'
+Deleted all object stores.
 
 testInvalidKeyPaths():
 Deleted all object stores.
@@ -136,6 +246,314 @@
 PASS Exception was thrown.
 PASS code is DOMException.SYNTAX_ERR
 Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u0300'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u0300')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u0903'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u0903')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u0300'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u0300')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u203F'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u203F')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u200C'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u200C')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u200D'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u200D')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u002D'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u002D')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u0028'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u0028')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u0029'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u0029')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u00AB'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u00AB')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u00BB'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u00BB')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u0021'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u0021')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u002B'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u002B')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u00A2'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u00A2')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u005E'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u005E')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u00A6'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u00A6')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u00A0'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u00A0')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u2028'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u2028')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u2029'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u2029')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u0000'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u0000')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\u00AD'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\u00AD')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\uD800'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\uD800')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\uE000'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\uE000')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\uFFFE'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\uFFFE')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '\uFFFF'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '\uFFFF')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '_\u002D'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '_\u002D')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '_\u0028'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '_\u0028')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '_\u0029'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '_\u0029')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '_\u00AB'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '_\u00AB')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '_\u00BB'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '_\u00BB')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '_\u0021'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '_\u0021')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '_\u002B'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '_\u002B')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '_\u00A2'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '_\u00A2')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '_\u005E'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '_\u005E')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '_\u00A6'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '_\u00A6')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '_\u00A0'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '_\u00A0')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '_\u2028'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '_\u2028')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '_\u2029'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '_\u2029')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '_\u0000'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '_\u0000')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '_\u00AD'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '_\u00AD')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '_\uD800'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '_\uD800')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '_\uE000'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '_\uE000')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '_\uFFFE'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '_\uFFFE')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
+Expecting exception from db.createObjectStore('name', {keyPath: '_\uFFFF'})
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Expecting exception from db.createObjectStore('name').createIndex('name', '_\uFFFF')
+PASS Exception was thrown.
+PASS code is DOMException.SYNTAX_ERR
+Deleted all object stores.
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/storage/indexeddb/resources/keypath-basics.js (131355 => 131356)


--- trunk/LayoutTests/storage/indexeddb/resources/keypath-basics.js	2012-10-15 21:20:06 UTC (rev 131355)
+++ trunk/LayoutTests/storage/indexeddb/resources/keypath-basics.js	2012-10-15 21:22:08 UTC (rev 131356)
@@ -36,16 +36,45 @@
     testKeyPaths = [
         { keyPath: "null", storeExpected: "null", indexExpected: "'null'" },
         { keyPath: "undefined", storeExpected: "null", indexExpected: "'undefined'" },
-        { keyPath: "''", storeExpected: "''", indexExpected: "''" },
-        { keyPath: "'foo'", storeExpected: "'foo'", indexExpected: "'foo'" },
-        { keyPath: "'foo.bar.baz'", storeExpected: "'foo.bar.baz'", indexExpected: "'foo.bar.baz'" }
+        { keyPath: "''" },
+        { keyPath: "'foo'" },
+        { keyPath: "'foo.bar.baz'" },
+
+        // IdentifierStart
+        { keyPath: "'$'" },
+        { keyPath: "'_'" },
+        { keyPath: "'\\u0391'" }, // GREEK CAPITAL LETTER ALPHA (Lc)
+        { keyPath: "'\\u0371'" }, // GREEK SMALL LETTER ALPHA (Lu)
+        { keyPath: "'\\u01C5'" }, // LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON (Lt)
+        { keyPath: "'\\u02B0'" }, // MODIFIER LETTER SMALL H (Lm)
+        { keyPath: "'\\u00AA'" }, // FEMININE ORDINAL INDICATOR (Lo)
+        { keyPath: "'\\u16EE'" }, // RUNIC ARLAUG SYMBOL (Nl)
+
+        // IdentifierPart
+        { keyPath: "'_$'" },
+        { keyPath: "'__'" },
+        { keyPath: "'_\\u0391'" }, // GREEK CAPITAL LETTER ALPHA (Lc)
+        { keyPath: "'_\\u0371'" }, // GREEK SMALL LETTER ALPHA (Lu)
+        { keyPath: "'_\\u01C5'" }, // LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON (Lt)
+        { keyPath: "'_\\u02B0'" }, // MODIFIER LETTER SMALL H (Lm)
+        { keyPath: "'_\\u00AA'" }, // FEMININE ORDINAL INDICATOR (Lo)
+        { keyPath: "'_\\u16EE'" }, // RUNIC ARLAUG SYMBOL (Nl)
+        { keyPath: "'_\\u0300'" }, // COMBINING GRAVE ACCENT (Mn)
+        { keyPath: "'_\\u0903'" }, // DEVANAGARI SIGN VISARGA (Mc)
+        { keyPath: "'_\\u0300'" }, // DIGIT ZERO (Nd)
+        { keyPath: "'_\\u203F'" }, // UNDERTIE (Pc)
+        { keyPath: "'_\\u200C'" }, // ZWNJ
+        { keyPath: "'_\\u200D'" }  // ZWJ
     ];
 
     testKeyPaths.forEach(function (testCase) {
+        storeExpected = ('storeExpected' in testCase) ? testCase.storeExpected : testCase.keyPath;
+        indexExpected = ('indexExpected' in testCase) ? testCase.indexExpected : testCase.keyPath;
+
         evalAndLog("store = db.createObjectStore('name', {keyPath: " + testCase.keyPath + "})");
-        shouldBe("store.keyPath", testCase.storeExpected);
+        shouldBe("store.keyPath", storeExpected);
         evalAndLog("index = store.createIndex('name', " + testCase.keyPath + ")");
-        shouldBe("index.keyPath", testCase.indexExpected);
+        shouldBe("index.keyPath", indexExpected);
         deleteAllObjectStores(db);
     });
 
@@ -68,7 +97,69 @@
 
     debug("");
     debug("Key paths which are never valid:");
-    testKeyPaths = ["' '", "'foo '", "'foo bar'", "'foo. bar'", "'foo .bar'", "'foo..bar'", "'+foo'", "'foo%'", "'1'", "'1.0'", "[]"];
+    testKeyPaths = [
+        "' '",
+        "'foo '",
+        "'foo bar'",
+        "'foo. bar'",
+        "'foo .bar'",
+        "'foo..bar'",
+        "'+foo'",
+        "'foo%'",
+        "'1'",
+        "'1.0'",
+        "[]",
+
+        // IdentifierPart but not IdentifierStart
+        "'\\u0300'", // COMBINING GRAVE ACCENT (Mn)
+        "'\\u0903'", // DEVANAGARI SIGN VISARGA (Mc)
+        "'\\u0300'", // DIGIT ZERO (Nd)
+        "'\\u203F'", // UNDERTIE (Pc)
+        "'\\u200C'", // ZWNJ
+        "'\\u200D'", // ZWJ
+
+        // Neither IdentifierPart nor IdentifierStart
+        "'\\u002D'", // HYPHEN-MINUS (Pd)
+        "'\\u0028'", // LEFT PARENTHESIS (Ps)
+        "'\\u0029'", // RIGHT PARENTHESIS (Pe)
+        "'\\u00AB'", // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK (Pi)
+        "'\\u00BB'", // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK (Pf)
+        "'\\u0021'", // EXCLAMATION MARK (Po)
+        "'\\u002B'", // PLUS SIGN (Sm)
+        "'\\u00A2'", // CENT SIGN (Sc)
+        "'\\u005E'", // CIRCUMFLEX ACCENT (Sk)
+        "'\\u00A6'", // BROKEN BAR (So)
+        "'\\u00A0'", // NO-BREAK SPACE (Zs)
+        "'\\u2028'", // LINE SEPARATOR (Zl)
+        "'\\u2029'", // PARAGRAPH SEPARATOR (Zp)
+        "'\\u0000'", // NULL (Cc)
+        "'\\u00AD'", // SOFT HYPHEN (Cf)
+        "'\\uD800'", // Surrogate (Cs)
+        "'\\uE000'", // Private Use (Co)
+        "'\\uFFFE'", // Special
+        "'\\uFFFF'", // Special
+
+        // Neither IdentifierPart nor IdentifierStart
+        "'_\\u002D'", // HYPHEN-MINUS (Pd)
+        "'_\\u0028'", // LEFT PARENTHESIS (Ps)
+        "'_\\u0029'", // RIGHT PARENTHESIS (Pe)
+        "'_\\u00AB'", // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK (Pi)
+        "'_\\u00BB'", // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK (Pf)
+        "'_\\u0021'", // EXCLAMATION MARK (Po)
+        "'_\\u002B'", // PLUS SIGN (Sm)
+        "'_\\u00A2'", // CENT SIGN (Sc)
+        "'_\\u005E'", // CIRCUMFLEX ACCENT (Sk)
+        "'_\\u00A6'", // BROKEN BAR (So)
+        "'_\\u00A0'", // NO-BREAK SPACE (Zs)
+        "'_\\u2028'", // LINE SEPARATOR (Zl)
+        "'_\\u2029'", // PARAGRAPH SEPARATOR (Zp)
+        "'_\\u0000'", // NULL (Cc)
+        "'_\\u00AD'", // SOFT HYPHEN (Cf)
+        "'_\\uD800'", // Surrogate (Cs)
+        "'_\\uE000'", // Private Use (Co)
+        "'_\\uFFFE'", // Special
+        "'_\\uFFFF'"  // Special
+    ];
     testKeyPaths.forEach(function (keyPath) {
         evalAndExpectException("db.createObjectStore('name', {keyPath: " + keyPath + "})", "DOMException.SYNTAX_ERR");
         evalAndExpectException("db.createObjectStore('name').createIndex('name', " + keyPath + ")", "DOMException.SYNTAX_ERR");

Modified: trunk/Source/WebCore/ChangeLog (131355 => 131356)


--- trunk/Source/WebCore/ChangeLog	2012-10-15 21:20:06 UTC (rev 131355)
+++ trunk/Source/WebCore/ChangeLog	2012-10-15 21:22:08 UTC (rev 131356)
@@ -1,3 +1,19 @@
+2012-10-15  Joshua Bell  <jsb...@chromium.org>
+
+        IndexedDB: Key paths should support non-ASCII identifiers
+        https://bugs.webkit.org/show_bug.cgi?id=98814
+
+        Reviewed by Kentaro Hara.
+
+        Update the parser for key paths to use the unicode classes from
+        the IdentifierName production in ECMA-262.
+
+        Test: storage/indexeddb/keypath-basics.html
+
+        * Modules/indexeddb/IDBKeyPath.cpp:
+        (WebCore):
+        (WebCore::IDBKeyPathLexer::lexIdentifier):
+
 2012-10-15  Yael Aharon  <yael.aha...@intel.com>
 
         [EFL][WK2][Texmap] Set gl context in GraphicsContext3DPrivate

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBKeyPath.cpp (131355 => 131356)


--- trunk/Source/WebCore/Modules/indexeddb/IDBKeyPath.cpp	2012-10-15 21:20:06 UTC (rev 131355)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBKeyPath.cpp	2012-10-15 21:22:08 UTC (rev 131356)
@@ -31,6 +31,7 @@
 #include "DOMStringList.h"
 #include <wtf/ASCIICType.h>
 #include <wtf/dtoa.h>
+#include <wtf/unicode/Unicode.h>
 
 namespace WebCore {
 
@@ -84,25 +85,39 @@
     return lexIdentifier(element);
 }
 
-static inline bool isSafeIdentifierStartCharacter(UChar c)
+namespace {
+
+using namespace WTF::Unicode;
+
+// The following correspond to grammar in ECMA-262.
+const uint32_t unicodeLetter = Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other | Number_Letter;
+const uint32_t unicodeCombiningMark = Mark_NonSpacing | Mark_SpacingCombining;
+const uint32_t unicodeDigit = Number_DecimalDigit;
+const uint32_t unicodeConnectorPunctuation = Punctuation_Connector;
+const UChar ZWNJ = 0x200C;
+const UChar ZWJ = 0x200D;
+
+static inline bool isIdentifierStartCharacter(UChar c)
 {
-    return isASCIIAlpha(c) || (c == '_') || (c == '$');
+    return (category(c) & unicodeLetter) || (c == '$') || (c == '_');
 }
 
-static inline bool isSafeIdentifierCharacter(UChar c)
+static inline bool isIdentifierCharacter(UChar c)
 {
-    return isASCIIAlphanumeric(c) || (c == '_') || (c == '$');
+    return (category(c) & (unicodeLetter | unicodeCombiningMark | unicodeDigit | unicodeConnectorPunctuation)) || (c == '$') || (c == '_') || (c == ZWNJ) || (c == ZWJ);
 }
 
+} // namespace
+
 IDBKeyPathLexer::TokenType IDBKeyPathLexer::lexIdentifier(String& element)
 {
     const UChar* start = m_ptr;
-    if (m_ptr < m_end && isSafeIdentifierStartCharacter(*m_ptr))
+    if (m_ptr < m_end && isIdentifierStartCharacter(*m_ptr))
         ++m_ptr;
     else
         return TokenError;
 
-    while (m_ptr < m_end && isSafeIdentifierCharacter(*m_ptr))
+    while (m_ptr < m_end && isIdentifierCharacter(*m_ptr))
         ++m_ptr;
 
     element = String(start, m_ptr - start);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to