Skip to content
This repository
Browse code

Monotonic key encoding/decoding is implemented.

  • Loading branch information...
commit 791c626d6c8d55b579f973a6fb980713431a41c0 1 parent aca67c6
khamza authored July 18, 2012
52  IDBCursor.js
@@ -11,7 +11,7 @@ if (window.indexedDB.polyfill)
11 11
 		this._request = request;
12 12
 		this._range = null;
13 13
 		this._gotValue = true;
14  
-		this._effectiveKey = null;
  14
+		this._effectiveKeyEncoded = null;
15 15
 	};
16 16
 
17 17
 	IDBCursor.prototype.update = function (value)
@@ -36,7 +36,7 @@ if (window.indexedDB.polyfill)
36 36
 				noOverwrite : false,
37 37
 				value : value
38 38
 			},
39  
-			me._effectiveKey);
  39
+			me._effectiveKeyEncoded);
40 40
 		});
41 41
 		return request;
42 42
 	};
@@ -64,7 +64,7 @@ if (window.indexedDB.polyfill)
64 64
 		var me = this;
65 65
 		objectStore.transaction._queueOperation(function (sqlTx, nextRequestCallback)
66 66
 		{
67  
-			objectStore._deleteRecord(sqlTx, me._effectiveKey,
  67
+			objectStore._deleteRecord(sqlTx, me._effectiveKeyEncoded,
68 68
 				function ()
69 69
 				{
70 70
 					if (request.onsuccess) request.onsuccess(util.event("success", request));
@@ -130,18 +130,16 @@ if (window.indexedDB.polyfill)
130 130
 		me._request.readyState = util.IDBRequest.LOADING;
131 131
 		tx._queueOperation(function (sqlTx, nextRequestCallback)
132 132
 		{
133  
-			var sql = ["SELECT key, value FROM [" + me.source.name + "]"];
  133
+			var sql = ["SELECT hex(key) 'key', value FROM [" + me.source.name + "]"];
134 134
 			var where = [];
135 135
 			var args = [];
136 136
 			if (filter.lower != null)
137 137
 			{
138  
-				where.push("(key >" + (filter.lowerOpen ? "" : "=") + " ?)");
139  
-				args.push(util.encodeKey(filter.lower));
  138
+				where.push("(key >" + (filter.lowerOpen ? "" : "=") + " X'" + util.encodeKey(filter.lower) + "')");
140 139
 			}
141 140
 			if (filter.upper != null)
142 141
 			{
143  
-				where.push("(key <" + (filter.upperOpen ? "" : "=") + " ?)");
144  
-				args.push(util.encodeKey(filter.upper));
  142
+				where.push("(key <" + (filter.upperOpen ? "" : "=") + " X'" + util.encodeKey(filter.upper) + "')");
145 143
 			}
146 144
 			if (where.length > 0)
147 145
 			{
@@ -157,14 +155,14 @@ if (window.indexedDB.polyfill)
157 155
 					request.readyState = util.IDBRequest.DONE;
158 156
 					if (results.rows.length < filter.count)
159 157
 					{
160  
-						me.key = me.primaryKey = me._effectiveKey = undefined;
  158
+						me.key = me.primaryKey = me._effectiveKeyEncoded = undefined;
161 159
 						if (typeof me.value !== "undefined") me.value = undefined;
162 160
 						request.result = null;
163 161
 					}
164 162
 					else
165 163
 					{
166 164
 						var found = results.rows.item(filter.count - 1);
167  
-						me._effectiveKey = found.key;
  165
+						me._effectiveKeyEncoded = found.key;
168 166
 						me.key = me.primaryKey = util.decodeKey(found.key);
169 167
 						if (typeof me.value !== "undefined") me.value = w_JSON.parse(found.value);
170 168
 						me._gotValue = true;
@@ -193,53 +191,51 @@ if (window.indexedDB.polyfill)
193 191
 			var desc = isDesc(me);
194 192
 			var objectStoreName = me.source.objectStore.name;
195 193
 			var tableName = util.indexTable(objectStoreName, me.source.name);
196  
-			var sql = ["SELECT i.key, i.primaryKey" + (withValue ? ", t.value" : ""),
  194
+			var sql = ["SELECT hex(i.key) 'key', hex(i.primaryKey) 'primaryKey'" + (withValue ? ", t.value" : ""),
197 195
 				"FROM [" + tableName + "] as i"];
198 196
 
199 197
 			if (withValue)
200 198
 			{
201 199
 				sql.push("LEFT JOIN [" + objectStoreName + "] as t ON t.Id = i.recordId");
202 200
 			}
203  
-			var where = [], args = [];
  201
+			var where = [], args = [], encoded;
204 202
 			if (filter.lower != null)
205 203
 			{
206  
-				var strLower = util.encodeKey(filter.lower);
207  
-				args.push(strLower);
  204
+				encoded = util.encodeKey(filter.lower);
208 205
 				if (filter.lowerOpen)
209 206
 				{
210  
-					where.push("(i.key > ?)");
  207
+					where.push("(i.key > X'" + encoded + "')");
211 208
 				}
212 209
 				else
213 210
 				{
214  
-					if (me._effectiveKey == null || desc)
  211
+					if (me._effectiveKeyEncoded == null || desc)
215 212
 					{
216  
-						where.push("(i.key >= ?)");
  213
+						where.push("(i.key >= X'" + encoded+ "')");
217 214
 					}
218 215
 					else
219 216
 					{
220  
-						where.push("((i.key > ?) OR (i.key = ? AND i.primaryKey > ?))");
221  
-						args.push(strLower, me._effectiveKey);
  217
+						where.push("((i.key > X'" + encoded + "') OR (i.key = X'" + encoded +
  218
+							"' AND i.primaryKey > X'" + me._effectiveKeyEncoded + "'))");
222 219
 					}
223 220
 				}
224 221
 			}
225 222
 			if (filter.upper != null)
226 223
 			{
227  
-				var strUpper = util.encodeKey(filter.upper);
228  
-				args.push(strUpper);
  224
+				encoded = util.encodeKey(filter.upper);
229 225
 				if (filter.upperOpen)
230 226
 				{
231  
-					where.push("(i.key < ?)");
  227
+					where.push("(i.key < X'" + encoded + "')");
232 228
 				}
233 229
 				else
234 230
 				{
235  
-					if (me._effectiveKey == null || !desc)
  231
+					if (me._effectiveKeyEncoded == null || !desc)
236 232
 					{
237  
-						where.push("(i.key <= ?)");
  233
+						where.push("(i.key <= X'" + encoded + "')");
238 234
 					}
239 235
 					else
240 236
 					{
241  
-						where.push("((i.key < ?) OR (i.key = ? AND i.primaryKey < ?))");
242  
-						args.push(strUpper, me._effectiveKey);
  237
+						where.push("((i.key < X'" + encoded + "') OR (i.key = X'" + encoded +
  238
+							"' AND i.primaryKey < X'" + me._effectiveKeyEncoded + "'))");
243 239
 					}
244 240
 				}
245 241
 			}
@@ -258,7 +254,7 @@ if (window.indexedDB.polyfill)
258 254
 					request.readyState = util.IDBRequest.DONE;
259 255
 					if (results.rows.length < filter.count)
260 256
 					{
261  
-						me.key = me.primaryKey = me._effectiveKey = undefined;
  257
+						me.key = me.primaryKey = me._effectiveKeyEncoded = undefined;
262 258
 						if (typeof me.value !== "undefined") me.value = undefined;
263 259
 						request.result = null;
264 260
 					}
@@ -266,7 +262,7 @@ if (window.indexedDB.polyfill)
266 262
 					{
267 263
 						var found = results.rows.item(filter.count - 1);
268 264
 						me.key = util.decodeKey(found.key);
269  
-						me._effectiveKey = found.primaryKey;
  265
+						me._effectiveKeyEncoded = found.primaryKey;
270 266
 						me.primaryKey = util.decodeKey(found.primaryKey);
271 267
 						if (typeof me.value !== "undefined") me.value = w_JSON.parse(found.value);
272 268
 						me._gotValue = true;
10  IDBDatabase.js
@@ -49,7 +49,7 @@ if (window.indexedDB.polyfill)
49 49
 		var objectStore = this._objectStores[name];
50 50
 		delete this._objectStores[name];
51 51
 		var me = this;
52  
-		var errorCallback = function (tx, sqlError)
  52
+		var errorCallback = function (_, sqlError)
53 53
 		{
54 54
 			me.objectStoreNames.push(name);
55 55
 			me._objectStores[name] = objectStore;
@@ -66,7 +66,7 @@ if (window.indexedDB.polyfill)
66 66
 
67 67
 	IDBDatabase.prototype.transaction = function (storeNames, mode)
68 68
 	{
69  
-		// TODO: 4.2.1. throw InvalidStateError if a transaction being createing within transaction callback
  69
+		// TODO: 4.2.1. throw InvalidStateError if a transaction being creating within transaction callback
70 70
 		if (storeNames instanceof Array || storeNames == null)
71 71
 		{
72 72
 			if (storeNames.length == 0) throw util.error("InvalidAccessError");
@@ -142,7 +142,7 @@ if (window.indexedDB.polyfill)
142 142
 		var objectStore = new util.IDBObjectStore(name, keyPath, autoIncrement, me._versionChangeTransaction);
143 143
 		me.objectStoreNames.push(name);
144 144
 		me._objectStores[name] = objectStore;
145  
-		var errorCallback = function (tx, sqlError)
  145
+		var errorCallback = function (_, sqlError)
146 146
 		{
147 147
 			util.arrayRemove(me.objectStoreNames, name);
148 148
 			delete me._objectStores[name];
@@ -150,9 +150,9 @@ if (window.indexedDB.polyfill)
150 150
 		me._versionChangeTransaction._queueOperation(function (sqlTx, nextRequestCallback)
151 151
 		{
152 152
 			sqlTx.executeSql("CREATE TABLE [" + name + "] (id INTEGER PRIMARY KEY AUTOINCREMENT, " +
153  
-				"key TEXT UNIQUE, value BLOB)", [], null, errorCallback);
  153
+				"key BLOB UNIQUE, value BLOB)", null, null, errorCallback);
154 154
 
155  
-			sqlTx.executeSql("CREATE INDEX INDEX_" + name + "_key ON [" + name + "] (key)", [], null, errorCallback);
  155
+			sqlTx.executeSql("CREATE INDEX INDEX_" + name + "_key ON [" + name + "] (key)", null, null, errorCallback);
156 156
 
157 157
 			sqlTx.executeSql("INSERT INTO " + indexedDB.SCHEMA_TABLE +
158 158
 				" (type, name, keyPath, autoInc) VALUES ('table', ?, ?, ?)",
22  IDBFactory.js
@@ -5,6 +5,7 @@ if (window.indexedDB.polyfill)
5 5
 
6 6
 	indexedDB.open = function (name, version)
7 7
 	{
  8
+		console.group
8 9
 		if (arguments.length == 2 && version == undefined) throw util.error("TypeError");
9 10
 		if (version !== undefined)
10 11
 		{
@@ -168,24 +169,30 @@ if (window.indexedDB.polyfill)
168 169
 	// IDBFactory.deleteDatabase
169 170
 	indexedDB.deleteDatabase = function (name)
170 171
 	{
  172
+		console.groupCollapsed("indexedDB.deleteDatabase('%s')", name);
171 173
 		// INFO: There is no way to delete database in Web SQL Database API.
172 174
 		var database = getOriginDatabase(name);
173 175
 		database.deletePending = true;
174 176
 		var request = new util.IDBOpenDBRequest(null);
175 177
 		util.async(function()
176 178
 		{
  179
+			console.log("deleteDatabase async started.");
177 180
 			request.readyState = util.IDBRequest.DONE;
178 181
 			var sqldb = openSqlDB(name);
179 182
 			if (sqldb.version == "")
180 183
 			{
  184
+				console.log("Database deleted succesfully. (No such database was found)");
  185
+				console.groupEnd();
181 186
 				database.deletePending = false;
182 187
 				if (request.onsuccess) request.onsuccess(util.event("success", request));
183 188
 			}
184 189
 			else
185 190
 			{
  191
+				console.log("Deleting existing database");
186 192
 				fireVersionChangeEvent(request, name, parseInt(sqldb.version), null);
187 193
 				util.wait(function ()
188 194
 					{
  195
+						console.log("Waiting %d connection to be closed", database.connections.length);
189 196
 						return database.connections.length == 0;
190 197
 					},
191 198
 					function ()
@@ -245,12 +252,14 @@ if (window.indexedDB.polyfill)
245 252
 			var conn = database.connections[i];
246 253
 			if (conn._closePending) continue;
247 254
 
  255
+			console.log("Open connection found, firing versionchange event on them.");
248 256
 			anyOpenConnection = true;
249 257
 			var event = new util.IDBVersionChangeEvent("versionchange", request, oldVersion, newVersion);
250 258
 			if (conn.onversionchange) conn.onversionchange(event);
251 259
 		}
252 260
 		if (anyOpenConnection)
253 261
 		{
  262
+			console.log("Open connection found, firing onblocked event.");
254 263
 			var event = new util.IDBVersionChangeEvent("blocked", request, oldVersion, newVersion);
255 264
 			if (request.onblocked) request.onblocked(event);
256 265
 		}
@@ -258,32 +267,39 @@ if (window.indexedDB.polyfill)
258 267
 
259 268
 	function deleteDatabase(request, sqldb, database)
260 269
 	{
  270
+		console.log("Setting sql database version %d to empty.", sqldb.version);
261 271
 		sqldb.changeVersion(sqldb.version, "",
262 272
 			function (sqlTx)
263 273
 			{
  274
+				console.log("Selecting all tables and indexes from schema table.");
264 275
 				sqlTx.executeSql("SELECT a.type, a.name, b.name 'table' FROM " + indexedDB.SCHEMA_TABLE +
265 276
 					" a LEFT JOIN " + indexedDB.SCHEMA_TABLE + " b ON a.type = 'index' AND a.tableId = b.Id",
266 277
 					null,
267  
-					function (tx, results)
  278
+					function (sqlTx, results)
268 279
 					{
269 280
 						var name;
270 281
 						for (var i = 0; i < results.rows.length; i++)
271 282
 						{
272 283
 							var item = results.rows.item(i);
273 284
 							name = item.type == 'table' ? item.name : util.indexTable(item.table, item.name);
274  
-							tx.executeSql("DROP TABLE [" + name + "]");
  285
+							console.log("Dropping table %s.", name);
  286
+							sqlTx.executeSql("DROP TABLE [" + name + "]");
275 287
 						}
276  
-						tx.executeSql("DROP TABLE " + indexedDB.SCHEMA_TABLE);
  288
+						console.log("Dropping schema table.");
  289
+						sqlTx.executeSql("DROP TABLE " + indexedDB.SCHEMA_TABLE);
277 290
 					});
278 291
 			},
279 292
 			function (sqlError)
280 293
 			{
  294
+				console.error("Database (version %d) deletion failed.", sqldb.version, sqlError);
281 295
 				database.deletePending = false;
282 296
 				request.error = sqlError;
283 297
 				if (request.onerror) request.onerror(util.event("error", request));
284 298
 			},
285 299
 			function ()
286 300
 			{
  301
+				console.log("Database deleted successfully.");
  302
+				console.groupEnd();
287 303
 				database.deletePending = false;
288 304
 				if (request.onsuccess) request.onsuccess(util.event("success", request));
289 305
 			});
52  IDBIndex.js
@@ -23,27 +23,23 @@ if (window.indexedDB.polyfill)
23 23
 
24 24
 	IDBIndex.prototype.get = function (key)
25 25
 	{
26  
-		key = util.validateKeyOrRange(key);
  26
+		var encodedKeyOrRange = util.validateKeyOrRange(key);
27 27
 		var request = new util.IDBRequest(this);
28 28
 		var me = this;
29 29
 		this.objectStore.transaction._queueOperation(function (sqlTx, nextRequestCallback)
30 30
 		{
31 31
 			var sql = ["SELECT s.value FROM [" + util.indexTable(me) + "] AS i INNER JOIN"];
32  
-			sql.push("[" + me.objectStore.name + "] AS s ON s.id = i.recordId")
33  
-			var args = [];
34  
-			if (key instanceof util.IDBKeyRange)
  32
+			sql.push("[" + me.objectStore.name + "] AS s ON s.id = i.recordId");
  33
+			if (encodedKeyOrRange instanceof util.IDBKeyRange)
35 34
 			{
36  
-				var filter = key._getSqlFilter("i.key");
37  
-				sql.push("WHERE", filter.sql);
38  
-				args = filter.args;
  35
+				sql.push("WHERE", encodedKeyOrRange._getSqlFilter("i.key"));
39 36
 			}
40  
-			else if (key != null)
  37
+			else if (encodedKeyOrRange != null)
41 38
 			{
42  
-				sql.push("WHERE (i.key = ?)");
43  
-				args.push(key);
  39
+				sql.push("WHERE (i.key = X'" + encodedKeyOrRange + "')");
44 40
 			}
45 41
 			sql.push("ORDER BY i.key, i.primaryKey LIMIT 1");
46  
-			sqlTx.executeSql(sql.join(" "), args,
  42
+			sqlTx.executeSql(sql.join(" "), null,
47 43
 				function (_, results)
48 44
 				{
49 45
 					request.result = results.rows.length > 0 ? w_JSON.parse(results.rows.item(0).value) : undefined;
@@ -62,26 +58,22 @@ if (window.indexedDB.polyfill)
62 58
 
63 59
 	IDBIndex.prototype.getKey = function (key)
64 60
 	{
65  
-		key = util.validateKeyOrRange(key);
  61
+		var encodedKeyOrRange = util.validateKeyOrRange(key);
66 62
 		var request = new util.IDBRequest(this);
67 63
 		var me = this;
68 64
 		this.objectStore.transaction._queueOperation(function (sqlTx, nextRequestCallback)
69 65
 		{
70  
-			var sql = ["SELECT primaryKey FROM [" + util.indexTable(me) + "]"];
71  
-			var args = [];
72  
-			if (key instanceof util.IDBKeyRange)
  66
+			var sql = ["SELECT hex(primaryKey) 'primaryKey' FROM [" + util.indexTable(me) + "]"];
  67
+			if (encodedKeyOrRange instanceof util.IDBKeyRange)
73 68
 			{
74  
-				var filter = key._getSqlFilter();
75  
-				sql.push("WHERE", filter.sql);
76  
-				args = filter.args;
  69
+				sql.push("WHERE", encodedKeyOrRange._getSqlFilter());
77 70
 			}
78  
-			else if (key != null)
  71
+			else if (encodedKeyOrRange != null)
79 72
 			{
80  
-				sql.push("WHERE (key = ?)");
81  
-				args.push(key);
  73
+				sql.push("WHERE (key = X'" + encodedKeyOrRange + "')");
82 74
 			}
83 75
 			sql.push("LIMIT 1");
84  
-			sqlTx.executeSql(sql.join(" "), args,
  76
+			sqlTx.executeSql(sql.join(" "), null,
85 77
 				function (_, results)
86 78
 				{
87 79
 					request.result = results.rows.length > 0 ?
@@ -101,25 +93,21 @@ if (window.indexedDB.polyfill)
101 93
 
102 94
 	IDBIndex.prototype.count = function (key)
103 95
 	{
104  
-		key = util.validateKeyOrRange(key);
  96
+		var encodedKeyOrRange = util.validateKeyOrRange(key);
105 97
 		var request = new util.IDBRequest(this);
106 98
 		var me = this;
107 99
 		this.objectStore.transaction._queueOperation(function (sqlTx, nextRequestCallback)
108 100
 		{
109 101
 			var sql = ["SELECT COUNT(recordId) AS 'count' FROM [" + util.indexTable(me) + "]"];
110  
-			var args = [];
111  
-			if (key instanceof util.IDBKeyRange)
  102
+			if (encodedKeyOrRange instanceof util.IDBKeyRange)
112 103
 			{
113  
-				var filter = key._getSqlFilter();
114  
-				sql.push("WHERE", filter.sql);
115  
-				args = filter.args;
  104
+				sql.push("WHERE", encodedKeyOrRange._getSqlFilter());
116 105
 			}
117  
-			else if (key != null)
  106
+			else if (encodedKeyOrRange != null)
118 107
 			{
119  
-				sql.push("WHERE (key = ?)");
120  
-				args.push(key);
  108
+				sql.push("WHERE (key = X'" + encodedKeyOrRange + "')");
121 109
 			}
122  
-			sqlTx.executeSql(sql.join(" "), args,
  110
+			sqlTx.executeSql(sql.join(" "), null,
123 111
 				function (_, results)
124 112
 				{
125 113
 					request.result = results.rows.item(0).count;
21  IDBKeyRange.js
@@ -50,32 +50,25 @@ if (window.indexedDB.polyfill)
50 50
 	IDBKeyRange.prototype._getSqlFilter = function (keyColumnName)
51 51
 	{
52 52
 		if (keyColumnName == undefined) keyColumnName = "key";
53  
-
54  
-		var sql = [], args = [];
55  
-		var hasLower = this.lower != null, hasUpper = this.upper != null;
56  
-
  53
+		var sql = [], hasLower = this.lower != null, hasUpper = this.upper != null;
57 54
 		if (this.lower == this.upper)
58 55
 		{
59  
-			sql.push("(" + keyColumnName + " = ?)");
60  
-			args = [this.lower];
  56
+			sql.push("(" + keyColumnName + " = X'" + util.encodeKey(this.lower) + "')");
61 57
 		}
62 58
 		else
63 59
 		{
64 60
 			if (hasLower)
65 61
 			{
66  
-				sql.push("(? <" + (this.lowerOpen ? "" : "=") + " " + keyColumnName + ")");
67  
-				args.push(util.encodeKey(this.lower));
  62
+				sql.push("(X'" + util.encodeKey(this.lower) + "' <" +
  63
+					(this.lowerOpen ? "" : "=") + " " + keyColumnName + ")");
68 64
 			}
69 65
 			if (hasUpper)
70 66
 			{
71  
-				sql.push("(" + keyColumnName + " <" + (this.upperOpen ? "" : "=") + " ?)");
72  
-				args.push(util.encodeKey(this.upper));
  67
+				sql.push("(" + keyColumnName + " <" +
  68
+					(this.upperOpen ? "" : "=") + " X'" + util.encodeKey(this.upper) +"')");
73 69
 			}
74 70
 		}
75  
-		return { sql : sql.join(" AND "), args : args };
  71
+		return sql.join(" AND ");
76 72
 	};
77 73
 
78  
-	// Utils
79  
-	var w_JSON = window.JSON;
80  
-
81 74
 }(window, window.indexedDB.util));
95  IDBObjectStore.js
@@ -46,7 +46,7 @@ if (window.indexedDB.polyfill)
46 46
 
47 47
 	function validateObjectStoreKey(keyPath, autoIncrement, value, key)
48 48
 	{
49  
-		var key = key, str;
  49
+		var key = key, encodedKey;
50 50
 		if (keyPath != null)
51 51
 		{
52 52
 			if (key != null) throw util.error("DataError");
@@ -84,7 +84,7 @@ if (window.indexedDB.polyfill)
84 84
 					if (key == null)
85 85
 					{
86 86
 						key = currentNo;
87  
-						encodedKey = key.toString();
  87
+						encodedKey = util.encodeKey(key);
88 88
 						if (me.keyPath != null)
89 89
 						{
90 90
 							assignKeyToValue(context.value, me.keyPath, key);
@@ -121,7 +121,7 @@ if (window.indexedDB.polyfill)
121 121
 					// TODO: error
122 122
 				}
123 123
 			},
124  
-			function (sqlTx, sqlError)
  124
+			function (_, sqlError)
125 125
 			{
126 126
 				// TODO: error
127 127
 			});
@@ -203,26 +203,26 @@ if (window.indexedDB.polyfill)
203 203
 		return encodedKey;
204 204
 	}
205 205
 
206  
-	function storeIndex(context, index, strKey, isLast)
  206
+	function storeIndex(context, index, encodedKey, isLast)
207 207
 	{
208 208
 		var indexTable = util.indexTable(index.objectStore.name, index.name);
209 209
 
210 210
 		var sql = ["INSERT INTO", indexTable, "(recordId, key, primaryKey)"];
211 211
 		var args = [];
212  
-		if (index.multiEntry && (strKey instanceof Array))
  212
+		if (index.multiEntry && (encodedKey instanceof Array))
213 213
 		{
214 214
 			var select = [];
215  
-			for (var i = 0; i < strKey.length; i++)
  215
+			for (var i = 0; i < encodedKey.length; i++)
216 216
 			{
217  
-				sql.push("SELECT ?, ?, ?");
218  
-				args.push(context.recordId, strKey[i], context.primaryKey);
  217
+				sql.push("SELECT ?, X'" + encodedKey[i] + "', X'" + context.primaryKeyEncoded + "'");
  218
+				args.push(context.recordId);
219 219
 			}
220 220
 			sql.push(select.join(" UNION ALL "))
221 221
 		}
222 222
 		else
223 223
 		{
224  
-			sql.push("VALUES (?, ?, ?)");
225  
-			args.push(context.recordId, strKey, context.primaryKey);
  224
+			sql.push("VALUES (?, X'" + encodedKey + "', X'" + context.primaryKeyEncoded +"')");
  225
+			args.push(context.recordId);
226 226
 		}
227 227
 		var request = context.request;
228 228
 		context.sqlTx.executeSql(sql.join(" "), args,
@@ -270,22 +270,19 @@ if (window.indexedDB.polyfill)
270 270
 
271 271
 	IDBObjectStore.prototype.get = function (key)
272 272
 	{
273  
-		key = util.validateKeyOrRange(key);
  273
+		var encodedKeyOrRange = util.validateKeyOrRange(key);
274 274
 		var request = new util.IDBRequest(this);
275 275
 		var me = this;
276 276
 		me.transaction._queueOperation(function (sqlTx, nextRequestCallback)
277 277
 		{
278 278
 			var where = "", args = [];
279  
-			if (key instanceof util.IDBKeyRange)
  279
+			if (encodedKeyOrRange instanceof util.IDBKeyRange)
280 280
 			{
281  
-				var filter = key._getSqlFilter();
282  
-				where = "WHERE " + filter.sql;
283  
-				args = filter.args;
  281
+				where = "WHERE " + encodedKeyOrRange._getSqlFilter();
284 282
 			}
285  
-			else if (key != null)
  283
+			else if (encodedKeyOrRange != null)
286 284
 			{
287  
-				where = "WHERE (key = ?)";
288  
-				args.push(key);
  285
+				where = "WHERE (key = X'" + encodedKeyOrRange + "')";
289 286
 			}
290 287
 
291 288
 			sqlTx.executeSql("SELECT [value] FROM [" + me.name + "] " + where +" LIMIT 1", args,
@@ -404,22 +401,19 @@ if (window.indexedDB.polyfill)
404 401
 
405 402
 	IDBObjectStore.prototype.count = function (key)
406 403
 	{
407  
-		key = util.validateKeyOrRange(key);
  404
+		var encodedKeyOrRange = util.validateKeyOrRange(key);
408 405
 		var request = new util.IDBRequest(this);
409 406
 		var me = this;
410 407
 		this.transaction._queueOperation(function (sqlTx, nextRequestCallback)
411 408
 		{
412 409
 			var where = "", args = [];
413  
-			if (key instanceof util.IDBKeyRange)
  410
+			if (encodedKeyOrRange instanceof util.IDBKeyRange)
414 411
 			{
415  
-				var filter = key._getSqlFilter();
416  
-				where = "WHERE " + filter.sql;
417  
-				args = filter.args;
  412
+				where = "WHERE " + encodedKeyOrRange._getSqlFilter();
418 413
 			}
419  
-			else if (key != null)
  414
+			else if (encodedKeyOrRange != null)
420 415
 			{
421  
-				where = "WHERE (key = ?)";
422  
-				args.push(key);
  416
+				where = "WHERE (key = X'" + encodedKeyOrRange + "')";
423 417
 			}
424 418
 			sqlTx.executeSql("SELECT COUNT(id) AS 'count' FROM [" + me.name + "] " + where, args,
425 419
 				function (_, results)
@@ -438,32 +432,29 @@ if (window.indexedDB.polyfill)
438 432
 		return request;
439 433
 	};
440 434
 
441  
-	IDBObjectStore.prototype._deleteRecord = function (sqlTx, strKeyOrRange, onsuccess, onerror)
  435
+	IDBObjectStore.prototype._deleteRecord = function (sqlTx, encodedKeyOrRange, onsuccess, onerror)
442 436
 	{
443 437
 		var objectStore = this;
444  
-		var sql, where, args = [];
445  
-		if (strKeyOrRange instanceof util.IDBKeyRange)
  438
+		var sql, where;
  439
+		if (encodedKeyOrRange instanceof util.IDBKeyRange)
446 440
 		{
447  
-			var filter = strKeyOrRange._getSqlFilter();
448  
-			where = "WHERE " + filter.sql;
449  
-			args = filter.args;
  441
+			where = "WHERE " + encodedKeyOrRange._getSqlFilter();
450 442
 		}
451 443
 		else
452 444
 		{
453  
-			where = "WHERE (key = ?)";
454  
-			args.push(strKeyOrRange);
  445
+			where = "WHERE (key = X'" + encodedKeyOrRange + "')";
455 446
 		}
456 447
 		for (var indexName in objectStore._indexes)
457 448
 		{
458 449
 			var index = objectStore._indexes[indexName];
459 450
 			sql = ["DELETE FROM [" + util.indexTable(objectStore.name, index.name) + "]"];
460  
-			if (args.length > 0)
  451
+			if (where)
461 452
 			{
462 453
 				sql.push("WHERE recordId IN (SELECT id FROM [" + objectStore.name + "]", where + ")");
463 454
 			}
464  
-			sqlTx.executeSql(sql.join(" "), args, null, onerror);
  455
+			sqlTx.executeSql(sql.join(" "), null, null, onerror);
465 456
 		}
466  
-		sqlTx.executeSql("DELETE FROM [" + objectStore.name + "] " + where, args, onsuccess, onerror);
  457
+		sqlTx.executeSql("DELETE FROM [" + objectStore.name + "] " + where, null, onsuccess, onerror);
467 458
 	};
468 459
 
469 460
 	IDBObjectStore.prototype._insertOrReplaceRecord = function (context, encodedKey)
@@ -481,17 +472,17 @@ if (window.indexedDB.polyfill)
481 472
 		}
482 473
 		var me = this;
483 474
 		var encodedValue = w_JSON.stringify(context.value);
484  
-		context.sqlTx.executeSql("INSERT INTO [" + me.name + "] (key, value) VALUES (?, ?)",
485  
-			[encodedKey, encodedValue],
  475
+		context.sqlTx.executeSql("INSERT INTO [" + me.name + "] (key, value) VALUES (X'" + encodedKey + "', ?)",
  476
+			[encodedValue],
486 477
 			function (sqlTx, results)
487 478
 			{
488 479
 				context.objectStore = me;
489 480
 				context.sqlTx = sqlTx;
490  
-				context.primaryKey = encodedKey;
  481
+				context.primaryKeyEncoded = encodedKey;
491 482
 				context.recordId = results.insertId;
492 483
 				storeIndexes(context);
493 484
 			},
494  
-			function (sqlTx, sqlError)
  485
+			function (_, sqlError)
495 486
 			{
496 487
 				// TODO: proper error handling
497 488
 				request.error = util.error("ConstraintError");
@@ -521,8 +512,8 @@ if (window.indexedDB.polyfill)
521 512
 		};
522 513
 		me.transaction._queueOperation(function (sqlTx, nextRequestCallback)
523 514
 		{
524  
-			sqlTx.executeSql("CREATE TABLE " + util.indexTable(me.name, name) + " (recordId INTEGER, key TEXT" +
525  
-				(unique ? " UNIQUE" : "") + ", primaryKey TEXT)", null, null, errorCallback);
  515
+			sqlTx.executeSql("CREATE TABLE " + util.indexTable(me.name, name) + " (recordId INTEGER, key BLOB" +
  516
+				(unique ? " UNIQUE" : "") + ", primaryKey BLOB)", null, null, errorCallback);
526 517
 
527 518
 			sqlTx.executeSql("INSERT INTO " + indexedDB.SCHEMA_TABLE +
528 519
 				" (name, type, keyPath, tableId, [unique], multiEntry) VALUES (?, 'index', ?, " +
@@ -530,7 +521,7 @@ if (window.indexedDB.polyfill)
530 521
 				[name, w_JSON.stringify(keyPath), me.name, unique ? 1 : 0, multiEntry ? 1 : 0],
531 522
 				null, errorCallback);
532 523
 
533  
-			sqlTx.executeSql("SELECT id, key, value FROM [" + me.name + "]", null,
  524
+			sqlTx.executeSql("SELECT id, hex(key) 'key', value FROM [" + me.name + "]", null,
534 525
 				function (sqlTx, results)
535 526
 				{
536 527
 					if (results.rows.length == 0) return;
@@ -540,21 +531,21 @@ if (window.indexedDB.polyfill)
540 531
 					for (var i = 0; i < results.rows.length; i++)
541 532
 					{
542 533
 						var item = results.rows.item(i);
543  
-						var strKey = getValidIndexKeyString(index, w_JSON.parse(item.value));
544  
-						if (strKey == null) continue;
  534
+						var encodedKey = getValidIndexKeyString(index, w_JSON.parse(item.value));
  535
+						if (encodedKey == null) continue;
545 536
 
546  
-						if (index.multiEntry && (strKey instanceof Array))
  537
+						if (index.multiEntry && (encodedKey instanceof Array))
547 538
 						{
548  
-							for (var j = 0; j < strKey.length; j++)
  539
+							for (var j = 0; j < encodedKey.length; j++)
549 540
 							{
550  
-								select.push("SELECT ?, ?, ?");
551  
-								args.push(item.id, strKey[j], item.key);
  541
+								select.push("SELECT ?, X'" + encodedKey[j] + "', X'" + item.key + "'");
  542
+								args.push(item.id);
552 543
 							}
553 544
 						}
554 545
 						else
555 546
 						{
556  
-							select.push("SELECT ?, ?, ?");
557  
-							args.push(item.id, strKey, item.key);
  547
+							select.push("SELECT ?, X'" + encodedKey + "', X'" + item.key + "'");
  548
+							args.push(item.id);
558 549
 						}
559 550
 					}
560 551
 					sql.push(select.join(" UNION ALL "));
4  IDBRequest.js
... ...
@@ -1,5 +1,5 @@
1 1
 if (window.indexedDB.polyfill)
2  
-(function(window, indexedDB, util, undefined)
  2
+(function(window, util, undefined)
3 3
 {
4 4
 	var IDBRequest = util.IDBRequest = window.IDBRequest = function(source)
5 5
 	{
@@ -23,4 +23,4 @@ if (window.indexedDB.polyfill)
23 23
 	IDBOpenDBRequest.prototype = new IDBRequest();
24 24
 	IDBOpenDBRequest.prototype.constructor = IDBOpenDBRequest;
25 25
 
26  
-}(window, window.indexedDB, window.indexedDB.util));
  26
+}(window, window.indexedDB.util));
3  IDBTransaction.js
@@ -58,8 +58,7 @@ if (window.indexedDB.polyfill)
58 58
 			}*/
59 59
 			return;
60 60
 		}
61  
-		operation =  me._requests[operationIndex];
62  
-		operation(sqlTx, function ()
  61
+		me._requests[operationIndex](sqlTx, function ()
63 62
 		{
64 63
 			performOperation(me, sqlTx, operationIndex + 1);
65 64
 		});
4  README
@@ -4,13 +4,11 @@ A. Unit Test.
4 4
 
5 5
 To run unit tests open index.html in target browser. To verify unit tests against Firefox's native implementation of IndexedDB API, open the same page through web (http) server. Because, otherwise Firefox does not let to create IndexedDB databases under localhost origin.
6 6
 
7  
-Tests sometimes may fail due to their incompleteness in development. Particularly, QUnit's execution of asynchronous code needs to be wrapped by stop-start sign posts correctly and there must be one-to-one correspondence between all 'stops' and 'starts' in the code. However, sometimes it is not easy to foresee which async code get executed at the very end, 'start' command may be executed too early leaving other async code with unit tests to be left out of a test scope. This results test failures also affects to subsequent tests with outcomes like databases left unclosed or current test's 'stop' stops the 'start' from previous unsuccessful test, thus leaving current closing 'start' without a match.
8  
-
9 7
 B. Useful Resources.
10 8
 
11 9
 1) Test suits http://w3c-test.org/webapps/IndexedDB/.
12 10
 
13  
-Among test suits from w3c-test.org/webapps/IndexedDB/tests/submissions/Microsoft/ the following are failing: idbobjectstore_count2 & index_sort_order & objectstore_keyorder (lacking monotonic encoding), idbobjectstore_get3 (lacking Date support). In sum 4 tests failed out of 107. Last Update: Jule 9, 2012.
  11
+Among test suits from w3c-test.org/webapps/IndexedDB/tests/submissions/Microsoft/ the following are failing: idbobjectstore_get3 (JSON lacks Date support). In sum 4 tests failed out of 107. Last Update: Jule 9, 2012.
14 12
 
15 13
 
16 14
 2) Mozilla IndexedDB implementation: http://hg.mozilla.org/mozilla-central/file/895e12563245/dom/indexedDB/ and http://people.mozilla.org/~jcranmer2/c-ccov-js/mozilla/dom/indexedDB/.
34  indexedDB.init.js
@@ -37,6 +37,7 @@
37 37
 
38 38
 		this.error = function (name, message, innerError)
39 39
 		{
  40
+			console.gro
40 41
 			return {
41 42
 				name : name,
42 43
 				message : message,
@@ -118,14 +119,15 @@
118 119
 			return key;
119 120
 		};
120 121
 
121  
-		this.validateKeyOrRange = function (encodedKey)
  122
+		this.validateKeyOrRange = function (key)
122 123
 		{
123  
-			if (!(encodedKey instanceof this.IDBKeyRange))
  124
+			if (key == null) return null;
  125
+			if (!(key instanceof this.IDBKeyRange))
124 126
 			{
125  
-				encodedKey = this.encodeKey(encodedKey);
126  
-				if (encodedKey === null) throw this.error("DataError");
  127
+				key = this.encodeKey(key);
  128
+				if (key === null) throw this.error("DataError");
127 129
 			}
128  
-			return encodedKey;
  130
+			return key;
129 131
 		};
130 132
 
131 133
 		this.wait = function (conditionFunc, bodyFunc, async)
@@ -177,4 +179,26 @@
177 179
 	// Cached
178 180
 	var w_setTimeout = window.setTimeout;
179 181
 
  182
+	// Temp
  183
+	var db = openDatabase("__TEMP__32D0E022D11311E1B4DD4EB66188709B", "", null, null);
  184
+	db.transaction(function (sqlTx)
  185
+	{
  186
+		var exec = sqlTx.constructor.prototype.executeSql;
  187
+		sqlTx.constructor.prototype.executeSql = function (sql, args, callback, errorCallback)
  188
+		{
  189
+			console.log("[SQL]: %s; args: %o", sql, args);
  190
+			exec.call(this, sql, args,
  191
+				function (sqlTx, results)
  192
+				{
  193
+					if (callback) callback(sqlTx, results);
  194
+				},
  195
+				function (sqlTx, sqlError)
  196
+				{
  197
+					console.error("[SQL Error]: ", sqlError);
  198
+					if (errorCallback) errorCallback(sqlTx, sqlError);
  199
+				})
  200
+		}
  201
+	});
  202
+
  203
+
180 204
 }(window));
157  key.js
@@ -27,7 +27,7 @@
27 27
  Chars (3FFF+80) - FFFF         are encoded as 11xxxxxx xxxxxxxx xx000000
28 28
 
29 29
  This ensures that the first byte is never encoded as 0, which means that the
30  
- string terminator (per basic-stategy table) sorts before any character.
  30
+ string terminator (per basic-strategy table) sorts before any character.
31 31
  The reason that (3FFF+80) - FFFF is encoded "shifted up" 6 bits is to maximize
32 32
  the chance that the last character is 0. See below for why.
33 33
 
@@ -67,7 +67,7 @@
67 67
 
68 68
  We could use a much higher number than 3 at no complexity or performance cost,
69 69
  however it seems unlikely that it'll make a practical difference, and the low
70  
- limit makes testing eaiser.
  70
+ limit makes testing easier.
71 71
 
72 72
 
73 73
  As a final optimization we do a post-encoding step which drops all 0s at the
@@ -93,12 +93,12 @@ if (window.indexedDB.polyfill)
93 93
 
94 94
 	util.encodeKey = function (key)
95 95
 	{
96  
-		var stack = [key], buffer = [], type = 0, dataType, obj, tmp;
  96
+		var stack = [key], writer = new HexStringWriter(), type = 0, dataType, obj;
97 97
 		while ((obj = stack.pop()) !== undefined)
98 98
 		{
99 99
 			if (type % 4 === 0 && type + TYPE_ARRAY > MAX_TYPE_BYTE_SIZE)
100 100
 			{
101  
-				buffer.push(type);
  101
+				writer.write(type);
102 102
 				type = 0;
103 103
 			}
104 104
 			dataType = typeof obj;
@@ -114,35 +114,35 @@ if (window.indexedDB.polyfill)
114 114
 				}
115 115
 				else
116 116
 				{
117  
-					buffer.push(type);
  117
+					writer.write(type);
118 118
 				}
119 119
 			}
120 120
 			else if (dataType === "number")
121 121
 			{
122 122
 				type += TYPE_NUMBER;
123  
-				buffer.push(type);
124  
-				encodeNumber(buffer, obj);
  123
+				writer.write(type);
  124
+				encodeNumber(writer, obj);
125 125
 			}
126 126
 			else if (obj instanceof Date)
127 127
 			{
128 128
 				type += TYPE_DATE;
129  
-				buffer.push(type);
130  
-				encodeNumber(buffer, obj.valueOf());
  129
+				writer.write(type);
  130
+				encodeNumber(writer, obj.valueOf());
131 131
 			}
132 132
 			else if (dataType === "string")
133 133
 			{
134 134
 				type += TYPE_STRING;
135  
-				buffer.push(type);
136  
-				encodeString(buffer, obj);
  135
+				writer.write(type);
  136
+				encodeString(writer, obj);
137 137
 			}
138 138
 			else if (obj === ARRAY_TERMINATOR)
139 139
 			{
140  
-				buffer.push(BYTE_TERMINATOR);
  140
+				writer.write(BYTE_TERMINATOR);
141 141
 			}
142 142
 			else return null;
143 143
 			type = 0;
144 144
 		}
145  
-		return bufferToUnicodeString(buffer);
  145
+		return writer.trim().toString();
146 146
 	};
147 147
 
148 148
 	util.decodeKey = function (encodedKey)
@@ -150,22 +150,22 @@ if (window.indexedDB.polyfill)
150 150
 		var rootArray = []; // one-element root array that contains the result
151 151
 		var parentArray = rootArray;
152 152
 		var type, arrayStack = [], depth, tmp;
153  
-		var byteReader = new ByteReader(encodedKey);
154  
-		while (byteReader.read() != null)
  153
+		var reader = new HexStringReader(encodedKey);
  154
+		while (reader.read() != null)
155 155
 		{
156  
-			if (byteReader.current === 0) // end of array
  156
+			if (reader.current === 0) // end of array
157 157
 			{
158 158
 				parentArray = arrayStack.pop();
159 159
 				continue;
160 160
 			}
161  
-			if (byteReader.current === null)
  161
+			if (reader.current === null)
162 162
 			{
163 163
 				return rootArray[0];
164 164
 			}
165 165
 			do
166 166
 			{
167  
-				depth = byteReader.current / 4 | 0;
168  
-				type = byteReader.current % 4;
  167
+				depth = reader.current / 4 | 0;
  168
+				type = reader.current % 4;
169 169
 				for (var i = 0; i < depth; i++)
170 170
 				{
171 171
 					tmp = [];
@@ -173,24 +173,24 @@ if (window.indexedDB.polyfill)
173 173
 					arrayStack.push(parentArray);
174 174
 					parentArray = tmp;
175 175
 				}
176  
-				if (type === 0 && byteReader.current + TYPE_ARRAY > MAX_TYPE_BYTE_SIZE)
  176
+				if (type === 0 && reader.current + TYPE_ARRAY > MAX_TYPE_BYTE_SIZE)
177 177
 				{
178  
-					byteReader.read();
  178
+					reader.read();
179 179
 				}
180 180
 				else break;
181 181
 			} while (true);
182 182
 
183 183
 			if (type === TYPE_NUMBER)
184 184
 			{
185  
-				parentArray.push(decodeNumber(byteReader));
  185
+				parentArray.push(decodeNumber(reader));
186 186
 			}
187 187
 			else if (type === TYPE_DATE)
188 188
 			{
189  
-				parentArray.push(new Date(decodeNumber(byteReader)));
  189
+				parentArray.push(new Date(decodeNumber(reader)));
190 190
 			}
191 191
 			else if (type === TYPE_STRING)
192 192
 			{
193  
-				parentArray.push(decodeString(byteReader));
  193
+				parentArray.push(decodeString(reader));
194 194
 			}
195 195
 			else if (type === 0) // empty array case
196 196
 			{
@@ -246,7 +246,7 @@ if (window.indexedDB.polyfill)
246 246
 		return { sign : s, exponent : e, mantissa : m };
247 247
 	}
248 248
 
249  
-	function encodeNumber(buffer, number)
  249
+	function encodeNumber(writer, number)
250 250
 	{
251 251
 		var number = ieee754(number);
252 252
 		if (number.sign)
@@ -256,40 +256,37 @@ if (window.indexedDB.polyfill)
256 256
 		}
257 257
 		var word, m = number.mantissa;
258 258
 
259  
-		buffer.push((number.sign ? 0 : 0x80) | (number.exponent >> 4));
260  
-		buffer.push((number.exponent & 0xF) << 4 | (0 | m / p48));
  259
+		writer.write((number.sign ? 0 : 0x80) | (number.exponent >> 4));
  260
+		writer.write((number.exponent & 0xF) << 4 | (0 | m / p48));
261 261
 
262 262
 		m %= p48; word = 0 | m / p32;
263  
-		buffer.push(word >> 8, word & 0xFF);
  263
+		writer.write(word >> 8, word & 0xFF);
264 264
 
265 265
 		m %= p32; word = 0 | m / p16;
266  
-		buffer.push(word >> 8, word & 0xFF);
  266
+		writer.write(word >> 8, word & 0xFF);
267 267
 
268 268
 		word = m % p16;
269  
-		buffer.push(word >> 8, word & 0xFF);
  269
+		writer.write(word >> 8, word & 0xFF);
270 270
 	}
271 271
 
272  
-	function decodeNumber(byteReader)
  272
+	function decodeNumber(reader)
273 273
 	{
274  
-		var b = byteReader.read();
  274
+		var b = reader.read() | 0;
275 275
 		var sign = b >> 7 ? false : true;
276 276
 
277 277
 		var s = sign ? -1 : 1;
278 278
 
279 279
 		var e = (b & 0x7F) << 4;
280  
-		b = byteReader.read();
  280
+		b = reader.read() | 0;
281 281
 		e += b >> 4;
282 282
 		if (sign) e = 0x7FF - e;
283 283
 
284 284
 		var tmp = [sign ? (0xF - (b & 0xF)) : b & 0xF];
285 285
 		var i = 6;
286  
-		while (i--) tmp.push(sign ? (0xFF - byteReader.read()) : byteReader.read());
  286
+		while (i--) tmp.push(sign ? (0xFF - (reader.read() | 0)) : reader.read() | 0);
287 287
 
288 288
 		var m = 0; i = 7;
289  
-		while (i--)
290  
-		{
291  
-			m = m / 256 + tmp[i];
292  
-		}
  289
+		while (i--) m = m / 256 + tmp[i];
293 290
 		m /= 16;
294 291
 
295 292
 		if (m === 0 && e === 0) return 0;
@@ -298,7 +295,7 @@ if (window.indexedDB.polyfill)
298 295
 
299 296
 	var secondLayer = 0x3FFF + 0x7F;
300 297
 
301  
-	function encodeString(buffer, string)
  298
+	function encodeString(writer, string)
302 299
 	{
303 300
 		/* 3 layers:
304 301
 		 Chars 0         - 7E            are encoded as 0xxxxxxx with 1 added
@@ -310,58 +307,58 @@ if (window.indexedDB.polyfill)
310 307
 			var code = string.charCodeAt(i);
311 308
 			if (code <= 0x7E)
312 309
 			{
313  
-				buffer.push(code + 1);
  310
+				writer.write(code + 1);
314 311
 			}
315 312
 			else if (code <= secondLayer)
316 313
 			{
317 314
 				code -= 0x7F;
318  
-				buffer.push(0x80 | code >> 8, code & 0xFF);
  315
+				writer.write(0x80 | code >> 8, code & 0xFF);
319 316
 			}
320 317
 			else
321 318
 			{
322  
-				buffer.push(0xC0 | code >> 10, code >> 2 | 0xFF, (code | 3) << 6);
  319
+				writer.write(0xC0 | code >> 10, code >> 2 | 0xFF, (code | 3) << 6);
323 320
 			}
324 321
 		}
325  
-		buffer.push(BYTE_TERMINATOR);
  322
+		writer.write(BYTE_TERMINATOR);
326 323
 	}
327 324
 
328  
-	function decodeString(byteReader)
  325
+	function decodeString(reader)
329 326
 	{
330  
-		var buffer = [], layer = 0, unicode = 0, count = 0, byte, tmp;
  327
+		var buffer = [], layer = 0, unicode = 0, count = 0, $byte, tmp;
331 328
 		while (true)
332 329
 		{
333  
-			byte = byteReader.read();
334  
-			if (byte === 0 || byte == null) break;
  330
+			$byte = reader.read();
  331
+			if ($byte === 0 || $byte == null) break;
335 332
 
336 333
 			if (layer === 0)
337 334
 			{
338  
-				tmp = byte >> 6;
  335
+				tmp = $byte >> 6;
339 336
 				if (tmp < 2)
340 337
 				{
341  
-					buffer.push(String.fromCharCode(byte - 1));
  338
+					buffer.push(String.fromCharCode($byte - 1));
342 339
 				}
343 340
 				else // tmp equals 2 or 3
344 341
 				{
345 342
 					layer = tmp;
346  
-					unicode = byte << 10;
  343
+					unicode = $byte << 10;
347 344
 					count++;
348 345
 				}
349 346
 			}
350 347
 			else if (layer === 2)
351 348
 			{
352  
-				buffer.push(String.fromCharCode(unicode + byte + 0x7F));
  349
+				buffer.push(String.fromCharCode(unicode + $byte + 0x7F));
353 350
 				layer = unicode = count = 0;
354 351
 			}
355 352
 			else // layer === 3
356 353
 			{
357 354
 				if (count === 2)
358 355
 				{
359  
-					unicode += byte << 2;
  356
+					unicode += $byte << 2;
360 357
 					count++;
361 358
 				}
362 359
 				else // count === 3
363 360
 				{
364  
-					buffer.push(String.fromCharCode(unicode | byte >> 6));
  361
+					buffer.push(String.fromCharCode(unicode | $byte >> 6));
365 362
 					layer = unicode = count = 0;
366 363
 				}
367 364
 			}
@@ -369,48 +366,42 @@ if (window.indexedDB.polyfill)
369 366
 		return buffer.join("");
370 367
 	}
371 368
 
372  
-	var ByteReader = function (string)
  369
+	var HexStringReader = function (string)
373 370
 	{
374 371
 		this.current = null;
375 372
 
376 373
 		var string = string;
377  
-		var code, index = -1, high = false;
  374
+		var lastIndex = string.length - 1;
  375
+		var index = -1;
378 376
 
379 377
 		this.read = function ()
380 378
 		{
381  
-			high = !high;
382  
-			if (high)
383  
-			{
384  
-				index++;
385  
-				code = string.charCodeAt(index);
386  
-			}
387  
-			if (isNaN(code))
388  
-			{
389  
-				this.current = null;
390  
-			}
391  
-			else
392  
-			{
393  
-				this.current = high ? code >> 8 : code & 0xFF;
394  
-			}
395  
-			return this.current;
  379
+			return this.current = index < lastIndex ? parseInt(string[++index] + string[++index], 16) : null;
396 380
 		}
397 381
 	};
398 382
 
399  
-	function bufferToUnicodeString(buffer)
  383
+	var HexStringWriter = function()
400 384
 	{
401  
-		var index = buffer.length;
402  
-		while (buffer[--index] === 0);
403  
-		buffer.length = ++index;
404  
-
405  
-		if ((index & 1) === 1) buffer.push(0);
406  
-		var result = [], length = buffer.length >> 1;
407  
-
408  
-		for (var i = 0; i < length; i++)
  385
+		var buffer = [], c;
  386
+		this.write = function ($byte)
  387
+		{
  388
+			for (var i = 0; i < arguments.length; i++)
  389
+			{
  390
+				c = arguments[i].toString(16);
  391
+				buffer.push(c.length === 2 ? c : c = "0" + c);
  392
+			}
  393
+		};
  394
+		this.toString = function ()
  395
+		{
  396
+			return buffer.length ? buffer.join("") : null;
  397
+		};
  398
+		this.trim = function()
409 399
 		{
410  
-			index = i << 1;
411  
-			result.push(String.fromCharCode(buffer[index] << 8 | buffer[index + 1]));
  400
+			var length = buffer.length;
  401
+			while (buffer[--length] === "00");
  402
+			buffer.length = ++length;
  403
+			return this;
412 404
 		}
413  
-		return result.join("");
414  
-	}
  405
+	};
415 406
 
416 407
 }(window.indexedDB.util));
9  w3c-tests/testharness.js
@@ -363,13 +363,16 @@ policies and contribution forms [3].
363 363
 
364 364
     function __delayFuncCall(func)
365 365
     {
  366
+	    var delay = 25;
  367
+	    window.setTimeout(function () {
366 368
         window.setTimeout(function () {
367 369
             window.setTimeout(function () {
368 370
                 window.setTimeout(function () {
369 371
                     func();
370  
-                }, 10);
371  
-            }, 10);
372  
-        }, 10);
  372
+                }, delay);
  373
+            }, delay);
  374
+        }, delay);
  375
+        }, delay);
373 376
     }
374 377
 
375 378
 

0 notes on commit 791c626

Please sign in to comment.
Something went wrong with that request. Please try again.