|  | <!DOCTYPE html> | 
|  | <!-- Submitted from TestTWF Paris --> | 
|  | <meta charset=utf-8"> | 
|  | <title>Invalid key</title> | 
|  | <link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-construct"> | 
|  | <link rel=assert title="A value is said to be a valid key if it is one of the following types: Array JavaScript objects [ECMA-262], DOMString [WEBIDL], Date [ECMA-262] or float [WEBIDL]. However Arrays are only valid keys if every item in the array is defined and is a valid key (i.e. sparse arrays can not be valid keys) and if the Array doesn't directly or indirectly contain itself. Any non-numeric properties are ignored, and thus does not affect whether the Array is a valid key. Additionally, if the value is of type float, it is only a valid key if it is not NaN, and if the value is of type Date it is only a valid key if its [[PrimitiveValue]] internal property, as defined by [ECMA-262], is not NaN. Conforming user agents must support all valid keys as keys."> | 
|  | <!-- original author --> | 
|  | <link rel=author href="mailto:odinho@opera.com" title="Odin Hørthe Omdal"> | 
|  | <!-- some additions by Baptiste Fontaine (batifon@yahoo.fr) --> | 
|  | <script src=/resources/testharness.js></script> | 
|  | <script src=/resources/testharnessreport.js></script> | 
|  | <script src=support.js></script> | 
|  |  | 
|  | <script> | 
|  | var db        = createdb_for_multiple_tests(), | 
|  | // cache for ObjectStores | 
|  | objStore  = null, | 
|  | objStore2 = null; | 
|  |  | 
|  | function is_cloneable(o) { | 
|  | try { | 
|  | self.postMessage(o, '*'); | 
|  | return true; | 
|  | } catch (ex) { | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | function invalid_key(desc, key) { | 
|  | var t = async_test(document.title + " - " + desc); | 
|  |  | 
|  | // set the current test, and run it | 
|  | db.setTest(t).onupgradeneeded = function(e) { | 
|  | objStore = objStore || e.target.result.createObjectStore("store"); | 
|  | assert_throws('DataError', function() { | 
|  | objStore.add("value", key); | 
|  | }); | 
|  |  | 
|  | if (is_cloneable(key)) { | 
|  | objStore2 = objStore2 || e.target.result.createObjectStore("store2", { keyPath: ["x", "keypath"] }); | 
|  | assert_throws('DataError', function() { | 
|  | objStore2.add({ x: "value", keypath: key }); | 
|  | }); | 
|  | } | 
|  | this.done(); | 
|  | }; | 
|  | } | 
|  |  | 
|  | var fake_array = { | 
|  | length      : 0, | 
|  | constructor : Array | 
|  | }; | 
|  |  | 
|  | var ArrayClone = function(){}; | 
|  | ArrayClone.prototype = Array; | 
|  | var ArrayClone_instance = new ArrayClone(); | 
|  |  | 
|  | // booleans | 
|  | invalid_key( 'true'  , true ); | 
|  | invalid_key( 'false' , false ); | 
|  |  | 
|  | // null/NaN/undefined | 
|  | invalid_key( 'null'      , null ); | 
|  | invalid_key( 'NaN'       , NaN ); | 
|  | invalid_key( 'undefined' , undefined ); | 
|  | invalid_key( 'undefined2'); | 
|  |  | 
|  | // functions | 
|  | invalid_key( 'function() {}', function(){} ); | 
|  |  | 
|  | // objects | 
|  | invalid_key( '{}'                           , {} ); | 
|  | invalid_key( '{ obj: 1 }'                   , { obj: 1 }); | 
|  | invalid_key( 'Math'                         , Math ); | 
|  | invalid_key( 'window'                       , window ); | 
|  | invalid_key( '{length:0,constructor:Array}' , fake_array ); | 
|  | invalid_key( 'Array clone’s instance'       , ArrayClone_instance ); | 
|  | invalid_key( 'Array (object)'               , Array ); | 
|  | invalid_key( 'String (object)'              , String ); | 
|  | invalid_key( 'new String()'                 , new String() ); | 
|  | invalid_key( 'new Number()'                 , new Number() ); | 
|  | invalid_key( 'new Boolean()'                , new Boolean() ); | 
|  |  | 
|  | // arrays | 
|  | invalid_key( '[{}]'                     , [{}] ); | 
|  | invalid_key( '[[], [], [], [[ Date ]]]' , [ [], [], [], [[ Date ]] ] ); | 
|  | invalid_key( '[undefined]'              , [undefined] ); | 
|  | invalid_key( '[,1]'                     , [,1] ); | 
|  |  | 
|  | invalid_key( 'document.getElements' | 
|  | +'ByTagName("script")'      , document.getElementsByTagName("script") ); | 
|  |  | 
|  | //  dates | 
|  | invalid_key( 'new Date(NaN)'      , new Date(NaN) ); | 
|  | invalid_key( 'new Date(Infinity)' , new Date(Infinity) ); | 
|  |  | 
|  | // regexes | 
|  | invalid_key( '/foo/'        , /foo/ ); | 
|  | invalid_key( 'new RegExp()' , new RegExp() ); | 
|  |  | 
|  | var sparse = []; | 
|  | sparse[10] = "hei"; | 
|  | invalid_key('sparse array', sparse); | 
|  |  | 
|  | var sparse2 = []; | 
|  | sparse2[0]  = 1; | 
|  | sparse2[""] = 2; | 
|  | sparse2[2]  = 3; | 
|  | invalid_key('sparse array 2', sparse2); | 
|  |  | 
|  | invalid_key('[[1], [3], [7], [[ sparse array ]]]', [ [1], [3], [7], [[ sparse2 ]] ]); | 
|  |  | 
|  | // sparse3 | 
|  | invalid_key( '[1,2,3,,]', [1,2,3,,] ); | 
|  |  | 
|  | var recursive = []; | 
|  | recursive.push(recursive); | 
|  | invalid_key('array directly contains self', recursive); | 
|  |  | 
|  | var recursive2 = []; | 
|  | recursive2.push([recursive2]); | 
|  | invalid_key('array indirectly contains self', recursive2); | 
|  |  | 
|  | var recursive3 = [recursive]; | 
|  | invalid_key('array member contains self', recursive3); | 
|  |  | 
|  | </script> | 
|  |  | 
|  | <div id=log></div> |