dom/imptests/html/microdata/microdata-dom-api/test_001.html

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/imptests/html/microdata/microdata-dom-api/test_001.html	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,3661 @@
     1.4 +<!doctype html>
     1.5 +<html>
     1.6 +	<head>
     1.7 +		<meta charset="UTF-8">
     1.8 +		<title>Microdata tests</title>
     1.9 +		<script type="text/javascript" src="/resources/testharness.js"></script>
    1.10 +		<script type="text/javascript" src="/resources/testharnessreport.js"></script>
    1.11 +		<link rel="help" href="http://dev.w3.org/html5/md/#microdata-dom-api">
    1.12 +		<link rel="help" href="http://dev.w3.org/html5/md/#encoding-microdata">
    1.13 +	</head>
    1.14 +	<body>
    1.15 +		<noscript><p>Enable JavaScript and reload</p></noscript>
    1.16 +		<div id="log">Running test...</div>
    1.17 +		<div itemscope itemtype="http://example.com/bar data:text/plain, http://example.com/foo" id="one"></div>
    1.18 +		<div itemscope itemtype="http://example.com/bar" id="two"></div>
    1.19 +		<div itemscope itemtype="http://example.com/foo http://example.com/bar" id="three">
    1.20 +			<div itemscope itemtype="http://example.com/bar data:text/plain," id="four"></div>
    1.21 +		</div>
    1.22 +		<div itemscope id="five"></div>
    1.23 +		<script type="text/javascript">
    1.24 +/* All tests are stand-alone.
    1.25 +To reduce this testsuite to show only a single desired test,
    1.26 +simply remove all test(...) blocks before and after it. */
    1.27 +
    1.28 +function makeEl(eltype,props,contents) {
    1.29 +	var elem = document.createElement(eltype);
    1.30 +	for( var i in props ) {
    1.31 +		//just in case the framework extends object...
    1.32 +		if( props.hasOwnProperty(i) ) {
    1.33 +			elem.setAttribute(i,props[i]);
    1.34 +		}
    1.35 +	}
    1.36 +	if( contents ) {
    1.37 +		elem.innerHTML = contents;
    1.38 +	}
    1.39 +	return elem;
    1.40 +}
    1.41 +
    1.42 +/* getItem tests */
    1.43 +test(function () {
    1.44 +	assert_true( !!document.getItems );
    1.45 +}, 'document.getItems must exist');
    1.46 +test(function () {
    1.47 +	assert_true( document.getItems() instanceof NodeList, 'instanceof test' );
    1.48 +	NodeList.prototype.customProperty = true;
    1.49 +	assert_true( document.getItems().customProperty, 'inheritance test' );
    1.50 +}, 'document.getItems must return a NodeList');
    1.51 +test(function () {
    1.52 +	assert_equals( document.getItems().length, 5 );
    1.53 +}, 'document.getItems must locate the correct number of items');
    1.54 +test(function () {
    1.55 +	var nlist = document.getItems();
    1.56 +	var foo = makeEl('div',{itemscope:'itemscope'});
    1.57 +	document.body.appendChild(foo);
    1.58 +	var templength = nlist.length;
    1.59 +	document.body.removeChild(foo);
    1.60 +	assert_equals( templength, 6 );
    1.61 +	assert_equals( nlist.length, 5 );
    1.62 +}, 'document.getItems must return a live NodeList');
    1.63 +test(function () {
    1.64 +	var nlist = document.getItems();
    1.65 +	document.getElementById('one').removeAttribute('itemscope');
    1.66 +	var templength = nlist.length;
    1.67 +	document.getElementById('one').setAttribute('itemscope','itemscope');
    1.68 +	assert_equals( templength, 4 );
    1.69 +	assert_equals( nlist.length, 5 );
    1.70 +}, 'live NodeList must notice when itemscope changes');
    1.71 +test(function () {
    1.72 +	document.getElementById('one').removeAttribute('itemscope');
    1.73 +	var templength = document.getItems().length;
    1.74 +	document.getElementById('one').setAttribute('itemscope','itemscope');
    1.75 +	assert_equals( templength, 4 );
    1.76 +	assert_equals( document.getItems().length, 5 );
    1.77 +}, 'next request must notice when itemscope changes');
    1.78 +test(function () {
    1.79 +	assert_equals( document.getItems('http://example.com/').length, 0, 'http://example.com/' );
    1.80 +	assert_equals( document.getItems('example').length, 0, 'example' );
    1.81 +	assert_equals( document.getItems('http://example.com/foo').length, 2, 'http://example.com/foo' );
    1.82 +	assert_equals( document.getItems('http://example.com/bar').length, 4, 'http://example.com/bar' );
    1.83 +	assert_equals( document.getItems('data:text/plain,').length, 2, 'data:text/plain,' );
    1.84 +}, 'document.getItems must locate the right number of items for each itemtype');
    1.85 +test(function () {
    1.86 +	assert_equals( document.getItems('http://example.com/Foo').length, 0, 'http://example.com/Foo' );
    1.87 +	assert_equals( document.getItems('HTTP://example.com/foo').length, 0, 'HTTP://example.com/foo' );
    1.88 +}, 'document.getItems must be case sensitive');
    1.89 +test(function () {
    1.90 +	var nlist = document.getItems('http://example.com/foo');
    1.91 +	var foo = makeEl('div',{itemscope:'itemscope',itemtype:'http://example.com/foo'});
    1.92 +	document.body.appendChild(foo);
    1.93 +	var templength = nlist.length;
    1.94 +	document.body.removeChild(foo);
    1.95 +	assert_equals( templength, 3 );
    1.96 +	assert_equals( nlist.length, 2 );
    1.97 +}, 'document.getItems must return a live NodeList when using URLs');
    1.98 +test(function () {
    1.99 +	var nlist = document.getItems('http://example.com/foo');
   1.100 +	document.getElementById('one').removeAttribute('itemtype');
   1.101 +	var templength = nlist.length;
   1.102 +	document.getElementById('one').setAttribute('itemtype','http://example.com/bar data:text/plain, http://example.com/foo');
   1.103 +	assert_equals( templength, 1 );
   1.104 +	assert_equals( nlist.length, 2 );
   1.105 +}, 'live NodeList must notice when itemtype changes');
   1.106 +test(function () {
   1.107 +	document.getElementById('one').removeAttribute('itemtype');
   1.108 +	var templength = document.getItems('http://example.com/foo').length;
   1.109 +	document.getElementById('one').setAttribute('itemtype','http://example.com/bar data:text/plain, http://example.com/foo');
   1.110 +	assert_equals( templength, 1 );
   1.111 +	assert_equals( document.getItems('http://example.com/foo').length, 2 );
   1.112 +}, 'next request must notice when itemtype changes');
   1.113 +test(function () {
   1.114 +        assert_equals( document.getItems('http://example.com/foo data:text/plain,').length, 1, 'basic spaces' );
   1.115 +	assert_equals( document.getItems('  http://example.com/foo  data:text/plain,  ').length, 1, 'extraneous spaces' );
   1.116 +}, 'document.getItems must locate items when parameters are separated by spaces');
   1.117 +test(function () {
   1.118 +	assert_equals( document.getItems('http://example.com/foo data:text/plain, http://example.com/foo').length, 1 );
   1.119 +}, 'document.getItems must ignore duplicated tokens');
   1.120 +test(function () {
   1.121 +	var testitems = document.getItems('http://example.com/bar');
   1.122 +	assert_equals( testitems[0].id, 'one' );
   1.123 +	assert_equals( testitems[1].id, 'two' );
   1.124 +	assert_equals( testitems[2].id, 'three' );
   1.125 +	assert_equals( testitems[3].id, 'four' );
   1.126 +}, 'document.getItems NodeList must be in source tree order');
   1.127 +test(function () {
   1.128 +	assert_true( document.getItems('http://example.com/abc') != document.getItems('http://example.com/def'), 'different tokens' );
   1.129 +	assert_true( document.getItems() != document.getItems(' '), 'no tokens' );
   1.130 +}, 'document.getItems must not return the same NodeList for different parameters');
   1.131 +test(function () {
   1.132 +	assert_equals( document.getItems('').length, 5, 'empty string' );
   1.133 +	assert_equals( document.getItems('  ').length, 5, 'string with spaces' );
   1.134 +}, 'document.getItems must treat no tokens as no parameter');
   1.135 +//removed due to disputed Web compatibility of casting null with DOM methods
   1.136 +/*
   1.137 +test(function () {
   1.138 +	assert_equals( document.getItems(null).length, 0, 'null' );
   1.139 +	assert_equals( document.getItems(window.undefined).length, 0, 'undefined' );
   1.140 +}, 'document.getItems must cast null and undefined to strings');
   1.141 +*/
   1.142 +test(function () {
   1.143 +	var foo = makeEl('div',{itemtype:'http://example.com/foo'});
   1.144 +	document.body.appendChild(foo);
   1.145 +	var templength = document.getItems('http://example.com/foo').length;
   1.146 +	document.body.removeChild(foo);
   1.147 +	assert_equals( templength, 2 );
   1.148 +}, 'document.getItems must not find items with itemtype but not itemscope');
   1.149 +test(function () {
   1.150 +	var foo = makeEl('div',{itemscope:'itemscope',itemtype:'baz'}),
   1.151 +	    bar = makeEl('div',{itemscope:'itemscope',itemtype:location.href.replace(/\/[^\/]*$/,'/baz')});
   1.152 +	document.body.appendChild(foo);
   1.153 +	document.body.appendChild(bar);
   1.154 +	var unrezlength = document.getItems('baz').length;
   1.155 +	var rezlength = document.getItems(location.href.replace(/\/[^\/]*$/,'/baz')).length;
   1.156 +	document.body.removeChild(foo);
   1.157 +	document.body.removeChild(bar);
   1.158 +	assert_equals( unrezlength, 1, 'unresolved URL' );
   1.159 +	assert_equals( rezlength, 1, 'resolved URL' );
   1.160 +}, 'document.getItems and itemtype must not resolve URLs');
   1.161 +test(function () {
   1.162 +	document.getElementById('one').setAttribute('itemprop','test');
   1.163 +	document.getElementById('four').setAttribute('itemprop','test');
   1.164 +	var templength = document.getItems().length;
   1.165 +	document.getElementById('one').removeAttribute('itemprop');
   1.166 +	document.getElementById('four').removeAttribute('itemprop');
   1.167 +	assert_equals( templength, 3 );
   1.168 +}, 'document.getItems must not see items that have the itemprop attribute set');
   1.169 +
   1.170 +/* itemScope property tests */
   1.171 +test(function () {
   1.172 +	assert_true(makeEl('div',{itemscope:'itemscope'}).itemScope);
   1.173 +	assert_false(makeEl('div',{}).itemScope);
   1.174 +}, 'the itemscope attribute must be reflected by the .itemScope property');
   1.175 +test(function () {
   1.176 +	assert_equals( typeof makeEl('div',{itemscope:'itemscope'}).itemScope, 'boolean', 'attribute exists' );
   1.177 +	assert_equals( typeof makeEl('div',{}).itemScope, 'boolean', 'attribute does not exist' );
   1.178 +}, 'the itemScope property must be boolean');
   1.179 +test(function () {
   1.180 +	var testEl = makeEl('div',{});
   1.181 +	testEl.itemScope = true;
   1.182 +	assert_true(testEl.itemScope,'writing true');
   1.183 +	testEl.itemScope = false;
   1.184 +	assert_false(testEl.itemScope,'writing false');
   1.185 +}, 'the itemScope property must be read/write');
   1.186 +test(function () {
   1.187 +	var testEl = makeEl('div',{});
   1.188 +	testEl.itemScope = true;
   1.189 +	assert_true(testEl.hasAttribute('itemscope'),'writing true');
   1.190 +	testEl.itemScope = false;
   1.191 +	assert_false(testEl.hasAttribute('itemscope'),'writing false');
   1.192 +}, 'writing to the itemScope property must toggle existence of the itemscope content attribute');
   1.193 +test(function () {
   1.194 +	var testEl = makeEl('div',{});
   1.195 +	document.body.appendChild(testEl);
   1.196 +	var numAppend = document.getItems().length;
   1.197 +	testEl.itemScope = true;
   1.198 +	var numTrue = document.getItems().length;
   1.199 +	testEl.itemScope = false;
   1.200 +	var numFalse = document.getItems().length;
   1.201 +	document.body.removeChild(testEl);
   1.202 +	assert_equals(numAppend,5,'after appending the new item');
   1.203 +	assert_equals(numTrue,6,'after setting the property to true');
   1.204 +	assert_equals(numFalse,5,'after setting the property to false');
   1.205 +}, 'writing to the itemScope property must affect whether the element is returned by getItems');
   1.206 +test(function () {
   1.207 +	var testEl = makeEl('div',{}), nlist = document.getItems();
   1.208 +	document.body.appendChild(testEl);
   1.209 +	var numAppend = nlist.length;
   1.210 +	testEl.itemScope = true;
   1.211 +	var numTrue = nlist.length;
   1.212 +	testEl.itemScope = false;
   1.213 +	var numFalse = nlist.length;
   1.214 +	document.body.removeChild(testEl);
   1.215 +	assert_equals(numAppend,5,'after appending the new item');
   1.216 +	assert_equals(numTrue,6,'after setting the property to true');
   1.217 +	assert_equals(numFalse,5,'after setting the property to false');
   1.218 +}, 'writing to the itemScope property must affect membership of live NodeLists');
   1.219 +
   1.220 +/* itemType property tests (properties collection tests are done later) */
   1.221 +test(function () {
   1.222 +	assert_equals(makeEl('div',{}).itemType.toString(),'','no attribute');
   1.223 +	assert_equals(makeEl('div',{itemtype:' foo  bar '}).itemType.toString(),' foo  bar ','with simple tokens');
   1.224 +	var testEl = makeEl('div',{itemtype:'foo'});
   1.225 +	testEl.removeAttribute('itemtype');
   1.226 +	assert_equals(testEl.itemType.toString(),'','removed attribute');
   1.227 +}, 'the itemType attribute must be reflected by the .itemRef property');
   1.228 +test(function () {
   1.229 +	assert_equals( typeof makeEl('div',{}).itemType, 'object' );
   1.230 +}, 'the itemType property must be an object');
   1.231 +test(function () {
   1.232 +	assert_true( makeEl('div',{}).itemType instanceof DOMTokenList, 'instanceof test' );
   1.233 +	DOMTokenList.prototype.customProperty = true;
   1.234 +	assert_true( makeEl('div',{}).itemType.customProperty, 'inheritance test' );
   1.235 +}, 'the itemType property must implement DOMTokenList');
   1.236 +test(function () {
   1.237 +	var testEl = makeEl('div',{});
   1.238 +	assert_equals( testEl.itemType, testEl.itemType );
   1.239 +}, 'the itemType property must always reference the same object');
   1.240 +test(function () {
   1.241 +	assert_equals( makeEl('div',{itemtype:'test test'}).itemType.length, 2, 'duplicates in initial string should be preserved' );
   1.242 +	assert_equals( makeEl('div',{itemtype:'test test'}).itemType.item(0), 'test' );
   1.243 +	assert_true( makeEl('div',{itemtype:'test test'}).itemType.contains('test') );
   1.244 +}, 'itemType must be correct for an element that has itemtype tokens');
   1.245 +test(function () {
   1.246 +	assert_equals( makeEl('div',{itemtype:' '}).itemType.length, 0 );
   1.247 +}, 'itemType.length must be 0 for an element that has no tokens');
   1.248 +test(function () {
   1.249 +	assert_false( makeEl('div',{itemtype:' '}).itemType.contains('foo') );
   1.250 +}, 'itemType must not contain an undefined class');
   1.251 +test(function () {
   1.252 +	assert_equals( makeEl('div',{itemtype:' '}).itemType.item(0), null );
   1.253 +}, 'itemType.item() must return null for out-of-range index');
   1.254 +test(function () {
   1.255 +	assert_equals( makeEl('div',{itemtype:' '}).itemType.item(-1), null );
   1.256 +}, 'itemType.item() must return null for negative index');
   1.257 +test(function () {
   1.258 +	/* the normative part of the spec states that:
   1.259 +	"unless the length is zero, in which case there are no supported property indices"
   1.260 +	...
   1.261 +	"The term[...] supported property indices [is] used as defined in the WebIDL specification."
   1.262 +	WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
   1.263 +	assert_equals( makeEl('div',{itemtype:' '}).itemType[0], window.undefined );
   1.264 +}, 'itemType[index] must be undefined for out-of-range index');
   1.265 +test(function () {
   1.266 +	assert_equals( makeEl('div',{itemtype:' '}).itemType[-1], window.undefined );
   1.267 +}, 'itemType[index] must be undefined for negative index');
   1.268 +test(function () {
   1.269 +	assert_equals( makeEl('div',{itemType:' '}).itemType.toString(), ' ' );
   1.270 +}, 'empty itemType should stringify to contain the attribute\'s whitespace');
   1.271 +test(function () {
   1.272 +	assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemtype:' '}).itemType.contains(''); } );
   1.273 +}, 'itemType.contains(empty_string) must throw a SYNTAX_ERR');
   1.274 +test(function () {
   1.275 +	assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemtype:' '}).itemType.add(''); } );
   1.276 +}, 'itemType.add(empty_string) must throw a SYNTAX_ERR');
   1.277 +test(function () {
   1.278 +	assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemtype:' '}).itemType.remove(''); } );
   1.279 +}, 'itemType.remove(empty_string) must throw a SYNTAX_ERR');
   1.280 +test(function () {
   1.281 +	assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemtype:' '}).itemType.toggle(''); } );
   1.282 +}, 'itemType.toggle(empty_string) must throw a SYNTAX_ERR');
   1.283 +test(function () {
   1.284 +	assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemtype:' '}).itemType.contains('a b'); } );
   1.285 +}, 'itemType.contains(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
   1.286 +test(function () {
   1.287 +	assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemtype:' '}).itemType.add('a b'); } );
   1.288 +}, 'itemType.add(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
   1.289 +test(function () {
   1.290 +	assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemtype:' '}).itemType.remove('a b'); } );
   1.291 +}, 'itemType.remove(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
   1.292 +test(function () {
   1.293 +	assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemtype:' '}).itemType.toggle('a b'); } );
   1.294 +}, 'itemType.toggle(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
   1.295 +test(function () {
   1.296 +	var testEl = makeEl('div',{itemtype:'foo'});
   1.297 +	assert_true( testEl.itemType.contains('foo'), 'before change' );
   1.298 +	testEl.setAttribute('itemtype','bar');
   1.299 +	assert_true( testEl.itemType.contains('bar'), 'after change' );
   1.300 +	assert_false( testEl.itemType.contains('foo'), 'after change' );
   1.301 +}, 'itemType.contains must update when the underlying attribute is changed');
   1.302 +test(function () {
   1.303 +	assert_false( makeEl('div',{itemtype:'foo'}).itemType.contains('FOO') );
   1.304 +}, 'itemType.contains must be case sensitive');
   1.305 +test(function () {
   1.306 +	assert_false( makeEl('div',{itemtype:'foo'}).itemType.contains('foo.') );
   1.307 +	assert_false( makeEl('div',{itemtype:'foo'}).itemType.contains('foo)') );
   1.308 +	assert_false( makeEl('div',{itemtype:'foo'}).itemType.contains('foo\'') );
   1.309 +	assert_false( makeEl('div',{itemtype:'foo'}).itemType.contains('foo$') );
   1.310 +	assert_false( makeEl('div',{itemtype:'foo'}).itemType.contains('foo~') );
   1.311 +	assert_false( makeEl('div',{itemtype:'foo'}).itemType.contains('foo?') );
   1.312 +	assert_false( makeEl('div',{itemtype:'foo'}).itemType.contains('foo\\') );
   1.313 +}, 'itemType.contains must not match when punctuation characters are added');
   1.314 +test(function () {
   1.315 +	var elem = makeEl('div',{itemtype:'foo'});
   1.316 +	elem.itemType.add('FOO');
   1.317 +	assert_true( elem.itemType.contains('foo') );
   1.318 +}, 'itemType.add must not remove existing tokens');
   1.319 +test(function () {
   1.320 +	assert_true( makeEl('div',{itemtype:'foo FOO'}).itemType.contains('FOO') );
   1.321 +}, 'itemType.contains case sensitivity must match a case-specific string');
   1.322 +test(function () {
   1.323 +	assert_equals( makeEl('div',{itemtype:'foo FOO'}).itemType.length, 2 );
   1.324 +}, 'itemType.length must correctly reflect the number of tokens');
   1.325 +test(function () {
   1.326 +	assert_equals( makeEl('div',{itemtype:'foo FOO'}).itemType.item(0), 'foo' );
   1.327 +}, 'itemType.item(0) must return the first token');
   1.328 +test(function () {
   1.329 +	var elem = makeEl('div',{itemtype:'foo'});
   1.330 +	elem.itemType.add('FOO');
   1.331 +	assert_equals( elem.itemType.item(1), 'FOO' );
   1.332 +}, 'itemType.item must return case-sensitive strings and preserve token order');
   1.333 +test(function () {
   1.334 +	assert_equals( makeEl('div',{itemtype:'foo FOO'}).itemType[0], 'foo' );
   1.335 +}, 'itemType[0] must return the first token');
   1.336 +test(function () {
   1.337 +	assert_equals( makeEl('div',{itemtype:'foo FOO'}).itemType[1], 'FOO' );
   1.338 +}, 'itemType[index] must return case-sensitive strings and preserve token order');
   1.339 +test(function () {
   1.340 +	/* the normative part of the spec states that:
   1.341 +	"unless the length is zero, in which case there are no supported property indices"
   1.342 +	...
   1.343 +	"The term[...] supported property indices [is] used as defined in the WebIDL specification."
   1.344 +	WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
   1.345 +	assert_equals( makeEl('div',{itemtype:'foo FOO'}).itemType[2], window.undefined );
   1.346 +}, 'itemType[index] must still be undefined for out-of-range index when earlier indexes exist');
   1.347 +test(function () {
   1.348 +	var elem = makeEl('div',{});
   1.349 +	elem.itemType.add('foo');
   1.350 +	elem.itemType.add('FOO');
   1.351 +	assert_equals( elem.getAttribute('itemtype'), 'foo FOO' );
   1.352 +}, 'itemtype attribute must update correctly when items have been added through itemType');
   1.353 +test(function () {
   1.354 +	var elem = makeEl('div',{});
   1.355 +	elem.itemType.add('foo');
   1.356 +	elem.itemType.add('FOO');
   1.357 +	assert_equals( elem.itemType + '', 'foo FOO' );
   1.358 +}, 'itemType must stringify correctly when items have been added');
   1.359 +test(function () {
   1.360 +	var elem = makeEl('div',{itemtype:'foo FOO'});
   1.361 +	elem.itemType.add('foo');
   1.362 +	assert_equals( elem.itemType.length, 2 );
   1.363 +	assert_equals( elem.itemType + '', 'foo FOO' );
   1.364 +}, 'itemType.add must not make any changes if an existing token is added');
   1.365 +test(function () {
   1.366 +	var elem = makeEl('div',{itemtype:'foo FOO'});
   1.367 +	elem.itemType.remove('bar');
   1.368 +	assert_equals( elem.itemType.length, 2 );
   1.369 +	assert_equals( elem.itemType + '', 'foo FOO' );
   1.370 +}, 'itemType.remove must not make any changes if a non-existing token is removed');
   1.371 +test(function () {
   1.372 +	var elem = makeEl('div',{itemtype:'foo FOO'});
   1.373 +	elem.itemType.remove('foo');
   1.374 +	assert_equals( elem.itemType.length, 1 );
   1.375 +	assert_equals( elem.itemType.toString(), 'FOO' );
   1.376 +	assert_false( elem.itemType.contains('foo') );
   1.377 +	assert_true( elem.itemType.contains('FOO') );
   1.378 +}, 'itemType.remove must remove existing tokens');
   1.379 +test(function () {
   1.380 +        var elem = makeEl('div',{itemtype:'test test'});
   1.381 +        elem.itemType.remove('test');
   1.382 +        assert_equals( elem.itemType.length, 0 );
   1.383 +        assert_false( elem.itemType.contains('test') );
   1.384 +}, 'itemType.remove must remove duplicated tokens');
   1.385 +test(function () {
   1.386 +        var elem = makeEl('div',{itemtype:'token1 token2 token3'});
   1.387 +        elem.itemType.remove('token2');
   1.388 +        assert_equals( elem.itemType.toString(), 'token1 token3' );
   1.389 +}, 'itemType.remove must collapse whitespace around removed tokens');
   1.390 +test(function () {
   1.391 +        var elem = makeEl('div',{itemtype:' token1 token2  '});
   1.392 +        elem.itemType.remove('token2');
   1.393 +        assert_equals( elem.itemType.toString(), 'token1' );
   1.394 +}, 'itemType.remove must remove all useless whitespace');
   1.395 +test(function () {
   1.396 +        var elem = makeEl('div',{itemtype:'  token1  token2  token3  '});
   1.397 +        elem.itemType.remove('token2');
   1.398 +        assert_equals( elem.itemType.toString(), 'token1 token3' );
   1.399 +}, 'itemType.remove must collapse multiple whitespace around removed tokens');
   1.400 +test(function () {
   1.401 +        var elem = makeEl('div',{itemtype:'  token1  token2  token1  '});
   1.402 +        elem.itemType.remove('token2');
   1.403 +        assert_equals( elem.itemType.toString(), 'token1' );
   1.404 +}, 'itemType.remove must remove duplicates when removing tokens');
   1.405 +test(function () {
   1.406 +        var elem = makeEl('div',{itemtype:'  token1  token2  token3  '});
   1.407 +        elem.itemType.remove('token1', 'token3');
   1.408 +        assert_equals( elem.itemType.toString(), 'token2' );
   1.409 +}, 'itemType.remove must collapse whitespace when removing multiple tokens');
   1.410 +test(function () {
   1.411 +        var elem = makeEl('div',{itemtype:'  token1  token2  '});
   1.412 +        elem.itemType.add('token1');
   1.413 +        assert_equals( elem.itemType.toString(), 'token1 token2' );
   1.414 +}, 'itemType.add must remove unused whitespace when the token already exists');
   1.415 +test(function () {
   1.416 +        var elem = makeEl('div',{itemtype:'FOO'});
   1.417 +        assert_true(elem.itemType.toggle('foo'));
   1.418 +        assert_equals( elem.itemType.length, 2 );
   1.419 +        assert_true( elem.itemType.contains('foo') );
   1.420 +        assert_true( elem.itemType.contains('FOO') );
   1.421 +}, 'itemType.toggle must toggle tokens case-sensitively when adding');
   1.422 +test(function () {
   1.423 +        var elem = makeEl('div',{itemtype:'foo FOO'});
   1.424 +        assert_false(elem.itemType.toggle('foo'));
   1.425 +        assert_false(elem.itemType.toggle('FOO'));
   1.426 +        assert_false( elem.itemType.contains('foo') );
   1.427 +        assert_false( elem.itemType.contains('FOO') );
   1.428 +}, 'itemType.toggle must be able to remove tokens case-sensitively');
   1.429 +test(function () {
   1.430 +        var elem = makeEl('div',{itemtype:'foo FOO'});
   1.431 +        elem.itemType.toggle('foo');
   1.432 +        elem.itemType.toggle('FOO');
   1.433 +        assert_equals( elem.getAttribute('itemtype'), '' );
   1.434 +}, 'itemtype attribute must be empty when all classes have been removed');
   1.435 +test(function () {
   1.436 +        var elem = makeEl('div',{itemtype:'foo FOO'});
   1.437 +        elem.itemType.toggle('foo');
   1.438 +        elem.itemType.toggle('FOO');
   1.439 +        assert_equals( elem.itemType.toString(), '' );
   1.440 +}, 'itemType must stringify to an empty string when all classes have been removed');
   1.441 +test(function () {
   1.442 +        var elem = makeEl('div',{itemtype:'foo FOO'});
   1.443 +        elem.itemType.toggle('foo');
   1.444 +        elem.itemType.toggle('FOO');
   1.445 +        assert_equals( elem.itemType.item(0), null );
   1.446 +}, 'itemType.item(0) must return null when all classes have been removed');
   1.447 +test(function () {
   1.448 +        /* the normative part of the spec states that:
   1.449 +        "unless the length is zero, in which case there are no supported property indices"
   1.450 +        ...
   1.451 +        "The term[...] supported property indices [is] used as defined in the WebIDL specification."
   1.452 +        WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
   1.453 +        var elem = makeEl('div',{itemtype:'foo FOO'});
   1.454 +        elem.itemType.toggle('foo');
   1.455 +        elem.itemType.toggle('FOO');
   1.456 +        assert_equals( elem.itemType[0], window.undefined );
   1.457 +}, 'itemType[0] must be undefined when all classes have been removed');
   1.458 +//if the last character of DOMTokenSting underlying character is not a space character, append U+0020", where "space character" is from " \t\r\n\f"
   1.459 +test(function () {
   1.460 +        var elem = makeEl('div',{itemtype:'a '});
   1.461 +        elem.itemType.add('b');
   1.462 +        assert_equals(elem.itemType.toString(),'a b');
   1.463 +}, 'itemType.add should treat " " as a space');
   1.464 +test(function () {
   1.465 +        var elem = makeEl('div',{itemtype:'a\t'});
   1.466 +        elem.itemType.add('b');
   1.467 +        assert_equals(elem.itemType.toString(),'a b');
   1.468 +}, 'itemType.add should normalize \\t as a space');
   1.469 +test(function () {
   1.470 +        var elem = makeEl('div',{itemtype:'a\r'});
   1.471 +        elem.itemType.add('b');
   1.472 +        assert_equals(elem.itemType.toString(),'a b');
   1.473 +}, 'itemType.add should normalize \\r as a space');
   1.474 +test(function () {
   1.475 +        var elem = makeEl('div',{itemtype:'a\n'});
   1.476 +        elem.itemType.add('b');
   1.477 +        assert_equals(elem.itemType.toString(),'a b');
   1.478 +}, 'itemType.add should normalize \\n as a space');
   1.479 +test(function () {
   1.480 +        var elem = makeEl('div',{itemtype:'a\f'});
   1.481 +        elem.itemType.add('b');
   1.482 +        assert_equals(elem.itemType.toString(),'a b');
   1.483 +}, 'itemType.add should normalize \\f as a space');
   1.484 +test(function () {
   1.485 +        var elem = makeEl('div',{itemtype:'foo'});
   1.486 +        elem.itemType.remove('foo');
   1.487 +        elem.removeAttribute('itemtype');
   1.488 +        assert_true( elem.itemType.toggle('foo') );
   1.489 +}, 'itemType.toggle must work after removing the itemtype attribute');
   1.490 +test(function () {
   1.491 +        //WebIDL and ECMAScript 5 - a readonly property has a getter but not a setter
   1.492 +        //ES5 makes [[Put]] fail but not throw
   1.493 +        var failed = false;
   1.494 +        var elem = makeEl('div',{itemtype:'token1'});
   1.495 +        try {
   1.496 +                elem.itemType.length = 0;
   1.497 +        } catch(e) {
   1.498 +                failed = e;
   1.499 +        }
   1.500 +        assert_equals(elem.itemType.length,1);
   1.501 +        assert_false(failed,'an error was thrown');
   1.502 +}, 'itemType.length must be read-only');
   1.503 +test(function () {
   1.504 +        var failed = false, elem = makeEl('div',{itemtype:'test'}), realList = elem.itemType;
   1.505 +        try {
   1.506 +                elem.itemType = 'dummy';
   1.507 +        } catch(e) {
   1.508 +                failed = e;
   1.509 +        }
   1.510 +        assert_equals(elem.itemType,realList);
   1.511 +        assert_equals(elem.itemType.toString(),'dummy','attempting to write should modify the underlying string');
   1.512 +        assert_false(failed,'an error was thrown');
   1.513 +}, 'itemType must be read-only');
   1.514 +
   1.515 +/* itemProp property tests (properties collection tests are done later) */
   1.516 +test(function () {
   1.517 +	assert_equals(makeEl('div',{}).itemProp.toString(),'','no attribute');
   1.518 +	assert_equals(makeEl('div',{itemprop:' http://example.com/foo#bar  test '}).itemProp.toString(),' http://example.com/foo#bar  test ','with URL and simple tokens');
   1.519 +	var testEl = makeEl('div',{itemprop:'http://example.com/foo#bar'});
   1.520 +	testEl.removeAttribute('itemprop');
   1.521 +	assert_equals(testEl.itemProp.toString(),'','removed attribute');
   1.522 +}, 'the itemprop attribute must be reflected by the .itemProp property');
   1.523 +test(function () {
   1.524 +	assert_equals( typeof makeEl('div',{}).itemProp, 'object' );
   1.525 +}, 'the itemProp property must be an object');
   1.526 +test(function () {
   1.527 +	assert_true( makeEl('div',{}).itemProp instanceof DOMTokenList, 'instanceof test' );
   1.528 +	DOMTokenList.prototype.customProperty = true;
   1.529 +	assert_true( makeEl('div',{}).itemProp.customProperty, 'inheritance test' );
   1.530 +}, 'the itemProp property must implement DOMTokenList');
   1.531 +test(function () {
   1.532 +	var testEl = makeEl('div',{});
   1.533 +	assert_equals( testEl.itemProp, testEl.itemProp );
   1.534 +}, 'the itemProp property must always reference the same object');
   1.535 +test(function () {
   1.536 +	assert_equals( makeEl('div',{itemprop:'test test'}).itemProp.length, 2, 'duplicates in initial string should be preserved' );
   1.537 +	assert_equals( makeEl('div',{itemprop:'test test'}).itemProp.item(0), 'test' );
   1.538 +	assert_true( makeEl('div',{itemprop:'test test'}).itemProp.contains('test') );
   1.539 +}, 'itemProp must be correct for an element that has itemprop tokens');
   1.540 +test(function () {
   1.541 +	assert_equals( makeEl('div',{itemprop:' '}).itemProp.length, 0 );
   1.542 +}, 'itemProp.length must be 0 for an element that has no tokens');
   1.543 +test(function () {
   1.544 +	assert_false( makeEl('div',{itemprop:' '}).itemProp.contains('foo') );
   1.545 +}, 'itemProp must not contain an undefined class');
   1.546 +test(function () {
   1.547 +	assert_equals( makeEl('div',{itemprop:' '}).itemProp.item(0), null );
   1.548 +}, 'itemProp.item() must return null for out-of-range index');
   1.549 +test(function () {
   1.550 +	assert_equals( makeEl('div',{itemprop:' '}).itemProp.item(-1), null );
   1.551 +}, 'itemProp.item() must return null for negative index');
   1.552 +test(function () {
   1.553 +	/* the normative part of the spec states that:
   1.554 +	"unless the length is zero, in which case there are no supported property indices"
   1.555 +	...
   1.556 +	"The term[...] supported property indices [is] used as defined in the WebIDL specification."
   1.557 +	WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
   1.558 +	assert_equals( makeEl('div',{itemprop:' '}).itemProp[0], window.undefined );
   1.559 +}, 'itemProp[index] must be undefined for out-of-range index');
   1.560 +test(function () {
   1.561 +	assert_equals( makeEl('div',{itemprop:' '}).itemProp[-1], window.undefined );
   1.562 +}, 'itemProp[index] must be undefined for negative index');
   1.563 +test(function () {
   1.564 +	assert_equals( makeEl('div',{itemprop:' '}).itemProp.toString(), ' ' );
   1.565 +}, 'empty itemProp should stringify to contain the attribute\'s whitespace');
   1.566 +test(function () {
   1.567 +	assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemprop:' '}).itemProp.contains(''); } );
   1.568 +}, 'itemProp.contains(empty_string) must throw a SYNTAX_ERR');
   1.569 +test(function () {
   1.570 +	assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemprop:' '}).itemProp.add(''); } );
   1.571 +}, 'itemProp.add(empty_string) must throw a SYNTAX_ERR');
   1.572 +test(function () {
   1.573 +	assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemprop:' '}).itemProp.remove(''); } );
   1.574 +}, 'itemProp.remove(empty_string) must throw a SYNTAX_ERR');
   1.575 +test(function () {
   1.576 +	assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemprop:' '}).itemProp.toggle(''); } );
   1.577 +}, 'itemProp.toggle(empty_string) must throw a SYNTAX_ERR');
   1.578 +test(function () {
   1.579 +	assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemprop:' '}).itemProp.contains('a b'); } );
   1.580 +}, '.contains(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
   1.581 +test(function () {
   1.582 +	assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemprop:' '}).itemProp.add('a b'); } );
   1.583 +}, 'itemProp.add(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
   1.584 +test(function () {
   1.585 +	assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemprop:' '}).itemProp.remove('a b'); } );
   1.586 +}, 'itemProp.remove(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
   1.587 +test(function () {
   1.588 +	assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemprop:' '}).itemProp.toggle('a b'); } );
   1.589 +}, 'itemProp.toggle(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
   1.590 +test(function () {
   1.591 +	var testEl = makeEl('div',{itemprop:'foo'});
   1.592 +	assert_true( testEl.itemProp.contains('foo'), 'before change' );
   1.593 +	testEl.setAttribute('itemprop','bar');
   1.594 +	assert_true( testEl.itemProp.contains('bar'), 'after change' );
   1.595 +	assert_false( testEl.itemProp.contains('foo'), 'after change' );
   1.596 +}, 'itemProp.contains must update when the underlying attribute is changed');
   1.597 +test(function () {
   1.598 +	assert_false( makeEl('div',{itemprop:'foo'}).itemProp.contains('FOO') );
   1.599 +}, 'itemProp.contains must be case sensitive');
   1.600 +test(function () {
   1.601 +	assert_false( makeEl('div',{itemprop:'foo'}).itemProp.contains('foo.') );
   1.602 +	assert_false( makeEl('div',{itemprop:'foo'}).itemProp.contains('foo)') );
   1.603 +	assert_false( makeEl('div',{itemprop:'foo'}).itemProp.contains('foo\'') );
   1.604 +	assert_false( makeEl('div',{itemprop:'foo'}).itemProp.contains('foo$') );
   1.605 +	assert_false( makeEl('div',{itemprop:'foo'}).itemProp.contains('foo~') );
   1.606 +	assert_false( makeEl('div',{itemprop:'foo'}).itemProp.contains('foo?') );
   1.607 +	assert_false( makeEl('div',{itemprop:'foo'}).itemProp.contains('foo\\') );
   1.608 +}, 'itemProp.contains must not match when punctuation characters are added');
   1.609 +test(function () {
   1.610 +	var elem = makeEl('div',{itemprop:'foo'});
   1.611 +	elem.itemProp.add('FOO');
   1.612 +	assert_true( elem.itemProp.contains('foo') );
   1.613 +}, 'itemProp.add must not remove existing tokens');
   1.614 +test(function () {
   1.615 +	assert_true( makeEl('div',{itemprop:'foo FOO'}).itemProp.contains('FOO') );
   1.616 +}, 'itemProp.contains case sensitivity must match a case-specific string');
   1.617 +test(function () {
   1.618 +	assert_equals( makeEl('div',{itemprop:'foo FOO'}).itemProp.length, 2 );
   1.619 +}, 'itemProp.length must correctly reflect the number of tokens');
   1.620 +test(function () {
   1.621 +	assert_equals( makeEl('div',{itemprop:'foo FOO'}).itemProp.item(0), 'foo' );
   1.622 +}, 'itemProp.item(0) must return the first token');
   1.623 +test(function () {
   1.624 +	var elem = makeEl('div',{itemprop:'foo'});
   1.625 +	elem.itemProp.add('FOO');
   1.626 +	assert_equals( elem.itemProp.item(1), 'FOO' );
   1.627 +}, 'itemProp.item must return case-sensitive strings and preserve token order');
   1.628 +test(function () {
   1.629 +	assert_equals( makeEl('div',{itemprop:'foo FOO'}).itemProp[0], 'foo' );
   1.630 +}, 'itemProp[0] must return the first token');
   1.631 +test(function () {
   1.632 +	assert_equals( makeEl('div',{itemprop:'foo FOO'}).itemProp[1], 'FOO' );
   1.633 +}, 'itemProp[index] must return case-sensitive strings and preserve token order');
   1.634 +test(function () {
   1.635 +	/* the normative part of the spec states that:
   1.636 +	"unless the length is zero, in which case there are no supported property indices"
   1.637 +	...
   1.638 +	"The term[...] supported property indices [is] used as defined in the WebIDL specification."
   1.639 +	WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
   1.640 +	assert_equals( makeEl('div',{itemprop:'foo FOO'}).itemProp[2], window.undefined );
   1.641 +}, 'itemProp[index] must still be undefined for out-of-range index when earlier indexes exist');
   1.642 +test(function () {
   1.643 +	var elem = makeEl('div',{});
   1.644 +	elem.itemProp.add('foo');
   1.645 +	elem.itemProp.add('FOO');
   1.646 +	assert_equals( elem.getAttribute('itemprop'), 'foo FOO' );
   1.647 +}, 'itemprop attribute must update correctly when items have been added through itemProp');
   1.648 +test(function () {
   1.649 +	var elem = makeEl('div',{});
   1.650 +	elem.itemProp.add('foo');
   1.651 +	elem.itemProp.add('FOO');
   1.652 +	assert_equals( elem.itemProp + '', 'foo FOO' );
   1.653 +}, 'itemProp must stringify correctly when items have been added');
   1.654 +test(function () {
   1.655 +	var elem = makeEl('div',{itemprop:'foo FOO'});
   1.656 +	elem.itemProp.add('foo');
   1.657 +	assert_equals( elem.itemProp.length, 2 );
   1.658 +	assert_equals( elem.itemProp + '', 'foo FOO' );
   1.659 +}, 'itemProp.add must not make any changes if an existing token is added');
   1.660 +test(function () {
   1.661 +	var elem = makeEl('div',{itemprop:'foo FOO'});
   1.662 +	elem.itemProp.remove('bar');
   1.663 +	assert_equals( elem.itemProp.length, 2 );
   1.664 +	assert_equals( elem.itemProp + '', 'foo FOO' );
   1.665 +}, 'itemProp.remove must not make any changes if a non-existing token is removed');
   1.666 +test(function () {
   1.667 +	var elem = makeEl('div',{itemprop:'foo FOO'});
   1.668 +	elem.itemProp.remove('foo');
   1.669 +	assert_equals( elem.itemProp.length, 1 );
   1.670 +	assert_equals( elem.itemProp.toString(), 'FOO' );
   1.671 +	assert_false( elem.itemProp.contains('foo') );
   1.672 +	assert_true( elem.itemProp.contains('FOO') );
   1.673 +}, 'itemProp.remove must remove existing tokens');
   1.674 +test(function () {
   1.675 +	var elem = makeEl('div',{itemprop:'test test'});
   1.676 +	elem.itemProp.remove('test');
   1.677 +	assert_equals( elem.itemProp.length, 0 );
   1.678 +	assert_false( elem.itemProp.contains('test') );
   1.679 +}, 'itemProp.remove must remove duplicated tokens');
   1.680 +test(function () {
   1.681 +	var elem = makeEl('div',{itemprop:'token1 token2 token3'});
   1.682 +	elem.itemProp.remove('token2');
   1.683 +	assert_equals( elem.itemProp.toString(), 'token1 token3' );
   1.684 +}, 'itemProp.remove must collapse whitespace around removed tokens');
   1.685 +test(function () {
   1.686 +	var elem = makeEl('div',{itemprop:'  token1  token2  token3  '});
   1.687 +	elem.itemProp.remove('token2');
   1.688 +	assert_equals( elem.itemProp.toString(), 'token1 token3' );
   1.689 +}, 'itemProp.remove must remove all useless whitespace');
   1.690 +test(function () {
   1.691 +	var elem = makeEl('div',{itemprop:'  token1  token2  token3  '});
   1.692 +	elem.itemProp.remove('token1', 'token3');
   1.693 +	assert_equals( elem.itemProp.toString(), 'token2' );
   1.694 +}, 'itemProp.remove must remove useless whitespace when removing multiple tokens');
   1.695 +test(function () {
   1.696 +	var elem = makeEl('div',{itemprop:'  token1  token1  '});
   1.697 +	elem.itemProp.add('token1');
   1.698 +	assert_equals( elem.itemProp.toString(), 'token1' );
   1.699 +}, 'itemProp.add must remove useless whitespace and duplicates when the token already exists');
   1.700 +test(function () {
   1.701 +	var elem = makeEl('div',{itemprop:'FOO'});
   1.702 +	assert_true(elem.itemProp.toggle('foo'));
   1.703 +	assert_equals( elem.itemProp.length, 2 );
   1.704 +	assert_true( elem.itemProp.contains('foo') );
   1.705 +	assert_true( elem.itemProp.contains('FOO') );
   1.706 +}, 'itemProp.toggle must toggle tokens case-sensitively when adding');
   1.707 +test(function () {
   1.708 +	var elem = makeEl('div',{itemprop:'foo FOO'});
   1.709 +	assert_false(elem.itemProp.toggle('foo'));
   1.710 +	assert_false(elem.itemProp.toggle('FOO'));
   1.711 +	assert_false( elem.itemProp.contains('foo') );
   1.712 +	assert_false( elem.itemProp.contains('FOO') );
   1.713 +}, 'itemProp.toggle must be able to remove tokens case-sensitively');
   1.714 +test(function () {
   1.715 +	var elem = makeEl('div',{itemprop:'foo FOO'});
   1.716 +	elem.itemProp.toggle('foo');
   1.717 +	elem.itemProp.toggle('FOO');
   1.718 +	assert_equals( elem.getAttribute('itemprop'), '' );
   1.719 +}, 'itemprop attribute must be empty when all classes have been removed');
   1.720 +test(function () {
   1.721 +	var elem = makeEl('div',{itemprop:'foo FOO'});
   1.722 +	elem.itemProp.toggle('foo');
   1.723 +	elem.itemProp.toggle('FOO');
   1.724 +	assert_equals( elem.itemProp.toString(), '' );
   1.725 +}, 'itemProp must stringify to an empty string when all classes have been removed');
   1.726 +test(function () {
   1.727 +	var elem = makeEl('div',{itemprop:'foo FOO'});
   1.728 +	elem.itemProp.toggle('foo');
   1.729 +	elem.itemProp.toggle('FOO');
   1.730 +	assert_equals( elem.itemProp.item(0), null );
   1.731 +}, 'itemProp.item(0) must return null when all classes have been removed');
   1.732 +test(function () {
   1.733 +	/* the normative part of the spec states that:
   1.734 +	"unless the length is zero, in which case there are no supported property indices"
   1.735 +	...
   1.736 +	"The term[...] supported property indices [is] used as defined in the WebIDL specification."
   1.737 +	WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
   1.738 +	var elem = makeEl('div',{itemprop:'foo FOO'});
   1.739 +	elem.itemProp.toggle('foo');
   1.740 +	elem.itemProp.toggle('FOO');
   1.741 +	assert_equals( elem.itemProp[0], window.undefined );
   1.742 +}, 'itemProp[0] must be undefined when all classes have been removed');
   1.743 +//if the last character of DOMTokenSting underlying character is not a space character, append U+0020", where "space character" is from " \t\r\n\f"
   1.744 +test(function () {
   1.745 +	var elem = makeEl('div',{itemprop:'a '});
   1.746 +	elem.itemProp.add('b');
   1.747 +	assert_equals(elem.itemProp.toString(),'a b');
   1.748 +}, 'itemProp.add should treat " " as a space');
   1.749 +test(function () {
   1.750 +	var elem = makeEl('div',{itemprop:'a\t'});
   1.751 +	elem.itemProp.add('b');
   1.752 +	assert_equals(elem.itemProp.toString(),'a b');
   1.753 +}, 'itemProp.add should normalize \\t as a space');
   1.754 +test(function () {
   1.755 +	var elem = makeEl('div',{itemprop:'a\r'});
   1.756 +	elem.itemProp.add('b');
   1.757 +	assert_equals(elem.itemProp.toString(),'a b');
   1.758 +}, 'itemProp.add should normalize \\r as a space');
   1.759 +test(function () {
   1.760 +	var elem = makeEl('div',{itemprop:'a\n'});
   1.761 +	elem.itemProp.add('b');
   1.762 +	assert_equals(elem.itemProp.toString(),'a b');
   1.763 +}, 'itemProp.add should normalize \\n as a space');
   1.764 +test(function () {
   1.765 +	var elem = makeEl('div',{itemprop:'a\f'});
   1.766 +	elem.itemProp.add('b');
   1.767 +	assert_equals(elem.itemProp.toString(),'a b');
   1.768 +}, 'itemProp.add should normalize \\f as a space');
   1.769 +test(function () {
   1.770 +	var elem = makeEl('div',{itemprop:'foo'});
   1.771 +	elem.itemProp.remove('foo');
   1.772 +	elem.removeAttribute('itemprop');
   1.773 +	assert_true( elem.itemProp.toggle('foo') );
   1.774 +}, 'itemProp.toggle must work after removing the itemprop attribute');
   1.775 +test(function () {
   1.776 +	//WebIDL and ECMAScript 5 - a readonly property has a getter but not a setter
   1.777 +	//ES5 makes [[Put]] fail but not throw
   1.778 +	var failed = false;
   1.779 +	var elem = makeEl('div',{itemprop:'token1'});
   1.780 +	try {
   1.781 +		elem.itemProp.length = 0;
   1.782 +	} catch(e) {
   1.783 +		failed = e;
   1.784 +	}
   1.785 +	assert_equals(elem.itemProp.length,1);
   1.786 +	assert_false(failed,'an error was thrown');
   1.787 +}, 'itemProp.length must be read-only');
   1.788 +test(function () {
   1.789 +	var failed = false, elem = makeEl('div',{itemprop:'test'}), realList = elem.itemProp;
   1.790 +	try {
   1.791 +		elem.itemProp = 'dummy';
   1.792 +	} catch(e) {
   1.793 +		failed = e;
   1.794 +	}
   1.795 +	assert_equals(elem.itemProp,realList);
   1.796 +	assert_equals(elem.itemProp.toString(),'dummy','attempting to write should modify the underlying string');
   1.797 +	assert_false(failed,'an error was thrown');
   1.798 +}, 'itemProp must be read-only');
   1.799 +
   1.800 +/* itemId property tests */
   1.801 +test(function () {
   1.802 +	assert_equals( makeEl('div',{itemid:'http://example.com/foo'}).itemId, 'http://example.com/foo' );
   1.803 +	assert_equals( makeEl('div',{itemid:'http://example.com/FOO'}).itemId, 'http://example.com/FOO', 'case-sensitive' );
   1.804 +	assert_equals( makeEl('div',{itemid:' http://example.com/foo '}).itemId, 'http://example.com/foo', 'whitespace' );
   1.805 +	assert_equals( makeEl('div',{itemid:'data:text/plain,'}).itemId, 'data:text/plain,' );
   1.806 +	assert_equals( makeEl('div',{itemid:'madeup:onthespot'}).itemId, 'madeup:onthespot' );
   1.807 +	assert_equals( makeEl('div',{}).itemId, '' );
   1.808 +}, 'the itemid attribute must be reflected by the .itemId property');
   1.809 +test(function () {
   1.810 +	var testEl = makeEl('div',{});
   1.811 +	testEl.itemId = 'http://example.com/foo';
   1.812 +	assert_equals(testEl.itemId,'http://example.com/foo','writing a URL');
   1.813 +	testEl.itemId = '';
   1.814 +	assert_equals(testEl.itemId,location.href,'writing an empty string');
   1.815 +}, 'the itemId property must be read/write');
   1.816 +test(function () {
   1.817 +	var testEl = makeEl('div',{});
   1.818 +	testEl.itemId = 'http://example.com/foo';
   1.819 +	assert_true(testEl.hasAttribute('itemid'),'writing a URL');
   1.820 +	assert_equals(testEl.getAttribute('itemid'),'http://example.com/foo','writing a URL');
   1.821 +	testEl = makeEl('div',{})
   1.822 +	testEl.itemId = '';
   1.823 +	assert_true(testEl.hasAttribute('itemid'),'writing an empty string');
   1.824 +	assert_equals(testEl.getAttribute('itemid'),'','writing an empty string');
   1.825 +}, 'writing to the itemId property must create the itemid content attribute');
   1.826 +test(function () {
   1.827 +	assert_equals( makeEl('div',{itemid:'foo'}).itemId, location.href.replace(/\/[^\/]*$/,'\/foo'),'foo' );
   1.828 +	assert_equals( makeEl('div',{itemid:'foo bar'}).itemId, location.href.replace(/\/[^\/]*$/,'\/foo%20bar'),'foo bar' );
   1.829 +	assert_equals( makeEl('div',{itemid:'foo\u0129 bar'}).itemId, location.href.replace(/\/[^\/]*$/,'\/foo%C4%A9%20bar'),'foo\u0129 bar' );
   1.830 +}, 'the itemId property must see the resolved itemid URL');
   1.831 +test(function () {
   1.832 +	var testEl = makeEl('div',{});
   1.833 +	testEl.itemId = 'foo';
   1.834 +	assert_equals( testEl.itemId, location.href.replace(/\/[^\/]*$/,'\/foo') );
   1.835 +}, 'the itemId property must see the resolved itemId property URL on setting');
   1.836 +test(function () {
   1.837 +	var testEl = makeEl('div',{});
   1.838 +	testEl.itemId = 'foo';
   1.839 +	assert_equals( testEl.getAttribute('itemid'), 'foo' );
   1.840 +}, 'the itemid attribute must see the resolved itemId URL');
   1.841 +
   1.842 +/* itemRef property tests (properties collection tests are done later) */
   1.843 +test(function () {
   1.844 +	assert_equals(makeEl('div',{}).itemRef.toString(),'','no attribute');
   1.845 +	assert_equals(makeEl('div',{itemref:' foo  bar '}).itemRef.toString(),' foo  bar ','with simple tokens');
   1.846 +	var testEl = makeEl('div',{itemref:'foo'});
   1.847 +	testEl.removeAttribute('itemref');
   1.848 +	assert_equals(testEl.itemRef.toString(),'','removed attribute');
   1.849 +}, 'the itemref attribute must be reflected by the .itemRef property');
   1.850 +test(function () {
   1.851 +	assert_equals( typeof makeEl('div',{}).itemRef, 'object' );
   1.852 +}, 'the itemRef property must be an object');
   1.853 +test(function () {
   1.854 +	assert_true( makeEl('div',{}).itemRef instanceof DOMTokenList, 'instanceof test' );
   1.855 +	DOMTokenList.prototype.customProperty = true;
   1.856 +	assert_true( makeEl('div',{}).itemRef.customProperty, 'inheritance test' );
   1.857 +}, 'the itemRef property must implement DOMTokenList');
   1.858 +test(function () {
   1.859 +	var testEl = makeEl('div',{});
   1.860 +	assert_equals( testEl.itemRef, testEl.itemRef );
   1.861 +}, 'the itemRef property must always reference the same object');
   1.862 +test(function () {
   1.863 +	assert_equals( makeEl('div',{itemref:'test test'}).itemRef.length, 2, 'duplicates in initial string should be preserved' );
   1.864 +	assert_equals( makeEl('div',{itemref:'test test'}).itemRef.item(0), 'test' );
   1.865 +	assert_true( makeEl('div',{itemref:'test test'}).itemRef.contains('test') );
   1.866 +}, 'itemRef must be correct for an element that has itemref tokens');
   1.867 +test(function () {
   1.868 +	assert_equals( makeEl('div',{itemref:' '}).itemRef.length, 0 );
   1.869 +}, 'itemRef.length must be 0 for an element that has no tokens');
   1.870 +test(function () {
   1.871 +	assert_false( makeEl('div',{itemref:' '}).itemRef.contains('foo') );
   1.872 +}, 'itemRef must not contain an undefined class');
   1.873 +test(function () {
   1.874 +	assert_equals( makeEl('div',{itemref:' '}).itemRef.item(0), null );
   1.875 +}, 'itemRef.item() must return null for out-of-range index');
   1.876 +test(function () {
   1.877 +	assert_equals( makeEl('div',{itemref:' '}).itemRef.item(-1), null );
   1.878 +}, 'itemRef.item() must return null for negative index');
   1.879 +test(function () {
   1.880 +	/* the normative part of the spec states that:
   1.881 +	"unless the length is zero, in which case there are no supported property indices"
   1.882 +	...
   1.883 +	"The term[...] supported property indices [is] used as defined in the WebIDL specification."
   1.884 +	WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
   1.885 +	assert_equals( makeEl('div',{itemref:' '}).itemRef[0], window.undefined );
   1.886 +}, 'itemRef[index] must be undefined for out-of-range index');
   1.887 +test(function () {
   1.888 +	assert_equals( makeEl('div',{itemref:' '}).itemRef[-1], window.undefined );
   1.889 +}, 'itemRef[index] must be undefined for negative index');
   1.890 +test(function () {
   1.891 +	assert_equals( makeEl('div',{itemref:' '}).itemRef.toString(), ' ' );
   1.892 +}, 'empty itemRef should stringify to contain the attribute\'s whitespace');
   1.893 +test(function () {
   1.894 +	assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemref:' '}).itemRef.contains(''); } );
   1.895 +}, 'itemRef.contains(empty_string) must throw a SYNTAX_ERR');
   1.896 +test(function () {
   1.897 +	assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemref:' '}).itemRef.add(''); } );
   1.898 +}, 'itemRef.add(empty_string) must throw a SYNTAX_ERR');
   1.899 +test(function () {
   1.900 +	assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemref:' '}).itemRef.remove(''); } );
   1.901 +}, 'itemRef.remove(empty_string) must throw a SYNTAX_ERR');
   1.902 +test(function () {
   1.903 +	assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemref:' '}).itemRef.toggle(''); } );
   1.904 +}, 'itemRef.toggle(empty_string) must throw a SYNTAX_ERR');
   1.905 +test(function () {
   1.906 +	assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemref:' '}).itemRef.contains('a b'); } );
   1.907 +}, 'itemRef.contains(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
   1.908 +test(function () {
   1.909 +	assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemref:' '}).itemRef.add('a b'); } );
   1.910 +}, 'itemRef.add(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
   1.911 +test(function () {
   1.912 +	assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemref:' '}).itemRef.remove('a b'); } );
   1.913 +}, 'itemRef.remove(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
   1.914 +test(function () {
   1.915 +	assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemref:' '}).itemRef.toggle('a b'); } );
   1.916 +}, 'itemRef.toggle(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
   1.917 +test(function () {
   1.918 +	var testEl = makeEl('div',{itemref:'foo'});
   1.919 +	assert_true( testEl.itemRef.contains('foo'), 'before change' );
   1.920 +	testEl.setAttribute('itemref','bar');
   1.921 +	assert_true( testEl.itemRef.contains('bar'), 'after change' );
   1.922 +	assert_false( testEl.itemRef.contains('foo'), 'after change' );
   1.923 +}, 'itemRef.contains must update when the underlying attribute is changed');
   1.924 +test(function () {
   1.925 +	assert_false( makeEl('div',{itemref:'foo'}).itemRef.contains('FOO') );
   1.926 +}, 'itemRef.contains must be case sensitive');
   1.927 +test(function () {
   1.928 +	assert_false( makeEl('div',{itemref:'foo'}).itemRef.contains('foo.') );
   1.929 +	assert_false( makeEl('div',{itemref:'foo'}).itemRef.contains('foo)') );
   1.930 +	assert_false( makeEl('div',{itemref:'foo'}).itemRef.contains('foo\'') );
   1.931 +	assert_false( makeEl('div',{itemref:'foo'}).itemRef.contains('foo$') );
   1.932 +	assert_false( makeEl('div',{itemref:'foo'}).itemRef.contains('foo~') );
   1.933 +	assert_false( makeEl('div',{itemref:'foo'}).itemRef.contains('foo?') );
   1.934 +	assert_false( makeEl('div',{itemref:'foo'}).itemRef.contains('foo\\') );
   1.935 +}, 'itemRef.contains must not match when punctuation characters are added');
   1.936 +test(function () {
   1.937 +	var elem = makeEl('div',{itemref:'foo'});
   1.938 +	elem.itemRef.add('FOO');
   1.939 +	assert_true( elem.itemRef.contains('foo') );
   1.940 +}, 'itemRef.add must not remove existing tokens');
   1.941 +test(function () {
   1.942 +	assert_true( makeEl('div',{itemref:'foo FOO'}).itemRef.contains('FOO') );
   1.943 +}, 'itemRef.contains case sensitivity must match a case-specific string');
   1.944 +test(function () {
   1.945 +	assert_equals( makeEl('div',{itemref:'foo FOO'}).itemRef.length, 2 );
   1.946 +}, 'itemRef.length must correctly reflect the number of tokens');
   1.947 +test(function () {
   1.948 +	assert_equals( makeEl('div',{itemref:'foo FOO'}).itemRef.item(0), 'foo' );
   1.949 +}, 'itemRef.item(0) must return the first token');
   1.950 +test(function () {
   1.951 +	var elem = makeEl('div',{itemref:'foo'});
   1.952 +	elem.itemRef.add('FOO');
   1.953 +	assert_equals( elem.itemRef.item(1), 'FOO' );
   1.954 +}, 'itemRef.item must return case-sensitive strings and preserve token order');
   1.955 +test(function () {
   1.956 +	assert_equals( makeEl('div',{itemref:'foo FOO'}).itemRef[0], 'foo' );
   1.957 +}, 'itemRef[0] must return the first token');
   1.958 +test(function () {
   1.959 +	assert_equals( makeEl('div',{itemref:'foo FOO'}).itemRef[1], 'FOO' );
   1.960 +}, 'itemRef[index] must return case-sensitive strings and preserve token order');
   1.961 +test(function () {
   1.962 +	/* the normative part of the spec states that:
   1.963 +	"unless the length is zero, in which case there are no supported property indices"
   1.964 +	...
   1.965 +	"The term[...] supported property indices [is] used as defined in the WebIDL specification."
   1.966 +	WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
   1.967 +	assert_equals( makeEl('div',{itemref:'foo FOO'}).itemRef[2], window.undefined );
   1.968 +}, 'itemRef[index] must still be undefined for out-of-range index when earlier indexes exist');
   1.969 +test(function () {
   1.970 +	var elem = makeEl('div',{});
   1.971 +	elem.itemRef.add('foo');
   1.972 +	elem.itemRef.add('FOO');
   1.973 +	assert_equals( elem.getAttribute('itemref'), 'foo FOO' );
   1.974 +}, 'itemref attribute must update correctly when items have been added through itemRef');
   1.975 +test(function () {
   1.976 +	var elem = makeEl('div',{});
   1.977 +	elem.itemRef.add('foo');
   1.978 +	elem.itemRef.add('FOO');
   1.979 +	assert_equals( elem.itemRef + '', 'foo FOO' );
   1.980 +}, 'itemRef must stringify correctly when items have been added');
   1.981 +test(function () {
   1.982 +	var elem = makeEl('div',{itemref:'foo FOO'});
   1.983 +	elem.itemRef.add('foo');
   1.984 +	assert_equals( elem.itemRef.length, 2 );
   1.985 +	assert_equals( elem.itemRef + '', 'foo FOO' );
   1.986 +}, 'itemRef.add must not make any changes if an existing token is added');
   1.987 +test(function () {
   1.988 +	var elem = makeEl('div',{itemref:'foo FOO'});
   1.989 +	elem.itemRef.remove('bar');
   1.990 +	assert_equals( elem.itemRef.length, 2 );
   1.991 +	assert_equals( elem.itemRef + '', 'foo FOO' );
   1.992 +}, 'itemRef.remove must not make any changes if a non-existing token is removed');
   1.993 +test(function () {
   1.994 +	var elem = makeEl('div',{itemref:'foo FOO'});
   1.995 +	elem.itemRef.remove('foo');
   1.996 +	assert_equals( elem.itemRef.length, 1 );
   1.997 +	assert_equals( elem.itemRef.toString(), 'FOO' );
   1.998 +	assert_false( elem.itemRef.contains('foo') );
   1.999 +	assert_true( elem.itemRef.contains('FOO') );
  1.1000 +}, 'itemRef.remove must remove existing tokens');
  1.1001 +test(function () {
  1.1002 +	var elem = makeEl('div',{itemref:'test test'});
  1.1003 +	elem.itemRef.remove('test');
  1.1004 +	assert_equals( elem.itemRef.length, 0 );
  1.1005 +	assert_false( elem.itemRef.contains('test') );
  1.1006 +}, 'itemRef.remove must remove duplicated tokens');
  1.1007 +test(function () {
  1.1008 +	var elem = makeEl('div',{itemref:'token1 token2 token3'});
  1.1009 +	elem.itemRef.remove('token2');
  1.1010 +	assert_equals( elem.itemRef.toString(), 'token1 token3' );
  1.1011 +}, 'itemRef.remove must collapse whitespace around removed tokens');
  1.1012 +test(function () {
  1.1013 +	var elem = makeEl('div',{itemref:' token1 token2  '});
  1.1014 +	elem.itemRef.remove('token2');
  1.1015 +	assert_equals( elem.itemRef.toString(), 'token1' );
  1.1016 +}, 'itemRef.remove must remove useless whitespace when removing tokens');
  1.1017 +test(function () {
  1.1018 +	var elem = makeEl('div',{itemref:'  token1  token2  token3  '});
  1.1019 +	elem.itemRef.remove('token2');
  1.1020 +	assert_equals( elem.itemRef.toString(), 'token1 token3' );
  1.1021 +}, 'itemRef.remove must remove useless whitespace when removing tokens');
  1.1022 +test(function () {
  1.1023 +	var elem = makeEl('div',{itemref:'  token1  token2  token3  '});
  1.1024 +	elem.itemRef.remove('token1', 'token3');
  1.1025 +	assert_equals( elem.itemRef.toString(), 'token2' );
  1.1026 +}, 'itemRef.remove must collapse whitespace when removing multiple tokens');
  1.1027 +test(function () {
  1.1028 +	var elem = makeEl('div',{itemref:'  token1  token1  '});
  1.1029 +	elem.itemRef.add('token1');
  1.1030 +	assert_equals( elem.itemRef.toString(), 'token1' );
  1.1031 +}, 'itemRef.add must remove whitespace and duplicate when the token already exists');
  1.1032 +test(function () {
  1.1033 +	var elem = makeEl('div',{itemref:'FOO'});
  1.1034 +	assert_true(elem.itemRef.toggle('foo'));
  1.1035 +	assert_equals( elem.itemRef.length, 2 );
  1.1036 +	assert_true( elem.itemRef.contains('foo') );
  1.1037 +	assert_true( elem.itemRef.contains('FOO') );
  1.1038 +}, 'itemRef.toggle must toggle tokens case-sensitively when adding');
  1.1039 +test(function () {
  1.1040 +	var elem = makeEl('div',{itemref:'foo FOO'});
  1.1041 +	assert_false(elem.itemRef.toggle('foo'));
  1.1042 +	assert_false(elem.itemRef.toggle('FOO'));
  1.1043 +	assert_false( elem.itemRef.contains('foo') );
  1.1044 +	assert_false( elem.itemRef.contains('FOO') );
  1.1045 +}, 'itemRef.toggle must be able to remove tokens case-sensitively');
  1.1046 +test(function () {
  1.1047 +	var elem = makeEl('div',{itemref:'foo FOO'});
  1.1048 +	elem.itemRef.toggle('foo');
  1.1049 +	elem.itemRef.toggle('FOO');
  1.1050 +	assert_equals( elem.getAttribute('itemref'), '' );
  1.1051 +}, 'itemref attribute must be empty when all classes have been removed');
  1.1052 +test(function () {
  1.1053 +	var elem = makeEl('div',{itemref:'foo FOO'});
  1.1054 +	elem.itemRef.toggle('foo');
  1.1055 +	elem.itemRef.toggle('FOO');
  1.1056 +	assert_equals( elem.itemRef.toString(), '' );
  1.1057 +}, 'itemRef must stringify to an empty string when all classes have been removed');
  1.1058 +test(function () {
  1.1059 +	var elem = makeEl('div',{itemref:'foo FOO'});
  1.1060 +	elem.itemRef.toggle('foo');
  1.1061 +	elem.itemRef.toggle('FOO');
  1.1062 +	assert_equals( elem.itemRef.item(0), null );
  1.1063 +}, 'itemRef.item(0) must return null when all classes have been removed');
  1.1064 +test(function () {
  1.1065 +	/* the normative part of the spec states that:
  1.1066 +	"unless the length is zero, in which case there are no supported property indices"
  1.1067 +	...
  1.1068 +	"The term[...] supported property indices [is] used as defined in the WebIDL specification."
  1.1069 +	WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
  1.1070 +	var elem = makeEl('div',{itemref:'foo FOO'});
  1.1071 +	elem.itemRef.toggle('foo');
  1.1072 +	elem.itemRef.toggle('FOO');
  1.1073 +	assert_equals( elem.itemRef[0], window.undefined );
  1.1074 +}, 'itemRef[0] must be undefined when all classes have been removed');
  1.1075 +//if the last character of DOMTokenSting underlying character is not a space character, append U+0020", where "space character" is from " \t\r\n\f"
  1.1076 +test(function () {
  1.1077 +	var elem = makeEl('div',{itemref:'a '});
  1.1078 +	elem.itemRef.add('b');
  1.1079 +	assert_equals(elem.itemRef.toString(),'a b');
  1.1080 +}, 'itemRef.add should treat " " as a space');
  1.1081 +test(function () {
  1.1082 +	var elem = makeEl('div',{itemref:'a\t'});
  1.1083 +	elem.itemRef.add('b');
  1.1084 +	assert_equals(elem.itemRef.toString(),'a b');
  1.1085 +}, 'itemRef.add should normalize \\t as a space');
  1.1086 +test(function () {
  1.1087 +	var elem = makeEl('div',{itemref:'a\r'});
  1.1088 +	elem.itemRef.add('b');
  1.1089 +	assert_equals(elem.itemRef.toString(),'a b');
  1.1090 +}, 'itemRef.add should normalize \\r as a space');
  1.1091 +test(function () {
  1.1092 +	var elem = makeEl('div',{itemref:'a\n'});
  1.1093 +	elem.itemRef.add('b');
  1.1094 +	assert_equals(elem.itemRef.toString(),'a b');
  1.1095 +}, 'itemRef.add should normalize \\n as a space');
  1.1096 +test(function () {
  1.1097 +	var elem = makeEl('div',{itemref:'a\f'});
  1.1098 +	elem.itemRef.add('b');
  1.1099 +	assert_equals(elem.itemRef.toString(),'a b');
  1.1100 +}, 'itemRef.add should normalize \\f as a space');
  1.1101 +test(function () {
  1.1102 +	var elem = makeEl('div',{itemref:'foo'});
  1.1103 +	elem.itemRef.remove('foo');
  1.1104 +	elem.removeAttribute('itemref');
  1.1105 +	assert_true( elem.itemRef.toggle('foo') );
  1.1106 +}, 'itemRef.toggle must work after removing the itemref attribute');
  1.1107 +test(function () {
  1.1108 +	//WebIDL and ECMAScript 5 - a readonly property has a getter but not a setter
  1.1109 +	//ES5 makes [[Put]] fail but not throw
  1.1110 +	var failed = false;
  1.1111 +	var elem = makeEl('div',{itemref:'token1'});
  1.1112 +	try {
  1.1113 +		elem.itemRef.length = 0;
  1.1114 +	} catch(e) {
  1.1115 +		failed = e;
  1.1116 +	}
  1.1117 +	assert_equals(elem.itemRef.length,1);
  1.1118 +	assert_false(failed,'an error was thrown');
  1.1119 +}, 'itemRef.length must be read-only');
  1.1120 +test(function () {
  1.1121 +	var failed = false, elem = makeEl('div',{itemref:'test'}), realList = elem.itemRef;
  1.1122 +	try {
  1.1123 +		elem.itemRef = 'dummy';
  1.1124 +	} catch(e) {
  1.1125 +		failed = e;
  1.1126 +	}
  1.1127 +	assert_equals(elem.itemRef,realList);
  1.1128 +	assert_equals(elem.itemRef.toString(),'dummy','attempting to write should modify the underlying string');
  1.1129 +	assert_false(failed,'an error was thrown');
  1.1130 +}, 'itemRef must be read-only');
  1.1131 +
  1.1132 +/* itemValue property tests */
  1.1133 +test(function () {
  1.1134 +	assert_equals( makeEl('meta',{content:'test'}).itemValue, null, 'meta' );
  1.1135 +	assert_equals( makeEl('audio',{src:'test'}).itemValue, null, 'audio' );
  1.1136 +	assert_equals( makeEl('embed',{src:'test'}).itemValue, null, 'embed' );
  1.1137 +	assert_equals( makeEl('iframe',{src:'test'}).itemValue, null, 'iframe' );
  1.1138 +	assert_equals( makeEl('img',{src:'test'}).itemValue, null, 'img' );
  1.1139 +	assert_equals( makeEl('source',{src:'test'}).itemValue, null, 'source' );
  1.1140 +	assert_equals( makeEl('track',{src:'test'}).itemValue, null, 'track' );
  1.1141 +	assert_equals( makeEl('video',{src:'test'}).itemValue, null, 'video' );
  1.1142 +	assert_equals( makeEl('a',{href:'test'}).itemValue, null, 'a' );
  1.1143 +	assert_equals( makeEl('area',{href:'test'}).itemValue, null, 'area' );
  1.1144 +	assert_equals( makeEl('link',{href:'test'}).itemValue, null, 'link' );
  1.1145 +	assert_equals( makeEl('object',{data:'test'}).itemValue, null, 'object' );
  1.1146 +	assert_equals( makeEl('time',{}).itemValue, null, 'time without datetime' );
  1.1147 +	assert_equals( makeEl('time',{datetime:'test'}).itemValue, null, 'time with datetime' );
  1.1148 +	assert_equals( makeEl('div',{},'test').itemValue, null, 'otherwise' );
  1.1149 +	assert_equals( makeEl('madeuponthespot',{},'test').itemValue, null, 'unknown element' );
  1.1150 +}, 'itemValue must be null if the element does not have an itemprop attribute');
  1.1151 +test(function () {
  1.1152 +	assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('meta',{content:'test'}); testEl.itemValue = 'test2'; }, 'meta' );
  1.1153 +	assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('audio',{content:'test'}); testEl.itemValue = 'test2'; }, 'audio' );
  1.1154 +	assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('embed',{content:'test'}); testEl.itemValue = 'test2'; }, 'embed' );
  1.1155 +	assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('iframe',{content:'test'}); testEl.itemValue = 'test2'; }, 'iframe' );
  1.1156 +	assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('img',{content:'test'}); testEl.itemValue = 'test2'; }, 'img' );
  1.1157 +	assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('source',{content:'test'}); testEl.itemValue = 'test2'; }, 'source' );
  1.1158 +	assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('track',{content:'test'}); testEl.itemValue = 'test2'; }, 'track' );
  1.1159 +	assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('video',{content:'test'}); testEl.itemValue = 'test2'; }, 'video' );
  1.1160 +	assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('a',{href:'test'}); testEl.itemValue = 'test2'; }, 'a' );
  1.1161 +	assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('area',{href:'test'}); testEl.itemValue = 'test2'; }, 'area' );
  1.1162 +	assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('link',{href:'test'}); testEl.itemValue = 'test2'; }, 'link' );
  1.1163 +	assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('object',{data:'test'}); testEl.itemValue = 'test2'; }, 'object' );
  1.1164 +	assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('time',{}); testEl.itemValue = 'test2'; }, 'time without datetime' );
  1.1165 +	assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('time',{datetime:'test'}); testEl.itemValue = 'test2'; }, 'time with datetime' );
  1.1166 +	assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('div',{},'test'); testEl.itemValue = 'test2'; }, 'otherwise' );
  1.1167 +	assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('madeuponthespot',{},'test'); testEl.itemValue = 'test2'; }, 'unknown element' );
  1.1168 +}, 'writing to itemValue must throw an INVALID_ACCESS_ERR error if the element does not have an itemprop attribute');
  1.1169 +test(function () {
  1.1170 +	var testEl;
  1.1171 +	testEl = makeEl('meta',{itemscope:'itemscope',itemprop:'foo',content:'test'});
  1.1172 +	assert_equals( testEl.itemValue, testEl, 'meta' );
  1.1173 +	testEl = makeEl('audio',{itemscope:'itemscope',itemprop:'foo',src:'test'},'fail');
  1.1174 +	assert_equals( testEl.itemValue, testEl, 'audio' );
  1.1175 +	testEl = makeEl('embed',{itemscope:'itemscope',itemprop:'foo',src:'test'});
  1.1176 +	assert_equals( testEl.itemValue, testEl, 'embed' );
  1.1177 +	testEl = makeEl('iframe',{itemscope:'itemscope',itemprop:'foo',src:'test'},'fail');
  1.1178 +	assert_equals( testEl.itemValue, testEl, 'iframe' );
  1.1179 +	testEl = makeEl('img',{itemscope:'itemscope',itemprop:'foo',src:'test'});
  1.1180 +	assert_equals( testEl.itemValue, testEl, 'img' );
  1.1181 +	testEl = makeEl('source',{itemscope:'itemscope',itemprop:'foo',src:'test'});
  1.1182 +	assert_equals( testEl.itemValue, testEl, 'source' );
  1.1183 +	testEl = makeEl('track',{itemscope:'itemscope',itemprop:'foo',src:'test'});
  1.1184 +	assert_equals( testEl.itemValue, testEl, 'track' );
  1.1185 +	testEl = makeEl('video',{itemscope:'itemscope',itemprop:'foo',src:'test'},'fail');
  1.1186 +	assert_equals( testEl.itemValue, testEl, 'video' );
  1.1187 +	testEl = makeEl('a',{itemscope:'itemscope',itemprop:'foo',href:'test'},'fail');
  1.1188 +	assert_equals( testEl.itemValue, testEl, 'a' );
  1.1189 +	testEl = makeEl('area',{itemscope:'itemscope',itemprop:'foo',href:'test'});
  1.1190 +	assert_equals( testEl.itemValue, testEl, 'area' );
  1.1191 +	testEl = makeEl('link',{itemscope:'itemscope',itemprop:'foo',href:'test'});
  1.1192 +	assert_equals( testEl.itemValue, testEl, 'link' );
  1.1193 +	testEl = makeEl('object',{itemscope:'itemscope',itemprop:'foo',data:'test'},'fail');
  1.1194 +	assert_equals( testEl.itemValue, testEl, 'object' );
  1.1195 +	testEl = makeEl('time',{itemscope:'itemscope',itemprop:'foo'},'fail');
  1.1196 +	assert_equals( testEl.itemValue, testEl, 'time without datetime' );
  1.1197 +	testEl = makeEl('time',{itemscope:'itemscope',itemprop:'foo',datetime:'test'},'fail');
  1.1198 +	assert_equals( testEl.itemValue, testEl, 'time with datetime' );
  1.1199 +	testEl = makeEl('div',{itemscope:'itemscope',itemprop:'foo'},'test');
  1.1200 +	assert_equals( testEl.itemValue, testEl, 'otherwise' );
  1.1201 +	testEl = makeEl('madeuponthespot',{itemscope:'itemscope',itemprop:'foo'},'test');
  1.1202 +	assert_equals( testEl.itemValue, testEl, 'unknown element' );
  1.1203 +	testEl = makeEl('madeuponthespot',{itemscope:'itemscope',itemprop:'foo',content:'test',src:'test',href:'test',data:'test',datetime:'test',value:'test'},'test');
  1.1204 +	assert_equals( testEl.itemValue, testEl, 'unknown element with known attributes' );
  1.1205 +	testEl = makeEl('input',{itemscope:'itemscope',itemprop:'foo',value:'test'},'test');
  1.1206 +	assert_equals( testEl.itemValue, testEl, 'input' );
  1.1207 +}, 'itemValue must return the element if the element has an itemscope attribute');
  1.1208 +test(function () {
  1.1209 +	var testEl = makeEl('meta',{itemprop:'foo',content:'test'});
  1.1210 +	assert_equals( testEl.itemValue, 'test', 'reading' );
  1.1211 +	testEl.content = 'retest';
  1.1212 +	assert_equals( testEl.itemValue, 'retest', 'reading after change' );
  1.1213 +	testEl.itemValue = 'bar';
  1.1214 +	assert_equals( testEl.content, 'bar', 'writing (checking content)' );
  1.1215 +	assert_equals( testEl.textContent, '', 'writing (checking textContent)' );
  1.1216 +}, 'itemValue must reflect the content attribute on meta elements');
  1.1217 +test(function () {
  1.1218 +	var testEl = makeEl('audio',{itemprop:'foo',src:'http://example.org/'},'contained text');
  1.1219 +	assert_equals( testEl.itemValue, 'http://example.org/', 'reading' );
  1.1220 +	testEl.src = 'http://example.net/';
  1.1221 +	assert_equals( testEl.itemValue, 'http://example.net/', 'reading after change' );
  1.1222 +	testEl.itemValue = 'http://example.com/';
  1.1223 +	assert_equals( testEl.src, 'http://example.com/', 'writing (checking src)' );
  1.1224 +	assert_equals( testEl.textContent, 'contained text', 'writing (checking textContent)' );
  1.1225 +	assert_equals( makeEl('audio',{itemprop:'foo'},'contained text').itemValue, '', 'reading with missing attribute' );
  1.1226 +	testEl.src = 'bar';
  1.1227 +	assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
  1.1228 +}, 'itemValue must reflect the src attribute on audio elements');
  1.1229 +test(function () {
  1.1230 +	var testEl = makeEl('embed',{itemprop:'foo',src:'http://example.org/'});
  1.1231 +	assert_equals( testEl.itemValue, 'http://example.org/', 'reading' );
  1.1232 +	testEl.src = 'http://example.net/';
  1.1233 +	assert_equals( testEl.itemValue, 'http://example.net/', 'reading after change' );
  1.1234 +	testEl.itemValue = 'http://example.com/';
  1.1235 +	assert_equals( testEl.src, 'http://example.com/', 'writing (checking src)' );
  1.1236 +	assert_equals( testEl.textContent, '', 'writing (checking textContent)' );
  1.1237 +	testEl.src = 'bar';
  1.1238 +	assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
  1.1239 +}, 'itemValue must reflect the src attribute on embed elements');
  1.1240 +test(function () {
  1.1241 +	var testEl = makeEl('iframe',{itemprop:'foo',src:'http://example.org/'},'contained text');
  1.1242 +	assert_equals( testEl.itemValue, 'http://example.org/', 'reading' );
  1.1243 +	testEl.src = 'http://example.net/';
  1.1244 +	assert_equals( testEl.itemValue, 'http://example.net/', 'reading after change' );
  1.1245 +	testEl.itemValue = 'http://example.com/';
  1.1246 +	assert_equals( testEl.src, 'http://example.com/', 'writing (checking src)' );
  1.1247 +	assert_equals( testEl.textContent, 'contained text', 'writing (checking textContent)' );
  1.1248 +	assert_equals( makeEl('iframe',{itemprop:'foo'},'contained text').itemValue, '', 'reading with missing attribute' );
  1.1249 +	testEl.src = 'bar';
  1.1250 +	assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
  1.1251 +}, 'itemValue must reflect the src attribute on iframe elements');
  1.1252 +test(function () {
  1.1253 +	var testEl = makeEl('img',{itemprop:'foo',src:'http://example.org/'});
  1.1254 +	assert_equals( testEl.itemValue, 'http://example.org/', 'reading' );
  1.1255 +	testEl.src = 'http://example.net/';
  1.1256 +	assert_equals( testEl.itemValue, 'http://example.net/', 'reading after change' );
  1.1257 +	testEl.itemValue = 'http://example.com/';
  1.1258 +	assert_equals( testEl.src, 'http://example.com/', 'writing (checking src)' );
  1.1259 +	assert_equals( testEl.textContent, '', 'writing (checking textContent)' );
  1.1260 +	testEl.src = 'bar';
  1.1261 +	assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
  1.1262 +}, 'itemValue must reflect the src attribute on img elements');
  1.1263 +test(function () {
  1.1264 +	var testEl = makeEl('source',{itemprop:'foo',src:'http://example.org/'});
  1.1265 +	assert_equals( testEl.itemValue, 'http://example.org/', 'reading' );
  1.1266 +	testEl.src = 'http://example.net/';
  1.1267 +	assert_equals( testEl.itemValue, 'http://example.net/', 'reading after change' );
  1.1268 +	testEl.itemValue = 'http://example.com/';
  1.1269 +	assert_equals( testEl.src, 'http://example.com/', 'writing (checking src)' );
  1.1270 +	assert_equals( testEl.textContent, '', 'writing (checking textContent)' );
  1.1271 +	testEl.src = 'bar';
  1.1272 +	assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
  1.1273 +}, 'itemValue must reflect the src attribute on source elements');
  1.1274 +test(function () {
  1.1275 +	var testEl = makeEl('track',{itemprop:'foo',src:'http://example.org/'});
  1.1276 +	assert_equals( testEl.itemValue, 'http://example.org/', 'reading' );
  1.1277 +	testEl.src = 'http://example.net/';
  1.1278 +	assert_equals( testEl.itemValue, 'http://example.net/', 'reading after change' );
  1.1279 +	testEl.itemValue = 'http://example.com/';
  1.1280 +	assert_equals( testEl.src, 'http://example.com/', 'writing (checking src)' );
  1.1281 +	assert_equals( testEl.textContent, '', 'writing (checking textContent)' );
  1.1282 +	testEl.src = 'bar';
  1.1283 +	assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
  1.1284 +}, 'itemValue must reflect the src attribute on track elements');
  1.1285 +test(function () {
  1.1286 +	var testEl = makeEl('video',{itemprop:'foo',src:'http://example.org/'},'contained text');
  1.1287 +	assert_equals( testEl.itemValue, 'http://example.org/', 'reading' );
  1.1288 +	testEl.src = 'http://example.net/';
  1.1289 +	assert_equals( testEl.itemValue, 'http://example.net/', 'reading after change' );
  1.1290 +	testEl.itemValue = 'http://example.com/';
  1.1291 +	assert_equals( testEl.src, 'http://example.com/', 'writing (checking src)' );
  1.1292 +	assert_equals( testEl.textContent, 'contained text', 'writing (checking textContent)' );
  1.1293 +	assert_equals( makeEl('video',{itemprop:'foo'},'contained text').itemValue, '', 'reading with missing attribute' );
  1.1294 +	testEl.src = 'bar';
  1.1295 +	assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
  1.1296 +}, 'itemValue must reflect the src attribute on video elements');
  1.1297 +test(function () {
  1.1298 +	var testEl = makeEl('a',{itemprop:'foo',href:'http://example.org/'},'contained text');
  1.1299 +	assert_equals( testEl.itemValue, 'http://example.org/', 'reading' );
  1.1300 +	testEl.href = 'http://example.net/';
  1.1301 +	assert_equals( testEl.itemValue, 'http://example.net/', 'reading after change' );
  1.1302 +	testEl.itemValue = 'http://example.com/';
  1.1303 +	assert_equals( testEl.href, 'http://example.com/', 'writing (checking href)' );
  1.1304 +	assert_equals( testEl.textContent, 'contained text', 'writing (checking textContent)' );
  1.1305 +	assert_equals( makeEl('a',{itemprop:'foo'},'contained text').itemValue, '', 'reading with missing attribute' );
  1.1306 +	testEl.href = 'bar';
  1.1307 +	assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
  1.1308 +}, 'itemValue must reflect the src attribute on anchor elements');
  1.1309 +test(function () {
  1.1310 +	var testEl = makeEl('area',{itemprop:'foo',href:'http://example.org/'});
  1.1311 +	assert_equals( testEl.itemValue, 'http://example.org/', 'reading' );
  1.1312 +	testEl.href = 'http://example.net/';
  1.1313 +	assert_equals( testEl.itemValue, 'http://example.net/', 'reading after change' );
  1.1314 +	testEl.itemValue = 'http://example.com/';
  1.1315 +	assert_equals( testEl.href, 'http://example.com/', 'writing (checking href)' );
  1.1316 +	assert_equals( testEl.textContent, '', 'writing (checking textContent)' );
  1.1317 +	testEl.href = 'bar';
  1.1318 +	assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
  1.1319 +}, 'itemValue must reflect the src attribute on area elements');
  1.1320 +test(function () {
  1.1321 +	var testEl = makeEl('link',{itemprop:'foo',href:'http://example.org/'});
  1.1322 +	assert_equals( testEl.itemValue, 'http://example.org/', 'reading' );
  1.1323 +	testEl.href = 'http://example.net/';
  1.1324 +	assert_equals( testEl.itemValue, 'http://example.net/', 'reading after change' );
  1.1325 +	testEl.itemValue = 'http://example.com/';
  1.1326 +	assert_equals( testEl.href, 'http://example.com/', 'writing (checking href)' );
  1.1327 +	assert_equals( testEl.textContent, '', 'writing (checking textContent)' );
  1.1328 +	testEl.href = 'bar';
  1.1329 +	assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
  1.1330 +}, 'itemValue must reflect the src attribute on link elements');
  1.1331 +test(function () {
  1.1332 +	var testEl = makeEl('object',{itemprop:'foo',data:'http://example.org/'},'contained text');
  1.1333 +	assert_equals( testEl.itemValue, 'http://example.org/', 'reading' );
  1.1334 +	testEl.data = 'http://example.net/';
  1.1335 +	assert_equals( testEl.itemValue, 'http://example.net/', 'reading after change' );
  1.1336 +	testEl.itemValue = 'http://example.com/';
  1.1337 +	assert_equals( testEl.data, 'http://example.com/', 'writing (checking data)' );
  1.1338 +	assert_equals( testEl.textContent, 'contained text', 'writing (checking textContent)' );
  1.1339 +	assert_equals( makeEl('object',{itemprop:'foo'},'contained text').itemValue, '', 'reading with missing attribute' );
  1.1340 +	testEl.data = 'bar';
  1.1341 +	assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
  1.1342 +}, 'itemValue must reflect the src attribute on object elements');
  1.1343 +test(function () {
  1.1344 +	var testEl = makeEl('time',{itemprop:'foo'},'te <span itemprop="bar" itemscope>st</span> ing');
  1.1345 +	assert_equals( testEl.itemValue, 'te st ing', 'reading' );
  1.1346 +	testEl.innerHTML = 'retest';
  1.1347 +	assert_equals( testEl.itemValue, 'retest', 'reading after change' );
  1.1348 +	testEl.itemValue = '2001-02-03T04:05:06Z';
  1.1349 +	assert_equals( testEl.dateTime, '2001-02-03T04:05:06Z', 'writing (checking dateTime)' );
  1.1350 +	assert_equals( testEl.textContent, 'retest', 'writing (checking textContent)' );
  1.1351 +	assert_equals( testEl.itemValue, '2001-02-03T04:05:06Z', 'writing (checking itemValue)' );
  1.1352 +}, 'itemValue must reflect the dateTime attribute of time elements with no datetime attribute');
  1.1353 +test(function () {
  1.1354 +	var testEl = makeEl('time',{itemprop:'foo',datetime:'test'},'te <span itemprop="bar" itemscope>st</span> ing');
  1.1355 +	assert_equals( testEl.itemValue, 'test', 'reading' );
  1.1356 +	testEl.dateTime = 'retest';
  1.1357 +	assert_equals( testEl.itemValue, 'retest', 'reading after change' );
  1.1358 +	testEl.itemValue = '2001-02-03T04:05:06Z';
  1.1359 +	assert_equals( testEl.dateTime, '2001-02-03T04:05:06Z', 'writing (checking dateTime)' );
  1.1360 +	assert_equals( testEl.textContent, 'te st ing', 'writing (checking textContent)' );
  1.1361 +}, 'itemValue must reflect the datetime attribute of time elements with a datetime attribute');
  1.1362 +test(function () {
  1.1363 +	var testEl = makeEl('div',{itemprop:'foo'},'te <span itemprop="bar" itemscope>st</span> ing');
  1.1364 +	assert_equals( testEl.itemValue, 'te st ing', 'reading' );
  1.1365 +	testEl.innerHTML = 're<strong>te</strong>st';
  1.1366 +	assert_equals( testEl.itemValue, 'retest', 'reading after change' );
  1.1367 +	testEl.itemValue = 'test';
  1.1368 +	assert_equals( testEl.textContent, 'test', 'writing' );
  1.1369 +}, 'itemValue must reflect the textContent of other elements');
  1.1370 +test(function () {
  1.1371 +	var testEl = makeEl('madeuponthespot',{itemprop:'foo'},'te <span itemprop="bar" itemscope>st</span> ing');
  1.1372 +	assert_equals( testEl.itemValue, 'te st ing', 'reading' );
  1.1373 +	testEl.innerHTML = 're<strong>te</strong>st';
  1.1374 +	assert_equals( testEl.itemValue, 'retest', 'reading after change' );
  1.1375 +	testEl.itemValue = 'test';
  1.1376 +	assert_equals( testEl.textContent, 'test', 'writing' );
  1.1377 +}, 'itemValue must reflect the textContent of unknown elements');
  1.1378 +test(function () {
  1.1379 +	var testEl = makeEl('madeuponthespot',{itemprop:'foo',content:'test',src:'test',href:'test',data:'test',datetime:'test',value:'test'},'te <span itemprop="bar" itemscope>st</span> ing');
  1.1380 +	assert_equals( testEl.itemValue, 'te st ing', 'reading' );
  1.1381 +	testEl.innerHTML = 're<strong>te</strong>st';
  1.1382 +	assert_equals( testEl.itemValue, 'retest', 'reading after change' );
  1.1383 +	testEl.itemValue = 'test';
  1.1384 +	assert_equals( testEl.textContent, 'test', 'writing' );
  1.1385 +}, 'itemValue must reflect the textContent of unknown elements with known attributes');
  1.1386 +test(function () {
  1.1387 +	var testEl = makeEl('input',{itemprop:'foo',value:'test'});
  1.1388 +	assert_equals( testEl.itemValue, '', 'reading' );
  1.1389 +	testEl.value = 'retest';
  1.1390 +	assert_equals( testEl.itemValue, '', 'reading after change' );
  1.1391 +}, 'itemValue must not reflect the value of input elements');
  1.1392 +test(function () {
  1.1393 +	var testEl, eltypes = [
  1.1394 +		makeEl('meta',{itemprop:'foo',content:'test'}),
  1.1395 +		makeEl('audio',{itemprop:'foo',src:'test'},'fail'),
  1.1396 +		makeEl('embed',{itemprop:'foo',src:'test'}),
  1.1397 +		makeEl('iframe',{itemprop:'foo',src:'test'},'fail'),
  1.1398 +		makeEl('img',{itemprop:'foo',src:'test'}),
  1.1399 +		makeEl('source',{itemprop:'foo',src:'test'}),
  1.1400 +		makeEl('track',{itemprop:'foo',src:'test'}),
  1.1401 +		makeEl('video',{itemprop:'foo',src:'test'},'fail'),
  1.1402 +		makeEl('a',{itemprop:'foo',href:'test'},'fail'),
  1.1403 +		makeEl('area',{itemprop:'foo',href:'test'}),
  1.1404 +		makeEl('link',{itemprop:'foo',href:'test'}),
  1.1405 +		makeEl('object',{itemprop:'foo',data:'test'},'fail'),
  1.1406 +		makeEl('time',{itemprop:'foo'},'fail'),
  1.1407 +		makeEl('time',{itemprop:'foo',datetime:'test'},'fail'),
  1.1408 +		makeEl('div',{itemprop:'foo'},'test'),
  1.1409 +		makeEl('madeuponthespot',{itemprop:'foo'},'test'),
  1.1410 +		makeEl('madeuponthespot',{itemprop:'foo',content:'test',src:'test',href:'test',data:'test',datetime:'test',value:'test'},'test'),
  1.1411 +		makeEl('input',{itemprop:'foo',value:'test'},'test')
  1.1412 +	], beforeValues, i;
  1.1413 +	for( i = 0; i < eltypes.length; i++ ) {
  1.1414 +		testEl = eltypes[i];
  1.1415 +		beforeValues = testEl.itemValue;
  1.1416 +		testEl.itemScope = true;
  1.1417 +		assert_equals( testEl.itemValue, testEl, 'itemscope enabled on '+testEl.tagName+' index '+i );
  1.1418 +		testEl.itemScope = false;
  1.1419 +		assert_equals( testEl.itemValue, beforeValues, 'itemscope disabled on '+testEl.tagName+' index '+i );
  1.1420 +		testEl.itemScope = true;
  1.1421 +		testEl.removeAttribute('itemscope');
  1.1422 +		assert_equals( testEl.itemValue, beforeValues, 'itemscope attribute removed on '+testEl.tagName+' index '+i );
  1.1423 +	}
  1.1424 +}, 'dynamic changes of itemscope should change the value exposed through itemValue');
  1.1425 +
  1.1426 +test(function () {
  1.1427 +	var testEl, eltypes = [
  1.1428 +		makeEl('meta',{itemprop:'foo',content:'test'}),
  1.1429 +		makeEl('audio',{itemprop:'foo',src:'test'},'fail'),
  1.1430 +		makeEl('embed',{itemprop:'foo',src:'test'}),
  1.1431 +		makeEl('iframe',{itemprop:'foo',src:'test'},'fail'),
  1.1432 +		makeEl('img',{itemprop:'foo',src:'test'}),
  1.1433 +		makeEl('source',{itemprop:'foo',src:'test'}),
  1.1434 +		makeEl('track',{itemprop:'foo',src:'test'}),
  1.1435 +		makeEl('video',{itemprop:'foo',src:'test'},'fail'),
  1.1436 +		makeEl('a',{itemprop:'foo',href:'test'},'fail'),
  1.1437 +		makeEl('area',{itemprop:'foo',href:'test'}),
  1.1438 +		makeEl('link',{itemprop:'foo',href:'test'}),
  1.1439 +		makeEl('object',{itemprop:'foo',data:'test'},'fail'),
  1.1440 +		makeEl('time',{itemprop:'foo'},'fail'),
  1.1441 +		makeEl('time',{itemprop:'foo',datetime:'test'},'fail'),
  1.1442 +		makeEl('div',{itemprop:'foo'},'test'),
  1.1443 +		makeEl('madeuponthespot',{itemprop:'foo'},'test'),
  1.1444 +		makeEl('madeuponthespot',{itemprop:'foo',content:'test',src:'test',href:'test',data:'test',datetime:'test',value:'test'},'test'),
  1.1445 +		makeEl('input',{itemprop:'foo',value:'test'},'test')
  1.1446 +	], beforeValues, i;
  1.1447 +	for( i = 0; i < eltypes.length; i++ ) {
  1.1448 +		testEl = eltypes[i];
  1.1449 +		beforeValues = testEl.itemValue;
  1.1450 +		testEl.itemProp.remove('foo');
  1.1451 +		assert_equals( testEl.itemValue, beforeValues, 'itemprop tokens removed on '+testEl.tagName+' index '+i );
  1.1452 +		testEl.removeAttribute('itemprop');
  1.1453 +		assert_equals( testEl.itemValue, null, 'itemprop attribute removed on '+testEl.tagName+' index '+i );
  1.1454 +		testEl.itemProp.toggle('foo');
  1.1455 +		assert_equals( testEl.itemValue, beforeValues, 'itemprop tokens added on '+testEl.tagName+' index '+i );
  1.1456 +	}
  1.1457 +}, 'dynamic changes of itemprop should change the value exposed through itemValue');
  1.1458 +
  1.1459 +/* properties */
  1.1460 +test(function () {
  1.1461 +	assert_equals( typeof makeEl('div',{}).properties, 'object' );
  1.1462 +}, 'the properties property must be an object');
  1.1463 +test(function () {
  1.1464 +	var testEl = makeEl('div',{});
  1.1465 +	assert_true( testEl.properties instanceof HTMLPropertiesCollection, 'instanceof HTMLPropertiesCollection' );
  1.1466 +	assert_true( testEl.properties instanceof HTMLCollection, 'instanceof HTMLCollection' );
  1.1467 +	HTMLPropertiesCollection.prototype.customProperty = true;
  1.1468 +	HTMLCollection.prototype.anotherCustomProperty = true;
  1.1469 +	assert_true( testEl.properties.customProperty, 'inheritance from HTMLPropertiesCollection' );
  1.1470 +	assert_true( testEl.properties.anotherCustomProperty, 'inheritance from HTMLCollection' );
  1.1471 +	HTMLPropertiesCollection.prototype.anotherCustomProperty = false;
  1.1472 +	assert_false( testEl.properties.anotherCustomProperty, 'shadowing by HTMLPropertiesCollection' );
  1.1473 +}, 'the properties property must implement HTMLPropertiesCollection and HTMLCollection');
  1.1474 +test(function () {
  1.1475 +	var failed = false, elem = makeEl('div',{itemscope:'itemscope'}), realList = elem.properties;
  1.1476 +	try {
  1.1477 +		elem.properties = '';
  1.1478 +	} catch(e) {
  1.1479 +		failed = e;
  1.1480 +	}
  1.1481 +	assert_equals(elem.properties,realList);
  1.1482 +	assert_false(failed,'an error was thrown');
  1.1483 +}, 'the properties property must be read-only');
  1.1484 +test(function () {
  1.1485 +	var testEl = makeEl('div',{});
  1.1486 +	assert_equals( testEl.properties, testEl.properties );
  1.1487 +}, 'the properties property must always reference the same object');
  1.1488 +test(function () {
  1.1489 +	var testEl = makeEl('div',{},'<div itemprop="foo">bar</div>');
  1.1490 +	assert_equals( testEl.properties.length, 0, 'length' );
  1.1491 +	assert_true( !testEl.properties.item(0), 'item(0)' );
  1.1492 +	assert_true( !testEl.properties[0], '[0]' );
  1.1493 +	assert_equals( testEl.properties.namedItem('foo').length, 0, 'namedItem' );
  1.1494 +	assert_true( !testEl.properties['foo'], '[namedItem]' );
  1.1495 +	assert_equals( testEl.properties.namedItem('foo').getValues().length, 0, 'namedItem' );
  1.1496 +	assert_equals( testEl.properties.names.length, 0, 'names' );
  1.1497 +}, 'the properties collection must be empty if the element does not have an itemscope property');
  1.1498 +test(function() {
  1.1499 +	var testEl = makeEl('div',{},'<div itemprop="foo">bar</div>');
  1.1500 +	assert_throws( new TypeError(), function() { testEl.properties('foo'); } );
  1.1501 +	assert_throws( new TypeError(), function() { testEl.properties(0); } );
  1.1502 +}, 'the properties collection must not support legacycaller');	
  1.1503 +test(function () {
  1.1504 +	var testEl = makeEl('div',{},'<div itemprop="foo">bar</div>');
  1.1505 +	testEl.itemScope = true;
  1.1506 +	assert_equals( testEl.properties.length, 1, 'length' );
  1.1507 +	assert_equals( testEl.properties.item(0), testEl.firstChild, 'item(0)' );
  1.1508 +	assert_equals( testEl.properties[0], testEl.firstChild, '[0]' );
  1.1509 +	assert_equals( testEl.properties.namedItem('foo').length, 1, 'namedItem' );
  1.1510 +	assert_equals( testEl.properties['foo'].length, 1, '[namedItem]' );
  1.1511 +	assert_equals( testEl.properties.namedItem('foo').getValues().length, 1, 'namedItem' );
  1.1512 +	assert_equals( testEl.properties.names.length, 1, 'names' );
  1.1513 +}, 'the properties collection must become populated if the element is given an itemscope property');
  1.1514 +test(function () {
  1.1515 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo">bar</div>');
  1.1516 +	testEl.itemScope = false;
  1.1517 +	assert_equals( testEl.properties.length, 0, 'length' );
  1.1518 +	assert_true( !testEl.properties.item(0), 'item(0)' );
  1.1519 +	assert_true( !testEl.properties[0], '[0]' );
  1.1520 +	assert_equals( testEl.properties.namedItem('foo').length, 0, 'namedItem' );
  1.1521 +	assert_true( !testEl.properties['foo'], '[namedItem]' );
  1.1522 +	assert_equals( testEl.properties.namedItem('foo').getValues().length, 0, 'namedItem' );
  1.1523 +	assert_equals( testEl.properties.names.length, 0, 'names' );
  1.1524 +}, 'the properties collection must become empty if the element\'s itemscope property is removed');
  1.1525 +//properties.item and properties.length (part 1)
  1.1526 +test(function () {
  1.1527 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="foo"></div><div itemprop="foo"></div></div><div itemprop="baz qux"></div>');
  1.1528 +	assert_equals( testEl.properties.length, 5 );
  1.1529 +}, 'properties.length must be the total number of properties');
  1.1530 +test(function () {
  1.1531 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="foo"></div></div><div itemprop="baz qux"></div>');
  1.1532 +	assert_equals( testEl.properties.item(0), testEl.childNodes[0], 'item(0)' );
  1.1533 +	assert_equals( testEl.properties.item(1), testEl.childNodes[1], 'item(1)' );
  1.1534 +	assert_equals( testEl.properties.item(2), testEl.childNodes[1].childNodes[0], 'item(2)' );
  1.1535 +	assert_equals( testEl.properties.item(3), testEl.childNodes[2], 'item(3)' );
  1.1536 +}, 'properties.item must give each property in tree order');
  1.1537 +test(function () {
  1.1538 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="foo"></div></div><div itemprop="baz qux"></div>');
  1.1539 +	testEl.properties.something = "another";
  1.1540 +	var names = Object.getOwnPropertyNames(testEl.properties);
  1.1541 +	assert_array_equals( names, ["0", "1", "2", "3", "foo", "bar", "baz", "qux", "something"] );
  1.1542 +}, 'properties.item must have the right property names on it when enumerated');
  1.1543 +test(function () {
  1.1544 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="foo"></div></div><div itemprop="baz qux"></div>');
  1.1545 +	assert_equals( testEl.properties.item(4), null, 'positive index' );
  1.1546 +	assert_equals( testEl.properties.item(-1), null, 'negative index' );
  1.1547 +}, 'properties.item must give null for out of range index');
  1.1548 +test(function () {
  1.1549 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="foo"></div></div><div itemprop="baz qux"></div>');
  1.1550 +	assert_equals( testEl.properties[0], testEl.childNodes[0], '[0]' );
  1.1551 +	assert_equals( testEl.properties[1], testEl.childNodes[1], '[1]' );
  1.1552 +	assert_equals( testEl.properties[2], testEl.childNodes[1].childNodes[0], '[2]' );
  1.1553 +	assert_equals( testEl.properties[3], testEl.childNodes[2], '[3]' );
  1.1554 +}, 'properties[index] must give each property in tree order');
  1.1555 +test(function () {
  1.1556 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="foo"></div></div><div itemprop="baz qux"></div>');
  1.1557 +	assert_equals( testEl.properties[4], window.undefined, 'positive index' );
  1.1558 +	assert_equals( testEl.properties[-1], window.undefined, 'negative index' );
  1.1559 +}, 'properties[index] must give undefined for out of range index');
  1.1560 +test(function () {
  1.1561 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemscope itemprop="foo"><div itemprop="bar"></div></div><div><div itemprop="baz"></div></div>');
  1.1562 +	assert_equals( testEl.properties.length, 2, 'length' );
  1.1563 +	assert_equals( testEl.properties.item(0), testEl.firstChild, 'properties.item(0)' );
  1.1564 +	assert_equals( testEl.properties[0], testEl.firstChild, 'properties[0]' );
  1.1565 +	assert_equals( testEl.properties.item(1), testEl.childNodes[1].firstChild, 'properties.item(1)' );
  1.1566 +	assert_equals( testEl.properties[1], testEl.childNodes[1].firstChild, 'properties[1]' );
  1.1567 +}, 'properties.item and length must ignore properties of nested items');
  1.1568 +test(function () {
  1.1569 +	//note, itemref ordering is reversed compared with the next test to catch failed sorting algorithms
  1.1570 +	var parEl = makeEl('div',{},'<div itemprop="foo" id="id1"></div><div itemscope itemref="id2 id1"><div itemprop="bar"></div></div><div itemprop="baz" id="id2"><div itemprop="qux"></div></div>');
  1.1571 +	var testEl = parEl.childNodes[1];
  1.1572 +	document.body.appendChild(parEl);
  1.1573 +	var propLength = testEl.properties.length;
  1.1574 +	var item0 = testEl.properties.item(0);
  1.1575 +	var square0 = testEl.properties[0];
  1.1576 +	var item1 = testEl.properties.item(1);
  1.1577 +	var square1 = testEl.properties[1];
  1.1578 +	var item2 = testEl.properties.item(2);
  1.1579 +	var square2 = testEl.properties[2];
  1.1580 +	var item3 = testEl.properties.item(3);
  1.1581 +	var square3 = testEl.properties[3];
  1.1582 +	document.body.removeChild(parEl);
  1.1583 +	assert_equals( propLength, 4, 'length' );
  1.1584 +	assert_equals( item0, parEl.firstChild, 'properties.item(0)' );
  1.1585 +	assert_equals( square0, parEl.firstChild, 'properties[0]' );
  1.1586 +	assert_equals( item1, testEl.firstChild, 'properties.item(1)' );
  1.1587 +	assert_equals( square1, testEl.firstChild, 'properties[1]' );
  1.1588 +	assert_equals( item2, parEl.childNodes[2], 'properties.item(2)' );
  1.1589 +	assert_equals( square2, parEl.childNodes[2], 'properties[2]' );
  1.1590 +	assert_equals( item3, parEl.childNodes[2].firstChild, 'properties.item(3)' );
  1.1591 +	assert_equals( square3, parEl.childNodes[2].firstChild, 'properties[3]' );
  1.1592 +}, 'properties.item and length must see items added with itemref when attached to the document\'s DOM');
  1.1593 +test(function () {
  1.1594 +	var parEl = makeEl('div',{},'<div itemprop="foo" id="id1"></div><div itemscope itemref="id1 id2"><div itemprop="bar"></div></div><div itemprop="baz" id="id2"><div itemprop="qux"></div></div>');
  1.1595 +	var testEl = parEl.childNodes[1];
  1.1596 +	assert_equals( testEl.properties.length, 4, 'length' );
  1.1597 +	assert_equals( testEl.properties.item(0), parEl.firstChild, 'properties.item(0)' );
  1.1598 +	assert_equals( testEl.properties[0], parEl.firstChild, 'properties[0]' );
  1.1599 +	assert_equals( testEl.properties.item(1), testEl.firstChild, 'properties.item(1)' );
  1.1600 +	assert_equals( testEl.properties[1], testEl.firstChild, 'properties[1]' );
  1.1601 +	assert_equals( testEl.properties.item(2), parEl.childNodes[2], 'properties.item(2)' );
  1.1602 +	assert_equals( testEl.properties[2], parEl.childNodes[2], 'properties[2]' );
  1.1603 +	assert_equals( testEl.properties.item(3), parEl.childNodes[2].firstChild, 'properties.item(3)' );
  1.1604 +	assert_equals( testEl.properties[3], parEl.childNodes[2].firstChild, 'properties[3]' );
  1.1605 +}, 'properties.item and length must see items added with itemref');
  1.1606 +test(function () {
  1.1607 +	var parEl = makeEl('div',{},'<div itemscope itemref="id1"></div><div itemprop="foo" id="id1"><div itemprop="bar"></div></div><div itemprop="baz" id="id1"></div>');
  1.1608 +	var testEl = parEl.childNodes[0];
  1.1609 +	assert_equals( testEl.properties.length, 2, 'length' );
  1.1610 +	assert_equals( testEl.properties.item(0), parEl.childNodes[1], 'properties.item(0)' );
  1.1611 +	assert_equals( testEl.properties.item(1), parEl.childNodes[1].firstChild, 'properties.item(1)' );
  1.1612 +	document.body.appendChild(parEl)
  1.1613 +	var length = testEl.properties.length;
  1.1614 +	var item0 = testEl.properties.item(0);
  1.1615 +	var item1 = testEl.properties.item(0);
  1.1616 +	document.body.removeChild(parEl)
  1.1617 +	assert_equals( testEl.properties.length, 2, 'length (attached to document)' );
  1.1618 +	assert_equals( testEl.properties.item(0), parEl.childNodes[1], 'properties.item(0) (attached to document)' );
  1.1619 +	assert_equals( testEl.properties.item(1), parEl.childNodes[1].firstChild, 'properties.item(1) (attached to document)' );
  1.1620 +}, 'itemref must reference the first element with a given ID');
  1.1621 +test(function () {
  1.1622 +	var parEl = makeEl('div',{},'<div itemscope itemref="id1 id1"></div><div itemprop="foo" id="id1"><div itemprop="bar"></div></div><div itemprop="baz" id="id1"></div>');
  1.1623 +	var testEl = parEl.childNodes[0];
  1.1624 +	assert_equals( testEl.properties.length, 2, 'length' );
  1.1625 +	assert_equals( testEl.properties.item(0), parEl.childNodes[1], 'properties.item(0)' );
  1.1626 +	assert_equals( testEl.properties.item(1), parEl.childNodes[1].firstChild, 'properties.item(1)' );
  1.1627 +	document.body.appendChild(parEl)
  1.1628 +	var length = testEl.properties.length;
  1.1629 +	var item0 = testEl.properties.item(0);
  1.1630 +	var item1 = testEl.properties.item(0);
  1.1631 +	document.body.removeChild(parEl)
  1.1632 +	assert_equals( testEl.properties.length, 2, 'length (attached to document)' );
  1.1633 +	assert_equals( testEl.properties.item(0), parEl.childNodes[1], 'properties.item(0) (attached to document)' );
  1.1634 +	assert_equals( testEl.properties.item(1), parEl.childNodes[1].firstChild, 'properties.item(1) (attached to document)' );
  1.1635 +}, 'itemref must ignore duplicated IDs');
  1.1636 +test(function () {
  1.1637 +	var parEl = makeEl('div',{},'<div itemscope itemref="id0 id1"></div><div itemprop="foo" id="id1"><div itemprop="bar"></div></div>');
  1.1638 +	var testEl = parEl.childNodes[0];
  1.1639 +	assert_equals( testEl.properties.length, 2, 'length' );
  1.1640 +	assert_equals( testEl.properties.item(0), parEl.childNodes[1], 'properties.item(0)' );
  1.1641 +	assert_equals( testEl.properties.item(1), parEl.childNodes[1].firstChild, 'properties.item(1)' );
  1.1642 +	document.body.appendChild(parEl)
  1.1643 +	var length = testEl.properties.length;
  1.1644 +	var item0 = testEl.properties.item(0);
  1.1645 +	var item1 = testEl.properties.item(0);
  1.1646 +	document.body.removeChild(parEl)
  1.1647 +	assert_equals( testEl.properties.length, 2, 'length (attached to document)' );
  1.1648 +	assert_equals( testEl.properties.item(0), parEl.childNodes[1], 'properties.item(0) (attached to document)' );
  1.1649 +	assert_equals( testEl.properties.item(1), parEl.childNodes[1].firstChild, 'properties.item(1) (attached to document)' );
  1.1650 +}, 'itemref must ignore non-existent IDs');
  1.1651 +test(function () {
  1.1652 +	var testEl = makeEl('div',{itemscope:'itemscope',itemref:'id1'});
  1.1653 +	var dummyEl = makeEl('div',{id:'id1',itemprop:'foo'});
  1.1654 +	assert_equals( testEl.properties.length, 0 );
  1.1655 +}, 'itemref in a dislocated tree must not reference elements from another dislocated tree');
  1.1656 +test(function () {
  1.1657 +	var testEl = makeEl('div',{itemscope:'itemscope',itemref:'id1'});
  1.1658 +	var dummyEl = makeEl('div',{id:'id1',itemprop:'foo'});
  1.1659 +	document.body.appendChild(dummyEl);
  1.1660 +	var tmp = testEl.properties.length;
  1.1661 +	document.body.removeChild(dummyEl);
  1.1662 +	assert_equals( tmp, 0 );
  1.1663 +}, 'itemref in a dislocated tree must not reference elements from the main document');
  1.1664 +test(function () {
  1.1665 +	var testEl = makeEl('div',{itemscope:'itemscope',itemref:'id1'});
  1.1666 +	var dummyEl = makeEl('div',{id:'id1',itemprop:'foo'});
  1.1667 +	document.body.appendChild(testEl);
  1.1668 +	var tmp = testEl.properties.length;
  1.1669 +	document.body.removeChild(testEl);
  1.1670 +	assert_equals( tmp, 0 );
  1.1671 +}, 'itemref in the main document must not reference elements from a dislocated tree');
  1.1672 +test(function () {
  1.1673 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>');
  1.1674 +	assert_equals( testEl.properties.length, 1, 'length (before test)' );
  1.1675 +	assert_equals( testEl.properties.item(0), testEl.firstChild, 'properties.item(0) (before test)' );
  1.1676 +	assert_equals( testEl.properties[0], testEl.firstChild, 'properties[0] (before test)' );
  1.1677 +	testEl.appendChild(makeEl('div',{itemprop:'bar'}));
  1.1678 +	assert_equals( testEl.properties.length, 2, 'length after adding a child' );
  1.1679 +	assert_equals( testEl.properties.item(1), testEl.childNodes[1], 'properties.item(1) after adding a child' );
  1.1680 +	assert_equals( testEl.properties[1], testEl.childNodes[1], 'properties[1] after adding a child' );
  1.1681 +	testEl.lastChild.appendChild(makeEl('div',{itemprop:'foo'}));
  1.1682 +	assert_equals( testEl.properties.length, 3, 'length after adding a child with duplicated name' );
  1.1683 +	assert_equals( testEl.properties.item(2), testEl.childNodes[1].firstChild, 'properties.item(2) after adding a child with duplicated name' );
  1.1684 +	assert_equals( testEl.properties[2], testEl.childNodes[1].firstChild, 'properties[2] after adding a child with duplicated name' );
  1.1685 +	testEl.lastChild.removeChild(testEl.lastChild.firstChild);
  1.1686 +	assert_equals( testEl.properties.length, 2, 'length after removing a child' );
  1.1687 +	assert_true( !testEl.properties.item(2), 'properties.item(1) after removing a child' );
  1.1688 +	assert_true( !testEl.properties[2], 'properties[1] after removing a child' );
  1.1689 +}, 'properties.item and length must update when adding property elements');
  1.1690 +test(function () {
  1.1691 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"></div>');
  1.1692 +	assert_equals( testEl.properties.length, 2, 'length (before test)' );
  1.1693 +	assert_equals( testEl.properties.item(0), testEl.firstChild, 'properties.item(0) (before test)' );
  1.1694 +	assert_equals( testEl.properties[0], testEl.firstChild, 'properties[0] (before test)' );
  1.1695 +	assert_equals( testEl.properties.item(1), testEl.childNodes[1], 'properties.item(1) (before test)' );
  1.1696 +	assert_equals( testEl.properties[1], testEl.childNodes[1], 'properties[1] (before test)' );
  1.1697 +	testEl.appendChild(testEl.firstChild);
  1.1698 +	assert_equals( testEl.properties.length, 2, 'length (after test)' );
  1.1699 +	assert_equals( testEl.properties.item(0), testEl.firstChild, 'properties.item(0) (after test)' );
  1.1700 +	assert_equals( testEl.properties[0], testEl.firstChild, 'properties[0] (after test)' );
  1.1701 +	assert_equals( testEl.properties.item(1), testEl.childNodes[1], 'properties.item(1) (after test)' );
  1.1702 +	assert_equals( testEl.properties[1], testEl.childNodes[1], 'properties[1] (after test)' );
  1.1703 +}, 'properties.item must update when re-ordering property elements, but length must not');
  1.1704 +test(function () {
  1.1705 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div></div>');
  1.1706 +	assert_equals( testEl.properties.length, 1, 'length (before test)' );
  1.1707 +	assert_equals( testEl.properties[0], testEl.firstChild, 'properties[0] (before test)' );
  1.1708 +	testEl.lastChild.itemProp.toggle('bar');
  1.1709 +	assert_equals( testEl.properties.length, 2, 'length (after test 1)' );
  1.1710 +	assert_equals( testEl.properties.item(0), testEl.firstChild, 'properties.item(0) after adding a token' );
  1.1711 +	assert_equals( testEl.properties[0], testEl.firstChild, 'properties[0] after adding a token' );
  1.1712 +	assert_equals( testEl.properties.item(1), testEl.childNodes[1], 'properties.item(1) after adding a token' );
  1.1713 +	assert_equals( testEl.properties[1], testEl.childNodes[1], 'properties[1] after adding a token' );
  1.1714 +	testEl.lastChild.removeAttribute('itemprop');
  1.1715 +	assert_equals( testEl.properties.length, 1, 'length after removing an attribute' );
  1.1716 +	assert_equals( testEl.properties.item(0), testEl.firstChild, 'properties.item(0) after removing an attribute' );
  1.1717 +	assert_equals( testEl.properties[0], testEl.firstChild, 'properties[0] after removing an attribute' );
  1.1718 +	assert_true( !testEl.properties.item(1), 'properties.item(1) after removing an attribute' );
  1.1719 +	assert_true( !testEl.properties[1], 'properties[1] after removing an attribute' );
  1.1720 +}, 'properties.item and length must update when changing itemProp of children');
  1.1721 +test(function () {
  1.1722 +	var parEl = makeEl('div',{},'<div itemprop="foo"><div itemprop="bar"></div></div><div itemscope itemref="id1"></div>');
  1.1723 +	var testEl = parEl.childNodes[1];
  1.1724 +	assert_equals( testEl.properties.length, 0, 'length (before test)' );
  1.1725 +	parEl.firstChild.id = 'id1';
  1.1726 +	assert_equals( testEl.properties.length, 2, 'length after id is created' );
  1.1727 +	assert_equals( testEl.properties.item(0), parEl.firstChild, 'properties.item(0) after id is created' );
  1.1728 +	assert_equals( testEl.properties[0], parEl.firstChild, 'properties[0] after id is created' );
  1.1729 +	assert_equals( testEl.properties.item(1), parEl.firstChild.firstChild, 'properties.item(1) after id is created' );
  1.1730 +	assert_equals( testEl.properties[1], parEl.firstChild.firstChild, 'properties[1] after id is created' );
  1.1731 +	parEl.firstChild.removeAttribute('id');
  1.1732 +	assert_equals( testEl.properties.length, 0, 'length after removing an attribute' );
  1.1733 +	assert_true( !testEl.properties.item(0), 'properties.item(0) after removing an attribute' );
  1.1734 +	assert_true( !testEl.properties[0], 'properties[0] after removing an attribute' );
  1.1735 +	document.body.appendChild(parEl);
  1.1736 +	var beflength = testEl.properties.length;
  1.1737 +	parEl.firstChild.id = 'id1';
  1.1738 +	var length1 = testEl.properties.length,
  1.1739 +	    item0 = testEl.properties.item(0),
  1.1740 +	    prop0 = testEl.properties[0],
  1.1741 +	    item1 = testEl.properties.item(1),
  1.1742 +	    prop1 = testEl.properties[1];
  1.1743 +	parEl.firstChild.removeAttribute('id');
  1.1744 +	var length2 = testEl.properties.length,
  1.1745 +	    bitem = !testEl.properties.item(0),
  1.1746 +	    bprop = !testEl.properties[0];
  1.1747 +	document.body.removeChild(parEl);
  1.1748 +	assert_equals( beflength, 0, 'length (before test) when appended to document' );
  1.1749 +	assert_equals( length1, 2, 'length after id is created when appended to document' );
  1.1750 +	assert_equals( item0, parEl.firstChild, 'properties.item(0) after id is created when appended to document' );
  1.1751 +	assert_equals( prop0, parEl.firstChild, 'properties[0] after id is created when appended to document' );
  1.1752 +	assert_equals( item1, parEl.firstChild.firstChild, 'properties.item(1) after id is created when appended to document' );
  1.1753 +	assert_equals( prop1, parEl.firstChild.firstChild, 'properties[1] after id is created when appended to document' );
  1.1754 +	assert_equals( length2, 0, 'length after removing an attribute when appended to document' );
  1.1755 +	assert_true( bitem, 'properties.item(0) after removing an attribute when appended to document' );
  1.1756 +	assert_true( bprop, 'properties[0] after removing an attribute when appended to document' );
  1.1757 +}, 'properties.item and length must update when changing id of referenced sibling');
  1.1758 +test(function () {
  1.1759 +	var parEl = makeEl('div',{},'<div itemprop="foo"><div itemprop="bar"></div></div><div itemscope itemref="id1"></div><div itemprop="baz" id="id1"></div>');
  1.1760 +	var testEl = parEl.childNodes[1];
  1.1761 +	assert_equals( testEl.properties.length, 1, 'length (before test)' );
  1.1762 +	assert_equals( testEl.properties.item(0), parEl.lastChild, 'properties.item(0) (before test)' );
  1.1763 +	assert_equals( testEl.properties[0], parEl.lastChild, 'properties[0] (before test)' );
  1.1764 +	parEl.firstChild.id = 'id1';
  1.1765 +	assert_equals( testEl.properties.length, 2, 'length after id is created' );
  1.1766 +	assert_equals( testEl.properties.item(0), parEl.firstChild, 'properties.item(0) after id is created' );
  1.1767 +	assert_equals( testEl.properties[0], parEl.firstChild, 'properties[0] after id is created' );
  1.1768 +	assert_equals( testEl.properties.item(1), parEl.firstChild.firstChild, 'properties.item(1) after id is created' );
  1.1769 +	assert_equals( testEl.properties[1], parEl.firstChild.firstChild, 'properties[1] after id is created' );
  1.1770 +	parEl.firstChild.removeAttribute('id');
  1.1771 +	assert_equals( testEl.properties.length, 1, 'length after removing an attribute' );
  1.1772 +	assert_equals( testEl.properties.item(0), parEl.lastChild, 'properties.item(0) after removing an attribute' );
  1.1773 +	assert_equals( testEl.properties[0], parEl.lastChild, 'properties[0] after removing an attribute' );
  1.1774 +	document.body.appendChild(parEl);
  1.1775 +	var beflength = testEl.properties.length,
  1.1776 +	    befitem = testEl.properties.item(0),
  1.1777 +	    befprop = testEl.properties[0];
  1.1778 +	parEl.firstChild.id = 'id1';
  1.1779 +	var length1 = testEl.properties.length,
  1.1780 +	    item0 = testEl.properties.item(0),
  1.1781 +	    prop0 = testEl.properties[0],
  1.1782 +	    item1 = testEl.properties.item(1),
  1.1783 +	    prop1 = testEl.properties[1];
  1.1784 +	parEl.firstChild.removeAttribute('id');
  1.1785 +	var length2 = testEl.properties.length,
  1.1786 +	    afitem = testEl.properties.item(0),
  1.1787 +	    afprop = testEl.properties[0];
  1.1788 +	document.body.removeChild(parEl);
  1.1789 +	assert_equals( beflength, 1, 'length (before test) when appended to document' );
  1.1790 +	assert_equals( befitem, parEl.lastChild, 'properties.item(0) (before test)' );
  1.1791 +	assert_equals( befprop, parEl.lastChild, 'properties[0] (before test)' );
  1.1792 +	assert_equals( length1, 2, 'length after id is created when appended to document' );
  1.1793 +	assert_equals( item0, parEl.firstChild, 'properties.item(0) after id is created when appended to document' );
  1.1794 +	assert_equals( prop0, parEl.firstChild, 'properties[0] after id is created when appended to document' );
  1.1795 +	assert_equals( item1, parEl.firstChild.firstChild, 'properties.item(1) after id is created when appended to document' );
  1.1796 +	assert_equals( prop1, parEl.firstChild.firstChild, 'properties[1] after id is created when appended to document' );
  1.1797 +	assert_equals( length2, 1, 'length after removing an attribute when appended to document' );
  1.1798 +	assert_equals( afitem, parEl.lastChild, 'properties.item(0) after removing an attribute when appended to document' );
  1.1799 +	assert_equals( afprop, parEl.lastChild, 'properties[0] after removing an attribute when appended to document' );
  1.1800 +}, 'properties.item and length must update when changing duplicated id of referenced sibling');
  1.1801 +test(function () {
  1.1802 +	var parEl = makeEl('div',{},'<div id="id1" itemprop="foo"></div><div itemscope></div>');
  1.1803 +	var testEl = parEl.childNodes[1];
  1.1804 +	assert_equals( testEl.properties.length, 0, 'length (before test)' );
  1.1805 +	testEl.itemRef.toggle('id1');
  1.1806 +	assert_equals( testEl.properties.length, 1, 'length after itemref is changed' );
  1.1807 +	assert_equals( testEl.properties.item(0), parEl.firstChild, 'properties.item(0) after itemref is changed' );
  1.1808 +	assert_equals( testEl.properties[0], parEl.firstChild, 'properties[0] after itemref is changed' );
  1.1809 +	testEl.removeAttribute('itemref');
  1.1810 +	assert_equals( testEl.properties.length, 0, 'length after itemref is removed' );
  1.1811 +	assert_true( !testEl.properties.item(0), 'properties.item(0) itemref is removed' );
  1.1812 +	assert_true( !testEl.properties[0], 'properties[0] itemref is removed' );
  1.1813 +	document.body.appendChild(parEl);
  1.1814 +	var beflength = testEl.properties.length;
  1.1815 +	testEl.itemRef.toggle('id1');
  1.1816 +	var length1 = testEl.properties.length,
  1.1817 +	    item0 = testEl.properties.item(0),
  1.1818 +	    prop0 = testEl.properties[0];
  1.1819 +	testEl.removeAttribute('itemref');
  1.1820 +	var length2 = testEl.properties.length,
  1.1821 +	    bitem = !testEl.properties.item(0),
  1.1822 +	    bprop = !testEl.properties[0];
  1.1823 +	document.body.removeChild(parEl);
  1.1824 +	assert_equals( beflength, 0, 'length (before test) when appended to document' );
  1.1825 +	assert_equals( length1, 1, 'length after itemref is changed when appended to document' );
  1.1826 +	assert_equals( item0, parEl.firstChild, 'properties.item(0) after itemref is changed when appended to document' );
  1.1827 +	assert_equals( prop0, parEl.firstChild, 'properties[0] after itemref is changed when appended to document' );
  1.1828 +	assert_equals( length2, 0, 'length after itemref is removed when appended to document' );
  1.1829 +	assert_true( bitem, 'properties.item(0) after itemref is removed when appended to document' );
  1.1830 +	assert_true( bprop, 'properties[0] after itemref is removed when appended to document' );
  1.1831 +}, 'properties.item and length must update when changing itemref to point to an element');
  1.1832 +test(function () {
  1.1833 +	var parEl = makeEl('div',{},'<div id="id1"><div></div></div><div itemscope itemref="id1"></div>');
  1.1834 +	var testEl = parEl.childNodes[1];
  1.1835 +	assert_equals( testEl.properties.length, 0, 'length (before test)' );
  1.1836 +	parEl.firstChild.appendChild(makeEl('div',{itemprop:'foo'}));
  1.1837 +	assert_equals( testEl.properties.length, 1, 'length after a referenced element is added' );
  1.1838 +	assert_equals( testEl.properties.item(0), parEl.firstChild.lastChild, 'properties.item(0) after a referenced element is added' );
  1.1839 +	assert_equals( testEl.properties[0], parEl.firstChild.lastChild, 'properties[0] after a referenced element is added' );
  1.1840 +	parEl.firstChild.firstChild.itemProp.toggle('bar');
  1.1841 +	assert_equals( testEl.properties.length, 2, 'length after a referenced itemprop is changed' );
  1.1842 +	assert_equals( testEl.properties.item(0), parEl.firstChild.firstChild, 'properties.item(0) after a referenced itemprop is changed' );
  1.1843 +	assert_equals( testEl.properties[0], parEl.firstChild.firstChild, 'properties[0] after a referenced itemprop is changed' );
  1.1844 +	assert_equals( testEl.properties.item(1), parEl.firstChild.lastChild, 'properties.item(1) after a referenced itemprop is changed' );
  1.1845 +	assert_equals( testEl.properties[1], parEl.firstChild.lastChild, 'properties[1] after a referenced itemprop is changed' );
  1.1846 +	parEl.firstChild.removeChild(parEl.firstChild.firstChild);
  1.1847 +	assert_equals( testEl.properties.length, 1, 'length after a referenced element is removed' );
  1.1848 +	assert_equals( testEl.properties.item(0), parEl.firstChild.firstChild, 'properties.item(0) after a referenced element is removed' );
  1.1849 +	assert_equals( testEl.properties[0], parEl.firstChild.firstChild, 'properties[0] after a referenced element is removed' );
  1.1850 +	assert_true( !testEl.properties.item(1), 'properties.item(1) after a referenced element is removed' );
  1.1851 +	assert_true( !testEl.properties[1], 'properties[1] after a referenced element is removed' );
  1.1852 +	parEl.innerHTML = '<div id="id1"><div></div></div><div itemscope itemref="id1"></div>';
  1.1853 +	testEl = parEl.childNodes[1];
  1.1854 +	document.body.appendChild(parEl);
  1.1855 +	var beflength = testEl.properties.length;
  1.1856 +	parEl.firstChild.appendChild(makeEl('div',{itemprop:'foo'}));
  1.1857 +	var length1 = testEl.properties.length,
  1.1858 +	    item0a = testEl.properties.item(0),
  1.1859 +	    prop0a = testEl.properties[0],
  1.1860 +	    targ0a = parEl.firstChild.lastChild;
  1.1861 +	parEl.firstChild.firstChild.itemProp.toggle('bar');
  1.1862 +	var length2 = testEl.properties.length,
  1.1863 +	    item0b = testEl.properties.item(0),
  1.1864 +	    prop0b = testEl.properties[0];
  1.1865 +	    item1b = testEl.properties.item(1),
  1.1866 +	    prop1b = testEl.properties[1],
  1.1867 +	    targ0b = parEl.firstChild.firstChild,
  1.1868 +	    targ1b = parEl.firstChild.lastChild;
  1.1869 +	parEl.firstChild.removeChild(parEl.firstChild.firstChild);
  1.1870 +	var length3 = testEl.properties.length,
  1.1871 +	    item0c = testEl.properties.item(0),
  1.1872 +	    prop0c = testEl.properties[0];
  1.1873 +	    item1c = testEl.properties.item(1),
  1.1874 +	    prop1c = testEl.properties[1],
  1.1875 +	    targ0c = parEl.firstChild.firstChild;
  1.1876 +	document.body.removeChild(parEl);
  1.1877 +	assert_equals( beflength, 0, 'length (before test) when appended to document' );
  1.1878 +	assert_equals( length1, 1, 'length after a referenced element is added when appended to document' );
  1.1879 +	assert_equals( item0a, targ0a, 'properties.item(0) after a referenced element is added when appended to document' );
  1.1880 +	assert_equals( prop0a, targ0a, 'properties[0] after a referenced element is added when appended to document' );
  1.1881 +	assert_equals( length2, 2, 'length after a referenced itemprop is changed when appended to document' );
  1.1882 +	assert_equals( item0b, targ0b, 'properties.item(0) after a referenced itemprop is changed when appended to document' );
  1.1883 +	assert_equals( prop0b, targ0b, 'properties[0] after a referenced itemprop is changed when appended to document' );
  1.1884 +	assert_equals( item1b, targ1b, 'properties.item(1) after a referenced itemprop is changed when appended to document' );
  1.1885 +	assert_equals( prop1b, targ1b, 'properties[1] after a referenced itemprop is changed when appended to document' );
  1.1886 +	assert_equals( length3, 1, 'length after a referenced element is removed when appended to document' );
  1.1887 +	assert_equals( item0c, targ0c, 'properties.item(0) after a referenced element is removed when appended to document' );
  1.1888 +	assert_equals( prop0c, targ0c, 'properties[0] after a referenced element is removed when appended to document' );
  1.1889 +	assert_true( !item1c, 'properties.item(1) after a referenced element is removed when appended to document' );
  1.1890 +	assert_true( !prop1c, 'properties[1] after a referenced element is removed when appended to document' );
  1.1891 +}, 'properties.item and length must update when changing children of elements referenced through itemref');
  1.1892 +test(function () {
  1.1893 +	var parEl = makeEl('div',{},'<div id="id1" itemprop="foo"></div><div itemscope itemref="id1"><div itemprop="foo"></div></div>');
  1.1894 +	var testEl = parEl.childNodes[1];
  1.1895 +	assert_equals( testEl.properties.length, 2, 'length (before test)' );
  1.1896 +	assert_equals( testEl.properties[0], parEl.firstChild, 'properties[0] (before test)' );
  1.1897 +	assert_equals( testEl.properties[1], testEl.firstChild, 'properties[1] (before test)' );
  1.1898 +	document.body.appendChild(testEl);
  1.1899 +	var step1length = testEl.properties.length;
  1.1900 +	var step1prop0 = testEl.properties[0];
  1.1901 +	var step1prop1 = testEl.properties[1];
  1.1902 +	parEl.appendChild(testEl);
  1.1903 +	assert_equals( step1length, 1, 'length after changing parent' );
  1.1904 +	assert_equals( step1prop0, testEl.firstChild, 'properties[0] after changing parent' );
  1.1905 +	assert_true( !step1prop1, 'properties[1] after changing parent' );
  1.1906 +	assert_equals( testEl.properties.length, 2, 'length after re-parenting' );
  1.1907 +	assert_equals( testEl.properties[0], parEl.firstChild, 'properties[0] after re-parenting' );
  1.1908 +	assert_equals( testEl.properties[1], testEl.firstChild, 'properties[1] after re-parenting' );
  1.1909 +	document.body.appendChild(parEl);
  1.1910 +	var step2length = testEl.properties.length;
  1.1911 +	var step2prop0 = testEl.properties[0];
  1.1912 +	var step2prop1 = testEl.properties[1];
  1.1913 +	document.createElement('div').appendChild(testEl);
  1.1914 +	var step3length = testEl.properties.length;
  1.1915 +	var step3prop0 = testEl.properties[0];
  1.1916 +	var step3prop1 = testEl.properties[1];
  1.1917 +	parEl.appendChild(testEl);
  1.1918 +	var step4length = testEl.properties.length;
  1.1919 +	var step4prop0 = testEl.properties[0];
  1.1920 +	var step4prop1 = testEl.properties[1];
  1.1921 +	document.body.removeChild(parEl);
  1.1922 +	assert_equals( step2length, 2, 'length (before test) when appended to document' );
  1.1923 +	assert_equals( step2prop0, parEl.firstChild, 'properties[0] (before test) when appended to document' );
  1.1924 +	assert_equals( step2prop1, testEl.firstChild, 'properties[1] (before test) when appended to document' );
  1.1925 +	assert_equals( step3length, 1, 'length after changing parent when appended to document' );
  1.1926 +	assert_equals( step3prop0, testEl.firstChild, 'properties[0] after changing parent when appended to document' );
  1.1927 +	assert_true( !step3prop1, 'properties[1] after changing parent when appended to document' );
  1.1928 +	assert_equals( step4length, 2, 'length after re-parenting when appended to document' );
  1.1929 +	assert_equals( step4prop0, parEl.firstChild, 'properties[0] after re-parenting when appended to document' );
  1.1930 +	assert_equals( step4prop1, testEl.firstChild, 'properties[1] after re-parenting when appended to document' );
  1.1931 +}, 'properties.item and length must update when appending elements with itemref to different parents');
  1.1932 +test(function () {
  1.1933 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div><div itemprop="foo"></div></div>');
  1.1934 +	assert_equals( testEl.properties.length, 1, 'length (before test)' );
  1.1935 +	assert_equals( testEl.properties.item(0), testEl.firstChild.firstChild, 'properties.item(0) (before test)' );
  1.1936 +	assert_equals( testEl.properties[0], testEl.firstChild.firstChild, 'properties[0] (before test)' );
  1.1937 +	testEl.firstChild.itemScope = true;
  1.1938 +	assert_equals( testEl.properties.length, 0, 'length after setting itemscope' );
  1.1939 +	assert_true( !testEl.properties.item(0), 'properties.item(0) after setting itemscope' );
  1.1940 +	assert_true( !testEl.properties[0], 'properties[0] after setting itemscope' );
  1.1941 +	testEl.firstChild.removeAttribute('itemscope');
  1.1942 +	assert_equals( testEl.properties.length, 1, 'length after removing itemscope attribute' );
  1.1943 +	assert_equals( testEl.properties.item(0), testEl.firstChild.firstChild, 'properties.item(0) after removing itemscope attribute' );
  1.1944 +	assert_equals( testEl.properties[0], testEl.firstChild.firstChild, 'properties[0] after removing itemscope attribute' );
  1.1945 +}, 'properties.item and length must update when changing itemscope of children');
  1.1946 +//properties.namedItem
  1.1947 +test(function () {
  1.1948 +	assert_equals( typeof makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>').properties.namedItem('foo'), 'object' );
  1.1949 +}, 'the namedItem must return an object');
  1.1950 +test(function () {
  1.1951 +	assert_equals( typeof makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>').properties['foo'], 'object' );
  1.1952 +}, '.properties[] must also act as .properties.namedItem() when there are matching properties');
  1.1953 +test(function () {
  1.1954 +	assert_equals( typeof makeEl('div',{itemscope:'itemscope'},'').properties.namedItem('foo'), 'object' );
  1.1955 +}, 'the namedItem must return an object even if there are no matching properties');
  1.1956 +test(function () {
  1.1957 +	assert_equals( typeof makeEl('div',{itemscope:'itemscope'},'').properties['foo'], 'undefined' );
  1.1958 +}, '.properties[] must return undefined when no property exists with the given name');
  1.1959 +test(function () {
  1.1960 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>');
  1.1961 +	var PNL = testEl.properties.namedItem('foo');
  1.1962 +	assert_equals( PNL, testEl.properties.namedItem('foo'), 'before modification' );
  1.1963 +	testEl.innerHTML = '';
  1.1964 +	assert_equals( PNL, testEl.properties.namedItem('foo'), 'after modification' );
  1.1965 +}, 'namedItem must return the same object for the same property name');
  1.1966 +test(function () {
  1.1967 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>');
  1.1968 +	assert_false( testEl.properties.namedItem('foo') == testEl.properties.namedItem('bar') );
  1.1969 +}, 'namedItem must return a different object for a different property name');
  1.1970 +test(function () {
  1.1971 +	assert_false( makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>').properties.namedItem('foo') == makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>').properties.namedItem('foo') );
  1.1972 +}, 'namedItem must return a different object for different elements with the same property name');
  1.1973 +test(function () {
  1.1974 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>');
  1.1975 +	assert_equals( testEl.properties.namedItem('foo'), testEl.properties['foo'] );
  1.1976 +}, 'namedItem() and properties[] must return the same object for the same property name');
  1.1977 +test(function () {
  1.1978 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>');
  1.1979 +	assert_true( testEl.properties.namedItem('foo') instanceof PropertyNodeList, 'instanceof PropertyNodeList' );
  1.1980 +	assert_true( testEl.properties.namedItem('foo') instanceof NodeList, 'instanceof NodeList' );
  1.1981 +	PropertyNodeList.prototype.customProperty = true;
  1.1982 +	NodeList.prototype.anotherCustomProperty = true;
  1.1983 +	assert_true( testEl.properties.namedItem('foo').customProperty, 'inheritance from PropertyNodeList' );
  1.1984 +	assert_true( testEl.properties.namedItem('foo').anotherCustomProperty, 'inheritance from NodeList' );
  1.1985 +	PropertyNodeList.prototype.anotherCustomProperty = false;
  1.1986 +	assert_false( testEl.properties.anotherCustomProperty, 'shadowing by PropertyNodeList' );
  1.1987 +}, 'the properties property must implement PropertyNodeList and NodeList');
  1.1988 +test(function () {
  1.1989 +	var failed = false, elem = makeEl('div',{itemscope:'itemscope'});
  1.1990 +	try {
  1.1991 +		elem.properties.namedItem = 'pass';
  1.1992 +	} catch(e) {
  1.1993 +		failed = e;
  1.1994 +	}
  1.1995 +	assert_equals(elem.properties.namedItem,'pass');
  1.1996 +	assert_false(failed,'an error was thrown');
  1.1997 +}, 'the namedItem property must be read/write');
  1.1998 +test(function () {
  1.1999 +	//also tests for sort ordering, which is fairly simple in this case
  1.2000 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="baz qux"></div></div><div itemprop="foo"></div>');
  1.2001 +	assert_equals( testEl.properties.namedItem('foo').length, 2, 'length of foo' );
  1.2002 +	assert_equals( testEl.properties.namedItem('bar').length, 1, 'length of bar' );
  1.2003 +	assert_equals( testEl.properties.namedItem('baz').length, 1, 'length of baz' );
  1.2004 +	assert_equals( testEl.properties.namedItem('qux').length, 1, 'length of qux' );
  1.2005 +	assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'first foo' );
  1.2006 +	assert_equals( testEl.properties.namedItem('foo')[1], testEl.lastChild, 'last foo' );
  1.2007 +	assert_equals( testEl.properties.namedItem('bar')[0], testEl.childNodes[1], 'bar' );
  1.2008 +	assert_equals( testEl.properties.namedItem('baz')[0], testEl.childNodes[1].firstChild, 'baz' );
  1.2009 +	assert_equals( testEl.properties.namedItem('qux')[0], testEl.childNodes[1].firstChild, 'qux' );
  1.2010 +}, 'PropertyNodeList must contain the correct properties');
  1.2011 +test(function () {
  1.2012 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="FOO"></div><div itemprop="foo FOO foo"></div></div><div itemprop="baz qux"></div>');
  1.2013 +	assert_equals( testEl.properties.namedItem('foo').length, 2, 'length of foo' );
  1.2014 +	assert_equals( testEl.properties.namedItem('FOO').length, 2, 'length of FOO' );
  1.2015 +	assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'first foo' );
  1.2016 +	assert_equals( testEl.properties.namedItem('foo')[1], testEl.childNodes[1].lastChild, 'last foo' );
  1.2017 +	assert_equals( testEl.properties.namedItem('FOO')[0], testEl.childNodes[1].firstChild, 'first FOO' );
  1.2018 +	assert_equals( testEl.properties.namedItem('FOO')[1], testEl.childNodes[1].lastChild, 'last FOO' );
  1.2019 +}, 'PropertyNodeList must be case sensitive');
  1.2020 +test(function () {
  1.2021 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo bar"></div>');
  1.2022 +	assert_equals( testEl.properties.namedItem('foo bar').length, 0, 'space' );
  1.2023 +	testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo\tbar"></div>');
  1.2024 +	assert_equals( testEl.properties.namedItem('foo\tbar').length, 0, 'tab' );
  1.2025 +	testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo\rbar"></div>');
  1.2026 +	assert_equals( testEl.properties.namedItem('foo\rbar').length, 0, 'carriage return' );
  1.2027 +	testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo\nbar"></div>');
  1.2028 +	assert_equals( testEl.properties.namedItem('foo\nbar').length, 0, 'newline' );
  1.2029 +	testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo\fbar"></div>');
  1.2030 +	assert_equals( testEl.properties.namedItem('foo\fbar').length, 0, 'formfeed' );
  1.2031 +}, 'namedItem must not match property names containing whitespace');
  1.2032 +test(function () {
  1.2033 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="|§!&quot;#¤%&/()=?`\\@£${[]}´€^¨~\'*,;.:-_&lt;&gt;帿ŨÆ"></div>');
  1.2034 +	assert_equals( testEl.properties.namedItem('|§!"#¤%&/()=?`\\@£${[]}´€^¨~\'*,;.:-_<>帿ŨÆ').length, 1 );
  1.2035 +}, 'namedItem must match property names containing other special characters');
  1.2036 +test(function () {
  1.2037 +	var testEl = makeEl('div',{itemscope:'itemscope'});
  1.2038 +	var PNL = testEl.properties.namedItem('foo');
  1.2039 +	testEl.innerHTML = '<div itemprop="foo"></div>';
  1.2040 +	assert_equals( PNL.length, 1 );
  1.2041 +	assert_equals( PNL[0], testEl.firstChild );
  1.2042 +}, 'PropertyNodeList must be live');
  1.2043 +test(function () {
  1.2044 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemscope><div itemprop="foo"></div><div itemprop="bar"></div></div>');
  1.2045 +	assert_equals( testEl.properties.namedItem('foo').length, 1, 'length of foo' );
  1.2046 +	assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'item 0' );
  1.2047 +	assert_equals( testEl.properties.namedItem('bar').length, 0, 'length of bar' );
  1.2048 +}, 'PropertyNodeList must ignore properties of nested items');
  1.2049 +test(function () {
  1.2050 +
  1.2051 +	//note, itemref ordering is reversed compared with the next test to catch failed sorting algorithms - not that that should make much difference here
  1.2052 +	var parEl = makeEl('div',{},'<div itemprop="foo" id="id1"></div><div itemscope itemref="id2 id1"><div itemprop="foo bar"></div></div><div itemprop="baz" id="id2"><div itemprop="qux"></div></div>');
  1.2053 +	var testEl = parEl.childNodes[1];
  1.2054 +	document.body.appendChild(parEl);
  1.2055 +	var fooLength = testEl.properties.namedItem('foo').length;
  1.2056 +	var barLength = testEl.properties.namedItem('bar').length;
  1.2057 +	var bazLength = testEl.properties.namedItem('baz').length;
  1.2058 +	var quxLength = testEl.properties.namedItem('qux').length;
  1.2059 +	var foo0 = testEl.properties.namedItem('foo')[0];
  1.2060 +	var foo1 = testEl.properties.namedItem('foo')[1];
  1.2061 +	var bar0 = testEl.properties.namedItem('bar')[0];
  1.2062 +	var baz0 = testEl.properties.namedItem('baz')[0];
  1.2063 +	var qux0 = testEl.properties.namedItem('qux')[0];
  1.2064 +	document.body.removeChild(parEl);
  1.2065 +	assert_equals( fooLength, 2, 'foo length' );
  1.2066 +	assert_equals( barLength, 1, 'bar length' );
  1.2067 +	assert_equals( bazLength, 1, 'baz length' );
  1.2068 +	assert_equals( quxLength, 1, 'qux length' );
  1.2069 +	assert_equals( foo0, parEl.firstChild, 'foo 0' );
  1.2070 +	assert_equals( foo1, testEl.firstChild, 'foo 1' );
  1.2071 +	assert_equals( bar0, testEl.firstChild, 'bar 0' );
  1.2072 +	assert_equals( baz0, parEl.lastChild, 'baz 0' );
  1.2073 +	assert_equals( qux0, parEl.lastChild.firstChild, 'qux 0' );
  1.2074 +}, 'PropertyNodeList must see items added with itemref when attached to the document\'s DOM');
  1.2075 +test(function () {
  1.2076 +	var parEl = makeEl('div',{},'<div itemprop="foo" id="id1"></div><div itemscope itemref="id1 id2"><div itemprop="foo bar"></div></div><div itemprop="baz" id="id2"><div itemprop="qux"></div></div>');
  1.2077 +	var testEl = parEl.childNodes[1];
  1.2078 +	assert_equals( testEl.properties.namedItem('foo').length, 2, 'foo length' );
  1.2079 +	assert_equals( testEl.properties.namedItem('bar').length, 1, 'bar length' );
  1.2080 +	assert_equals( testEl.properties.namedItem('baz').length, 1, 'baz length' );
  1.2081 +	assert_equals( testEl.properties.namedItem('qux').length, 1, 'qux length' );
  1.2082 +	assert_equals( testEl.properties.namedItem('foo')[0], parEl.firstChild, 'foo 0' );
  1.2083 +	assert_equals( testEl.properties.namedItem('foo')[1], testEl.firstChild, 'foo 1' );
  1.2084 +	assert_equals( testEl.properties.namedItem('bar')[0], testEl.firstChild, 'bar 0' );
  1.2085 +	assert_equals( testEl.properties.namedItem('baz')[0], parEl.lastChild, 'baz 0' );
  1.2086 +	assert_equals( testEl.properties.namedItem('qux')[0], parEl.lastChild.firstChild, 'qux 0' );
  1.2087 +}, 'PropertyNodeList must see items added with itemref');
  1.2088 +test(function () {
  1.2089 +	//this one also tests the live object just in case - further ones will not always do this as its live status will already have been well established
  1.2090 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>');
  1.2091 +	var PNL = testEl.properties.namedItem('foo');
  1.2092 +	testEl.removeAttribute('itemscope');
  1.2093 +	assert_equals( testEl.properties.namedItem('foo').length, 0, 'removing attribute' );
  1.2094 +	assert_equals( PNL.length, 0, 'removing attribute (live)' );
  1.2095 +	assert_true( !testEl.properties['foo'], 'removing attribute []' );
  1.2096 +	testEl.itemScope = true;
  1.2097 +	assert_equals( testEl.properties.namedItem('foo').length, 1, 'setting itemScope' );
  1.2098 +	assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'property 0 after setting itemScope' );
  1.2099 +	assert_equals( PNL.length, 1, 'setting itemScope (live)' );
  1.2100 +	assert_equals( PNL[0], testEl.firstChild, 'property 0 after setting itemScope (live)' );
  1.2101 +	assert_false( !testEl.properties['foo'], 'setting itemScope []' );
  1.2102 +}, 'PropertyNodeList must update when adding itemscope on the root');
  1.2103 +test(function () {
  1.2104 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>');
  1.2105 +	assert_equals( testEl.properties.namedItem('foo').length, 1, 'foo length (before test)' );
  1.2106 +	assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'foo 0 (before test)' );
  1.2107 +	assert_equals( testEl.properties.namedItem('bar').length, 0, 'bar length (before test)' );
  1.2108 +	testEl.appendChild(makeEl('div',{itemprop:'bar'}));
  1.2109 +	assert_equals( testEl.properties.namedItem('foo').length, 1, 'foo length after adding a child' );
  1.2110 +	assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'foo 0 after adding a child' );
  1.2111 +	assert_equals( testEl.properties.namedItem('bar').length, 1, 'bar length after adding a child' );
  1.2112 +	assert_equals( testEl.properties.namedItem('bar')[0], testEl.lastChild, 'bar 0 after adding a child' );
  1.2113 +	testEl.lastChild.appendChild(makeEl('div',{itemprop:'foo'}));
  1.2114 +	assert_equals( testEl.properties.namedItem('foo').length, 2, 'foo length after adding a child with duplicated name' );
  1.2115 +	assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'foo 0 after adding a child with duplicated name' );
  1.2116 +	assert_equals( testEl.properties.namedItem('foo')[1], testEl.lastChild.firstChild, 'foo 1 after adding a child with duplicated name' );
  1.2117 +	assert_equals( testEl.properties.namedItem('bar').length, 1, 'bar length after adding a child with duplicated name' );
  1.2118 +	assert_equals( testEl.properties.namedItem('bar')[0], testEl.lastChild, 'bar 0 after adding a child with duplicated name' );
  1.2119 +	testEl.lastChild.removeChild(testEl.lastChild.firstChild);
  1.2120 +	assert_equals( testEl.properties.namedItem('foo').length, 1, 'foo length after removing a child' );
  1.2121 +	assert_equals( testEl.properties.namedItem('bar').length, 1, 'bar length after removing a child' );
  1.2122 +}, 'PropertyNodeList must update when adding property elements');
  1.2123 +test(function () {
  1.2124 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="foo"></div>');
  1.2125 +	var PNL = testEl.properties.namedItem('foo');
  1.2126 +	assert_equals( PNL[0], testEl.firstChild, 'item 0 (before test)' );
  1.2127 +	assert_equals( PNL[1], testEl.lastChild, 'item 1 (before test)' );
  1.2128 +	testEl.appendChild(testEl.firstChild);
  1.2129 +	assert_equals( PNL[0], testEl.firstChild, 'item 0 (after test)' );
  1.2130 +	assert_equals( PNL[1], testEl.lastChild, 'item 1 (after test)' );
  1.2131 +}, 'PropertyNodeList must update when re-ordering property elements');
  1.2132 +test(function () {
  1.2133 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div></div>');
  1.2134 +	var PNLfoo = testEl.properties.namedItem('foo'), PNLbar = testEl.properties.namedItem('bar');
  1.2135 +	assert_equals( PNLfoo.length, 1, 'foo length (before test)' );
  1.2136 +	assert_equals( PNLbar.length, 0, 'bar length (before test)' );
  1.2137 +	assert_equals( PNLfoo[0], testEl.firstChild, 'foo[0] (before test)' );
  1.2138 +	testEl.lastChild.itemProp.toggle('bar');
  1.2139 +	assert_equals( PNLfoo.length, 1, 'foo length after adding a token' );
  1.2140 +	assert_equals( PNLbar.length, 1, 'bar length after adding a token' );
  1.2141 +	assert_equals( PNLfoo[0], testEl.firstChild, 'foo[0] after adding a token' );
  1.2142 +	assert_equals( PNLbar[0], testEl.lastChild, 'bar[0] after adding a token' );
  1.2143 +	testEl.lastChild.itemProp.add('foo');
  1.2144 +	assert_equals( PNLfoo.length, 2, 'foo length after adding a duplicated token' );
  1.2145 +	assert_equals( PNLbar.length, 1, 'bar length after adding a duplicated token' );
  1.2146 +	assert_equals( PNLfoo[0], testEl.firstChild, 'foo[0] after adding a duplicated token' );
  1.2147 +	assert_equals( PNLfoo[1], testEl.lastChild, 'foo[1] after adding a duplicated token' );
  1.2148 +	assert_equals( PNLbar[0], testEl.lastChild, 'bar[0] after adding a duplicated token' );
  1.2149 +	testEl.lastChild.removeAttribute('itemprop');
  1.2150 +	assert_equals( PNLfoo.length, 1, 'foo length after removing an attribute' );
  1.2151 +	assert_equals( PNLbar.length, 0, 'bar length after removing an attribute' );
  1.2152 +	assert_equals( PNLfoo[0], testEl.firstChild, 'foo[0] after removing an attribute' );
  1.2153 +}, 'PropertyNodeList must update when changing itemProp of children');
  1.2154 +test(function () {
  1.2155 +	var parEl = makeEl('div',{},'<div itemprop="foo"><div itemprop="bar"></div></div><div itemscope itemref="id1"></div>');
  1.2156 +	var testEl = parEl.childNodes[1];
  1.2157 +	var PNLfoo = testEl.properties.namedItem('foo'), PNLbar = testEl.properties.namedItem('bar');
  1.2158 +	assert_equals( PNLfoo.length, 0, 'foo length (before test)' );
  1.2159 +	assert_equals( PNLbar.length, 0, 'bar length (before test)' );
  1.2160 +	parEl.firstChild.id = 'id1';
  1.2161 +	assert_equals( PNLfoo.length, 1, 'foo length after id is created' );
  1.2162 +	assert_equals( PNLbar.length, 1, 'bar length after id is created' );
  1.2163 +	assert_equals( PNLfoo[0], parEl.firstChild, 'foo[0] after id is created' );
  1.2164 +	assert_equals( PNLbar[0], parEl.firstChild.firstChild, 'bar[0] after id is created' );
  1.2165 +	parEl.firstChild.removeAttribute('id');
  1.2166 +	assert_equals( PNLfoo.length, 0, 'foo length after removing an attribute' );
  1.2167 +	assert_equals( PNLbar.length, 0, 'bar length after removing an attribute' );
  1.2168 +	document.body.appendChild(parEl);
  1.2169 +	var fooLength0 = PNLfoo.length;
  1.2170 +	var barLength0 = PNLbar.length;
  1.2171 +	parEl.firstChild.id = 'id1';
  1.2172 +	var fooLength1 = PNLfoo.length;
  1.2173 +	var barLength1 = PNLbar.length;
  1.2174 +	var foo0 = PNLfoo[0];
  1.2175 +	var bar0 = PNLbar[0];
  1.2176 +	parEl.firstChild.removeAttribute('id');
  1.2177 +	var fooLength2 = PNLfoo.length;
  1.2178 +	var barLength2 = PNLbar.length;
  1.2179 +	document.body.removeChild(parEl);
  1.2180 +	assert_equals( fooLength0, 0, 'foo length (before test) when appended to document' );
  1.2181 +	assert_equals( barLength0, 0, 'bar length (before test) when appended to document' );
  1.2182 +	assert_equals( fooLength1, 1, 'foo length after id is created when appended to document' );
  1.2183 +	assert_equals( barLength1, 1, 'bar length after id is created when appended to document' );
  1.2184 +	assert_equals( foo0, parEl.firstChild, 'foo[0] after id is created when appended to document' );
  1.2185 +	assert_equals( bar0, parEl.firstChild.firstChild, 'bar[0] after id is created when appended to document' );
  1.2186 +	assert_equals( fooLength2, 0, 'foo length after removing an attribute when appended to document' );
  1.2187 +	assert_equals( barLength2, 0, 'bar length after removing an attribute when appended to document' );
  1.2188 +}, 'PropertyNodeList must update when changing id of referenced sibling');
  1.2189 +test(function () {
  1.2190 +	var parEl = makeEl('div',{},'<div itemprop="foo"><div itemprop="bar"></div></div><div itemscope itemref="id1"></div><div itemprop="baz" id="id1"></div>');
  1.2191 +	var testEl = parEl.childNodes[1];
  1.2192 +	var PNLfoo = testEl.properties.namedItem('foo'), PNLbar = testEl.properties.namedItem('bar'), PNLbaz = testEl.properties.namedItem('baz');
  1.2193 +	assert_equals( PNLfoo.length, 0, 'foo length (before test)' );
  1.2194 +	assert_equals( PNLbar.length, 0, 'bar length (before test)' );
  1.2195 +	assert_equals( PNLbaz.length, 1, 'baz length (before test)' );
  1.2196 +	assert_equals( PNLbaz[0], parEl.lastChild, 'baz[0] (before test)' );
  1.2197 +	parEl.firstChild.id = 'id1';
  1.2198 +	assert_equals( PNLfoo.length, 1, 'foo length after id is created' );
  1.2199 +	assert_equals( PNLbar.length, 1, 'bar length after id is created' );
  1.2200 +	assert_equals( PNLbaz.length, 0, 'baz length after id is created' );
  1.2201 +	assert_equals( PNLfoo[0], parEl.firstChild, 'foo[0] after id is created' );
  1.2202 +	assert_equals( PNLbar[0], parEl.firstChild.firstChild, 'bar[0] after id is created' );
  1.2203 +	parEl.firstChild.removeAttribute('id');
  1.2204 +	assert_equals( PNLfoo.length, 0, 'foo length after removing an attribute' );
  1.2205 +	assert_equals( PNLbar.length, 0, 'bar length after removing an attribute' );
  1.2206 +	assert_equals( PNLbaz.length, 1, 'baz length after removing an attribute' );
  1.2207 +	assert_equals( PNLbaz[0], parEl.lastChild, 'baz[0] after removing an attribute' );
  1.2208 +	document.body.appendChild(parEl);
  1.2209 +	var fooLength0 = PNLfoo.length;
  1.2210 +	var barLength0 = PNLbar.length;
  1.2211 +	var bazLength0 = PNLbaz.length;
  1.2212 +	var baz0 = PNLbaz[0];
  1.2213 +	parEl.firstChild.id = 'id1';
  1.2214 +	var fooLength1 = PNLfoo.length;
  1.2215 +	var barLength1 = PNLbar.length;
  1.2216 +	var bazLength1 = PNLbaz.length;
  1.2217 +	var foo0 = PNLfoo[0];
  1.2218 +	var bar0 = PNLbar[0];
  1.2219 +	parEl.firstChild.removeAttribute('id');
  1.2220 +	var fooLength2 = PNLfoo.length;
  1.2221 +	var barLength2 = PNLbar.length;
  1.2222 +	var bazLength2 = PNLbaz.length;
  1.2223 +	var baz1 = PNLbaz[0];
  1.2224 +	document.body.removeChild(parEl);
  1.2225 +	assert_equals( fooLength0, 0, 'foo length (before test) when appended to document' );
  1.2226 +	assert_equals( barLength0, 0, 'bar length (before test) when appended to document' );
  1.2227 +	assert_equals( bazLength0, 1, 'baz length (before test)' );
  1.2228 +	assert_equals( baz0, parEl.lastChild, 'baz[0] (before test)' );
  1.2229 +	assert_equals( fooLength1, 1, 'foo length after id is created when appended to document' );
  1.2230 +	assert_equals( barLength1, 1, 'bar length after id is created when appended to document' );
  1.2231 +	assert_equals( bazLength1, 0, 'baz length after id is created' );
  1.2232 +	assert_equals( foo0, parEl.firstChild, 'foo[0] after id is created when appended to document' );
  1.2233 +	assert_equals( bar0, parEl.firstChild.firstChild, 'bar[0] after id is created when appended to document' );
  1.2234 +	assert_equals( fooLength2, 0, 'foo length after removing an attribute when appended to document' );
  1.2235 +	assert_equals( barLength2, 0, 'bar length after removing an attribute when appended to document' );
  1.2236 +	assert_equals( bazLength2, 1, 'baz length after removing an attribute' );
  1.2237 +	assert_equals( baz0, parEl.lastChild, 'baz[0] after removing an attribute' );
  1.2238 +}, 'PropertyNodeList must update when changing duplicated id of referenced sibling');
  1.2239 +test(function () {
  1.2240 +	var parEl = makeEl('div',{},'<div id="id1" itemprop="foo"></div><div itemscope></div>');
  1.2241 +	var testEl = parEl.childNodes[1];
  1.2242 +	var PNL = testEl.properties.namedItem('foo');
  1.2243 +	assert_equals( PNL.length, 0, 'length (before test)' );
  1.2244 +	testEl.itemRef.toggle('id1');
  1.2245 +	assert_equals( PNL.length, 1, 'length after itemref is changed' );
  1.2246 +	assert_equals( PNL[0], parEl.firstChild, 'item 0 after itemref is changed' );
  1.2247 +	testEl.removeAttribute('itemref');
  1.2248 +	assert_equals( PNL.length, 0, 'length after itemref is removed' );
  1.2249 +	assert_true( !PNL[0], 'item 0 after itemref is removed' );
  1.2250 +	document.body.appendChild(parEl);
  1.2251 +	var length0 = PNL.length;
  1.2252 +	testEl.itemRef.toggle('id1');
  1.2253 +	var length1 = PNL.length;
  1.2254 +	var foo0 = PNL[0];
  1.2255 +	testEl.removeAttribute('itemref');
  1.2256 +	var length2 = PNL.length;
  1.2257 +	var foo1 = PNL[0];
  1.2258 +	document.body.removeChild(parEl);
  1.2259 +	assert_equals( length0, 0, 'length (before test) when appended to document' );
  1.2260 +	assert_equals( length1, 1, 'length after itemref is changed when appended to document' );
  1.2261 +	assert_equals( foo0, parEl.firstChild, 'item 0 after itemref is changed when appended to document' );
  1.2262 +	assert_equals( length2, 0, 'length after itemref is removed when appended to document' );
  1.2263 +	assert_true( !foo1, 'item 0 after itemref is removed when appended to document' );
  1.2264 +}, 'PropertyNodeList must update when changing itemref to point to an element');
  1.2265 +test(function () {
  1.2266 +	var parEl = makeEl('div',{},'<div id="id1"><div></div></div><div itemscope itemref="id1"></div>');
  1.2267 +	var testEl = parEl.childNodes[1];
  1.2268 +	var PNLfoo = testEl.properties.namedItem('foo'), PNLbar = testEl.properties.namedItem('bar');
  1.2269 +	assert_equals( PNLfoo.length, 0, 'foo length (before test)' );
  1.2270 +	assert_equals( PNLbar.length, 0, 'bar length (before test)' );
  1.2271 +	parEl.firstChild.appendChild(makeEl('div',{itemprop:'foo'}));
  1.2272 +	assert_equals( PNLfoo.length, 1, 'foo length after a referenced element is added' );
  1.2273 +	assert_equals( PNLbar.length, 0, 'bar length after a referenced element is added' );
  1.2274 +	assert_equals( PNLfoo.item(0), parEl.firstChild.lastChild, 'foo 0 after a referenced element is added' ); //uses item just for the fun of it
  1.2275 +	parEl.firstChild.firstChild.itemProp.toggle('bar');
  1.2276 +	assert_equals( PNLfoo.length, 1, 'foo length after a referenced itemprop is changed' );
  1.2277 +	assert_equals( PNLbar.length, 1, 'bar length after a referenced itemprop is changed' );
  1.2278 +	assert_equals( PNLfoo[0], parEl.firstChild.lastChild, 'foo 0 after a referenced element is added' );
  1.2279 +	assert_equals( PNLbar[0], parEl.firstChild.firstChild, 'bar 0 after a referenced element is added' );
  1.2280 +	parEl.firstChild.removeChild(parEl.firstChild.firstChild);
  1.2281 +	assert_equals( PNLfoo.length, 1, 'foo length after a referenced element is removed' );
  1.2282 +	assert_equals( PNLbar.length, 0, 'bar length after a referenced element is removed' );
  1.2283 +	assert_equals( PNLfoo[0], parEl.firstChild.firstChild, 'foo 0 after a referenced element is removed' );
  1.2284 +	assert_true( !PNLbar[0], 'bar 0 after a referenced element is removed' );
  1.2285 +	parEl.innerHTML = '<div id="id1"><div></div></div><div itemscope itemref="id1"></div>';
  1.2286 +	testEl = parEl.childNodes[1];
  1.2287 +	PNLfoo = testEl.properties.namedItem('foo');
  1.2288 +	PNLbar = testEl.properties.namedItem('bar');
  1.2289 +	document.body.appendChild(parEl);
  1.2290 +	var step1fooLength = PNLfoo.length;
  1.2291 +	var step1barLength = PNLbar.length;
  1.2292 +	parEl.firstChild.appendChild(makeEl('div',{itemprop:'foo'}));
  1.2293 +	var step2fooLength = PNLfoo.length;
  1.2294 +	var step2barLength = PNLbar.length;
  1.2295 +	var step2foo0 = PNLfoo.item(0); //uses item just for the fun of it
  1.2296 +	var step2fooExpected = parEl.firstChild.lastChild;
  1.2297 +	parEl.firstChild.firstChild.itemProp.toggle('bar');
  1.2298 +	var step3fooLength = PNLfoo.length;
  1.2299 +	var step3barLength = PNLbar.length;
  1.2300 +	var step3foo0 = PNLfoo[0];
  1.2301 +	var step3bar0 = PNLbar[0];
  1.2302 +	var step3fooExpected = parEl.firstChild.lastChild;
  1.2303 +	var step3barExpected = parEl.firstChild.firstChild;
  1.2304 +	parEl.firstChild.removeChild(parEl.firstChild.firstChild);
  1.2305 +	var step4fooLength = PNLfoo.length;
  1.2306 +	var step4barLength = PNLbar.length;
  1.2307 +	var step4foo0 = PNLfoo[0];
  1.2308 +	var step4bar0 = PNLbar[0];
  1.2309 +	var step4fooExpected = parEl.firstChild.firstChild;
  1.2310 +	document.body.removeChild(parEl);
  1.2311 +	assert_equals( step1fooLength, 0, 'foo length (before test) when appended to document' );
  1.2312 +	assert_equals( step1barLength, 0, 'bar length (before test) when appended to document' );
  1.2313 +	assert_equals( step2fooLength, 1, 'foo length after a referenced element is added when appended to document' );
  1.2314 +	assert_equals( step2barLength, 0, 'bar length after a referenced element is added when appended to document' );
  1.2315 +	assert_equals( step2foo0, step2fooExpected, 'foo 0 after a referenced element is added when appended to document' );
  1.2316 +	assert_equals( step3fooLength, 1, 'foo length after a referenced itemprop is changed when appended to document' );
  1.2317 +	assert_equals( step3barLength, 1, 'bar length after a referenced itemprop is changed when appended to document' );
  1.2318 +	assert_equals( step3foo0, step3fooExpected, 'foo 0 after a referenced element is added when appended to document' );
  1.2319 +	assert_equals( step3bar0, step3barExpected, 'bar 0 after a referenced element is added when appended to document' );
  1.2320 +	assert_equals( step4fooLength, 1, 'foo length after a referenced element is removed when appended to document' );
  1.2321 +	assert_equals( step4barLength, 0, 'bar length after a referenced element is removed when appended to document' );
  1.2322 +	assert_equals( step4foo0, step4fooExpected, 'foo 0 after a referenced element is removed when appended to document' );
  1.2323 +	assert_true( !step4bar0, 'bar 0 after a referenced element is removed when appended to document' );
  1.2324 +}, 'PropertyNodeList must update when changing children of elements referenced through itemref');
  1.2325 +test(function () {
  1.2326 +	var parEl = makeEl('div',{},'<div id="id1" itemprop="foo"></div><div itemscope itemref="id1"><div itemprop="foo"></div></div>');
  1.2327 +	var testEl = parEl.childNodes[1];
  1.2328 +	var PNL = testEl.properties.namedItem('foo');
  1.2329 +	assert_equals( PNL.length, 2, 'length (before test)' );
  1.2330 +	assert_equals( PNL[0], parEl.firstChild, 'item 0 (before test)' );
  1.2331 +	assert_equals( PNL[1], testEl.firstChild, 'item 1 (before test)' );
  1.2332 +	document.body.appendChild(testEl);
  1.2333 +	var step1length = PNL.length;
  1.2334 +	var step1prop0 = PNL[0];
  1.2335 +	var step1prop1 = PNL[1];
  1.2336 +	parEl.appendChild(testEl);
  1.2337 +	assert_equals( step1length, 1, 'length after changing parent' );
  1.2338 +	assert_equals( step1prop0, testEl.firstChild, 'item 0 after changing parent' );
  1.2339 +	assert_true( !step1prop1, 'item 1 after changing parent' );
  1.2340 +	assert_equals( PNL.length, 2, 'length after re-parenting' );
  1.2341 +	assert_equals( PNL[0], parEl.firstChild, 'item 0 after re-parenting' );
  1.2342 +	assert_equals( PNL[1], testEl.firstChild, 'item 1 after re-parenting' );
  1.2343 +	document.body.appendChild(parEl);
  1.2344 +	var step2length = PNL.length;
  1.2345 +	var step2prop0 = PNL[0];
  1.2346 +	var step2prop1 = PNL[1];
  1.2347 +	document.createElement('div').appendChild(testEl);
  1.2348 +	var step3length = PNL.length;
  1.2349 +	var step3prop0 = PNL[0];
  1.2350 +	var step3prop1 = PNL[1];
  1.2351 +	parEl.appendChild(testEl);
  1.2352 +	var step4length = PNL.length;
  1.2353 +	var step4prop0 = PNL[0];
  1.2354 +	var step4prop1 = PNL[1];
  1.2355 +	document.body.removeChild(parEl);
  1.2356 +	assert_equals( step2length, 2, 'length (before test) when appended to document' );
  1.2357 +	assert_equals( step2prop0, parEl.firstChild, 'item 0 (before test) when appended to document' );
  1.2358 +	assert_equals( step2prop1, testEl.firstChild, 'item 1 (before test) when appended to document' );
  1.2359 +	assert_equals( step3length, 1, 'length after changing parent when appended to document' );
  1.2360 +	assert_equals( step3prop0, testEl.firstChild, 'item 0 after changing parent when appended to document' );
  1.2361 +	assert_true( !step3prop1, 'item 1 after changing parent when appended to document' );
  1.2362 +	assert_equals( step4length, 2, 'length after re-parenting when appended to document' );
  1.2363 +	assert_equals( step4prop0, parEl.firstChild, 'item 0 after re-parenting when appended to document' );
  1.2364 +	assert_equals( step4prop1, testEl.firstChild, 'item 1 after re-parenting when appended to document' );
  1.2365 +}, 'PropertyNodeList must update when appending elements with itemref to different parents');
  1.2366 +test(function () {
  1.2367 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div><div itemprop="foo"></div></div>');
  1.2368 +	var PNL = testEl.properties.namedItem('foo');
  1.2369 +	assert_equals( PNL.length, 1, 'length (before test)' );
  1.2370 +	assert_equals( PNL[0], testEl.firstChild.firstChild, 'foo 0 (before test)' );
  1.2371 +	testEl.firstChild.itemScope = true;
  1.2372 +	assert_equals( PNL.length, 0, 'length after setting itemscope' );
  1.2373 +	assert_true( !PNL[0], 'foo 0 after setting itemscope' );
  1.2374 +	testEl.firstChild.removeAttribute('itemscope');
  1.2375 +	assert_equals( PNL.length, 1, 'length after removing itemscope attribute' );
  1.2376 +	assert_equals( PNL[0], testEl.firstChild.firstChild, 'foo 0 after removing itemscope attribute' );
  1.2377 +}, 'PropertyNodeList must update when changing itemscope of children');
  1.2378 +//PropertyNodeList.getValues
  1.2379 +test(function () {
  1.2380 +	var valuesArray = makeEl('div',{}).properties.namedItem('foo').getValues();
  1.2381 +	assert_true( valuesArray instanceof Array, 'instanceof test' );
  1.2382 +	Array.prototype.customProp = true;
  1.2383 +	assert_true( valuesArray.customProp, 'inheritance test' );
  1.2384 +}, 'getValues must return an array');
  1.2385 +test(function () {
  1.2386 +	var testEl = makeEl('div',{});
  1.2387 +	var props = testEl.properties.namedItem('foo');
  1.2388 +	assert_not_equals( props.getValues(), props.getValues() );
  1.2389 +}, 'getValues must always return a newly constructed array');
  1.2390 +test(function () {
  1.2391 +	var parEl = makeEl('div',{},'<div id="id1"></div>');
  1.2392 +	var testEl = makeEl('div',{itemscope:'itemscope',itemref:'id1 id2'});
  1.2393 +	parEl.appendChild(testEl);
  1.2394 +	testEl.appendChild(makeEl('meta',{itemprop:'foo',content:'test'}));
  1.2395 +	testEl.appendChild(makeEl('audio',{itemprop:'foo',src:'http://example.org/'},'contained text'));
  1.2396 +	testEl.appendChild(makeEl('embed',{itemprop:'foo',src:'http://example.org/'}));
  1.2397 +	testEl.appendChild(makeEl('iframe',{itemprop:'foo',src:'http://example.org/'},'contained text'));
  1.2398 +	testEl.appendChild(makeEl('img',{itemprop:'foo',src:'http://example.org/'}));
  1.2399 +	testEl.appendChild(makeEl('source',{itemprop:'foo',src:'http://example.org/'}));
  1.2400 +	testEl.appendChild(makeEl('track',{itemprop:'foo',src:'http://example.org/'}));
  1.2401 +	testEl.appendChild(makeEl('video',{itemprop:'foo',src:'http://example.org/'},'contained text'));
  1.2402 +	testEl.appendChild(makeEl('a',{itemprop:'foo',href:'http://example.org/'},'contained text'));
  1.2403 +	testEl.appendChild(makeEl('area',{itemprop:'foo',href:'http://example.org/'}));
  1.2404 +	testEl.appendChild(makeEl('link',{itemprop:'foo',href:'http://example.org/'}));
  1.2405 +	testEl.appendChild(makeEl('object',{itemprop:'foo',data:'http://example.org/'},'contained text'));
  1.2406 +	parEl.appendChild(makeEl('time',{itemprop:'foo',id:'id2'},'te <span itemprop="foo" itemscope>st</span> ing'));
  1.2407 +	testEl.appendChild(makeEl('time',{itemprop:'foo',datetime:'test'},'te <span itemprop="foo" itemscope>st</span> ing'));
  1.2408 +	parEl.firstChild.appendChild(makeEl('div',{itemprop:'foo'},'te <span itemprop="foo" itemscope>st</span> ing'));
  1.2409 +	testEl.appendChild(makeEl('madeuponthespot',{itemprop:'foo'},'te <span itemprop="foo" itemscope>st</span> ing'));
  1.2410 +	var PNL = testEl.properties.namedItem('foo');
  1.2411 +	var valuesArray = PNL.getValues();
  1.2412 +	for( var i = 0; i < PNL.length; i++ ) {
  1.2413 +		assert_equals( valuesArray[i], PNL[i].itemValue, 'property index ' + i + ', tag ' + PNL[i].tagName );
  1.2414 +	}
  1.2415 +	assert_equals( valuesArray.length, 20, 'length' );
  1.2416 +}, 'getValues array must contain the same item values as itemValue would return for the given properties');
  1.2417 +test(function () {
  1.2418 +	var parEl = makeEl('div',{},'<div id="id1"></div>');
  1.2419 +	var testEl = makeEl('div',{itemscope:'itemscope',itemref:'id1 id2'});
  1.2420 +	parEl.appendChild(testEl);
  1.2421 +	testEl.appendChild(makeEl('meta',{itemprop:'foo',content:'test'}));
  1.2422 +	testEl.appendChild(makeEl('audio',{itemprop:'foo',src:'http://example.org/'},'contained text'));
  1.2423 +	testEl.appendChild(makeEl('embed',{itemprop:'foo',src:'http://example.org/'}));
  1.2424 +	testEl.appendChild(makeEl('iframe',{itemprop:'foo',src:'http://example.org/'},'contained text'));
  1.2425 +	testEl.appendChild(makeEl('img',{itemprop:'foo',src:'http://example.org/'}));
  1.2426 +	testEl.appendChild(makeEl('source',{itemprop:'foo',src:'http://example.org/'}));
  1.2427 +	testEl.appendChild(makeEl('track',{itemprop:'foo',src:'http://example.org/'}));
  1.2428 +	testEl.appendChild(makeEl('video',{itemprop:'foo',src:'http://example.org/'},'contained text'));
  1.2429 +	testEl.appendChild(makeEl('a',{itemprop:'foo',href:'http://example.org/'},'contained text'));
  1.2430 +	testEl.appendChild(makeEl('area',{itemprop:'foo',href:'http://example.org/'}));
  1.2431 +	testEl.appendChild(makeEl('link',{itemprop:'foo',href:'http://example.org/'}));
  1.2432 +	testEl.appendChild(makeEl('object',{itemprop:'foo',data:'http://example.org/'},'contained text'));
  1.2433 +	parEl.appendChild(makeEl('time',{itemprop:'foo',id:'id2'},'te <span itemprop="foo" itemscope>st</span> ing'));
  1.2434 +	testEl.appendChild(makeEl('time',{itemprop:'foo',datetime:'test'},'te <span itemprop="foo" itemscope>st</span> ing'));
  1.2435 +	parEl.firstChild.appendChild(makeEl('div',{itemprop:'foo'},'te <span itemprop="foo" itemscope>st</span> ing'));
  1.2436 +	testEl.appendChild(makeEl('madeuponthespot',{itemprop:'foo'},'te <span itemprop="foo" itemscope>st</span> ing'));
  1.2437 +	var PNL = testEl.properties.namedItem('foo');
  1.2438 +	var valuesArray = PNL.getValues();
  1.2439 +	var staticArray = [];
  1.2440 +	for( var i = 0; i < PNL.length; i++ ) {
  1.2441 +		staticArray[i] = PNL[i].itemValue;
  1.2442 +	}
  1.2443 +	testEl.innerHTML = '';
  1.2444 +	parEl.firstChild.firstChild.childNodes[1].itemScope = false;
  1.2445 +	assert_equals( valuesArray.length, staticArray.length, 'length after modification' );
  1.2446 +	for( var j = 0; j < staticArray.length; j++ ) {
  1.2447 +		assert_equals( valuesArray[j], staticArray[j], 'property index ' + j );
  1.2448 +	}
  1.2449 +	assert_equals( valuesArray[1], parEl.firstChild.firstChild.childNodes[1], 'retaining pointer after modification' );
  1.2450 +	staticArray = null;
  1.2451 +	parEl.firstChild.firstChild.innerHTML = '';
  1.2452 +	assert_equals( valuesArray[1] && valuesArray[1].nodeType, 1, 'retaining pointer after removal' );
  1.2453 +}, 'getValues array must not be live');
  1.2454 +//names
  1.2455 +test(function () {
  1.2456 +	assert_equals( typeof makeEl('div',{}).properties.names, 'object' );
  1.2457 +}, 'the names property must be an object');
  1.2458 +test(function () {
  1.2459 +	var testEl = makeEl('div',{});
  1.2460 +	assert_true( testEl.properties.names instanceof DOMStringList, 'instanceof DOMStringList' );
  1.2461 +	DOMStringList.prototype.stringCustomProperty = true;
  1.2462 +	assert_true( testEl.properties.names.stringCustomProperty, 'inheritance from DOMStringList' );
  1.2463 +}, 'the names property must implement DOMStringList');
  1.2464 +test(function () {
  1.2465 +	var failed = false, elem = makeEl('div',{itemscope:'itemscope'}), realList = elem.properties.names;
  1.2466 +	try {
  1.2467 +		elem.properties.names = '';
  1.2468 +	} catch(e) {
  1.2469 +		failed = e;
  1.2470 +	}
  1.2471 +	assert_equals(elem.properties.names,realList);
  1.2472 +	assert_false(failed,'an error was thrown');
  1.2473 +}, 'the names property must be read-only');
  1.2474 +test(function () {
  1.2475 +	var testEl = makeEl('div',{});
  1.2476 +	assert_equals( testEl.properties.names, testEl.properties.names );
  1.2477 +}, 'the names property must always reference the same object');
  1.2478 +test(function () {
  1.2479 +	var testEl = makeEl('div',{});
  1.2480 +	assert_equals( testEl.properties.names.item(0), null, 'item(0)' );
  1.2481 +	assert_equals( testEl.properties.names.item(-1), null, 'item(-1)' );
  1.2482 +}, 'names.item() must return null for out of range indexes');
  1.2483 +test(function () {
  1.2484 +	var testEl = makeEl('div',{});
  1.2485 +	assert_equals( testEl.properties.names[0], window.undefined, '[0]' );
  1.2486 +	assert_equals( testEl.properties.names[-1], window.undefined, '[-1]' );
  1.2487 +}, 'names[index] must return undefined for out of range indexes');
  1.2488 +test(function () {
  1.2489 +	var testEl = makeEl('div',{},'<div itemprop="foo">bar</div>');
  1.2490 +	assert_equals( testEl.properties.names.length, 0, 'length' );
  1.2491 +	assert_true( !testEl.properties.names.item(0), 'item(0)' );
  1.2492 +	assert_true( !testEl.properties.names[0], '[0]' );
  1.2493 +	assert_false( testEl.properties.names.contains('foo'), 'contains' );
  1.2494 +}, 'the names collection must be empty if the element does not have an itemscope property');
  1.2495 +test(function () {
  1.2496 +	var testEl = makeEl('div',{},'<div itemprop="foo">bar</div>');
  1.2497 +	testEl.itemScope = true;
  1.2498 +	assert_equals( testEl.properties.names.length, 1, 'length' );
  1.2499 +	assert_equals( testEl.properties.names.item(0), 'foo', 'item(0)' );
  1.2500 +	assert_equals( testEl.properties.names[0], 'foo', '[0]' );
  1.2501 +	assert_true( testEl.properties.names.contains('foo'), 'contains' );
  1.2502 +}, 'the names collection must become populated if the element is given an itemscope property');
  1.2503 +test(function () {
  1.2504 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo">bar</div>');
  1.2505 +	testEl.itemScope = false;
  1.2506 +	assert_equals( testEl.properties.names.length, 0, 'length' );
  1.2507 +	assert_true( !testEl.properties.names.item(0), 'item(0)' );
  1.2508 +	assert_true( !testEl.properties.names[0], '[0]' );
  1.2509 +	assert_false( testEl.properties.names.contains('foo'), 'contains' );
  1.2510 +}, 'the names collection must become empty if the element\'s itemscope property is removed');
  1.2511 +test(function () {
  1.2512 +	var testEl = makeEl('div',{},'<div itemprop="foo">bar</div>');
  1.2513 +	testEl.properties.names.item = 'test';
  1.2514 +	testEl.properties.names.contains = 'test';
  1.2515 +	assert_equals( testEl.properties.names.item, 'test', 'item' );
  1.2516 +	assert_equals( testEl.properties.names.contains, 'test', 'contains' );
  1.2517 +}, 'the names.item and names.contains methods should be overwriteable');
  1.2518 +test(function () {
  1.2519 +	var testEl = makeEl('div',{},'<div itemprop="foo">bar</div>');
  1.2520 +	testEl.properties.names.localCustomProperty = 'test';
  1.2521 +	assert_equals( testEl.properties.names.localCustomProperty, 'test' );
  1.2522 +}, 'the names.customProperty should be writeable');
  1.2523 +test(function () {
  1.2524 +	//WebIDL and ECMAScript 5 - a readonly property has a getter but not a setter
  1.2525 +	//ES5 makes [[Put]] fail but not throw
  1.2526 +	var failed = false;
  1.2527 +	var elem = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo">bar</div>');
  1.2528 +	try {
  1.2529 +		elem.properties.names.length = 0;
  1.2530 +	} catch(e) {
  1.2531 +		failed = e;
  1.2532 +	}
  1.2533 +	assert_equals(elem.properties.names.length,1);
  1.2534 +	assert_false(failed,'an error was thrown');
  1.2535 +}, 'names.length must be read-only');
  1.2536 +test(function () {
  1.2537 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="foo"></div><div itemprop="foo"></div></div><div itemprop="baz qux"></div>');
  1.2538 +	assert_equals( testEl.properties.names.length, 4 );
  1.2539 +}, 'names.length must be the total number of property names');
  1.2540 +test(function () {
  1.2541 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="foo"></div><div itemprop="foo"></div></div><div itemprop="baz \t\r\n\fqux"></div>');
  1.2542 +	assert_equals( testEl.properties.names.item(0), 'foo', 'item(0)' );
  1.2543 +	assert_equals( testEl.properties.names.item(1), 'bar', 'item(1)' );
  1.2544 +	assert_equals( testEl.properties.names.item(2), 'baz', 'item(2)' );
  1.2545 +	assert_equals( testEl.properties.names.item(3), 'qux', 'item(3)' );
  1.2546 +	assert_equals( testEl.properties.names[0], 'foo', '[0]' );
  1.2547 +	assert_equals( testEl.properties.names[1], 'bar', '[1]' );
  1.2548 +	assert_equals( testEl.properties.names[2], 'baz', '[2]' );
  1.2549 +	assert_equals( testEl.properties.names[3], 'qux', '[3]' );
  1.2550 +}, 'names.item must give each property name in tree order');
  1.2551 +test(function () {
  1.2552 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar BAR bar"><div itemprop="FOO"></div><div itemprop="foo"></div></div><div itemprop="baz qux"></div>');
  1.2553 +	assert_equals( testEl.properties.names.length, 6, 'length' );
  1.2554 +	assert_equals( testEl.properties.names.item(0), 'foo', 'item(0)' );
  1.2555 +	assert_equals( testEl.properties.names.item(1), 'bar', 'item(1)' );
  1.2556 +	assert_equals( testEl.properties.names.item(2), 'BAR', 'item(2)' );
  1.2557 +	assert_equals( testEl.properties.names.item(3), 'FOO', 'item(3)' );
  1.2558 +	assert_equals( testEl.properties.names.item(4), 'baz', 'item(4)' );
  1.2559 +	assert_equals( testEl.properties.names.item(5), 'qux', 'item(5)' );
  1.2560 +	assert_equals( testEl.properties.names[0], 'foo', '[0]' );
  1.2561 +	assert_equals( testEl.properties.names[1], 'bar', '[1]' );
  1.2562 +	assert_equals( testEl.properties.names[2], 'BAR', '[2]' );
  1.2563 +	assert_equals( testEl.properties.names[3], 'FOO', '[3]' );
  1.2564 +	assert_equals( testEl.properties.names[4], 'baz', '[4]' );
  1.2565 +	assert_equals( testEl.properties.names[5], 'qux', '[5]' );
  1.2566 +}, 'names must be case sensitive');
  1.2567 +test(function () {
  1.2568 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="FOO"></div><div itemprop="foo"></div></div><div itemprop="baz qux"></div>');
  1.2569 +	assert_true( testEl.properties.names.contains('foo'), 'foo' );
  1.2570 +	assert_true( testEl.properties.names.contains('FOO'), 'FOO' );
  1.2571 +	assert_true( testEl.properties.names.contains('bar'), 'bar' );
  1.2572 +	assert_false( testEl.properties.names.contains('BAR'), 'BAR' );
  1.2573 +	assert_true( testEl.properties.names.contains('baz'), 'baz' );
  1.2574 +	assert_true( testEl.properties.names.contains('qux'), 'qux' );
  1.2575 +	assert_false( testEl.properties.names.contains('madeup'), 'madeup' );
  1.2576 +}, 'names.contains must return boolean if the name exists');
  1.2577 +test(function () {
  1.2578 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="1"></div>');
  1.2579 +	assert_equals( testEl.properties.names.item('1'), null );
  1.2580 +}, 'names.item must cast to number');
  1.2581 +test(function () {
  1.2582 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="1"></div>');
  1.2583 +	assert_true( testEl.properties.names.contains({ valueOf: function () { return 2; }, toString: function () { return 'foo'; } }), 'object' );
  1.2584 +	assert_true( testEl.properties.names.contains(1), 'number' );
  1.2585 +}, 'names.contains must cast to string');
  1.2586 +test(function () {
  1.2587 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"></div>');
  1.2588 +	var namesList = testEl.properties.names;
  1.2589 +	testEl.innerHTML = '<div itemprop="baz"></div>';
  1.2590 +	assert_equals( testEl.properties.names.length, 1, 'length' );
  1.2591 +	assert_equals( testEl.properties.names[0], 'baz', '[0]' );
  1.2592 +}, 'the names collection must be live');
  1.2593 +test(function () {
  1.2594 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="|§!&quot;#¤%&/()=?`\\@£${[]}´€^¨~\'*,;.:-_&lt;&gt;帿ŨÆ"></div>');
  1.2595 +	assert_equals( testEl.properties.names[0], '|§!"#¤%&/()=?`\\@£${[]}´€^¨~\'*,;.:-_<>帿ŨÆ' );
  1.2596 +}, 'names must reflect property names containing special characters');
  1.2597 +test(function () {
  1.2598 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemscope><div itemprop="bar"></div></div>');
  1.2599 +	assert_equals( testEl.properties.names.length, 1, 'length' );
  1.2600 +	assert_equals( testEl.properties.names[0], 'foo', '[0]' );
  1.2601 +	assert_true( testEl.properties.names.contains('foo'), 'contains(foo)' );
  1.2602 +	assert_false( testEl.properties.names.contains('bar'), 'contains(bar)' );
  1.2603 +}, 'names must ignore properties of nested items');
  1.2604 +test(function () {
  1.2605 +	//note, itemref ordering is reversed compared with the next test to catch failed sorting algorithms
  1.2606 +	var parEl = makeEl('div',{},'<div itemprop="foo" id="id1"></div><div itemscope itemref="id2 id1"><div itemprop="bar"></div></div><div itemprop="baz" id="id2"><div itemprop="qux"></div></div>');
  1.2607 +	var testEl = parEl.childNodes[1];
  1.2608 +	document.body.appendChild(parEl);
  1.2609 +	var length = testEl.properties.names.length;
  1.2610 +	var names0 = testEl.properties.names[0];
  1.2611 +	var names1 = testEl.properties.names[1];
  1.2612 +	var names2 = testEl.properties.names[2];
  1.2613 +	var names3 = testEl.properties.names[3];
  1.2614 +	document.body.removeChild(parEl);
  1.2615 +	assert_equals( length, 4, 'length' );
  1.2616 +	assert_equals( names0, 'foo', 'names[0]' );
  1.2617 +	assert_equals( names1, 'bar', 'names[1]' );
  1.2618 +	assert_equals( names2, 'baz', 'names[2]' );
  1.2619 +	assert_equals( names3, 'qux', 'names[3]' );
  1.2620 +}, 'names must see items added with itemref when attached to the document\'s DOM');
  1.2621 +test(function () {
  1.2622 +	var parEl = makeEl('div',{},'<div itemprop="foo" id="id1"></div><div itemscope itemref="id1 id2"><div itemprop="bar"></div></div><div itemprop="baz" id="id2"><div itemprop="qux"></div></div>');
  1.2623 +	var testEl = parEl.childNodes[1];
  1.2624 +	assert_equals( testEl.properties.names.length, 4, 'length' );
  1.2625 +	assert_equals( testEl.properties.names[0], 'foo', 'names[0]' );
  1.2626 +	assert_equals( testEl.properties.names[1], 'bar', 'names[1]' );
  1.2627 +	assert_equals( testEl.properties.names[2], 'baz', 'names[2]' );
  1.2628 +	assert_equals( testEl.properties.names[3], 'qux', 'names[3]' );
  1.2629 +}, 'names must see items added with itemref');
  1.2630 +test(function () {
  1.2631 +	//this one also tests the live object just in case - further ones will not always do this as its live status will already have been well established
  1.2632 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>');
  1.2633 +	var DSL = testEl.properties.names;
  1.2634 +	testEl.removeAttribute('itemscope');
  1.2635 +	assert_equals( testEl.properties.names.length, 0, 'removing attribute' );
  1.2636 +	assert_equals( DSL.length, 0, 'removing attribute (live)' );
  1.2637 +	assert_true( !testEl.properties.names[0], 'removing attribute [0]' );
  1.2638 +	assert_true( !DSL[0], 'removing attribute [0] (live)' );
  1.2639 +	testEl.itemScope = true;
  1.2640 +	assert_equals( testEl.properties.names.length, 1, 'setting itemScope' );
  1.2641 +	assert_equals( DSL.length, 1, 'setting itemScope (live)' );
  1.2642 +	assert_equals( testEl.properties.names[0], 'foo', 'names[0] after setting itemScope' );
  1.2643 +	assert_equals( DSL[0], 'foo', 'names[0] after setting itemScope (live)' );
  1.2644 +}, 'names must update when adding itemscope on the root');
  1.2645 +test(function () {
  1.2646 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>');
  1.2647 +	assert_equals( testEl.properties.names.length, 1, 'length (before test)' );
  1.2648 +	assert_equals( testEl.properties.names[0], 'foo', 'item 0 (before test)' );
  1.2649 +	testEl.appendChild(makeEl('div',{itemprop:'bar'}));
  1.2650 +	assert_equals( testEl.properties.names.length, 2, 'length after adding a child' );
  1.2651 +	assert_equals( testEl.properties.names[0], 'foo', 'item 0 after adding a child' );
  1.2652 +	assert_equals( testEl.properties.names[1], 'bar', 'item 1 after adding a child' );
  1.2653 +	testEl.lastChild.appendChild(makeEl('div',{itemprop:'foo'}));
  1.2654 +	assert_equals( testEl.properties.names.length, 2, 'foo length after adding a child with duplicated name' );
  1.2655 +	assert_equals( testEl.properties.names[0], 'foo', 'item 0 after adding a child with duplicated name' );
  1.2656 +	assert_equals( testEl.properties.names[1], 'bar', 'item 1 after adding a child with duplicated name' );
  1.2657 +	testEl.removeChild(testEl.lastChild);
  1.2658 +	assert_equals( testEl.properties.names.length, 1, 'length after removing a child' );
  1.2659 +	assert_equals( testEl.properties.names[0], 'foo', 'item 0 after removing a child' );
  1.2660 +}, 'names must update when adding property elements');
  1.2661 +test(function () {
  1.2662 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"></div>');
  1.2663 +	var DSL = testEl.properties.names;
  1.2664 +	assert_equals( DSL[0], 'foo', 'item 0 (before test)' );
  1.2665 +	assert_equals( DSL[1], 'bar', 'item 1 (before test)' );
  1.2666 +	testEl.appendChild(testEl.firstChild);
  1.2667 +	assert_equals( DSL[0], 'bar', 'item 0 (after test)' );
  1.2668 +	assert_equals( DSL[1], 'foo', 'item 1 (after test)' );
  1.2669 +}, 'names must update when re-ordering property elements');
  1.2670 +test(function () {
  1.2671 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div></div>');
  1.2672 +	var DSL = testEl.properties.names;
  1.2673 +	assert_equals( DSL.length, 1, 'length (before test)' );
  1.2674 +	assert_equals( DSL[0], 'foo', 'item 0 (before test)' );
  1.2675 +	testEl.lastChild.itemProp.toggle('bar');
  1.2676 +	assert_equals( DSL.length, 2, 'length after adding a token' );
  1.2677 +	assert_equals( DSL[0], 'foo', 'item 0 after adding a token' );
  1.2678 +	assert_equals( DSL[1], 'bar', 'item 1 after adding a token' );
  1.2679 +	testEl.lastChild.itemProp.add('foo');
  1.2680 +	assert_equals( DSL.length, 2, 'length after adding a duplicated token' );
  1.2681 +	assert_equals( DSL[0], 'foo', 'item 0 after adding a duplicated token' );
  1.2682 +	assert_equals( DSL[1], 'bar', 'item 1 after adding a duplicated token' );
  1.2683 +	testEl.lastChild.removeAttribute('itemprop');
  1.2684 +	assert_equals( DSL.length, 1, 'length after removing an attribute' );
  1.2685 +	assert_equals( DSL[0], 'foo', 'item 0 after removing an attribute' );
  1.2686 +	testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"></div><div itemprop="foo"></div>');
  1.2687 +	DSL = testEl.properties.names;
  1.2688 +	assert_equals( DSL.length, 2, 'length (before second test)' );
  1.2689 +	assert_equals( DSL[0], 'foo', 'item 0 (before second test)' );
  1.2690 +	assert_equals( DSL[1], 'bar', 'item 1 (before second test)' );
  1.2691 +	testEl.firstChild.removeAttribute('itemprop');
  1.2692 +	assert_equals( DSL.length, 2, 'length after removing attribute of first item' );
  1.2693 +	assert_equals( DSL[0], 'bar', 'item 0 after removing attribute of first item' );
  1.2694 +	assert_equals( DSL[1], 'foo', 'item 1 after removing attribute of first item' );
  1.2695 +	testEl.firstChild.itemProp.add('foo');
  1.2696 +	assert_equals( DSL.length, 2, 'length after adding duplicated token to first item' );
  1.2697 +	assert_equals( DSL[0], 'foo', 'item 0 after adding duplicated token to first item' );
  1.2698 +	assert_equals( DSL[1], 'bar', 'item 1 after adding duplicated token to first item' );
  1.2699 +	testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo bar"></div>');
  1.2700 +	DSL = testEl.properties.names;
  1.2701 +	assert_equals( DSL.length, 2, 'length (before third test)' );
  1.2702 +	assert_equals( DSL[0], 'foo', 'item 0 (before third test)' );
  1.2703 +	assert_equals( DSL[1], 'bar', 'item 1 (before third test)' );
  1.2704 +	testEl.firstChild.itemProp.toggle('foo');
  1.2705 +	testEl.firstChild.itemProp.toggle('foo');
  1.2706 +	assert_equals( DSL.length, 2, 'length after swapping tokens' );
  1.2707 +	assert_equals( DSL[0], 'bar', 'item 0 after swapping tokens' );
  1.2708 +	assert_equals( DSL[1], 'foo', 'item 1 after swapping tokens' );
  1.2709 +}, 'names must update when changing itemProp of children');
  1.2710 +test(function () {
  1.2711 +	var parEl = makeEl('div',{},'<div itemprop="foo"><div itemprop="bar"></div></div><div itemscope itemref="id1"></div>');
  1.2712 +	var testEl = parEl.childNodes[1];
  1.2713 +	var DSL = testEl.properties.names;
  1.2714 +	assert_equals( DSL.length, 0, 'length (before test)' );
  1.2715 +	parEl.firstChild.id = 'id1';
  1.2716 +	assert_equals( DSL.length, 2, 'length after id is created' );
  1.2717 +	assert_equals( DSL[0], 'foo', 'item 0 after id is created' );
  1.2718 +	assert_equals( DSL[1], 'bar', 'item 1 after id is created' );
  1.2719 +	parEl.firstChild.removeAttribute('id');
  1.2720 +	assert_equals( DSL.length, 0, 'length after removing an attribute' );
  1.2721 +	document.body.appendChild(parEl);
  1.2722 +	var step1length = DSL.length;
  1.2723 +	parEl.firstChild.id = 'id1';
  1.2724 +	var step2length = DSL.length;
  1.2725 +	var step2item0 = DSL[0];
  1.2726 +	var step2item1 = DSL[1];
  1.2727 +	parEl.firstChild.removeAttribute('id');
  1.2728 +	var step3length = DSL.length;
  1.2729 +	document.body.removeChild(parEl);
  1.2730 +	assert_equals( step1length, 0, 'length (before test) when appended to document' );
  1.2731 +	assert_equals( step2length, 2, 'length after id is created when appended to document' );
  1.2732 +	assert_equals( step2item0, 'foo', 'item 0 after id is created when appended to document' );
  1.2733 +	assert_equals( step2item1, 'bar', 'item 1 after id is created when appended to document' );
  1.2734 +	assert_equals( step3length, 0, 'length after removing an attribute when appended to document' );
  1.2735 +}, 'names must update when changing id of referenced sibling when appended to document');
  1.2736 +test(function () {
  1.2737 +	var parEl = makeEl('div',{},'<div itemprop="foo"><div itemprop="bar"></div></div><div itemscope itemref="id1"></div><div itemprop="baz" id="id1"></div>');
  1.2738 +	var testEl = parEl.childNodes[1];
  1.2739 +	var DSL = testEl.properties.names;
  1.2740 +	assert_equals( DSL.length, 1, 'length (before test)' );
  1.2741 +	assert_equals( DSL[0], 'baz', 'item 0 (before test)' );
  1.2742 +	parEl.firstChild.id = 'id1';
  1.2743 +	assert_equals( DSL.length, 2, 'length after id is created' );
  1.2744 +	assert_equals( DSL[0], 'foo', 'item 0 after id is created' );
  1.2745 +	assert_equals( DSL[1], 'bar', 'item 1 after id is created' );
  1.2746 +	parEl.firstChild.removeAttribute('id');
  1.2747 +	assert_equals( DSL.length, 1, 'length after removing an attribute' );
  1.2748 +	assert_equals( DSL[0], 'baz', 'item 0 after removing an attribute' );
  1.2749 +	document.body.appendChild(parEl);
  1.2750 +	var step1length = DSL.length;
  1.2751 +	var step1item0 = DSL[0];
  1.2752 +	parEl.firstChild.id = 'id1';
  1.2753 +	var step2length = DSL.length;
  1.2754 +	var step2item0 = DSL[0];
  1.2755 +	var step2item1 = DSL[1];
  1.2756 +	parEl.firstChild.removeAttribute('id');
  1.2757 +	var step3length = DSL.length;
  1.2758 +	var step3item0 = DSL[0];
  1.2759 +	document.body.removeChild(parEl);
  1.2760 +	assert_equals( step1length, 1, 'length (before test)' );
  1.2761 +	assert_equals( step1item0, 'baz', 'item 0 (before test)' );
  1.2762 +	assert_equals( step2length, 2, 'length after id is created' );
  1.2763 +	assert_equals( step2item0, 'foo', 'item 0 after id is created' );
  1.2764 +	assert_equals( step2item1, 'bar', 'item 1 after id is created' );
  1.2765 +	assert_equals( step3length, 1, 'length after removing an attribute' );
  1.2766 +	assert_equals( step3item0, 'baz', 'item 0 after removing an attribute' );
  1.2767 +}, 'names must update when changing duplicated id of referenced sibling');
  1.2768 +test(function () {
  1.2769 +	var parEl = makeEl('div',{},'<div id="id1" itemprop="foo"></div><div itemscope></div>');
  1.2770 +	var testEl = parEl.childNodes[1];
  1.2771 +	var DSL = testEl.properties.names;
  1.2772 +	assert_equals( DSL.length, 0, 'length (before test)' );
  1.2773 +	testEl.itemRef.toggle('id1');
  1.2774 +	assert_equals( DSL.length, 1, 'length after itemref is changed' );
  1.2775 +	assert_equals( DSL[0], 'foo', 'item 0 after itemref is changed' );
  1.2776 +	testEl.removeAttribute('itemref');
  1.2777 +	assert_equals( DSL.length, 0, 'length after itemref is removed' );
  1.2778 +	assert_true( !DSL[0], 'item 0 after itemref is removed' );
  1.2779 +	document.body.appendChild(parEl);
  1.2780 +	var step1length = DSL.length;
  1.2781 +	testEl.itemRef.toggle('id1');
  1.2782 +	var step2length = DSL.length;
  1.2783 +	var step2item = DSL[0];
  1.2784 +	testEl.removeAttribute('itemref');
  1.2785 +	var step3length = DSL.length;
  1.2786 +	var step3item = DSL[0];
  1.2787 +	document.body.removeChild(parEl);
  1.2788 +	assert_equals( step1length, 0, 'length (before test)' );
  1.2789 +	assert_equals( step2length, 1, 'length after itemref is changed' );
  1.2790 +	assert_equals( step2item, 'foo', 'item 0 after itemref is changed' );
  1.2791 +	assert_equals( step3length, 0, 'length after itemref is removed' );
  1.2792 +	assert_true( !step3item, 'item 0 after itemref is removed' );
  1.2793 +}, 'names must update when changing itemref to point to an element');
  1.2794 +test(function () {
  1.2795 +	var parEl = makeEl('div',{},'<div id="id1"><div></div></div><div itemscope itemref="id1"></div>');
  1.2796 +	var testEl = parEl.childNodes[1];
  1.2797 +	var DSL = testEl.properties.names;
  1.2798 +	assert_equals( DSL.length, 0, 'length (before test)' );
  1.2799 +	parEl.firstChild.appendChild(makeEl('div',{itemprop:'foo'}));
  1.2800 +	assert_equals( DSL.length, 1, 'length after a referenced element is added' );
  1.2801 +	assert_equals( DSL.item(0), 'foo', 'item 0 after a referenced element is added' ); //uses item just for the fun of it
  1.2802 +	parEl.firstChild.firstChild.itemProp.toggle('bar');
  1.2803 +	assert_equals( DSL.length, 2, 'length after a referenced itemprop is changed' );
  1.2804 +	assert_equals( DSL[0], 'bar', 'item 0 after a referenced element is added' );
  1.2805 +	assert_equals( DSL[1], 'foo', 'item 1 after a referenced element is added' );
  1.2806 +	parEl.firstChild.removeChild(parEl.firstChild.firstChild);
  1.2807 +	assert_equals( DSL.length, 1, 'length after a referenced element is removed' );
  1.2808 +	assert_equals( DSL[0], 'foo', 'item 0 after a referenced element is removed' );
  1.2809 +	parEl.innerHTML = '<div id="id1"><div></div></div><div itemscope itemref="id1"></div>';
  1.2810 +	testEl = parEl.childNodes[1];
  1.2811 +	DSL = testEl.properties.names;
  1.2812 +	document.body.appendChild(parEl);
  1.2813 +	var step1length = DSL.length;
  1.2814 +	parEl.firstChild.appendChild(makeEl('div',{itemprop:'foo'}));
  1.2815 +	var step2length = DSL.length;
  1.2816 +	var step2item0 = DSL.item(0); //uses item just for the fun of it
  1.2817 +	parEl.firstChild.firstChild.itemProp.toggle('bar');
  1.2818 +	var step3length = DSL.length;
  1.2819 +	var step3item0 = DSL[0];
  1.2820 +	var step3item1 = DSL[1];
  1.2821 +	parEl.firstChild.removeChild(parEl.firstChild.firstChild);
  1.2822 +	var step4length = DSL.length;
  1.2823 +	var step4item0 = DSL[0];
  1.2824 +	document.body.removeChild(parEl);
  1.2825 +	assert_equals( step1length, 0, 'length (before test)' );
  1.2826 +	parEl.firstChild.appendChild(makeEl('div',{itemprop:'foo'}));
  1.2827 +	assert_equals( step2length, 1, 'length after a referenced element is added' );
  1.2828 +	assert_equals( step2item0, 'foo', 'item 0 after a referenced element is added' ); //uses item just for the fun of it
  1.2829 +	parEl.firstChild.firstChild.itemProp.toggle('bar');
  1.2830 +	assert_equals( step3length, 2, 'length after a referenced itemprop is changed' );
  1.2831 +	assert_equals( step3item0, 'bar', 'item 0 after a referenced element is added' );
  1.2832 +	assert_equals( step3item1, 'foo', 'item 1 after a referenced element is added' );
  1.2833 +	parEl.firstChild.removeChild(parEl.firstChild.firstChild);
  1.2834 +	assert_equals( step4length, 1, 'length after a referenced element is removed' );
  1.2835 +	assert_equals( step4item0, 'foo', 'item 0 after a referenced element is removed' );
  1.2836 +}, 'names must update when changing children of elements referenced through itemref');
  1.2837 +test(function () {
  1.2838 +	var parEl = makeEl('div',{},'<div id="id1" itemprop="foo"></div><div itemscope itemref="id1"><div itemprop="bar"></div></div>');
  1.2839 +	var testEl = parEl.childNodes[1];
  1.2840 +	var DSL = testEl.properties.names;
  1.2841 +	assert_equals( DSL.length, 2, 'length (before test)' );
  1.2842 +	assert_equals( DSL[0], 'foo', 'item 0 (before test)' );
  1.2843 +	assert_equals( DSL[1], 'bar', 'item 1 (before test)' );
  1.2844 +	document.body.appendChild(testEl);
  1.2845 +	var step1length = DSL.length;
  1.2846 +	var step1prop0 = DSL[0];
  1.2847 +	var step1prop1 = DSL[1];
  1.2848 +	parEl.appendChild(testEl);
  1.2849 +	assert_equals( step1length, 1, 'length after changing parent' );
  1.2850 +	assert_equals( step1prop0, 'bar', 'item 0 after changing parent' );
  1.2851 +	assert_true( !step1prop1, 'item 1 after changing parent' );
  1.2852 +	assert_equals( DSL.length, 2, 'length after re-parenting' );
  1.2853 +	assert_equals( DSL[0], 'foo', 'item 0 after re-parenting' );
  1.2854 +	assert_equals( DSL[1], 'bar', 'item 1 after re-parenting' );
  1.2855 +	document.body.appendChild(parEl);
  1.2856 +	var step2length = DSL.length;
  1.2857 +	var step2prop0 = DSL[0];
  1.2858 +	var step2prop1 = DSL[1];
  1.2859 +	document.createElement('div').appendChild(testEl);
  1.2860 +	var step3length = DSL.length;
  1.2861 +	var step3prop0 = DSL[0];
  1.2862 +	var step3prop1 = DSL[1];
  1.2863 +	parEl.appendChild(testEl);
  1.2864 +	var step4length = DSL.length;
  1.2865 +	var step4prop0 = DSL[0];
  1.2866 +	var step4prop1 = DSL[1];
  1.2867 +	document.body.removeChild(parEl);
  1.2868 +	assert_equals( step2length, 2, 'length (before test) when appended to document' );
  1.2869 +	assert_equals( step2prop0, 'foo', 'item 0 (before test) when appended to document' );
  1.2870 +	assert_equals( step2prop1, 'bar', 'item 1 (before test) when appended to document' );
  1.2871 +	assert_equals( step3length, 1, 'length after changing parent when appended to document' );
  1.2872 +	assert_equals( step3prop0, 'bar', 'item 0 after changing parent when appended to document' );
  1.2873 +	assert_true( !step3prop1, 'item 1 after changing parent when appended to document' );
  1.2874 +	assert_equals( step4length, 2, 'length after re-parenting when appended to document' );
  1.2875 +	assert_equals( step4prop0, 'foo', 'item 0 after re-parenting when appended to document' );
  1.2876 +	assert_equals( step4prop1, 'bar', 'item 1 after re-parenting when appended to document' );
  1.2877 +}, 'names must update when appending elements with itemref to different parents');
  1.2878 +test(function () {
  1.2879 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div><div itemprop="foo"></div></div>');
  1.2880 +	var DSL = testEl.properties.names;
  1.2881 +	assert_equals( DSL.length, 1, 'length (before test)' );
  1.2882 +	assert_equals( DSL[0], 'foo', 'item 0 (before test)' );
  1.2883 +	testEl.firstChild.itemScope = true;
  1.2884 +	assert_equals( DSL.length, 0, 'length after setting itemscope' );
  1.2885 +	assert_true( !DSL[0], 'item 0 after setting itemscope' );
  1.2886 +	testEl.firstChild.removeAttribute('itemscope');
  1.2887 +	assert_equals( DSL.length, 1, 'length after removing itemscope attribute' );
  1.2888 +	assert_equals( DSL[0], 'foo', 'item 0 after removing itemscope attribute' );
  1.2889 +}, 'names must update when changing itemscope of children');
  1.2890 +
  1.2891 +/* potential bugs */
  1.2892 +test(function () {
  1.2893 +	var parEl = makeEl('div',{},'<div id="id1"></div>');
  1.2894 +	var testEl = makeEl('div',{itemscope:'itemscope',itemref:'id1 id2'});
  1.2895 +	parEl.appendChild(testEl);
  1.2896 +	testEl.appendChild(makeEl('meta',{itemprop:'foo',content:'test'}));
  1.2897 +	testEl.appendChild(makeEl('audio',{itemprop:'foo',src:'http://example.org/'},'contained text'));
  1.2898 +	testEl.appendChild(makeEl('embed',{itemprop:'foo',src:'http://example.org/'}));
  1.2899 +	testEl.appendChild(makeEl('iframe',{itemprop:'foo',src:'http://example.org/'},'contained text'));
  1.2900 +	testEl.appendChild(makeEl('img',{itemprop:'foo',src:'http://example.org/'}));
  1.2901 +	testEl.appendChild(makeEl('source',{itemprop:'foo',src:'http://example.org/'}));
  1.2902 +	testEl.appendChild(makeEl('track',{itemprop:'foo',src:'http://example.org/'}));
  1.2903 +	testEl.appendChild(makeEl('video',{itemprop:'foo',src:'http://example.org/'},'contained text'));
  1.2904 +	testEl.appendChild(makeEl('a',{itemprop:'foo',href:'http://example.org/'},'contained text'));
  1.2905 +	testEl.appendChild(makeEl('area',{itemprop:'foo',href:'http://example.org/'}));
  1.2906 +	testEl.appendChild(makeEl('link',{itemprop:'foo',href:'http://example.org/'}));
  1.2907 +	testEl.appendChild(makeEl('object',{itemprop:'foo',data:'http://example.org/'},'contained text'));
  1.2908 +	parEl.appendChild(makeEl('time',{itemprop:'bar',id:'id2'},'te <span itemprop="foo" itemscope>st</span> ing'));
  1.2909 +	testEl.appendChild(makeEl('time',{itemprop:'foo',datetime:'test'},'te <span itemprop="foo" itemscope>st</span> ing'));
  1.2910 +	parEl.firstChild.appendChild(makeEl('div',{itemprop:'baz'},'te <span itemprop="foo" itemscope>st</span> ing'));
  1.2911 +	testEl.appendChild(makeEl('madeuponthespot',{itemprop:'baz'},'te <span itemprop="foo" itemscope>st</span> ing'));
  1.2912 +	var properties, PNLfoo, PNLbar, PNLbaz, fooValues, barValues, bazValues, allArrays, snapshot = [];
  1.2913 +	document.body.appendChild(parEl);
  1.2914 +	try {
  1.2915 +		properties = testEl.properties;
  1.2916 +		PNLfoo = properties.namedItem('foo');
  1.2917 +		PNLbar = properties.namedItem('bar');
  1.2918 +		PNLbaz = properties.namedItem('baz');
  1.2919 +		fooValues = PNLfoo.getValues();
  1.2920 +		barValues = PNLbar.getValues();
  1.2921 +		bazValues = PNLbaz.getValues();
  1.2922 +		allArrays = [properties,PNLfoo,PNLbar,PNLbaz,fooValues,barValues,bazValues];
  1.2923 +		for( var a = 0; a < allArrays.length; a++ ) {
  1.2924 +			snapshot[a] = [];
  1.2925 +			for( var b = 0; b < allArrays[a].length; b++ ) {
  1.2926 +				snapshot[a][b] = allArrays[a][b];
  1.2927 +			}
  1.2928 +		}
  1.2929 +	} catch(e) { /* need to clean up */ }
  1.2930 +	document.body.removeChild(parEl);
  1.2931 +	var c, d;
  1.2932 +	for( c = 0; c < allArrays.length; c++ ) {
  1.2933 +		for( d = 0; d < allArrays[c].length; d++ ) {
  1.2934 +			assert_equals( snapshot[c][d], allArrays[c][d], 'allArrays['+c+']['+d+']' );
  1.2935 +		}
  1.2936 +	}
  1.2937 +	var newArrays = [testEl.properties,testEl.properties.namedItem('foo'),testEl.properties.namedItem('bar'),testEl.properties.namedItem('baz'),testEl.properties.namedItem('foo').getValues(),testEl.properties.namedItem('bar').getValues(),testEl.properties.namedItem('baz').getValues()];
  1.2938 +	for( c = 0; c < newArrays.length; c++ ) {
  1.2939 +		for( d = 0; d < newArrays[c].length; d++ ) {
  1.2940 +			assert_equals( snapshot[c][d], newArrays[c][d], 'newArrays['+c+']['+d+']' );
  1.2941 +		}
  1.2942 +	}
  1.2943 +}, 'collections must survive the parent\'s removal from the document');
  1.2944 +test(function () {
  1.2945 +	var testEl = makeEl('div',{itemscope:'itemscope'});
  1.2946 +	testEl.appendChild(makeEl('meta',{itemprop:'foo',content:'test'}));
  1.2947 +	testEl.appendChild(makeEl('audio',{itemprop:'foo',src:'http://example.org/'},'contained text'));
  1.2948 +	testEl.appendChild(makeEl('embed',{itemprop:'foo',src:'http://example.org/'}));
  1.2949 +	testEl.appendChild(makeEl('iframe',{itemprop:'foo',src:'http://example.org/'},'contained text'));
  1.2950 +	testEl.appendChild(makeEl('img',{itemprop:'foo',src:'http://example.org/'}));
  1.2951 +	testEl.appendChild(makeEl('source',{itemprop:'foo',src:'http://example.org/'}));
  1.2952 +	testEl.appendChild(makeEl('track',{itemprop:'foo',src:'http://example.org/'}));
  1.2953 +	testEl.appendChild(makeEl('video',{itemprop:'foo',src:'http://example.org/'},'contained text'));
  1.2954 +	testEl.appendChild(makeEl('a',{itemprop:'foo',href:'http://example.org/'},'contained text'));
  1.2955 +	testEl.appendChild(makeEl('area',{itemprop:'foo',href:'http://example.org/'}));
  1.2956 +	testEl.appendChild(makeEl('link',{itemprop:'foo',href:'http://example.org/'}));
  1.2957 +	testEl.appendChild(makeEl('object',{itemprop:'foo',data:'http://example.org/'},'contained text'));
  1.2958 +	testEl.appendChild(makeEl('time',{itemprop:'bar',id:'id2'},'te <span itemprop="foo" itemscope>st</span> ing'));
  1.2959 +	testEl.appendChild(makeEl('time',{itemprop:'foo',datetime:'test'},'te <span itemprop="foo" itemscope>st</span> ing'));
  1.2960 +	testEl.appendChild(makeEl('div',{itemprop:'baz'},'te <span itemprop="foo" itemscope>st</span> ing'));
  1.2961 +	testEl.appendChild(makeEl('madeuponthespot',{itemprop:'baz'},'te <span itemprop="foo" itemscope>st</span> ing'));
  1.2962 +	var properties, PNLfoo, PNLbar, PNLbaz, fooValues, barValues, bazValues, allArrays, snapshot = [];
  1.2963 +	document.body.appendChild(testEl);
  1.2964 +	try {
  1.2965 +		properties = testEl.properties;
  1.2966 +		PNLfoo = properties.namedItem('foo');
  1.2967 +		PNLbar = properties.namedItem('bar');
  1.2968 +		PNLbaz = properties.namedItem('baz');
  1.2969 +		fooValues = PNLfoo.getValues();
  1.2970 +		barValues = PNLbar.getValues();
  1.2971 +		bazValues = PNLbaz.getValues();
  1.2972 +		allArrays = [properties,PNLfoo,PNLbar,PNLbaz,fooValues,barValues,bazValues];
  1.2973 +		for( var a = 0; a < allArrays.length; a++ ) {
  1.2974 +			snapshot[a] = [];
  1.2975 +			for( var b = 0; b < allArrays[a].length; b++ ) {
  1.2976 +				snapshot[a][b] = allArrays[a][b];
  1.2977 +			}
  1.2978 +		}
  1.2979 +	} catch(e) { /* need to clean up */ }
  1.2980 +	document.body.removeChild(testEl);
  1.2981 +	var c, d;
  1.2982 +	for( c = 0; c < allArrays.length; c++ ) {
  1.2983 +		for( d = 0; d < allArrays[c].length; d++ ) {
  1.2984 +			assert_equals( snapshot[c][d], allArrays[c][d], 'allArrays['+c+']['+d+']' );
  1.2985 +		}
  1.2986 +	}
  1.2987 +	var newArrays = [testEl.properties,testEl.properties.namedItem('foo'),testEl.properties.namedItem('bar'),testEl.properties.namedItem('baz'),testEl.properties.namedItem('foo').getValues(),testEl.properties.namedItem('bar').getValues(),testEl.properties.namedItem('baz').getValues()];
  1.2988 +	for( c = 0; c < newArrays.length; c++ ) {
  1.2989 +		for( d = 0; d < newArrays[c].length; d++ ) {
  1.2990 +			assert_equals( snapshot[c][d], newArrays[c][d], 'newArrays['+c+']['+d+']' );
  1.2991 +		}
  1.2992 +	}
  1.2993 +}, 'collections must survive the item\'s removal from the document');
  1.2994 +
  1.2995 +/* override_builtins */
  1.2996 +test(function () {
  1.2997 +	//http://dev.w3.org/2006/webapi/WebIDL/#named-properties
  1.2998 +	//[OverrideBuiltins] is not declared for any of the properties, hence no overriding is allowed
  1.2999 +	var testEl = makeEl('div',{itemscope:'itemscope'});
  1.3000 +	var namedItem = testEl.properties.namedItem;
  1.3001 +	var item = testEl.properties.item;
  1.3002 +	var names = testEl.properties.names;
  1.3003 +	testEl.innerHTML = '<div itemprop="namedItem length item names"></div>';
  1.3004 +	assert_equals( testEl.properties['namedItem'], namedItem, 'namedItem' );
  1.3005 +	assert_equals( testEl.properties['length'], 1, 'length' );
  1.3006 +	assert_equals( testEl.properties['item'], item, 'item' );
  1.3007 +	assert_equals( testEl.properties['names'], names, 'names' );
  1.3008 +}, 'itemprop names must not override builtin properties');
  1.3009 +
  1.3010 +/* casting */
  1.3011 +//when calling object[other_object], ECMAScript treats other_object as a named property so it casts it to a string using toString
  1.3012 +//when looking up a named property, ECMAScript and WebIDL <http://dev.w3.org/2006/webapi/WebIDL/#named-properties> will prefer an array index property name
  1.3013 +test(function () {
  1.3014 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="2"></div><div itemprop="0"></div>');
  1.3015 +	assert_equals( testEl.properties.item('0'), testEl.properties.item(0), '0' );
  1.3016 +	assert_equals( testEl.properties.item('2'), testEl.properties.item(2), '2' );
  1.3017 +}, 'properties.item(integerString) should cast to a number');
  1.3018 +test(function () {
  1.3019 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="2"></div><div itemprop="0"></div>');
  1.3020 +	assert_equals( testEl.properties['0'], testEl.properties.item(0), '0' );
  1.3021 +	assert_equals( testEl.properties['2'], window.undefined, '2' );
  1.3022 +}, 'properties[integerString] should act as a numeric index');
  1.3023 +test(function () {
  1.3024 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="0"></div>');
  1.3025 +	assert_equals( testEl.properties.namedItem(0), testEl.properties.namedItem('0'), '0' );
  1.3026 +	assert_true( testEl.properties.namedItem(0) instanceof PropertyNodeList , 'instanceof' );
  1.3027 +}, 'properties.namedItem(integer) should cast to a string');
  1.3028 +test(function () {
  1.3029 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="2 foo"></div><div itemprop="0"></div>');
  1.3030 +	assert_equals( testEl.properties[{ toString: function(){return 'foo';}, valueOf: function(){return 1;} }][0], testEl.firstChild, 'foo' );
  1.3031 +	assert_equals( testEl.properties[{ toString: function(){return '0';}, valueOf: function(){return 1;} }], testEl.firstChild, '0' );
  1.3032 +	assert_equals( testEl.properties[{ toString: function(){return '2';}, valueOf: function(){return 0;} }], window.undefined, '2' );
  1.3033 +}, 'properties[someObject] should cast toString before using whichever casting applies');
  1.3034 +
  1.3035 +/* loops and evil itemref */
  1.3036 +test(function () {
  1.3037 +	//This should have 1 property on each itemscope, pointing only to its direct child
  1.3038 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemscope itemprop="foo"><div itemprop="bar"></div></div>');
  1.3039 +	assert_equals( testEl.properties.length, 1, 'outer length' );
  1.3040 +	assert_equals( testEl.properties[0], testEl.firstChild, 'outer properties[0]' );
  1.3041 +	assert_true( !testEl.properties[1], 'outer properties[1]' );
  1.3042 +	assert_equals( testEl.properties.namedItem('foo').length, 1, 'outer foo.length' );
  1.3043 +	assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'outer foo[0]' );
  1.3044 +	assert_true( !testEl.properties.namedItem('foo')[1], 'outer foo[1]' );
  1.3045 +	assert_equals( testEl.properties.namedItem('bar').length, 0, 'outer bar.length' );
  1.3046 +	assert_true( !testEl.properties.namedItem('bar')[0], 'outer bar[0]' );
  1.3047 +	assert_equals( testEl.properties.names.length, 1, 'outer names.length' );
  1.3048 +	assert_equals( testEl.properties.names[0], 'foo', 'outer names[0]' );
  1.3049 +	assert_true( !testEl.properties.names[1], 'outer names[1]' );
  1.3050 +	assert_equals( testEl.firstChild.properties.length, 1, 'inner length' );
  1.3051 +	assert_equals( testEl.firstChild.properties[0], testEl.firstChild.firstChild, 'inner properties[0]' );
  1.3052 +	assert_true( !testEl.firstChild.properties[1], 'inner properties[1]' );
  1.3053 +	assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'inner foo.length' );
  1.3054 +	assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'inner foo[0]' );
  1.3055 +	assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'inner bar.length' );
  1.3056 +	assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.firstChild.firstChild, 'inner bar[0]' );
  1.3057 +	assert_true( !testEl.firstChild.properties.namedItem('foo')[1], 'inner foo[1]' );
  1.3058 +	assert_equals( testEl.firstChild.properties.names.length, 1, 'inner names.length' );
  1.3059 +	assert_equals( testEl.firstChild.properties.names[0], 'bar', 'inner names[0]' );
  1.3060 +	assert_true( !testEl.firstChild.properties.names[1], 'inner names[1]' );
  1.3061 +}, 'simple nested itemscope');
  1.3062 +test(function () {
  1.3063 +	//This should have 1 property on each itemscope, pointing only to its direct child
  1.3064 +	var testEl = makeEl('div',{itemscope:'itemscope',itemref:'id1'},'<div itemscope itemprop="foo" id="id1" itemref="id2"><div itemprop="bar" id="id2"></div></div>');
  1.3065 +	assert_equals( testEl.properties.length, 1, 'outer length' );
  1.3066 +	assert_equals( testEl.properties[0], testEl.firstChild, 'outer properties[0]' );
  1.3067 +	assert_true( !testEl.properties[1], 'outer properties[1]' );
  1.3068 +	assert_equals( testEl.properties.namedItem('foo').length, 1, 'outer foo.length' );
  1.3069 +	assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'outer foo[0]' );
  1.3070 +	assert_true( !testEl.properties.namedItem('foo')[1], 'outer foo[1]' );
  1.3071 +	assert_equals( testEl.properties.namedItem('bar').length, 0, 'outer bar.length' );
  1.3072 +	assert_true( !testEl.properties.namedItem('bar')[0], 'outer bar[0]' );
  1.3073 +	assert_equals( testEl.properties.names.length, 1, 'outer names.length' );
  1.3074 +	assert_equals( testEl.properties.names[0], 'foo', 'outer names[0]' );
  1.3075 +	assert_true( !testEl.properties.names[1], 'outer names[1]' );
  1.3076 +	assert_equals( testEl.firstChild.properties.length, 1, 'inner length' );
  1.3077 +	assert_equals( testEl.firstChild.properties[0], testEl.firstChild.firstChild, 'inner properties[0]' );
  1.3078 +	assert_true( !testEl.firstChild.properties[1], 'inner properties[1]' );
  1.3079 +	assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'inner foo.length' );
  1.3080 +	assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'inner foo[0]' );
  1.3081 +	assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'inner bar.length' );
  1.3082 +	assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.firstChild.firstChild, 'inner bar[0]' );
  1.3083 +	assert_true( !testEl.firstChild.properties.namedItem('foo')[1], 'inner foo[1]' );
  1.3084 +	assert_equals( testEl.firstChild.properties.names.length, 1, 'inner names.length' );
  1.3085 +	assert_equals( testEl.firstChild.properties.names[0], 'bar', 'inner names[0]' );
  1.3086 +	assert_true( !testEl.firstChild.properties.names[1], 'inner names[1]' );
  1.3087 +	document.body.appendChild(testEl);
  1.3088 +	try {
  1.3089 +		assert_equals( testEl.properties.length, 1, 'outer length when appended to document' );
  1.3090 +		assert_equals( testEl.properties[0], testEl.firstChild, 'outer properties[0] when appended to document' );
  1.3091 +		assert_true( !testEl.properties[1], 'outer properties[1] when appended to document' );
  1.3092 +		assert_equals( testEl.properties.namedItem('foo').length, 1, 'outer foo.length when appended to document' );
  1.3093 +		assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'outer foo[0] when appended to document' );
  1.3094 +		assert_true( !testEl.properties.namedItem('foo')[1], 'outer foo[1] when appended to document' );
  1.3095 +		assert_equals( testEl.properties.namedItem('bar').length, 0, 'outer bar.length when appended to document' );
  1.3096 +		assert_true( !testEl.properties.namedItem('bar')[0], 'outer bar[0] when appended to document' );
  1.3097 +		assert_equals( testEl.properties.names.length, 1, 'outer names.length when appended to document' );
  1.3098 +		assert_equals( testEl.properties.names[0], 'foo', 'outer names[0] when appended to document' );
  1.3099 +		assert_true( !testEl.properties.names[1], 'outer names[1] when appended to document' );
  1.3100 +		assert_equals( testEl.firstChild.properties.length, 1, 'inner length when appended to document' );
  1.3101 +		assert_equals( testEl.firstChild.properties[0], testEl.firstChild.firstChild, 'inner properties[0] when appended to document' );
  1.3102 +		assert_true( !testEl.firstChild.properties[1], 'inner properties[1] when appended to document' );
  1.3103 +		assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'inner foo.length when appended to document' );
  1.3104 +		assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'inner foo[0] when appended to document' );
  1.3105 +		assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'inner bar.length when appended to document' );
  1.3106 +		assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.firstChild.firstChild, 'inner bar[0] when appended to document' );
  1.3107 +		assert_true( !testEl.firstChild.properties.namedItem('foo')[1], 'inner foo[1] when appended to document' );
  1.3108 +		assert_equals( testEl.firstChild.properties.names.length, 1, 'inner names.length when appended to document' );
  1.3109 +		assert_equals( testEl.firstChild.properties.names[0], 'bar', 'inner names[0] when appended to document' );
  1.3110 +		assert_true( !testEl.firstChild.properties.names[1], 'inner names[1] when appended to document' );
  1.3111 +	} catch(e) {
  1.3112 +		document.body.removeChild(testEl);
  1.3113 +		throw (e);
  1.3114 +	}
  1.3115 +	document.body.removeChild(testEl);
  1.3116 +}, 'simple nested itemscope with itemref');
  1.3117 +test(function () {
  1.3118 +	//This should have 3 properties on the item; foo, bar and baz
  1.3119 +	var parEl = makeEl('div',{},'<div itemprop="foo" id="id2"></div><div itemscope itemref="id1 id2"><div itemprop="bar"></div></div><div itemprop="baz" id="id1"></div>');
  1.3120 +	var testEl = parEl.childNodes[1];
  1.3121 +	assert_equals( testEl.properties.length, 3, 'length' );
  1.3122 +	assert_equals( testEl.properties[0], parEl.firstChild, 'properties[0]' );
  1.3123 +	assert_equals( testEl.properties[1], testEl.firstChild, 'properties[1]' );
  1.3124 +	assert_equals( testEl.properties[2], parEl.lastChild, 'properties[2]' );
  1.3125 +	assert_true( !testEl.properties[3], 'properties[3]' );
  1.3126 +	assert_equals( testEl.properties.namedItem('foo').length, 1, 'foo.length' );
  1.3127 +	assert_equals( testEl.properties.namedItem('foo')[0], parEl.firstChild, 'foo[0]' );
  1.3128 +	assert_true( !testEl.properties.namedItem('foo')[1], 'foo[1]' );
  1.3129 +	assert_equals( testEl.properties.namedItem('bar').length, 1, 'bar.length' );
  1.3130 +	assert_equals( testEl.properties.namedItem('bar')[0], testEl.firstChild, 'bar[0]' );
  1.3131 +	assert_true( !testEl.properties.namedItem('bar')[1], 'bar[1]' );
  1.3132 +	assert_equals( testEl.properties.namedItem('baz').length, 1, 'baz.length' );
  1.3133 +	assert_equals( testEl.properties.namedItem('baz')[0], parEl.lastChild, 'baz[0]' );
  1.3134 +	assert_true( !testEl.properties.namedItem('baz')[1], 'baz[1]' );
  1.3135 +	assert_equals( testEl.properties.names.length, 3, 'names.length' );
  1.3136 +	assert_equals( testEl.properties.names[0], 'foo', 'names[0]' );
  1.3137 +	assert_equals( testEl.properties.names[1], 'bar', 'names[1]' );
  1.3138 +	assert_equals( testEl.properties.names[2], 'baz', 'names[2]' );
  1.3139 +	assert_true( !testEl.properties.names[3], 'names[3]' );
  1.3140 +	document.body.appendChild(parEl);
  1.3141 +	try {
  1.3142 +		assert_equals( testEl.properties.length, 3, 'length when appended to document' );
  1.3143 +		assert_equals( testEl.properties[0], parEl.firstChild, 'properties[0] when appended to document' );
  1.3144 +		assert_equals( testEl.properties[1], testEl.firstChild, 'properties[1] when appended to document' );
  1.3145 +		assert_equals( testEl.properties[2], parEl.lastChild, 'properties[2] when appended to document' );
  1.3146 +		assert_true( !testEl.properties[3], 'properties[3] when appended to document' );
  1.3147 +		assert_equals( testEl.properties.namedItem('foo').length, 1, 'foo.length when appended to document' );
  1.3148 +		assert_equals( testEl.properties.namedItem('foo')[0], parEl.firstChild, 'foo[0] when appended to document' );
  1.3149 +		assert_true( !testEl.properties.namedItem('foo')[1], 'foo[1] when appended to document' );
  1.3150 +		assert_equals( testEl.properties.namedItem('bar').length, 1, 'bar.length when appended to document' );
  1.3151 +		assert_equals( testEl.properties.namedItem('bar')[0], testEl.firstChild, 'bar[0] when appended to document' );
  1.3152 +		assert_true( !testEl.properties.namedItem('bar')[1], 'bar[1] when appended to document' );
  1.3153 +		assert_equals( testEl.properties.namedItem('baz').length, 1, 'baz.length when appended to document' );
  1.3154 +		assert_equals( testEl.properties.namedItem('baz')[0], parEl.lastChild, 'baz[0] when appended to document' );
  1.3155 +		assert_true( !testEl.properties.namedItem('baz')[1], 'baz[1] when appended to document' );
  1.3156 +		assert_equals( testEl.properties.names.length, 3, 'names.length when appended to document' );
  1.3157 +		assert_equals( testEl.properties.names[0], 'foo', 'names[0] when appended to document' );
  1.3158 +		assert_equals( testEl.properties.names[1], 'bar', 'names[1] when appended to document' );
  1.3159 +		assert_equals( testEl.properties.names[2], 'baz', 'names[2] when appended to document' );
  1.3160 +		assert_true( !testEl.properties.names[3], 'names[3] when appended to document' );
  1.3161 +	} catch(e) {
  1.3162 +		document.body.removeChild(parEl);
  1.3163 +		throw (e);
  1.3164 +	}
  1.3165 +	document.body.removeChild(parEl);
  1.3166 +}, 'simple sibling itemref');
  1.3167 +test(function () {
  1.3168 +	//This should have no properties
  1.3169 +	var testEl = makeEl('div',{itemscope:'itemscope',id:'id1',itemref:'id1',itemprop:'foo'});
  1.3170 +	assert_equals( testEl.properties.length, 0, 'length' );
  1.3171 +	assert_true( !testEl.properties[0], 'properties[0]' );
  1.3172 +	assert_equals( testEl.properties.namedItem('foo').length, 0, 'foo.length' );
  1.3173 +	assert_true( !testEl.properties.namedItem('foo')[0], 'foo[0]' );
  1.3174 +	assert_equals( testEl.properties.names.length, 0, 'names.length' );
  1.3175 +	assert_true( !testEl.properties.names[0], 'names[0]' );
  1.3176 +	document.body.appendChild(testEl);
  1.3177 +	try {
  1.3178 +		assert_equals( testEl.properties.length, 0, 'length when appended to document' );
  1.3179 +		assert_true( !testEl.properties[0], 'properties[0] when appended to document' );
  1.3180 +		assert_equals( testEl.properties.namedItem('foo').length, 0, 'foo.length when appended to document' );
  1.3181 +		assert_true( !testEl.properties.namedItem('foo')[0], 'foo[0] when appended to document' );
  1.3182 +		assert_equals( testEl.properties.names.length, 0, 'names.length when appended to document' );
  1.3183 +		assert_true( !testEl.properties.names[0], 'names[0] when appended to document' );
  1.3184 +	} catch(e) {
  1.3185 +		document.body.removeChild(testEl);
  1.3186 +		throw (e);
  1.3187 +	}
  1.3188 +	document.body.removeChild(testEl);
  1.3189 +}, 'itemref pointing to itself');
  1.3190 +test(function () {
  1.3191 +	//This should have 1 property, pointing to the child
  1.3192 +	var testEl = makeEl('div',{itemscope:'itemscope',id:'id1',itemref:'id1',itemprop:'foo'},'<div itemprop="bar"></div>');
  1.3193 +	assert_equals( testEl.properties.length, 1, 'length' );
  1.3194 +	assert_equals( testEl.properties[0], testEl.firstChild, 'properties[0]' );
  1.3195 +	assert_true( !testEl.properties[1], 'properties[1]' );
  1.3196 +	assert_equals( testEl.properties.namedItem('foo').length, 0, 'foo.length' );
  1.3197 +	assert_true( !testEl.properties.namedItem('foo')[0], 'foo[0]' );
  1.3198 +	assert_equals( testEl.properties.namedItem('bar').length, 1, 'bar.length' );
  1.3199 +	assert_equals( testEl.properties.namedItem('bar')[0], testEl.firstChild, 'bar[0]' );
  1.3200 +	assert_true( !testEl.properties.namedItem('bar')[1], 'bar[1]' );
  1.3201 +	assert_equals( testEl.properties.names.length, 1, 'names.length' );
  1.3202 +	assert_equals( testEl.properties.names[0], 'bar', 'names[0]' );
  1.3203 +	assert_true( !testEl.properties.names[1], 'names[1]' );
  1.3204 +	document.body.appendChild(testEl);
  1.3205 +	try {
  1.3206 +		assert_equals( testEl.properties.length, 1, 'length when appended to document' );
  1.3207 +		assert_equals( testEl.properties[0], testEl.firstChild, 'properties[0] when appended to document' );
  1.3208 +		assert_true( !testEl.properties[1], 'properties[1] when appended to document' );
  1.3209 +		assert_equals( testEl.properties.namedItem('foo').length, 0, 'foo.length when appended to document' );
  1.3210 +		assert_true( !testEl.properties.namedItem('foo')[0], 'foo[0] when appended to document' );
  1.3211 +		assert_equals( testEl.properties.namedItem('bar').length, 1, 'bar.length when appended to document' );
  1.3212 +		assert_equals( testEl.properties.namedItem('bar')[0], testEl.firstChild, 'bar[0] when appended to document' );
  1.3213 +		assert_true( !testEl.properties.namedItem('bar')[1], 'bar[1] when appended to document' );
  1.3214 +		assert_equals( testEl.properties.names.length, 1, 'names.length when appended to document' );
  1.3215 +		assert_equals( testEl.properties.names[0], 'bar', 'names[0] when appended to document' );
  1.3216 +		assert_true( !testEl.properties.names[1], 'names[1] when appended to document' );
  1.3217 +	} catch(e) {
  1.3218 +		document.body.removeChild(testEl);
  1.3219 +		throw (e);
  1.3220 +	}
  1.3221 +	document.body.removeChild(testEl);
  1.3222 +}, 'itemref pointing to itself with child');
  1.3223 +test(function () {
  1.3224 +	//This should have 1 property on each itemscope, pointing only to its direct child
  1.3225 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemscope itemprop="foo" id="id1" itemref="id1"><div itemprop="bar"></div></div>');
  1.3226 +	assert_equals( testEl.properties.length, 1, 'outer length' );
  1.3227 +	assert_equals( testEl.properties[0], testEl.firstChild, 'outer properties[0]' );
  1.3228 +	assert_true( !testEl.properties[1], 'outer properties[1]' );
  1.3229 +	assert_equals( testEl.properties.namedItem('foo').length, 1, 'outer foo.length' );
  1.3230 +	assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'outer foo[0]' );
  1.3231 +	assert_true( !testEl.properties.namedItem('foo')[1], 'outer foo[1]' );
  1.3232 +	assert_equals( testEl.properties.namedItem('bar').length, 0, 'outer bar.length' );
  1.3233 +	assert_true( !testEl.properties.namedItem('bar')[0], 'outer bar[0]' );
  1.3234 +	assert_equals( testEl.properties.names.length, 1, 'outer names.length' );
  1.3235 +	assert_equals( testEl.properties.names[0], 'foo', 'outer names[0]' );
  1.3236 +	assert_true( !testEl.properties.names[1], 'outer names[1]' );
  1.3237 +	assert_equals( testEl.firstChild.properties.length, 1, 'inner length' );
  1.3238 +	assert_equals( testEl.firstChild.properties[0], testEl.firstChild.firstChild, 'inner properties[0]' );
  1.3239 +	assert_true( !testEl.firstChild.properties[1], 'inner properties[1]' );
  1.3240 +	assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'inner foo.length' );
  1.3241 +	assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'inner foo[0]' );
  1.3242 +	assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'inner bar.length' );
  1.3243 +	assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.firstChild.firstChild, 'inner bar[0]' );
  1.3244 +	assert_true( !testEl.firstChild.properties.namedItem('bar')[1], 'inner bar[1]' );
  1.3245 +	assert_equals( testEl.firstChild.properties.names.length, 1, 'inner names.length' );
  1.3246 +	assert_equals( testEl.firstChild.properties.names[0], 'bar', 'inner names[0]' );
  1.3247 +	assert_true( !testEl.firstChild.properties.names[1], 'inner names[1]' );
  1.3248 +	document.body.appendChild(testEl);
  1.3249 +	try {
  1.3250 +		assert_equals( testEl.properties.length, 1, 'outer length when appended to document' );
  1.3251 +		assert_equals( testEl.properties[0], testEl.firstChild, 'outer properties[0] when appended to document' );
  1.3252 +		assert_true( !testEl.properties[1], 'outer properties[1] when appended to document' );
  1.3253 +		assert_equals( testEl.properties.namedItem('foo').length, 1, 'outer foo.length when appended to document' );
  1.3254 +		assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'outer foo[0] when appended to document' );
  1.3255 +		assert_true( !testEl.properties.namedItem('foo')[1], 'outer foo[1] when appended to document' );
  1.3256 +		assert_equals( testEl.properties.namedItem('bar').length, 0, 'outer bar.length when appended to document' );
  1.3257 +		assert_true( !testEl.properties.namedItem('bar')[0], 'outer bar[0] when appended to document' );
  1.3258 +		assert_equals( testEl.properties.names.length, 1, 'outer names.length when appended to document' );
  1.3259 +		assert_equals( testEl.properties.names[0], 'foo', 'outer names[0] when appended to document' );
  1.3260 +		assert_true( !testEl.properties.names[1], 'outer names[1] when appended to document' );
  1.3261 +		assert_equals( testEl.firstChild.properties.length, 1, 'inner length when appended to document' );
  1.3262 +		assert_equals( testEl.firstChild.properties[0], testEl.firstChild.firstChild, 'inner properties[0] when appended to document' );
  1.3263 +		assert_true( !testEl.firstChild.properties[1], 'inner properties[1] when appended to document' );
  1.3264 +		assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'inner foo.length when appended to document' );
  1.3265 +		assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'inner foo[0] when appended to document' );
  1.3266 +		assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'inner bar.length when appended to document' );
  1.3267 +		assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.firstChild.firstChild, 'inner bar[0] when appended to document' );
  1.3268 +		assert_true( !testEl.firstChild.properties.namedItem('bar')[1], 'inner bar[1] when appended to document' );
  1.3269 +		assert_equals( testEl.firstChild.properties.names.length, 1, 'inner names.length when appended to document' );
  1.3270 +		assert_equals( testEl.firstChild.properties.names[0], 'bar', 'inner names[0] when appended to document' );
  1.3271 +		assert_true( !testEl.firstChild.properties.names[1], 'inner names[1] when appended to document' );
  1.3272 +	} catch(e) {
  1.3273 +		document.body.removeChild(testEl);
  1.3274 +		throw (e);
  1.3275 +	}
  1.3276 +	document.body.removeChild(testEl);
  1.3277 +}, 'nested itemref pointing to itself with child');
  1.3278 +test(function () {
  1.3279 +	//Each itemscope has one property, pointing to the other one
  1.3280 +	var testEl = makeEl('div',{},'<div id="id1" itemprop="foo" itemscope itemref="id2"></div><div id="id2" itemprop="bar" itemscope itemref="id1"></div>');
  1.3281 +	assert_equals( testEl.firstChild.properties.length, 1, 'id1 length' );
  1.3282 +	assert_equals( testEl.firstChild.properties[0], testEl.lastChild, 'id1 properties[0]' );
  1.3283 +	assert_true( !testEl.firstChild.properties[1], 'id1 properties[1]' );
  1.3284 +	assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'id1 foo.length' );
  1.3285 +	assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'id1 foo[0]' );
  1.3286 +	assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'id1 bar.length' );
  1.3287 +	assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.lastChild, 'id1 bar[0]' );
  1.3288 +	assert_true( !testEl.firstChild.properties.namedItem('bar')[1], 'id1 bar[1]' );
  1.3289 +	assert_equals( testEl.firstChild.properties.names.length, 1, 'id1 names.length' );
  1.3290 +	assert_equals( testEl.firstChild.properties.names[0], 'bar', 'id1 names[0]' );
  1.3291 +	assert_true( !testEl.firstChild.properties.names[1], 'id1 names[1]' );
  1.3292 +	assert_equals( testEl.lastChild.properties.length, 1, 'id2 length' );
  1.3293 +	assert_equals( testEl.lastChild.properties[0], testEl.firstChild, 'id2 properties[0]' );
  1.3294 +	assert_true( !testEl.lastChild.properties[1], 'id2 properties[1]' );
  1.3295 +	assert_equals( testEl.lastChild.properties.namedItem('foo').length, 1, 'id2 foo.length' );
  1.3296 +	assert_equals( testEl.lastChild.properties.namedItem('foo')[0], testEl.firstChild, 'id2 foo[0]' );
  1.3297 +	assert_true( !testEl.lastChild.properties.namedItem('foo')[1], 'id2 foo[1]' );
  1.3298 +	assert_equals( testEl.lastChild.properties.namedItem('bar').length, 0, 'id2 bar.length' );
  1.3299 +	assert_true( !testEl.lastChild.properties.namedItem('bar')[0], 'id2 bar[0]' );
  1.3300 +	assert_equals( testEl.lastChild.properties.names.length, 1, 'id2 names.length' );
  1.3301 +	assert_equals( testEl.lastChild.properties.names[0], 'foo', 'id2 names[0]' );
  1.3302 +	assert_true( !testEl.lastChild.properties.names[1], 'id2 names[1]' );
  1.3303 +	document.body.appendChild(testEl);
  1.3304 +	try {
  1.3305 +		assert_equals( testEl.firstChild.properties.length, 1, 'id1 length when appended to document' );
  1.3306 +		assert_equals( testEl.firstChild.properties[0], testEl.lastChild, 'id1 properties[0] when appended to document' );
  1.3307 +		assert_true( !testEl.firstChild.properties[1], 'id1 properties[1] when appended to document' );
  1.3308 +		assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'id1 foo.length when appended to document' );
  1.3309 +		assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'id1 foo[0] when appended to document' );
  1.3310 +		assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'id1 bar.length when appended to document' );
  1.3311 +		assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.lastChild, 'id1 bar[0] when appended to document' );
  1.3312 +		assert_true( !testEl.firstChild.properties.namedItem('bar')[1], 'id1 bar[1] when appended to document' );
  1.3313 +		assert_equals( testEl.firstChild.properties.names.length, 1, 'id1 names.length when appended to document' );
  1.3314 +		assert_equals( testEl.firstChild.properties.names[0], 'bar', 'id1 names[0] when appended to document' );
  1.3315 +		assert_true( !testEl.firstChild.properties.names[1], 'id1 names[1] when appended to document' );
  1.3316 +		assert_equals( testEl.lastChild.properties.length, 1, 'id2 length when appended to document' );
  1.3317 +		assert_equals( testEl.lastChild.properties[0], testEl.firstChild, 'id2 properties[0] when appended to document' );
  1.3318 +		assert_true( !testEl.lastChild.properties[1], 'id2 properties[1] when appended to document' );
  1.3319 +		assert_equals( testEl.lastChild.properties.namedItem('foo').length, 1, 'id2 foo.length when appended to document' );
  1.3320 +		assert_equals( testEl.lastChild.properties.namedItem('foo')[0], testEl.firstChild, 'id2 foo[0] when appended to document' );
  1.3321 +		assert_true( !testEl.lastChild.properties.namedItem('foo')[1], 'id2 foo[1] when appended to document' );
  1.3322 +		assert_equals( testEl.lastChild.properties.namedItem('bar').length, 0, 'id2 bar.length when appended to document' );
  1.3323 +		assert_true( !testEl.lastChild.properties.namedItem('bar')[0], 'id2 bar[0] when appended to document' );
  1.3324 +		assert_equals( testEl.lastChild.properties.names.length, 1, 'id2 names.length when appended to document' );
  1.3325 +		assert_equals( testEl.lastChild.properties.names[0], 'foo', 'id2 names[0] when appended to document' );
  1.3326 +		assert_true( !testEl.lastChild.properties.names[1], 'id2 names[1] when appended to document' );
  1.3327 +	} catch(e) {
  1.3328 +		document.body.removeChild(testEl);
  1.3329 +		throw (e);
  1.3330 +	}
  1.3331 +	document.body.removeChild(testEl);
  1.3332 +}, 'mutually referencing siblings');
  1.3333 +test(function () {
  1.3334 +	//Root has 2 properties, foo and bar
  1.3335 +	//Each itemscope has one property, pointing to the other one
  1.3336 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div id="id1" itemprop="foo" itemscope itemref="id2"></div><div id="id2" itemprop="bar" itemscope itemref="id1"></div>');
  1.3337 +	assert_equals( testEl.properties.length, 2, 'root length' );
  1.3338 +	assert_equals( testEl.properties[0], testEl.firstChild, 'root properties[0]' );
  1.3339 +	assert_equals( testEl.properties[1], testEl.lastChild, 'root properties[1]' );
  1.3340 +	assert_true( !testEl.properties[2], 'root properties[2]' );
  1.3341 +	assert_equals( testEl.properties.namedItem('foo').length, 1, 'root foo.length' );
  1.3342 +	assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'root foo[0]' );
  1.3343 +	assert_true( !testEl.properties.namedItem('foo')[1], 'root foo[1]' );
  1.3344 +	assert_equals( testEl.properties.namedItem('bar').length, 1, 'root bar.length' );
  1.3345 +	assert_equals( testEl.properties.namedItem('bar')[0], testEl.lastChild, 'root bar[0]' );
  1.3346 +	assert_true( !testEl.properties.namedItem('bar')[1], 'root bar[1]' );
  1.3347 +	assert_equals( testEl.properties.names.length, 2, 'root names.length' );
  1.3348 +	assert_equals( testEl.properties.names[0], 'foo', 'root names[0]' );
  1.3349 +	assert_equals( testEl.properties.names[1], 'bar', 'root names[1]' );
  1.3350 +	assert_true( !testEl.properties.names[2], 'root names[2]' );
  1.3351 +	assert_equals( testEl.firstChild.properties.length, 1, 'id1 length' );
  1.3352 +	assert_equals( testEl.firstChild.properties[0], testEl.lastChild, 'id1 properties[0]' );
  1.3353 +	assert_true( !testEl.firstChild.properties[1], 'id1 properties[1]' );
  1.3354 +	assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'id1 foo.length' );
  1.3355 +	assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'id1 foo[0]' );
  1.3356 +	assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'id1 bar.length' );
  1.3357 +	assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.lastChild, 'id1 bar[0]' );
  1.3358 +	assert_true( !testEl.firstChild.properties.namedItem('bar')[1], 'id1 bar[1]' );
  1.3359 +	assert_equals( testEl.firstChild.properties.names.length, 1, 'id1 names.length' );
  1.3360 +	assert_equals( testEl.firstChild.properties.names[0], 'bar', 'id1 names[0]' );
  1.3361 +	assert_true( !testEl.firstChild.properties.names[1], 'id1 names[1]' );
  1.3362 +	assert_equals( testEl.lastChild.properties.length, 1, 'id2 length' );
  1.3363 +	assert_equals( testEl.lastChild.properties[0], testEl.firstChild, 'id2 properties[0]' );
  1.3364 +	assert_true( !testEl.lastChild.properties[1], 'id2 properties[1]' );
  1.3365 +	assert_equals( testEl.lastChild.properties.namedItem('foo').length, 1, 'id2 foo.length' );
  1.3366 +	assert_equals( testEl.lastChild.properties.namedItem('foo')[0], testEl.firstChild, 'id2 foo[0]' );
  1.3367 +	assert_true( !testEl.lastChild.properties.namedItem('foo')[1], 'id2 foo[1]' );
  1.3368 +	assert_equals( testEl.lastChild.properties.namedItem('bar').length, 0, 'id2 bar.length' );
  1.3369 +	assert_true( !testEl.lastChild.properties.namedItem('bar')[0], 'id2 bar[0]' );
  1.3370 +	assert_equals( testEl.lastChild.properties.names.length, 1, 'id2 names.length' );
  1.3371 +	assert_equals( testEl.lastChild.properties.names[0], 'foo', 'id2 names[0]' );
  1.3372 +	assert_true( !testEl.lastChild.properties.names[1], 'id2 names[1]' );
  1.3373 +	document.body.appendChild(testEl);
  1.3374 +	try {
  1.3375 +		assert_equals( testEl.properties.length, 2, 'root length when appended to document' );
  1.3376 +		assert_equals( testEl.properties[0], testEl.firstChild, 'root properties[0] when appended to document' );
  1.3377 +		assert_equals( testEl.properties[1], testEl.lastChild, 'root properties[1] when appended to document' );
  1.3378 +		assert_true( !testEl.properties[2], 'root properties[2] when appended to document' );
  1.3379 +		assert_equals( testEl.properties.namedItem('foo').length, 1, 'root foo.length when appended to document' );
  1.3380 +		assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'root foo[0] when appended to document' );
  1.3381 +		assert_true( !testEl.properties.namedItem('foo')[1], 'root foo[1] when appended to document' );
  1.3382 +		assert_equals( testEl.properties.namedItem('bar').length, 1, 'root bar.length when appended to document' );
  1.3383 +		assert_equals( testEl.properties.namedItem('bar')[0], testEl.lastChild, 'root bar[0] when appended to document' );
  1.3384 +		assert_true( !testEl.properties.namedItem('bar')[1], 'root bar[1] when appended to document' );
  1.3385 +		assert_equals( testEl.properties.names.length, 2, 'root names.length when appended to document' );
  1.3386 +		assert_equals( testEl.properties.names[0], 'foo', 'root names[0] when appended to document' );
  1.3387 +		assert_equals( testEl.properties.names[1], 'bar', 'root names[1] when appended to document' );
  1.3388 +		assert_true( !testEl.properties.names[2], 'root names[2] when appended to document' );
  1.3389 +		assert_equals( testEl.firstChild.properties.length, 1, 'id1 length when appended to document' );
  1.3390 +		assert_equals( testEl.firstChild.properties[0], testEl.lastChild, 'id1 properties[0] when appended to document' );
  1.3391 +		assert_true( !testEl.firstChild.properties[1], 'id1 properties[1] when appended to document' );
  1.3392 +		assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'id1 foo.length when appended to document' );
  1.3393 +		assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'id1 foo[0] when appended to document' );
  1.3394 +		assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'id1 bar.length when appended to document' );
  1.3395 +		assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.lastChild, 'id1 bar[0] when appended to document' );
  1.3396 +		assert_true( !testEl.firstChild.properties.namedItem('bar')[1], 'id1 bar[1] when appended to document' );
  1.3397 +		assert_equals( testEl.firstChild.properties.names.length, 1, 'id1 names.length when appended to document' );
  1.3398 +		assert_equals( testEl.firstChild.properties.names[0], 'bar', 'id1 names[0] when appended to document' );
  1.3399 +		assert_true( !testEl.firstChild.properties.names[1], 'id1 names[1] when appended to document' );
  1.3400 +		assert_equals( testEl.lastChild.properties.length, 1, 'id2 length when appended to document' );
  1.3401 +		assert_equals( testEl.lastChild.properties[0], testEl.firstChild, 'id2 properties[0] when appended to document' );
  1.3402 +		assert_true( !testEl.lastChild.properties[1], 'id2 properties[1] when appended to document' );
  1.3403 +		assert_equals( testEl.lastChild.properties.namedItem('foo').length, 1, 'id2 foo.length when appended to document' );
  1.3404 +		assert_equals( testEl.lastChild.properties.namedItem('foo')[0], testEl.firstChild, 'id2 foo[0] when appended to document' );
  1.3405 +		assert_true( !testEl.lastChild.properties.namedItem('foo')[1], 'id2 foo[1] when appended to document' );
  1.3406 +		assert_equals( testEl.lastChild.properties.namedItem('bar').length, 0, 'id2 bar.length when appended to document' );
  1.3407 +		assert_true( !testEl.lastChild.properties.namedItem('bar')[0], 'id2 bar[0] when appended to document' );
  1.3408 +		assert_equals( testEl.lastChild.properties.names.length, 1, 'id2 names.length when appended to document' );
  1.3409 +		assert_equals( testEl.lastChild.properties.names[0], 'foo', 'id2 names[0] when appended to document' );
  1.3410 +		assert_true( !testEl.lastChild.properties.names[1], 'id2 names[1] when appended to document' );
  1.3411 +	} catch(e) {
  1.3412 +		document.body.removeChild(testEl);
  1.3413 +		throw (e);
  1.3414 +	}
  1.3415 +	document.body.removeChild(testEl);
  1.3416 +}, 'mutually referencing siblings with item parent');
  1.3417 +test(function () {
  1.3418 +	//Root has two properties, foo and bar
  1.3419 +	//Bar has two properties, baz and qux
  1.3420 +	//Qux has one property, bar
  1.3421 +	var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div id="id1" itemprop="bar" itemscope><div itemprop="baz"></div><div itemprop="qux" itemscope itemref="id1"></div></div>');
  1.3422 +	assert_equals( testEl.properties.length, 2, 'root length' );
  1.3423 +	assert_equals( testEl.properties[0], testEl.firstChild, 'root properties[0]' );
  1.3424 +	assert_equals( testEl.properties[1], testEl.lastChild, 'root properties[1]' );
  1.3425 +	assert_true( !testEl.properties[2], 'root properties[2]' );
  1.3426 +	assert_equals( testEl.properties.namedItem('foo').length, 1, 'root foo.length' );
  1.3427 +	assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'root foo[0]' );
  1.3428 +	assert_true( !testEl.properties.namedItem('foo')[1], 'root foo[1]' );
  1.3429 +	assert_equals( testEl.properties.namedItem('bar').length, 1, 'root bar.length' );
  1.3430 +	assert_equals( testEl.properties.namedItem('bar')[0], testEl.lastChild, 'root bar[0]' );
  1.3431 +	assert_true( !testEl.properties.namedItem('bar')[1], 'root bar[1]' );
  1.3432 +	assert_equals( testEl.properties.namedItem('baz').length, 0, 'root baz.length' );
  1.3433 +	assert_true( !testEl.properties.namedItem('baz')[0], 'root baz[0]' );
  1.3434 +	assert_equals( testEl.properties.namedItem('qux').length, 0, 'root qux.length' );
  1.3435 +	assert_true( !testEl.properties.namedItem('qux')[0], 'root qux[0]' );
  1.3436 +	assert_equals( testEl.properties.names.length, 2, 'root names.length' );
  1.3437 +	assert_equals( testEl.properties.names[0], 'foo', 'root names[0]' );
  1.3438 +	assert_equals( testEl.properties.names[1], 'bar', 'root names[1]' );
  1.3439 +	assert_true( !testEl.properties.names[2], 'root names[2]' );
  1.3440 +	assert_equals( testEl.lastChild.properties.length, 2, 'bar length' );
  1.3441 +	assert_equals( testEl.lastChild.properties[0], testEl.lastChild.firstChild, 'bar properties[0]' );
  1.3442 +	assert_equals( testEl.lastChild.properties[1], testEl.lastChild.lastChild, 'bar properties[1]' );
  1.3443 +	assert_true( !testEl.lastChild.properties[2], 'bar properties[2]' );
  1.3444 +	assert_equals( testEl.lastChild.properties.namedItem('foo').length, 0, 'bar foo.length' );
  1.3445 +	assert_true( !testEl.lastChild.properties.namedItem('foo')[0], 'bar foo[0]' );
  1.3446 +	assert_equals( testEl.lastChild.properties.namedItem('bar').length, 0, 'bar bar.length' );
  1.3447 +	assert_true( !testEl.lastChild.properties.namedItem('bar')[0], 'bar bar[0]' );
  1.3448 +	assert_equals( testEl.lastChild.properties.namedItem('baz').length, 1, 'bar baz.length' );
  1.3449 +	assert_equals( testEl.lastChild.properties.namedItem('baz')[0], testEl.lastChild.firstChild, 'bar baz[0]' );
  1.3450 +	assert_true( !testEl.lastChild.properties.namedItem('baz')[1], 'bar baz[1]' );
  1.3451 +	assert_equals( testEl.lastChild.properties.namedItem('qux').length, 1, 'bar qux.length' );
  1.3452 +	assert_equals( testEl.lastChild.properties.namedItem('qux')[0], testEl.lastChild.lastChild, 'bar qux[0]' );
  1.3453 +	assert_true( !testEl.lastChild.properties.namedItem('qux')[1], 'bar qux[1]' );
  1.3454 +	assert_equals( testEl.lastChild.properties.names.length, 2, 'bar names.length' );
  1.3455 +	assert_equals( testEl.lastChild.properties.names[0], 'baz', 'bar names[0]' );
  1.3456 +	assert_equals( testEl.lastChild.properties.names[1], 'qux', 'bar names[1]' );
  1.3457 +	assert_true( !testEl.lastChild.properties.names[2], 'bar names[2]' );
  1.3458 +	assert_equals( testEl.lastChild.lastChild.properties.length, 1, 'qux length' );
  1.3459 +	assert_equals( testEl.lastChild.lastChild.properties[0], testEl.lastChild, 'qux properties[0]' );
  1.3460 +	assert_true( !testEl.lastChild.lastChild.properties[1], 'qux properties[1]' );
  1.3461 +	assert_equals( testEl.lastChild.lastChild.properties.namedItem('foo').length, 0, 'qux foo.length' );
  1.3462 +	assert_true( !testEl.lastChild.lastChild.properties.namedItem('foo')[0], 'qux foo[0]' );
  1.3463 +	assert_equals( testEl.lastChild.lastChild.properties.namedItem('bar').length, 1, 'qux bar.length' );
  1.3464 +	assert_equals( testEl.lastChild.lastChild.properties.namedItem('bar')[0], testEl.lastChild, 'qux bar[0]' );
  1.3465 +	assert_true( !testEl.lastChild.lastChild.properties.namedItem('bar')[1], 'qux bar[1]' );
  1.3466 +	assert_equals( testEl.lastChild.lastChild.properties.namedItem('baz').length, 0, 'qux baz.length' );
  1.3467 +	assert_true( !testEl.lastChild.lastChild.properties.namedItem('baz')[0], 'qux baz[0]' );
  1.3468 +	assert_equals( testEl.lastChild.lastChild.properties.namedItem('qux').length, 0, 'qux qux.length' );
  1.3469 +	assert_true( !testEl.lastChild.lastChild.properties.namedItem('qux')[0], 'qux qux[0]' );
  1.3470 +	assert_equals( testEl.lastChild.lastChild.properties.names.length, 1, 'qux names.length' );
  1.3471 +	assert_equals( testEl.lastChild.lastChild.properties.names[0], 'bar', 'qux names[0]' );
  1.3472 +	assert_true( !testEl.lastChild.lastChild.properties.names[1], 'qux names[1]' );
  1.3473 +	document.body.appendChild(testEl);
  1.3474 +	try {
  1.3475 +		assert_equals( testEl.properties.length, 2, 'root length when appended to document' );
  1.3476 +		assert_equals( testEl.properties[0], testEl.firstChild, 'root properties[0] when appended to document' );
  1.3477 +		assert_equals( testEl.properties[1], testEl.lastChild, 'root properties[1] when appended to document' );
  1.3478 +		assert_true( !testEl.properties[2], 'root properties[2] when appended to document' );
  1.3479 +		assert_equals( testEl.properties.namedItem('foo').length, 1, 'root foo.length when appended to document' );
  1.3480 +		assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'root foo[0] when appended to document' );
  1.3481 +		assert_true( !testEl.properties.namedItem('foo')[1], 'root foo[1] when appended to document' );
  1.3482 +		assert_equals( testEl.properties.namedItem('bar').length, 1, 'root bar.length when appended to document' );
  1.3483 +		assert_equals( testEl.properties.namedItem('bar')[0], testEl.lastChild, 'root bar[0] when appended to document' );
  1.3484 +		assert_true( !testEl.properties.namedItem('bar')[1], 'root bar[1] when appended to document' );
  1.3485 +		assert_equals( testEl.properties.namedItem('baz').length, 0, 'root baz.length when appended to document' );
  1.3486 +		assert_true( !testEl.properties.namedItem('baz')[0], 'root baz[0] when appended to document' );
  1.3487 +		assert_equals( testEl.properties.namedItem('qux').length, 0, 'root qux.length when appended to document' );
  1.3488 +		assert_true( !testEl.properties.namedItem('qux')[0], 'root qux[0] when appended to document' );
  1.3489 +		assert_equals( testEl.properties.names.length, 2, 'root names.length when appended to document' );
  1.3490 +		assert_equals( testEl.properties.names[0], 'foo', 'root names[0] when appended to document' );
  1.3491 +		assert_equals( testEl.properties.names[1], 'bar', 'root names[1] when appended to document' );
  1.3492 +		assert_true( !testEl.properties.names[2], 'root names[2] when appended to document' );
  1.3493 +		assert_equals( testEl.lastChild.properties.length, 2, 'bar length when appended to document' );
  1.3494 +		assert_equals( testEl.lastChild.properties[0], testEl.lastChild.firstChild, 'bar properties[0] when appended to document' );
  1.3495 +		assert_equals( testEl.lastChild.properties[1], testEl.lastChild.lastChild, 'bar properties[1] when appended to document' );
  1.3496 +		assert_true( !testEl.lastChild.properties[2], 'bar properties[2] when appended to document' );
  1.3497 +		assert_equals( testEl.lastChild.properties.namedItem('foo').length, 0, 'bar foo.length when appended to document' );
  1.3498 +		assert_true( !testEl.lastChild.properties.namedItem('foo')[0], 'bar foo[0] when appended to document' );
  1.3499 +		assert_equals( testEl.lastChild.properties.namedItem('bar').length, 0, 'bar bar.length when appended to document' );
  1.3500 +		assert_true( !testEl.lastChild.properties.namedItem('bar')[0], 'bar bar[0] when appended to document' );
  1.3501 +		assert_equals( testEl.lastChild.properties.namedItem('baz').length, 1, 'bar baz.length when appended to document' );
  1.3502 +		assert_equals( testEl.lastChild.properties.namedItem('baz')[0], testEl.lastChild.firstChild, 'bar baz[0] when appended to document' );
  1.3503 +		assert_true( !testEl.lastChild.properties.namedItem('baz')[1], 'bar baz[1] when appended to document' );
  1.3504 +		assert_equals( testEl.lastChild.properties.namedItem('qux').length, 1, 'bar qux.length when appended to document' );
  1.3505 +		assert_equals( testEl.lastChild.properties.namedItem('qux')[0], testEl.lastChild.lastChild, 'bar qux[0] when appended to document' );
  1.3506 +		assert_true( !testEl.lastChild.properties.namedItem('qux')[1], 'bar qux[1] when appended to document' );
  1.3507 +		assert_equals( testEl.lastChild.properties.names.length, 2, 'bar names.length when appended to document' );
  1.3508 +		assert_equals( testEl.lastChild.properties.names[0], 'baz', 'bar names[0] when appended to document' );
  1.3509 +		assert_equals( testEl.lastChild.properties.names[1], 'qux', 'bar names[1] when appended to document' );
  1.3510 +		assert_true( !testEl.lastChild.properties.names[2], 'bar names[2] when appended to document' );
  1.3511 +		assert_equals( testEl.lastChild.lastChild.properties.length, 1, 'qux length when appended to document' );
  1.3512 +		assert_equals( testEl.lastChild.lastChild.properties[0], testEl.lastChild, 'qux properties[0] when appended to document' );
  1.3513 +		assert_true( !testEl.lastChild.lastChild.properties[1], 'qux properties[1] when appended to document' );
  1.3514 +		assert_equals( testEl.lastChild.lastChild.properties.namedItem('foo').length, 0, 'qux foo.length when appended to document' );
  1.3515 +		assert_true( !testEl.lastChild.lastChild.properties.namedItem('foo')[0], 'qux foo[0] when appended to document' );
  1.3516 +		assert_equals( testEl.lastChild.lastChild.properties.namedItem('bar').length, 1, 'qux bar.length when appended to document' );
  1.3517 +		assert_equals( testEl.lastChild.lastChild.properties.namedItem('bar')[0], testEl.lastChild, 'qux bar[0] when appended to document' );
  1.3518 +		assert_true( !testEl.lastChild.lastChild.properties.namedItem('bar')[1], 'qux bar[1] when appended to document' );
  1.3519 +		assert_equals( testEl.lastChild.lastChild.properties.namedItem('baz').length, 0, 'qux baz.length when appended to document' );
  1.3520 +		assert_true( !testEl.lastChild.lastChild.properties.namedItem('baz')[0], 'qux baz[0] when appended to document' );
  1.3521 +		assert_equals( testEl.lastChild.lastChild.properties.namedItem('qux').length, 0, 'qux qux.length when appended to document' );
  1.3522 +		assert_true( !testEl.lastChild.lastChild.properties.namedItem('qux')[0], 'qux qux[0] when appended to document' );
  1.3523 +		assert_equals( testEl.lastChild.lastChild.properties.names.length, 1, 'qux names.length when appended to document' );
  1.3524 +		assert_equals( testEl.lastChild.lastChild.properties.names[0], 'bar', 'qux names[0] when appended to document' );
  1.3525 +		assert_true( !testEl.lastChild.lastChild.properties.names[1], 'qux names[1] when appended to document' );
  1.3526 +	} catch(e) {
  1.3527 +		document.body.removeChild(testEl);
  1.3528 +		throw (e);
  1.3529 +	}
  1.3530 +	document.body.removeChild(testEl);
  1.3531 +}, 'itemref referencing parent item');
  1.3532 +test(function () {
  1.3533 +	//foo has one property, bar
  1.3534 +	var testEl = makeEl('div',{id:'id1'},'<div itemprop="bar"></div><div itemscope itemref="id1" itemprop="foo"></div>');
  1.3535 +	assert_equals( testEl.lastChild.properties.length, 1, 'length' );
  1.3536 +	assert_equals( testEl.lastChild.properties[0], testEl.firstChild, 'properties[0]' );
  1.3537 +	assert_true( !testEl.lastChild.properties[1], 'properties[1]' );
  1.3538 +	assert_equals( testEl.lastChild.properties.namedItem('foo').length, 0, 'foo.length' );
  1.3539 +	assert_true( !testEl.lastChild.properties.namedItem('foo')[0], 'foo[0]' );
  1.3540 +	assert_equals( testEl.lastChild.properties.namedItem('bar').length, 1, 'bar.length' );
  1.3541 +	assert_equals( testEl.lastChild.properties.namedItem('bar')[0], testEl.firstChild, 'bar[0]' );
  1.3542 +	assert_true( !testEl.lastChild.properties.namedItem('bar')[1], 'bar[1]' );
  1.3543 +	assert_equals( testEl.lastChild.properties.names.length, 1, 'names.length' );
  1.3544 +	assert_equals( testEl.lastChild.properties.names[0], 'bar', 'names[0]' );
  1.3545 +	assert_true( !testEl.lastChild.properties.names[1], 'names[1]' );
  1.3546 +	document.body.appendChild(testEl);
  1.3547 +	try {
  1.3548 +		assert_equals( testEl.lastChild.properties.length, 1, 'length when appended to document' );
  1.3549 +		assert_equals( testEl.lastChild.properties[0], testEl.firstChild, 'properties[0] when appended to document' );
  1.3550 +		assert_true( !testEl.lastChild.properties[1], 'properties[1] when appended to document' );
  1.3551 +		assert_equals( testEl.lastChild.properties.namedItem('foo').length, 0, 'foo.length when appended to document' );
  1.3552 +		assert_true( !testEl.lastChild.properties.namedItem('foo')[0], 'foo[0] when appended to document' );
  1.3553 +		assert_equals( testEl.lastChild.properties.namedItem('bar').length, 1, 'bar.length when appended to document' );
  1.3554 +		assert_equals( testEl.lastChild.properties.namedItem('bar')[0], testEl.firstChild, 'bar[0] when appended to document' );
  1.3555 +		assert_true( !testEl.lastChild.properties.namedItem('bar')[1], 'bar[1] when appended to document' );
  1.3556 +		assert_equals( testEl.lastChild.properties.names.length, 1, 'names.length when appended to document' );
  1.3557 +		assert_equals( testEl.lastChild.properties.names[0], 'bar', 'names[0] when appended to document' );
  1.3558 +		assert_true( !testEl.lastChild.properties.names[1], 'names[1] when appended to document' );
  1.3559 +	} catch(e) {
  1.3560 +		document.body.removeChild(testEl);
  1.3561 +		throw (e);
  1.3562 +	}
  1.3563 +	document.body.removeChild(testEl);
  1.3564 +}, 'itemref referencing parent without itemscope');
  1.3565 +test(function () {
  1.3566 +	var testDiv = makeEl('div', {itemprop:'bar', id:'foo'}, '');
  1.3567 +	var testSpan = makeEl('span', {itemscope:'itemscope', itemref: 'foo', id: 'foo'}, '');
  1.3568 +	document.body.appendChild(testDiv);
  1.3569 +	document.body.appendChild(testSpan);
  1.3570 +	assert_equals(testSpan.properties.length, 1, 'has one property');
  1.3571 +	assert_equals(testSpan.properties[0], testDiv, 'has first property');
  1.3572 +	assert_equals(testSpan.properties.item(0), testDiv, 'has first property');
  1.3573 +	assert_equals(testSpan.properties.namedItem('bar').length, 1, 'has 1 foo property');
  1.3574 +	assert_equals(testSpan.properties.namedItem('bar').item(0), testDiv, 'div is foo property');
  1.3575 +	assert_equals(testSpan.properties.names.length, 1, 'only has one property');
  1.3576 +	document.body.removeChild(testDiv);
  1.3577 +	document.body.removeChild(testSpan);
  1.3578 +}, 'itemref referencing element with same id');
  1.3579 +test(function () {
  1.3580 +	//Root has three properties, foo, bar and baz
  1.3581 +	//Foo has two properties, bar and baz
  1.3582 +	var testEl = makeEl('div',{itemscope:'itemscope',itemref:'id1'},'<div itemscope itemprop="foo"><div itemprop="bar" id="id1"><div itemprop="baz"></div></div></div>');
  1.3583 +	assert_equals( testEl.properties.length, 3, 'outer length' );
  1.3584 +	assert_equals( testEl.properties[0], testEl.firstChild, 'outer properties[0]' );
  1.3585 +	assert_equals( testEl.properties[1], testEl.firstChild.firstChild, 'outer properties[1]' );
  1.3586 +	assert_equals( testEl.properties[2], testEl.firstChild.firstChild.firstChild, 'outer properties[2]' );
  1.3587 +	assert_true( !testEl.properties[3], 'outer properties[3]' );
  1.3588 +	assert_equals( testEl.properties.namedItem('foo').length, 1, 'outer foo.length' );
  1.3589 +	assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'outer foo[0]' );
  1.3590 +	assert_true( !testEl.properties.namedItem('foo')[1], 'outer foo[1]' );
  1.3591 +	assert_equals( testEl.properties.namedItem('bar').length, 1, 'outer bar.length' );
  1.3592 +	assert_equals( testEl.properties.namedItem('bar')[0], testEl.firstChild.firstChild, 'outer bar[0]' );
  1.3593 +	assert_true( !testEl.properties.namedItem('bar')[1], 'outer bar[1]' );
  1.3594 +	assert_equals( testEl.properties.namedItem('baz').length, 1, 'outer baz.length' );
  1.3595 +	assert_equals( testEl.properties.namedItem('baz')[0], testEl.firstChild.firstChild.firstChild, 'outer baz[0]' );
  1.3596 +	assert_true( !testEl.properties.namedItem('baz')[1], 'outer baz[1]' );
  1.3597 +	assert_equals( testEl.properties.names.length, 3, 'outer names.length' );
  1.3598 +	assert_equals( testEl.properties.names[0], 'foo', 'outer names[0]' );
  1.3599 +	assert_equals( testEl.properties.names[1], 'bar', 'outer names[1]' );
  1.3600 +	assert_equals( testEl.properties.names[2], 'baz', 'outer names[2]' );
  1.3601 +	assert_true( !testEl.properties.names[3], 'outer names[3]' );
  1.3602 +	assert_equals( testEl.firstChild.properties.length, 2, 'inner length' );
  1.3603 +	assert_equals( testEl.firstChild.properties[0], testEl.firstChild.firstChild, 'inner properties[0]' );
  1.3604 +	assert_equals( testEl.firstChild.properties[1], testEl.firstChild.firstChild.firstChild, 'inner properties[1]' );
  1.3605 +	assert_true( !testEl.firstChild.properties[2], 'inner properties[2]' );
  1.3606 +	assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'inner foo.length' );
  1.3607 +	assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'inner foo[0]' );
  1.3608 +	assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'inner bar.length' );
  1.3609 +	assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.firstChild.firstChild, 'inner bar[0]' );
  1.3610 +	assert_true( !testEl.firstChild.properties.namedItem('bar')[1], 'inner bar[1]' );
  1.3611 +	assert_equals( testEl.firstChild.properties.namedItem('baz').length, 1, 'inner baz.length' );
  1.3612 +	assert_equals( testEl.firstChild.properties.namedItem('baz')[0], testEl.firstChild.firstChild.firstChild, 'inner baz[0]' );
  1.3613 +	assert_true( !testEl.firstChild.properties.namedItem('baz')[1], 'inner baz[1]' );
  1.3614 +	assert_equals( testEl.firstChild.properties.names.length, 2, 'inner names.length' );
  1.3615 +	assert_equals( testEl.firstChild.properties.names[0], 'bar', 'inner names[0]' );
  1.3616 +	assert_equals( testEl.firstChild.properties.names[1], 'baz', 'inner names[1]' );
  1.3617 +	assert_true( !testEl.firstChild.properties.names[2], 'inner names[2]' );
  1.3618 +	document.body.appendChild(testEl);
  1.3619 +	try {
  1.3620 +		assert_equals( testEl.properties.length, 3, 'outer length when appended to document' );
  1.3621 +		assert_equals( testEl.properties[0], testEl.firstChild, 'outer properties[0] when appended to document' );
  1.3622 +		assert_equals( testEl.properties[1], testEl.firstChild.firstChild, 'outer properties[1] when appended to document' );
  1.3623 +		assert_equals( testEl.properties[2], testEl.firstChild.firstChild.firstChild, 'outer properties[2] when appended to document' );
  1.3624 +		assert_true( !testEl.properties[3], 'outer properties[3] when appended to document' );
  1.3625 +		assert_equals( testEl.properties.namedItem('foo').length, 1, 'outer foo.length when appended to document' );
  1.3626 +		assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'outer foo[0] when appended to document' );
  1.3627 +		assert_true( !testEl.properties.namedItem('foo')[1], 'outer foo[1] when appended to document' );
  1.3628 +		assert_equals( testEl.properties.namedItem('bar').length, 1, 'outer bar.length when appended to document' );
  1.3629 +		assert_equals( testEl.properties.namedItem('bar')[0], testEl.firstChild.firstChild, 'outer bar[0] when appended to document' );
  1.3630 +		assert_true( !testEl.properties.namedItem('bar')[1], 'outer bar[1] when appended to document' );
  1.3631 +		assert_equals( testEl.properties.namedItem('baz').length, 1, 'outer baz.length when appended to document' );
  1.3632 +		assert_equals( testEl.properties.namedItem('baz')[0], testEl.firstChild.firstChild.firstChild, 'outer baz[0] when appended to document' );
  1.3633 +		assert_true( !testEl.properties.namedItem('baz')[1], 'outer baz[1] when appended to document' );
  1.3634 +		assert_equals( testEl.properties.names.length, 3, 'outer names.length when appended to document' );
  1.3635 +		assert_equals( testEl.properties.names[0], 'foo', 'outer names[0] when appended to document' );
  1.3636 +		assert_equals( testEl.properties.names[1], 'bar', 'outer names[1] when appended to document' );
  1.3637 +		assert_equals( testEl.properties.names[2], 'baz', 'outer names[2] when appended to document' );
  1.3638 +		assert_true( !testEl.properties.names[3], 'outer names[3] when appended to document' );
  1.3639 +		assert_equals( testEl.firstChild.properties.length, 2, 'inner length when appended to document' );
  1.3640 +		assert_equals( testEl.firstChild.properties[0], testEl.firstChild.firstChild, 'inner properties[0] when appended to document' );
  1.3641 +		assert_equals( testEl.firstChild.properties[1], testEl.firstChild.firstChild.firstChild, 'inner properties[1] when appended to document' );
  1.3642 +		assert_true( !testEl.firstChild.properties[2], 'inner properties[2] when appended to document' );
  1.3643 +		assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'inner foo.length when appended to document' );
  1.3644 +		assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'inner foo[0] when appended to document' );
  1.3645 +		assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'inner bar.length when appended to document' );
  1.3646 +		assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.firstChild.firstChild, 'inner bar[0] when appended to document' );
  1.3647 +		assert_true( !testEl.firstChild.properties.namedItem('bar')[1], 'inner bar[1] when appended to document' );
  1.3648 +		assert_equals( testEl.firstChild.properties.namedItem('baz').length, 1, 'inner baz.length when appended to document' );
  1.3649 +		assert_equals( testEl.firstChild.properties.namedItem('baz')[0], testEl.firstChild.firstChild.firstChild, 'inner baz[0] when appended to document' );
  1.3650 +		assert_true( !testEl.firstChild.properties.namedItem('baz')[1], 'inner baz[1] when appended to document' );
  1.3651 +		assert_equals( testEl.firstChild.properties.names.length, 2, 'inner names.length when appended to document' );
  1.3652 +		assert_equals( testEl.firstChild.properties.names[0], 'bar', 'inner names[0] when appended to document' );
  1.3653 +		assert_equals( testEl.firstChild.properties.names[1], 'baz', 'inner names[1] when appended to document' );
  1.3654 +		assert_true( !testEl.firstChild.properties.names[2], 'inner names[2] when appended to document' );
  1.3655 +	} catch(e) {
  1.3656 +		document.body.removeChild(testEl);
  1.3657 +		throw (e);
  1.3658 +	}
  1.3659 +	document.body.removeChild(testEl);
  1.3660 +}, 'itemref pointing to child of nested itemscope');
  1.3661 +
  1.3662 +		</script>
  1.3663 +	</body>
  1.3664 +</html>

mercurial