| // META: global=window,worker | 
 | // META: title=Keypath | 
 | // META: script=resources/support.js | 
 |  | 
 | // Spec: | 
 | // http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-path-construct | 
 |  | 
 | 'use strict'; | 
 |  | 
 | let global_db = createdb_for_multiple_tests(); | 
 |  | 
 | function keypath(keypath, objects, expected_keys, desc) { | 
 |   let db; | 
 |   let t = async_test(self.title + ' - ' + (desc ? desc : keypath)); | 
 |   let store_name = 'store-' + (Date.now()) + Math.random(); | 
 |  | 
 |   let open_rq = global_db.setTest(t); | 
 |   open_rq.onupgradeneeded = function(e) { | 
 |     db = e.target.result; | 
 |     let objStore = db.createObjectStore(store_name, {keyPath: keypath}); | 
 |  | 
 |     for (let i = 0; i < objects.length; i++) | 
 |       objStore.add(objects[i]); | 
 |   }; | 
 |  | 
 |   open_rq.onsuccess = function(e) { | 
 |     let actual_keys = []; | 
 |     let rq = db.transaction(store_name).objectStore(store_name).openCursor(); | 
 |  | 
 |     rq.onsuccess = t.step_func(function(e) { | 
 |       let cursor = e.target.result; | 
 |  | 
 |       if (cursor) { | 
 |         actual_keys.push(cursor.key.valueOf()); | 
 |         cursor.continue(); | 
 |       } else { | 
 |         assert_key_equals(actual_keys, expected_keys, 'keyorder array'); | 
 |         t.done(); | 
 |       } | 
 |     }); | 
 |   }; | 
 | } | 
 |  | 
 | keypath('my.key', [{my: {key: 10}}], [10]); | 
 |  | 
 | keypath('my.køi', [{my: {køi: 5}}], [5]); | 
 |  | 
 | keypath('my.key_ya', [{my: {key_ya: 10}}], [10]); | 
 |  | 
 | keypath('public.key$ya', [{public: {key$ya: 10}}], [10]); | 
 |  | 
 | keypath('true.$', [{true: {$: 10}}], [10]); | 
 |  | 
 | keypath('my._', [{my: {_: 10}}], [10]); | 
 |  | 
 | keypath('delete.a7', [{delete: {a7: 10}}], [10]); | 
 |  | 
 | keypath( | 
 |     'p.p.p.p.p.p.p.p.p.p.p.p.p.p', | 
 |     [{p: {p: {p: {p: {p: {p: {p: {p: {p: {p: {p: {p: {p: {p: 10}}}}}}}}}}}}}}], | 
 |     [10]); | 
 |  | 
 | keypath( | 
 |     'str.length', [{str: 'pony'}, {str: 'my'}, {str: 'little'}, {str: ''}], | 
 |     [0, 2, 4, 6]); | 
 |  | 
 | keypath( | 
 |     'arr.length', | 
 |     [ | 
 |       {arr: [0, 0, 0, 0]}, {arr: [{}, 0, 'hei', 'length', Infinity, []]}, | 
 |       {arr: [10, 10]}, {arr: []} | 
 |     ], | 
 |     [0, 2, 4, 6]); | 
 |  | 
 | keypath('length', [[10, 10], '123', {length: 20}], [2, 3, 20]); | 
 |  | 
 | keypath( | 
 |     '', [['bags'], 'bean', 10], [10, 'bean', ['bags']], | 
 |     '\'\' uses value as key'); | 
 |  | 
 | keypath( | 
 |     [''], [['bags'], 'bean', 10], [[10], ['bean'], [['bags']]], | 
 |     '[\'\'] uses value as [key]'); | 
 |  | 
 | keypath( | 
 |     ['x', 'y'], [{x: 10, y: 20}, {y: 1.337, x: 100}], [[10, 20], [100, 1.337]], | 
 |     '[\'x\', \'y\']'); | 
 |  | 
 | keypath( | 
 |     [['x'], ['y']], [{x: 10, y: 20}, {y: 1.337, x: 100}], | 
 |     [[10, 20], [100, 1.337]], '[[\'x\'], \'y\'] (stringifies)'); | 
 |  | 
 | keypath( | 
 |     [ | 
 |       'x', { | 
 |         toString: function() { | 
 |           return 'y' | 
 |         } | 
 |       } | 
 |     ], | 
 |     [{x: 10, y: 20}, {y: 1.337, x: 100}], [[10, 20], [100, 1.337]], | 
 |     '[\'x\', {toString->\'y\'}] (stringifies)'); | 
 |  | 
 | if (false) { | 
 |   let myblob = Blob(['Yoda'], {type: 'suprawsum'}); | 
 |   keypath( | 
 |       ['length', 'type'], [myblob], [4, 'suprawsum'], | 
 |       '[Blob.length, Blob.type]'); | 
 | } | 
 |  | 
 | // File.name and File.lastModified is not testable automatically | 
 |  | 
 | keypath( | 
 |     ['name', 'type'], | 
 |     [ | 
 |       {name: 'orange', type: 'fruit'}, | 
 |       {name: 'orange', type: ['telecom', 'french']} | 
 |     ], | 
 |     [['orange', 'fruit'], ['orange', ['telecom', 'french']]]); | 
 |  | 
 | keypath( | 
 |     ['name', 'type.name'], | 
 |     [ | 
 |       {name: 'orange', type: {name: 'fruit'}}, | 
 |       {name: 'orange', type: {name: 'telecom'}} | 
 |     ], | 
 |     [['orange', 'fruit'], ['orange', 'telecom']]); | 
 |  | 
 | keypath( | 
 |     ['type'], | 
 |     [{name: 'orange', type: 'fruit'}, {name: 'cucumber', type: 'vegetable'}], | 
 |     [['fruit'], ['vegetable']], 'list with 1 field'); | 
 |  | 
 | let loop_array = []; | 
 | loop_array.push(loop_array); | 
 | keypath( | 
 |     loop_array, ['a', 1, ['k']], [[1], ['a'], [['k']]], | 
 |     'array loop -> stringify becomes [\'\']'); |