forked from mirrors/gecko-dev
		
	Bug 1356225 - Update web-platform-tests to revision d519fe9011da7cfce7949f7ed826e9759dc5c532, a=testonly
MozReview-Commit-ID: GmGgeZxHy0j --HG-- rename : testing/web-platform/tests/content-security-policy/media-src/media-src-7_1_2.html.sub.headers => testing/web-platform/tests/content-security-policy/media-src/media-src-7_1_2.sub.html.sub.headers rename : testing/web-platform/tests/content-security-policy/media-src/media-src-7_2_2.html.sub.headers => testing/web-platform/tests/content-security-policy/media-src/media-src-7_2_2.sub.html.sub.headers rename : testing/web-platform/tests/content-security-policy/media-src/media-src-7_3_2.html.sub.headers => testing/web-platform/tests/content-security-policy/media-src/media-src-7_3_2.sub.html.sub.headers rename : testing/web-platform/tests/html/browsers/windows/nested-browsing-contexts/test.html => testing/web-platform/tests/html/browsers/windows/nested-browsing-contexts/resources/frameElement-nested-frame.html rename : testing/web-platform/tests/html/browsers/windows/nested-browsing-contexts/testcase3.html => testing/web-platform/tests/html/browsers/windows/nested-browsing-contexts/resources/frameElement-window-post.html rename : testing/web-platform/tests/presentation-api/controlling-ua/PresentationAvailability_onchange-manual.html => testing/web-platform/tests/presentation-api/controlling-ua/PresentationAvailability_onchange-manual.https.html rename : testing/web-platform/tests/presentation-api/controlling-ua/PresentationConnection_onmessage-manual.html => testing/web-platform/tests/presentation-api/controlling-ua/PresentationConnection_onmessage-manual.https.html rename : testing/web-platform/tests/presentation-api/controlling-ua/PresentationConnection_send-manual.html => testing/web-platform/tests/presentation-api/controlling-ua/PresentationConnection_send-manual.https.html rename : testing/web-platform/tests/presentation-api/controlling-ua/PresentationRequest_error.html => testing/web-platform/tests/presentation-api/controlling-ua/PresentationRequest_error.https.html rename : testing/web-platform/tests/presentation-api/controlling-ua/PresentationRequest_onconnectionavailable-manual.html => testing/web-platform/tests/presentation-api/controlling-ua/PresentationRequest_onconnectionavailable-manual.https.html rename : testing/web-platform/tests/presentation-api/controlling-ua/PresentationRequest_sandboxing_error.html => testing/web-platform/tests/presentation-api/controlling-ua/PresentationRequest_sandboxing_error.https.html rename : testing/web-platform/tests/presentation-api/controlling-ua/PresentationRequest_sandboxing_success.html => testing/web-platform/tests/presentation-api/controlling-ua/PresentationRequest_sandboxing_success.https.html rename : testing/web-platform/tests/presentation-api/controlling-ua/PresentationRequest_success.html => testing/web-platform/tests/presentation-api/controlling-ua/PresentationRequest_success.https.html rename : testing/web-platform/tests/presentation-api/controlling-ua/defaultRequest_success-manual.html => testing/web-platform/tests/presentation-api/controlling-ua/defaultRequest_success-manual.https.html rename : testing/web-platform/tests/presentation-api/controlling-ua/getAvailability.html => testing/web-platform/tests/presentation-api/controlling-ua/getAvailability.https.html rename : testing/web-platform/tests/presentation-api/controlling-ua/getAvailability_sandboxing_success.html => testing/web-platform/tests/presentation-api/controlling-ua/getAvailability_sandboxing_success.https.html rename : testing/web-platform/tests/presentation-api/controlling-ua/reconnectToPresentation_notfound_error.html => testing/web-platform/tests/presentation-api/controlling-ua/reconnectToPresentation_notfound_error.https.html rename : testing/web-platform/tests/presentation-api/controlling-ua/reconnectToPresentation_sandboxing_success.html => testing/web-platform/tests/presentation-api/controlling-ua/reconnectToPresentation_sandboxing_success.https.html rename : testing/web-platform/tests/presentation-api/controlling-ua/reconnectToPresentation_success-manual.html => testing/web-platform/tests/presentation-api/controlling-ua/reconnectToPresentation_success-manual.https.html rename : testing/web-platform/tests/presentation-api/controlling-ua/startNewPresentation_displaynotallowed-manual.html => testing/web-platform/tests/presentation-api/controlling-ua/startNewPresentation_displaynotallowed-manual.https.html rename : testing/web-platform/tests/presentation-api/controlling-ua/startNewPresentation_displaynotfound-manual.html => testing/web-platform/tests/presentation-api/controlling-ua/startNewPresentation_displaynotfound-manual.https.html rename : testing/web-platform/tests/presentation-api/controlling-ua/startNewPresentation_error.html => testing/web-platform/tests/presentation-api/controlling-ua/startNewPresentation_error.https.html rename : testing/web-platform/tests/presentation-api/controlling-ua/startNewPresentation_sandboxing_success-manual.html => testing/web-platform/tests/presentation-api/controlling-ua/startNewPresentation_sandboxing_success-manual.https.html rename : testing/web-platform/tests/presentation-api/controlling-ua/startNewPresentation_success-manual.html => testing/web-platform/tests/presentation-api/controlling-ua/startNewPresentation_success-manual.https.html rename : testing/web-platform/tests/presentation-api/controlling-ua/startNewPresentation_unsettledpromise-manual.html => testing/web-platform/tests/presentation-api/controlling-ua/startNewPresentation_unsettledpromise-manual.https.html rename : testing/web-platform/tests/presentation-api/receiving-ua/idlharness-manual.html => testing/web-platform/tests/presentation-api/receiving-ua/idlharness-manual.https.html rename : testing/web-platform/tests/presentation-api/receiving-ua/support/idlharness_receiving-ua.html => testing/web-platform/tests/presentation-api/receiving-ua/support/idlharness_receiving-ua.https.html rename : testing/web-platform/tests/webdriver/util/http_request.py => testing/web-platform/tests/webdriver/support/http_request.py
This commit is contained in:
		
							parent
							
								
									beabf923ac
								
							
						
					
					
						commit
						1325009ca4
					
				
					 924 changed files with 33612 additions and 6217 deletions
				
			
		
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,2 +1,2 @@ | ||||||
| local: 5dc5249408ecc0003f0c68d32a8e782dec23fd36 | local: 0000000000000000000000000000000000000000 | ||||||
| upstream: aef9b4f327326fd32420281f9bc1ca9b60d553b3 | upstream: 8181d7f09ee35cb521452bb727a48a1667901afd | ||||||
|  |  | ||||||
							
								
								
									
										8
									
								
								testing/web-platform/tests/.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								testing/web-platform/tests/.gitmodules
									
									
									
									
										vendored
									
									
								
							|  | @ -5,4 +5,10 @@ | ||||||
| [submodule "tools"] | [submodule "tools"] | ||||||
| 	path = tools | 	path = tools | ||||||
| 	url = https://github.com/w3c/wpt-tools.git | 	url = https://github.com/w3c/wpt-tools.git | ||||||
| 	ignore = dirty | 	ignore = dirty | ||||||
|  | [submodule "css/tools/apiclient"] | ||||||
|  | 	path = css/tools/apiclient | ||||||
|  | 	url = https://github.com/w3c/csswg-apiclient.git | ||||||
|  | [submodule "css/tools/w3ctestlib"] | ||||||
|  | 	path = css/tools/w3ctestlib | ||||||
|  | 	url = https://github.com/w3c/csswg-w3ctestlib.git | ||||||
|  |  | ||||||
|  | @ -16,16 +16,18 @@ before_install: | ||||||
| install: | install: | ||||||
|   - pip install -U setuptools |   - pip install -U setuptools | ||||||
|   - pip install -U requests |   - pip install -U requests | ||||||
|  | env:  # required at the top-level for allow_failures to work below | ||||||
| matrix: | matrix: | ||||||
|   include: |   include: | ||||||
|     - os: linux |     - os: linux | ||||||
|       python: "2.7" |       python: "2.7" | ||||||
|       env: |       env: SCRIPT=ci_lint.sh | ||||||
|         - SCRIPT=ci_lint.sh |  | ||||||
|     - os: linux |     - os: linux | ||||||
|       python: "2.7" |       python: "2.7" | ||||||
|       env: |       env: SCRIPT=ci_built_diff.sh | ||||||
|         - SCRIPT=ci_built_diff.sh |     - os: linux | ||||||
|  |       python: "2.7" | ||||||
|  |       env: SCRIPT=css/build-css-testsuites.sh | ||||||
|     - os: linux |     - os: linux | ||||||
|       python: "2.7" |       python: "2.7" | ||||||
|       addons: |       addons: | ||||||
|  | @ -34,8 +36,7 @@ matrix: | ||||||
|             - libnss3-tools |             - libnss3-tools | ||||||
|       env: |       env: | ||||||
|         - secure: "YTSXPwI0DyCA1GhYrLT9KMEV6b7QQKuEeaQgeFDP38OTzJ1+cIj3CC4SRNqbnJ/6SJwPGcdqSxLuV8m4e5HFFnyCcQnJe6h8EMsTehZ7W3j/fP9UYrJqYqvGpe3Vj3xblO5pwBYmq7sg3jAmmuCgAgOW6VGf7cRMucrsmFeo7VM=" |         - secure: "YTSXPwI0DyCA1GhYrLT9KMEV6b7QQKuEeaQgeFDP38OTzJ1+cIj3CC4SRNqbnJ/6SJwPGcdqSxLuV8m4e5HFFnyCcQnJe6h8EMsTehZ7W3j/fP9UYrJqYqvGpe3Vj3xblO5pwBYmq7sg3jAmmuCgAgOW6VGf7cRMucrsmFeo7VM=" | ||||||
|         - SCRIPT=ci_stability.sh |         - SCRIPT=ci_stability.sh PRODUCT=firefox:nightly | ||||||
|         - PRODUCT=firefox:nightly |  | ||||||
|     - os: linux |     - os: linux | ||||||
|       sudo: required |       sudo: required | ||||||
|       python: "2.7" |       python: "2.7" | ||||||
|  | @ -46,8 +47,11 @@ matrix: | ||||||
|             - fonts-liberation |             - fonts-liberation | ||||||
|       env: |       env: | ||||||
|         - secure: "YTSXPwI0DyCA1GhYrLT9KMEV6b7QQKuEeaQgeFDP38OTzJ1+cIj3CC4SRNqbnJ/6SJwPGcdqSxLuV8m4e5HFFnyCcQnJe6h8EMsTehZ7W3j/fP9UYrJqYqvGpe3Vj3xblO5pwBYmq7sg3jAmmuCgAgOW6VGf7cRMucrsmFeo7VM=" |         - secure: "YTSXPwI0DyCA1GhYrLT9KMEV6b7QQKuEeaQgeFDP38OTzJ1+cIj3CC4SRNqbnJ/6SJwPGcdqSxLuV8m4e5HFFnyCcQnJe6h8EMsTehZ7W3j/fP9UYrJqYqvGpe3Vj3xblO5pwBYmq7sg3jAmmuCgAgOW6VGf7cRMucrsmFeo7VM=" | ||||||
|         - SCRIPT=ci_stability.sh |         - SCRIPT=ci_stability.sh PRODUCT=chrome:unstable | ||||||
|         - PRODUCT=chrome:unstable |   exclude: | ||||||
|  |     - env:  # exclude empty env from the top-level above | ||||||
|  |   allow_failures: | ||||||
|  |     - env: SCRIPT=css/build-css-testsuites.sh | ||||||
| script: | script: | ||||||
|   - bash $SCRIPT |   - bash $SCRIPT | ||||||
| cache: | cache: | ||||||
|  |  | ||||||
							
								
								
									
										58
									
								
								testing/web-platform/tests/2dcontext/imagebitmap/common.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								testing/web-platform/tests/2dcontext/imagebitmap/common.js
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,58 @@ | ||||||
|  | function testCanvasDisplayingPattern(canvas) | ||||||
|  | { | ||||||
|  |     var tolerance = 5; // for creating ImageBitmap from a video, the tolerance needs to be high
 | ||||||
|  |     _assertPixelApprox(canvas, 5,5, 255,0,0,255, "5,5", "255,0,0,255", tolerance); | ||||||
|  |     _assertPixelApprox(canvas, 15,5, 0,255,0,255, "15,5", "0,255,0,255", tolerance); | ||||||
|  |     _assertPixelApprox(canvas, 5,15, 0,0,255,255, "5,15", "0,0,255,255", tolerance); | ||||||
|  |     _assertPixelApprox(canvas, 15,15, 0,0,0,255, "15,15", "0,0,0,255", tolerance); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function testDrawImageBitmap(source) | ||||||
|  | { | ||||||
|  |     var canvas = document.createElement("canvas"); | ||||||
|  |     canvas.width = 20; | ||||||
|  |     canvas.height = 20; | ||||||
|  |     var ctx = canvas.getContext("2d"); | ||||||
|  |     ctx.clearRect(0, 0, canvas.width, canvas.height); | ||||||
|  |     return createImageBitmap(source).then(imageBitmap => { | ||||||
|  |         ctx.drawImage(imageBitmap, 0, 0); | ||||||
|  |         testCanvasDisplayingPattern(canvas); | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function initializeTestCanvas(testCanvas) | ||||||
|  | { | ||||||
|  |     testCanvas.width = 20; | ||||||
|  |     testCanvas.height = 20; | ||||||
|  |     var testCtx = testCanvas.getContext("2d"); | ||||||
|  |     testCtx.fillStyle = "rgb(255, 0, 0)"; | ||||||
|  |     testCtx.fillRect(0, 0, 10, 10); | ||||||
|  |     testCtx.fillStyle = "rgb(0, 255, 0)"; | ||||||
|  |     testCtx.fillRect(10, 0, 10, 10); | ||||||
|  |     testCtx.fillStyle = "rgb(0, 0, 255)"; | ||||||
|  |     testCtx.fillRect(0, 10, 10, 10); | ||||||
|  |     testCtx.fillStyle = "rgb(0, 0, 0)"; | ||||||
|  |     testCtx.fillRect(10, 10, 10, 10); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function initializeImageData(imgData, width, height) | ||||||
|  | { | ||||||
|  |     for (var i = 0; i < width * height * 4; i+=4) { | ||||||
|  |         imgData.data[i] = 0; | ||||||
|  |         imgData.data[i + 1] = 0; | ||||||
|  |         imgData.data[i + 2] = 0; | ||||||
|  |         imgData.data[i + 3] = 255; //alpha channel: 255
 | ||||||
|  |     } | ||||||
|  |     var halfWidth = width/2; | ||||||
|  |     var halfHeight = height/2; | ||||||
|  |     // initialize to R, G, B, Black, with each one 10*10 pixels
 | ||||||
|  |     for (var i = 0; i < halfHeight; i++) | ||||||
|  |         for (var j = 0; j < halfWidth; j++) | ||||||
|  |             imgData.data[i * width * 4 + j * 4] = 255; | ||||||
|  |     for (var i = 0; i < halfHeight; i++) | ||||||
|  |         for (var j = halfWidth; j < width; j++) | ||||||
|  |             imgData.data[i * width * 4 + j * 4 + 1] = 255; | ||||||
|  |     for (var i = halfHeight; i < height; i++) | ||||||
|  |         for (var j = 0; j < halfWidth; j++) | ||||||
|  |             imgData.data[i * width * 4 + j * 4 + 2] = 255; | ||||||
|  | } | ||||||
|  | @ -0,0 +1,75 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <html> | ||||||
|  | <title>createImageBitmap + drawImage test</title> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | <script src="/common/canvas-tests.js"></script> | ||||||
|  | <script src="common.js"></script> | ||||||
|  | <link rel="stylesheet" href="/common/canvas-tests.css"> | ||||||
|  | <body> | ||||||
|  | <script> | ||||||
|  | (function() { | ||||||
|  |     promise_test(function() { | ||||||
|  |         return new Promise(function(resolve, reject) { | ||||||
|  |             var img = new Image(); | ||||||
|  |             img.onload = function() { resolve(img); }; | ||||||
|  |             img.src = "/images/pattern.png"; | ||||||
|  |         }).then(function(img) { | ||||||
|  |             return testDrawImageBitmap(img); | ||||||
|  |         }); | ||||||
|  |     }, "createImageBitmap from a HTMLImageElement, and drawImage on the created ImageBitmap"); | ||||||
|  | 
 | ||||||
|  |     promise_test(function() { | ||||||
|  |         return new Promise(function(resolve, reject) { | ||||||
|  |             var xhr = new XMLHttpRequest(); | ||||||
|  |             xhr.open("GET", '/images/pattern.png'); | ||||||
|  |             xhr.responseType = 'blob'; | ||||||
|  |             xhr.send(); | ||||||
|  |             xhr.onload = function() { | ||||||
|  |                 blob = xhr.response; | ||||||
|  |                 resolve(blob); | ||||||
|  |             }; | ||||||
|  |         }).then(function(blob) { | ||||||
|  |             return testDrawImageBitmap(blob); | ||||||
|  |         }); | ||||||
|  |     }, "createImageBitmap from a Blob, and drawImage on the created ImageBitmap"); | ||||||
|  | 
 | ||||||
|  |     promise_test(function() { | ||||||
|  |         var testCanvas = document.createElement("canvas"); | ||||||
|  |         initializeTestCanvas(testCanvas); | ||||||
|  |         testDrawImageBitmap(testCanvas); | ||||||
|  |     }, "createImageBitmap from a HTMLCanvasElement, and drawImage on the created ImageBitmap"); | ||||||
|  | 
 | ||||||
|  |     promise_test(function() { | ||||||
|  |         var testCanvas = document.createElement("canvas"); | ||||||
|  |         initializeTestCanvas(testCanvas); | ||||||
|  |         return new Promise(function(resolve, reject) { | ||||||
|  |             createImageBitmap(testCanvas).then(function(bitmap) { | ||||||
|  |                 resolve(bitmap); | ||||||
|  |             }); | ||||||
|  |         }).then(function(bitmap) { | ||||||
|  |             return testDrawImageBitmap(bitmap); | ||||||
|  |         }); | ||||||
|  |     }, "createImageBitmap from an ImageBitmap, and drawImage on the created ImageBitmap"); | ||||||
|  | 
 | ||||||
|  |     promise_test(function() { | ||||||
|  |         var imgData = new ImageData(20, 20); | ||||||
|  |         initializeImageData(imgData, 20, 20); | ||||||
|  |         return testDrawImageBitmap(imgData); | ||||||
|  |     }, "createImageBitmap from an ImageData, and drawImage on the created ImageBitmap"); | ||||||
|  | 
 | ||||||
|  |     promise_test(function() { | ||||||
|  |         return new Promise(function(resolve, reject) { | ||||||
|  |             var video = document.createElement("video"); | ||||||
|  |             video.oncanplaythrough = function() { | ||||||
|  |                 resolve(video); | ||||||
|  |             }; | ||||||
|  |             video.src = "/images/pattern.ogv"; | ||||||
|  |         }).then(function(video) { | ||||||
|  |             return testDrawImageBitmap(video); | ||||||
|  |         }); | ||||||
|  |     }, "createImageBitmap from a HTMLVideoElement, and drawImage on the created ImageBitmap"); | ||||||
|  | })(); | ||||||
|  | </script> | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -1,14 +1,14 @@ | ||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
| <!-- DO NOT EDIT! This test has been generated by tools/gentest.py. --> | <!-- DO NOT EDIT! This test has been generated by tools/gentest.py. --> | ||||||
| <title>Canvas test: 2d.imageData.create2.round</title> | <title>Canvas test: 2d.imageData.create2.double</title> | ||||||
| <script src="/resources/testharness.js"></script> | <script src="/resources/testharness.js"></script> | ||||||
| <script src="/resources/testharnessreport.js"></script> | <script src="/resources/testharnessreport.js"></script> | ||||||
| <script src="/common/canvas-tests.js"></script> | <script src="/common/canvas-tests.js"></script> | ||||||
| <link rel="stylesheet" href="/common/canvas-tests.css"> | <link rel="stylesheet" href="/common/canvas-tests.css"> | ||||||
| <body class="show_output"> | <body class="show_output"> | ||||||
| 
 | 
 | ||||||
| <h1>2d.imageData.create2.round</h1> | <h1>2d.imageData.create2.double</h1> | ||||||
| <p class="desc">createImageData(w, h) is rounded the same as getImageData(0, 0, w, h)</p> | <p class="desc">createImageData(w, h) double is converted to long</p> | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| <p class="output">Actual output:</p> | <p class="output">Actual output:</p> | ||||||
|  | @ -16,13 +16,15 @@ | ||||||
| 
 | 
 | ||||||
| <ul id="d"></ul> | <ul id="d"></ul> | ||||||
| <script> | <script> | ||||||
| var t = async_test("createImageData(w, h) is rounded the same as getImageData(0, 0, w, h)"); | var t = async_test("createImageData(w, h) double is converted to long"); | ||||||
| _addTest(function(canvas, ctx) { | _addTest(function(canvas, ctx) { | ||||||
| 
 | 
 | ||||||
| var imgdata1 = ctx.createImageData(10.01, 10.99); | var imgdata1 = ctx.createImageData(10.01, 10.99); | ||||||
| var imgdata2 = ctx.getImageData(0, 0, 10.01, 10.99); | var imgdata2 = ctx.createImageData(-10.01, -10.99); | ||||||
| _assertSame(imgdata1.width, imgdata2.width, "imgdata1.width", "imgdata2.width"); | _assertSame(imgdata1.width, 10, "imgdata1.width", "10"); | ||||||
| _assertSame(imgdata1.height, imgdata2.height, "imgdata1.height", "imgdata2.height"); | _assertSame(imgdata1.height, 10, "imgdata1.height", "10"); | ||||||
|  | _assertSame(imgdata2.width, 10, "imgdata2.width", "10"); | ||||||
|  | _assertSame(imgdata2.height, 10, "imgdata2.height", "10"); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| }); | }); | ||||||
|  | @ -1,35 +0,0 @@ | ||||||
| <!DOCTYPE html> |  | ||||||
| <!-- DO NOT EDIT! This test has been generated by tools/gentest.py. --> |  | ||||||
| <title>Canvas test: 2d.imageData.create2.tiny</title> |  | ||||||
| <script src="/resources/testharness.js"></script> |  | ||||||
| <script src="/resources/testharnessreport.js"></script> |  | ||||||
| <script src="/common/canvas-tests.js"></script> |  | ||||||
| <link rel="stylesheet" href="/common/canvas-tests.css"> |  | ||||||
| <body class="show_output"> |  | ||||||
| 
 |  | ||||||
| <h1>2d.imageData.create2.tiny</h1> |  | ||||||
| <p class="desc">createImageData(sw, sh) works for sizes smaller than one pixel</p> |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| <p class="output">Actual output:</p> |  | ||||||
| <canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas> |  | ||||||
| 
 |  | ||||||
| <ul id="d"></ul> |  | ||||||
| <script> |  | ||||||
| var t = async_test("createImageData(sw, sh) works for sizes smaller than one pixel"); |  | ||||||
| _addTest(function(canvas, ctx) { |  | ||||||
| 
 |  | ||||||
| var imgdata = ctx.createImageData(0.0001, 0.0001); |  | ||||||
| _assertSame(imgdata.data.length, imgdata.width*imgdata.height*4, "imgdata.data.length", "imgdata.width*imgdata.height*4"); |  | ||||||
| _assertSame(imgdata.width, 1, "imgdata.width", "1"); |  | ||||||
| _assertSame(imgdata.height, 1, "imgdata.height", "1"); |  | ||||||
| var isTransparentBlack = true; |  | ||||||
| for (var i = 0; i < imgdata.data.length; ++i) |  | ||||||
|     if (imgdata.data[i] !== 0) |  | ||||||
|         isTransparentBlack = false; |  | ||||||
| _assert(isTransparentBlack, "isTransparentBlack"); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| }); |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
|  | @ -22,6 +22,8 @@ _addTest(function(canvas, ctx) { | ||||||
| assert_throws("INDEX_SIZE_ERR", function() { ctx.createImageData(10, 0); }); | assert_throws("INDEX_SIZE_ERR", function() { ctx.createImageData(10, 0); }); | ||||||
| assert_throws("INDEX_SIZE_ERR", function() { ctx.createImageData(0, 10); }); | assert_throws("INDEX_SIZE_ERR", function() { ctx.createImageData(0, 10); }); | ||||||
| assert_throws("INDEX_SIZE_ERR", function() { ctx.createImageData(0, 0); }); | assert_throws("INDEX_SIZE_ERR", function() { ctx.createImageData(0, 0); }); | ||||||
|  | assert_throws("INDEX_SIZE_ERR", function() { ctx.createImageData(0.99, 10); }); | ||||||
|  | assert_throws("INDEX_SIZE_ERR", function() { ctx.createImageData(10, 0.1); }); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | @ -0,0 +1,32 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <!-- DO NOT EDIT! This test has been generated by tools/gentest.py. --> | ||||||
|  | <title>Canvas test: 2d.imageData.get.double</title> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | <script src="/common/canvas-tests.js"></script> | ||||||
|  | <link rel="stylesheet" href="/common/canvas-tests.css"> | ||||||
|  | <body class="show_output"> | ||||||
|  | 
 | ||||||
|  | <h1>2d.imageData.get.double</h1> | ||||||
|  | <p class="desc">createImageData(w, h) double is converted to long</p> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | <p class="output">Actual output:</p> | ||||||
|  | <canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas> | ||||||
|  | 
 | ||||||
|  | <ul id="d"></ul> | ||||||
|  | <script> | ||||||
|  | var t = async_test("createImageData(w, h) double is converted to long"); | ||||||
|  | _addTest(function(canvas, ctx) { | ||||||
|  | 
 | ||||||
|  | var imgdata1 = ctx.getImageData(0, 0, 10.01, 10.99); | ||||||
|  | var imgdata2 = ctx.getImageData(0, 0, -10.01, -10.99); | ||||||
|  | _assertSame(imgdata1.width, 10, "imgdata1.width", "10"); | ||||||
|  | _assertSame(imgdata1.height, 10, "imgdata1.height", "10"); | ||||||
|  | _assertSame(imgdata2.width, 10, "imgdata2.width", "10"); | ||||||
|  | _assertSame(imgdata2.height, 10, "imgdata2.height", "10"); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | @ -22,6 +22,10 @@ _addTest(function(canvas, ctx) { | ||||||
| assert_throws("INDEX_SIZE_ERR", function() { ctx.getImageData(1, 1, 10, 0); }); | assert_throws("INDEX_SIZE_ERR", function() { ctx.getImageData(1, 1, 10, 0); }); | ||||||
| assert_throws("INDEX_SIZE_ERR", function() { ctx.getImageData(1, 1, 0, 10); }); | assert_throws("INDEX_SIZE_ERR", function() { ctx.getImageData(1, 1, 0, 10); }); | ||||||
| assert_throws("INDEX_SIZE_ERR", function() { ctx.getImageData(1, 1, 0, 0); }); | assert_throws("INDEX_SIZE_ERR", function() { ctx.getImageData(1, 1, 0, 0); }); | ||||||
|  | assert_throws("INDEX_SIZE_ERR", function() { ctx.getImageData(1, 1, 0.1, 10); }); | ||||||
|  | assert_throws("INDEX_SIZE_ERR", function() { ctx.getImageData(1, 1, 10, 0.99); }); | ||||||
|  | assert_throws("INDEX_SIZE_ERR", function() { ctx.getImageData(1, 1, -0.1, 10); }); | ||||||
|  | assert_throws("INDEX_SIZE_ERR", function() { ctx.getImageData(1, 1, 10, -0.99); }); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | @ -0,0 +1,34 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <!-- DO NOT EDIT! This test has been generated by tools/gentest.py. --> | ||||||
|  | <title>Canvas test: 2d.imageData.object.ctor.array.bounds</title> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | <script src="/common/canvas-tests.js"></script> | ||||||
|  | <link rel="stylesheet" href="/common/canvas-tests.css"> | ||||||
|  | <body class="show_output"> | ||||||
|  | 
 | ||||||
|  | <h1>2d.imageData.object.ctor.array.bounds</h1> | ||||||
|  | <p class="desc">ImageData has a usable constructor</p> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | <p class="output">Actual output:</p> | ||||||
|  | <canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas> | ||||||
|  | 
 | ||||||
|  | <ul id="d"></ul> | ||||||
|  | <script> | ||||||
|  | var t = async_test("ImageData has a usable constructor"); | ||||||
|  | _addTest(function(canvas, ctx) { | ||||||
|  | 
 | ||||||
|  | _assertDifferent(window.ImageData, undefined, "window.ImageData", "undefined"); | ||||||
|  | 
 | ||||||
|  | assert_throws("INVALID_STATE_ERR", function() { new ImageData(new Uint8ClampedArray(0), 1); }); | ||||||
|  | assert_throws("INVALID_STATE_ERR", function() { new ImageData(new Uint8ClampedArray(3), 1); }); | ||||||
|  | assert_throws("INDEX_SIZE_ERR", function() { new ImageData(new Uint8ClampedArray(4), 0); }); | ||||||
|  | assert_throws("INDEX_SIZE_ERR", function() { new ImageData(new Uint8ClampedArray(4), 1, 2); }); | ||||||
|  | assert_throws(new TypeError(), function() { new ImageData(new Uint8Array(8), 1, 2); }); | ||||||
|  | assert_throws(new TypeError(), function() { new ImageData(new Int8Array(8), 1, 2); }); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | @ -1,14 +1,14 @@ | ||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
| <!-- DO NOT EDIT! This test has been generated by tools/gentest.py. --> | <!-- DO NOT EDIT! This test has been generated by tools/gentest.py. --> | ||||||
| <title>Canvas test: 2d.imageData.get.tiny</title> | <title>Canvas test: 2d.imageData.object.ctor.array</title> | ||||||
| <script src="/resources/testharness.js"></script> | <script src="/resources/testharness.js"></script> | ||||||
| <script src="/resources/testharnessreport.js"></script> | <script src="/resources/testharnessreport.js"></script> | ||||||
| <script src="/common/canvas-tests.js"></script> | <script src="/common/canvas-tests.js"></script> | ||||||
| <link rel="stylesheet" href="/common/canvas-tests.css"> | <link rel="stylesheet" href="/common/canvas-tests.css"> | ||||||
| <body class="show_output"> | <body class="show_output"> | ||||||
| 
 | 
 | ||||||
| <h1>2d.imageData.get.tiny</h1> | <h1>2d.imageData.object.ctor.array</h1> | ||||||
| <p class="desc">getImageData() works for sizes smaller than one pixel</p> | <p class="desc">ImageData has a usable constructor</p> | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| <p class="output">Actual output:</p> | <p class="output">Actual output:</p> | ||||||
|  | @ -16,13 +16,16 @@ | ||||||
| 
 | 
 | ||||||
| <ul id="d"></ul> | <ul id="d"></ul> | ||||||
| <script> | <script> | ||||||
| var t = async_test("getImageData() works for sizes smaller than one pixel"); | var t = async_test("ImageData has a usable constructor"); | ||||||
| _addTest(function(canvas, ctx) { | _addTest(function(canvas, ctx) { | ||||||
| 
 | 
 | ||||||
| var imgdata = ctx.getImageData(0, 0, 0.0001, 0.0001); | _assertDifferent(window.ImageData, undefined, "window.ImageData", "undefined"); | ||||||
| _assertSame(imgdata.data.length, imgdata.width*imgdata.height*4, "imgdata.data.length", "imgdata.width*imgdata.height*4"); | 
 | ||||||
|  | var array = new Uint8ClampedArray(8); | ||||||
|  | var imgdata = new window.ImageData(array, 1, 2); | ||||||
| _assertSame(imgdata.width, 1, "imgdata.width", "1"); | _assertSame(imgdata.width, 1, "imgdata.width", "1"); | ||||||
| _assertSame(imgdata.height, 1, "imgdata.height", "1"); | _assertSame(imgdata.height, 2, "imgdata.height", "2"); | ||||||
|  | _assertSame(imgdata.data, array, "imgdata.data", "array"); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| }); | }); | ||||||
|  | @ -1,14 +1,14 @@ | ||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
| <!-- DO NOT EDIT! This test has been generated by tools/gentest.py. --> | <!-- DO NOT EDIT! This test has been generated by tools/gentest.py. --> | ||||||
| <title>Canvas test: 2d.imageData.object.ctor</title> | <title>Canvas test: 2d.imageData.object.ctor.size.bounds</title> | ||||||
| <script src="/resources/testharness.js"></script> | <script src="/resources/testharness.js"></script> | ||||||
| <script src="/resources/testharnessreport.js"></script> | <script src="/resources/testharnessreport.js"></script> | ||||||
| <script src="/common/canvas-tests.js"></script> | <script src="/common/canvas-tests.js"></script> | ||||||
| <link rel="stylesheet" href="/common/canvas-tests.css"> | <link rel="stylesheet" href="/common/canvas-tests.css"> | ||||||
| <body class="show_output"> | <body class="show_output"> | ||||||
| 
 | 
 | ||||||
| <h1>2d.imageData.object.ctor</h1> | <h1>2d.imageData.object.ctor.size.bounds</h1> | ||||||
| <p class="desc">ImageData does not have a usable constructor</p> | <p class="desc">ImageData has a usable constructor</p> | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| <p class="output">Actual output:</p> | <p class="output">Actual output:</p> | ||||||
|  | @ -16,11 +16,13 @@ | ||||||
| 
 | 
 | ||||||
| <ul id="d"></ul> | <ul id="d"></ul> | ||||||
| <script> | <script> | ||||||
| var t = async_test("ImageData does not have a usable constructor"); | var t = async_test("ImageData has a usable constructor"); | ||||||
| _addTest(function(canvas, ctx) { | _addTest(function(canvas, ctx) { | ||||||
| 
 | 
 | ||||||
| _assertDifferent(window.ImageData, undefined, "window.ImageData", "undefined"); | _assertDifferent(window.ImageData, undefined, "window.ImageData", "undefined"); | ||||||
| assert_throws(new TypeError(), function() { new window.ImageData(1,1); }); | assert_throws("INDEX_SIZE_ERR", function() { new window.ImageData(0, 0); }); | ||||||
|  | assert_throws("INDEX_SIZE_ERR", function() { new window.ImageData(0, 1); }); | ||||||
|  | assert_throws("INDEX_SIZE_ERR", function() { new window.ImageData(1, 0); }); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| }); | }); | ||||||
|  | @ -0,0 +1,35 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <!-- DO NOT EDIT! This test has been generated by tools/gentest.py. --> | ||||||
|  | <title>Canvas test: 2d.imageData.object.ctor.size</title> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | <script src="/common/canvas-tests.js"></script> | ||||||
|  | <link rel="stylesheet" href="/common/canvas-tests.css"> | ||||||
|  | <body class="show_output"> | ||||||
|  | 
 | ||||||
|  | <h1>2d.imageData.object.ctor.size</h1> | ||||||
|  | <p class="desc">ImageData has a usable constructor</p> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | <p class="output">Actual output:</p> | ||||||
|  | <canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas> | ||||||
|  | 
 | ||||||
|  | <ul id="d"></ul> | ||||||
|  | <script> | ||||||
|  | var t = async_test("ImageData has a usable constructor"); | ||||||
|  | _addTest(function(canvas, ctx) { | ||||||
|  | 
 | ||||||
|  | _assertDifferent(window.ImageData, undefined, "window.ImageData", "undefined"); | ||||||
|  | 
 | ||||||
|  | var imgdata = new window.ImageData(2, 3); | ||||||
|  | _assertSame(imgdata.width, 2, "imgdata.width", "2"); | ||||||
|  | _assertSame(imgdata.height, 3, "imgdata.height", "3"); | ||||||
|  | _assertSame(imgdata.data.length, 2 * 3 * 4, "imgdata.data.length", "2 * 3 * 4"); | ||||||
|  | for (var i = 0; i < imgdata.data.length; ++i) { | ||||||
|  |   _assertSame(imgdata.data[i], 0, "imgdata.data[\""+(i)+"\"]", "0"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | @ -9276,22 +9276,6 @@ | ||||||
|             isTransparentBlack = false; |             isTransparentBlack = false; | ||||||
|     @assert isTransparentBlack; |     @assert isTransparentBlack; | ||||||
| 
 | 
 | ||||||
| - name: 2d.imageData.create2.tiny |  | ||||||
|   desc: createImageData(sw, sh) works for sizes smaller than one pixel |  | ||||||
|   testing: |  | ||||||
|     - 2d.imageData.create2.size |  | ||||||
|     - 2d.imageData.one |  | ||||||
|   code: | |  | ||||||
|     var imgdata = ctx.createImageData(0.0001, 0.0001); |  | ||||||
|     @assert imgdata.data.length === imgdata.width*imgdata.height*4; |  | ||||||
|     @assert imgdata.width === 1; |  | ||||||
|     @assert imgdata.height === 1; |  | ||||||
|     var isTransparentBlack = true; |  | ||||||
|     for (var i = 0; i < imgdata.data.length; ++i) |  | ||||||
|         if (imgdata.data[i] !== 0) |  | ||||||
|             isTransparentBlack = false; |  | ||||||
|     @assert isTransparentBlack; |  | ||||||
| 
 |  | ||||||
| - name: 2d.imageData.create2.negative | - name: 2d.imageData.create2.negative | ||||||
|   desc: createImageData(sw, sh) takes the absolute magnitude of the size arguments |   desc: createImageData(sw, sh) takes the absolute magnitude of the size arguments | ||||||
|   testing: |   testing: | ||||||
|  | @ -9313,6 +9297,8 @@ | ||||||
|     @assert throws INDEX_SIZE_ERR ctx.createImageData(10, 0); |     @assert throws INDEX_SIZE_ERR ctx.createImageData(10, 0); | ||||||
|     @assert throws INDEX_SIZE_ERR ctx.createImageData(0, 10); |     @assert throws INDEX_SIZE_ERR ctx.createImageData(0, 10); | ||||||
|     @assert throws INDEX_SIZE_ERR ctx.createImageData(0, 0); |     @assert throws INDEX_SIZE_ERR ctx.createImageData(0, 0); | ||||||
|  |     @assert throws INDEX_SIZE_ERR ctx.createImageData(0.99, 10); | ||||||
|  |     @assert throws INDEX_SIZE_ERR ctx.createImageData(10, 0.1); | ||||||
| 
 | 
 | ||||||
| - name: 2d.imageData.create2.nonfinite | - name: 2d.imageData.create2.nonfinite | ||||||
|   desc: createImageData() throws TypeError if arguments are not finite |   desc: createImageData() throws TypeError if arguments are not finite | ||||||
|  | @ -9333,15 +9319,17 @@ | ||||||
|   code: | |   code: | | ||||||
|     @assert throws TypeError ctx.createImageData(null); |     @assert throws TypeError ctx.createImageData(null); | ||||||
| 
 | 
 | ||||||
| - name: 2d.imageData.create2.round | - name: 2d.imageData.create2.double | ||||||
|   desc: createImageData(w, h) is rounded the same as getImageData(0, 0, w, h) |   desc: createImageData(w, h) double is converted to long | ||||||
|   testing: |   testing: | ||||||
|     - 2d.imageData.createround |     - 2d.imageData.create2.size | ||||||
|   code: | |   code: | | ||||||
|     var imgdata1 = ctx.createImageData(10.01, 10.99); |     var imgdata1 = ctx.createImageData(10.01, 10.99); | ||||||
|     var imgdata2 = ctx.getImageData(0, 0, 10.01, 10.99); |     var imgdata2 = ctx.createImageData(-10.01, -10.99); | ||||||
|     @assert imgdata1.width === imgdata2.width; |     @assert imgdata1.width === 10; | ||||||
|     @assert imgdata1.height === imgdata2.height; |     @assert imgdata1.height === 10; | ||||||
|  |     @assert imgdata2.width === 10; | ||||||
|  |     @assert imgdata2.height === 10; | ||||||
| 
 | 
 | ||||||
| - name: 2d.imageData.get.basic | - name: 2d.imageData.get.basic | ||||||
|   desc: getImageData() exists and returns something |   desc: getImageData() exists and returns something | ||||||
|  | @ -9371,6 +9359,10 @@ | ||||||
|     @assert throws INDEX_SIZE_ERR ctx.getImageData(1, 1, 10, 0); |     @assert throws INDEX_SIZE_ERR ctx.getImageData(1, 1, 10, 0); | ||||||
|     @assert throws INDEX_SIZE_ERR ctx.getImageData(1, 1, 0, 10); |     @assert throws INDEX_SIZE_ERR ctx.getImageData(1, 1, 0, 10); | ||||||
|     @assert throws INDEX_SIZE_ERR ctx.getImageData(1, 1, 0, 0); |     @assert throws INDEX_SIZE_ERR ctx.getImageData(1, 1, 0, 0); | ||||||
|  |     @assert throws INDEX_SIZE_ERR ctx.getImageData(1, 1, 0.1, 10); | ||||||
|  |     @assert throws INDEX_SIZE_ERR ctx.getImageData(1, 1, 10, 0.99); | ||||||
|  |     @assert throws INDEX_SIZE_ERR ctx.getImageData(1, 1, -0.1, 10); | ||||||
|  |     @assert throws INDEX_SIZE_ERR ctx.getImageData(1, 1, 10, -0.99); | ||||||
| 
 | 
 | ||||||
| - name: 2d.imageData.get.nonfinite | - name: 2d.imageData.get.nonfinite | ||||||
|   desc: getImageData() throws TypeError if arguments are not finite |   desc: getImageData() throws TypeError if arguments are not finite | ||||||
|  | @ -9488,15 +9480,17 @@ | ||||||
|     @assert imgdata2.width > imgdata1.width; |     @assert imgdata2.width > imgdata1.width; | ||||||
|     @assert imgdata2.height > imgdata1.height; |     @assert imgdata2.height > imgdata1.height; | ||||||
| 
 | 
 | ||||||
| - name: 2d.imageData.get.tiny | - name: 2d.imageData.get.double | ||||||
|   desc: getImageData() works for sizes smaller than one pixel |   desc: createImageData(w, h) double is converted to long | ||||||
|   testing: |   testing: | ||||||
|     - 2d.imageData.one |     - 2d.imageData.get.basic | ||||||
|   code: | |   code: | | ||||||
|     var imgdata = ctx.getImageData(0, 0, 0.0001, 0.0001); |     var imgdata1 = ctx.getImageData(0, 0, 10.01, 10.99); | ||||||
|     @assert imgdata.data.length === imgdata.width*imgdata.height*4; |     var imgdata2 = ctx.getImageData(0, 0, -10.01, -10.99); | ||||||
|     @assert imgdata.width === 1; |     @assert imgdata1.width === 10; | ||||||
|     @assert imgdata.height === 1; |     @assert imgdata1.height === 10; | ||||||
|  |     @assert imgdata2.width === 10; | ||||||
|  |     @assert imgdata2.height === 10; | ||||||
| 
 | 
 | ||||||
| - name: 2d.imageData.get.nonpremul | - name: 2d.imageData.get.nonpremul | ||||||
|   desc: getImageData() returns non-premultiplied colours |   desc: getImageData() returns non-premultiplied colours | ||||||
|  | @ -9664,13 +9658,57 @@ | ||||||
|     @assert imgdata.data[2] === 0; |     @assert imgdata.data[2] === 0; | ||||||
|     @assert imgdata.data[3] === 0; |     @assert imgdata.data[3] === 0; | ||||||
| 
 | 
 | ||||||
| - name: 2d.imageData.object.ctor | - name: 2d.imageData.object.ctor.size | ||||||
|   desc: ImageData does not have a usable constructor |   desc: ImageData has a usable constructor | ||||||
|   testing: |   testing: | ||||||
|     - 2d.imageData.type |     - 2d.imageData.type | ||||||
|   code: | |   code: | | ||||||
|     @assert window.ImageData !== undefined; |     @assert window.ImageData !== undefined; | ||||||
|     @assert throws TypeError new window.ImageData(1,1); | 
 | ||||||
|  |     var imgdata = new window.ImageData(2, 3); | ||||||
|  |     @assert imgdata.width === 2; | ||||||
|  |     @assert imgdata.height === 3; | ||||||
|  |     @assert imgdata.data.length === 2 * 3 * 4; | ||||||
|  |     for (var i = 0; i < imgdata.data.length; ++i) { | ||||||
|  |       @assert imgdata.data[i] === 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | - name: 2d.imageData.object.ctor.size.bounds | ||||||
|  |   desc: ImageData has a usable constructor | ||||||
|  |   testing: | ||||||
|  |     - 2d.imageData.type | ||||||
|  |   code: | | ||||||
|  |     @assert window.ImageData !== undefined; | ||||||
|  |     @assert throws INDEX_SIZE_ERR new window.ImageData(0, 0); | ||||||
|  |     @assert throws INDEX_SIZE_ERR new window.ImageData(0, 1); | ||||||
|  |     @assert throws INDEX_SIZE_ERR new window.ImageData(1, 0); | ||||||
|  | 
 | ||||||
|  | - name: 2d.imageData.object.ctor.array | ||||||
|  |   desc: ImageData has a usable constructor | ||||||
|  |   testing: | ||||||
|  |     - 2d.imageData.type | ||||||
|  |   code: | | ||||||
|  |     @assert window.ImageData !== undefined; | ||||||
|  | 
 | ||||||
|  |     var array = new Uint8ClampedArray(8); | ||||||
|  |     var imgdata = new window.ImageData(array, 1, 2); | ||||||
|  |     @assert imgdata.width === 1; | ||||||
|  |     @assert imgdata.height === 2; | ||||||
|  |     @assert imgdata.data === array; | ||||||
|  | 
 | ||||||
|  | - name: 2d.imageData.object.ctor.array.bounds | ||||||
|  |   desc: ImageData has a usable constructor | ||||||
|  |   testing: | ||||||
|  |     - 2d.imageData.type | ||||||
|  |   code: | | ||||||
|  |     @assert window.ImageData !== undefined; | ||||||
|  | 
 | ||||||
|  |     @assert throws INVALID_STATE_ERR new ImageData(new Uint8ClampedArray(0), 1); | ||||||
|  |     @assert throws INVALID_STATE_ERR new ImageData(new Uint8ClampedArray(3), 1); | ||||||
|  |     @assert throws INDEX_SIZE_ERR new ImageData(new Uint8ClampedArray(4), 0); | ||||||
|  |     @assert throws INDEX_SIZE_ERR new ImageData(new Uint8ClampedArray(4), 1, 2); | ||||||
|  |     @assert throws TypeError new ImageData(new Uint8Array(8), 1, 2); | ||||||
|  |     @assert throws TypeError new ImageData(new Int8Array(8), 1, 2); | ||||||
| 
 | 
 | ||||||
| - name: 2d.imageData.object.set | - name: 2d.imageData.object.set | ||||||
|   desc: ImageData.data can be modified |   desc: ImageData.data can be modified | ||||||
|  |  | ||||||
|  | @ -27,3 +27,8 @@ non-infringement, or title; nor that the contents of this repository are | ||||||
| suitable for any purpose. We make no representations, express or implied, that | suitable for any purpose. We make no representations, express or implied, that | ||||||
| the content of this repository or the use thereof indicates conformance to a | the content of this repository or the use thereof indicates conformance to a | ||||||
| specification. All content is provided as-is to help reach interoperability. | specification. All content is provided as-is to help reach interoperability. | ||||||
|  | 
 | ||||||
|  | Documentation | ||||||
|  | ------------- | ||||||
|  | 
 | ||||||
|  | See [web-platform-tests.org](http://web-platform-tests.org/). | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
|   <title>Historical features</title> |   <title>Historical features</title> | ||||||
|   <script src="/resources/testharness.js"></script> |   <script src="/resources/testharness.js"></script> | ||||||
|   <script src="/resources/testharnessreport.js"></script> |   <script src="/resources/testharnessreport.js"></script> | ||||||
|  |   <script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script> | ||||||
|  </head> |  </head> | ||||||
|  <body> |  <body> | ||||||
|   <div id="log"></div> |   <div id="log"></div> | ||||||
|  | @ -48,6 +49,10 @@ | ||||||
|         assert_false('isClosed' in b, 'isClosed in b'); |         assert_false('isClosed' in b, 'isClosed in b'); | ||||||
|         assert_false('isClosed' in Blob.prototype, 'isClosed in Blob.prototype'); |         assert_false('isClosed' in Blob.prototype, 'isClosed in Blob.prototype'); | ||||||
|     }, 'Blob.close() should not be supported'); |     }, 'Blob.close() should not be supported'); | ||||||
|  | 
 | ||||||
|  |     // Only add service worker test if service workers are actually supported. | ||||||
|  |     if (navigator.serviceWorker) | ||||||
|  |       service_worker_test('support/historical-serviceworker.js', 'Service worker test setup'); | ||||||
|   </script> |   </script> | ||||||
|  </body> |  </body> | ||||||
| </html> | </html> | ||||||
|  | @ -0,0 +1,5 @@ | ||||||
|  | importScripts('/resources/testharness.js'); | ||||||
|  | 
 | ||||||
|  | test(() => { | ||||||
|  |   assert_false('FileReaderSync' in self); | ||||||
|  | }, '"FileReaderSync" should not be supported in service workers'); | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
|  | <meta charset=utf-8> | ||||||
| <title>IDBCursor direction - index with keyrange</title> | <title>IDBCursor direction - index with keyrange</title> | ||||||
| <link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal"> | <link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal"> | ||||||
| <link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#cursor-iteration-operation"> | <link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#cursor-iteration-operation"> | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
|  | <meta charset=utf-8> | ||||||
| <title>IDBCursor direction - object store with keyrange</title> | <title>IDBCursor direction - object store with keyrange</title> | ||||||
| <link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal"> | <link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal"> | ||||||
| <link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#cursor-iteration-operation"> | <link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#cursor-iteration-operation"> | ||||||
|  |  | ||||||
|  | @ -0,0 +1,28 @@ | ||||||
|  | <!doctype html> | ||||||
|  | <meta charset=utf-8> | ||||||
|  | <title>IndexedDB: Test IDBFactory open() error event properties</title> | ||||||
|  | <meta name=help href="https://w3c.github.io/IndexedDB/#dom-idbfactory-open"> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | <script src="support.js"></script> | ||||||
|  | <script> | ||||||
|  | 
 | ||||||
|  | async_test(t => { | ||||||
|  |   const dbname = document.location + '-' + t.name; | ||||||
|  |   indexedDB.deleteDatabase(dbname); | ||||||
|  |   const open = indexedDB.open(dbname); | ||||||
|  |   open.onsuccess = t.unreached_func('open should not succeed'); | ||||||
|  |   open.onupgradeneeded = t.step_func(() => { | ||||||
|  |     const tx = open.transaction; | ||||||
|  |     tx.abort(); | ||||||
|  |   }); | ||||||
|  |   open.onerror = t.step_func(e => { | ||||||
|  |     assert_equals(e.target, open, 'event target should be request'); | ||||||
|  |     assert_equals(e.type, 'error', 'Event type should be error'); | ||||||
|  |     assert_true(e.bubbles, 'Event should bubble'); | ||||||
|  |     assert_true(e.cancelable, 'Event should be cancelable'); | ||||||
|  |     t.done(); | ||||||
|  |   }); | ||||||
|  | }, 'Properties of error event from failed open()'); | ||||||
|  | 
 | ||||||
|  | </script> | ||||||
|  | @ -0,0 +1,52 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <meta charset=utf-8> | ||||||
|  | <title>IDBObjectStore.createIndex() - AutoIncrement in Compound Index</title> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | <script src="support.js"></script> | ||||||
|  | <script> | ||||||
|  |   indexeddb_test( | ||||||
|  |     function(t, db, txn) { | ||||||
|  |       // No auto-increment | ||||||
|  |       var store = db.createObjectStore("Store1", {keyPath: "id"}); | ||||||
|  |       store.createIndex("CompoundKey", ["num", "id"]); | ||||||
|  | 
 | ||||||
|  |       // Add data | ||||||
|  |       store.put({id: 1, num: 100}); | ||||||
|  |     }, | ||||||
|  |     function(t, db) { | ||||||
|  |       var store = db.transaction("Store1", "readwrite").objectStore("Store1"); | ||||||
|  | 
 | ||||||
|  |       store.openCursor().onsuccess = t.step_func(function(e) { | ||||||
|  |         var item = e.target.result.value; | ||||||
|  |         store.index("CompoundKey").get([item.num, item.id]).onsuccess = t.step_func(function(e) { | ||||||
|  |           assert_equals(e.target.result ? e.target.result.num : null, 100, 'Expected 100.'); | ||||||
|  |           t.done(); | ||||||
|  |         }); | ||||||
|  |       }); | ||||||
|  |     }, | ||||||
|  |     "Explicit Primary Key" | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   indexeddb_test( | ||||||
|  |     function(t, db, txn) { | ||||||
|  |       // Auto-increment | ||||||
|  |       var store = db.createObjectStore("Store2", {keyPath: "id", autoIncrement: true}); | ||||||
|  |       store.createIndex("CompoundKey", ["num", "id"]); | ||||||
|  | 
 | ||||||
|  |       // Add data | ||||||
|  |       store.put({num: 100}); | ||||||
|  |     }, | ||||||
|  |     function(t, db) { | ||||||
|  |       var store = db.transaction("Store2", "readwrite").objectStore("Store2"); | ||||||
|  |       store.openCursor().onsuccess = t.step_func(function(e) { | ||||||
|  |         var item = e.target.result.value; | ||||||
|  |         store.index("CompoundKey").get([item.num, item.id]).onsuccess = t.step_func(function(e) { | ||||||
|  |           assert_equals(e.target.result ? e.target.result.num : null, 100, 'Expected 100.'); | ||||||
|  |           t.done(); | ||||||
|  |         }); | ||||||
|  |       }); | ||||||
|  |     }, | ||||||
|  |     "Auto-Increment Primary Key" | ||||||
|  |   ); | ||||||
|  | </script> | ||||||
							
								
								
									
										196
									
								
								testing/web-platform/tests/IndexedDB/interleaved-cursors.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								testing/web-platform/tests/IndexedDB/interleaved-cursors.html
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,196 @@ | ||||||
|  | <!doctype html> | ||||||
|  | <meta charset="utf-8"> | ||||||
|  | <meta name="timeout" content="long"> | ||||||
|  | <title>IndexedDB: Interleaved iteration of multiple cursors</title> | ||||||
|  | <link rel="author" href="pwnall@chromium.org" title="Victor Costan"> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | <script src="support-promises.js"></script> | ||||||
|  | <script> | ||||||
|  | // Number of objects that each iterator goes over. | ||||||
|  | const itemCount = 10; | ||||||
|  | 
 | ||||||
|  | // Ratio of small objects to large objects. | ||||||
|  | const largeObjectRatio = 5; | ||||||
|  | 
 | ||||||
|  | // Size of large objects. This should exceed the size of a block in the storage | ||||||
|  | // method underlying the browser's IndexedDB implementation. For example, this | ||||||
|  | // needs to exceed the LevelDB block size on Chrome, and the SQLite block size | ||||||
|  | // on Firefox. | ||||||
|  | const largeObjectSize = 48 * 1024; | ||||||
|  | 
 | ||||||
|  | function objectKey(cursorIndex, itemIndex) { | ||||||
|  |   return `${cursorIndex}-key-${itemIndex}`; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function objectValue(cursorIndex, itemIndex) { | ||||||
|  |   if ((cursorIndex * itemCount + itemIndex) % largeObjectRatio === 0) { | ||||||
|  |     // We use a typed array (as opposed to a string) because IndexedDB | ||||||
|  |     // implementations may serialize strings using UTF-8 or UTF-16, yielding | ||||||
|  |     // larger IndexedDB entries than we'd expect. It's very unlikely that an | ||||||
|  |     // IndexedDB implementation would use anything other than the raw buffer to | ||||||
|  |     // serialize a typed array. | ||||||
|  |     const buffer = new Uint8Array(largeObjectSize); | ||||||
|  | 
 | ||||||
|  |     // Some IndexedDB implementations, like LevelDB, compress their data blocks | ||||||
|  |     // before storing them to disk. We use a simple 32-bit xorshift PRNG, which | ||||||
|  |     // should be sufficient to foil any fast generic-purpose compression scheme. | ||||||
|  | 
 | ||||||
|  |     // 32-bit xorshift - the seed can't be zero | ||||||
|  |     let state = 1000 + (cursorIndex * itemCount + itemIndex); | ||||||
|  | 
 | ||||||
|  |     for (let i = 0; i < largeObjectSize; ++i) { | ||||||
|  |       state ^= state << 13; | ||||||
|  |       state ^= state >> 17; | ||||||
|  |       state ^= state << 5; | ||||||
|  |       buffer[i] = state & 0xff; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return buffer; | ||||||
|  |   } | ||||||
|  |   return [cursorIndex, 'small', itemIndex]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Writes the objects to be read by one cursor. Returns a promise that resolves | ||||||
|  | // when the write completes. | ||||||
|  | // | ||||||
|  | // We want to avoid creating a large transaction, because that is outside the | ||||||
|  | // test's scope, and it's a bad practice. So we break up the writes across | ||||||
|  | // multiple transactions. For simplicity, each transaction writes all the | ||||||
|  | // objects that will be read by a cursor. | ||||||
|  | function writeCursorObjects(database, cursorIndex) { | ||||||
|  |   return new Promise((resolve, reject) => { | ||||||
|  |     const transaction = database.transaction('cache', 'readwrite'); | ||||||
|  |     transaction.onabort = () => { reject(transaction.error); }; | ||||||
|  | 
 | ||||||
|  |     const store = transaction.objectStore('cache'); | ||||||
|  |     for (let i = 0; i < itemCount; ++i) { | ||||||
|  |       store.put({ | ||||||
|  |           key: objectKey(cursorIndex, i), value: objectValue(cursorIndex, i)}); | ||||||
|  |     } | ||||||
|  |     transaction.oncomplete = resolve; | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Returns a promise that resolves when the store has been populated. | ||||||
|  | function populateTestStore(testCase, database, cursorCount) { | ||||||
|  |   let promiseChain = Promise.resolve(); | ||||||
|  | 
 | ||||||
|  |   for (let i = 0; i < cursorCount; ++i) | ||||||
|  |     promiseChain = promiseChain.then(() => writeCursorObjects(database, i)); | ||||||
|  | 
 | ||||||
|  |   return promiseChain; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Reads cursors in an interleaved fashion, as shown below. | ||||||
|  | // | ||||||
|  | // Given N cursors, each of which points to the beginning of a K-item sequence, | ||||||
|  | // the following accesses will be made. | ||||||
|  | // | ||||||
|  | // OC(i)    = open cursor i | ||||||
|  | // RD(i, j) = read result of cursor i, which should be at item j | ||||||
|  | // CC(i)    = continue cursor i | ||||||
|  | // |        = wait for onsuccess on the previous OC or CC | ||||||
|  | // | ||||||
|  | // OC(1)            | RD(1, 1) OC(2) | RD(2, 1) OC(3) | ... | RD(n-1, 1) CC(n) | | ||||||
|  | // RD(n, 1)   CC(1) | RD(1, 2) CC(2) | RD(2, 2) CC(3) | ... | RD(n-1, 2) CC(n) | | ||||||
|  | // RD(n, 2)   CC(1) | RD(1, 3) CC(2) | RD(2, 3) CC(3) | ... | RD(n-1, 3) CC(n) | | ||||||
|  | // ... | ||||||
|  | // RD(n, k-1) CC(1) | RD(1, k) CC(2) | RD(2, k) CC(3) | ... | RD(n-1, k) CC(n) | | ||||||
|  | // RD(n, k)           done | ||||||
|  | function interleaveCursors(testCase, store, cursorCount) { | ||||||
|  |   return new Promise((resolve, reject) => { | ||||||
|  |     // The cursors used for iteration are stored here so each cursor's onsuccess | ||||||
|  |     // handler can call continue() on the next cursor. | ||||||
|  |     const cursors = []; | ||||||
|  | 
 | ||||||
|  |     // The results of IDBObjectStore.openCursor() calls are stored here so we | ||||||
|  |     // we can change the requests' onsuccess handler after every | ||||||
|  |     // IDBCursor.continue() call. | ||||||
|  |     const requests = []; | ||||||
|  | 
 | ||||||
|  |     const checkCursorState = (cursorIndex, itemIndex) => { | ||||||
|  |       const cursor = cursors[cursorIndex]; | ||||||
|  |       assert_equals(cursor.key, objectKey(cursorIndex, itemIndex)); | ||||||
|  |       assert_equals(cursor.value.key, objectKey(cursorIndex, itemIndex)); | ||||||
|  |       assert_equals( | ||||||
|  |           cursor.value.value.join('-'), | ||||||
|  |           objectValue(cursorIndex, itemIndex).join('-')); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     const openCursor = (cursorIndex, callback) => { | ||||||
|  |       const request = store.openCursor( | ||||||
|  |           IDBKeyRange.lowerBound(objectKey(cursorIndex, 0))); | ||||||
|  |       requests[cursorIndex] = request; | ||||||
|  | 
 | ||||||
|  |       request.onsuccess = testCase.step_func(() => { | ||||||
|  |         const cursor = request.result; | ||||||
|  |         cursors[cursorIndex] = cursor; | ||||||
|  |         checkCursorState(cursorIndex, 0); | ||||||
|  |         callback(); | ||||||
|  |       }); | ||||||
|  |       request.onerror = event => reject(request.error); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     const readItemFromCursor = (cursorIndex, itemIndex, callback) => { | ||||||
|  |       const request = requests[cursorIndex]; | ||||||
|  |       request.onsuccess = testCase.step_func(() => { | ||||||
|  |         const cursor = request.result; | ||||||
|  |         cursors[cursorIndex] = cursor; | ||||||
|  |         checkCursorState(cursorIndex, itemIndex); | ||||||
|  |         callback(); | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       const cursor = cursors[cursorIndex]; | ||||||
|  |       cursor.continue(); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     // We open all the cursors one at a time, then cycle through the cursors and | ||||||
|  |     // call continue() on each of them. This access pattern causes maximal | ||||||
|  |     // trashing to an LRU cursor cache. Eviction scheme aside, any cache will | ||||||
|  |     // have to evict some cursors, and this access pattern verifies that the | ||||||
|  |     // cache correctly restores the state of evicted cursors. | ||||||
|  |     const steps = []; | ||||||
|  |     for (let cursorIndex = 0; cursorIndex < cursorCount; ++cursorIndex) | ||||||
|  |       steps.push(openCursor.bind(null, cursorIndex)); | ||||||
|  |     for (let itemIndex = 1; itemIndex < itemCount; ++itemIndex) { | ||||||
|  |       for (let cursorIndex = 0; cursorIndex < cursorCount; ++cursorIndex) | ||||||
|  |         steps.push(readItemFromCursor.bind(null, cursorIndex, itemIndex)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const runStep = (stepIndex) => { | ||||||
|  |       if (stepIndex === steps.length) { | ||||||
|  |         resolve(); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |       steps[stepIndex](() => { runStep(stepIndex + 1); }); | ||||||
|  |     }; | ||||||
|  |     runStep(0); | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | for (let cursorCount of [1, 10, 100, 500]) { | ||||||
|  |   promise_test(testCase => { | ||||||
|  |     return createDatabase(testCase, (database, transaction) => { | ||||||
|  |       const store = database.createObjectStore('cache', | ||||||
|  |           { keyPath: 'key', autoIncrement: true }); | ||||||
|  |     }).then(database => { | ||||||
|  |       return populateTestStore(testCase, database, cursorCount).then( | ||||||
|  |           () => database); | ||||||
|  |     }).then(database => { | ||||||
|  |       database.close(); | ||||||
|  |     }).then(() => { | ||||||
|  |       return openDatabase(testCase); | ||||||
|  |     }).then(database => { | ||||||
|  |       const transaction = database.transaction('cache', 'readonly'); | ||||||
|  |       transaction.onabort = () => { reject(transaction.error); }; | ||||||
|  | 
 | ||||||
|  |       const store = transaction.objectStore('cache'); | ||||||
|  |       return interleaveCursors(testCase, store, cursorCount).then( | ||||||
|  |           () => database); | ||||||
|  |     }).then(database => { | ||||||
|  |       database.close(); | ||||||
|  |     }); | ||||||
|  |   }, `${cursorCount} cursors`); | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  | @ -0,0 +1,52 @@ | ||||||
|  | <!doctype html> | ||||||
|  | <meta charset="utf-8"> | ||||||
|  | <meta name="timeout" content="long"> | ||||||
|  | <title>IndexedDB: Parallel iteration of cursors in upgradeneeded</title> | ||||||
|  | <link rel="author" href="pwnall@chromium.org" title="Victor Costan"> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | <script src="support-promises.js"></script> | ||||||
|  | <script> | ||||||
|  | 'use strict'; | ||||||
|  | 
 | ||||||
|  | for (let cursorCount of [2, 10, 100, 1000, 10000]) { | ||||||
|  |   promise_test(testCase => { | ||||||
|  |     return createDatabase(testCase, (database, transaction) => { | ||||||
|  |       const store = database.createObjectStore('cache', { keyPath: 'key' }); | ||||||
|  |       store.put({ key: '42' }); | ||||||
|  | 
 | ||||||
|  |       const promises = []; | ||||||
|  | 
 | ||||||
|  |       for (let j = 0; j < 2; j += 1) { | ||||||
|  |         const promise = new Promise((resolve, reject) => { | ||||||
|  |           let request = null; | ||||||
|  |           for (let i = 0; i < cursorCount / 2; i += 1) { | ||||||
|  |             request = store.openCursor(); | ||||||
|  |           } | ||||||
|  | 
 | ||||||
|  |           let continued = false; | ||||||
|  |           request.onsuccess = testCase.step_func(() => { | ||||||
|  |             const cursor = request.result; | ||||||
|  | 
 | ||||||
|  |             if (!continued) { | ||||||
|  |               assert_equals(cursor.key, '42'); | ||||||
|  |               assert_equals(cursor.value.key, '42'); | ||||||
|  |               continued = true; | ||||||
|  |               cursor.continue(); | ||||||
|  |             } else { | ||||||
|  |               assert_equals(cursor, null); | ||||||
|  |               resolve(); | ||||||
|  |             } | ||||||
|  |           }); | ||||||
|  |           request.onerror = () => reject(request.error); | ||||||
|  |         }); | ||||||
|  |         promises.push(promise); | ||||||
|  |       } | ||||||
|  |       return Promise.all(promises); | ||||||
|  |     }).then(database => { | ||||||
|  |       database.close(); | ||||||
|  |     }); | ||||||
|  |   }, `${cursorCount} cursors`); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | </script> | ||||||
|  | @ -21,7 +21,7 @@ function requestWatcher(testCase, request) { | ||||||
| // open request.
 | // open request.
 | ||||||
| //
 | //
 | ||||||
| // Returns a promise. If the versionchange transaction goes through, the promise
 | // Returns a promise. If the versionchange transaction goes through, the promise
 | ||||||
| // resolves to an IndexedDB database that must be closed by the caller. If the
 | // resolves to an IndexedDB database that should be closed by the caller. If the
 | ||||||
| // versionchange transaction is aborted, the promise resolves to an error.
 | // versionchange transaction is aborted, the promise resolves to an error.
 | ||||||
| function migrateDatabase(testCase, newVersion, migrationCallback) { | function migrateDatabase(testCase, newVersion, migrationCallback) { | ||||||
|   return migrateNamedDatabase( |   return migrateNamedDatabase( | ||||||
|  | @ -37,7 +37,7 @@ function migrateDatabase(testCase, newVersion, migrationCallback) { | ||||||
| // open request.
 | // open request.
 | ||||||
| //
 | //
 | ||||||
| // Returns a promise. If the versionchange transaction goes through, the promise
 | // Returns a promise. If the versionchange transaction goes through, the promise
 | ||||||
| // resolves to an IndexedDB database that must be closed by the caller. If the
 | // resolves to an IndexedDB database that should be closed by the caller. If the
 | ||||||
| // versionchange transaction is aborted, the promise resolves to an error.
 | // versionchange transaction is aborted, the promise resolves to an error.
 | ||||||
| function migrateNamedDatabase( | function migrateNamedDatabase( | ||||||
|     testCase, databaseName, newVersion, migrationCallback) { |     testCase, databaseName, newVersion, migrationCallback) { | ||||||
|  | @ -88,10 +88,20 @@ function migrateNamedDatabase( | ||||||
|       resolve(Promise.resolve(callbackResult).then(() => requestEventPromise)); |       resolve(Promise.resolve(callbackResult).then(() => requestEventPromise)); | ||||||
|     }); |     }); | ||||||
|     request.onerror = event => reject(event.target.error); |     request.onerror = event => reject(event.target.error); | ||||||
|     request.onsuccess = () => reject(new Error( |     request.onsuccess = () => { | ||||||
|         'indexedDB.open should not succeed without creating a ' + |       const database = request.result; | ||||||
|         'versionchange transaction')); |       testCase.add_cleanup(() => { database.close(); }); | ||||||
|   }).then(event => event.target.result || event.target.error); |       reject(new Error( | ||||||
|  |           'indexedDB.open should not succeed without creating a ' + | ||||||
|  |           'versionchange transaction')); | ||||||
|  |     }; | ||||||
|  |   }).then(event => { | ||||||
|  |     const database = event.target.result; | ||||||
|  |     if (database) { | ||||||
|  |       testCase.add_cleanup(() => { database.close(); }); | ||||||
|  |     } | ||||||
|  |     return database || event.target.error; | ||||||
|  |   }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Creates an IndexedDB database whose name is unique for the test case.
 | // Creates an IndexedDB database whose name is unique for the test case.
 | ||||||
|  | @ -100,7 +110,7 @@ function migrateNamedDatabase( | ||||||
| // given the created database, the versionchange transaction, and the database
 | // given the created database, the versionchange transaction, and the database
 | ||||||
| // open request.
 | // open request.
 | ||||||
| //
 | //
 | ||||||
| // Returns a promise that resolves to an IndexedDB database. The caller must
 | // Returns a promise that resolves to an IndexedDB database. The caller should
 | ||||||
| // close the database.
 | // close the database.
 | ||||||
| function createDatabase(testCase, setupCallback) { | function createDatabase(testCase, setupCallback) { | ||||||
|   return createNamedDatabase(testCase, databaseName(testCase), setupCallback); |   return createNamedDatabase(testCase, databaseName(testCase), setupCallback); | ||||||
|  | @ -112,21 +122,23 @@ function createDatabase(testCase, setupCallback) { | ||||||
| // given the created database, the versionchange transaction, and the database
 | // given the created database, the versionchange transaction, and the database
 | ||||||
| // open request.
 | // open request.
 | ||||||
| //
 | //
 | ||||||
| // Returns a promise that resolves to an IndexedDB database. The caller must
 | // Returns a promise that resolves to an IndexedDB database. The caller should
 | ||||||
| // close the database.
 | // close the database.
 | ||||||
| function createNamedDatabase(testCase, databaseName, setupCallback) { | function createNamedDatabase(testCase, databaseName, setupCallback) { | ||||||
|   const request = indexedDB.deleteDatabase(databaseName); |   const request = indexedDB.deleteDatabase(databaseName); | ||||||
|   const eventWatcher = requestWatcher(testCase, request); |   const eventWatcher = requestWatcher(testCase, request); | ||||||
| 
 | 
 | ||||||
|   return eventWatcher.wait_for('success').then(event => |   return eventWatcher.wait_for('success').then(event => { | ||||||
|       migrateNamedDatabase(testCase, databaseName, 1, setupCallback)); |     testCase.add_cleanup(() => { indexedDB.deleteDatabase(databaseName); }); | ||||||
|  |     return migrateNamedDatabase(testCase, databaseName, 1, setupCallback) | ||||||
|  |   }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Opens an IndexedDB database without performing schema changes.
 | // Opens an IndexedDB database without performing schema changes.
 | ||||||
| //
 | //
 | ||||||
| // The given version number must match the database's current version.
 | // The given version number must match the database's current version.
 | ||||||
| //
 | //
 | ||||||
| // Returns a promise that resolves to an IndexedDB database. The caller must
 | // Returns a promise that resolves to an IndexedDB database. The caller should
 | ||||||
| // close the database.
 | // close the database.
 | ||||||
| function openDatabase(testCase, version) { | function openDatabase(testCase, version) { | ||||||
|   return openNamedDatabase(testCase, databaseName(testCase), version); |   return openNamedDatabase(testCase, databaseName(testCase), version); | ||||||
|  | @ -136,12 +148,16 @@ function openDatabase(testCase, version) { | ||||||
| //
 | //
 | ||||||
| // The given version number must match the database's current version.
 | // The given version number must match the database's current version.
 | ||||||
| //
 | //
 | ||||||
| // Returns a promise that resolves to an IndexedDB database. The caller must
 | // Returns a promise that resolves to an IndexedDB database. The caller should
 | ||||||
| // close the database.
 | // close the database.
 | ||||||
| function openNamedDatabase(testCase, databaseName, version) { | function openNamedDatabase(testCase, databaseName, version) { | ||||||
|   const request = indexedDB.open(databaseName, version); |   const request = indexedDB.open(databaseName, version); | ||||||
|   const eventWatcher = requestWatcher(testCase, request); |   const eventWatcher = requestWatcher(testCase, request); | ||||||
|   return eventWatcher.wait_for('success').then(event => event.target.result); |   return eventWatcher.wait_for('success').then(() => { | ||||||
|  |     const database = request.result; | ||||||
|  |     testCase.add_cleanup(() => { database.close(); }); | ||||||
|  |     return database; | ||||||
|  |   }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // The data in the 'books' object store records in the first example of the
 | // The data in the 'books' object store records in the first example of the
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,68 @@ | ||||||
|  | <!doctype html> | ||||||
|  | <meta charset=utf-8> | ||||||
|  | <title>IndexedDB: Test error events fired at requests from aborted transaction</title> | ||||||
|  | <meta name=help href="https://w3c.github.io/IndexedDB/#abort-a-transaction"> | ||||||
|  | <meta name=help href="https://w3c.github.io/IndexedDB/#request-construct"> | ||||||
|  | <meta name=help href="https://w3c.github.io/IndexedDB/#transaction-construct"> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | <script src="support.js"></script> | ||||||
|  | <script> | ||||||
|  | 
 | ||||||
|  | indexeddb_test( | ||||||
|  |   (t, db) => { | ||||||
|  |     db.createObjectStore('store'); | ||||||
|  |   }, | ||||||
|  |   (t, db) => { | ||||||
|  |     const tx = db.transaction('store'); | ||||||
|  |     const request = tx.objectStore('store').get(0); | ||||||
|  |     tx.abort(); | ||||||
|  |     request.onsuccess = t.unreached_func('request should not succeed'); | ||||||
|  | 
 | ||||||
|  |     let connection_saw_error = false; | ||||||
|  |     let transaction_saw_error = false; | ||||||
|  | 
 | ||||||
|  |     request.onerror = t.step_func(e => { | ||||||
|  |       assert_equals(request.readyState, 'done', | ||||||
|  |                     'Request\'s done flag should be set'); | ||||||
|  |       assert_equals(request.result, undefined, | ||||||
|  |                     'Request\'s result should be undefined'); | ||||||
|  |       assert_equals(request.error.name, 'AbortError', | ||||||
|  |                     'Request\'s error should be AbortError'); | ||||||
|  | 
 | ||||||
|  |       assert_equals(e.target, request, 'event target should be request'); | ||||||
|  |       assert_equals(e.type, 'error', 'Event type should be error'); | ||||||
|  |       assert_true(e.bubbles, 'Event should bubble'); | ||||||
|  |       assert_true(e.cancelable, 'Event should cancelable'); | ||||||
|  | 
 | ||||||
|  |       assert_true(connection_saw_error, | ||||||
|  |                   'Event propagated through connection'); | ||||||
|  |       assert_true(transaction_saw_error, | ||||||
|  |                   'Event propagated through transaction'); | ||||||
|  |       t.done(); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     // Event propagates via "get the parent" on request and transaction. | ||||||
|  | 
 | ||||||
|  |     db.addEventListener('error', t.step_func(e => { | ||||||
|  |       connection_saw_error = true; | ||||||
|  |       assert_equals(e.target, request, 'event target should be request'); | ||||||
|  |       assert_equals(e.type, 'error', 'Event type should be error'); | ||||||
|  |       assert_true(e.bubbles, 'Event should bubble'); | ||||||
|  |       assert_true(e.cancelable, 'Event should cancelable'); | ||||||
|  |     }), true); | ||||||
|  | 
 | ||||||
|  |     tx.addEventListener('error', t.step_func(e => { | ||||||
|  |       transaction_saw_error = true; | ||||||
|  |       assert_equals(e.target, request, 'event target should be request'); | ||||||
|  |       assert_equals(e.type, 'error', 'Event type should be error'); | ||||||
|  |       assert_true(e.bubbles, 'Event should bubble'); | ||||||
|  |       assert_true(e.cancelable, 'Event should cancelable'); | ||||||
|  | 
 | ||||||
|  |       assert_true(connection_saw_error, | ||||||
|  |                   'Event propagated through connection'); | ||||||
|  |     }), true); | ||||||
|  |   }, | ||||||
|  |   'Properties of error events fired at requests when aborting a transaction'); | ||||||
|  | 
 | ||||||
|  | </script> | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| #Dual-License for W3C Test Suites | # Dual-License for W3C Test Suites | ||||||
| 
 | 
 | ||||||
| All documents in this Repository are licensed by contributors to be distributed under both the [W3C Test Suite License](#w3c-test-suite-license) and the [W3C 3-clause BSD License](#w3c-3-clause-bsd-license), reproduced below. The choice of license is up to the licensee. For more information, see [Licenses for W3C Test Suites](https://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html) | All documents in this Repository are licensed by contributors to be distributed under both the [W3C Test Suite License](#w3c-test-suite-license) and the [W3C 3-clause BSD License](#w3c-3-clause-bsd-license), reproduced below. The choice of license is up to the licensee. For more information, see [Licenses for W3C Test Suites](https://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -2,9 +2,7 @@ The web-platform-tests Project [](http://irc.w | ||||||
| ============================== | ============================== | ||||||
| 
 | 
 | ||||||
| The web-platform-tests Project is a W3C-coordinated attempt to build a | The web-platform-tests Project is a W3C-coordinated attempt to build a | ||||||
| cross-browser testsuite for the Web-platform stack.  However, for mainly | cross-browser testsuite for the Web-platform stack. Writing tests in a way | ||||||
| historic reasons, the CSS WG testsuite is in a separate repository, |  | ||||||
| [csswg-test](https://github.com/w3c/csswg-test). Writing tests in a way |  | ||||||
| that allows them to be run in all browsers gives browser projects | that allows them to be run in all browsers gives browser projects | ||||||
| confidence that they are shipping software that is compatible with other | confidence that they are shipping software that is compatible with other | ||||||
| implementations, and that later implementations will be compatible with | implementations, and that later implementations will be compatible with | ||||||
|  | @ -110,41 +108,23 @@ Alternatively, you may also use | ||||||
| in the Windows 10 Anniversary Update build, then access your windows | in the Windows 10 Anniversary Update build, then access your windows | ||||||
| partition from there to launch wptserve. | partition from there to launch wptserve. | ||||||
| 
 | 
 | ||||||
| Test Runner |  | ||||||
| =========== |  | ||||||
| 
 |  | ||||||
| There is a test runner that is designed to provide a |  | ||||||
| convenient way to run the web-platform-tests in-browser. It will run |  | ||||||
| testharness.js tests automatically but requires manual work for |  | ||||||
| reftests and manual tests. |  | ||||||
| 
 |  | ||||||
| The runner can be found at `/tools/runner/index.html` on the local |  | ||||||
| server i.e. |  | ||||||
| 
 |  | ||||||
| ``` |  | ||||||
| http://web-platform.test:8000/tools/runner/index.html |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| in the default configuration. The first time you use this it has to |  | ||||||
| generate a manifest of all tests. This may take some time, so please |  | ||||||
| be patient. |  | ||||||
| 
 |  | ||||||
| Publication | Publication | ||||||
| =========== | =========== | ||||||
| 
 | 
 | ||||||
| The master branch is automatically synced to http://w3c-test.org/. | The master branch is automatically synced to http://w3c-test.org/. | ||||||
| 
 | 
 | ||||||
| Pull requests are automatically mirrored to | Pull requests are | ||||||
| http://w3c-test.org/submissions/ a few minutes after someone with merge | [automatically mirrored](http://w3c-test.org/submissions/) except those | ||||||
| access has added a comment with "LGTM" (or "w3c-test:mirror") to indicate | that modify sensitive resources (such as `.py`). The latter require | ||||||
| the PR has been checked. | someone with merge access to comment with "LGTM" or "w3c-test:mirror" to | ||||||
|  | indicate the pull request has been checked. | ||||||
| 
 | 
 | ||||||
| Finding Things | Finding Things | ||||||
| ============== | ============== | ||||||
| 
 | 
 | ||||||
| Each top-level directory represents a W3C specification: the name | Each top-level directory matches the shortname used by a standard, with | ||||||
| matches the shortname used after the canonical address of the said | some exceptions. (Typically the shortname is from the standard's | ||||||
| specification under http://www.w3.org/TR/ . | corresponding GitHub repository.) | ||||||
| 
 | 
 | ||||||
| For some of the specifications, the tree under the top-level directory | For some of the specifications, the tree under the top-level directory | ||||||
| represents the sections of the respective documents, using the section | represents the sections of the respective documents, using the section | ||||||
|  | @ -185,6 +165,14 @@ The way to contribute is just as usual: | ||||||
| * Commit locally and push that to your repo. | * Commit locally and push that to your repo. | ||||||
| * Send in a pull request based on the above. | * Send in a pull request based on the above. | ||||||
| 
 | 
 | ||||||
|  | Issues with web-platform-tests | ||||||
|  | ------------------------------ | ||||||
|  | 
 | ||||||
|  | If you spot an issue with a test and are not comfortable providing a | ||||||
|  | pull request per above to fix it, please | ||||||
|  | [file a new issue](https://github.com/w3c/web-platform-tests/issues/new). | ||||||
|  | Thank you! | ||||||
|  | 
 | ||||||
| Lint tool | Lint tool | ||||||
| --------- | --------- | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,48 @@ | ||||||
|  | // Step 1.
 | ||||||
|  | test(function() { | ||||||
|  |     assert_throws("TypeMismatchError", function() { | ||||||
|  |         self.crypto.getRandomValues(new Float32Array(6)) | ||||||
|  |     }, "Float32Array") | ||||||
|  |     assert_throws("TypeMismatchError", function() { | ||||||
|  |         self.crypto.getRandomValues(new Float64Array(6)) | ||||||
|  |     }, "Float64Array") | ||||||
|  | 
 | ||||||
|  |     assert_throws("TypeMismatchError", function() { | ||||||
|  |         self.crypto.getRandomValues(new Float32Array(65537)) | ||||||
|  |     }, "Float32Array (too long)") | ||||||
|  |     assert_throws("TypeMismatchError", function() { | ||||||
|  |         self.crypto.getRandomValues(new Float64Array(65537)) | ||||||
|  |     }, "Float64Array (too long)") | ||||||
|  | }, "Float arrays") | ||||||
|  | 
 | ||||||
|  | var arrays = { | ||||||
|  |     'Int8Array': Int8Array, | ||||||
|  |     'Int16Array': Int16Array, | ||||||
|  |     'Int32Array': Int32Array, | ||||||
|  |     'Uint8Array': Uint8Array, | ||||||
|  |     'Uint8ClampedArray': Uint8ClampedArray, | ||||||
|  |     'Uint16Array': Uint16Array, | ||||||
|  |     'Uint32Array': Uint32Array, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | test(function() { | ||||||
|  |     for (var array in arrays) { | ||||||
|  |         assert_equals(self.crypto.getRandomValues(new arrays[array](8)).constructor, | ||||||
|  |                       arrays[array], "crypto.getRandomValues(new " + array + "(8))") | ||||||
|  |     } | ||||||
|  | }, "Integer array") | ||||||
|  | 
 | ||||||
|  | test(function() { | ||||||
|  |     for (var array in arrays) { | ||||||
|  |         var maxlength = 65536 / (arrays[array].BYTES_PER_ELEMENT); | ||||||
|  |         assert_throws("QuotaExceededError", function() { | ||||||
|  |             self.crypto.getRandomValues(new arrays[array](maxlength + 1)) | ||||||
|  |         }, "crypto.getRandomValues length over 65536") | ||||||
|  |     } | ||||||
|  | }, "Large length") | ||||||
|  | 
 | ||||||
|  | test(function() { | ||||||
|  |     for (var array in arrays) { | ||||||
|  |         assert_true(self.crypto.getRandomValues(new arrays[array](0)).length == 0) | ||||||
|  |     } | ||||||
|  | }, "Null arrays") | ||||||
|  | @ -1,50 +0,0 @@ | ||||||
| function run_test() { |  | ||||||
|     // Step 1.
 |  | ||||||
|     test(function() { |  | ||||||
|         assert_throws("TypeMismatchError", function() { |  | ||||||
|             self.crypto.getRandomValues(new Float32Array(6)) |  | ||||||
|         }, "Float32Array") |  | ||||||
|         assert_throws("TypeMismatchError", function() { |  | ||||||
|             self.crypto.getRandomValues(new Float64Array(6)) |  | ||||||
|         }, "Float64Array") |  | ||||||
| 
 |  | ||||||
|         assert_throws("TypeMismatchError", function() { |  | ||||||
|             self.crypto.getRandomValues(new Float32Array(65537)) |  | ||||||
|         }, "Float32Array (too long)") |  | ||||||
|         assert_throws("TypeMismatchError", function() { |  | ||||||
|             self.crypto.getRandomValues(new Float64Array(65537)) |  | ||||||
|         }, "Float64Array (too long)") |  | ||||||
|     }, "Float arrays") |  | ||||||
| 
 |  | ||||||
|     var arrays = { |  | ||||||
|         'Int8Array': Int8Array, |  | ||||||
|         'Int16Array': Int16Array, |  | ||||||
|         'Int32Array': Int32Array, |  | ||||||
|         'Uint8Array': Uint8Array, |  | ||||||
|         'Uint8ClampedArray': Uint8ClampedArray, |  | ||||||
|         'Uint16Array': Uint16Array, |  | ||||||
|         'Uint32Array': Uint32Array, |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     test(function() { |  | ||||||
|         for (var array in arrays) { |  | ||||||
|             assert_equals(self.crypto.getRandomValues(new arrays[array](8)).constructor, |  | ||||||
|                           arrays[array], "crypto.getRandomValues(new " + array + "(8))") |  | ||||||
|         } |  | ||||||
|     }, "Integer array") |  | ||||||
| 
 |  | ||||||
|     test(function() { |  | ||||||
|         for (var array in arrays) { |  | ||||||
|             var maxlength = 65536 / (arrays[array].BYTES_PER_ELEMENT); |  | ||||||
|             assert_throws("QuotaExceededError", function() { |  | ||||||
|                 self.crypto.getRandomValues(new arrays[array](maxlength + 1)) |  | ||||||
|             }, "crypto.getRandomValues length over 65536") |  | ||||||
|         } |  | ||||||
|     }, "Large length") |  | ||||||
| 
 |  | ||||||
|     test(function() { |  | ||||||
|         for (var array in arrays) { |  | ||||||
|             assert_true(self.crypto.getRandomValues(new arrays[array](0)).length == 0) |  | ||||||
|         } |  | ||||||
|     }, "Null arrays") |  | ||||||
| } |  | ||||||
|  | @ -1,4 +0,0 @@ | ||||||
| importScripts("/resources/testharness.js"); |  | ||||||
| importScripts("getRandomValues.js"); |  | ||||||
| run_test(); |  | ||||||
| done(); |  | ||||||
|  | @ -1,12 +0,0 @@ | ||||||
| <!DOCTYPE HTML> |  | ||||||
| <meta charset=utf-8> |  | ||||||
| <title>WebCryptoAPI: getRandomValues()</title> |  | ||||||
| <link rel="author" title="Sunil Yoo" href="mailto:usuanday83@gmail.com"> |  | ||||||
| <link rel="help" href="https://dvcs.w3.org/hg/webcrypto-api/raw-file/tip/spec/Overview.html#dfn-Crypto-method-getRandomValues"> |  | ||||||
| <script src="/resources/testharness.js"></script> |  | ||||||
| <script src="/resources/testharnessreport.js"></script> |  | ||||||
| <script src="getRandomValues.js"></script> |  | ||||||
| <div id="log"></div> |  | ||||||
| <script> |  | ||||||
| run_test(); |  | ||||||
| </script> |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| <!doctype html> | <!doctype html> | ||||||
|  | <meta charset=utf-8> | ||||||
| <title>DOMException-throwing tests</title> | <title>DOMException-throwing tests</title> | ||||||
| <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name> | <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name> | ||||||
| <div id=log></div> | <div id=log></div> | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ test(() => { | ||||||
|   const client = new XMLHttpRequest |   const client = new XMLHttpRequest | ||||||
|   client.open("GET", "resources/header-content-length.asis", false) |   client.open("GET", "resources/header-content-length.asis", false) | ||||||
|   client.send() |   client.send() | ||||||
|   assert_equals(client.getAllResponseHeaders(), "CONTENT-LENGTH: 0\r\n") |   assert_equals(client.getAllResponseHeaders(), "content-length: 0\r\n") | ||||||
| }) | }) | ||||||
| test(() => { | test(() => { | ||||||
|   const client = new XMLHttpRequest |   const client = new XMLHttpRequest | ||||||
|  | @ -17,11 +17,11 @@ test(() => { | ||||||
|   client.setRequestHeader("content-TYPE", "x/x") |   client.setRequestHeader("content-TYPE", "x/x") | ||||||
|   client.send() |   client.send() | ||||||
|   assert_regexp_match(client.responseText, /content-TYPE/) |   assert_regexp_match(client.responseText, /content-TYPE/) | ||||||
|   assert_regexp_match(client.responseText, /THIS-IS-A-TEST: 1,/) |   assert_regexp_match(client.responseText, /THIS-IS-A-TEST: 1, 2/) | ||||||
| }) | }) | ||||||
| promise_test(() => { | promise_test(() => { | ||||||
|   return fetch("resources/echo-headers.py", {headers: [["THIS-is-A-test", 1], ["THIS-IS-A-TEST", 2]] }).then(res => res.text()).then(body => { |   return fetch("resources/echo-headers.py", {headers: [["THIS-is-A-test", 1], ["THIS-IS-A-TEST", 2]] }).then(res => res.text()).then(body => { | ||||||
|     assert_regexp_match(body, /THIS-is-A-test: 1/) |     assert_regexp_match(body, /THIS-is-A-test: 1, 2/) | ||||||
|   }) |   }) | ||||||
| }) | }) | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
|  | @ -0,0 +1,56 @@ | ||||||
|  | <!doctype html> | ||||||
|  | <title>XMLHttpRequest: open() during abort event - abort() called from upload.onloadstart</title> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | <div id="log"></div> | ||||||
|  | <script> | ||||||
|  | async_test(t => { | ||||||
|  |   let client = new XMLHttpRequest(), | ||||||
|  |       log = [], | ||||||
|  |       lastTest = false, | ||||||
|  |       expected = [ | ||||||
|  |         'readyState before abort() 1', | ||||||
|  |         "upload.onabort - before open() 4", | ||||||
|  |         "readyState after open() 1", | ||||||
|  |         "client.onabort 1", | ||||||
|  |         "client.onloadend 1", | ||||||
|  |         "readyState after abort() 1", | ||||||
|  |         "client.onload 4", | ||||||
|  |         "client.onloadend 4" | ||||||
|  |       ] | ||||||
|  | 
 | ||||||
|  |   client.upload.onloadstart = t.step_func(() => { | ||||||
|  |     log.push('readyState before abort() '+client.readyState) | ||||||
|  |     client.abort() | ||||||
|  |     log.push('readyState after abort() '+client.readyState) | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   client.upload.onabort = t.step_func(() => { | ||||||
|  |     log.push('upload.onabort - before open() ' + client.readyState) | ||||||
|  |     client.open("GET", "resources/content.py") | ||||||
|  |     log.push('readyState after open() ' + client.readyState) | ||||||
|  |     client.send(null) | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   client.onabort = t.step_func(() => { | ||||||
|  |     // happens immediately after all of upload.onabort, so readyState is 1 | ||||||
|  |     log.push('client.onabort ' + client.readyState) | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   client.onloadend = t.step_func(() => { | ||||||
|  |     log.push('client.onloadend ' + client.readyState) | ||||||
|  |     if(lastTest) { | ||||||
|  |       assert_array_equals(log, expected) | ||||||
|  |       t.done() | ||||||
|  |     } | ||||||
|  |     lastTest = true | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   client.onload = t.step_func(() => { | ||||||
|  |     log.push('client.onload ' + client.readyState) | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   client.open("POST", "resources/content.py") | ||||||
|  |   client.send("non-empty") | ||||||
|  | }) | ||||||
|  | </script> | ||||||
|  | @ -0,0 +1,64 @@ | ||||||
|  | <!doctype html> | ||||||
|  | <title>XMLHttpRequest: open() during abort processing - abort() called from onloadstart</title> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | <div id="log"></div> | ||||||
|  | <script> | ||||||
|  | async_test(t => { | ||||||
|  |   let client = new XMLHttpRequest(), | ||||||
|  |       test_state = 1, | ||||||
|  |       log = [], | ||||||
|  |       expected = [ | ||||||
|  |         "onloadstart readyState before abort() 1", | ||||||
|  |         "onreadystatechange readyState before open() 4", | ||||||
|  |         "onreadystatechange readyState after open() 1", | ||||||
|  |         "onloadstart readyState 1", | ||||||
|  |         "upload.onabort 1", | ||||||
|  |         "upload.onloadend 1", | ||||||
|  |         "client.onabort 1", | ||||||
|  |         "readyState after abort() 1", | ||||||
|  |         "client.onload 4" | ||||||
|  |       ] | ||||||
|  | 
 | ||||||
|  |   client.onreadystatechange = t.step_func(() => { | ||||||
|  |     if(test_state === 2){ | ||||||
|  |       test_state = 3 | ||||||
|  |       log.push('onreadystatechange readyState before open() ' + client.readyState) | ||||||
|  |       client.open("GET", "resources/content.py") | ||||||
|  |       log.push('onreadystatechange readyState after open() ' + client.readyState) | ||||||
|  |       client.send(null) | ||||||
|  |     } | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   client.onloadstart = t.step_func(() => { | ||||||
|  |     if(test_state === 1){ | ||||||
|  |       test_state = 2 | ||||||
|  |       log.push('onloadstart readyState before abort() ' + client.readyState) | ||||||
|  |       client.abort() | ||||||
|  |       log.push('readyState after abort() ' + client.readyState) | ||||||
|  |     }else{ | ||||||
|  |       log.push('onloadstart readyState ' + client.readyState) | ||||||
|  |     } | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   client.upload.onabort = t.step_func(() => { | ||||||
|  |     log.push('upload.onabort ' + client.readyState) | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   client.onabort = t.step_func(() => { | ||||||
|  |     log.push('client.onabort ' + client.readyState) | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   client.upload.onloadend = t.step_func(() => { | ||||||
|  |     log.push('upload.onloadend ' + client.readyState) | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   client.onload = t.step_func_done(() => { | ||||||
|  |     log.push('client.onload ' + client.readyState) | ||||||
|  |     assert_array_equals(log, expected) | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   client.open("POST", "resources/content.py") | ||||||
|  |   client.send('abcd') | ||||||
|  | }) | ||||||
|  | </script> | ||||||
|  | @ -5,15 +5,14 @@ | ||||||
|     <title>XMLHttpRequest: redirected worker scripts, origin and referrer</title> |     <title>XMLHttpRequest: redirected worker scripts, origin and referrer</title> | ||||||
|     <script src="/resources/testharness.js"></script> |     <script src="/resources/testharness.js"></script> | ||||||
|     <script src="/resources/testharnessreport.js"></script> |     <script src="/resources/testharnessreport.js"></script> | ||||||
|     <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::OL[1]/LI[3] following::OL[1]/LI[3]/ol[1]/li[1] following::OL[1]/LI[3]/ol[1]/li[2] following::OL[1]/LI[3]/ol[1]/li[3]" /> |  | ||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
|     <div id="log"></div> |     <div id="log"></div> | ||||||
|     <script type="text/javascript"> |     <script type="text/javascript"> | ||||||
|         var test = async_test() // This "test" does not actually do any assertations. It's just there to have multiple, separate, asyncronous sub-tests. |         var test = async_test() // This "test" does not actually do any assertations. It's just there to have multiple, separate, asyncronous sub-tests. | ||||||
|         var expectations = { |         var expectations = { | ||||||
|             'Referer header': 'referer: '+(location.href.replace(/[^/]*$/, ''))+"resources/workerxhr-origin-referrer.js\n", |             'Referer header': 'Referer: '+(location.href.replace(/[^/]*$/, ''))+"resources/workerxhr-origin-referrer.js\n", | ||||||
|             'Origin header': 'origin: '+location.protocol+'//'+location.hostname+((location.port === "")?"":":"+location.port)+'\n', |             'Origin header': 'Origin: '+location.protocol+'//'+location.hostname+((location.port === "")?"":":"+location.port)+'\n', | ||||||
|             'Request URL test' : (location.href.replace(/[^/]*$/, ''))+'resources/requri.py?full' |             'Request URL test' : (location.href.replace(/[^/]*$/, ''))+'resources/requri.py?full' | ||||||
|         } |         } | ||||||
|         // now start the worker |         // now start the worker | ||||||
|  |  | ||||||
|  | @ -7,14 +7,8 @@ def main(request, response): | ||||||
|     response.headers.set('Access-Control-Allow-Methods', 'GET'); |     response.headers.set('Access-Control-Allow-Methods', 'GET'); | ||||||
|     response.headers.set('Access-Control-Allow-Headers', 'authorization, x-user, x-pass'); |     response.headers.set('Access-Control-Allow-Headers', 'authorization, x-user, x-pass'); | ||||||
|     response.headers.set('Access-Control-Expose-Headers', 'x-challenge, xhr-user, ses-user'); |     response.headers.set('Access-Control-Expose-Headers', 'x-challenge, xhr-user, ses-user'); | ||||||
|     auth = imp.load_source("", os.path.join(os.path.abspath(os.curdir), |     auth = imp.load_source("", os.path.abspath("XMLHttpRequest/resources/authentication.py")) | ||||||
|                                             "XMLHttpRequest", |  | ||||||
|                                             "resources", |  | ||||||
|                                             "authentication.py")) |  | ||||||
|     if request.method == "OPTIONS": |     if request.method == "OPTIONS": | ||||||
|         return "" |         return "" | ||||||
|     else: |     else: | ||||||
|         return auth.main(request, response) |         return auth.main(request, response) | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|  |  | ||||||
|  | @ -3,15 +3,27 @@ def main(request, response): | ||||||
|     match = request.headers.get("If-None-Match", None) |     match = request.headers.get("If-None-Match", None) | ||||||
|     date = request.GET.first("date", "") |     date = request.GET.first("date", "") | ||||||
|     modified = request.headers.get("If-Modified-Since", None) |     modified = request.headers.get("If-Modified-Since", None) | ||||||
|  |     cors = request.GET.first("cors", None) | ||||||
|  | 
 | ||||||
|  |     if request.method == "OPTIONS": | ||||||
|  |         response.headers.set("Access-Control-Allow-Origin", "*") | ||||||
|  |         response.headers.set("Access-Control-Allow-Headers", "IF-NONE-MATCH") | ||||||
|  |         return "" | ||||||
|  | 
 | ||||||
|     if tag: |     if tag: | ||||||
|         response.headers.set("ETag", '"%s"' % tag) |         response.headers.set("ETag", '"%s"' % tag) | ||||||
|     elif date: |     elif date: | ||||||
|         response.headers.set("Last-Modified", date) |         response.headers.set("Last-Modified", date) | ||||||
| 
 | 
 | ||||||
|  |     if cors: | ||||||
|  |         response.headers.set("Access-Control-Allow-Origin", "*") | ||||||
|  | 
 | ||||||
|     if ((match is not None and match == tag) or |     if ((match is not None and match == tag) or | ||||||
|         (modified is not None and modified == date)): |         (modified is not None and modified == date)): | ||||||
|         response.status = (304, "SUPERCOOL") |         response.status = (304, "SUPERCOOL") | ||||||
|         return "" |         return "" | ||||||
|     else: |     else: | ||||||
|  |         if not cors: | ||||||
|  |             response.headers.set("Access-Control-Allow-Origin", "*") | ||||||
|         response.headers.set("Content-Type", "text/plain") |         response.headers.set("Content-Type", "text/plain") | ||||||
|         return "MAYBE NOT" |         return "MAYBE NOT" | ||||||
|  |  | ||||||
|  | @ -11,6 +11,9 @@ def main(request, response): | ||||||
|         delay = int(request.GET.first("delay")) |         delay = int(request.GET.first("delay")) | ||||||
|         time.sleep(delay) |         time.sleep(delay) | ||||||
| 
 | 
 | ||||||
|  |     if "safelist_content_type" in request.GET: | ||||||
|  |         headers.append(("Access-Control-Allow-Headers", "content-type")) | ||||||
|  | 
 | ||||||
|     headers.append(("X-Request-Method", request.method)) |     headers.append(("X-Request-Method", request.method)) | ||||||
|     headers.append(("X-Request-Query", request.url_parts.query if request.url_parts.query else "NO")) |     headers.append(("X-Request-Query", request.url_parts.query if request.url_parts.query else "NO")) | ||||||
|     headers.append(("X-Request-Content-Length", request.headers.get("Content-Length", "NO"))) |     headers.append(("X-Request-Content-Length", request.headers.get("Content-Length", "NO"))) | ||||||
|  |  | ||||||
|  | @ -3,4 +3,5 @@ import time | ||||||
| def main(request, response): | def main(request, response): | ||||||
|     delay = float(request.GET.first("ms", 500)) |     delay = float(request.GET.first("ms", 500)) | ||||||
|     time.sleep(delay / 1E3); |     time.sleep(delay / 1E3); | ||||||
|     return [("Content-type", "text/plain")], "TEST_DELAY" | 
 | ||||||
|  |     return [("Access-Control-Allow-Origin", "*"), ("Access-Control-Allow-Methods", "YO"), ("Content-type", "text/plain")], "TEST_DELAY" | ||||||
|  |  | ||||||
|  | @ -1,8 +1,14 @@ | ||||||
|  | import time | ||||||
|  | 
 | ||||||
| def main(request, response): | def main(request, response): | ||||||
|     code = int(request.GET.first("code", 302)) |     code = int(request.GET.first("code", 302)) | ||||||
|     location = request.GET.first("location", request.url_parts.path +"?followed") |     location = request.GET.first("location", request.url_parts.path +"?followed") | ||||||
| 
 | 
 | ||||||
|     if request.url.endswith("?followed"): |     if "delay" in request.GET: | ||||||
|  |         delay = float(request.GET.first("delay")) | ||||||
|  |         time.sleep(delay / 1E3); | ||||||
|  | 
 | ||||||
|  |     if "followed" in request.GET: | ||||||
|         return [("Content:Type", "text/plain")], "MAGIC HAPPENED" |         return [("Content:Type", "text/plain")], "MAGIC HAPPENED" | ||||||
|     else: |     else: | ||||||
|         return (code, "WEBSRT MARKETING"), [("Location", location)], "TEST" |         return (code, "WEBSRT MARKETING"), [("Location", location)], "TEST" | ||||||
|  |  | ||||||
|  | @ -5,15 +5,11 @@ | ||||||
|     <script src="/resources/testharness.js"></script> |     <script src="/resources/testharness.js"></script> | ||||||
|     <script src="/resources/testharnessreport.js"></script> |     <script src="/resources/testharnessreport.js"></script> | ||||||
|     <script src="/common/utils.js"></script> |     <script src="/common/utils.js"></script> | ||||||
|     <!-- These spec references do not make much sense simply because the spec doesn't say very much about this.. --> |  | ||||||
|     <link rel="help" href="https://xhr.spec.whatwg.org/#the-setrequestheader()-method" data-tested-assertations="following::ol[1]/li[6]" /> |  | ||||||
|     <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::code[contains(@title,'http-authorization')]/.." /> |  | ||||||
|   </head> |   </head> | ||||||
|   <body> |   <body> | ||||||
|     <div id="log"></div> |     <div id="log"></div> | ||||||
|     <script> |     <script> | ||||||
|       var test = async_test() |       async_test(test => { | ||||||
|       test.step(function() { |  | ||||||
|         var client = new XMLHttpRequest(), |         var client = new XMLHttpRequest(), | ||||||
|             urlstart = location.host + location.pathname.replace(/\/[^\/]*$/, '/'), |             urlstart = location.host + location.pathname.replace(/\/[^\/]*$/, '/'), | ||||||
|             user = token() |             user = token() | ||||||
|  | @ -22,15 +18,11 @@ | ||||||
|         client.setRequestHeader("x-user", user) |         client.setRequestHeader("x-user", user) | ||||||
|         client.setRequestHeader("x-pass", 'pass') |         client.setRequestHeader("x-pass", 'pass') | ||||||
|         client.setRequestHeader('Authorization', 'Basic ' + btoa(user + ":pass")) |         client.setRequestHeader('Authorization', 'Basic ' + btoa(user + ":pass")) | ||||||
|         client.onreadystatechange = function () { |         client.onload = test.step_func_done(() => { | ||||||
|           if (client.readyState < 4) {return} |             assert_equals(client.responseText, user + '\npass', 'responseText should contain the right user and password') | ||||||
|           test.step( function () { |  | ||||||
|             assert_true(client.responseText == (user + '\npass'), 'responseText should contain the right user and password') |  | ||||||
|             assert_equals(client.status, 200) |             assert_equals(client.status, 200) | ||||||
|             assert_equals(client.getResponseHeader('x-challenge'), 'DID-NOT') |             assert_equals(client.getResponseHeader('x-challenge'), 'DID-NOT') | ||||||
|             test.done() |         }) | ||||||
|           } ) |  | ||||||
|         } |  | ||||||
|         client.send(null) |         client.send(null) | ||||||
|       }) |       }) | ||||||
|     </script> |     </script> | ||||||
|  |  | ||||||
|  | @ -0,0 +1,42 @@ | ||||||
|  | <!doctype html> | ||||||
|  | <title>XMLHttpRequest: send() - conditional cross-origin requests</title> | ||||||
|  | <script src=/resources/testharness.js></script> | ||||||
|  | <script src=/resources/testharnessreport.js></script> | ||||||
|  | <script src=/cors/support.js?pipe=sub></script> | ||||||
|  | <div id=log></div> | ||||||
|  | <script> | ||||||
|  | function request(withCORS, desc) { | ||||||
|  |   async_test(t => { | ||||||
|  |     const client = new XMLHttpRequest, | ||||||
|  |           identifier = Math.random(), | ||||||
|  |           cors = withCORS ? "&cors=yes" : "", | ||||||
|  |           url = CROSSDOMAIN + "resources/conditional.py?tag=" + identifier + cors | ||||||
|  |     client.onload = t.step_func(() => { | ||||||
|  |       assert_equals(client.status, 200) | ||||||
|  |       assert_equals(client.statusText, "OK") | ||||||
|  |       assert_equals(client.responseText, "MAYBE NOT") | ||||||
|  | 
 | ||||||
|  |       if(withCORS) { | ||||||
|  |         client.onload = t.step_func_done(() => { | ||||||
|  |           assert_equals(client.status, 304) | ||||||
|  |           assert_equals(client.statusText, "SUPERCOOL") | ||||||
|  |           assert_equals(client.responseText, "") | ||||||
|  |         }) | ||||||
|  |       } else { | ||||||
|  |         client.onload = null | ||||||
|  |         client.onerror = t.step_func_done(() => { | ||||||
|  |           assert_equals(client.status, 0) | ||||||
|  |           assert_equals(client.statusText, "") | ||||||
|  |         }) | ||||||
|  |       } | ||||||
|  |       client.open("GET", url) | ||||||
|  |       client.setRequestHeader("If-None-Match", identifier) | ||||||
|  |       client.send() | ||||||
|  |     }) | ||||||
|  |     client.open("GET", url) | ||||||
|  |     client.send() | ||||||
|  |   }, desc) | ||||||
|  | } | ||||||
|  | request(false, "304 without appropriate CORS header") | ||||||
|  | request(true, "304 with appropriate CORS header") | ||||||
|  | </script> | ||||||
|  | @ -1,26 +1,26 @@ | ||||||
| <!doctype html> | <!doctype html> | ||||||
| <html> | <title>XMLHttpRequest: send() - Document with serialization errors</title> | ||||||
|   <head> | <script src="/resources/testharness.js"></script> | ||||||
|     <title>XMLHttpRequest: send() - unserializable Document</title> | <script src="/resources/testharnessreport.js"></script> | ||||||
|     <script src="/resources/testharness.js"></script> | <div id="log"></div> | ||||||
|     <script src="/resources/testharnessreport.js"></script> | <script> | ||||||
|     <link rel="help" href="https://xhr.spec.whatwg.org/#dom-XMLHttpRequest-send-document" data-tested-assertations="following::p[3]" /> | function serialize(input, output) { | ||||||
|   </head> |   async_test(t => { | ||||||
|   <body> |     const client = new XMLHttpRequest | ||||||
|     <div id="log"></div> |     client.open("POST", "resources/content.py") | ||||||
|     <script> |     client.send(input) | ||||||
|       function request_throws(input) { |     client.onload = t.step_func_done(() => { | ||||||
|         test(function() { |       assert_equals(client.responseText, output) | ||||||
|           var client = new XMLHttpRequest() |     }) | ||||||
|           client.open("POST", "resources/content.py", false) |   }, "Serializing documents through XMLHttpRequest: '" + output + "'") | ||||||
|           assert_throws("InvalidStateError", function() { client.send(input) }) | } | ||||||
|         }) | 
 | ||||||
|       } | var doc = document.implementation.createDocument(null, null, null) | ||||||
|       var doc = document.implementation.createDocument(null, null, null) | serialize(doc, "") | ||||||
|       while(doc.childNodes.length) { | doc.appendChild(doc.createElement("test:test")) | ||||||
|         doc.removeChild(doc.childNodes[0]) | serialize(doc, "<test:test/>") | ||||||
|       } | doc.childNodes[0].setAttribute("test:test", "gee") | ||||||
|       request_throws(doc) | serialize(doc, "<test:test test:test=\"gee\"/>") | ||||||
|     </script> | doc.childNodes[0].setAttribute("x", "\uD800") | ||||||
|   </body> | serialize(doc, "<test:test test:test=\"gee\" x=\"\uFFFD\"/>") | ||||||
| </html> | </script> | ||||||
|  |  | ||||||
|  | @ -5,8 +5,6 @@ | ||||||
|     <script src="/resources/testharness.js"></script> |     <script src="/resources/testharness.js"></script> | ||||||
|     <script src="/resources/testharnessreport.js"></script> |     <script src="/resources/testharnessreport.js"></script> | ||||||
|     <base> |     <base> | ||||||
|     <link rel="help" href="https://xhr.spec.whatwg.org/#cross-origin-request-steps" data-tested-assertations="/following::DL[2]/DT[1] /following::DL[2]/DD[1]" /> |  | ||||||
|     <link rel="help" href="https://xhr.spec.whatwg.org/#cross-origin-request-event-rules" data-tested-assertations="/following::DL[1]/DT[2] /following::DL[1]/DD[2]" /> |  | ||||||
|   </head> |   </head> | ||||||
|   <body> |   <body> | ||||||
|     <div id="log"></div> |     <div id="log"></div> | ||||||
|  | @ -28,6 +26,8 @@ | ||||||
|       url(host_info.HTTP_REMOTE_ORIGIN) |       url(host_info.HTTP_REMOTE_ORIGIN) | ||||||
|       url("javascript:alert('FAIL')") |       url("javascript:alert('FAIL')") | ||||||
|       url("folder.txt") |       url("folder.txt") | ||||||
|  |       url("about:blank") | ||||||
|  |       url("blob:bogusidentifier") | ||||||
|     </script> |     </script> | ||||||
|   </body> |   </body> | ||||||
| </html> | </html> | ||||||
|  |  | ||||||
|  | @ -4,7 +4,6 @@ | ||||||
|     <title>XMLHttpRequest: send() - Redirect to CORS-enabled resource</title> |     <title>XMLHttpRequest: send() - Redirect to CORS-enabled resource</title> | ||||||
|     <script src="/resources/testharness.js"></script> |     <script src="/resources/testharness.js"></script> | ||||||
|     <script src="/resources/testharnessreport.js"></script> |     <script src="/resources/testharnessreport.js"></script> | ||||||
|     <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dl[1]/dt[2] following::dl[1]/dd[2]/ol/li[1] following::dl[1]/dd[2]/ol/li[3]" /> |  | ||||||
|   </head> |   </head> | ||||||
|   <body> |   <body> | ||||||
|     <div id="log"></div> |     <div id="log"></div> | ||||||
|  | @ -13,56 +12,76 @@ | ||||||
|         if (body === null) { |         if (body === null) { | ||||||
|           return { body: "", type: "NO" }; |           return { body: "", type: "NO" }; | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         if (typeof body == "string") { |         if (typeof body == "string") { | ||||||
|           return { body: body, type: "text/plain;charset=UTF-8" }; |           return { body: body, type: "text/plain;charset=UTF-8" }; | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         if (body instanceof Uint8Array) { |         if (body instanceof Uint8Array) { | ||||||
|           var arr = Array.prototype.slice.call(body); |           var arr = Array.prototype.slice.call(body); | ||||||
|           return { body: String.fromCharCode.apply(null, arr), type: "NO" } |           return { body: String.fromCharCode.apply(null, arr), type: "NO" } | ||||||
|         } |         } | ||||||
| 
 |         return { body: "EXTRACT NOT IMPLEMENTED", type: "EXTRACT NOT IMPLEMENTED" } | ||||||
|         return { body: "EXTRACT NOT IMPLEMENTED", |  | ||||||
|                  type: "EXTRACT NOT IMPLEMENTED" } |  | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       function redirect(code, name = code, method = "GET", body = null, setExplicitType = true) { |       function redirect(code, name = code, method = "GET", body = null, explicitType = null, safelistContentType = false) { | ||||||
|         var test = async_test(document.title + " (" + name + ")") |         async_test(t => { | ||||||
|         test.step(function() { |  | ||||||
|           var client = new XMLHttpRequest() |           var client = new XMLHttpRequest() | ||||||
|           client.onreadystatechange = function() { |           client.onreadystatechange = t.step_func(() => { | ||||||
|             test.step(function() { |             if (client.readyState == 4) { | ||||||
|               if (client.readyState == 4) { |               if (explicitType !== "application/x-pony" || safelistContentType) { | ||||||
|                 assert_equals(client.status, 200); |  | ||||||
|                 assert_equals(client.getResponseHeader("x-request-method"), |  | ||||||
|                               method); |  | ||||||
|                 var { body: expectedBody, type: expectedType } = extractBody(body); |                 var { body: expectedBody, type: expectedType } = extractBody(body); | ||||||
|                 if (setExplicitType) { |                 if (explicitType !== null) { | ||||||
|                   expectedType = "application/x-pony"; |                   expectedType = explicitType | ||||||
|                 } |                 } | ||||||
|                 assert_equals(client.getResponseHeader("x-request-content-type"), |                 if (((code === "301" || code === "302") && method === "POST") || code === "303") { | ||||||
|                               expectedType); |                   method = "GET" | ||||||
|                 assert_equals(client.getResponseHeader("x-request-data"), |                   expectedBody = "" | ||||||
|                               expectedBody); |                 } | ||||||
|                 test.done(); |                 assert_equals(client.status, 200); | ||||||
|  |                 assert_equals(client.getResponseHeader("x-request-method"), method); | ||||||
|  |                 assert_equals(client.getResponseHeader("x-request-content-type"), expectedType); | ||||||
|  |                 assert_equals(client.getResponseHeader("x-request-data"), expectedBody); | ||||||
|  |               } else { | ||||||
|  |                 // "application/x-pony" is not safelisted by corsenabled.py -> network error | ||||||
|  |                 assert_equals(client.status, 0) | ||||||
|  |                 assert_equals(client.statusText, "") | ||||||
|  |                 assert_equals(client.responseText, "") | ||||||
|  |                 assert_equals(client.responseXML, null) | ||||||
|               } |               } | ||||||
|             }) |               t.done(); | ||||||
|  |             } | ||||||
|  |           }) | ||||||
|  |           let safelist = "" | ||||||
|  |           if (safelistContentType) { | ||||||
|  |             safelist = "?safelist_content_type" | ||||||
|           } |           } | ||||||
|           client.open(method, "resources/redirect.py?location="+encodeURIComponent("http://www2."+location.host+(location.pathname.replace(/[^\/]+$/, ''))+'resources/corsenabled.py')+"&code=" + code) |           client.open(method, "resources/redirect.py?location="+encodeURIComponent("http://www2."+location.host+(location.pathname.replace(/[^\/]+$/, ''))+'resources/corsenabled.py')+safelist+"&code=" + code) | ||||||
|           if (setExplicitType) { |           if (explicitType !== null) { | ||||||
|             client.setRequestHeader("Content-Type", "application/x-pony") |             client.setRequestHeader("Content-Type", explicitType) | ||||||
|           } |           } | ||||||
|           client.send(body) |           client.send(body) | ||||||
|         }) |         }, document.title + " (" + name + ")") | ||||||
|       } |       } | ||||||
|       redirect("301") |       redirect("301") | ||||||
|  |       redirect("301", "301 GET with explicit Content-Type", "GET", null, "application/x-pony") | ||||||
|  |       redirect("301", "301 GET with explicit Content-Type safelisted", "GET", null, "application/x-pony", true) | ||||||
|       redirect("302") |       redirect("302") | ||||||
|       redirect("303") |       redirect("303") | ||||||
|  |       redirect("303", "303 LALA with string and explicit Content-Type safelisted", "LALA", "test", "application/x-pony", true) | ||||||
|       redirect("307") |       redirect("307") | ||||||
|       redirect("307", "307 post with null", "POST", null, false); |       redirect("307", "307 post with null", "POST", null) | ||||||
|       redirect("307", "307 post with string", "POST", "hello", false); |       redirect("307", "307 post with string", "POST", "hello") | ||||||
|       redirect("307", "307 post with typed array", "POST", new Uint8Array([65, 66, 67]), false); |       redirect("307", "307 post with typed array", "POST", new Uint8Array([65, 66, 67])) | ||||||
|  |       redirect("301", "301 POST with string and explicit Content-Type", "POST", "yoyo", "application/x-pony") | ||||||
|  |       redirect("301", "301 POST with string and explicit Content-Type safelisted", "POST", "yoyo", "application/x-pony", true) | ||||||
|  |       redirect("302", "302 POST with string and explicit Content-Type", "POST", "yoyo", "application/x-pony") | ||||||
|  |       redirect("307", "307 POST with string and explicit Content-Type", "POST", "yoyo", "application/x-pony") | ||||||
|  |       redirect("307", "307 FOO with string and explicit Content-Type", "FOO", "yoyo", "application/x-pony") | ||||||
|  |       redirect("308", "308 POST with string and explicit Content-Type", "POST", "yoyo", "application/x-pony") | ||||||
|  |       redirect("308", "308 FOO with string and explicit Content-Type", "FOO", "yoyo", "application/x-pony") | ||||||
|  |       redirect("308", "308 FOO with string and explicit Content-Type text/plain", "FOO", "yoyo", "text/plain") | ||||||
|  |       redirect("308", "308 FOO with string and explicit Content-Type multipart/form-data", "FOO", "yoyo", "multipart/form-data") | ||||||
|  |       redirect("308", "308 FOO with string and explicit Content-Type safelisted", "FOO", "yoyo", "application/thunderstorm", true) | ||||||
|  |       redirect("307", "307 POST with string and explicit Content-Type safelisted", "POST", "yoyo", "application/thunderstorm", true) | ||||||
|     </script> |     </script> | ||||||
|   </body> |   </body> | ||||||
| </html> | </html> | ||||||
|  |  | ||||||
|  | @ -1,9 +1,6 @@ | ||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
| <html> | <html> | ||||||
| <head> | <head> | ||||||
|     <!-- This behaviour is not explicitly spelled out in the spec. |  | ||||||
|     It does say "queue tasks" under the "if the synchronous flag is unset" header in point 10 of the "send" algorithm.. --> |  | ||||||
|     <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following-sibling::ol/li[10]/dl/dd/dl/dd[2]/p[3]" /> |  | ||||||
|     <script src="/resources/testharness.js"></script> |     <script src="/resources/testharness.js"></script> | ||||||
|     <script src="/resources/testharnessreport.js"></script> |     <script src="/resources/testharnessreport.js"></script> | ||||||
|     <title>XMLHttpRequest: sync requests should block events on pending async requests</title> |     <title>XMLHttpRequest: sync requests should block events on pending async requests</title> | ||||||
|  | @ -22,7 +19,7 @@ | ||||||
|         { |         { | ||||||
|             var xhr_async = new XMLHttpRequest() |             var xhr_async = new XMLHttpRequest() | ||||||
|             xhr_async.open('GET', 'resources/delay.py?ms=1000', true) // first launch an async request, completes in 1 second |             xhr_async.open('GET', 'resources/delay.py?ms=1000', true) // first launch an async request, completes in 1 second | ||||||
|             xhr_async.onreadystatechange = t.step_func(() => { |             xhr_async.onreadystatechange = test.step_func(() => { | ||||||
|                 actual.push('async ' + xhr_async.readyState) |                 actual.push('async ' + xhr_async.readyState) | ||||||
|                 if(xhr_async.readyState === 4 && actual.indexOf('sync 4')>-1){ |                 if(xhr_async.readyState === 4 && actual.indexOf('sync 4')>-1){ | ||||||
|                     VerifyResult() |                     VerifyResult() | ||||||
|  | @ -33,7 +30,7 @@ | ||||||
|             test.step_timeout(() => { |             test.step_timeout(() => { | ||||||
|                 var xhr_sync = new XMLHttpRequest(); |                 var xhr_sync = new XMLHttpRequest(); | ||||||
|                 xhr_sync.open('GET', 'resources/delay.py?ms=2000', false) // here's a sync request that will take 2 seconds to finish |                 xhr_sync.open('GET', 'resources/delay.py?ms=2000', false) // here's a sync request that will take 2 seconds to finish | ||||||
|                 xhr_sync.onreadystatechange = t.step_func(() => { |                 xhr_sync.onreadystatechange = test.step_func(() => { | ||||||
|                     actual.push('sync ' + xhr_sync.readyState) |                     actual.push('sync ' + xhr_sync.readyState) | ||||||
|                     if(xhr_sync.readyState === 4 && actual.indexOf('async 4')>-1){ |                     if(xhr_sync.readyState === 4 && actual.indexOf('async 4')>-1){ | ||||||
|                         VerifyResult() |                         VerifyResult() | ||||||
|  |  | ||||||
|  | @ -15,7 +15,6 @@ function encode(n) { | ||||||
|   return "%" + (s.length === 2 ? s : '0' + s); |   return "%" + (s.length === 2 ? s : '0' + s); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function run_test() { |  | ||||||
|   var tests = []; |   var tests = []; | ||||||
|   var overall_test = async_test("Overall fetch with URLSearchParams"); |   var overall_test = async_test("Overall fetch with URLSearchParams"); | ||||||
|   for (var i = 0; i < NUM_TESTS; i++) { |   for (var i = 0; i < NUM_TESTS; i++) { | ||||||
|  | @ -45,4 +44,3 @@ function run_test() { | ||||||
|     usp.append("a" + i, String.fromCharCode(i)); |     usp.append("a" + i, String.fromCharCode(i)); | ||||||
|   } |   } | ||||||
|   x.send(usp) |   x.send(usp) | ||||||
| } |  | ||||||
|  | @ -1,10 +0,0 @@ | ||||||
| <!DOCTYPE html> |  | ||||||
| <meta charset=utf-8> |  | ||||||
| <title>XMLHttpRequest.send(URLSearchParams)</title> |  | ||||||
| <script src="/resources/testharness.js"></script> |  | ||||||
| <script src="/resources/testharnessreport.js"></script> |  | ||||||
| <script src="send-usp.js"></script> |  | ||||||
| <div id="log"></div> |  | ||||||
| <script> |  | ||||||
| run_test(); |  | ||||||
| </script> |  | ||||||
|  | @ -1,4 +0,0 @@ | ||||||
| importScripts("/resources/testharness.js"); |  | ||||||
| importScripts("send-usp.js"); |  | ||||||
| run_test(); |  | ||||||
| done(); |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| <title>XMLHttpRequest: template element parsing</title> | <title>XMLHttpRequest: template element parsing</title> | ||||||
| <script src=/resources/testharness.js></script> | <script src=/resources/testharness.js></script> | ||||||
| <script src=/resources/testharnessreport.js></script> | <script src=/resources/testharnessreport.js></script> | ||||||
| <div id=log> | <div id=log></div> | ||||||
| <script> | <script> | ||||||
| async_test(t => { | async_test(t => { | ||||||
|   const client = new XMLHttpRequest |   const client = new XMLHttpRequest | ||||||
|  |  | ||||||
|  | @ -0,0 +1,29 @@ | ||||||
|  | <!doctype html> | ||||||
|  | <title>XMLHttpRequest: timeout, redirects, and CORS preflights</title> | ||||||
|  | <script src=/resources/testharness.js></script> | ||||||
|  | <script src=/resources/testharnessreport.js></script> | ||||||
|  | <script src=/common/get-host-info.sub.js></script> | ||||||
|  | <div id=log></div> | ||||||
|  | <script> | ||||||
|  | async_test(t => { | ||||||
|  |   const client = new XMLHttpRequest | ||||||
|  |   client.open("GET", "resources/redirect.py?delay=500&location=delay.py") // 500 + 500 = 1000 | ||||||
|  |   client.timeout = 1000 | ||||||
|  |   client.send() | ||||||
|  |   client.ontimeout = t.step_func_done(() => { | ||||||
|  |     assert_equals(client.readyState, 4) | ||||||
|  |   }) | ||||||
|  |   client.onload = t.unreached_func("load event fired") | ||||||
|  | }, "Redirects should not reset the timer") | ||||||
|  | 
 | ||||||
|  | async_test(t => { | ||||||
|  |   const client = new XMLHttpRequest | ||||||
|  |   client.open("YO", get_host_info().HTTP_REMOTE_ORIGIN + "/XMLHttpRequest/resources/delay.py") | ||||||
|  |   client.timeout = 1000 | ||||||
|  |   client.send() | ||||||
|  |   client.ontimeout = t.step_func_done(() => { | ||||||
|  |     assert_equals(client.readyState, 4) | ||||||
|  |   }) | ||||||
|  |   client.onload = t.unreached_func("load event fired") | ||||||
|  | }, "CORS preflights should not reset the timer") | ||||||
|  | </script> | ||||||
							
								
								
									
										2
									
								
								testing/web-platform/tests/background-fetch/OWNERS
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								testing/web-platform/tests/background-fetch/OWNERS
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | ||||||
|  | @beverloo | ||||||
|  | @jakearchibald | ||||||
|  | @ -0,0 +1,15 @@ | ||||||
|  | <!doctype html> | ||||||
|  | <meta charset="utf-8"> | ||||||
|  | <title>Background Fetch API IDL tests</title> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | <script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script> | ||||||
|  | 
 | ||||||
|  | <h1>idlharness test</h1> | ||||||
|  | <p>This test validates the WebIDL included in the Background Fetch API (Service Workers).</p> | ||||||
|  | 
 | ||||||
|  | <script> | ||||||
|  | 'use strict'; | ||||||
|  | 
 | ||||||
|  | service_worker_test('interfaces.worker.js', 'Service Worker-scoped tests.'); | ||||||
|  | </script> | ||||||
							
								
								
									
										26
									
								
								testing/web-platform/tests/background-fetch/interfaces.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								testing/web-platform/tests/background-fetch/interfaces.html
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | ||||||
|  | <!doctype html> | ||||||
|  | <meta charset="utf-8"> | ||||||
|  | <title>Background Fetch API IDL tests</title> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | <script src="/resources/WebIDLParser.js"></script> | ||||||
|  | <script src="/resources/idlharness.js"></script> | ||||||
|  | 
 | ||||||
|  | <h1>idlharness test</h1> | ||||||
|  | <p>This test validates the WebIDL included in the Background Fetch API (Documents).</p> | ||||||
|  | 
 | ||||||
|  | <script> | ||||||
|  | 'use strict'; | ||||||
|  | 
 | ||||||
|  | promise_test(function() { | ||||||
|  |   return fetch('interfaces.idl') | ||||||
|  |     .then(response => response.text()) | ||||||
|  |     .then(idls => { | ||||||
|  |       var idlArray = new IdlArray(); | ||||||
|  |       idlArray.add_untested_idls('interface ServiceWorkerRegistration {};'); | ||||||
|  |       idlArray.add_untested_idls('[Exposed=ServiceWorker] interface ServiceWorkerGlobalScope {};'); | ||||||
|  |       idlArray.add_idls(idls); | ||||||
|  |       idlArray.test(); | ||||||
|  |     }); | ||||||
|  | }, 'Exposed interfaces in a Document.'); | ||||||
|  | </script> | ||||||
							
								
								
									
										115
									
								
								testing/web-platform/tests/background-fetch/interfaces.idl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								testing/web-platform/tests/background-fetch/interfaces.idl
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,115 @@ | ||||||
|  | // 3.1. Extensions to ServiceWorkerRegistration | ||||||
|  | 
 | ||||||
|  | partial interface ServiceWorkerRegistration { | ||||||
|  |   readonly attribute BackgroundFetchManager backgroundFetch; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // 3.2. BackgroundFetchManager | ||||||
|  | 
 | ||||||
|  | [Exposed=(Window,Worker)] | ||||||
|  | interface BackgroundFetchManager { | ||||||
|  |   Promise<BackgroundFetchRegistration> fetch(DOMString tag, (RequestInfo or sequence<RequestInfo>) requests, optional BackgroundFetchOptions options); | ||||||
|  |   Promise<BackgroundFetchRegistration?> get(DOMString tag); | ||||||
|  |   Promise<FrozenArray<DOMString>> getTags(); | ||||||
|  |   // TODO: in future this should become an async iterator for BackgroundFetchRegistration objects | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | dictionary BackgroundFetchOptions { | ||||||
|  |   sequence<IconDefinition> icons; | ||||||
|  |   DOMString title; | ||||||
|  |   long totalDownloadSize; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // This is taken from https://w3c.github.io/manifest/#icons-member. | ||||||
|  | // This definition should probably be moved somewhere more general. | ||||||
|  | dictionary IconDefinition { | ||||||
|  |   DOMString src; | ||||||
|  |   DOMString sizes; | ||||||
|  |   DOMString type; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // 3.3. BackgroundFetchRegistration | ||||||
|  | 
 | ||||||
|  | [Exposed=(Window,Worker)] | ||||||
|  | interface BackgroundFetchRegistration { | ||||||
|  |   readonly attribute DOMString tag; | ||||||
|  |   readonly attribute FrozenArray<IconDefinition> icons; | ||||||
|  |   readonly attribute long totalDownloadSize; | ||||||
|  |   readonly attribute DOMString title; | ||||||
|  |   readonly attribute FrozenArray<BackgroundFetchActiveFetches> fetches; | ||||||
|  | 
 | ||||||
|  |   void abort(); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | [Exposed=(Window,Worker)] | ||||||
|  | interface BackgroundFetchFetches { | ||||||
|  |   readonly attribute Request request; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | [Exposed=(Window,Worker)] | ||||||
|  | interface BackgroundFetchActiveFetches : BackgroundFetchFetches { | ||||||
|  |   readonly attribute Promise<Response> responseReady; | ||||||
|  |   // TODO: this will include fetch controller/observer objects | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // 3.4. Events | ||||||
|  | 
 | ||||||
|  | partial interface ServiceWorkerGlobalScope { | ||||||
|  |   attribute EventHandler onbackgroundfetched; | ||||||
|  |   attribute EventHandler onbackgroundfetchfail; | ||||||
|  |   attribute EventHandler onbackgroundfetchabort; | ||||||
|  |   attribute EventHandler onbackgroundfetchclick; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // 3.4.1. BackgroundFetchEvent | ||||||
|  | 
 | ||||||
|  | [Constructor(DOMString type, BackgroundFetchEventInit init), Exposed=ServiceWorker] | ||||||
|  | interface BackgroundFetchEvent : ExtendableEvent { | ||||||
|  |   readonly attribute DOMString tag; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | dictionary BackgroundFetchEventInit : ExtendableEventInit { | ||||||
|  |   required DOMString tag; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // 3.4.2. BackgroundFetchEndEvent | ||||||
|  | 
 | ||||||
|  | [Constructor(DOMString type, BackgroundFetchEndEventInit init), Exposed=ServiceWorker] | ||||||
|  | interface BackgroundFetchEndEvent : BackgroundFetchEvent { | ||||||
|  |   readonly attribute FrozenArray<BackgroundFetchSettledFetches> completeFetches; | ||||||
|  | 
 | ||||||
|  |   Promise<void> updateUI(DOMString title); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | dictionary BackgroundFetchEndEventInit : BackgroundFetchEventInit { | ||||||
|  |   required BackgroundFetchSettledFetches completeFetches; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | [Exposed=ServiceWorker] | ||||||
|  | interface BackgroundFetchSettledFetches : BackgroundFetchFetches { | ||||||
|  |   readonly attribute Response? response; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // 3.4.3. BackgroundFetchFailEvent | ||||||
|  | 
 | ||||||
|  | [Constructor(DOMString type, BackgroundFetchEndEventInit init), Exposed=ServiceWorker] | ||||||
|  | interface BackgroundFetchFailEvent : BackgroundFetchEndEvent { | ||||||
|  |   readonly attribute FrozenArray<BackgroundFetchSettledFetches> failedFetches; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | dictionary BackgroundFetchFailEventInit : BackgroundFetchEndEventInit { | ||||||
|  |   required BackgroundFetchSettledFetches failedFetches; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // 3.4.4. BackgroundFetchClickEvent | ||||||
|  | 
 | ||||||
|  | [Constructor(DOMString type, BackgroundFetchEndEventInit init), Exposed=ServiceWorker] | ||||||
|  | interface BackgroundFetchClickEvent : BackgroundFetchEvent { | ||||||
|  |   readonly attribute BackgroundFetchState state; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | dictionary BackgroundFetchClickEventInit : BackgroundFetchEventInit { | ||||||
|  |   required BackgroundFetchState state; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum BackgroundFetchState { "pending", "succeeded", "failed" }; | ||||||
|  | @ -0,0 +1,16 @@ | ||||||
|  | 'use strict'; | ||||||
|  | 
 | ||||||
|  | importScripts('/resources/testharness.js'); | ||||||
|  | importScripts('/resources/WebIDLParser.js', '/resources/idlharness.js'); | ||||||
|  | 
 | ||||||
|  | promise_test(function() { | ||||||
|  |   return fetch('interfaces.idl') | ||||||
|  |     .then(response => response.text()) | ||||||
|  |     .then(idls => { | ||||||
|  |       var idlArray = new IdlArray(); | ||||||
|  |       idlArray.add_untested_idls('interface ServiceWorkerRegistration {};'); | ||||||
|  |       idlArray.add_untested_idls('[Exposed=ServiceWorker] interface ServiceWorkerGlobalScope {};'); | ||||||
|  |       idlArray.add_idls(idls); | ||||||
|  |       idlArray.test(); | ||||||
|  |     }); | ||||||
|  | }, 'Exposed interfaces in a Service Worker.'); | ||||||
|  | @ -1,147 +0,0 @@ | ||||||
| 'use strict'; |  | ||||||
| 
 |  | ||||||
| // Bluetooth UUID constants:
 |  | ||||||
| // Services:
 |  | ||||||
| var blocklist_test_service_uuid = "611c954a-263b-4f4a-aab6-01ddb953f985"; |  | ||||||
| var request_disconnection_service_uuid = "01d7d889-7451-419f-aeb8-d65e7b9277af"; |  | ||||||
| // Characteristics:
 |  | ||||||
| var blocklist_exclude_reads_characteristic_uuid = "bad1c9a2-9a5b-4015-8b60-1579bbbf2135"; |  | ||||||
| var request_disconnection_characteristic_uuid = "01d7d88a-7451-419f-aeb8-d65e7b9277af"; |  | ||||||
| // Descriptors:
 |  | ||||||
| var blocklist_exclude_reads_descriptor_uuid = "aaaaaaaa-aaaa-1181-0510-810819516110"; |  | ||||||
| var blocklist_descriptor_uuid = "07711111-6104-0970-7011-1107105110aaa"; |  | ||||||
| var characteristic_user_description_uuid = "00002901-0000-1000-8000-00805f9b34fb"; |  | ||||||
| 
 |  | ||||||
| // Bluetooth Adapter types:
 |  | ||||||
| var adapter_type = { |  | ||||||
|     not_present: 'NotPresentAdapter', |  | ||||||
|     not_powered: 'NotPoweredAdapter', |  | ||||||
|     empty: 'EmptyAdapter', |  | ||||||
|     heart_rate: 'HeartRateAdapter', |  | ||||||
|     two_heart_rate: 'TwoHeartRateServicesAdapter', |  | ||||||
|     empty_name_heart_rate: 'EmptyNameHeartRateAdapter', |  | ||||||
|     no_name_heart_rate: 'NoNameHeartRateAdapter', |  | ||||||
|     glucose_heart_rate: 'GlucoseHeartRateAdapter', |  | ||||||
|     unicode_device: 'UnicodeDeviceAdapter', |  | ||||||
|     blocklist: 'BlocklistTestAdapter', |  | ||||||
|     missing_characteristic_heart_rate: 'MissingCharacteristicHeartRateAdapter', |  | ||||||
|     missing_service_heart_rate: 'MissingServiceHeartRateAdapter', |  | ||||||
|     missing_descriptor_heart_rate: 'MissingDescriptorHeartRateAdapter' |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| var mock_device_name = { |  | ||||||
|     heart_rate: 'Heart Rate Device', |  | ||||||
|     glucose: 'Glucose Device' |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| var wrong = { |  | ||||||
|     name: 'wrong_name', |  | ||||||
|     service: 'wrong_service' |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| // Sometimes we need to test that using either the name, alias, or UUID
 |  | ||||||
| // produces the same result. The following objects help us do that.
 |  | ||||||
| var generic_access = { |  | ||||||
|     alias: 0x1800, |  | ||||||
|     name: 'generic_access', |  | ||||||
|     uuid: '00001800-0000-1000-8000-00805f9b34fb' |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| var device_name = { |  | ||||||
|     alias: 0x2a00, |  | ||||||
|     name: 'gap.device_name', |  | ||||||
|     uuid: '00002a00-0000-1000-8000-00805f9b34fb' |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| var reconnection_address = { |  | ||||||
|     alias: 0x2a03, |  | ||||||
|     name: 'gap.reconnection_address', |  | ||||||
|     uuid: '00002a03-0000-1000-8000-00805f9b34fb' |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| var heart_rate = { |  | ||||||
|     alias: 0x180d, |  | ||||||
|     name: 'heart_rate', |  | ||||||
|     uuid: '0000180d-0000-1000-8000-00805f9b34fb' |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| var heart_rate_measurement = { |  | ||||||
|     alias: 0x2a37, |  | ||||||
|     name: 'heart_rate_measurement', |  | ||||||
|     uuid: '00002a37-0000-1000-8000-00805f9b34fb' |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| var body_sensor_location = { |  | ||||||
|     alias: 0x2a38, |  | ||||||
|     name: 'body_sensor_location', |  | ||||||
|     uuid: '00002a38-0000-1000-8000-00805f9b34fb' |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| var glucose = { |  | ||||||
|     alias: 0x1808, |  | ||||||
|     name: 'glucose', |  | ||||||
|     uuid: '00001808-0000-1000-8000-00805f9b34fb' |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| var battery_service = { |  | ||||||
|     alias: 0x180f, |  | ||||||
|     name: 'battery_service', |  | ||||||
|     uuid: '0000180f-0000-1000-8000-00805f9b34fb' |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| var battery_level = { |  | ||||||
|     alias: 0x2a19, |  | ||||||
|     name: 'battery_level', |  | ||||||
|     uuid: '00002a19-0000-1000-8000-00805f9b34fb' |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| var tx_power = { |  | ||||||
|     alias: 0x1804, |  | ||||||
|     name: 'tx_power', |  | ||||||
|     uuid: '00001804-0000-1000-8000-00805f9b34fb' |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| var human_interface_device = { |  | ||||||
|     alias: 0x1812, |  | ||||||
|     name: 'human_interface_device', |  | ||||||
|     uuid: '00001812-0000-1000-8000-00805f9b34fb' |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| var device_information = { |  | ||||||
|     alias: 0x180a, |  | ||||||
|     name: 'device_information', |  | ||||||
|     uuid: '0000180a-0000-1000-8000-00805f9b34fb' |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| var peripherial_privacy_flag = { |  | ||||||
|     alias: 0x2a02, |  | ||||||
|     name: 'gap.peripheral_privacy_flag', |  | ||||||
|     uuid: '00002a02-0000-1000-8000-00805f9b34fb' |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| var serial_number_string = { |  | ||||||
|     alias: 0x2a25, |  | ||||||
|     name: 'serial_number_string', |  | ||||||
|     uuid: '00002a25-0000-1000-8000-00805f9b34fb' |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| var client_characteristic_configuration = { |  | ||||||
|     alias: 0x2902, |  | ||||||
|     name: 'gatt.client_characteristic_configuration', |  | ||||||
|     uuid: '00002902-0000-1000-8000-00805f9b34fb' |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| var number_of_digitals = { |  | ||||||
|     alias: 0x2909, |  | ||||||
|     name: 'number_of_digitals', |  | ||||||
|     uuid: '00002909-0000-1000-8000-00805f9b34fb' |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| // Helper function for converting strings to an array of bytes.
 |  | ||||||
| function asciiToDecimal(bytestr) { |  | ||||||
|     var result = []; |  | ||||||
|     for(var i = 0; i < bytestr.length; i++) { |  | ||||||
|         result[i] = bytestr.charCodeAt(i) ; |  | ||||||
|     } |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
							
								
								
									
										19
									
								
								testing/web-platform/tests/bluetooth/idl-Bluetooth.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								testing/web-platform/tests/bluetooth/idl-Bluetooth.html
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <title>Bluetooth interface</title> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | <script> | ||||||
|  | 'use strict'; | ||||||
|  | 
 | ||||||
|  | test(() => { | ||||||
|  |   assert_throws(null, () => new Bluetooth(), | ||||||
|  |                 'the constructor should not be callable with "new"'); | ||||||
|  |   assert_throws(null, () => Bluetooth(), | ||||||
|  |                 'the constructor should not be callable'); | ||||||
|  | 
 | ||||||
|  |   // Bluetooth implements BluetoothDiscovery; | ||||||
|  |   assert_true('requestDevice' in navigator.bluetooth); | ||||||
|  |   assert_equals(navigator.bluetooth.requestDevice.length, 0); | ||||||
|  | }, 'Bluetooth IDL test'); | ||||||
|  | 
 | ||||||
|  | </script> | ||||||
|  | @ -311,7 +311,8 @@ def get_git_cmd(repo_path): | ||||||
|     def git(cmd, *args): |     def git(cmd, *args): | ||||||
|         full_cmd = ["git", cmd] + list(args) |         full_cmd = ["git", cmd] + list(args) | ||||||
|         try: |         try: | ||||||
|             return subprocess.check_output(full_cmd, cwd=repo_path, stderr=subprocess.STDOUT) |             logger.debug(" ".join(full_cmd)) | ||||||
|  |             return subprocess.check_output(full_cmd, cwd=repo_path, stderr=subprocess.STDOUT).strip() | ||||||
|         except subprocess.CalledProcessError as e: |         except subprocess.CalledProcessError as e: | ||||||
|             logger.error("Git command exited with status %i" % e.returncode) |             logger.error("Git command exited with status %i" % e.returncode) | ||||||
|             logger.error(e.output) |             logger.error(e.output) | ||||||
|  | @ -363,10 +364,9 @@ class pwd(object): | ||||||
|         self.old_dir = None |         self.old_dir = None | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def fetch_wpt_master(user): | def fetch_wpt(user, *args): | ||||||
|     """Fetch the master branch via git.""" |  | ||||||
|     git = get_git_cmd(wpt_root) |     git = get_git_cmd(wpt_root) | ||||||
|     git("fetch", "https://github.com/%s/web-platform-tests.git" % user, "master:master") |     git("fetch", "https://github.com/%s/web-platform-tests.git" % user, *args) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def get_sha1(): | def get_sha1(): | ||||||
|  | @ -390,12 +390,44 @@ def install_wptrunner(): | ||||||
|     call("pip", "install", wptrunner_root) |     call("pip", "install", wptrunner_root) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def get_files_changed(): | def get_branch_point(user): | ||||||
|  |     git = get_git_cmd(wpt_root) | ||||||
|  |     if os.environ.get("TRAVIS_PULL_REQUEST", "false") != "false": | ||||||
|  |         # This is a PR, so the base branch is in TRAVIS_BRANCH | ||||||
|  |         branch_point = os.environ.get("TRAVIS_COMMIT_RANGE").split(".", 1)[0] | ||||||
|  |         branch_point = git("rev-parse", branch_point) | ||||||
|  |     else: | ||||||
|  |         # Otherwise we aren't on a PR, so we try to find commits that are only in the | ||||||
|  |         # current branch c.f. | ||||||
|  |         # http://stackoverflow.com/questions/13460152/find-first-ancestor-commit-in-another-branch | ||||||
|  |         head = git("rev-parse", "HEAD") | ||||||
|  |         # To do this we need all the commits in the local copy | ||||||
|  |         fetch_wpt(user, "--unshallow", "+refs/heads/*:refs/remotes/origin/*") | ||||||
|  |         not_heads = [item for item in git("rev-parse", "--not", "--all").split("\n") | ||||||
|  |                      if not head in item] | ||||||
|  |         commits = git("rev-list", "HEAD", *not_heads).split("\n") | ||||||
|  |         first_commit = commits[-1] | ||||||
|  |         branch_point = git("rev-parse", first_commit + "^") | ||||||
|  |         # The above can produce a too-early commit if we are e.g. on master and there are | ||||||
|  |         # preceding changes that were rebased and so aren't on any other branch. To avoid | ||||||
|  |         # this issue we check for the later of the above branch point and the merge-base | ||||||
|  |         # with master | ||||||
|  |         merge_base = git("merge-base", "HEAD", "origin/master") | ||||||
|  |         if (branch_point != merge_base and | ||||||
|  |             not git("log", "--oneline", "%s..%s" % (merge_base, branch_point)).strip()): | ||||||
|  |             logger.debug("Using merge-base as the branch point") | ||||||
|  |             branch_point = merge_base | ||||||
|  |         else: | ||||||
|  |             logger.debug("Using first commit on another branch as the branch point") | ||||||
|  | 
 | ||||||
|  |     logger.debug("Branch point from master: %s" % branch_point) | ||||||
|  |     return branch_point | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def get_files_changed(branch_point): | ||||||
|     """Get and return files changed since current branch diverged from master.""" |     """Get and return files changed since current branch diverged from master.""" | ||||||
|     root = os.path.abspath(os.curdir) |     root = os.path.abspath(os.curdir) | ||||||
|     git = get_git_cmd(wpt_root) |     git = get_git_cmd(wpt_root) | ||||||
|     branch_point = git("merge-base", "HEAD", "master").strip() |  | ||||||
|     logger.debug("Branch point from master: %s" % branch_point) |  | ||||||
|     files = git("diff", "--name-only", "-z", "%s.." % branch_point) |     files = git("diff", "--name-only", "-z", "%s.." % branch_point) | ||||||
|     if not files: |     if not files: | ||||||
|         return [] |         return [] | ||||||
|  | @ -557,7 +589,7 @@ def process_results(log, iterations): | ||||||
|     results = handler.results |     results = handler.results | ||||||
|     for test_name, test in results.iteritems(): |     for test_name, test in results.iteritems(): | ||||||
|         if is_inconsistent(test["status"], iterations): |         if is_inconsistent(test["status"], iterations): | ||||||
|             inconsistent.append((test_name, None, test["status"], None)) |             inconsistent.append((test_name, None, test["status"], [])) | ||||||
|         for subtest_name, subtest in test["subtests"].iteritems(): |         for subtest_name, subtest in test["subtests"].iteritems(): | ||||||
|             if is_inconsistent(subtest["status"], iterations): |             if is_inconsistent(subtest["status"], iterations): | ||||||
|                 inconsistent.append((test_name, subtest_name, subtest["status"], subtest["messages"])) |                 inconsistent.append((test_name, subtest_name, subtest["status"], subtest["messages"])) | ||||||
|  | @ -584,7 +616,7 @@ def markdown_adjust(s): | ||||||
|     s = s.replace('\t', u'\\t') |     s = s.replace('\t', u'\\t') | ||||||
|     s = s.replace('\n', u'\\n') |     s = s.replace('\n', u'\\n') | ||||||
|     s = s.replace('\r', u'\\r') |     s = s.replace('\r', u'\\r') | ||||||
|     s = s.replace('`',  u'\\`') |     s = s.replace('`',  u'') | ||||||
|     return s |     return s | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -726,14 +758,16 @@ def main(): | ||||||
|             logger.critical("Unrecognised browser %s" % browser_name) |             logger.critical("Unrecognised browser %s" % browser_name) | ||||||
|             return 1 |             return 1 | ||||||
| 
 | 
 | ||||||
|         fetch_wpt_master(args.user) |         fetch_wpt(args.user, "master:master") | ||||||
| 
 | 
 | ||||||
|         head_sha1 = get_sha1() |         head_sha1 = get_sha1() | ||||||
|         logger.info("Testing web-platform-tests at revision %s" % head_sha1) |         logger.info("Testing web-platform-tests at revision %s" % head_sha1) | ||||||
| 
 | 
 | ||||||
|  |         branch_point = get_branch_point(args.user) | ||||||
|  | 
 | ||||||
|         # For now just pass the whole list of changed files to wptrunner and |         # For now just pass the whole list of changed files to wptrunner and | ||||||
|         # assume that it will run everything that's actually a test |         # assume that it will run everything that's actually a test | ||||||
|         files_changed = get_files_changed() |         files_changed = get_files_changed(branch_point) | ||||||
| 
 | 
 | ||||||
|         if not files_changed: |         if not files_changed: | ||||||
|             logger.info("No files changed") |             logger.info("No files changed") | ||||||
|  |  | ||||||
|  | @ -2,4 +2,3 @@ set -ex | ||||||
| 
 | 
 | ||||||
| ./manifest | ./manifest | ||||||
| ./lint | ./lint | ||||||
| ./diff-manifest.py |  | ||||||
|  |  | ||||||
							
								
								
									
										116
									
								
								testing/web-platform/tests/common/PrefixedLocalStorage.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								testing/web-platform/tests/common/PrefixedLocalStorage.js
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,116 @@ | ||||||
|  | /** | ||||||
|  |  * Supports pseudo-"namespacing" localStorage for a given test | ||||||
|  |  * by generating and using a unique prefix for keys. Why trounce on other | ||||||
|  |  * tests' localStorage items when you can keep it "separated"? | ||||||
|  |  * | ||||||
|  |  * PrefixedLocalStorageTest: Instantiate in testharness.js tests to generate | ||||||
|  |  *   a new unique-ish prefix | ||||||
|  |  * PrefixedLocalStorageResource: Instantiate in supporting test resource | ||||||
|  |  *   files to use/share a prefix generated by a test. | ||||||
|  |  */ | ||||||
|  | var PrefixedLocalStorage = function () { | ||||||
|  |   this.prefix = ''; // Prefix for localStorage keys
 | ||||||
|  |   this.param = 'prefixedLocalStorage'; // Param to use in querystrings
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | PrefixedLocalStorage.prototype.clear = function () { | ||||||
|  |   if (this.prefix === '') { return; } | ||||||
|  |   Object.keys(localStorage).forEach(sKey => { | ||||||
|  |     if (sKey.indexOf(this.prefix) === 0) { | ||||||
|  |       localStorage.removeItem(sKey); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Append/replace prefix parameter and value in URI querystring | ||||||
|  |  * Use to generate URLs to resource files that will share the prefix. | ||||||
|  |  */ | ||||||
|  | PrefixedLocalStorage.prototype.url = function (uri) { | ||||||
|  |   function updateUrlParameter (uri, key, value) { | ||||||
|  |     var i         = uri.indexOf('#'); | ||||||
|  |     var hash      = (i === -1) ? '' : uri.substr(i); | ||||||
|  |     uri           = (i === -1) ? uri : uri.substr(0, i); | ||||||
|  |     var re        = new RegExp(`([?&])${key}=.*?(&|$)`, 'i'); | ||||||
|  |     var separator = uri.indexOf('?') !== -1 ? '&' : '?'; | ||||||
|  |     uri = (uri.match(re)) ? uri.replace(re, `$1${key}=${value}$2`) : | ||||||
|  |       `${uri}${separator}${key}=${value}`; | ||||||
|  |     return uri + hash; | ||||||
|  |   } | ||||||
|  |   return updateUrlParameter(uri, this.param, this.prefix); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | PrefixedLocalStorage.prototype.prefixedKey = function (baseKey) { | ||||||
|  |   return `${this.prefix}${baseKey}`; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | PrefixedLocalStorage.prototype.setItem = function (baseKey, value) { | ||||||
|  |   localStorage.setItem(this.prefixedKey(baseKey), value); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Listen for `storage` events pertaining to a particular key, | ||||||
|  |  * prefixed with this object's prefix. Ignore when value is being set to null | ||||||
|  |  * (i.e. removeItem). | ||||||
|  |  */ | ||||||
|  | PrefixedLocalStorage.prototype.onSet = function (baseKey, fn) { | ||||||
|  |   window.addEventListener('storage', e => { | ||||||
|  |     var match = this.prefixedKey(baseKey); | ||||||
|  |     if (e.newValue !== null && e.key.indexOf(match) === 0) { | ||||||
|  |       fn.call(this, e); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /***************************************************************************** | ||||||
|  |  * Use in a testharnessjs test to generate a new key prefix. | ||||||
|  |  * async_test(t => { | ||||||
|  |  *   var prefixedStorage = new PrefixedLocalStorageTest(); | ||||||
|  |  *   t.add_cleanup(() => prefixedStorage.cleanup()); | ||||||
|  |  *   /... | ||||||
|  |  * }); | ||||||
|  |  */ | ||||||
|  | var PrefixedLocalStorageTest = function () { | ||||||
|  |   PrefixedLocalStorage.call(this); | ||||||
|  |   this.prefix = `${document.location.pathname}-${Math.random()}-${Date.now()}-`; | ||||||
|  | }; | ||||||
|  | PrefixedLocalStorageTest.prototype = Object.create(PrefixedLocalStorage.prototype); | ||||||
|  | PrefixedLocalStorageTest.prototype.constructor = PrefixedLocalStorageTest; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Use in a cleanup function to clear out prefixed entries in localStorage | ||||||
|  |  */ | ||||||
|  | PrefixedLocalStorageTest.prototype.cleanup = function () { | ||||||
|  |   this.setItem('closeAll', 'true'); | ||||||
|  |   this.clear(); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /***************************************************************************** | ||||||
|  |  * Use in test resource files to share a prefix generated by a | ||||||
|  |  * PrefixedLocalStorageTest. Will look in URL querystring for prefix. | ||||||
|  |  * Setting `close_on_cleanup` opt truthy will make this script's window listen | ||||||
|  |  * for storage `closeAll` event from controlling test and close itself. | ||||||
|  |  * | ||||||
|  |  * var PrefixedLocalStorageResource({ close_on_cleanup: true }); | ||||||
|  |  */ | ||||||
|  | var PrefixedLocalStorageResource = function (options) { | ||||||
|  |   PrefixedLocalStorage.call(this); | ||||||
|  |   this.options = Object.assign({}, { | ||||||
|  |     close_on_cleanup: false | ||||||
|  |   }, options || {}); | ||||||
|  |   // Check URL querystring for prefix to use
 | ||||||
|  |   var regex = new RegExp(`[?&]${this.param}(=([^&#]*)|&|#|$)`), | ||||||
|  |     results = regex.exec(document.location.href); | ||||||
|  |   if (results && results[2]) { | ||||||
|  |     this.prefix = results[2]; | ||||||
|  |   } | ||||||
|  |   // Optionally have this window close itself when the PrefixedLocalStorageTest
 | ||||||
|  |   // sets a `closeAll` item.
 | ||||||
|  |   if (this.options.close_on_cleanup) { | ||||||
|  |     this.onSet('closeAll', () => { | ||||||
|  |       window.close(); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | PrefixedLocalStorageResource.prototype = Object.create(PrefixedLocalStorage.prototype); | ||||||
|  | PrefixedLocalStorageResource.prototype.constructor = PrefixedLocalStorageResource; | ||||||
							
								
								
									
										8
									
								
								testing/web-platform/tests/common/domain-setter.sub.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								testing/web-platform/tests/common/domain-setter.sub.html
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <meta charset="utf-8"> | ||||||
|  | <title>A page that will likely be same-origin-domain but not same-origin</title> | ||||||
|  | 
 | ||||||
|  | <script> | ||||||
|  | "use strict"; | ||||||
|  | document.domain = "{{host}}"; | ||||||
|  | </script> | ||||||
|  | @ -0,0 +1,57 @@ | ||||||
|  | self.testSettingImmutablePrototypeToNewValueOnly = | ||||||
|  |   (prefix, target, newValue, newValueString, { isSameOriginDomain }) => { | ||||||
|  |   test(() => { | ||||||
|  |     assert_throws(new TypeError, () => { | ||||||
|  |       Object.setPrototypeOf(target, newValue); | ||||||
|  |     }); | ||||||
|  |   }, `${prefix}: setting the prototype to ${newValueString} via Object.setPrototypeOf should throw a TypeError`); | ||||||
|  | 
 | ||||||
|  |   let dunderProtoError = "SecurityError"; | ||||||
|  |   let dunderProtoErrorName = "\"SecurityError\" DOMException"; | ||||||
|  |   if (isSameOriginDomain) { | ||||||
|  |     dunderProtoError = new TypeError(); | ||||||
|  |     dunderProtoErrorName = "TypeError"; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   test(() => { | ||||||
|  |     assert_throws(dunderProtoError, function() { | ||||||
|  |       target.__proto__ = newValue; | ||||||
|  |     }); | ||||||
|  |   }, `${prefix}: setting the prototype to ${newValueString} via __proto__ should throw a ${dunderProtoErrorName}`); | ||||||
|  | 
 | ||||||
|  |   test(() => { | ||||||
|  |     assert_false(Reflect.setPrototypeOf(target, newValue)); | ||||||
|  |   }, `${prefix}: setting the prototype to ${newValueString} via Reflect.setPrototypeOf should return false`); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | self.testSettingImmutablePrototype = | ||||||
|  |   (prefix, target, originalValue, { isSameOriginDomain }, newValue = {}, newValueString = "an empty object") => { | ||||||
|  |   testSettingImmutablePrototypeToNewValueOnly(prefix, target, newValue, newValueString, { isSameOriginDomain }); | ||||||
|  | 
 | ||||||
|  |   const originalValueString = originalValue === null ? "null" : "its original value"; | ||||||
|  | 
 | ||||||
|  |   test(() => { | ||||||
|  |     assert_equals(Object.getPrototypeOf(target), originalValue); | ||||||
|  |   }, `${prefix}: the prototype must still be ${originalValueString}`); | ||||||
|  | 
 | ||||||
|  |   test(() => { | ||||||
|  |     Object.setPrototypeOf(target, originalValue); | ||||||
|  |   }, `${prefix}: setting the prototype to ${originalValueString} via Object.setPrototypeOf should not throw`); | ||||||
|  | 
 | ||||||
|  |   if (isSameOriginDomain) { | ||||||
|  |     test(() => { | ||||||
|  |       target.__proto__ = originalValue; | ||||||
|  |     }, `${prefix}: setting the prototype to ${originalValueString} via __proto__ should not throw`); | ||||||
|  |   } else { | ||||||
|  |     test(() => { | ||||||
|  |       assert_throws("SecurityError", function() { | ||||||
|  |         target.__proto__ = newValue; | ||||||
|  |       }); | ||||||
|  |     }, `${prefix}: setting the prototype to ${originalValueString} via __proto__ should throw a "SecurityError" since ` + | ||||||
|  |        `it ends up in CrossOriginGetOwnProperty`); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   test(() => { | ||||||
|  |     assert_true(Reflect.setPrototypeOf(target, originalValue)); | ||||||
|  |   }, `${prefix}: setting the prototype to ${originalValueString} via Reflect.setPrototypeOf should return true`); | ||||||
|  | }; | ||||||
|  | @ -89,7 +89,7 @@ | ||||||
|     "html/attributes/lang/extlang-bad-novalid.html": "Bad value \u201cbat-smg\u201d for attribute \u201clang\u201d on element \u201cbody\u201d: Bad language tag: Bad extlang subtag \u201csmg\u201d.", |     "html/attributes/lang/extlang-bad-novalid.html": "Bad value \u201cbat-smg\u201d for attribute \u201clang\u201d on element \u201cbody\u201d: Bad language tag: Bad extlang subtag \u201csmg\u201d.", | ||||||
|     "html/attributes/lang/xmllang-different-value-novalid.html": "When the attribute \u201cxml:lang\u201d in no namespace is specified, the element must also have the attribute \u201clang\u201d present with the same value.", |     "html/attributes/lang/xmllang-different-value-novalid.html": "When the attribute \u201cxml:lang\u201d in no namespace is specified, the element must also have the attribute \u201clang\u201d present with the same value.", | ||||||
|     "html/attributes/lang/xmllang-only-novalid.html": "When the attribute \u201cxml:lang\u201d in no namespace is specified, the element must also have the attribute \u201clang\u201d present with the same value.", |     "html/attributes/lang/xmllang-only-novalid.html": "When the attribute \u201cxml:lang\u201d in no namespace is specified, the element must also have the attribute \u201clang\u201d present with the same value.", | ||||||
|     "html/attributes/role/unrecognized-role-name-novalid.html": "Discarding unrecognized tokens \u201cswitch\u201d, \u201cinput\u201d from value of attribute \u201crole\u201d. Browsers ignore any token that is not a defined ARIA non-abstract role.", |     "html/attributes/role/unrecognized-role-name-novalid.html": "Discarding unrecognized token \u201cinput\u201d from value of attribute \u201crole\u201d. Browsers ignore any token that is not a defined ARIA non-abstract role.", | ||||||
|     "html/attributes/spellcheck/value-bad-novalid.html": "Bad value \u201cbadvalue\u201d for attribute \u201cspellcheck\u201d on element \u201cp\u201d.", |     "html/attributes/spellcheck/value-bad-novalid.html": "Bad value \u201cbadvalue\u201d for attribute \u201cspellcheck\u201d on element \u201cp\u201d.", | ||||||
|     "html/elements/a/href/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in fragment: \u201c\\\u201d is not allowed.", |     "html/elements/a/href/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in fragment: \u201c\\\u201d is not allowed.", | ||||||
|     "html/elements/a/href/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in fragment: \u201c#\u201d is not allowed.", |     "html/elements/a/href/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in fragment: \u201c#\u201d is not allowed.", | ||||||
|  | @ -2435,7 +2435,7 @@ | ||||||
|     "xhtml/elements/keygen/361-novalid.xhtml": "The \u201ckeygen\u201d element is obsolete. ", |     "xhtml/elements/keygen/361-novalid.xhtml": "The \u201ckeygen\u201d element is obsolete. ", | ||||||
|     "xhtml/elements/keygen/keygen-novalid.xhtml": "The \u201ckeygen\u201d element is obsolete. ", |     "xhtml/elements/keygen/keygen-novalid.xhtml": "The \u201ckeygen\u201d element is obsolete. ", | ||||||
|     "xhtml/elements/link/001-novalid.xhtml": "Element \u201clink\u201d is missing required attribute \u201chref\u201d.", |     "xhtml/elements/link/001-novalid.xhtml": "Element \u201clink\u201d is missing required attribute \u201chref\u201d.", | ||||||
|     "xhtml/elements/menu/001-haswarn.xhtml": "The \u201cmenu\u201d element is not supported in all browsers. Please be sure to test, and consider using a polyfill.", |     "xhtml/elements/menu/001-haswarn.xhtml": "The \u201ccontextmenu\u201d attribute is not supported in all browsers. Please be sure to test, and consider using a polyfill.", | ||||||
|     "xhtml/elements/menu/001-novalid.xhtml": "The \u201ccontextmenu\u201d attribute must refer to a \u201cmenu\u201d element.", |     "xhtml/elements/menu/001-novalid.xhtml": "The \u201ccontextmenu\u201d attribute must refer to a \u201cmenu\u201d element.", | ||||||
|     "xhtml/elements/meter/010-novalid.xhtml": "The value of the \u201cmin\u201d attribute must be less than or equal to the value of the \u201cvalue\u201d attribute.", |     "xhtml/elements/meter/010-novalid.xhtml": "The value of the \u201cmin\u201d attribute must be less than or equal to the value of the \u201cvalue\u201d attribute.", | ||||||
|     "xhtml/elements/meter/011-novalid.xhtml": "Element \u201cmeter\u201d is missing required attribute \u201cvalue\u201d.", |     "xhtml/elements/meter/011-novalid.xhtml": "Element \u201cmeter\u201d is missing required attribute \u201cvalue\u201d.", | ||||||
|  |  | ||||||
|  | @ -0,0 +1,23 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <html> | ||||||
|  | <head> | ||||||
|  | <title>Console Count - Logging Manual Test</title> | ||||||
|  | <meta name="author" title="Dominic Farolino" href="mailto:domfarolino@gmail.com"> | ||||||
|  | <meta name="assert" content="Console count method default parameter should work"> | ||||||
|  | <link rel="help" href="https://console.spec.whatwg.org/#count"> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  | <p>Open the console inside the developer tools. It should contain four lines whose contents are:</p> | ||||||
|  | <p><code>default: 1</code></p> | ||||||
|  | <p><code>default: 2</code></p> | ||||||
|  | <p><code>default: 3</code></p> | ||||||
|  | <p><code>default: 4</code></p> | ||||||
|  | 
 | ||||||
|  | <script> | ||||||
|  | console.count(); | ||||||
|  | console.count(undefined); | ||||||
|  | console.count("default"); | ||||||
|  | console.count({toString() {return "default"}}); | ||||||
|  | </script> | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | "use strict"; | ||||||
|  | 
 | ||||||
|  | test(() => { | ||||||
|  |   assert_equals(console.timeline, undefined, "console.timeline should be undefined"); | ||||||
|  | }, "'timeline' function should not exist on the console object"); | ||||||
|  | 
 | ||||||
|  | test(() => { | ||||||
|  |   assert_equals(console.timelineEnd, undefined, "console.timelineEnd should be undefined"); | ||||||
|  | }, "'timelineEnd' function should not exist on the console object"); | ||||||
|  | @ -0,0 +1,80 @@ | ||||||
|  | <!DOCTYPE HTML> | ||||||
|  | <html> | ||||||
|  | 
 | ||||||
|  | <head> | ||||||
|  |     <meta charset="utf-8"> | ||||||
|  |     <title>base-uri works correctly inside a sandboxed iframe.</title> | ||||||
|  |     <script src='/resources/testharness.js'></script> | ||||||
|  |     <script src='/resources/testharnessreport.js'></script> | ||||||
|  | 
 | ||||||
|  |     <!-- CSP served: base-uri 'self' --> | ||||||
|  | </head> | ||||||
|  | 
 | ||||||
|  | <body> | ||||||
|  |     <h1>base-uri works correctly inside a sandboxed iframe.</h1> | ||||||
|  |     <div id='log'></div> | ||||||
|  | 
 | ||||||
|  |     <script> | ||||||
|  |         window.addEventListener('securitypolicyviolation', function(e) { | ||||||
|  |             assert_unreached('No CSP violation report has fired.'); | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         async_test(function(t) { | ||||||
|  |             var i = document.createElement('iframe'); | ||||||
|  |             i.sandbox = 'allow-scripts'; | ||||||
|  |             i.style.display = 'none'; | ||||||
|  |             i.srcdoc = ` | ||||||
|  |             <script> | ||||||
|  |               window.addEventListener('securitypolicyviolation', function() { | ||||||
|  |                 top.postMessage('FAIL', '*'); | ||||||
|  |               }); | ||||||
|  |             </sc` + `ript> | ||||||
|  |             <base href="{{location[scheme]}}://{{domains[]}}:{{ports[http][0]}}/base/"> | ||||||
|  |             <script> | ||||||
|  |               top.postMessage(document.baseURI, '*'); | ||||||
|  |             </sc` + `ript>`; | ||||||
|  | 
 | ||||||
|  |             window.addEventListener('message', t.step_func(function(e) { | ||||||
|  |                 if (e.source === i.contentWindow) { | ||||||
|  |                     assert_equals(e.data, location.origin + '/base/'); | ||||||
|  |                     t.done(); | ||||||
|  |                 } | ||||||
|  |             })); | ||||||
|  | 
 | ||||||
|  |             document.body.appendChild(i); | ||||||
|  |         }, 'base-uri \'self\' works with same-origin sandboxed iframes.'); | ||||||
|  | 
 | ||||||
|  |         async_test(function(t) { | ||||||
|  |             var i = document.createElement('iframe'); | ||||||
|  |             i.sandbox = 'allow-scripts'; | ||||||
|  |             i.style.display = 'none'; | ||||||
|  |             i.srcdoc = ` | ||||||
|  |             <script> | ||||||
|  |               window.addEventListener('securitypolicyviolation', | ||||||
|  |                 function(violation) { | ||||||
|  |                   if (violation.blockedURI !== '{{location[scheme]}}://{{domains[www2]}}:{{ports[http][0]}}/base/' || violation.effectiveDirective !== 'base-uri') { | ||||||
|  |                       top.postMessage('FAIL'); | ||||||
|  |                       return; | ||||||
|  |                   } | ||||||
|  |                   top.postMessage(document.baseURI, '*'); | ||||||
|  |               }); | ||||||
|  |             </sc` + `ript> | ||||||
|  |             <base href="{{location[scheme]}}://{{domains[www2]}}:{{ports[http][0]}}/base/"> | ||||||
|  |             <script> | ||||||
|  |               top.postMessage(document.baseURI, '*'); | ||||||
|  |             </sc` + `ript>`; | ||||||
|  | 
 | ||||||
|  |             window.addEventListener('message', t.step_func(function(e) { | ||||||
|  |                 if (e.source === i.contentWindow) { | ||||||
|  |                     assert_equals(e.data, location.href); | ||||||
|  |                     t.done(); | ||||||
|  |                 } | ||||||
|  |             })); | ||||||
|  | 
 | ||||||
|  |             document.body.appendChild(i); | ||||||
|  |         }, 'base-uri \'self\' blocks foreign-origin sandboxed iframes.'); | ||||||
|  |     </script> | ||||||
|  | 
 | ||||||
|  | </body> | ||||||
|  | 
 | ||||||
|  | </html> | ||||||
|  | @ -0,0 +1,5 @@ | ||||||
|  | Expires: Mon, 26 Jul 1997 05:00:00 GMT | ||||||
|  | Cache-Control: no-store, no-cache, must-revalidate | ||||||
|  | Cache-Control: post-check=0, pre-check=0, false | ||||||
|  | Pragma: no-cache | ||||||
|  | Content-Security-Policy: base-uri 'self' | ||||||
|  | @ -0,0 +1,16 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <meta http-equiv="Content-Security-Policy" content="connect-src 'self'"> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | <script> | ||||||
|  |     async_test(t => { | ||||||
|  |       document.addEventListener("securitypolicyviolation", t.step_func_done(e => { | ||||||
|  |         if (e.blockedURI != "http://{{domains[www]}}:{{ports[http][0]}}/common/text-plain.txt") | ||||||
|  |             return; | ||||||
|  | 
 | ||||||
|  |         assert_equals(e.violatedDirective, "connect-src"); | ||||||
|  |       })); | ||||||
|  | 
 | ||||||
|  |       assert_true(navigator.sendBeacon("http://{{domains[www]}}:{{ports[http][0]}}/common/text-plain.txt")); | ||||||
|  |     }, "sendBeacon should not throw."); | ||||||
|  | </script> | ||||||
|  | @ -0,0 +1,61 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <meta http-equiv="Content-Security-Policy" content="connect-src 'self'"> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | <script> | ||||||
|  |     async_test(t => { | ||||||
|  |       var errorEvent = false; | ||||||
|  |       var cspEvent = false; | ||||||
|  | 
 | ||||||
|  |       var es = new EventSource("http://{{domains[www]}}:{{ports[http][0]}}/common/text-plain.txt"); | ||||||
|  |       es.onerror = t.step_func(e => { | ||||||
|  |         assert_equals(es.readyState, EventSource.CLOSED); | ||||||
|  | 
 | ||||||
|  |         assert_false(errorEvent); | ||||||
|  |         errorEvent = true; | ||||||
|  |         if (cspEvent) | ||||||
|  |             t.done(); | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       document.addEventListener("securitypolicyviolation", t.step_func(e => { | ||||||
|  |         if (e.blockedURI != "http://{{domains[www]}}:{{ports[http][0]}}/common/text-plain.txt") | ||||||
|  |             return; | ||||||
|  | 
 | ||||||
|  |         assert_equals(es.readyState, EventSource.CLOSED); | ||||||
|  |         assert_equals(e.violatedDirective, "connect-src"); | ||||||
|  | 
 | ||||||
|  |         assert_false(cspEvent); | ||||||
|  |         cspEvent = true; | ||||||
|  |         if (errorEvent) | ||||||
|  |             t.done(); | ||||||
|  |       })); | ||||||
|  |     }, "EventSource should fire onerror."); | ||||||
|  | 
 | ||||||
|  |     async_test(t => { | ||||||
|  |       var errorEvent = false; | ||||||
|  |       var cspEvent = false; | ||||||
|  | 
 | ||||||
|  |       var es = new EventSource("http://{{domains[www]}}:{{ports[http][0]}}/common/text-plain.txt"); | ||||||
|  |       es.onerror = t.step_func(e => { | ||||||
|  |         assert_equals(es.readyState, EventSource.CLOSED); | ||||||
|  | 
 | ||||||
|  |         assert_false(errorEvent); | ||||||
|  |         errorEvent = true; | ||||||
|  |         if (cspEvent) | ||||||
|  |             t.done(); | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       document.addEventListener("securitypolicyviolation", t.step_func(e => { | ||||||
|  |         if (e.blockedURI != "http://{{domains[www]}}:{{ports[http][0]}}/common/text-plain.txt") | ||||||
|  |             return; | ||||||
|  | 
 | ||||||
|  |         assert_equals(es.readyState, EventSource.CLOSED); | ||||||
|  |         assert_equals(e.violatedDirective, "connect-src"); | ||||||
|  | 
 | ||||||
|  |         assert_false(cspEvent); | ||||||
|  |         cspEvent = true; | ||||||
|  |         if (errorEvent) | ||||||
|  |             t.done(); | ||||||
|  |       })); | ||||||
|  |     }, "EventSource should fire onerror."); | ||||||
|  | 
 | ||||||
|  | @ -0,0 +1,34 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <meta http-equiv="Content-Security-Policy" content="connect-src 'self'"> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | <script> | ||||||
|  |     async_test(t => { | ||||||
|  |       var errorEvent = false; | ||||||
|  |       var cspEvent = false; | ||||||
|  | 
 | ||||||
|  |       var ws = new WebSocket("ws://{{domains[www]}}:{{ports[ws][0]}}/echo"); | ||||||
|  |       ws.onopen = t.unreached_func("open should not fire."); | ||||||
|  |       ws.onerror = t.step_func(e => { | ||||||
|  |         assert_equals(ws.readyState, WebSocket.CLOSED); | ||||||
|  | 
 | ||||||
|  |         assert_false(errorEvent); | ||||||
|  |         errorEvent = true; | ||||||
|  |         if (cspEvent) | ||||||
|  |             t.done(); | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       document.addEventListener("securitypolicyviolation", t.step_func(e => { | ||||||
|  |         if (e.blockedURI != "ws://{{domains[www]}}:{{ports[ws][0]}}") | ||||||
|  |             return; | ||||||
|  | 
 | ||||||
|  |         assert_equals(ws.readyState, WebSocket.CLOSED); | ||||||
|  |         assert_equals(e.violatedDirective, "connect-src"); | ||||||
|  | 
 | ||||||
|  |         assert_false(cspEvent); | ||||||
|  |         cspEvent = true; | ||||||
|  |         if (errorEvent) | ||||||
|  |             t.done(); | ||||||
|  |       })); | ||||||
|  |     }, "WebSocket should fire error event."); | ||||||
|  | </script> | ||||||
|  | @ -0,0 +1,69 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <meta http-equiv="Content-Security-Policy" content="connect-src 'self'"> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | <script> | ||||||
|  |     async_test(t => { | ||||||
|  |       var errorEvent = false; | ||||||
|  |       var cspEvent = false; | ||||||
|  | 
 | ||||||
|  |       var xhr = new XMLHttpRequest; | ||||||
|  |       xhr.open("GET", "http://{{domains[www]}}:{{ports[http][0]}}/common/text-plain.txt"); | ||||||
|  |       xhr.onload = t.unreached_func("Load should not fire."); | ||||||
|  |       xhr.onerror = t.step_func(e => { | ||||||
|  |         assert_equals(xhr.readyState, XMLHttpRequest.DONE); | ||||||
|  | 
 | ||||||
|  |         assert_false(errorEvent); | ||||||
|  |         errorEvent = true; | ||||||
|  |         if (cspEvent) | ||||||
|  |             t.done(); | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       document.addEventListener("securitypolicyviolation", t.step_func(e => { | ||||||
|  |         if (e.blockedURI != "http://{{domains[www]}}:{{ports[http][0]}}/common/text-plain.txt") | ||||||
|  |             return; | ||||||
|  | 
 | ||||||
|  |         assert_equals(xhr.readyState, XMLHttpRequest.DONE); | ||||||
|  |         assert_equals(e.violatedDirective, "connect-src"); | ||||||
|  | 
 | ||||||
|  |         assert_false(cspEvent); | ||||||
|  |         cspEvent = true; | ||||||
|  |         if (errorEvent) | ||||||
|  |             t.done(); | ||||||
|  |       })); | ||||||
|  | 
 | ||||||
|  |       xhr.send(); | ||||||
|  |     }, "XHR should fire onerror."); | ||||||
|  | 
 | ||||||
|  |     async_test(t => { | ||||||
|  |       var errorEvent = false; | ||||||
|  |       var cspEvent = false; | ||||||
|  | 
 | ||||||
|  |       var xhr = new XMLHttpRequest; | ||||||
|  |       xhr.open("GET", "/common/redirect-opt-in.py?status=307&location=http://{{domains[www]}}:{{ports[http][0]}}/common/text-plain.txt"); | ||||||
|  |       xhr.onload = t.unreached_func("Load should not fire."); | ||||||
|  |       xhr.onerror = t.step_func(e => { | ||||||
|  |         assert_equals(xhr.readyState, XMLHttpRequest.DONE); | ||||||
|  | 
 | ||||||
|  |         assert_false(errorEvent); | ||||||
|  |         errorEvent = true; | ||||||
|  |         if (cspEvent) | ||||||
|  |             t.done(); | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       document.addEventListener("securitypolicyviolation", t.step_func(e => { | ||||||
|  |         if (e.blockedURI != "http://{{domains[www]}}:{{ports[http][0]}}") | ||||||
|  |             return; | ||||||
|  | 
 | ||||||
|  |         assert_equals(xhr.readyState, XMLHttpRequest.DONE); | ||||||
|  |         assert_equals(e.violatedDirective, "connect-src"); | ||||||
|  | 
 | ||||||
|  |         assert_false(cspEvent); | ||||||
|  |         cspEvent = true; | ||||||
|  |         if (errorEvent) | ||||||
|  |             t.done(); | ||||||
|  |       })); | ||||||
|  | 
 | ||||||
|  |       xhr.send(); | ||||||
|  |     }, "XHR should fire onerror after a redirect."); | ||||||
|  | </script> | ||||||
|  | @ -1,6 +0,0 @@ | ||||||
| <!doctype html> |  | ||||||
| <meta charset=utf-8> |  | ||||||
| <title>csp font-src: blacklisted</title> |  | ||||||
| <link href="fonts.css" rel="stylesheet" type="text/css"> |  | ||||||
|           |  | ||||||
| <p>The test passes if the line above are boxes in the test and glyphs in the reference.</p> |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| <!doctype html> |  | ||||||
| <meta charset=utf-8> |  | ||||||
| <meta http-equiv="Content-Security-Policy" content="font-src 'none'"> |  | ||||||
| <title>csp font-src: blacklisted</title> |  | ||||||
| <link rel="mismatch" href="font-blacklisted-ref.html"> |  | ||||||
| <link rel="help" href="https://www.w3.org/TR/CSP2/#directive-font-src"> |  | ||||||
| <link href="fonts.css" rel="stylesheet" type="text/css"> |  | ||||||
|           |  | ||||||
| <p>The test passes if the line above are boxes in the test and glyphs in the reference.</p> |  | ||||||
|  | @ -0,0 +1,23 @@ | ||||||
|  | <!doctype html> | ||||||
|  | <meta charset=utf-8> | ||||||
|  | <meta http-equiv="Content-Security-Policy" content="font-src {{domains[www1]}}:{{ports[http][0]}}"> | ||||||
|  | <head> | ||||||
|  |   <title>Test font loads if it matches font-src.</title> | ||||||
|  |   <script src='/resources/testharness.js'></script> | ||||||
|  |   <script src='/resources/testharnessreport.js'></script> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  |   <div id="log"/> | ||||||
|  |   <script> | ||||||
|  |     async_test(function(t) { | ||||||
|  |       document.addEventListener("securitypolicyviolation", t.unreached_func("Loading allowed fonts should not trigger a violation.")); | ||||||
|  |       var link = document.createElement('link'); | ||||||
|  |       link.rel="preload"; | ||||||
|  |       link.as="font"; | ||||||
|  |       link.href="http://{{domains[www1]}}:{{ports[http][0]}}/content-security-policy/support/Ahem.ttf"; | ||||||
|  |       link.onload = t.step_func_done(); | ||||||
|  |       link.onerror = t.unreached_func("Should have loaded the font."); | ||||||
|  |       document.getElementsByTagName('head')[0].appendChild(link); | ||||||
|  |     }, "Test font loads if it matches font-src."); | ||||||
|  |   </script> | ||||||
|  | </body> | ||||||
|  | @ -0,0 +1,22 @@ | ||||||
|  | <!doctype html> | ||||||
|  | <meta charset=utf-8> | ||||||
|  | <meta http-equiv="Content-Security-Policy" content="font-src {{domains[www1]}}:{{ports[http][0]}}"> | ||||||
|  | <head> | ||||||
|  |   <title>Test font does not load if it does not match font-src.</title> | ||||||
|  |   <script src='/resources/testharness.js'></script> | ||||||
|  |   <script src='/resources/testharnessreport.js'></script> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  |   <div id="log"/> | ||||||
|  |   <script> | ||||||
|  |     async_test(function(t) { | ||||||
|  |       var link = document.createElement('link'); | ||||||
|  |       link.rel="preload"; | ||||||
|  |       link.as="font"; | ||||||
|  |       link.href="http://{{domains[www2]}}:{{ports[http][0]}}/content-security-policy/support/Ahem.ttf"; | ||||||
|  |       link.onload = t.unreached_func("Should not have loaded the font."); | ||||||
|  |       link.onerror = t.step_func_done(); | ||||||
|  |       document.getElementsByTagName('head')[0].appendChild(link); | ||||||
|  |     }, "Test font does not load if it does not match font-src."); | ||||||
|  |   </script> | ||||||
|  | </body> | ||||||
|  | @ -0,0 +1,22 @@ | ||||||
|  | <!doctype html> | ||||||
|  | <meta charset=utf-8> | ||||||
|  | <meta http-equiv="Content-Security-Policy" content="font-src 'none'"> | ||||||
|  | <head> | ||||||
|  |   <title>Test font does not load if it does not match font-src.</title> | ||||||
|  |   <script src='/resources/testharness.js'></script> | ||||||
|  |   <script src='/resources/testharnessreport.js'></script> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  |   <div id="log"/> | ||||||
|  |   <script> | ||||||
|  |     async_test(function(t) { | ||||||
|  |       var link = document.createElement('link'); | ||||||
|  |       link.rel="preload"; | ||||||
|  |       link.as="font"; | ||||||
|  |       link.href="http://{{domains[www]}}:{{ports[http][0]}}/content-security-policy/support/Ahem.ttf"; | ||||||
|  |       link.onload = t.unreached_func("Should not have loaded the font."); | ||||||
|  |       link.onerror = t.step_func_done(); | ||||||
|  |       document.getElementsByTagName('head')[0].appendChild(link); | ||||||
|  |     }, "Test font does not load if it does not match font-src."); | ||||||
|  |   </script> | ||||||
|  | </body> | ||||||
|  | @ -0,0 +1,23 @@ | ||||||
|  | <!doctype html> | ||||||
|  | <meta charset=utf-8> | ||||||
|  | <meta http-equiv="Content-Security-Policy" content="font-src 'self'"> | ||||||
|  | <head> | ||||||
|  |   <title>Test font loads if it matches font-src.</title> | ||||||
|  |   <script src='/resources/testharness.js'></script> | ||||||
|  |   <script src='/resources/testharnessreport.js'></script> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  |   <div id="log"/> | ||||||
|  |   <script> | ||||||
|  |     async_test(function(t) { | ||||||
|  |       document.addEventListener("securitypolicyviolation", t.unreached_func("Loading allowed fonts should not trigger a violation.")); | ||||||
|  |       var link = document.createElement('link'); | ||||||
|  |       link.rel="preload"; | ||||||
|  |       link.as="font"; | ||||||
|  |       link.href="/content-security-policy/support/Ahem.ttf"; | ||||||
|  |       link.onload = t.step_func_done(); | ||||||
|  |       link.onerror = t.unreached_func("Should have loaded the font."); | ||||||
|  |       document.getElementsByTagName('head')[0].appendChild(link); | ||||||
|  |     }, "Test font loads if it matches font-src."); | ||||||
|  |   </script> | ||||||
|  | </body> | ||||||
|  | @ -0,0 +1,25 @@ | ||||||
|  | <!doctype html> | ||||||
|  | <meta charset=utf-8> | ||||||
|  | <meta http-equiv="Content-Security-Policy" content="font-src 'none'"> | ||||||
|  | <head> | ||||||
|  |   <title>Test font does not load if it does not match font-src.</title> | ||||||
|  |   <script src='/resources/testharness.js'></script> | ||||||
|  |   <script src='/resources/testharnessreport.js'></script> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  |   <div id="log"/> | ||||||
|  |   <script> | ||||||
|  |     async_test(function(t) { | ||||||
|  |       var link = document.createElement('link'); | ||||||
|  |       link.rel="stylesheet"; | ||||||
|  |       link.type="text/css"; | ||||||
|  |       link.href="/content-security-policy/support/fonts.css"; | ||||||
|  |       // The stylesheet should stil load, even though the font contained does not | ||||||
|  |       link.onerror = t.unreached_func("Should have loaded the stylesheet."); | ||||||
|  |       document.addEventListener("securitypolicyviolation", t.step_func_done(function(e) { | ||||||
|  |         assert_equals(e.violatedDirective, "font-src"); | ||||||
|  |       })); | ||||||
|  |       document.getElementsByTagName('head')[0].appendChild(link); | ||||||
|  |     }, "Test font does not load if it does not match font-src."); | ||||||
|  |   </script> | ||||||
|  | </body> | ||||||
|  | @ -1,6 +0,0 @@ | ||||||
| <!doctype html> |  | ||||||
| <meta charset=utf-8> |  | ||||||
| <title>csp font-src: whitelisted</title> |  | ||||||
| <link href="fonts.css" rel="stylesheet" type="text/css"> |  | ||||||
|           |  | ||||||
| <p>The test passes if the line above shows the same glyphs in the reference.</p> |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| <!doctype html> |  | ||||||
| <meta charset=utf-8> |  | ||||||
| <meta http-equiv="Content-Security-Policy" content="font-src 'self'"> |  | ||||||
| <title>csp font-src: whitelisted</title> |  | ||||||
| <link rel="match" href="font-whitelisted-ref.html"> |  | ||||||
| <link rel="help" href="https://www.w3.org/TR/CSP2/#directive-font-src"> |  | ||||||
| <link href="fonts.css" rel="stylesheet" type="text/css"> |  | ||||||
|           |  | ||||||
| <p>The test passes if the line above shows the same glyphs in the reference.</p> |  | ||||||
|  | @ -1,8 +0,0 @@ | ||||||
| @font-face { |  | ||||||
|   font-family: 'Halflings'; |  | ||||||
|   src:  url('/tools/runner/fonts/glyphicons-halflings-regular.woff') format('woff'); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| body { |  | ||||||
|     font-family: 'Halflings', Fallback, sans-serif; |  | ||||||
| } |  | ||||||
|  | @ -1,46 +0,0 @@ | ||||||
| <!DOCTYPE HTML> |  | ||||||
| <html> |  | ||||||
| <head> |  | ||||||
|     <title>img element src attribute must match src list.</title> |  | ||||||
|     <script src='/resources/testharness.js'></script> |  | ||||||
|     <script src='/resources/testharnessreport.js'></script> |  | ||||||
| </head> |  | ||||||
| <body> |  | ||||||
|     <h1>img element src attribute must match src list.</h1> |  | ||||||
|     <p> |  | ||||||
|     <div id='log'></div> |  | ||||||
| 
 |  | ||||||
|     <script type="text/javascript"> |  | ||||||
|       var t1 = async_test("img-src for relative path should load."); |  | ||||||
|       var t2 = async_test("img-src from unapproved domains should not load"); |  | ||||||
|       var t3 = async_test("img-src from approved domains should load"); |  | ||||||
|     </script> |  | ||||||
| 
 |  | ||||||
|     <img src='/content-security-policy/support/pass.png' |  | ||||||
|     onerror='t1.step(function() { assert_unreached("The img should have loaded."); t1.done() });' |  | ||||||
|     onload='t1.done();'> |  | ||||||
| 
 |  | ||||||
|     <img src='http://www1.web-platform.test/content-security-policy/support/fail.png' |  | ||||||
|     onerror='t2.done();' |  | ||||||
|     onload='t2.step(function() { assert_unreached("Image from unapproved domain was loaded."); t2.done()} );'> |  | ||||||
| 
 |  | ||||||
|     <div id='t3'></div> |  | ||||||
| 
 |  | ||||||
|     <script> |  | ||||||
|       var t3img = document.createElement('img'); |  | ||||||
|       t3img.onerror = function() {t3.step(function() { assert_unreached(); t3.done();})} |  | ||||||
|       t3img.onload = function() {t3.done();} |  | ||||||
|       t3img.src = location.protocol + '//www.' + location.hostname + ':' + location.port + |  | ||||||
|            '/content-security-policy/support/pass.png'; |  | ||||||
|       var t3div = document.getElementById('t3'); |  | ||||||
|       t3div.appendChild(t3img); |  | ||||||
| 
 |  | ||||||
|       var report = document.createElement('script'); |  | ||||||
|       report.src = '../support/checkReport.sub.js?reportField=violated-directive&reportValue=img-src%20%27self%27%20www.' + location.hostname + (location.port ? ':' + location.port : ''); |  | ||||||
|       t3div.appendChild(report); |  | ||||||
| 
 |  | ||||||
|     </script> |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| </body> |  | ||||||
| </html> |  | ||||||
|  | @ -1,6 +0,0 @@ | ||||||
| Expires: Mon, 26 Jul 1997 05:00:00 GMT |  | ||||||
| Cache-Control: no-store, no-cache, must-revalidate |  | ||||||
| Cache-Control: post-check=0, pre-check=0, false |  | ||||||
| Pragma: no-cache |  | ||||||
| Set-Cookie: img-src-4_1={{$id:uuid()}}; Path=/content-security-policy/img-src/ |  | ||||||
| Content-Security-Policy: img-src 'self' www.{{host}}:{{ports[http][0]}};  report-uri  ../support/report.py?op=put&reportID={{$id}} |  | ||||||
|  | @ -0,0 +1,35 @@ | ||||||
|  | <!DOCTYPE HTML> | ||||||
|  | <meta http-equiv="Content-Security-Policy" content="img-src 'self' {{domains[www]}}:{{ports[http][0]}}"> | ||||||
|  | <html> | ||||||
|  | <head> | ||||||
|  |     <title>img element src attribute must match src list.</title> | ||||||
|  |     <script src='/resources/testharness.js'></script> | ||||||
|  |     <script src='/resources/testharnessreport.js'></script> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  |     <div id='log'/> | ||||||
|  | 
 | ||||||
|  |     <script> | ||||||
|  |       async_test(function(t) { | ||||||
|  |         i = new Image(); | ||||||
|  |         i.onload = t.step_func_done(); | ||||||
|  |         i.onerror = t.unreached_func("The img should have loaded"); | ||||||
|  |         i.src = '/content-security-policy/support/pass.png'; | ||||||
|  |       }, "img-src for relative path should load"); | ||||||
|  | 
 | ||||||
|  |       async_test(function(t) { | ||||||
|  |         i = new Image(); | ||||||
|  |         i.onload = t.unreached_func("Image from unapproved domain was loaded."); | ||||||
|  |         i.onerror = t.step_func_done(); | ||||||
|  |         i.src = 'http://{{domains[www1]}}/content-security-policy/support/fail.png'; | ||||||
|  |       }, "img-src from unapproved domains should not load"); | ||||||
|  | 
 | ||||||
|  |       async_test(function(t) { | ||||||
|  |         i = new Image(); | ||||||
|  |         i.onload = t.step_func_done(); | ||||||
|  |         i.onerror = t.unreached_func("The img should have loaded"); | ||||||
|  |         i.src = location.protocol + '//{{domains[www]}}:{{ports[http][0]}}/content-security-policy/support/pass.png'; | ||||||
|  |       }, "img-src from approved domains should load"); | ||||||
|  |     </script> | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -0,0 +1,20 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <meta http-equiv="Content-Security-Policy" content="img-src *.{{host}}:{{ports[http][0]}}"> | ||||||
|  | <html> | ||||||
|  | <head> | ||||||
|  |     <title>img-src with full host and wildcard blocks correctly.</title> | ||||||
|  |     <script src='/resources/testharness.js'></script> | ||||||
|  |     <script src='/resources/testharnessreport.js'></script> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  |     <div id='log'/> | ||||||
|  | 
 | ||||||
|  |     <script> | ||||||
|  |       var t1 = async_test("img src does not match full host and wildcard csp directive"); | ||||||
|  |     </script> | ||||||
|  |     <img src='http://{{host}}:{{ports[http][0]}}/content-security-policy/support/fail.png' | ||||||
|  |          onload='t1.step(function() { assert_unreached("Image should have loaded"); t1.done(); });' | ||||||
|  |          onerror='t1.done();'> | ||||||
|  | 
 | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -0,0 +1,20 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <meta http-equiv="Content-Security-Policy" content="img-src *.{{host}}:{{ports[http][0]}}"> | ||||||
|  | <html> | ||||||
|  | <head> | ||||||
|  |     <title>img-src works correctly with partial host wildcard.</title> | ||||||
|  |     <script src='/resources/testharness.js'></script> | ||||||
|  |     <script src='/resources/testharnessreport.js'></script> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  |     <div id='log'/> | ||||||
|  | 
 | ||||||
|  |     <script> | ||||||
|  |       var t1 = async_test("img src matches correctly partial wildcard host csp directive"); | ||||||
|  |     </script> | ||||||
|  |     <img src='http://{{domains[www]}}:{{ports[http][0]}}/content-security-policy/support/pass.png' | ||||||
|  |          onload='t1.done();' | ||||||
|  |          onerror='t1.step(function() { assert_unreached("Image should have loaded"); t1.done(); });'> | ||||||
|  | 
 | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -0,0 +1,20 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <meta http-equiv="Content-Security-Policy" content="img-src 'none';"> | ||||||
|  | <html> | ||||||
|  | <head> | ||||||
|  |     <title>img element src attribute must match src list.</title> | ||||||
|  |     <script src='/resources/testharness.js'></script> | ||||||
|  |     <script src='/resources/testharnessreport.js'></script> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  |     <div id='log'/> | ||||||
|  | 
 | ||||||
|  |     <script> | ||||||
|  |       var t1 = async_test("img-src with 'none' source should not match"); | ||||||
|  |     </script> | ||||||
|  |     <img src='/content-security-policy/support/fail.png' | ||||||
|  |          onload='t1.step(function() { assert_unreached("Image should not have loaded"); t1.done(); });' | ||||||
|  |          onerror='t1.done();'> | ||||||
|  | 
 | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -0,0 +1,20 @@ | ||||||
|  | <!DOCTYPE HTML> | ||||||
|  | <meta http-equiv="Content-Security-Policy" content="img-src http://www.{{host}}:*"> | ||||||
|  | <html> | ||||||
|  | <head> | ||||||
|  |     <title>img-src works correctly with port wildcard source</title> | ||||||
|  |     <script src='/resources/testharness.js'></script> | ||||||
|  |     <script src='/resources/testharnessreport.js'></script> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  |     <div id='log'/> | ||||||
|  | 
 | ||||||
|  |     <script> | ||||||
|  |       var t1 = async_test("img-src with wildcard port should match any port"); | ||||||
|  |     </script> | ||||||
|  |     <img src='http://{{domains[www]}}:{{ports[http][0]}}/content-security-policy/support/pass.png' | ||||||
|  |          onload='t1.done();' | ||||||
|  |          onerror='t1.step(function() { assert_unreached("Image should have loaded."); t1.done()} );'> | ||||||
|  | 
 | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -0,0 +1,40 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <meta http-equiv="Content-Security-Policy" content="img-src *;"> | ||||||
|  | <html> | ||||||
|  | <head> | ||||||
|  |     <title>img element src attribute must match src list.</title> | ||||||
|  |     <script src='/resources/testharness.js'></script> | ||||||
|  |     <script src='/resources/testharnessreport.js'></script> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  |     <div id='log'/> | ||||||
|  | 
 | ||||||
|  |     <script> | ||||||
|  |       var t1 = async_test("img-src with wildcard should match all"); | ||||||
|  |     </script> | ||||||
|  |     <img src='/content-security-policy/support/pass.png' | ||||||
|  |          onload='t1.done();' | ||||||
|  |          onerror='t1.step(function() { assert_unreached("Image should have loaded"); t1.done(); });'> | ||||||
|  | 
 | ||||||
|  |     <script> | ||||||
|  |       async_test(function(t) { | ||||||
|  | 
 | ||||||
|  |         var pngBase64 = "iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD/gAIDAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAnklEQVR42u3QMQEAAAgDoGlyo1vBzwciUJlw1ApkyZIlS5YsBbJkyZIlS5YCWbJkyZIlS4EsWbJkyZKlQJYsWbJkyVIgS5YsWbJkKZAlS5YsWbIUyJIlS5YsWQpkyZIlS5YsBbJkyZIlS5YCWbJkyZIlS4EsWbJkyZKlQJYsWbJkyVIgS5YsWbJkKZAlS5YsWbIUyJIlS5YsWQpkyfq2MosBSIeKONMAAAAASUVORK5CYII="; | ||||||
|  | 
 | ||||||
|  |         blobContents = [atob(pngBase64)]; | ||||||
|  |         blob = new Blob(blobContents, {type: "image/png"}); | ||||||
|  |         img = document.createElement("img"); | ||||||
|  |         img.onerror = function (e) { | ||||||
|  |           t.done(); | ||||||
|  |         }; | ||||||
|  |         img.onload = function () { | ||||||
|  |           assert_unreached("Should not load blob img"); | ||||||
|  |           t.done(); | ||||||
|  |         }; | ||||||
|  |         blobURL = window.URL.createObjectURL(blob); | ||||||
|  |         img.src = blobURL; | ||||||
|  | 
 | ||||||
|  |       },"img-src with wildcard should not match blob"); | ||||||
|  |     </script> | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -0,0 +1,44 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | 
 | ||||||
|  | <meta http-equiv="content-security-policy" content="connect-src 'self'"> | ||||||
|  | <script> | ||||||
|  |   // External URLs inherit policy. | ||||||
|  |   fetch_tests_from_worker(new Worker("./support/connect-src-self.sub.js")); | ||||||
|  |   fetch_tests_from_worker(new Worker("./support/connect-src-self.sub.js?pipe=sub|header(Content-Security-Policy,connect-src 'none')")); | ||||||
|  |   fetch_tests_from_worker(new Worker("./support/connect-src-self.sub.js?pipe=sub|header(Content-Security-Policy,connect-src *)")); | ||||||
|  |   fetch_tests_from_worker(new Worker("./support/connect-src-self.sub.js?pipe=sub|header(Content-Security-Policy,default-src 'none')")); | ||||||
|  |   fetch_tests_from_worker(new Worker("./support/connect-src-self.sub.js?pipe=sub|header(Content-Security-Policy,default-src *)")); | ||||||
|  | 
 | ||||||
|  |   async_test(t => { | ||||||
|  |     fetch("./support/connect-src-self.sub.js") | ||||||
|  |       .then(r => r.blob()) | ||||||
|  |       .then(b => { | ||||||
|  |         // 'blob:' URLs inherit policy. | ||||||
|  |         var u = URL.createObjectURL(b); | ||||||
|  |         fetch_tests_from_worker(new Worker(u)); | ||||||
|  | 
 | ||||||
|  |         if (!window.webkitRequestFileSystem) | ||||||
|  |           return t.done(); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         // 'filesystem:' urls inherit policy. | ||||||
|  |         window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, fs => { | ||||||
|  |           fs.root.getFile('dedicated-inheritance-worker.js', { create: true }, entry => { | ||||||
|  |             entry.createWriter(w => { | ||||||
|  |               w.onwriteend = _ => { | ||||||
|  |                 var u = entry.toURL(); | ||||||
|  |                 fetch_tests_from_worker(new Worker(u)); | ||||||
|  | 
 | ||||||
|  |                 // explicit_done: yay. | ||||||
|  |                 t.done(); | ||||||
|  |               }; | ||||||
|  |               w.onerror = _ => t.unreached_func(); | ||||||
|  |               w.write(b); | ||||||
|  |             }); | ||||||
|  |           }); | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  |   }, "Filesystem and blob."); | ||||||
|  | </script> | ||||||
|  | @ -0,0 +1,44 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | 
 | ||||||
|  | <meta http-equiv="content-security-policy" content="script-src 'self' 'nonce-a' blob: filesystem:"> | ||||||
|  | <script nonce="a"> | ||||||
|  |   // External URLs inherit policy: the header delivered with the script resource is ignored. | ||||||
|  |   fetch_tests_from_worker(new Worker("./support/script-src-self.sub.js")); | ||||||
|  |   fetch_tests_from_worker(new Worker("./support/script-src-self.sub.js?pipe=sub|header(Content-Security-Policy,script-src 'none')")); | ||||||
|  |   fetch_tests_from_worker(new Worker("./support/script-src-self.sub.js?pipe=sub|header(Content-Security-Policy,script-src *)")); | ||||||
|  |   fetch_tests_from_worker(new Worker("./support/script-src-self.sub.js?pipe=sub|header(Content-Security-Policy,default-src 'none')")); | ||||||
|  |   fetch_tests_from_worker(new Worker("./support/script-src-self.sub.js?pipe=sub|header(Content-Security-Policy,default-src *)")); | ||||||
|  | 
 | ||||||
|  |   async_test(t => { | ||||||
|  |     fetch("./support/script-src-self.sub.js") | ||||||
|  |       .then(r => r.blob()) | ||||||
|  |       .then(b => { | ||||||
|  |         // 'blob:' URLs inherit policy. | ||||||
|  |         var u = URL.createObjectURL(b); | ||||||
|  |         fetch_tests_from_worker(new Worker(u)); | ||||||
|  | 
 | ||||||
|  |         if (!window.webkitRequestFileSystem) | ||||||
|  |           return t.done(); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         // 'filesystem:' urls inherit policy. | ||||||
|  |         window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, fs => { | ||||||
|  |           fs.root.getFile('dedicated-script-worker.js', { create: true }, entry => { | ||||||
|  |             entry.createWriter(w => { | ||||||
|  |               w.onwriteend = _ => { | ||||||
|  |                 var u = entry.toURL(); | ||||||
|  |                 fetch_tests_from_worker(new Worker(u)); | ||||||
|  | 
 | ||||||
|  |                 // explicit_done: yay. | ||||||
|  |                 t.done(); | ||||||
|  |               }; | ||||||
|  |               w.onerror = _ => t.unreached_func(); | ||||||
|  |               w.write(b); | ||||||
|  |             }); | ||||||
|  |           }); | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  |   }, "Filesystem and blob."); | ||||||
|  | </script> | ||||||
|  | @ -0,0 +1,11 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | 
 | ||||||
|  | <meta http-equiv="content-security-policy" content="connect-src 'self'"> | ||||||
|  | <script> | ||||||
|  |   // SharedWorkers do not inherit policy. | ||||||
|  |   fetch_tests_from_worker(new SharedWorker("./support/connect-src-allow.sub.js")); | ||||||
|  |   fetch_tests_from_worker(new SharedWorker("./support/connect-src-self.sub.js?pipe=sub|header(Content-Security-Policy,connect-src 'self')")); | ||||||
|  |   fetch_tests_from_worker(new SharedWorker("./support/connect-src-self.sub.js?pipe=sub|header(Content-Security-Policy,default-src 'self')")); | ||||||
|  | </script> | ||||||
|  | @ -0,0 +1,11 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <script src="/resources/testharness.js"></script> | ||||||
|  | <script src="/resources/testharnessreport.js"></script> | ||||||
|  | 
 | ||||||
|  | <meta http-equiv="content-security-policy" content="script-src 'self' 'nonce-a' blob: filesystem:"> | ||||||
|  | <script nonce="a"> | ||||||
|  |   // SharedWorker URLs do not inherit policy. | ||||||
|  |   fetch_tests_from_worker(new SharedWorker("./support/script-src-allow.sub.js")); | ||||||
|  |   fetch_tests_from_worker(new SharedWorker("./support/script-src-self.sub.js?pipe=sub|header(Content-Security-Policy,script-src 'self'")); | ||||||
|  |   fetch_tests_from_worker(new SharedWorker("./support/script-src-self.sub.js?pipe=sub|header(Content-Security-Policy,default-src 'self'")); | ||||||
|  | </script> | ||||||
|  | @ -0,0 +1,53 @@ | ||||||
|  | importScripts("{{location[server]}}/resources/testharness.js"); | ||||||
|  | importScripts("{{location[server]}}/content-security-policy/support/testharness-helper.js"); | ||||||
|  | 
 | ||||||
|  | // Same-origin
 | ||||||
|  | async_test(t => { | ||||||
|  |   var url = "{{location[server]}}/content-security-policy/support/resource.py?same-origin-fetch"; | ||||||
|  |   assert_no_csp_event_for_url(t, url); | ||||||
|  | 
 | ||||||
|  |   fetch(url) | ||||||
|  |     .then(t.step_func_done(r => assert_equals(r.status, 200))); | ||||||
|  | }, "Same-origin 'fetch()' in " + self.location.protocol + self.location.search); | ||||||
|  | 
 | ||||||
|  | async_test(t => { | ||||||
|  |   var url = "{{location[server]}}/content-security-policy/support/resource.py?same-origin-xhr"; | ||||||
|  |   assert_no_csp_event_for_url(t, url); | ||||||
|  | 
 | ||||||
|  |   var xhr = new XMLHttpRequest(); | ||||||
|  |   xhr.open("GET", url); | ||||||
|  |   xhr.onload = t.step_func_done(); | ||||||
|  |   xhr.onerror = t.unreached_func(); | ||||||
|  |   xhr.send(); | ||||||
|  | }, "Same-origin XHR in " + self.location.protocol + self.location.search); | ||||||
|  | 
 | ||||||
|  | // Cross-origin
 | ||||||
|  | async_test(t => { | ||||||
|  |   var url = "http://{{domains[www]}}:{{ports[http][1]}}/content-security-policy/support/resource.py?cross-origin-fetch"; | ||||||
|  |   assert_no_csp_event_for_url(t, url); | ||||||
|  | 
 | ||||||
|  |   fetch(url) | ||||||
|  |     .then(t.step_func_done(r => assert_equals(r.status, 200))); | ||||||
|  | }, "Cross-origin 'fetch()' in " + self.location.protocol + self.location.search); | ||||||
|  | 
 | ||||||
|  | async_test(t => { | ||||||
|  |   var url = "http://{{domains[www]}}:{{ports[http][1]}}/content-security-policy/support/resource.py?cross-origin-xhr"; | ||||||
|  |   assert_no_csp_event_for_url(t, url); | ||||||
|  | 
 | ||||||
|  |   var xhr = new XMLHttpRequest(); | ||||||
|  |   xhr.open("GET", url); | ||||||
|  |   xhr.onload = t.step_func_done(); | ||||||
|  |   xhr.onerror = t.unreached_func(); | ||||||
|  |   xhr.send(); | ||||||
|  | }, "Cross-origin XHR in " + self.location.protocol + self.location.search); | ||||||
|  | 
 | ||||||
|  | // Same-origin redirecting to cross-origin
 | ||||||
|  | async_test(t => { | ||||||
|  |   var url = "{{location[server]}}/common/redirect-opt-in.py?status=307&location=http://{{domains[www]}}:{{ports[http][1]}}/content-security-policy/support/resource.py?cross-origin-fetch"; | ||||||
|  |   assert_no_csp_event_for_url(t, url); | ||||||
|  | 
 | ||||||
|  |   fetch(url) | ||||||
|  |     .then(t.step_func_done(r => assert_equals(r.status, 200))); | ||||||
|  | }, "Same-origin => cross-origin 'fetch()' in " + self.location.protocol + self.location.search); | ||||||
|  | 
 | ||||||
|  | done(); | ||||||
|  | @ -0,0 +1,59 @@ | ||||||
|  | importScripts("{{location[server]}}/resources/testharness.js"); | ||||||
|  | importScripts("{{location[server]}}/content-security-policy/support/testharness-helper.js"); | ||||||
|  | 
 | ||||||
|  | // Same-origin
 | ||||||
|  | async_test(t => { | ||||||
|  |   var url = "{{location[server]}}/common/text-plain.txt?same-origin-fetch"; | ||||||
|  |   assert_no_csp_event_for_url(t, url); | ||||||
|  | 
 | ||||||
|  |   fetch(url) | ||||||
|  |     .then(t.step_func_done(r => assert_equals(r.status, 200))); | ||||||
|  | }, "Same-origin 'fetch()' in " + self.location.protocol + self.location.search); | ||||||
|  | 
 | ||||||
|  | async_test(t => { | ||||||
|  |   var url = "{{location[server]}}/common/text-plain.txt?same-origin-xhr"; | ||||||
|  |   assert_no_csp_event_for_url(t, url); | ||||||
|  | 
 | ||||||
|  |   var xhr = new XMLHttpRequest(); | ||||||
|  |   xhr.open("GET", url); | ||||||
|  |   xhr.onload = t.step_func_done(); | ||||||
|  |   xhr.onerror = t.unreached_func(); | ||||||
|  |   xhr.send(); | ||||||
|  | }, "Same-origin XHR in " + self.location.protocol + self.location.search); | ||||||
|  | 
 | ||||||
|  | // Cross-origin
 | ||||||
|  | async_test(t => { | ||||||
|  |   var url = "http://{{domains[www]}}:{{ports[http][1]}}/common/text-plain.txt?cross-origin-fetch"; | ||||||
|  | 
 | ||||||
|  |   Promise.all([ | ||||||
|  |     // TODO(mkwst): A 'securitypolicyviolation' event should fire.
 | ||||||
|  |     fetch(url) | ||||||
|  |       .catch(t.step_func(e => assert_true(e instanceof TypeError))) | ||||||
|  |   ]).then(t.step_func_done()); | ||||||
|  | }, "Cross-origin 'fetch()' in " + self.location.protocol + self.location.search); | ||||||
|  | 
 | ||||||
|  | async_test(t => { | ||||||
|  |   var url = "http://{{domains[www]}}:{{ports[http][1]}}/common/text-plain.txt?cross-origin-xhr"; | ||||||
|  | 
 | ||||||
|  |   Promise.all([ | ||||||
|  |     // TODO(mkwst): A 'securitypolicyviolation' event should fire.
 | ||||||
|  |     new Promise((resolve, reject) => { | ||||||
|  |       var xhr = new XMLHttpRequest(); | ||||||
|  |       xhr.open("GET", url); | ||||||
|  |       xhr.onload = t.step_func(_ => reject("xhr.open should have thrown.")); | ||||||
|  |       xhr.onerror = t.step_func(resolve); | ||||||
|  |       xhr.send(); | ||||||
|  |     }) | ||||||
|  |   ]).then(t.step_func_done()); | ||||||
|  | }, "Cross-origin XHR in " + self.location.protocol + self.location.search); | ||||||
|  | 
 | ||||||
|  | // Same-origin redirecting to cross-origin
 | ||||||
|  | async_test(t => { | ||||||
|  |   var url = "{{location[server]}}/common/redirect-opt-in.py?status=307&location=http://{{domains[www]}}:{{ports[http][1]}}/common/text-plain.txt?cross-origin-fetch"; | ||||||
|  | 
 | ||||||
|  |   // TODO(mkwst): A 'securitypolicyviolation' event should fire.
 | ||||||
|  |   fetch(url) | ||||||
|  |     .catch(t.step_func_done(e => assert_true(e instanceof TypeError))) | ||||||
|  | }, "Same-origin => cross-origin 'fetch()' in " + self.location.protocol + self.location.search); | ||||||
|  | 
 | ||||||
|  | done(); | ||||||
|  | @ -0,0 +1,18 @@ | ||||||
|  | importScripts("{{location[server]}}/resources/testharness.js"); | ||||||
|  | 
 | ||||||
|  | test(t => { | ||||||
|  |   importScripts("http://{{domains[www]}}:{{ports[http][1]}}/content-security-policy/support/testharness-helper.js"); | ||||||
|  | }, "Cross-origin `importScripts()` not blocked in " + self.location.protocol + self.location.search); | ||||||
|  | 
 | ||||||
|  | test(t => { | ||||||
|  |   assert_equals(2, eval("1+1")); | ||||||
|  |   assert_equals(2, (new Function("return 1+1;"))()); | ||||||
|  | }, "`eval()` not blocked in " + self.location.protocol + self.location.search); | ||||||
|  | 
 | ||||||
|  | async_test(t => { | ||||||
|  |   self.callback = t.step_func_done(); | ||||||
|  | 
 | ||||||
|  |   setTimeout("self.callback();", 1); | ||||||
|  | }, "`setTimeout([string])` not blocked in " + self.location.protocol + self.location.search); | ||||||
|  | 
 | ||||||
|  | done(); | ||||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
		Reference in a new issue
	
	 James Graham
						James Graham