mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Update web-platform-tests to revision f7e2ea2c50c4d23549d07cd24c7a96fc3f203d96
This commit is contained in:
parent
4b1bb895a3
commit
33357a82e4
175 changed files with 1667 additions and 4935 deletions
File diff suppressed because it is too large
Load diff
|
@ -1,4 +0,0 @@
|
|||
[hit-test-floats-002.html]
|
||||
[Hit test float]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[hit-test-floats-004.html]
|
||||
[Miss float below something else]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[hit-test-floats-005.html]
|
||||
[Miss clipped float]
|
||||
expected: FAIL
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
[ttwf-reftest-flex-wrap-reverse.html]
|
||||
type: reftest
|
||||
expected: FAIL
|
|
@ -1,3 +0,0 @@
|
|||
[ttwf-reftest-flex-wrap.html]
|
||||
type: reftest
|
||||
expected: FAIL
|
|
@ -0,0 +1,5 @@
|
|||
[viewport-units-after-font-load.html]
|
||||
expected: TIMEOUT
|
||||
[Viewport units are correctly updated after resize even if a font load has happened before]
|
||||
expected: TIMEOUT
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
[cors-preflight-response-validation.any.html]
|
||||
[Preflight response with a bad Access-Control-Allow-Methods]
|
||||
expected: FAIL
|
||||
|
||||
[Preflight response with a bad Access-Control-Allow-Headers]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[cors-preflight-response-validation.any.worker.html]
|
||||
[Preflight response with a bad Access-Control-Allow-Methods]
|
||||
expected: FAIL
|
||||
|
||||
[Preflight response with a bad Access-Control-Allow-Headers]
|
||||
expected: FAIL
|
||||
|
|
@ -312,24 +312,24 @@
|
|||
[fetch(): separate response Content-Type: text/plain ]
|
||||
expected: NOTRUN
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html;" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: */* text/html]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/html;x=" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/html */*]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html */*;charset=gbk]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html;" \\" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/html;" \\" text/plain]
|
||||
[<iframe>: combined response Content-Type: text/html;charset=gbk text/plain text/html]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html;x=" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/plain */*;charset=gbk]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -56,6 +56,6 @@
|
|||
[separate text/javascript x/x]
|
||||
expected: FAIL
|
||||
|
||||
[separate text/javascript;charset=windows-1252 error text/javascript]
|
||||
[separate text/javascript error]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -11,6 +11,3 @@
|
|||
[X-Content-Type-Options%3A%20nosniff%2C%2C%40%23%24%23%25%25%26%5E%26%5E*()()11!]
|
||||
expected: FAIL
|
||||
|
||||
[X-Content-Type-Options%3A%20%40%23%24%23%25%25%26%5E%26%5E*()()11!%2Cnosniff]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[traverse_the_history_4.html]
|
||||
[Multiple history traversals, last would be aborted]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[traverse_the_history_5.html]
|
||||
[Multiple history traversals, last would be aborted]
|
||||
expected: FAIL
|
||||
|
|
@ -18,6 +18,3 @@
|
|||
[Set HTTP URL frame location.protocol to ftp]
|
||||
expected: FAIL
|
||||
|
||||
[Set data URL frame location.protocol to file]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[img-aspect-ratio-lazy.tentative.html]
|
||||
[Image width and height attributes are used to infer aspect-ratio for lazy-loaded images]
|
||||
expected: FAIL
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
[iframe_sandbox_popups_escaping-3.html]
|
||||
type: testharness
|
||||
expected: CRASH
|
||||
expected: TIMEOUT
|
||||
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
|
||||
expected: TIMEOUT
|
||||
|
||||
|
|
|
@ -53,3 +53,6 @@
|
|||
[X Rendered audio for channel 5 does not equal [0,0.0626220703125,0.125030517578125,0.18695068359375,0.24810791015625,0.308319091796875,0.3673095703125,0.42486572265625,0.480743408203125,0.53472900390625,0.58660888671875,0.636199951171875,0.68328857421875,0.727691650390625,0.76922607421875,0.8077392578125...\] with an element-wise tolerance of {"absoluteThreshold":0.000030517578125,"relativeThreshold":0}.\n\tIndex\tActual\t\t\tExpected\t\tAbsError\t\tRelError\t\tTest threshold\n\t[1\]\t3.6732959747314453e-1\t6.2622070312500000e-2\t3.0470752716064453e-1\t4.8658168859649127e+0\t3.0517578125000000e-5\n\t[2\]\t6.8329977989196777e-1\t1.2503051757812500e-1\t5.5826926231384277e-1\t4.4650639949963384e+0\t3.0517578125000000e-5\n\t[3\]\t9.0373212099075317e-1\t1.8695068359375000e-1\t7.1678143739700317e-1\t3.8340669508039502e+0\t3.0517578125000000e-5\n\t[4\]\t9.9780619144439697e-1\t2.4810791015625000e-1\t7.4969828128814697e-1\t3.0216621502152523e+0\t3.0517578125000000e-5\n\t[5\]\t9.5236867666244507e-1\t3.0831909179687500e-1\t6.4404958486557007e-1\t2.0889059484187866e+0\t3.0517578125000000e-5\n\t...and 40534 more errors.\n\tMax AbsError of 1.9986916780471802e+0 at index of 29020.\n\t[29020\]\t9.9994289875030518e-1\t-9.9874877929687500e-1\t1.9986916780471802e+0\t2.0011956154322119e+0\t3.0517578125000000e-5\n\tMax RelError of Infinity at index of 12348.\n\t[12348\]\t9.5105654001235962e-1\t0.0000000000000000e+0\t9.5105654001235962e-1\tInfinity\t3.0517578125000000e-5\n]
|
||||
expected: FAIL
|
||||
|
||||
[X Rendered audio for channel 5 does not equal [0,0.0626220703125,0.125030517578125,0.18695068359375,0.24810791015625,0.308319091796875,0.3673095703125,0.42486572265625,0.480743408203125,0.53472900390625,0.58660888671875,0.636199951171875,0.68328857421875,0.727691650390625,0.76922607421875,0.8077392578125...\] with an element-wise tolerance of {"absoluteThreshold":0.000030517578125,"relativeThreshold":0}.\n\tIndex\tActual\t\t\tExpected\t\tAbsError\t\tRelError\t\tTest threshold\n\t[1\]\t3.6732959747314453e-1\t6.2622070312500000e-2\t3.0470752716064453e-1\t4.8658168859649127e+0\t3.0517578125000000e-5\n\t[2\]\t6.8329977989196777e-1\t1.2503051757812500e-1\t5.5826926231384277e-1\t4.4650639949963384e+0\t3.0517578125000000e-5\n\t[3\]\t9.0373212099075317e-1\t1.8695068359375000e-1\t7.1678143739700317e-1\t3.8340669508039502e+0\t3.0517578125000000e-5\n\t[4\]\t9.9780619144439697e-1\t2.4810791015625000e-1\t7.4969828128814697e-1\t3.0216621502152523e+0\t3.0517578125000000e-5\n\t[5\]\t9.5236867666244507e-1\t3.0831909179687500e-1\t6.4404958486557007e-1\t2.0889059484187866e+0\t3.0517578125000000e-5\n\t...and 44049 more errors.\n\tMax AbsError of 1.9985756278038025e+0 at index of 16692.\n\t[16692\]\t9.9997943639755249e-1\t-9.9859619140625000e-1\t1.9985756278038025e+0\t2.0013851895322721e+0\t3.0517578125000000e-5\n\tMax RelError of Infinity at index of 10584.\n\t[10584\]\t-5.8778524398803711e-1\t0.0000000000000000e+0\t5.8778524398803711e-1\tInfinity\t3.0517578125000000e-5\n]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -206,3 +206,9 @@
|
|||
[X Stitched sine-wave buffers at sample rate 44100 does not equal [0,0.06264832615852356,0.12505052983760834,0.18696144223213196,0.24813786149024963,0.308339387178421,0.36732959747314453,0.4248766601085663,0.480754554271698,0.5347436666488647,0.5866320133209229,0.6362156271934509,0.6832997798919678,0.7276994585990906,0.7692402601242065,0.8077589869499207...\] with an element-wise tolerance of {"absoluteThreshold":0.000090957,"relativeThreshold":0}.\n\tIndex\tActual\t\t\tExpected\t\tAbsError\t\tRelError\t\tTest threshold\n\t[31080\]\t7.7856257262238438e-27\t5.6332010030746460e-1\t5.6332010030746460e-1\t1.0000000000000000e+0\t9.0957000000000003e-5\n\t[31081\]\t4.5762203949455551e-41\t6.1397600173950195e-1\t6.1397600173950195e-1\t1.0000000000000000e+0\t9.0957000000000003e-5\n\tMax AbsError of 6.1397600173950195e-1 at index of 31081.\n\tMax RelError of 1.0000000000000000e+0 at index of 31080.\n]
|
||||
expected: FAIL
|
||||
|
||||
[X SNR (45.018638895477395 dB) is not greater than or equal to 85.58. Got 45.018638895477395.]
|
||||
expected: FAIL
|
||||
|
||||
[X Stitched sine-wave buffers at sample rate 44100 does not equal [0,0.06264832615852356,0.12505052983760834,0.18696144223213196,0.24813786149024963,0.308339387178421,0.36732959747314453,0.4248766601085663,0.480754554271698,0.5347436666488647,0.5866320133209229,0.6362156271934509,0.6832997798919678,0.7276994585990906,0.7692402601242065,0.8077589869499207...\] with an element-wise tolerance of {"absoluteThreshold":0.000090957,"relativeThreshold":0}.\n\tIndex\tActual\t\t\tExpected\t\tAbsError\t\tRelError\t\tTest threshold\n\t[31080\]\t2.1915524950344434e-12\t5.6332010030746460e-1\t5.6332010030527302e-1\t9.9999999999610956e-1\t9.0957000000000003e-5\n\t[31081\]\t4.5863097438886938e-41\t6.1397600173950195e-1\t6.1397600173950195e-1\t1.0000000000000000e+0\t9.0957000000000003e-5\n\tMax AbsError of 6.1397600173950195e-1 at index of 31081.\n\tMax RelError of 1.0000000000000000e+0 at index of 31081.\n]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
[shared-worker-in-data-url-context.window.html]
|
||||
expected: TIMEOUT
|
||||
[Create a shared worker in a data url frame]
|
||||
expected: FAIL
|
||||
expected: TIMEOUT
|
||||
|
||||
[Create a data url shared worker in a data url frame]
|
||||
expected: FAIL
|
||||
expected: NOTRUN
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ def main(request, response):
|
|||
"sec-ch-ua-arch",
|
||||
"sec-ch-ua-platform",
|
||||
"sec-ch-ua-model",
|
||||
"sec-ch-ua-full-version",
|
||||
]
|
||||
|
||||
request_client_hints = {i: request.headers.get(i) for i in client_hint_headers}
|
||||
|
|
|
@ -5,21 +5,53 @@
|
|||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/common/utils.js"></script>
|
||||
<script>
|
||||
const verify_headers = (header_list, response, verification_func) => {
|
||||
header_list.forEach(header => {
|
||||
const value = response.headers.get(header+"-recieved");
|
||||
if(value) {
|
||||
verification_func(value);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
promise_test(async (test) => {
|
||||
var request_token = token();
|
||||
var client_hint_headers = [
|
||||
const request_token = token();
|
||||
const string_list_client_hint_headers = [
|
||||
"sec-ch-ua",
|
||||
];
|
||||
const string_client_hint_headers = [
|
||||
"sec-ch-ua-arch",
|
||||
"sec-ch-ua-platform",
|
||||
"sec-ch-ua-model",
|
||||
"sec-ch-ua-full-version",
|
||||
];
|
||||
const boolean_client_hint_headers = [
|
||||
"sec-ch-mobile",
|
||||
];
|
||||
|
||||
const response = await fetch("resources/echo-ua-client-hints-received.py");
|
||||
client_hint_headers.forEach(header => {
|
||||
if(response.headers.get(header+"-recieved")) {
|
||||
verify_headers(string_client_hint_headers, response, value => {
|
||||
if(value) {
|
||||
// Check that the hints have quotes
|
||||
assert_equals(response.headers.get(header+"-recieved").slice(0,1), "\"");
|
||||
assert_equals(response.headers.get(header+"-recieved").slice(-1), "\"");
|
||||
// TODO(yoav): this doesn't account for parameters. Need an SH parser, that verifies no parameters are present.
|
||||
assert_equals(value.slice(0,1), "\"");
|
||||
assert_equals(value.slice(-1), "\"");
|
||||
}
|
||||
});
|
||||
verify_headers(string_list_client_hint_headers, response, value => {
|
||||
// Check that the hints have quotes
|
||||
// TODO(yoav): this doesn't account for list parsing or parameters. Need an SH parser, that verifies this is a list of strings with a "v" parameter present in at least one value.
|
||||
assert_false((typeof value) == "undefined");
|
||||
assert_equals(value.slice(0,1), "\"");
|
||||
assert_equals(value.slice(-1), "\"");
|
||||
});
|
||||
verify_headers(boolean_client_hint_headers, response, value => {
|
||||
if(value) {
|
||||
// Check that the value is a valid boolean
|
||||
assert_false((typeof value) == "undefined");
|
||||
assert_equals(value.slice(0,1), "?");
|
||||
const num = value.slice(-1);
|
||||
assert_true(num == "0" || num == "1");
|
||||
}
|
||||
});
|
||||
}, 'User agent client hint header values are surrounded by quotes');
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
window.onmessage = e => {
|
||||
try {
|
||||
assert_not_equals(e.data.header, "", "The `Sec-CH-UA` header is delivered.");
|
||||
assert_not_equals(e.data.header, minor, "The `Sec-CH-UA` header is different after the opt-in than before.");
|
||||
assert_equals(e.data.header, minor, "The `Sec-CH-UA` header did not change after the opt-in.");
|
||||
} catch (ex) {
|
||||
reject(ex);
|
||||
}
|
||||
|
|
|
@ -42,9 +42,9 @@ promise_test(async t => {
|
|||
const animA = div.animate({margin: ["100px","100px"]}, 100000);
|
||||
assert_equals(getComputedStyle(div).marginLeft, '100px');
|
||||
div.style.animation = 'margin50 100s';
|
||||
assert_equals(getComputedStyle(div).marginLeft, '50px');
|
||||
// Wait for animation starts
|
||||
await waitForAnimationFrames(2);
|
||||
await animA.ready;
|
||||
await waitForAnimationFrames(1);
|
||||
assert_equals(getComputedStyle(div).marginLeft, '100px',
|
||||
"A higher-priority animation is not overriden by a more recent"
|
||||
+ "one.");
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD//XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>CSS Test: A flex container with 'flex-flow' set to 'wrap'</title>
|
||||
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
|
||||
<link rel="help" href="http://www.w3.org/TR/css-flexbox-1/#flex-wrap-property" />
|
||||
<meta name="flags" content="">
|
||||
<meta name="assert" content="This test checks that the flex container with 'flex-flow: wrap' is a multi-line flex container." />
|
||||
<style type="text/css">
|
||||
#flexbox
|
||||
{
|
||||
background-color: red;
|
||||
display: flex;
|
||||
flex-flow: wrap;
|
||||
height: 100px;
|
||||
width: 300px;
|
||||
}
|
||||
div div
|
||||
{
|
||||
background-color: orange;
|
||||
width: 150px;
|
||||
}
|
||||
.blue
|
||||
{
|
||||
background-color: blue;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Test passes if there is a single blue rectangle on the left, a single orange rectangle directly to its right, and there is no red visible on the page.</p>
|
||||
<div id="flexbox">
|
||||
<div class="blue"></div>
|
||||
<div></div>
|
||||
<div class="blue"></div>
|
||||
<div></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,24 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Flexible Box Test: flex-wrap_nowrap</title>
|
||||
<link rel="author" title="Intel" href="http://www.intel.com" />
|
||||
<link rel="help" href="http://www.w3.org/TR/css-flexbox-1/#flex-wrap-property" />
|
||||
<link rel="stylesheet" href="support/test-style.css">
|
||||
<meta name="flags" content="" />
|
||||
<meta name="assert" content="Check if the web engine can identify the flex-wrap value nowrap." />
|
||||
<style>
|
||||
#test{
|
||||
width: 120px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Test passes if:<br>
|
||||
1. the rectangle 1, 2, 3 show up in a row and no gap between them.</p>
|
||||
<div id=test><div id=test01>1</div><div id=test02>2</div><div id=test03>3</div></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,25 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Flexible Box Test: flex-wrap_wrap-reverse</title>
|
||||
<link rel="author" title="Intel" href="http://www.intel.com" />
|
||||
<link rel="help" href="http://www.w3.org/TR/css-flexbox-1/#flex-wrap-property" />
|
||||
<link rel="stylesheet" href="support/test-style.css">
|
||||
<meta name="flags" content="" />
|
||||
<meta name="assert" content="Check if the web engine can identify the flex-wrap value wrap-reverse." />
|
||||
<style>
|
||||
#test{
|
||||
width: 120px;
|
||||
display: flex;
|
||||
flex-wrap: wrap-reverse;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Test passes if:<br>
|
||||
1. the rectangle 1, 2, 3 show up in two rows in a red rectangle and no gap between them.<br>
|
||||
2. the rectangle 3 appear in the first line of rows.<br>
|
||||
3. the rectangles appear in upper left of the red rectangle.</p>
|
||||
<div id=test><div id=test01>1</div><div id=test02>2</div><div id=test03>3</div></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,25 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Flexible Box Test: flex-wrap_wrap</title>
|
||||
<link rel="author" title="Intel" href="http://www.intel.com" />
|
||||
<link rel="help" href="http://www.w3.org/TR/css-flexbox-1/#flex-wrap-property" />
|
||||
<link rel="stylesheet" href="support/test-style.css">
|
||||
<meta name="flags" content="" />
|
||||
<meta name="assert" content="Check if the display can recognize inline-flex value." />
|
||||
<style>
|
||||
div#test{
|
||||
width: 120px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Test passes if:<br>
|
||||
1. the rectangle 1, 2, 3 show up in two rows in a red rectangle and no gap between them.<br>
|
||||
2. the rectangle 1 appear in the first line of rows.<br>
|
||||
3. the rectangles appear in upper left of the red rectangle.</p>
|
||||
<div id=test><div id=test01>1</div><div id=test02>2</div><div id=test03>3</div></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,36 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Flexible Box Test: flex-wrap proprety - wrap</title>
|
||||
<link rel="author" title="haosdent" href="mailto:haosdent@gmail.com">
|
||||
<style type="text/css">
|
||||
/* Positioned container allows for the self-describing statement to still
|
||||
be visible in the case of failure */
|
||||
.container {
|
||||
position: relative;
|
||||
background: red;
|
||||
margin: 1em 0;
|
||||
border: 1px solid black;
|
||||
width: 20em;
|
||||
height: 6.5em;
|
||||
}
|
||||
span {
|
||||
display: inline-block;
|
||||
background: green;
|
||||
color: white;
|
||||
margin: 1em;
|
||||
width: 8em;
|
||||
float: left;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>The test passed if you see a 2 * 2 table on the page.</p>
|
||||
<div class="container">
|
||||
<span>first</span>
|
||||
<span>second</span>
|
||||
<span>third</span>
|
||||
<span>forth</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,36 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Flexible Box Test: flex-wrap proprety - wrap-reverse</title>
|
||||
<link rel="author" title="haosdent" href="mailto:haosdent@gmail.com">
|
||||
<style type="text/css">
|
||||
/* Positioned container allows for the self-describing statement to still
|
||||
be visible in the case of failure */
|
||||
.container {
|
||||
position: relative;
|
||||
background: red;
|
||||
margin: 1em 0;
|
||||
border: 1px solid black;
|
||||
width: 20em;
|
||||
height: 6.5em;
|
||||
}
|
||||
span {
|
||||
display: inline-block;
|
||||
background: green;
|
||||
color: white;
|
||||
margin: 1em;
|
||||
width: 8em;
|
||||
float: left;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>The test passed if you see a 2 * 2 table on the page and the order of them are reversed.</p>
|
||||
<div class="container">
|
||||
<span>third</span>
|
||||
<span>forth</span>
|
||||
<span>first</span>
|
||||
<span>second</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,40 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Flexible Box Test: flex-wrap proprety - wrap-reverse</title>
|
||||
<link rel="author" title="haosdent" href="mailto:haosdent@gmail.com">
|
||||
<link rel="help" href="http://www.w3.org/TR/css-flexbox-1/#flex-wrap-property">
|
||||
<link rel="match" href="reference/ttwf-reftest-flex-wrap-reverse-ref.html">
|
||||
<meta name="assert" content="Statement describing what the test case is asserting">
|
||||
<style type="text/css">
|
||||
/* Positioned container allows for the self-describing statement to still
|
||||
be visible in the case of failure */
|
||||
.container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-wrap: wrap-reverse;
|
||||
background: red;
|
||||
margin: 1em 0;
|
||||
border: 1px solid black;
|
||||
width: 20em;
|
||||
height: 6.5em;
|
||||
}
|
||||
span {
|
||||
display: inline-block;
|
||||
background: green;
|
||||
color: white;
|
||||
margin: 1em;
|
||||
width: 8em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>The test passed if you see a 2 * 2 table on the page and the order of them are reversed.</p>
|
||||
<div class="container">
|
||||
<span>first</span>
|
||||
<span>second</span>
|
||||
<span>third</span>
|
||||
<span>forth</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,40 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Flexible Box Test: flex-wrap proprety - wrap</title>
|
||||
<link rel="author" title="haosdent" href="mailto:haosdent@gmail.com">
|
||||
<link rel="help" href="http://www.w3.org/TR/css-flexbox-1/#flex-wrap-property">
|
||||
<link rel="match" href="reference/ttwf-reftest-flex-wrap-ref.html">
|
||||
<meta name="assert" content="Statement describing what the test case is asserting">
|
||||
<style type="text/css">
|
||||
/* Positioned container allows for the self-describing statement to still
|
||||
be visible in the case of failure */
|
||||
.container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
background: red;
|
||||
margin: 1em 0;
|
||||
border: 1px solid black;
|
||||
width: 20em;
|
||||
height: 6.5em;
|
||||
}
|
||||
span {
|
||||
display: inline-block;
|
||||
background: green;
|
||||
color: white;
|
||||
margin: 1em;
|
||||
width: 8em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>The test passed if you see a 2 * 2 table on the page.</p>
|
||||
<div class="container">
|
||||
<span>first</span>
|
||||
<span>second</span>
|
||||
<span>third</span>
|
||||
<span>forth</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Values: Viewport units are computed correctly after font load.</title>
|
||||
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
|
||||
<link rel="author" title="Mozilla" href="https://mozilla.org">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-values-4/#viewport-relative-lengths">
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1620359">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<iframe width=300 height=300 scrolling=no srcdoc=""></iframe>
|
||||
<script>
|
||||
let t = async_test("Viewport units are correctly updated after resize even if a font load has happened before");
|
||||
let iframe = document.querySelector("iframe");
|
||||
onload = t.step_func(function() {
|
||||
let doc = iframe.contentDocument;
|
||||
let win = iframe.contentWindow;
|
||||
doc.body.innerHTML = `
|
||||
<div style="width: 100vw; height: 100vh; background: green"></div>
|
||||
`;
|
||||
let div = doc.querySelector("div");
|
||||
let oldWidth = win.getComputedStyle(div).width;
|
||||
let oldHeight = win.getComputedStyle(div).height;
|
||||
assert_equals(oldWidth, win.innerWidth + "px", "Should fill the viewport");
|
||||
assert_equals(oldHeight, win.innerHeight + "px", "Should fill the viewport");
|
||||
let link = doc.createElement("link");
|
||||
link.rel = "stylesheet";
|
||||
link.href = "/fonts/ahem.css";
|
||||
link.onload = t.step_func(function() {
|
||||
iframe.width = 400;
|
||||
win.requestAnimationFrame(t.step_func(function() {
|
||||
win.requestAnimationFrame(t.step_func_done(function() {
|
||||
let newWidth = win.getComputedStyle(div).width;
|
||||
let newHeight = win.getComputedStyle(div).height;
|
||||
assert_equals(newWidth, win.innerWidth + "px", "Should fill the viewport");
|
||||
assert_equals(newHeight, win.innerHeight + "px", "Should fill the viewport");
|
||||
assert_equals(newHeight, oldHeight, "Height shouldn't have changed");
|
||||
assert_not_equals(newWidth, oldWidth, "Width should have changed");
|
||||
}));
|
||||
}));
|
||||
});
|
||||
doc.body.appendChild(link);
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,33 @@
|
|||
// META: script=/common/utils.js
|
||||
// META: script=../resources/utils.js
|
||||
// META: script=/common/get-host-info.sub.js
|
||||
|
||||
function corsPreflightResponseValidation(desc, corsUrl, allowHeaders, allowMethods) {
|
||||
var uuid_token = token();
|
||||
var url = corsUrl;
|
||||
var requestInit = {"mode": "cors"};
|
||||
/* Force preflight */
|
||||
requestInit["headers"] = {"x-force-preflight": ""};
|
||||
|
||||
var urlParameters = "?token=" + uuid_token + "&max_age=0";
|
||||
urlParameters += "&allow_headers=x-force-preflight";
|
||||
if (allowHeaders)
|
||||
urlParameters += "," + allowHeaders;
|
||||
if (allowMethods)
|
||||
urlParameters += "&allow_methods="+ allowMethods;
|
||||
|
||||
promise_test(function(test) {
|
||||
return fetch(RESOURCES_DIR + "clean-stash.py?token=" + uuid_token).then(async function(resp) {
|
||||
assert_equals(resp.status, 200, "Clean stash response's status is 200");
|
||||
await promise_rejects_js(test, TypeError, fetch(url + urlParameters, requestInit));
|
||||
|
||||
return fetch(url + urlParameters).then(function(resp) {
|
||||
assert_equals(resp.headers.get("x-did-preflight"), "1", "Preflight request has been made");
|
||||
});
|
||||
});
|
||||
}, desc);
|
||||
}
|
||||
|
||||
var corsUrl = get_host_info().HTTP_REMOTE_ORIGIN + dirname(location.pathname) + RESOURCES_DIR + "preflight.py";
|
||||
corsPreflightResponseValidation("Preflight response with a bad Access-Control-Allow-Headers", corsUrl, "Bad value", null);
|
||||
corsPreflightResponseValidation("Preflight response with a bad Access-Control-Allow-Methods", corsUrl, null, "Bad value");
|
|
@ -0,0 +1,237 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title> Check COEP report are send for CacheStorage requests</title>
|
||||
<meta name="timeout" content="long">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/common/get-host-info.sub.js"></script>
|
||||
<script src="/common/utils.js"></script>
|
||||
<script src="/service-workers/service-worker/resources/test-helpers.sub.js">
|
||||
</script>
|
||||
</head>
|
||||
<script>
|
||||
|
||||
function remote(path) {
|
||||
const REMOTE_ORIGIN = get_host_info().HTTPS_REMOTE_ORIGIN;
|
||||
return new URL(path, REMOTE_ORIGIN);
|
||||
}
|
||||
|
||||
function local(path) {
|
||||
return new URL(path, location.origin);
|
||||
}
|
||||
|
||||
let encode = function(url) {
|
||||
return encodeURI(url).replace(/\;/g,"%3B");
|
||||
}
|
||||
|
||||
const resource_path = (new URL("./resources", location)).pathname;
|
||||
const report_token= token();
|
||||
const report_endpoint_url = local(resource_path + `/report.py?key=${report_token}`)
|
||||
const endpoint =
|
||||
{
|
||||
"group":"endpoint",
|
||||
"max_age":3600,
|
||||
"endpoints":[{ "url":report_endpoint_url.toString() }]
|
||||
};
|
||||
let endpoint_string =
|
||||
JSON.stringify(endpoint)
|
||||
.replace(/,/g, "\\,")
|
||||
.replace(/\(/g, "\\\(")
|
||||
.replace(/\)/g, "\\\)=");
|
||||
const header_report_to = `|header(report-to,${endpoint_string})`;
|
||||
const header_coep =
|
||||
'|header(Cross-Origin-Embedder-Policy,require-corp;report-to="endpoint")';
|
||||
const header_coep_report_only =
|
||||
'|header(Cross-Origin-Embedder-Policy-Report-Only,require-corp;report-to="endpoint")';
|
||||
const SW_SCOPE = local(resource_path + "/");
|
||||
const header_service_worker_allowed =
|
||||
`|header(service-worker-allowed,${SW_SCOPE})`;
|
||||
|
||||
const iframe_path = resource_path + "/iframe.html?pipe=";
|
||||
const worker_path = resource_path + "/universal-worker.js?pipe=";
|
||||
const image_url = remote("/images/blue.png");
|
||||
|
||||
// This script attempt to load a COEP:require-corp CORP:undefined response from
|
||||
// the CacheStorage.
|
||||
//
|
||||
// Executed from different context:
|
||||
// - A Document
|
||||
// - A ServiceWorker
|
||||
// - A DedicatedWorker
|
||||
// - A SharedWorker
|
||||
//
|
||||
// The context has either COEP or COEP-Report-Only defined.
|
||||
const eval_script = `
|
||||
(async function() {
|
||||
try {
|
||||
const cache = await caches.open('v1');
|
||||
const request = new Request('${image_url}', { mode: 'no-cors' });
|
||||
const response = await cache.match(request);
|
||||
} catch(e) {
|
||||
}
|
||||
})()
|
||||
`;
|
||||
|
||||
promise_setup(async (t) => {
|
||||
const cache = await caches.open('v1');
|
||||
const fetch_request = new Request(image_url, {mode: 'no-cors'});
|
||||
const fetch_response = await fetch(fetch_request);
|
||||
await cache.put(fetch_request, fetch_response);
|
||||
}, "Setup: store a CORS:cross-origin COEP:none response into CacheStorage")
|
||||
|
||||
async function makeIframe(test, iframe_url) {
|
||||
const iframe = document.createElement("iframe");
|
||||
test.add_cleanup(() => iframe.remove());
|
||||
iframe.src = iframe_url;
|
||||
const iframe_loaded = new Promise(resolve => iframe.onload = resolve);
|
||||
document.body.appendChild(iframe);
|
||||
await iframe_loaded;
|
||||
return iframe;
|
||||
}
|
||||
|
||||
function wait(ms) {
|
||||
return new Promise(resolve => step_timeout(resolve, ms));
|
||||
}
|
||||
|
||||
async function fetchReport() {
|
||||
const fetch_report_path = resource_path + `/report.py?key=${report_token}`;
|
||||
for(let i = 0; i<10; ++i) {
|
||||
const response = await fetch(encode(fetch_report_path));
|
||||
const reports = await response.json();
|
||||
if (reports.length == 0) {
|
||||
wait(100);
|
||||
continue;
|
||||
}
|
||||
if (reports.length != 1)
|
||||
throw "Too many reports received";
|
||||
|
||||
return reports[0];
|
||||
}
|
||||
throw "Report not send";
|
||||
}
|
||||
|
||||
// Remove parts of the URL that are differ at runtime.
|
||||
function normalize(url) {
|
||||
url = new URL(url);
|
||||
return url.origin + url.pathname;
|
||||
}
|
||||
|
||||
promise_test(async (t) => {
|
||||
const iframe_url =
|
||||
local(encode(iframe_path + header_coep + header_report_to));
|
||||
const iframe = await makeIframe(t, iframe_url);
|
||||
iframe.contentWindow.postMessage(eval_script);
|
||||
const report = await fetchReport();
|
||||
assert_equals(report["body"]["blocked-url"], image_url.toString());
|
||||
assert_equals(report["body"]["type"], "corp");
|
||||
assert_equals(report["type"], "coep");
|
||||
assert_equals(normalize(report["url"]), normalize(iframe_url.toString()));
|
||||
}, "COEP support on document.")
|
||||
|
||||
promise_test(async (t) => {
|
||||
const iframe_url =
|
||||
local(encode(iframe_path + header_coep_report_only + header_report_to));
|
||||
const iframe = await makeIframe(t, iframe_url);
|
||||
iframe.contentWindow.postMessage(eval_script);
|
||||
const report = await fetchReport();
|
||||
assert_equals(report["body"]["blocked-url"], image_url.toString());
|
||||
assert_equals(report["body"]["type"], "corp");
|
||||
assert_equals(report["type"], "coep");
|
||||
assert_equals(normalize(report["url"]), normalize(iframe_url.toString()));
|
||||
}, "COEP-Report-Only support on document.")
|
||||
|
||||
promise_test(async (t) => {
|
||||
const worker_url = local(encode(worker_path));
|
||||
const iframe_url =
|
||||
local(encode(iframe_path + header_coep + header_report_to));
|
||||
dedicated_worker_script = `
|
||||
(async function() {
|
||||
const w = new Worker('${worker_url}');
|
||||
w.postMessage(\`${eval_script}\`);
|
||||
})();
|
||||
`;
|
||||
const iframe = await makeIframe(t, iframe_url);
|
||||
iframe.contentWindow.postMessage(dedicated_worker_script);
|
||||
const report = await fetchReport();
|
||||
assert_equals(report["body"]["blocked-url"], image_url.toString());
|
||||
assert_equals(report["body"]["type"], "corp");
|
||||
assert_equals(report["type"], "coep");
|
||||
assert_equals(normalize(report["url"]), normalize(worker_url.toString()));
|
||||
}, "COEP support on DedicatedWorker.")
|
||||
|
||||
promise_test(async (t) => {
|
||||
const worker_url = local(encode(worker_path));
|
||||
const iframe_url =
|
||||
local(encode(iframe_path + header_coep_report_only + header_report_to));
|
||||
dedicated_worker_script = `
|
||||
(async function() {
|
||||
const w = new Worker('${worker_url}');
|
||||
w.postMessage(\`${eval_script}\`);
|
||||
})();
|
||||
`;
|
||||
const iframe = await makeIframe(t, iframe_url);
|
||||
iframe.contentWindow.postMessage(dedicated_worker_script);
|
||||
const report = await fetchReport();
|
||||
assert_equals(report["body"]["blocked-url"], image_url.toString());
|
||||
assert_equals(report["body"]["type"], "corp");
|
||||
assert_equals(report["type"], "coep");
|
||||
assert_equals(normalize(report["url"]), normalize(worker_url.toString()));
|
||||
}, "COEP-Report-Only support on DedicatedWorker.")
|
||||
|
||||
promise_test(async (t) => {
|
||||
const worker_url =
|
||||
local(encode(worker_path + header_coep + header_report_to));
|
||||
const worker = new Worker(worker_url);
|
||||
worker.postMessage(eval_script);
|
||||
const report = await fetchReport();
|
||||
assert_equals(report["body"]["blocked-url"], image_url.toString());
|
||||
assert_equals(report["body"]["type"], "corp");
|
||||
assert_equals(report["type"], "coep");
|
||||
assert_equals(normalize(report["url"]), normalize(worker_url.toString()));
|
||||
}, "COEP support on SharedWorker.")
|
||||
|
||||
promise_test(async (t) => {
|
||||
const worker_url =
|
||||
local(encode(worker_path + header_coep_report_only + header_report_to));
|
||||
const worker = new Worker(worker_url);
|
||||
worker.postMessage(eval_script);
|
||||
const report = await fetchReport();
|
||||
assert_equals(report["body"]["blocked-url"], image_url.toString());
|
||||
assert_equals(report["body"]["type"], "corp");
|
||||
assert_equals(report["type"], "coep");
|
||||
assert_equals(normalize(report["url"]), normalize(worker_url.toString()));
|
||||
}, "COEP-Report-Only support on SharedWorker.")
|
||||
|
||||
promise_test(async (t) => {
|
||||
const worker_url =
|
||||
local(encode(worker_path + header_coep + header_service_worker_allowed));
|
||||
const reg =
|
||||
await service_worker_unregister_and_register(t, worker_url, SW_SCOPE);
|
||||
add_completion_callback(() => reg.unregister());
|
||||
const worker = reg.installing || reg.waiting || reg.active;
|
||||
worker.postMessage(eval_script);
|
||||
const report = await fetchReport();
|
||||
assert_equals(report["body"]["blocked-url"], image_url.toString());
|
||||
assert_equals(report["body"]["type"], "corp");
|
||||
assert_equals(report["type"], "coep");
|
||||
assert_equals(normalize(report["url"]), normalize(worker_url.toString()));
|
||||
}, "COEP support on ServiceWorker.")
|
||||
|
||||
promise_test(async (t) => {
|
||||
const worker_url =
|
||||
local(encode(worker_path + header_coep_report_only + header_service_worker_allowed))
|
||||
const reg =
|
||||
await service_worker_unregister_and_register(t, worker_url, SW_SCOPE);
|
||||
add_completion_callback(() => reg.unregister());
|
||||
const worker = reg.installing || reg.waiting || reg.active;
|
||||
worker.postMessage(eval_script);
|
||||
const report = await fetchReport();
|
||||
assert_equals(report["body"]["blocked-url"], image_url.toString());
|
||||
assert_equals(report["body"]["type"], "corp");
|
||||
assert_equals(report["type"], "coep");
|
||||
assert_equals(normalize(report["url"]), normalize(worker_url.toString()));
|
||||
}, "COEP-Report-Only support on ServiceWorker.")
|
||||
|
||||
</script>
|
||||
</html>
|
|
@ -1,11 +1,12 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<html>
|
||||
<meta name="timeout" content="long">
|
||||
<body>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/common/utils.js"></script>
|
||||
<script src="/common/get-host-info.sub.js"></script>
|
||||
<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
const HOST = get_host_info();
|
||||
const REMOTE_ORIGIN = HOST.REMOTE_ORIGIN;
|
||||
|
@ -28,8 +29,8 @@ async function pollReports(endpoint, reports) {
|
|||
}
|
||||
}
|
||||
|
||||
let reports = []
|
||||
let reportsForReportOnly = []
|
||||
const reports = [];
|
||||
const reportsForReportOnly = [];
|
||||
pollReports('endpoint', reports);
|
||||
pollReports('report-only-endpoint', reportsForReportOnly);
|
||||
|
||||
|
@ -48,6 +49,21 @@ function checkCorpReportExistence(reports, blockedUrl, contextUrl) {
|
|||
assert_unreached(`A report whose blocked-url is ${blockedUrl} and url is ${contextUrl} is not found.`);
|
||||
}
|
||||
|
||||
function checkNavigationReportExistence(reports, blockedUrl, contextUrl) {
|
||||
blockedUrl = new URL(blockedUrl, location).href;
|
||||
contextUrl = new URL(contextUrl, location).href;
|
||||
for (const report of reports) {
|
||||
if (report.type !== 'coep' || report.url !== contextUrl ||
|
||||
report.body.type !== 'navigation') {
|
||||
continue;
|
||||
}
|
||||
if (report.body['blocked-url'] === blockedUrl) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert_unreached(`A report whose blocked-url is ${blockedUrl} and url is ${contextUrl} is not found.`);
|
||||
}
|
||||
|
||||
function checkReportNonExistence(reports, blockedUrl, contextUrl) {
|
||||
blockedUrl = new URL(blockedUrl, location).href;
|
||||
contextUrl = new URL(contextUrl, location).href;
|
||||
|
@ -87,7 +103,8 @@ async_test(async (t) => {
|
|||
fetchInIframe(blockedDueToCoep);
|
||||
fetchInIframe(redirect);
|
||||
|
||||
await new Promise(resolve => t.step_timeout(resolve, 3000));
|
||||
// Wait 3 seconds for reports to settle.
|
||||
await wait(3000);
|
||||
|
||||
checkReportNonExistence(reports, sameOriginUrl, iframe.src);
|
||||
checkReportNonExistence(reports, blockedByPureCorp, iframe.src);
|
||||
|
@ -101,6 +118,68 @@ async_test(async (t) => {
|
|||
}
|
||||
}, 'subresource CORP');
|
||||
|
||||
async_test(async (t) => {
|
||||
try {
|
||||
const IFRAME_SRC = 'resources/coep-iframe.html';
|
||||
const SCOPE = new URL(IFRAME_SRC, location).pathname;
|
||||
const SCRIPT =
|
||||
'resources/sw.js?' +
|
||||
`pipe=header(service-worker-allowed,${SCOPE})|` +
|
||||
'header(cross-origin-embedder-policy,require-corp%3breport-to=%22endpoint%22)|' +
|
||||
'header(cross-origin-embedder-policy-report-only,require-corp%3breport-to=%22report-only-endpoint%22)';
|
||||
|
||||
const reg = await service_worker_unregister_and_register(t, SCRIPT, SCOPE);
|
||||
await wait_for_state(t, reg.installing, 'activated');
|
||||
|
||||
const iframe = document.createElement('iframe');
|
||||
t.add_cleanup(() => {
|
||||
iframe.remove();
|
||||
reg.unregister();
|
||||
});
|
||||
iframe.src = IFRAME_SRC;
|
||||
document.body.appendChild(iframe);
|
||||
await new Promise(resolve => {
|
||||
iframe.addEventListener('load', resolve, {once: true});
|
||||
});
|
||||
|
||||
document.body.appendChild(iframe);
|
||||
await new Promise(resolve => {
|
||||
iframe.addEventListener('load', resolve, {once: true});
|
||||
});
|
||||
|
||||
function fetchInIframe(url) {
|
||||
const init = { mode: 'no-cors', cache: 'no-store' };
|
||||
iframe.contentWindow.fetch(url, init).catch(() => {});
|
||||
}
|
||||
|
||||
const suffix = 'subresource-corp-sw';
|
||||
const sameOriginUrl = `/common/text-plain.txt?${suffix}`;
|
||||
const blockedByPureCorp = `${REMOTE_ORIGIN}${BASE}/nothing-same-origin-corp.txt?${suffix}`;
|
||||
const blockedDueToCoep = `${REMOTE_ORIGIN}/common/text-plain.txt?abc&${suffix}`;
|
||||
const dest = `${REMOTE_ORIGIN}/common/text-plain.txt?xyz&${suffix}`;
|
||||
const redirect = `/common/redirect.py?location=${encodeURIComponent(dest)}&${suffix}`;
|
||||
|
||||
fetchInIframe(sameOriginUrl);
|
||||
fetchInIframe(blockedByPureCorp);
|
||||
fetchInIframe(blockedDueToCoep);
|
||||
fetchInIframe(redirect);
|
||||
|
||||
// Wait 3 seconds for reports to settle.
|
||||
await wait(3000);
|
||||
|
||||
const contextUrl = SCRIPT;
|
||||
checkReportNonExistence(reports, sameOriginUrl, contextUrl);
|
||||
checkReportNonExistence(reports, blockedByPureCorp, contextUrl);
|
||||
checkCorpReportExistence(reports, blockedDueToCoep, contextUrl);
|
||||
checkCorpReportExistence(reports, redirect, contextUrl);
|
||||
checkReportNonExistence(reports, dest, contextUrl);
|
||||
|
||||
t.done();
|
||||
} catch (e) {
|
||||
t.step(() => { throw e });
|
||||
}
|
||||
}, 'CORP for subresource requests initiated from a service worker');
|
||||
|
||||
async_test(async (t) => {
|
||||
try {
|
||||
const iframe = document.createElement('iframe');
|
||||
|
@ -121,16 +200,18 @@ async_test(async (t) => {
|
|||
}
|
||||
|
||||
const suffix = 'navigation-corp';
|
||||
const sameOrigin = `/common/blank.html?${suffix}`;
|
||||
const blockedDueToCoep = `${REMOTE_ORIGIN}/common/blank.html?abc&${suffix}`;
|
||||
const dest = `${REMOTE_ORIGIN}/common/blank.html?xyz&${suffix}`;
|
||||
const coep = `pipe=header(cross-origin-embedder-policy,require-corp)`;
|
||||
const sameOrigin = `/common/blank.html?${coep}&${suffix}`;
|
||||
const blockedDueToCoep = `${REMOTE_ORIGIN}/common/blank.html?${coep}&${suffix}-a`;
|
||||
const dest = `${REMOTE_ORIGIN}/common/blank.html?${coep}&${suffix}-b`;
|
||||
const redirect = `/common/redirect.py?location=${encodeURIComponent(dest)}&${suffix}`;
|
||||
|
||||
attachFrame(sameOrigin);
|
||||
attachFrame(blockedDueToCoep);
|
||||
attachFrame(redirect);
|
||||
|
||||
await new Promise(resolve => t.step_timeout(resolve, 3000));
|
||||
// Wait 3 seconds for reports to settle.
|
||||
await wait(3000);
|
||||
|
||||
checkReportNonExistence(reports, sameOrigin, iframe.src);
|
||||
checkCorpReportExistence(reports, blockedDueToCoep, iframe.src);
|
||||
|
@ -143,4 +224,187 @@ async_test(async (t) => {
|
|||
}
|
||||
}, 'navigation CORP');
|
||||
|
||||
</script>
|
||||
async_test(async (t) => {
|
||||
try {
|
||||
const iframe = document.createElement('iframe');
|
||||
t.add_cleanup(() => iframe.remove());
|
||||
|
||||
const suffix = '&navigation-coep';
|
||||
const corp = 'header(cross-origin-resource-policy,cross-origin)';
|
||||
const noCoep = `pipe=${corp}`;
|
||||
const coep =
|
||||
`pipe=header(cross-origin-embedder-policy,require-corp%3breport-to=%22endpoint%22)|${corp}`;
|
||||
const coepReportOnly =
|
||||
`pipe=header(cross-origin-embedder-policy-report-only,require-corp%3breport-to=%22report-only-endpoint%22)|${corp}`;
|
||||
const path = `/common/blank.html`;
|
||||
const pipes = [noCoep, coep, coepReportOnly];
|
||||
const settings = new Map();
|
||||
settings.set(noCoep, {
|
||||
pipe: noCoep,
|
||||
value: 'unsafe-none',
|
||||
reportOnlyValue: 'unsafe-none',
|
||||
});
|
||||
settings.set(coep, {
|
||||
pipe: coep,
|
||||
value: 'require-corp',
|
||||
reportOnlyValue: 'unsafe-none',
|
||||
});
|
||||
settings.set(coepReportOnly, {
|
||||
pipe: coepReportOnly,
|
||||
value: 'unsafe-none',
|
||||
reportOnlyValue: 'require-corp',
|
||||
});
|
||||
|
||||
function genUrl(pipe) {
|
||||
return `${path}?${pipe}${suffix}`;
|
||||
}
|
||||
|
||||
for (const outer of settings.keys()) {
|
||||
for (const inner of settings.keys()) {
|
||||
const iframe = document.createElement('iframe');
|
||||
t.add_cleanup(() => iframe.remove());
|
||||
|
||||
iframe.src = genUrl(outer);
|
||||
iframe.addEventListener('load', () => {
|
||||
const w = iframe.contentWindow;
|
||||
const d = iframe.contentDocument;
|
||||
const nested = d.createElement('iframe');
|
||||
nested.src = genUrl(inner) + '-nested';
|
||||
d.body.appendChild(nested);
|
||||
}, {once: true});
|
||||
document.body.appendChild(iframe);
|
||||
}
|
||||
}
|
||||
|
||||
// Wait 3 seconds for reports to settle.
|
||||
await wait(3000);
|
||||
|
||||
function check(rs, inner, outer) {
|
||||
checkNavigationReportExistence(
|
||||
rs, genUrl(inner) + '-nested', genUrl(outer));
|
||||
}
|
||||
function checkNoReport(reports, inner, outer) {
|
||||
checkReportNonExistence(
|
||||
reports, genUrl(inner) + '-nested', genUrl(outer));
|
||||
}
|
||||
|
||||
// outer === noCoep
|
||||
checkNoReport(reports, noCoep, noCoep);
|
||||
checkNoReport(reports, coep, noCoep);
|
||||
checkNoReport(reports, coepReportOnly, noCoep);
|
||||
checkNoReport(reportsForReportOnly, noCoep, noCoep);
|
||||
checkNoReport(reportsForReportOnly, coep, noCoep);
|
||||
checkNoReport(reportsForReportOnly, coepReportOnly, noCoep);
|
||||
|
||||
// outer === coep
|
||||
check(reports, noCoep, coep);
|
||||
checkNoReport(reports, coep, coep);
|
||||
check(reports, coepReportOnly, coep);
|
||||
checkNoReport(reportsForReportOnly, noCoep, coep);
|
||||
checkNoReport(reportsForReportOnly, coep, coep);
|
||||
checkNoReport(reportsForReportOnly, coepReportOnly, coep);
|
||||
|
||||
// outer === coepReportOnly
|
||||
checkNoReport(reports, noCoep, coepReportOnly);
|
||||
checkNoReport(reports, coep, coepReportOnly);
|
||||
checkNoReport(reports, coepReportOnly, coepReportOnly);
|
||||
check(reportsForReportOnly, noCoep, coepReportOnly);
|
||||
checkNoReport(reportsForReportOnly, coep, coepReportOnly);
|
||||
check(reportsForReportOnly, coepReportOnly, coepReportOnly);
|
||||
|
||||
t.done();
|
||||
} catch (e) {
|
||||
t.step(() => { throw e });
|
||||
}
|
||||
}, 'COEP violation on nested frame navigation');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const iframe_src = `resources/reporting-empty-frame.html?passthrough`;
|
||||
// Register a service worker that controls an iframe.
|
||||
const registration = await service_worker_unregister_and_register(
|
||||
t, 'resources/sw.js', iframe_src);
|
||||
t.add_cleanup(() => registration.unregister());
|
||||
await wait_for_state(t, registration.installing, 'activated');
|
||||
|
||||
const iframe = document.createElement('iframe');
|
||||
t.add_cleanup(() => iframe.remove());
|
||||
|
||||
iframe.src = iframe_src;
|
||||
document.body.appendChild(iframe);
|
||||
await new Promise(resolve => {
|
||||
iframe.addEventListener('load', resolve, {once: true});
|
||||
});
|
||||
|
||||
async function fetchInIframe(url) {
|
||||
const init = { mode: 'no-cors', cache: 'no-store' };
|
||||
// Ignore errors.
|
||||
return iframe.contentWindow.fetch(url, init).catch(() => {});
|
||||
}
|
||||
|
||||
const suffix = 'subresource-corp-passthrough-sw';
|
||||
const sameOriginUrl = `/common/text-plain.txt?${suffix}`;
|
||||
const blockedByPureCorp = `${REMOTE_ORIGIN}${BASE}/nothing-same-origin-corp.txt?${suffix}`;
|
||||
const blockedDueToCoep = `${REMOTE_ORIGIN}/common/text-plain.txt?abc&${suffix}`;
|
||||
const dest = `${REMOTE_ORIGIN}/common/text-plain.txt?xyz&${suffix}`;
|
||||
const redirect = `/common/redirect.py?location=${encodeURIComponent(dest)}&${suffix}`;
|
||||
|
||||
fetchInIframe(sameOriginUrl);
|
||||
fetchInIframe(blockedByPureCorp);
|
||||
fetchInIframe(blockedDueToCoep);
|
||||
fetchInIframe(redirect);
|
||||
|
||||
// Wait until |reports| is ready.
|
||||
await wait(1000);
|
||||
|
||||
checkReportNonExistence(reports, sameOriginUrl, iframe.src);
|
||||
checkReportNonExistence(reports, blockedByPureCorp, iframe.src);
|
||||
checkCorpReportExistence(reports, blockedDueToCoep, iframe.src);
|
||||
checkCorpReportExistence(reports, redirect, iframe.src);
|
||||
checkReportNonExistence(reports, dest, iframe.src);
|
||||
}, 'subresource CORP in a passthrough iframe hosted by a service worker without COEP');
|
||||
|
||||
promise_test(async (t) => {
|
||||
const iframe_src = `resources/reporting-empty-frame.html`;
|
||||
// Register a service worker that controls an iframe.
|
||||
const registration = await service_worker_unregister_and_register(
|
||||
t, 'resources/sw.js', iframe_src);
|
||||
t.add_cleanup(() => registration.unregister());
|
||||
await wait_for_state(t, registration.installing, 'activated');
|
||||
|
||||
const iframe = document.createElement('iframe');
|
||||
t.add_cleanup(() => iframe.remove());
|
||||
|
||||
iframe.src = iframe_src;
|
||||
document.body.appendChild(iframe);
|
||||
await new Promise(resolve => {
|
||||
iframe.addEventListener('load', resolve, {once: true});
|
||||
});
|
||||
|
||||
async function fetchInIframe(url) {
|
||||
const init = { mode: 'no-cors', cache: 'no-store' };
|
||||
// Ignore errors.
|
||||
return iframe.contentWindow.fetch(url, init).catch(() => {});
|
||||
}
|
||||
|
||||
const suffix = 'subresource-corp-respondwith-fetch-sw';
|
||||
const sameOriginUrl = `/common/text-plain.txt?${suffix}`;
|
||||
const blockedByPureCorp = `${REMOTE_ORIGIN}${BASE}/nothing-same-origin-corp.txt?${suffix}`;
|
||||
const blockedDueToCoep = `${REMOTE_ORIGIN}/common/text-plain.txt?abc&${suffix}`;
|
||||
const dest = `${REMOTE_ORIGIN}/common/text-plain.txt?xyz&${suffix}`;
|
||||
const redirect = `/common/redirect.py?location=${encodeURIComponent(dest)}&${suffix}`;
|
||||
|
||||
fetchInIframe(sameOriginUrl);
|
||||
fetchInIframe(blockedByPureCorp);
|
||||
fetchInIframe(blockedDueToCoep)
|
||||
fetchInIframe(redirect);
|
||||
|
||||
// Wait until |reports| is ready.
|
||||
await wait(1000);
|
||||
|
||||
checkReportNonExistence(reports, sameOriginUrl, iframe.src);
|
||||
checkReportNonExistence(reports, blockedByPureCorp, iframe.src);
|
||||
checkCorpReportExistence(reports, blockedDueToCoep, iframe.src);
|
||||
checkCorpReportExistence(reports, redirect, iframe.src);
|
||||
checkReportNonExistence(reports, dest, iframe.src);
|
||||
}, 'subresource CORP in a respondWith(fetch) iframe hosted by a service worker without COEP');
|
||||
</script>$
|
||||
|
|
|
@ -8,21 +8,23 @@ def main(request, response):
|
|||
response.headers.set('Access-Control-Allow-Methods', 'POST')
|
||||
response.headers.set('Access-Control-Allow-Headers', 'content-type')
|
||||
return ''
|
||||
|
||||
response.headers.set('Access-Control-Allow-Origin', '*')
|
||||
uuidMap = {
|
||||
'endpoint': '01234567-0123-0123-0123-0123456789AB',
|
||||
'report-only-endpoint': '01234567-0123-0123-0123-0123456789CD'
|
||||
}
|
||||
key = 0;
|
||||
if 'endpoint' in request.GET:
|
||||
key = uuidMap[request.GET['endpoint']]
|
||||
|
||||
response.headers.set('Access-Control-Allow-Origin', '*')
|
||||
endpoint = request.GET.first('endpoint')
|
||||
if endpoint not in uuidMap:
|
||||
if 'key' in request.GET:
|
||||
key = request.GET['key']
|
||||
|
||||
if key == 0:
|
||||
response.status = 400
|
||||
return 'invalid endpoint'
|
||||
|
||||
path = '/'.join(request.url_parts.path.split('/')[:-1]) + '/'
|
||||
key = uuidMap[endpoint]
|
||||
|
||||
if request.method == 'POST':
|
||||
reports = request.server.stash.take(key, path) or []
|
||||
for report in json.loads(request.body):
|
||||
|
|
|
@ -8,18 +8,21 @@
|
|||
|
||||
<div id=log></div>
|
||||
<script>
|
||||
// This document has COOP "same-origin". The popup has COOP "same-origin". Therefore there should
|
||||
// only be an opener and name if the frameOrigin and popupOrigin are same-origin with this document.
|
||||
[
|
||||
[SAME_ORIGIN, SAME_ORIGIN, "same-origin", true, true],
|
||||
[SAME_SITE, SAME_ORIGIN, "same-origin", false, false],
|
||||
[CROSS_ORIGIN, SAME_ORIGIN, "same-origin", false, false],
|
||||
[SAME_ORIGIN, SAME_SITE, "same-origin", false, false],
|
||||
[SAME_SITE, SAME_SITE, "same-origin", false, false],
|
||||
[CROSS_ORIGIN, SAME_SITE, "same-origin", false, false],
|
||||
[SAME_ORIGIN, CROSS_ORIGIN, "same-origin", false, false],
|
||||
[SAME_SITE, CROSS_ORIGIN, "same-origin", false, false],
|
||||
[CROSS_ORIGIN, CROSS_ORIGIN, "same-origin", false, false],
|
||||
].forEach( value => {
|
||||
run_coop_test_iframe("same-origin", value[0], value[1], value[2], value[3], value[4]);
|
||||
[SAME_ORIGIN, SAME_ORIGIN, true],
|
||||
[SAME_SITE, SAME_ORIGIN, false],
|
||||
[CROSS_ORIGIN, SAME_ORIGIN, false],
|
||||
[SAME_ORIGIN, SAME_SITE, false],
|
||||
[SAME_SITE, SAME_SITE, false],
|
||||
[CROSS_ORIGIN, SAME_SITE, false],
|
||||
[SAME_ORIGIN, CROSS_ORIGIN, false],
|
||||
[SAME_SITE, CROSS_ORIGIN, false],
|
||||
[CROSS_ORIGIN, CROSS_ORIGIN, false],
|
||||
].forEach(([frameOrigin, popupOrigin, popupHasOpenerAndName]) => {
|
||||
const testTitleStart = "same-origin";
|
||||
const popupCOOP = "same-origin";
|
||||
run_coop_test_iframe(testTitleStart, frameOrigin, popupOrigin, popupCOOP, popupHasOpenerAndName, popupHasOpenerAndName);
|
||||
});
|
||||
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -8,18 +8,22 @@
|
|||
|
||||
<div id=log></div>
|
||||
<script>
|
||||
// This document has COOP "same-origin". The popup has no COOP. Therefore there should be no
|
||||
// opener or name.
|
||||
[
|
||||
[SAME_ORIGIN, SAME_ORIGIN, "", false, false],
|
||||
[SAME_SITE, SAME_ORIGIN, "", false, true],
|
||||
[CROSS_ORIGIN, SAME_ORIGIN, "", false, true],
|
||||
[SAME_ORIGIN, SAME_SITE, "", false, false],
|
||||
[SAME_SITE, SAME_SITE, "", false, true],
|
||||
[CROSS_ORIGIN, SAME_SITE, "", false, true],
|
||||
[SAME_ORIGIN, CROSS_ORIGIN, "", false, false],
|
||||
[SAME_SITE, CROSS_ORIGIN, "", false, true],
|
||||
[CROSS_ORIGIN, CROSS_ORIGIN, "", false, true],
|
||||
].forEach( value => {
|
||||
run_coop_test_iframe("same-origin", value[0], value[1], value[2], value[3], value[4]);
|
||||
[SAME_ORIGIN, SAME_ORIGIN],
|
||||
[SAME_SITE, SAME_ORIGIN],
|
||||
[CROSS_ORIGIN, SAME_ORIGIN],
|
||||
[SAME_ORIGIN, SAME_SITE],
|
||||
[SAME_SITE, SAME_SITE],
|
||||
[CROSS_ORIGIN, SAME_SITE],
|
||||
[SAME_ORIGIN, CROSS_ORIGIN],
|
||||
[SAME_SITE, CROSS_ORIGIN],
|
||||
[CROSS_ORIGIN, CROSS_ORIGIN],
|
||||
].forEach(([frameOrigin, popupOrigin]) => {
|
||||
const testTitleStart = "same-origin";
|
||||
const popupCOOP = "";
|
||||
const popupHasOpenerAndName = false;
|
||||
run_coop_test_iframe(testTitleStart, frameOrigin, popupOrigin, popupCOOP, popupHasOpenerAndName, popupHasOpenerAndName);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<!doctype html>
|
||||
<title>Image width and height attributes are used to infer aspect-ratio for lazy-loaded images</title>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style>
|
||||
img {
|
||||
width: 100%;
|
||||
max-width: 100px;
|
||||
height: auto;
|
||||
}
|
||||
</style>
|
||||
<div style="height: 600vh"></div>
|
||||
<img src="/images/green.png" loading="lazy" width=100 height=100>
|
||||
<script>
|
||||
let t = async_test("Image width and height attributes are used to infer aspect-ratio for lazy-loaded images");
|
||||
|
||||
function assert_ratio(img, expected) {
|
||||
let epsilon = 0.001;
|
||||
assert_approx_equals(parseFloat(getComputedStyle(img).width, 10) / parseFloat(getComputedStyle(img).height, 10), expected, epsilon);
|
||||
}
|
||||
|
||||
t.step(function() {
|
||||
let img = document.querySelector("img");
|
||||
assert_ratio(img, 1.0);
|
||||
img.addEventListener("load", t.step_func_done(function() {
|
||||
assert_ratio(img, 2.0); // 2.0 is the original aspect ratio of green.png
|
||||
}));
|
||||
window.scrollTo(0, img.getBoundingClientRect().top);
|
||||
});
|
||||
</script>
|
|
@ -1,8 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<!--
|
||||
Tentative due to:
|
||||
https://github.com/whatwg/html/issues/1903
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
|
@ -11,7 +7,8 @@
|
|||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Activation state is visible in parent and not in child</h1>
|
||||
<h1>User activation visibility across cross-origin frame boundary</h1>
|
||||
<h2>Confirms that the state is visible in parent and not in child</h2>
|
||||
<ol id="instructions">
|
||||
<li>Click anywhere on the green area (child frame).
|
||||
</ol>
|
||||
|
@ -31,7 +28,7 @@
|
|||
t.done();
|
||||
}
|
||||
}));
|
||||
child.src = "http://{{domains[www1]}}:{{ports[http][0]}}/html/user-activation/resources/activation-hierarchy-child.sub.html";
|
||||
child.src = "http://{{domains[www1]}}:{{ports[http][0]}}/html/user-activation/resources/activation-hierarchy-crossorigin-child.sub.html";
|
||||
}, "Parent test");
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,35 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>User activation visibility across same-origin frame boundary</h1>
|
||||
<h2>Confirms that the state is visible in both parent and child</h2>
|
||||
<ol id="instructions">
|
||||
<li>Click anywhere on the green area (child frame).
|
||||
</ol>
|
||||
<iframe id="child" width="400" height="400"></iframe>
|
||||
<script>
|
||||
async_test(function(t) {
|
||||
assert_false(navigator.userActivation.isActive);
|
||||
assert_false(navigator.userActivation.hasBeenActive);
|
||||
|
||||
let child = document.getElementById("child");
|
||||
|
||||
window.addEventListener("message", t.step_func(event => {
|
||||
if (event.source === frames[0].frames[0] && event.data === 'checked') {
|
||||
// Parent should be active after child is clicked.
|
||||
assert_true(navigator.userActivation.isActive);
|
||||
assert_true(navigator.userActivation.hasBeenActive);
|
||||
t.done();
|
||||
}
|
||||
}));
|
||||
child.src = "resources/activation-hierarchy-sameorigin-child.html";
|
||||
}, "Parent test");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -25,7 +25,7 @@
|
|||
t.done();
|
||||
}));
|
||||
|
||||
grandchild.src = "http://{{domains[www2]}}:{{ports[http][0]}}/html/user-activation/resources/activation-hierarchy-grandchild.html";
|
||||
grandchild.src = "http://{{domains[www2]}}:{{ports[http][0]}}/html/user-activation/resources/activation-hierarchy-crossorigin-grandchild.html";
|
||||
}, "Child test");
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body style="background: lightgreen;">
|
||||
<h1>Child frame</h1>
|
||||
<iframe id="grandchild" width="350" height="200"></iframe>
|
||||
<script>
|
||||
async_test(function(t) {
|
||||
assert_false(navigator.userActivation.isActive);
|
||||
assert_false(navigator.userActivation.hasBeenActive);
|
||||
|
||||
var grandchild = document.getElementById("grandchild");
|
||||
|
||||
window.addEventListener("click", t.step_func(event => {
|
||||
// Child should be active when clicked.
|
||||
assert_true(navigator.userActivation.isActive);
|
||||
assert_true(navigator.userActivation.hasBeenActive);
|
||||
|
||||
// Ask grandchild to check its state (and notify top frame).
|
||||
grandchild.contentWindow.postMessage('check-request', '*');
|
||||
|
||||
t.done();
|
||||
}));
|
||||
|
||||
grandchild.src = "activation-hierarchy-sameorigin-grandchild.html";
|
||||
}, "Child test");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<head>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body style="background: lightgrey;">
|
||||
<h1>Grandchild frame</h1>
|
||||
<script>
|
||||
async_test(function(t) {
|
||||
assert_false(navigator.userActivation.isActive);
|
||||
assert_false(navigator.userActivation.hasBeenActive);
|
||||
|
||||
window.addEventListener("message", event => {
|
||||
if (event.source === parent && event.data === 'check-request') {
|
||||
// Grandchild shouldn't be active after child is clicked.
|
||||
assert_true(navigator.userActivation.isActive);
|
||||
assert_true(navigator.userActivation.hasBeenActive);
|
||||
|
||||
// Notify top frame that checks are done.
|
||||
parent.parent.postMessage('checked', '*');
|
||||
|
||||
t.done();
|
||||
}
|
||||
});
|
||||
|
||||
}, "Grandchild test");
|
||||
</script>
|
||||
</body>
|
|
@ -5,7 +5,7 @@
|
|||
<script>
|
||||
test(t => {
|
||||
assert_true("userAgentData" in navigator);
|
||||
}, "navigator.getUserAgent() is exposed.");
|
||||
}, "navigator.userAgentData is exposed.");
|
||||
|
||||
promise_test(async t => {
|
||||
const uaData = navigator.userAgentData;
|
||||
|
@ -24,5 +24,5 @@
|
|||
assert_equals(highEntropyData2["platformVersion"], "", "Platform version should be an empty string");
|
||||
assert_equals(highEntropyData2["architecture"], "", "Architecture should be an empty string");
|
||||
assert_equals(highEntropyData2["model"], "", "Model should be an empty string");
|
||||
}, "navigator.getUserAgent() returns a UserAgentMetadata object.");
|
||||
}, "navigator.userAgentData returns a UserAgentMetadata object.");
|
||||
</script>
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Content-Type: text/javascript
|
|
@ -1 +0,0 @@
|
|||
log.push("relative:@std/blank");
|
|
@ -1 +0,0 @@
|
|||
log.push("relative:@std/none");
|
|
@ -1,51 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<meta name="timeout" content="long">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../resources/test-helper.js"></script>
|
||||
|
||||
<script>
|
||||
// "bare/..." (i.e. without leading "./") are bare specifiers
|
||||
// (not relative paths).
|
||||
//
|
||||
// Discussions about notations for builtin modules are ongoing, e.g.
|
||||
// https://github.com/tc39/proposal-javascript-standard-library/issues/12
|
||||
// Currently the tests expects two notations are accepted.
|
||||
// TODO: Once the discussions converge, update the tests.
|
||||
const importMap = `
|
||||
{
|
||||
"imports": {
|
||||
"bare/std-blank": "std:blank",
|
||||
"bare/blank": "@std/blank",
|
||||
"bare/std-none": "std:none",
|
||||
"bare/none": "@std/none"
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const tests = {
|
||||
// Arrays of expected results for:
|
||||
// - <script src type="module">,
|
||||
// - <script src> (classic script),
|
||||
// - static import, and
|
||||
// - dynamic import.
|
||||
|
||||
// Currently, Chromium's implementation resolves import maps as a part of
|
||||
// specifier resolution, and thus failure in import map resolution causes
|
||||
// a parse error, not fetch error. Therefore, we use Result.PARSE_ERROR
|
||||
// below. https://crbug.com/928435
|
||||
|
||||
// Bare to built-in.
|
||||
"bare/std-blank":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"bare/blank":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"bare/std-none":
|
||||
[Result.URL, Result.URL, Result.PARSE_ERROR, Result.PARSE_ERROR],
|
||||
"bare/none":
|
||||
[Result.URL, Result.URL, Result.PARSE_ERROR, Result.PARSE_ERROR],
|
||||
};
|
||||
|
||||
doTests(importMap, null, tests);
|
||||
</script>
|
||||
<body>
|
|
@ -1 +0,0 @@
|
|||
Content-Type: text/javascript
|
|
@ -1 +0,0 @@
|
|||
log.push("relative:bare/blank");
|
|
@ -1 +0,0 @@
|
|||
log.push("relative:bare/none");
|
|
@ -1 +0,0 @@
|
|||
log.push("relative:bare/std-blank");
|
|
@ -1 +0,0 @@
|
|||
log.push("relative:bare/std-none");
|
|
@ -1,43 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../resources/test-helper.js"></script>
|
||||
|
||||
<script>
|
||||
const importMap = `
|
||||
{
|
||||
"imports": {
|
||||
"../resources/log.js?pipe=sub&name=empty": [ "@std/" ],
|
||||
"../resources/log.js?pipe=sub&name=empty-fallback": [
|
||||
"@std/",
|
||||
"../resources/log.js?pipe=sub&name=empty-fallback"
|
||||
]
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const tests = {
|
||||
// Arrays of expected results for:
|
||||
// - <script src type="module">,
|
||||
// - <script src> (classic script),
|
||||
// - static import, and
|
||||
// - dynamic import.
|
||||
|
||||
// Discussions about notations are ongoing, e.g.
|
||||
// https://github.com/tc39/proposal-javascript-standard-library/issues/12
|
||||
// Currently the tests expects two notations are accepted.
|
||||
// TODO: Once the discussions converge, update this and related tests.
|
||||
"std:":
|
||||
[Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR],
|
||||
"@std/":
|
||||
[Result.FETCH_ERROR, Result.PARSE_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR],
|
||||
|
||||
"../resources/log.js?pipe=sub&name=empty":
|
||||
[Result.URL, Result.URL, Result.PARSE_ERROR, Result.PARSE_ERROR],
|
||||
"../resources/log.js?pipe=sub&name=empty-fallback":
|
||||
[Result.URL, Result.URL, Result.URL, Result.URL],
|
||||
};
|
||||
|
||||
doTests(importMap, null, tests);
|
||||
</script>
|
||||
<body>
|
|
@ -1,27 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../resources/test-helper.js"></script>
|
||||
|
||||
<script>
|
||||
const tests = {
|
||||
// Arrays of expected results for:
|
||||
// - <script src type="module">,
|
||||
// - <script src> (classic script),
|
||||
// - static import, and
|
||||
// - dynamic import.
|
||||
|
||||
// Currently direct use of import: URLs are disabled.
|
||||
"import:std:blank":
|
||||
[Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR],
|
||||
"import:@std/blank":
|
||||
[Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR],
|
||||
"import:std:none":
|
||||
[Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR],
|
||||
"import:@std/none":
|
||||
[Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR],
|
||||
};
|
||||
|
||||
doTests(null, null, tests);
|
||||
</script>
|
||||
<body>
|
|
@ -1,30 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../resources/test-helper.js"></script>
|
||||
|
||||
<script>
|
||||
const tests = {
|
||||
// Arrays of expected results for:
|
||||
// - <script src type="module">,
|
||||
// - <script src> (classic script),
|
||||
// - static import, and
|
||||
// - dynamic import.
|
||||
|
||||
// Discussions about notations are ongoing, e.g.
|
||||
// https://github.com/tc39/proposal-javascript-standard-library/issues/12
|
||||
// Currently the tests expects two notations are accepted.
|
||||
// TODO: Once the discussions converge, update this and related tests.
|
||||
"std:blank":
|
||||
[Result.BUILTIN, Result.FETCH_ERROR, Result.BUILTIN, Result.BUILTIN],
|
||||
"@std/blank":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"std:none":
|
||||
[Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR, Result.FETCH_ERROR],
|
||||
"@std/none":
|
||||
[Result.URL, Result.URL, Result.FETCH_ERROR, Result.FETCH_ERROR],
|
||||
};
|
||||
|
||||
doTests(null, null, tests);
|
||||
</script>
|
||||
<body>
|
|
@ -1,51 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<meta name="timeout" content="long">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../resources/test-helper.js"></script>
|
||||
|
||||
<script>
|
||||
// "bare/..." (i.e. without leading "./") are bare specifiers
|
||||
// (not relative paths).
|
||||
//
|
||||
// Discussions about notations for builtin modules are ongoing, e.g.
|
||||
// https://github.com/tc39/proposal-javascript-standard-library/issues/12
|
||||
// Currently the tests expects two notations are accepted.
|
||||
// TODO: Once the discussions converge, update the tests.
|
||||
const importMap = `
|
||||
{
|
||||
"imports": {
|
||||
"data:text/javascript,log.push('data:std-blank')": "std:blank",
|
||||
"data:text/javascript,log.push('data:blank')": "@std/blank",
|
||||
"data:text/javascript,log.push('data:std-none')": "std:none",
|
||||
"data:text/javascript,log.push('data:none')": "@std/none"
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const tests = {
|
||||
// Arrays of expected results for:
|
||||
// - <script src type="module">,
|
||||
// - <script src> (classic script),
|
||||
// - static import, and
|
||||
// - dynamic import.
|
||||
|
||||
// Currently, Chromium's implementation resolves import maps as a part of
|
||||
// specifier resolution, and thus failure in import map resolution causes
|
||||
// a parse error, not fetch error. Therefore, we use Result.PARSE_ERROR
|
||||
// below. https://crbug.com/928435
|
||||
|
||||
// data: to built-in.
|
||||
"data:text/javascript,log.push('data:std-blank')":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"data:text/javascript,log.push('data:blank')":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"data:text/javascript,log.push('data:std-none')":
|
||||
[Result.URL, Result.URL, Result.PARSE_ERROR, Result.PARSE_ERROR],
|
||||
"data:text/javascript,log.push('data:none')":
|
||||
[Result.URL, Result.URL, Result.PARSE_ERROR, Result.PARSE_ERROR],
|
||||
};
|
||||
|
||||
doTests(importMap, null, tests);
|
||||
</script>
|
||||
<body>
|
|
@ -1,80 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<meta name="timeout" content="long">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../resources/test-helper.js"></script>
|
||||
|
||||
<script>
|
||||
// Fallbacks from external URLs (such as HTTPS URLs) are
|
||||
// blocked by ongoing spec discussions, for example
|
||||
// https://github.com/WICG/import-maps/issues/76.
|
||||
// https://crbug.com/928435
|
||||
//
|
||||
// This test, as well as Chromium's implementation, rejects broader range of
|
||||
// fallbacks (not only those from HTTPS), to avoid potential spec and
|
||||
// interoperability issues.
|
||||
// The only allowed fallback pattern is fallbacks from bare specifiers with
|
||||
// two elements, which are listed in fallback.sub.tentative.html.
|
||||
const importMap = `
|
||||
{
|
||||
"imports": {
|
||||
"bare": "../resources/log.js?pipe=sub&name=bare",
|
||||
|
||||
"../resources/log.js?pipe=sub&name=http-to-builtin": [
|
||||
"../resources/log.js?pipe=sub&name=http-to-builtin",
|
||||
"@std/blank"
|
||||
],
|
||||
|
||||
"../resources/log.js?pipe=sub&name=fallback-to-different-url-1": [
|
||||
"@std/blank",
|
||||
"../resources/log.js?pipe=sub&name=something-different"
|
||||
],
|
||||
"../resources/log.js?pipe=sub&name=fallback-to-different-url-2": [
|
||||
"@std/none",
|
||||
"../resources/log.js?pipe=sub&name=something-different2"
|
||||
],
|
||||
"../resources/log.js?pipe=sub&name=fallback-to-different-origin-1": [
|
||||
"@std/blank",
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=fallback-to-different-origin-1"
|
||||
],
|
||||
"../resources/log.js?pipe=sub&name=fallback-to-different-origin-2": [
|
||||
"@std/none",
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=fallback-to-different-origin-2"
|
||||
],
|
||||
|
||||
"../resources/log.js?pipe=sub&name=more-than-two-values-1": [
|
||||
"@std/none",
|
||||
"@std/blank",
|
||||
"../resources/log.js?pipe=sub&name=more-than-two-values-1"
|
||||
],
|
||||
"../resources/log.js?pipe=sub&name=more-than-two-values-2": [
|
||||
"@std/none",
|
||||
"../resources/log.js?pipe=sub&name=more-than-two-values-2",
|
||||
"@std/blank"
|
||||
],
|
||||
"../resources/log.js?pipe=sub&name=fallback-from-http": [
|
||||
"../resources/log.js?pipe=sub&name=non-built-in",
|
||||
"../resources/log.js?pipe=sub&name=fallback-from-http"
|
||||
],
|
||||
"../resources/log.js?pipe=sub&name=fallback-from-data-1": [
|
||||
"data:text/plain,",
|
||||
"../resources/log.js?pipe=sub&name=fallback-from-http"
|
||||
],
|
||||
"../resources/log.js?pipe=sub&name=fallback-from-data-2": [
|
||||
"data:text/javascript,log.push('dataURL')",
|
||||
"../resources/log.js?pipe=sub&name=fallback-from-http"
|
||||
]
|
||||
}
|
||||
}
|
||||
`;
|
||||
const tests = {};
|
||||
for (const key in JSON.parse(importMap).imports) {
|
||||
if (key === "bare") {
|
||||
continue;
|
||||
}
|
||||
tests[key] =
|
||||
[Result.URL, Result.URL, Result.PARSE_ERROR, Result.PARSE_ERROR];
|
||||
}
|
||||
doTests(importMap, null, tests);
|
||||
</script>
|
||||
<body>
|
|
@ -1,85 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<meta name="timeout" content="long">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../resources/test-helper.js"></script>
|
||||
|
||||
<script>
|
||||
// This tests is for fallbacks with the pattern of
|
||||
// `"https://some.external/url": ["@std/x", "https://some.external/url"]`
|
||||
// which maps "https://some.external/url" to "@std/x" if "@std/x" is
|
||||
// implemented, or leaves it unmodified otherwise.
|
||||
//
|
||||
// This is the primary use case where fallback should work.
|
||||
// Some other patterns of fallbacks are intentionally blocked due to ongoing
|
||||
// spec issues. See fallback-disallowed.sub.tentative.html.
|
||||
const importMap = `
|
||||
{
|
||||
"imports": {
|
||||
"../resources/log.js?pipe=sub&name=blank": [
|
||||
"@std/blank",
|
||||
"../resources/log.js?pipe=sub&name=blank"
|
||||
],
|
||||
"../resources/log.js?pipe=sub&name=none": [
|
||||
"@std/none",
|
||||
"../resources/log.js?pipe=sub&name=none"
|
||||
],
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=cross-origin-blank": [
|
||||
"@std/blank",
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=cross-origin-blank"
|
||||
],
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=cross-origin-none": [
|
||||
"@std/none",
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=cross-origin-none"
|
||||
],
|
||||
|
||||
"../resources/log.js?pipe=sub&name=std-blank": [
|
||||
"std:blank",
|
||||
"../resources/log.js?pipe=sub&name=std-blank"
|
||||
],
|
||||
"../resources/log.js?pipe=sub&name=std-none": [
|
||||
"std:none",
|
||||
"../resources/log.js?pipe=sub&name=std-none"
|
||||
],
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=std-cross-origin-blank": [
|
||||
"std:blank",
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=std-cross-origin-blank"
|
||||
],
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=std-cross-origin-none": [
|
||||
"std:none",
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=std-cross-origin-none"
|
||||
]
|
||||
|
||||
}
|
||||
}
|
||||
`;
|
||||
const tests = {
|
||||
// Arrays of expected results for:
|
||||
// - <script src type="module">,
|
||||
// - <script src> (classic script),
|
||||
// - static import, and
|
||||
// - dynamic import.
|
||||
// Result.URL indicates that the specifier was not re-mapped by import maps,
|
||||
// i.e. either considered as a relative path, or fallback occured.
|
||||
"../resources/log.js?pipe=sub&name=blank":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"../resources/log.js?pipe=sub&name=none":
|
||||
[Result.URL, Result.URL, Result.URL, Result.URL],
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=cross-origin-blank":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=cross-origin-none":
|
||||
[Result.URL, Result.URL, Result.URL, Result.URL],
|
||||
|
||||
"../resources/log.js?pipe=sub&name=std-blank":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"../resources/log.js?pipe=sub&name=std-none":
|
||||
[Result.URL, Result.URL, Result.URL, Result.URL],
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=std-cross-origin-blank":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=std-cross-origin-none":
|
||||
[Result.URL, Result.URL, Result.URL, Result.URL],
|
||||
};
|
||||
|
||||
doTests(importMap, null, tests);
|
||||
</script>
|
||||
<body>
|
|
@ -1,50 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../resources/test-helper.js"></script>
|
||||
|
||||
<script>
|
||||
// "bare/..." (i.e. without leading "./") are bare specifiers
|
||||
// (not relative paths).
|
||||
//
|
||||
// Discussions about notations for builtin modules are ongoing, e.g.
|
||||
// https://github.com/tc39/proposal-javascript-standard-library/issues/12
|
||||
// Currently the tests expects two notations are accepted.
|
||||
// TODO: Once the discussions converge, update the tests.
|
||||
const importMap = `
|
||||
{
|
||||
"imports": {
|
||||
"../resources/log.js?pipe=sub&name=std-blank": "std:blank",
|
||||
"../resources/log.js?pipe=sub&name=blank": "@std/blank",
|
||||
"../resources/log.js?pipe=sub&name=std-none": "std:none",
|
||||
"../resources/log.js?pipe=sub&name=none": "@std/none"
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const tests = {
|
||||
// Arrays of expected results for:
|
||||
// - <script src type="module">,
|
||||
// - <script src> (classic script),
|
||||
// - static import, and
|
||||
// - dynamic import.
|
||||
|
||||
// Currently, Chromium's implementation resolves import maps as a part of
|
||||
// specifier resolution, and thus failure in import map resolution causes
|
||||
// a parse error, not fetch error. Therefore, we use Result.PARSE_ERROR
|
||||
// below. https://crbug.com/928435
|
||||
|
||||
// HTTP(S) to built-in.
|
||||
"{{location[server]}}/import-maps/resources/log.js?pipe=sub&name=std-blank":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"{{location[server]}}/import-maps/resources/log.js?pipe=sub&name=blank":
|
||||
[Result.URL, Result.URL, Result.BUILTIN, Result.BUILTIN],
|
||||
"{{location[server]}}/import-maps/resources/log.js?pipe=sub&name=std-none":
|
||||
[Result.URL, Result.URL, Result.PARSE_ERROR, Result.PARSE_ERROR],
|
||||
"{{location[server]}}/import-maps/resources/log.js?pipe=sub&name=none":
|
||||
[Result.URL, Result.URL, Result.PARSE_ERROR, Result.PARSE_ERROR],
|
||||
};
|
||||
|
||||
doTests(importMap, null, tests);
|
||||
</script>
|
||||
<body>
|
|
@ -1,11 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../resources/jest-test-helper.js"></script>
|
||||
<script type="module" src="resources/helpers/parsing.js"></script>
|
||||
|
||||
<!--
|
||||
Imported from https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/parsing-addresses.js
|
||||
-->
|
||||
<script type="module" src="resources/parsing-addresses.js"></script>
|
|
@ -1,11 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../resources/jest-test-helper.js"></script>
|
||||
<script type="module" src="resources/helpers/parsing.js"></script>
|
||||
|
||||
<!--
|
||||
Imported from https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/parsing-schema.js
|
||||
-->
|
||||
<script type="module" src="resources/parsing-schema.js"></script>
|
|
@ -1,11 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../resources/jest-test-helper.js"></script>
|
||||
<script type="module" src="resources/helpers/parsing.js"></script>
|
||||
|
||||
<!--
|
||||
Imported from https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/parsing-scope-keys.js
|
||||
-->
|
||||
<script type="module" src="resources/parsing-scope-keys.js"></script>
|
|
@ -1,11 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../resources/jest-test-helper.js"></script>
|
||||
<script type="module" src="resources/helpers/parsing.js"></script>
|
||||
|
||||
<!--
|
||||
Imported from https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/parsing-specifier-keys.js
|
||||
-->
|
||||
<script type="module" src="resources/parsing-specifier-keys.js"></script>
|
|
@ -1,11 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../resources/jest-test-helper.js"></script>
|
||||
<script type="module" src="resources/helpers/parsing.js"></script>
|
||||
|
||||
<!--
|
||||
Imported from https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/resolving-builtins.js
|
||||
-->
|
||||
<script type="module" src="resources/resolving-builtins.js"></script>
|
|
@ -1,11 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../resources/jest-test-helper.js"></script>
|
||||
<script type="module" src="resources/helpers/parsing.js"></script>
|
||||
|
||||
<!--
|
||||
Imported from https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/resolving-not-yet-implemented.js
|
||||
-->
|
||||
<script type="module" src="resources/resolving-not-yet-implemented.js"></script>
|
|
@ -1,11 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../resources/jest-test-helper.js"></script>
|
||||
<script type="module" src="resources/helpers/parsing.js"></script>
|
||||
|
||||
<!--
|
||||
Imported from https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/resolving-scopes.js
|
||||
-->
|
||||
<script type="module" src="resources/resolving-scopes.js"></script>
|
|
@ -1,11 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../resources/jest-test-helper.js"></script>
|
||||
<script type="module" src="resources/helpers/parsing.js"></script>
|
||||
|
||||
<!--
|
||||
Imported from https://github.com/WICG/import-maps/blob/master/reference-implementation/__tests__/resolving.js
|
||||
-->
|
||||
<script type="module" src="resources/resolving.js"></script>
|
|
@ -1,44 +0,0 @@
|
|||
'use strict';
|
||||
const { parseFromString } = require('../../lib/parser.js');
|
||||
|
||||
// Local modifications from upstream:
|
||||
// Currently warnings and scopes are not checked in expectSpecifierMap().
|
||||
exports.expectSpecifierMap = (input, baseURL, output, warnings = []) => {
|
||||
expect(parseFromString(`{ "imports": ${input} }`, baseURL))
|
||||
.toEqual({ imports: output, scopes: {} });
|
||||
};
|
||||
|
||||
exports.expectScopes = (inputArray, baseURL, outputArray, warnings = []) => {
|
||||
const checkWarnings = testWarningHandler(warnings);
|
||||
|
||||
const inputScopesAsStrings = inputArray.map(scopePrefix => `${JSON.stringify(scopePrefix)}: {}`);
|
||||
const inputString = `{ "scopes": { ${inputScopesAsStrings.join(', ')} } }`;
|
||||
|
||||
const outputScopesObject = {};
|
||||
for (const outputScopePrefix of outputArray) {
|
||||
outputScopesObject[outputScopePrefix] = {};
|
||||
}
|
||||
|
||||
expect(parseFromString(inputString, baseURL)).toEqual({ imports: {}, scopes: outputScopesObject });
|
||||
|
||||
checkWarnings();
|
||||
};
|
||||
|
||||
exports.expectBad = (input, baseURL, warnings = []) => {
|
||||
const checkWarnings = testWarningHandler(warnings);
|
||||
expect(parseFromString(input, baseURL)).toThrow('TypeError');
|
||||
checkWarnings();
|
||||
};
|
||||
|
||||
exports.expectWarnings = (input, baseURL, output, warnings = []) => {
|
||||
const checkWarnings = testWarningHandler(warnings);
|
||||
expect(parseFromString(input, baseURL)).toEqual(output);
|
||||
|
||||
checkWarnings();
|
||||
};
|
||||
|
||||
function testWarningHandler(expectedWarnings) {
|
||||
// We don't check warnings on WPT tests, because there are no
|
||||
// ways to catch console warnings from JavaScript.
|
||||
return () => {};
|
||||
}
|
|
@ -1,351 +0,0 @@
|
|||
'use strict';
|
||||
const { expectSpecifierMap } = require('./helpers/parsing.js');
|
||||
const { BUILT_IN_MODULE_SCHEME } = require('../lib/utils.js');
|
||||
|
||||
describe('Relative URL-like addresses', () => {
|
||||
it('should accept strings prefixed with ./, ../, or /', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"dotSlash": "./foo",
|
||||
"dotDotSlash": "../foo",
|
||||
"slash": "/foo"
|
||||
}`,
|
||||
'https://base.example/path1/path2/path3',
|
||||
{
|
||||
dotSlash: [expect.toMatchURL('https://base.example/path1/path2/foo')],
|
||||
dotDotSlash: [expect.toMatchURL('https://base.example/path1/foo')],
|
||||
slash: [expect.toMatchURL('https://base.example/foo')]
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should not accept strings prefixed with ./, ../, or / for data: base URLs', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"dotSlash": "./foo",
|
||||
"dotDotSlash": "../foo",
|
||||
"slash": "/foo"
|
||||
}`,
|
||||
'data:text/html,test',
|
||||
{
|
||||
dotSlash: [],
|
||||
dotDotSlash: [],
|
||||
slash: []
|
||||
},
|
||||
[
|
||||
`Invalid address "./foo" for the specifier key "dotSlash".`,
|
||||
`Invalid address "../foo" for the specifier key "dotDotSlash".`,
|
||||
`Invalid address "/foo" for the specifier key "slash".`
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
it('should accept the literal strings ./, ../, or / with no suffix', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"dotSlash": "./",
|
||||
"dotDotSlash": "../",
|
||||
"slash": "/"
|
||||
}`,
|
||||
'https://base.example/path1/path2/path3',
|
||||
{
|
||||
dotSlash: [expect.toMatchURL('https://base.example/path1/path2/')],
|
||||
dotDotSlash: [expect.toMatchURL('https://base.example/path1/')],
|
||||
slash: [expect.toMatchURL('https://base.example/')]
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should ignore percent-encoded variants of ./, ../, or /', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"dotSlash1": "%2E/",
|
||||
"dotDotSlash1": "%2E%2E/",
|
||||
"dotSlash2": ".%2F",
|
||||
"dotDotSlash2": "..%2F",
|
||||
"slash2": "%2F",
|
||||
"dotSlash3": "%2E%2F",
|
||||
"dotDotSlash3": "%2E%2E%2F"
|
||||
}`,
|
||||
'https://base.example/path1/path2/path3',
|
||||
{
|
||||
dotSlash1: [],
|
||||
dotDotSlash1: [],
|
||||
dotSlash2: [],
|
||||
dotDotSlash2: [],
|
||||
slash2: [],
|
||||
dotSlash3: [],
|
||||
dotDotSlash3: []
|
||||
},
|
||||
[
|
||||
`Invalid address "%2E/" for the specifier key "dotSlash1".`,
|
||||
`Invalid address "%2E%2E/" for the specifier key "dotDotSlash1".`,
|
||||
`Invalid address ".%2F" for the specifier key "dotSlash2".`,
|
||||
`Invalid address "..%2F" for the specifier key "dotDotSlash2".`,
|
||||
`Invalid address "%2F" for the specifier key "slash2".`,
|
||||
`Invalid address "%2E%2F" for the specifier key "dotSlash3".`,
|
||||
`Invalid address "%2E%2E%2F" for the specifier key "dotDotSlash3".`
|
||||
]
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Built-in module addresses', () => {
|
||||
it('should accept URLs using the built-in module scheme', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"foo": "${BUILT_IN_MODULE_SCHEME}:foo"
|
||||
}`,
|
||||
'https://base.example/path1/path2/path3',
|
||||
{
|
||||
foo: [expect.toMatchURL(`${BUILT_IN_MODULE_SCHEME}:foo`)]
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should ignore percent-encoded variants of the built-in module scheme', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"foo": "${encodeURIComponent(BUILT_IN_MODULE_SCHEME + ':')}foo"
|
||||
}`,
|
||||
'https://base.example/path1/path2/path3',
|
||||
{
|
||||
foo: []
|
||||
},
|
||||
[`Invalid address "${encodeURIComponent(BUILT_IN_MODULE_SCHEME + ':')}foo" for the specifier key "foo".`]
|
||||
);
|
||||
});
|
||||
|
||||
it('should allow built-in module URLs that contain "/" or "\\"', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"slashEnd": "${BUILT_IN_MODULE_SCHEME}:foo/",
|
||||
"slashMiddle": "${BUILT_IN_MODULE_SCHEME}:foo/bar",
|
||||
"backslash": "${BUILT_IN_MODULE_SCHEME}:foo\\\\baz"
|
||||
}`,
|
||||
'https://base.example/path1/path2/path3',
|
||||
{
|
||||
slashEnd: [expect.toMatchURL(`${BUILT_IN_MODULE_SCHEME}:foo/`)],
|
||||
slashMiddle: [expect.toMatchURL(`${BUILT_IN_MODULE_SCHEME}:foo/bar`)],
|
||||
backslash: [expect.toMatchURL(`${BUILT_IN_MODULE_SCHEME}:foo\\baz`)]
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Absolute URL addresses', () => {
|
||||
it('should only accept absolute URL addresses with fetch schemes', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"about": "about:good",
|
||||
"blob": "blob:good",
|
||||
"data": "data:good",
|
||||
"file": "file:///good",
|
||||
"filesystem": "filesystem:good",
|
||||
"http": "http://good/",
|
||||
"https": "https://good/",
|
||||
"ftp": "ftp://good/",
|
||||
"import": "import:bad",
|
||||
"mailto": "mailto:bad",
|
||||
"javascript": "javascript:bad",
|
||||
"wss": "wss:bad"
|
||||
}`,
|
||||
'https://base.example/path1/path2/path3',
|
||||
{
|
||||
about: [expect.toMatchURL('about:good')],
|
||||
blob: [expect.toMatchURL('blob:good')],
|
||||
data: [expect.toMatchURL('data:good')],
|
||||
file: [expect.toMatchURL('file:///good')],
|
||||
filesystem: [expect.toMatchURL('filesystem:good')],
|
||||
http: [expect.toMatchURL('http://good/')],
|
||||
https: [expect.toMatchURL('https://good/')],
|
||||
ftp: [expect.toMatchURL('ftp://good/')],
|
||||
import: [],
|
||||
mailto: [],
|
||||
javascript: [],
|
||||
wss: []
|
||||
},
|
||||
[
|
||||
`Invalid address "import:bad" for the specifier key "import".`,
|
||||
`Invalid address "mailto:bad" for the specifier key "mailto".`,
|
||||
`Invalid address "javascript:bad" for the specifier key "javascript".`,
|
||||
`Invalid address "wss:bad" for the specifier key "wss".`
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
it('should only accept absolute URL addresses with fetch schemes inside arrays', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"about": ["about:good"],
|
||||
"blob": ["blob:good"],
|
||||
"data": ["data:good"],
|
||||
"file": ["file:///good"],
|
||||
"filesystem": ["filesystem:good"],
|
||||
"http": ["http://good/"],
|
||||
"https": ["https://good/"],
|
||||
"ftp": ["ftp://good/"],
|
||||
"import": ["import:bad"],
|
||||
"mailto": ["mailto:bad"],
|
||||
"javascript": ["javascript:bad"],
|
||||
"wss": ["wss:bad"]
|
||||
}`,
|
||||
'https://base.example/path1/path2/path3',
|
||||
{
|
||||
about: [expect.toMatchURL('about:good')],
|
||||
blob: [expect.toMatchURL('blob:good')],
|
||||
data: [expect.toMatchURL('data:good')],
|
||||
file: [expect.toMatchURL('file:///good')],
|
||||
filesystem: [expect.toMatchURL('filesystem:good')],
|
||||
http: [expect.toMatchURL('http://good/')],
|
||||
https: [expect.toMatchURL('https://good/')],
|
||||
ftp: [expect.toMatchURL('ftp://good/')],
|
||||
import: [],
|
||||
mailto: [],
|
||||
javascript: [],
|
||||
wss: []
|
||||
},
|
||||
[
|
||||
`Invalid address "import:bad" for the specifier key "import".`,
|
||||
`Invalid address "mailto:bad" for the specifier key "mailto".`,
|
||||
`Invalid address "javascript:bad" for the specifier key "javascript".`,
|
||||
`Invalid address "wss:bad" for the specifier key "wss".`
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
it('should parse absolute URLs, ignoring unparseable ones', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"unparseable1": "https://ex ample.org/",
|
||||
"unparseable2": "https://example.com:demo",
|
||||
"unparseable3": "http://[www.example.com]/",
|
||||
"invalidButParseable1": "https:example.org",
|
||||
"invalidButParseable2": "https://///example.com///",
|
||||
"prettyNormal": "https://example.net",
|
||||
"percentDecoding": "https://ex%41mple.com/",
|
||||
"noPercentDecoding": "https://example.com/%41"
|
||||
}`,
|
||||
'https://base.example/path1/path2/path3',
|
||||
{
|
||||
unparseable1: [],
|
||||
unparseable2: [],
|
||||
unparseable3: [],
|
||||
invalidButParseable1: [expect.toMatchURL('https://example.org/')],
|
||||
invalidButParseable2: [expect.toMatchURL('https://example.com///')],
|
||||
prettyNormal: [expect.toMatchURL('https://example.net/')],
|
||||
percentDecoding: [expect.toMatchURL('https://example.com/')],
|
||||
noPercentDecoding: [expect.toMatchURL('https://example.com/%41')]
|
||||
},
|
||||
[
|
||||
`Invalid address "https://ex ample.org/" for the specifier key "unparseable1".`,
|
||||
`Invalid address "https://example.com:demo" for the specifier key "unparseable2".`,
|
||||
`Invalid address "http://[www.example.com]/" for the specifier key "unparseable3".`
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
it('should parse absolute URLs, ignoring unparseable ones inside arrays', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"unparseable1": ["https://ex ample.org/"],
|
||||
"unparseable2": ["https://example.com:demo"],
|
||||
"unparseable3": ["http://[www.example.com]/"],
|
||||
"invalidButParseable1": ["https:example.org"],
|
||||
"invalidButParseable2": ["https://///example.com///"],
|
||||
"prettyNormal": ["https://example.net"],
|
||||
"percentDecoding": ["https://ex%41mple.com/"],
|
||||
"noPercentDecoding": ["https://example.com/%41"]
|
||||
}`,
|
||||
'https://base.example/path1/path2/path3',
|
||||
{
|
||||
unparseable1: [],
|
||||
unparseable2: [],
|
||||
unparseable3: [],
|
||||
invalidButParseable1: [expect.toMatchURL('https://example.org/')],
|
||||
invalidButParseable2: [expect.toMatchURL('https://example.com///')],
|
||||
prettyNormal: [expect.toMatchURL('https://example.net/')],
|
||||
percentDecoding: [expect.toMatchURL('https://example.com/')],
|
||||
noPercentDecoding: [expect.toMatchURL('https://example.com/%41')]
|
||||
},
|
||||
[
|
||||
`Invalid address "https://ex ample.org/" for the specifier key "unparseable1".`,
|
||||
`Invalid address "https://example.com:demo" for the specifier key "unparseable2".`,
|
||||
`Invalid address "http://[www.example.com]/" for the specifier key "unparseable3".`
|
||||
]
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Failing addresses: mismatched trailing slashes', () => {
|
||||
it('should warn for the simple case', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"trailer/": "/notrailer",
|
||||
"${BUILT_IN_MODULE_SCHEME}:trailer/": "/bim-notrailer"
|
||||
}`,
|
||||
'https://base.example/path1/path2/path3',
|
||||
{
|
||||
'trailer/': [],
|
||||
[`${BUILT_IN_MODULE_SCHEME}:trailer/`]: []
|
||||
},
|
||||
[
|
||||
`Invalid address "https://base.example/notrailer" for package specifier key "trailer/". Package addresses must end with "/".`,
|
||||
`Invalid address "https://base.example/bim-notrailer" for package specifier key "${BUILT_IN_MODULE_SCHEME}:trailer/". Package addresses must end with "/".`
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
it('should warn for a mismatch alone in an array', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"trailer/": ["/notrailer"],
|
||||
"${BUILT_IN_MODULE_SCHEME}:trailer/": ["/bim-notrailer"]
|
||||
}`,
|
||||
'https://base.example/path1/path2/path3',
|
||||
{
|
||||
'trailer/': [],
|
||||
[`${BUILT_IN_MODULE_SCHEME}:trailer/`]: []
|
||||
},
|
||||
[
|
||||
`Invalid address "https://base.example/notrailer" for package specifier key "trailer/". Package addresses must end with "/".`,
|
||||
`Invalid address "https://base.example/bim-notrailer" for package specifier key "${BUILT_IN_MODULE_SCHEME}:trailer/". Package addresses must end with "/".`
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
it('should warn for a mismatch alongside non-mismatches in an array', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"trailer/": ["/atrailer/", "/notrailer"],
|
||||
"${BUILT_IN_MODULE_SCHEME}:trailer/": ["/bim-atrailer/", "/bim-notrailer"]
|
||||
}`,
|
||||
'https://base.example/path1/path2/path3',
|
||||
{
|
||||
'trailer/': [expect.toMatchURL('https://base.example/atrailer/')],
|
||||
[`${BUILT_IN_MODULE_SCHEME}:trailer/`]: [expect.toMatchURL('https://base.example/bim-atrailer/')]
|
||||
},
|
||||
[
|
||||
`Invalid address "https://base.example/notrailer" for package specifier key "trailer/". Package addresses must end with "/".`,
|
||||
`Invalid address "https://base.example/bim-notrailer" for package specifier key "${BUILT_IN_MODULE_SCHEME}:trailer/". Package addresses must end with "/".`
|
||||
]
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Other invalid addresses', () => {
|
||||
it('should ignore unprefixed strings that are not absolute URLs', () => {
|
||||
for (const bad of ['bar', '\\bar', '~bar', '#bar', '?bar']) {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"foo": ${JSON.stringify(bad)}
|
||||
}`,
|
||||
'https://base.example/path1/path2/path3',
|
||||
{
|
||||
foo: []
|
||||
},
|
||||
[`Invalid address "${bad}" for the specifier key "foo".`]
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -1,139 +0,0 @@
|
|||
'use strict';
|
||||
const { parseFromString } = require('../lib/parser.js');
|
||||
const { expectBad, expectWarnings, expectSpecifierMap } = require('./helpers/parsing.js');
|
||||
|
||||
const nonObjectStrings = ['null', 'true', '1', '"foo"', '[]'];
|
||||
|
||||
test('Invalid JSON', () => {
|
||||
expect(parseFromString('{ imports: {} }', 'https://base.example/')).toThrow('SyntaxError');
|
||||
});
|
||||
|
||||
describe('Mismatching the top-level schema', () => {
|
||||
it('should throw for top-level non-objects', () => {
|
||||
for (const nonObject of nonObjectStrings) {
|
||||
expectBad(nonObject, 'https://base.example/');
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw if imports is a non-object', () => {
|
||||
for (const nonObject of nonObjectStrings) {
|
||||
expectBad(`{ "imports": ${nonObject} }`, 'https://base.example/');
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw if scopes is a non-object', () => {
|
||||
for (const nonObject of nonObjectStrings) {
|
||||
expectBad(`{ "scopes": ${nonObject} }`, 'https://base.example/');
|
||||
}
|
||||
});
|
||||
|
||||
it('should ignore unspecified top-level entries', () => {
|
||||
expectWarnings(
|
||||
`{
|
||||
"imports": {},
|
||||
"new-feature": {},
|
||||
"scops": {}
|
||||
}`,
|
||||
'https://base.example/',
|
||||
{ imports: {}, scopes: {} },
|
||||
[
|
||||
`Invalid top-level key "new-feature". Only "imports" and "scopes" can be present.`,
|
||||
`Invalid top-level key "scops". Only "imports" and "scopes" can be present.`
|
||||
]
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Mismatching the specifier map schema', () => {
|
||||
const invalidAddressStrings = ['true', '1', '{}'];
|
||||
const invalidInsideArrayStrings = ['null', 'true', '1', '{}', '[]'];
|
||||
|
||||
it('should ignore entries where the address is not a string, array, or null', () => {
|
||||
for (const invalid of invalidAddressStrings) {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"foo": ${invalid},
|
||||
"bar": ["https://example.com/"]
|
||||
}`,
|
||||
'https://base.example/',
|
||||
{
|
||||
bar: [expect.toMatchURL('https://example.com/')]
|
||||
},
|
||||
[
|
||||
`Invalid address ${invalid} for the specifier key "foo". ` +
|
||||
`Addresses must be strings, arrays, or null.`
|
||||
]
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should ignore entries where the specifier key is an empty string', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"": ["https://example.com/"]
|
||||
}`,
|
||||
'https://base.example/',
|
||||
{},
|
||||
[`Invalid empty string specifier key.`]
|
||||
);
|
||||
});
|
||||
|
||||
it('should ignore members of an address array that are not strings', () => {
|
||||
for (const invalid of invalidInsideArrayStrings) {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"foo": ["https://example.com/", ${invalid}],
|
||||
"bar": ["https://example.com/"]
|
||||
}`,
|
||||
'https://base.example/',
|
||||
{
|
||||
foo: [expect.toMatchURL('https://example.com/')],
|
||||
bar: [expect.toMatchURL('https://example.com/')]
|
||||
},
|
||||
[
|
||||
`Invalid address ${invalid} inside the address array for the specifier key "foo". ` +
|
||||
`Address arrays must only contain strings.`
|
||||
]
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw if a scope\'s value is not an object', () => {
|
||||
for (const invalid of nonObjectStrings) {
|
||||
expectBad(`{ "scopes": { "https://scope.example/": ${invalid} } }`, 'https://base.example/');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('Normalization', () => {
|
||||
it('should normalize empty import maps to have imports and scopes keys', () => {
|
||||
expect(parseFromString(`{}`, 'https://base.example/'))
|
||||
.toEqual({ imports: {}, scopes: {} });
|
||||
});
|
||||
|
||||
it('should normalize an import map without imports to have imports', () => {
|
||||
expect(parseFromString(`{ "scopes": {} }`, 'https://base.example/'))
|
||||
.toEqual({ imports: {}, scopes: {} });
|
||||
});
|
||||
|
||||
it('should normalize an import map without scopes to have scopes', () => {
|
||||
expect(parseFromString(`{ "imports": {} }`, 'https://base.example/'))
|
||||
.toEqual({ imports: {}, scopes: {} });
|
||||
});
|
||||
|
||||
it('should normalize addresses to arrays', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"foo": "https://example.com/1",
|
||||
"bar": ["https://example.com/2"],
|
||||
"baz": null
|
||||
}`,
|
||||
'https://base.example/',
|
||||
{
|
||||
foo: [expect.toMatchURL('https://example.com/1')],
|
||||
bar: [expect.toMatchURL('https://example.com/2')],
|
||||
baz: []
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,144 +0,0 @@
|
|||
'use strict';
|
||||
const { expectScopes } = require('./helpers/parsing.js');
|
||||
|
||||
describe('Relative URL scope keys', () => {
|
||||
it('should work with no prefix', () => {
|
||||
expectScopes(
|
||||
['foo'],
|
||||
'https://base.example/path1/path2/path3',
|
||||
['https://base.example/path1/path2/foo']
|
||||
);
|
||||
});
|
||||
|
||||
it('should work with ./, ../, and / prefixes', () => {
|
||||
expectScopes(
|
||||
['./foo', '../foo', '/foo'],
|
||||
'https://base.example/path1/path2/path3',
|
||||
[
|
||||
'https://base.example/path1/path2/foo',
|
||||
'https://base.example/path1/foo',
|
||||
'https://base.example/foo'
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
it('should work with /s, ?s, and #s', () => {
|
||||
expectScopes(
|
||||
['foo/bar?baz#qux'],
|
||||
'https://base.example/path1/path2/path3',
|
||||
['https://base.example/path1/path2/foo/bar?baz#qux']
|
||||
);
|
||||
});
|
||||
|
||||
it('should work with an empty string scope key', () => {
|
||||
expectScopes(
|
||||
[''],
|
||||
'https://base.example/path1/path2/path3',
|
||||
['https://base.example/path1/path2/path3']
|
||||
);
|
||||
});
|
||||
|
||||
it('should work with / suffixes', () => {
|
||||
expectScopes(
|
||||
['foo/', './foo/', '../foo/', '/foo/', '/foo//'],
|
||||
'https://base.example/path1/path2/path3',
|
||||
[
|
||||
'https://base.example/path1/path2/foo/',
|
||||
'https://base.example/path1/path2/foo/',
|
||||
'https://base.example/path1/foo/',
|
||||
'https://base.example/foo/',
|
||||
'https://base.example/foo//'
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
it('should deduplicate based on URL parsing rules', () => {
|
||||
expectScopes(
|
||||
['foo/\\', 'foo//', 'foo\\\\'],
|
||||
'https://base.example/path1/path2/path3',
|
||||
['https://base.example/path1/path2/foo//']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Absolute URL scope keys', () => {
|
||||
it('should accept all absolute URL scope keys, with or without fetch schemes', () => {
|
||||
expectScopes(
|
||||
[
|
||||
'about:good',
|
||||
'blob:good',
|
||||
'data:good',
|
||||
'file:///good',
|
||||
'filesystem:http://example.com/good/',
|
||||
'http://good/',
|
||||
'https://good/',
|
||||
'ftp://good/',
|
||||
'import:bad',
|
||||
'mailto:bad',
|
||||
'javascript:bad',
|
||||
'wss:ba'
|
||||
],
|
||||
'https://base.example/path1/path2/path3',
|
||||
[
|
||||
'about:good',
|
||||
'blob:good',
|
||||
'data:good',
|
||||
'file:///good',
|
||||
'filesystem:http://example.com/good/',
|
||||
'http://good/',
|
||||
'https://good/',
|
||||
'ftp://good/',
|
||||
'import:bad',
|
||||
'mailto:bad',
|
||||
'javascript:bad',
|
||||
'wss://ba/'
|
||||
],
|
||||
[]
|
||||
);
|
||||
});
|
||||
|
||||
it('should parse absolute URL scope keys, ignoring unparseable ones', () => {
|
||||
expectScopes(
|
||||
[
|
||||
'https://ex ample.org/',
|
||||
'https://example.com:demo',
|
||||
'http://[www.example.com]/',
|
||||
'https:example.org',
|
||||
'https://///example.com///',
|
||||
'https://example.net',
|
||||
'https://ex%41mple.com/foo/',
|
||||
'https://example.com/%41'
|
||||
],
|
||||
'https://base.example/path1/path2/path3',
|
||||
[
|
||||
'https://base.example/path1/path2/example.org', // tricky case! remember we have a base URL
|
||||
'https://example.com///',
|
||||
'https://example.net/',
|
||||
'https://example.com/foo/',
|
||||
'https://example.com/%41'
|
||||
],
|
||||
[
|
||||
'Invalid scope "https://ex ample.org/" (parsed against base URL "https://base.example/path1/path2/path3").',
|
||||
'Invalid scope "https://example.com:demo" (parsed against base URL "https://base.example/path1/path2/path3").',
|
||||
'Invalid scope "http://[www.example.com]/" (parsed against base URL "https://base.example/path1/path2/path3").'
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
it('should ignore relative URL scope keys when the base URL is a data: URL', () => {
|
||||
expectScopes(
|
||||
[
|
||||
'./foo',
|
||||
'../foo',
|
||||
'/foo'
|
||||
],
|
||||
'data:text/html,test',
|
||||
[],
|
||||
[
|
||||
'Invalid scope "./foo" (parsed against base URL "data:text/html,test").',
|
||||
'Invalid scope "../foo" (parsed against base URL "data:text/html,test").',
|
||||
'Invalid scope "/foo" (parsed against base URL "data:text/html,test").'
|
||||
]
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,159 +0,0 @@
|
|||
'use strict';
|
||||
const { expectSpecifierMap } = require('./helpers/parsing.js');
|
||||
const { BUILT_IN_MODULE_SCHEME } = require('../lib/utils.js');
|
||||
|
||||
const BLANK = `${BUILT_IN_MODULE_SCHEME}:blank`;
|
||||
|
||||
describe('Relative URL-like specifier keys', () => {
|
||||
it('should absolutize strings prefixed with ./, ../, or / into the corresponding URLs', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"./foo": "/dotslash",
|
||||
"../foo": "/dotdotslash",
|
||||
"/foo": "/slash"
|
||||
}`,
|
||||
'https://base.example/path1/path2/path3',
|
||||
{
|
||||
'https://base.example/path1/path2/foo': [expect.toMatchURL('https://base.example/dotslash')],
|
||||
'https://base.example/path1/foo': [expect.toMatchURL('https://base.example/dotdotslash')],
|
||||
'https://base.example/foo': [expect.toMatchURL('https://base.example/slash')]
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should not absolutize strings prefixed with ./, ../, or / with a data: URL base', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"./foo": "https://example.com/dotslash",
|
||||
"../foo": "https://example.com/dotdotslash",
|
||||
"/foo": "https://example.com/slash"
|
||||
}`,
|
||||
'data:text/html,test',
|
||||
{
|
||||
'./foo': [expect.toMatchURL('https://example.com/dotslash')],
|
||||
'../foo': [expect.toMatchURL('https://example.com/dotdotslash')],
|
||||
'/foo': [expect.toMatchURL('https://example.com/slash')]
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should absolutize the literal strings ./, ../, or / with no suffix', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"./": "/dotslash/",
|
||||
"../": "/dotdotslash/",
|
||||
"/": "/slash/"
|
||||
}`,
|
||||
'https://base.example/path1/path2/path3',
|
||||
{
|
||||
'https://base.example/path1/path2/': [expect.toMatchURL('https://base.example/dotslash/')],
|
||||
'https://base.example/path1/': [expect.toMatchURL('https://base.example/dotdotslash/')],
|
||||
'https://base.example/': [expect.toMatchURL('https://base.example/slash/')]
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should treat percent-encoded variants of ./, ../, or / as bare specifiers', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"%2E/": "/dotSlash1/",
|
||||
"%2E%2E/": "/dotDotSlash1/",
|
||||
".%2F": "/dotSlash2",
|
||||
"..%2F": "/dotDotSlash2",
|
||||
"%2F": "/slash2",
|
||||
"%2E%2F": "/dotSlash3",
|
||||
"%2E%2E%2F": "/dotDotSlash3"
|
||||
}`,
|
||||
'https://base.example/path1/path2/path3',
|
||||
{
|
||||
'%2E/': [expect.toMatchURL('https://base.example/dotSlash1/')],
|
||||
'%2E%2E/': [expect.toMatchURL('https://base.example/dotDotSlash1/')],
|
||||
'.%2F': [expect.toMatchURL('https://base.example/dotSlash2')],
|
||||
'..%2F': [expect.toMatchURL('https://base.example/dotDotSlash2')],
|
||||
'%2F': [expect.toMatchURL('https://base.example/slash2')],
|
||||
'%2E%2F': [expect.toMatchURL('https://base.example/dotSlash3')],
|
||||
'%2E%2E%2F': [expect.toMatchURL('https://base.example/dotDotSlash3')]
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Absolute URL specifier keys', () => {
|
||||
it('should only accept absolute URL specifier keys with fetch schemes, treating others as bare specifiers', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"about:good": "/about",
|
||||
"blob:good": "/blob",
|
||||
"data:good": "/data",
|
||||
"file:///good": "/file",
|
||||
"filesystem:good": "/filesystem",
|
||||
"http://good/": "/http/",
|
||||
"https://good/": "/https/",
|
||||
"ftp://good/": "/ftp/",
|
||||
"import:bad": "/import",
|
||||
"mailto:bad": "/mailto",
|
||||
"javascript:bad": "/javascript",
|
||||
"wss:bad": "/wss"
|
||||
}`,
|
||||
'https://base.example/path1/path2/path3',
|
||||
{
|
||||
'about:good': [expect.toMatchURL('https://base.example/about')],
|
||||
'blob:good': [expect.toMatchURL('https://base.example/blob')],
|
||||
'data:good': [expect.toMatchURL('https://base.example/data')],
|
||||
'file:///good': [expect.toMatchURL('https://base.example/file')],
|
||||
'filesystem:good': [expect.toMatchURL('https://base.example/filesystem')],
|
||||
'http://good/': [expect.toMatchURL('https://base.example/http/')],
|
||||
'https://good/': [expect.toMatchURL('https://base.example/https/')],
|
||||
'ftp://good/': [expect.toMatchURL('https://base.example/ftp/')],
|
||||
'import:bad': [expect.toMatchURL('https://base.example/import')],
|
||||
'mailto:bad': [expect.toMatchURL('https://base.example/mailto')],
|
||||
'javascript:bad': [expect.toMatchURL('https://base.example/javascript')],
|
||||
'wss:bad': [expect.toMatchURL('https://base.example/wss')]
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should parse absolute URLs, treating unparseable ones as bare specifiers', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"https://ex ample.org/": "/unparseable1/",
|
||||
"https://example.com:demo": "/unparseable2",
|
||||
"http://[www.example.com]/": "/unparseable3/",
|
||||
"https:example.org": "/invalidButParseable1/",
|
||||
"https://///example.com///": "/invalidButParseable2/",
|
||||
"https://example.net": "/prettyNormal/",
|
||||
"https://ex%41mple.com/": "/percentDecoding/",
|
||||
"https://example.com/%41": "/noPercentDecoding"
|
||||
}`,
|
||||
'https://base.example/path1/path2/path3',
|
||||
{
|
||||
'https://ex ample.org/': [expect.toMatchURL('https://base.example/unparseable1/')],
|
||||
'https://example.com:demo': [expect.toMatchURL('https://base.example/unparseable2')],
|
||||
'http://[www.example.com]/': [expect.toMatchURL('https://base.example/unparseable3/')],
|
||||
'https://example.org/': [expect.toMatchURL('https://base.example/invalidButParseable1/')],
|
||||
'https://example.com///': [expect.toMatchURL('https://base.example/invalidButParseable2/')],
|
||||
'https://example.net/': [expect.toMatchURL('https://base.example/prettyNormal/')],
|
||||
'https://example.com/': [expect.toMatchURL('https://base.example/percentDecoding/')],
|
||||
'https://example.com/%41': [expect.toMatchURL('https://base.example/noPercentDecoding')]
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should parse built-in module specifier keys, including with a "/"', () => {
|
||||
expectSpecifierMap(
|
||||
`{
|
||||
"${BLANK}": "/blank",
|
||||
"${BLANK}/": "/blank/",
|
||||
"${BLANK}/foo": "/blank/foo",
|
||||
"${BLANK}\\\\foo": "/blank/backslashfoo"
|
||||
}`,
|
||||
'https://base.example/path1/path2/path3',
|
||||
{
|
||||
[BLANK]: [expect.toMatchURL('https://base.example/blank')],
|
||||
[`${BLANK}/`]: [expect.toMatchURL('https://base.example/blank/')],
|
||||
[`${BLANK}/foo`]: [expect.toMatchURL('https://base.example/blank/foo')],
|
||||
[`${BLANK}\\foo`]: [expect.toMatchURL('https://base.example/blank/backslashfoo')]
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,158 +0,0 @@
|
|||
'use strict';
|
||||
const { URL } = require('url');
|
||||
const { parseFromString } = require('../lib/parser.js');
|
||||
const { resolve } = require('../lib/resolver.js');
|
||||
const { BUILT_IN_MODULE_SCHEME } = require('../lib/utils.js');
|
||||
|
||||
const mapBaseURL = new URL('https://example.com/app/index.html');
|
||||
const scriptURL = new URL('https://example.com/js/app.mjs');
|
||||
|
||||
const BLANK = `${BUILT_IN_MODULE_SCHEME}:blank`;
|
||||
const NONE = `${BUILT_IN_MODULE_SCHEME}:none`;
|
||||
|
||||
function makeResolveUnderTest(mapString) {
|
||||
const map = parseFromString(mapString, mapBaseURL);
|
||||
return specifier => resolve(specifier, map, scriptURL);
|
||||
}
|
||||
|
||||
describe('Unmapped built-in module specifiers', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{}`);
|
||||
|
||||
it(`should resolve "${BLANK}" to "${BLANK}"`, () => {
|
||||
expect(resolveUnderTest(BLANK)).toMatchURL(BLANK);
|
||||
});
|
||||
|
||||
it(`should error resolving "${NONE}"`, () => {
|
||||
expect(() => resolveUnderTest(NONE)).toThrow(TypeError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Remapping built-in module specifiers', () => {
|
||||
it('should remap built-in modules', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"${BLANK}": "./blank.mjs",
|
||||
"${NONE}": "./none.mjs"
|
||||
}
|
||||
}`);
|
||||
|
||||
expect(resolveUnderTest(BLANK)).toMatchURL('https://example.com/app/blank.mjs');
|
||||
expect(resolveUnderTest(NONE)).toMatchURL('https://example.com/app/none.mjs');
|
||||
});
|
||||
|
||||
it('should remap built-in modules with slashes', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"${BLANK}/": "./blank-slash/",
|
||||
"${BLANK}/foo": "./blank-foo.mjs",
|
||||
"${NONE}/": "./none-slash/",
|
||||
"${NONE}/foo": "./none-foo.mjs"
|
||||
}
|
||||
}`);
|
||||
|
||||
expect(resolveUnderTest(`${BLANK}/`)).toMatchURL('https://example.com/app/blank-slash/');
|
||||
expect(resolveUnderTest(`${BLANK}/foo`)).toMatchURL('https://example.com/app/blank-foo.mjs');
|
||||
expect(resolveUnderTest(`${BLANK}/bar`)).toMatchURL('https://example.com/app/blank-slash/bar');
|
||||
expect(resolveUnderTest(`${NONE}/`)).toMatchURL('https://example.com/app/none-slash/');
|
||||
expect(resolveUnderTest(`${NONE}/foo`)).toMatchURL('https://example.com/app/none-foo.mjs');
|
||||
expect(resolveUnderTest(`${NONE}/bar`)).toMatchURL('https://example.com/app/none-slash/bar');
|
||||
});
|
||||
|
||||
it('should remap built-in modules with fallbacks', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"${BLANK}": ["${BLANK}", "./blank.mjs"],
|
||||
"${NONE}": ["${NONE}", "./none.mjs"]
|
||||
}
|
||||
}`);
|
||||
|
||||
expect(resolveUnderTest(BLANK)).toMatchURL(BLANK);
|
||||
expect(resolveUnderTest(NONE)).toMatchURL('https://example.com/app/none.mjs');
|
||||
});
|
||||
|
||||
it('should remap built-in modules with slashes and fallbacks', () => {
|
||||
// NOTE: `${BLANK}/for-testing` is not per spec, just for these tests.
|
||||
// See resolver.js.
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"${BLANK}/": ["${BLANK}/", "./blank/"],
|
||||
"${BLANK}/for-testing": ["${BLANK}/for-testing", "./blank-for-testing-special"],
|
||||
"${NONE}/": ["${NONE}/", "./none/"],
|
||||
"${NONE}/foo": ["${NONE}/foo", "./none-foo-special"]
|
||||
}
|
||||
}`);
|
||||
|
||||
// Built-in modules only resolve for exact matches, so this will trigger the fallback.
|
||||
expect(resolveUnderTest(`${BLANK}/`)).toMatchURL('https://example.com/app/blank/');
|
||||
expect(resolveUnderTest(`${BLANK}/foo`)).toMatchURL('https://example.com/app/blank/foo');
|
||||
|
||||
// This would fall back in a real implementation; it's only because we've gone against
|
||||
// spec in the reference implementation (to make this testable) that this maps.
|
||||
expect(resolveUnderTest(`${BLANK}/for-testing`)).toMatchURL(`${BLANK}/for-testing`);
|
||||
|
||||
expect(resolveUnderTest(`${NONE}/`)).toMatchURL('https://example.com/app/none/');
|
||||
expect(resolveUnderTest(`${NONE}/bar`)).toMatchURL('https://example.com/app/none/bar');
|
||||
expect(resolveUnderTest(`${NONE}/foo`)).toMatchURL('https://example.com/app/none-foo-special');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Remapping to built-in modules', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"blank": "${BLANK}",
|
||||
"/blank": "${BLANK}",
|
||||
"/blank/": "${BLANK}/",
|
||||
"/blank-for-testing": "${BLANK}/for-testing",
|
||||
"none": "${NONE}",
|
||||
"/none": "${NONE}"
|
||||
}
|
||||
}`);
|
||||
|
||||
it(`should remap to "${BLANK}"`, () => {
|
||||
expect(resolveUnderTest('blank')).toMatchURL(BLANK);
|
||||
expect(resolveUnderTest('/blank')).toMatchURL(BLANK);
|
||||
});
|
||||
|
||||
it(`should fail when remapping to "${BLANK}/"`, () => {
|
||||
expect(() => resolveUnderTest('/blank/')).toThrow(TypeError);
|
||||
});
|
||||
|
||||
it(`should remap to "${BLANK}/for-testing"`, () => {
|
||||
expect(resolveUnderTest('/blank/for-testing')).toMatchURL(`${BLANK}/for-testing`);
|
||||
expect(resolveUnderTest('/blank-for-testing')).toMatchURL(`${BLANK}/for-testing`);
|
||||
});
|
||||
|
||||
it(`should remap to "${BLANK}" for URL-like specifiers`, () => {
|
||||
expect(resolveUnderTest('/blank')).toMatchURL(BLANK);
|
||||
expect(resolveUnderTest('https://example.com/blank')).toMatchURL(BLANK);
|
||||
expect(resolveUnderTest('https://///example.com/blank')).toMatchURL(BLANK);
|
||||
});
|
||||
|
||||
it(`should fail when remapping to "${NONE}"`, () => {
|
||||
expect(() => resolveUnderTest('none')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('/none')).toThrow(TypeError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Fallbacks with built-in module addresses', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"blank": [
|
||||
"${BLANK}",
|
||||
"./blank-fallback.mjs"
|
||||
],
|
||||
"none": [
|
||||
"${NONE}",
|
||||
"./none-fallback.mjs"
|
||||
]
|
||||
}
|
||||
}`);
|
||||
|
||||
it(`should resolve to "${BLANK}"`, () => {
|
||||
expect(resolveUnderTest('blank')).toMatchURL(BLANK);
|
||||
});
|
||||
|
||||
it(`should fall back past "${NONE}"`, () => {
|
||||
expect(resolveUnderTest('none')).toMatchURL('https://example.com/app/none-fallback.mjs');
|
||||
});
|
||||
});
|
|
@ -1,47 +0,0 @@
|
|||
'use strict';
|
||||
const { URL } = require('url');
|
||||
const { parseFromString } = require('../lib/parser.js');
|
||||
const { resolve } = require('../lib/resolver.js');
|
||||
const { BUILT_IN_MODULE_SCHEME } = require('../lib/utils.js');
|
||||
|
||||
const mapBaseURL = new URL('https://example.com/app/index.html');
|
||||
const scriptURL = new URL('https://example.com/js/app.mjs');
|
||||
|
||||
const BLANK = `${BUILT_IN_MODULE_SCHEME}:blank`;
|
||||
|
||||
function makeResolveUnderTest(mapString) {
|
||||
const map = parseFromString(mapString, mapBaseURL);
|
||||
return specifier => resolve(specifier, map, scriptURL);
|
||||
}
|
||||
|
||||
describe('Fallbacks that are not [built-in, fetch scheme]', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"bad1": [
|
||||
"${BLANK}",
|
||||
"${BLANK}"
|
||||
],
|
||||
"bad2": [
|
||||
"${BLANK}",
|
||||
"/bad2-1.mjs",
|
||||
"/bad2-2.mjs"
|
||||
],
|
||||
"bad3": [
|
||||
"/bad3-1.mjs",
|
||||
"/bad3-2.mjs"
|
||||
]
|
||||
}
|
||||
}`);
|
||||
|
||||
it('should fail for [built-in, built-in]', () => {
|
||||
expect(() => resolveUnderTest('bad1')).toThrow(/not yet implemented/);
|
||||
});
|
||||
|
||||
it('should fail for [built-in, fetch scheme, fetch scheme]', () => {
|
||||
expect(() => resolveUnderTest('bad2')).toThrow(/not yet implemented/);
|
||||
});
|
||||
|
||||
it('should fail for [fetch scheme, fetch scheme]', () => {
|
||||
expect(() => resolveUnderTest('bad3')).toThrow(/not yet implemented/);
|
||||
});
|
||||
});
|
|
@ -1,230 +0,0 @@
|
|||
'use strict';
|
||||
const { URL } = require('url');
|
||||
const { parseFromString } = require('../lib/parser.js');
|
||||
const { resolve } = require('../lib/resolver.js');
|
||||
|
||||
const mapBaseURL = new URL('https://example.com/app/index.html');
|
||||
|
||||
function makeResolveUnderTest(mapString) {
|
||||
const map = parseFromString(mapString, mapBaseURL);
|
||||
return (specifier, baseURL) => resolve(specifier, map, baseURL);
|
||||
}
|
||||
|
||||
describe('Mapped using scope instead of "imports"', () => {
|
||||
const jsNonDirURL = new URL('https://example.com/js');
|
||||
const jsPrefixedURL = new URL('https://example.com/jsiscool');
|
||||
const inJSDirURL = new URL('https://example.com/js/app.mjs');
|
||||
const topLevelURL = new URL('https://example.com/app.mjs');
|
||||
|
||||
it('should fail when the mapping is to an empty array', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"scopes": {
|
||||
"/js/": {
|
||||
"moment": null,
|
||||
"lodash": []
|
||||
}
|
||||
}
|
||||
}`);
|
||||
|
||||
expect(() => resolveUnderTest('moment', inJSDirURL)).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('lodash', inJSDirURL)).toThrow(TypeError);
|
||||
});
|
||||
|
||||
describe('Exact vs. prefix based matching', () => {
|
||||
it('should match correctly when both are in the map', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"scopes": {
|
||||
"/js": {
|
||||
"moment": "/only-triggered-by-exact/moment",
|
||||
"moment/": "/only-triggered-by-exact/moment/"
|
||||
},
|
||||
"/js/": {
|
||||
"moment": "/triggered-by-any-subpath/moment",
|
||||
"moment/": "/triggered-by-any-subpath/moment/"
|
||||
}
|
||||
}
|
||||
}`);
|
||||
|
||||
expect(resolveUnderTest('moment', jsNonDirURL)).toMatchURL('https://example.com/only-triggered-by-exact/moment');
|
||||
expect(resolveUnderTest('moment/foo', jsNonDirURL)).toMatchURL('https://example.com/only-triggered-by-exact/moment/foo');
|
||||
|
||||
expect(resolveUnderTest('moment', inJSDirURL)).toMatchURL('https://example.com/triggered-by-any-subpath/moment');
|
||||
expect(resolveUnderTest('moment/foo', inJSDirURL)).toMatchURL('https://example.com/triggered-by-any-subpath/moment/foo');
|
||||
|
||||
expect(() => resolveUnderTest('moment', jsPrefixedURL)).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('moment/foo', jsPrefixedURL)).toThrow(TypeError);
|
||||
});
|
||||
|
||||
it('should match correctly when only an exact match is in the map', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"scopes": {
|
||||
"/js": {
|
||||
"moment": "/only-triggered-by-exact/moment",
|
||||
"moment/": "/only-triggered-by-exact/moment/"
|
||||
}
|
||||
}
|
||||
}`);
|
||||
|
||||
expect(resolveUnderTest('moment', jsNonDirURL)).toMatchURL('https://example.com/only-triggered-by-exact/moment');
|
||||
expect(resolveUnderTest('moment/foo', jsNonDirURL)).toMatchURL('https://example.com/only-triggered-by-exact/moment/foo');
|
||||
|
||||
expect(() => resolveUnderTest('moment', inJSDirURL)).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('moment/foo', inJSDirURL)).toThrow(TypeError);
|
||||
|
||||
expect(() => resolveUnderTest('moment', jsPrefixedURL)).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('moment/foo', jsPrefixedURL)).toThrow(TypeError);
|
||||
});
|
||||
|
||||
it('should match correctly when only a prefix match is in the map', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"scopes": {
|
||||
"/js/": {
|
||||
"moment": "/triggered-by-any-subpath/moment",
|
||||
"moment/": "/triggered-by-any-subpath/moment/"
|
||||
}
|
||||
}
|
||||
}`);
|
||||
|
||||
expect(() => resolveUnderTest('moment', jsNonDirURL)).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('moment/foo', jsNonDirURL)).toThrow(TypeError);
|
||||
|
||||
expect(resolveUnderTest('moment', inJSDirURL)).toMatchURL('https://example.com/triggered-by-any-subpath/moment');
|
||||
expect(resolveUnderTest('moment/foo', inJSDirURL)).toMatchURL('https://example.com/triggered-by-any-subpath/moment/foo');
|
||||
|
||||
expect(() => resolveUnderTest('moment', jsPrefixedURL)).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('moment/foo', jsPrefixedURL)).toThrow(TypeError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Package-like scenarios', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"moment": "/node_modules/moment/src/moment.js",
|
||||
"moment/": "/node_modules/moment/src/",
|
||||
"lodash-dot": "./node_modules/lodash-es/lodash.js",
|
||||
"lodash-dot/": "./node_modules/lodash-es/",
|
||||
"lodash-dotdot": "../node_modules/lodash-es/lodash.js",
|
||||
"lodash-dotdot/": "../node_modules/lodash-es/"
|
||||
},
|
||||
"scopes": {
|
||||
"/": {
|
||||
"moment": "/node_modules_3/moment/src/moment.js",
|
||||
"vue": "/node_modules_3/vue/dist/vue.runtime.esm.js"
|
||||
},
|
||||
"/js/": {
|
||||
"lodash-dot": "./node_modules_2/lodash-es/lodash.js",
|
||||
"lodash-dot/": "./node_modules_2/lodash-es/",
|
||||
"lodash-dotdot": "../node_modules_2/lodash-es/lodash.js",
|
||||
"lodash-dotdot/": "../node_modules_2/lodash-es/"
|
||||
}
|
||||
}
|
||||
}`);
|
||||
|
||||
it('should resolve scoped', () => {
|
||||
expect(resolveUnderTest('lodash-dot', inJSDirURL)).toMatchURL('https://example.com/app/node_modules_2/lodash-es/lodash.js');
|
||||
expect(resolveUnderTest('lodash-dotdot', inJSDirURL)).toMatchURL('https://example.com/node_modules_2/lodash-es/lodash.js');
|
||||
expect(resolveUnderTest('lodash-dot/foo', inJSDirURL)).toMatchURL('https://example.com/app/node_modules_2/lodash-es/foo');
|
||||
expect(resolveUnderTest('lodash-dotdot/foo', inJSDirURL)).toMatchURL('https://example.com/node_modules_2/lodash-es/foo');
|
||||
});
|
||||
|
||||
it('should apply best scope match', () => {
|
||||
expect(resolveUnderTest('moment', topLevelURL)).toMatchURL('https://example.com/node_modules_3/moment/src/moment.js');
|
||||
expect(resolveUnderTest('moment', inJSDirURL)).toMatchURL('https://example.com/node_modules_3/moment/src/moment.js');
|
||||
expect(resolveUnderTest('vue', inJSDirURL)).toMatchURL('https://example.com/node_modules_3/vue/dist/vue.runtime.esm.js');
|
||||
});
|
||||
|
||||
it('should fallback to "imports"', () => {
|
||||
expect(resolveUnderTest('moment/foo', topLevelURL)).toMatchURL('https://example.com/node_modules/moment/src/foo');
|
||||
expect(resolveUnderTest('moment/foo', inJSDirURL)).toMatchURL('https://example.com/node_modules/moment/src/foo');
|
||||
expect(resolveUnderTest('lodash-dot', topLevelURL)).toMatchURL('https://example.com/app/node_modules/lodash-es/lodash.js');
|
||||
expect(resolveUnderTest('lodash-dotdot', topLevelURL)).toMatchURL('https://example.com/node_modules/lodash-es/lodash.js');
|
||||
expect(resolveUnderTest('lodash-dot/foo', topLevelURL)).toMatchURL('https://example.com/app/node_modules/lodash-es/foo');
|
||||
expect(resolveUnderTest('lodash-dotdot/foo', topLevelURL)).toMatchURL('https://example.com/node_modules/lodash-es/foo');
|
||||
});
|
||||
|
||||
it('should still fail for package-like specifiers that are not declared', () => {
|
||||
expect(() => resolveUnderTest('underscore/', inJSDirURL)).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('underscore/foo', inJSDirURL)).toThrow(TypeError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('The scope inheritance example from the README', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"a": "/a-1.mjs",
|
||||
"b": "/b-1.mjs",
|
||||
"c": "/c-1.mjs"
|
||||
},
|
||||
"scopes": {
|
||||
"/scope2/": {
|
||||
"a": "/a-2.mjs"
|
||||
},
|
||||
"/scope2/scope3/": {
|
||||
"b": "/b-3.mjs"
|
||||
}
|
||||
}
|
||||
}`);
|
||||
|
||||
const scope1URL = new URL('https://example.com/scope1/foo.mjs');
|
||||
const scope2URL = new URL('https://example.com/scope2/foo.mjs');
|
||||
const scope3URL = new URL('https://example.com/scope2/scope3/foo.mjs');
|
||||
|
||||
it('should fall back to "imports" when none match', () => {
|
||||
expect(resolveUnderTest('a', scope1URL)).toMatchURL('https://example.com/a-1.mjs');
|
||||
expect(resolveUnderTest('b', scope1URL)).toMatchURL('https://example.com/b-1.mjs');
|
||||
expect(resolveUnderTest('c', scope1URL)).toMatchURL('https://example.com/c-1.mjs');
|
||||
});
|
||||
|
||||
it('should use a direct scope override', () => {
|
||||
expect(resolveUnderTest('a', scope2URL)).toMatchURL('https://example.com/a-2.mjs');
|
||||
expect(resolveUnderTest('b', scope2URL)).toMatchURL('https://example.com/b-1.mjs');
|
||||
expect(resolveUnderTest('c', scope2URL)).toMatchURL('https://example.com/c-1.mjs');
|
||||
});
|
||||
|
||||
it('should use an indirect scope override', () => {
|
||||
expect(resolveUnderTest('a', scope3URL)).toMatchURL('https://example.com/a-2.mjs');
|
||||
expect(resolveUnderTest('b', scope3URL)).toMatchURL('https://example.com/b-3.mjs');
|
||||
expect(resolveUnderTest('c', scope3URL)).toMatchURL('https://example.com/c-1.mjs');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Relative URL scope keys', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"a": "/a-1.mjs",
|
||||
"b": "/b-1.mjs",
|
||||
"c": "/c-1.mjs"
|
||||
},
|
||||
"scopes": {
|
||||
"": {
|
||||
"a": "/a-empty-string.mjs"
|
||||
},
|
||||
"./": {
|
||||
"b": "/b-dot-slash.mjs"
|
||||
},
|
||||
"../": {
|
||||
"c": "/c-dot-dot-slash.mjs"
|
||||
}
|
||||
}
|
||||
}`);
|
||||
const inSameDirAsMap = new URL('./foo.mjs', mapBaseURL);
|
||||
const inDirAboveMap = new URL('../foo.mjs', mapBaseURL);
|
||||
|
||||
it('should resolve an empty string scope using the import map URL', () => {
|
||||
expect(resolveUnderTest('a', mapBaseURL)).toMatchURL('https://example.com/a-empty-string.mjs');
|
||||
expect(resolveUnderTest('a', inSameDirAsMap)).toMatchURL('https://example.com/a-1.mjs');
|
||||
});
|
||||
|
||||
it('should resolve a ./ scope using the import map URL\'s directory', () => {
|
||||
expect(resolveUnderTest('b', mapBaseURL)).toMatchURL('https://example.com/b-dot-slash.mjs');
|
||||
expect(resolveUnderTest('b', inSameDirAsMap)).toMatchURL('https://example.com/b-dot-slash.mjs');
|
||||
});
|
||||
|
||||
it('should resolve a ../ scope using the import map URL\'s directory', () => {
|
||||
expect(resolveUnderTest('c', mapBaseURL)).toMatchURL('https://example.com/c-dot-dot-slash.mjs');
|
||||
expect(resolveUnderTest('c', inSameDirAsMap)).toMatchURL('https://example.com/c-dot-dot-slash.mjs');
|
||||
expect(resolveUnderTest('c', inDirAboveMap)).toMatchURL('https://example.com/c-dot-dot-slash.mjs');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -1,270 +0,0 @@
|
|||
'use strict';
|
||||
const { URL } = require('url');
|
||||
const { parseFromString } = require('../lib/parser.js');
|
||||
const { resolve } = require('../lib/resolver.js');
|
||||
|
||||
const mapBaseURL = new URL('https://example.com/app/index.html');
|
||||
const scriptURL = new URL('https://example.com/js/app.mjs');
|
||||
|
||||
function makeResolveUnderTest(mapString) {
|
||||
const map = parseFromString(mapString, mapBaseURL);
|
||||
return specifier => resolve(specifier, map, scriptURL);
|
||||
}
|
||||
|
||||
describe('Unmapped', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{}`);
|
||||
|
||||
it('should resolve ./ specifiers as URLs', () => {
|
||||
expect(resolveUnderTest('./foo')).toMatchURL('https://example.com/js/foo');
|
||||
expect(resolveUnderTest('./foo/bar')).toMatchURL('https://example.com/js/foo/bar');
|
||||
expect(resolveUnderTest('./foo/../bar')).toMatchURL('https://example.com/js/bar');
|
||||
expect(resolveUnderTest('./foo/../../bar')).toMatchURL('https://example.com/bar');
|
||||
});
|
||||
|
||||
it('should resolve ../ specifiers as URLs', () => {
|
||||
expect(resolveUnderTest('../foo')).toMatchURL('https://example.com/foo');
|
||||
expect(resolveUnderTest('../foo/bar')).toMatchURL('https://example.com/foo/bar');
|
||||
expect(resolveUnderTest('../../../foo/bar')).toMatchURL('https://example.com/foo/bar');
|
||||
});
|
||||
|
||||
it('should resolve / specifiers as URLs', () => {
|
||||
expect(resolveUnderTest('/foo')).toMatchURL('https://example.com/foo');
|
||||
expect(resolveUnderTest('/foo/bar')).toMatchURL('https://example.com/foo/bar');
|
||||
expect(resolveUnderTest('/../../foo/bar')).toMatchURL('https://example.com/foo/bar');
|
||||
expect(resolveUnderTest('/../foo/../bar')).toMatchURL('https://example.com/bar');
|
||||
});
|
||||
|
||||
it('should parse absolute fetch-scheme URLs', () => {
|
||||
expect(resolveUnderTest('about:good')).toMatchURL('about:good');
|
||||
expect(resolveUnderTest('https://example.net')).toMatchURL('https://example.net/');
|
||||
expect(resolveUnderTest('https://ex%41mple.com/')).toMatchURL('https://example.com/');
|
||||
expect(resolveUnderTest('https:example.org')).toMatchURL('https://example.org/');
|
||||
expect(resolveUnderTest('https://///example.com///')).toMatchURL('https://example.com///');
|
||||
});
|
||||
|
||||
it('should fail for absolute non-fetch-scheme URLs', () => {
|
||||
expect(() => resolveUnderTest('mailto:bad')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('import:bad')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('javascript:bad')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('wss:bad')).toThrow(TypeError);
|
||||
});
|
||||
|
||||
it('should fail for strings not parseable as absolute URLs and not starting with ./ ../ or /', () => {
|
||||
expect(() => resolveUnderTest('foo')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('\\foo')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest(':foo')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('@foo')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('%2E/foo')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('%2E%2E/foo')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('.%2Ffoo')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('https://ex ample.org/')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('https://example.com:demo')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('http://[www.example.com]/')).toThrow(TypeError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Mapped using the "imports" key only (no scopes)', () => {
|
||||
it('should fail when the mapping is to an empty array', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"moment": null,
|
||||
"lodash": []
|
||||
}
|
||||
}`);
|
||||
|
||||
expect(() => resolveUnderTest('moment')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('lodash')).toThrow(TypeError);
|
||||
});
|
||||
|
||||
describe('Package-like scenarios', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"moment": "/node_modules/moment/src/moment.js",
|
||||
"moment/": "/node_modules/moment/src/",
|
||||
"lodash-dot": "./node_modules/lodash-es/lodash.js",
|
||||
"lodash-dot/": "./node_modules/lodash-es/",
|
||||
"lodash-dotdot": "../node_modules/lodash-es/lodash.js",
|
||||
"lodash-dotdot/": "../node_modules/lodash-es/",
|
||||
"nowhere/": []
|
||||
}
|
||||
}`);
|
||||
|
||||
it('should work for package main modules', () => {
|
||||
expect(resolveUnderTest('moment')).toMatchURL('https://example.com/node_modules/moment/src/moment.js');
|
||||
expect(resolveUnderTest('lodash-dot')).toMatchURL('https://example.com/app/node_modules/lodash-es/lodash.js');
|
||||
expect(resolveUnderTest('lodash-dotdot')).toMatchURL('https://example.com/node_modules/lodash-es/lodash.js');
|
||||
});
|
||||
|
||||
it('should work for package submodules', () => {
|
||||
expect(resolveUnderTest('moment/foo')).toMatchURL('https://example.com/node_modules/moment/src/foo');
|
||||
expect(resolveUnderTest('lodash-dot/foo')).toMatchURL('https://example.com/app/node_modules/lodash-es/foo');
|
||||
expect(resolveUnderTest('lodash-dotdot/foo')).toMatchURL('https://example.com/node_modules/lodash-es/foo');
|
||||
});
|
||||
|
||||
it('should work for package names that end in a slash by just passing through', () => {
|
||||
// TODO: is this the right behavior, or should we throw?
|
||||
expect(resolveUnderTest('moment/')).toMatchURL('https://example.com/node_modules/moment/src/');
|
||||
});
|
||||
|
||||
it('should still fail for package modules that are not declared', () => {
|
||||
expect(() => resolveUnderTest('underscore/')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('underscore/foo')).toThrow(TypeError);
|
||||
});
|
||||
|
||||
it('should fail for package submodules that map to nowhere', () => {
|
||||
expect(() => resolveUnderTest('nowhere/foo')).toThrow(TypeError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Tricky specifiers', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"package/withslash": "/node_modules/package-with-slash/index.mjs",
|
||||
"not-a-package": "/lib/not-a-package.mjs",
|
||||
".": "/lib/dot.mjs",
|
||||
"..": "/lib/dotdot.mjs",
|
||||
"..\\\\": "/lib/dotdotbackslash.mjs",
|
||||
"%2E": "/lib/percent2e.mjs",
|
||||
"%2F": "/lib/percent2f.mjs"
|
||||
}
|
||||
}`);
|
||||
|
||||
it('should work for explicitly-mapped specifiers that happen to have a slash', () => {
|
||||
expect(resolveUnderTest('package/withslash')).toMatchURL('https://example.com/node_modules/package-with-slash/index.mjs');
|
||||
});
|
||||
|
||||
it('should work when the specifier has punctuation', () => {
|
||||
expect(resolveUnderTest('.')).toMatchURL('https://example.com/lib/dot.mjs');
|
||||
expect(resolveUnderTest('..')).toMatchURL('https://example.com/lib/dotdot.mjs');
|
||||
expect(resolveUnderTest('..\\')).toMatchURL('https://example.com/lib/dotdotbackslash.mjs');
|
||||
expect(resolveUnderTest('%2E')).toMatchURL('https://example.com/lib/percent2e.mjs');
|
||||
expect(resolveUnderTest('%2F')).toMatchURL('https://example.com/lib/percent2f.mjs');
|
||||
});
|
||||
|
||||
it('should fail for attempting to get a submodule of something not declared with a trailing slash', () => {
|
||||
expect(() => resolveUnderTest('not-a-package/foo')).toThrow(TypeError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('URL-like specifiers', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"/node_modules/als-polyfill/index.mjs": "std:kv-storage",
|
||||
|
||||
"/lib/foo.mjs": "./more/bar.mjs",
|
||||
"./dotrelative/foo.mjs": "/lib/dot.mjs",
|
||||
"../dotdotrelative/foo.mjs": "/lib/dotdot.mjs",
|
||||
|
||||
"/lib/no.mjs": null,
|
||||
"./dotrelative/no.mjs": [],
|
||||
|
||||
"/": "/lib/slash-only/",
|
||||
"./": "/lib/dotslash-only/",
|
||||
|
||||
"/test/": "/lib/url-trailing-slash/",
|
||||
"./test/": "/lib/url-trailing-slash-dot/",
|
||||
|
||||
"/test": "/lib/test1.mjs",
|
||||
"../test": "/lib/test2.mjs"
|
||||
}
|
||||
}`);
|
||||
|
||||
it('should remap to other URLs', () => {
|
||||
expect(resolveUnderTest('https://example.com/lib/foo.mjs')).toMatchURL('https://example.com/app/more/bar.mjs');
|
||||
expect(resolveUnderTest('https://///example.com/lib/foo.mjs')).toMatchURL('https://example.com/app/more/bar.mjs');
|
||||
expect(resolveUnderTest('/lib/foo.mjs')).toMatchURL('https://example.com/app/more/bar.mjs');
|
||||
|
||||
expect(resolveUnderTest('https://example.com/app/dotrelative/foo.mjs')).toMatchURL('https://example.com/lib/dot.mjs');
|
||||
expect(resolveUnderTest('../app/dotrelative/foo.mjs')).toMatchURL('https://example.com/lib/dot.mjs');
|
||||
|
||||
expect(resolveUnderTest('https://example.com/dotdotrelative/foo.mjs')).toMatchURL('https://example.com/lib/dotdot.mjs');
|
||||
expect(resolveUnderTest('../dotdotrelative/foo.mjs')).toMatchURL('https://example.com/lib/dotdot.mjs');
|
||||
});
|
||||
|
||||
it('should fail for URLs that remap to empty arrays', () => {
|
||||
expect(() => resolveUnderTest('https://example.com/lib/no.mjs')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('/lib/no.mjs')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('../lib/no.mjs')).toThrow(TypeError);
|
||||
|
||||
expect(() => resolveUnderTest('https://example.com/app/dotrelative/no.mjs')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('/app/dotrelative/no.mjs')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('../app/dotrelative/no.mjs')).toThrow(TypeError);
|
||||
});
|
||||
|
||||
it('should remap URLs that are just composed from / and .', () => {
|
||||
expect(resolveUnderTest('https://example.com/')).toMatchURL('https://example.com/lib/slash-only/');
|
||||
expect(resolveUnderTest('/')).toMatchURL('https://example.com/lib/slash-only/');
|
||||
expect(resolveUnderTest('../')).toMatchURL('https://example.com/lib/slash-only/');
|
||||
|
||||
expect(resolveUnderTest('https://example.com/app/')).toMatchURL('https://example.com/lib/dotslash-only/');
|
||||
expect(resolveUnderTest('/app/')).toMatchURL('https://example.com/lib/dotslash-only/');
|
||||
expect(resolveUnderTest('../app/')).toMatchURL('https://example.com/lib/dotslash-only/');
|
||||
});
|
||||
|
||||
it('should remap URLs that are prefix-matched by keys with trailing slashes', () => {
|
||||
expect(resolveUnderTest('/test/foo.mjs')).toMatchURL('https://example.com/lib/url-trailing-slash/foo.mjs');
|
||||
expect(resolveUnderTest('https://example.com/app/test/foo.mjs')).toMatchURL('https://example.com/lib/url-trailing-slash-dot/foo.mjs');
|
||||
});
|
||||
|
||||
it('should use the last entry\'s address when URL-like specifiers parse to the same absolute URL', () => {
|
||||
expect(resolveUnderTest('/test')).toMatchURL('https://example.com/lib/test2.mjs');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Overlapping entries with trailing slashes', () => {
|
||||
it('should favor the most-specific key (no empty arrays)', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"a": "/1",
|
||||
"a/": "/2/",
|
||||
"a/b": "/3",
|
||||
"a/b/": "/4/"
|
||||
}
|
||||
}`);
|
||||
|
||||
expect(resolveUnderTest('a')).toMatchURL('https://example.com/1');
|
||||
expect(resolveUnderTest('a/')).toMatchURL('https://example.com/2/');
|
||||
expect(resolveUnderTest('a/b')).toMatchURL('https://example.com/3');
|
||||
expect(resolveUnderTest('a/b/')).toMatchURL('https://example.com/4/');
|
||||
expect(resolveUnderTest('a/b/c')).toMatchURL('https://example.com/4/c');
|
||||
});
|
||||
|
||||
it('should favor the most-specific key when empty arrays are involved for less-specific keys', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"a": [],
|
||||
"a/": [],
|
||||
"a/b": "/3",
|
||||
"a/b/": "/4/"
|
||||
}
|
||||
}`);
|
||||
|
||||
expect(() => resolveUnderTest('a')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('a/')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('a/x')).toThrow(TypeError);
|
||||
expect(resolveUnderTest('a/b')).toMatchURL('https://example.com/3');
|
||||
expect(resolveUnderTest('a/b/')).toMatchURL('https://example.com/4/');
|
||||
expect(resolveUnderTest('a/b/c')).toMatchURL('https://example.com/4/c');
|
||||
expect(() => resolveUnderTest('a/x/c')).toThrow(TypeError);
|
||||
});
|
||||
|
||||
it('should favor the most-specific key when empty arrays are involved for more-specific keys', () => {
|
||||
const resolveUnderTest = makeResolveUnderTest(`{
|
||||
"imports": {
|
||||
"a": "/1",
|
||||
"a/": "/2/",
|
||||
"a/b": [],
|
||||
"a/b/": []
|
||||
}
|
||||
}`);
|
||||
|
||||
expect(resolveUnderTest('a')).toMatchURL('https://example.com/1');
|
||||
expect(resolveUnderTest('a/')).toMatchURL('https://example.com/2/');
|
||||
expect(resolveUnderTest('a/x')).toMatchURL('https://example.com/2/x');
|
||||
expect(() => resolveUnderTest('a/b')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('a/b/')).toThrow(TypeError);
|
||||
expect(() => resolveUnderTest('a/b/c')).toThrow(TypeError);
|
||||
expect(resolveUnderTest('a/x/c')).toMatchURL('https://example.com/2/x/c');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,5 +0,0 @@
|
|||
def main(request, response):
|
||||
return (
|
||||
(('Content-Type', 'text/javascript'),),
|
||||
'import "{}";\n'.format(request.GET.first('url'))
|
||||
)
|
|
@ -1,132 +0,0 @@
|
|||
// Hacky glue code to run Jest-based tests as WPT tests.
|
||||
// TODO(https://github.com/WICG/import-maps/issues/170): Consider better ways
|
||||
// to write and run tests.
|
||||
|
||||
setup({allow_uncaught_exception : true});
|
||||
|
||||
const exports = {};
|
||||
|
||||
function require(name) {
|
||||
return Object.assign({
|
||||
'URL': URL,
|
||||
'parseFromString': parseFromString,
|
||||
'resolve': resolve,
|
||||
'BUILT_IN_MODULE_SCHEME': 'std'
|
||||
}, exports);
|
||||
}
|
||||
|
||||
// Sort keys and then stringify for comparison.
|
||||
function stringifyImportMap(importMap) {
|
||||
function getKeys(m) {
|
||||
if (typeof m !== 'object')
|
||||
return [];
|
||||
|
||||
let keys = [];
|
||||
for (const key in m) {
|
||||
keys.push(key);
|
||||
keys = keys.concat(getKeys(m[key]));
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
return JSON.stringify(importMap, getKeys(importMap).sort());
|
||||
}
|
||||
|
||||
function expect(v) {
|
||||
return {
|
||||
toMatchURL: expected => assert_equals(v, expected),
|
||||
toThrow: expected => {
|
||||
if (v.localName === 'iframe') {
|
||||
// `v` is the result of parseFromString(), and thus toThrow()
|
||||
// should be examining the error in that iframe.
|
||||
assert_throws_js(v.contentWindow[expected], () => { throw v.contentWindow.windowError });
|
||||
} else if (expected.test && expected.test('not yet implemented')) {
|
||||
// We override /not yet implemented/ expectation.
|
||||
assert_throws_js(TypeError, v);
|
||||
} else {
|
||||
assert_throws_js(expected, v);
|
||||
}
|
||||
},
|
||||
toEqual: expected => {
|
||||
if (v.localName === 'iframe') {
|
||||
// `v` is the result of parseFromString(), and thus toEqual() is
|
||||
// expected to compare parsed import maps.
|
||||
// We sort keys when stringifying for normalization.
|
||||
const actualParsedImportMap = JSON.parse(
|
||||
internals.getParsedImportMap(v.contentDocument));
|
||||
assert_equals(
|
||||
stringifyImportMap(actualParsedImportMap),
|
||||
stringifyImportMap(expected)
|
||||
);
|
||||
} else {
|
||||
assert_object_equals(v, expected);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
expect.toMatchURL = expected => expected;
|
||||
|
||||
const test_harness_test = test;
|
||||
test = it;
|
||||
|
||||
let current_message = '';
|
||||
function describe(message, f) {
|
||||
const old = current_message;
|
||||
if (current_message !== '') {
|
||||
current_message += ' / ';
|
||||
}
|
||||
current_message += message;
|
||||
f();
|
||||
current_message = old;
|
||||
}
|
||||
function it(message, f) {
|
||||
const old = current_message;
|
||||
if (current_message !== '') {
|
||||
current_message += ' / ';
|
||||
}
|
||||
current_message += message;
|
||||
test_harness_test(t => t.step_func(f)(), current_message);
|
||||
current_message = old;
|
||||
}
|
||||
|
||||
// Creates a new Document (via <iframe>) and add an inline import map.
|
||||
// Currently document.write() is used to make everything synchronous, which
|
||||
// is just needed for running the existing Jest-based tests easily.
|
||||
function parseFromString(mapString, mapBaseURL) {
|
||||
// We can't test data: base URLs because <base> rejects data: URLs.
|
||||
if (new URL(mapBaseURL).protocol === 'data:') {
|
||||
throw Error('test helper does not support data: base URLs');
|
||||
}
|
||||
|
||||
const iframe = document.createElement('iframe');
|
||||
document.body.appendChild(iframe);
|
||||
iframe.contentDocument.write(`
|
||||
<base href="${mapBaseURL}">
|
||||
<script>
|
||||
var scriptError;
|
||||
var windowError;
|
||||
function onScriptError(event) {
|
||||
scriptError = event.error;
|
||||
}
|
||||
function onWindowError(event) {
|
||||
windowError = event.error;
|
||||
return false;
|
||||
}
|
||||
window.addEventListener('error', onWindowError);
|
||||
</sc` + `ript>
|
||||
<script type="importmap" onerror="onScriptError(event)">
|
||||
${mapString}
|
||||
</sc` + `ript>
|
||||
`);
|
||||
iframe.contentDocument.close();
|
||||
|
||||
return iframe;
|
||||
}
|
||||
|
||||
// URL resolution is tested using Chromium's `internals`.
|
||||
// TODO(hiroshige): Remove the Chromium-specific dependency.
|
||||
function resolve(specifier, map, baseURL) {
|
||||
return internals.resolveModuleSpecifier(specifier,
|
||||
baseURL,
|
||||
map.contentDocument);
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Mixed-Content: Blockable content</title>
|
||||
<meta charset='utf-8'>
|
||||
<meta name="description" content="Test behavior of blockable content.">
|
||||
<link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
|
||||
<link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
|
||||
<meta name="assert" content="Mixed-Content: Expects blocked for sharedworker-classic to cross-http origin and keep-scheme redirection from https context.">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/common/security-features/resources/common.sub.js"></script>
|
||||
<script src="../../../../generic/test-case.sub.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
TestCase(
|
||||
{
|
||||
"expectation": "blocked",
|
||||
"origin": "cross-http",
|
||||
"redirection": "keep-scheme",
|
||||
"source_context_list": [],
|
||||
"source_scheme": "https",
|
||||
"subresource": "sharedworker-classic",
|
||||
"subresource_policy_deliveries": []
|
||||
},
|
||||
document.querySelector("meta[name=assert]").content,
|
||||
new SanityChecker()
|
||||
).start();
|
||||
</script>
|
||||
<div id="log"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1 +0,0 @@
|
|||
Content-Security-Policy: block-all-mixed-content
|
|
@ -1,34 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Mixed-Content: Blockable content</title>
|
||||
<meta charset='utf-8'>
|
||||
<meta name="description" content="Test behavior of blockable content.">
|
||||
<link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
|
||||
<link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
|
||||
<meta name="assert" content="Mixed-Content: Expects blocked for sharedworker-classic to cross-http origin and no-redirect redirection from https context.">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/common/security-features/resources/common.sub.js"></script>
|
||||
<script src="../../../../generic/test-case.sub.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
TestCase(
|
||||
{
|
||||
"expectation": "blocked",
|
||||
"origin": "cross-http",
|
||||
"redirection": "no-redirect",
|
||||
"source_context_list": [],
|
||||
"source_scheme": "https",
|
||||
"subresource": "sharedworker-classic",
|
||||
"subresource_policy_deliveries": []
|
||||
},
|
||||
document.querySelector("meta[name=assert]").content,
|
||||
new SanityChecker()
|
||||
).start();
|
||||
</script>
|
||||
<div id="log"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1 +0,0 @@
|
|||
Content-Security-Policy: block-all-mixed-content
|
|
@ -1,34 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Mixed-Content: Blockable content</title>
|
||||
<meta charset='utf-8'>
|
||||
<meta name="description" content="Test behavior of blockable content.">
|
||||
<link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
|
||||
<link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
|
||||
<meta name="assert" content="Mixed-Content: Expects blocked for sharedworker-classic to cross-http origin and swap-scheme redirection from https context.">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/common/security-features/resources/common.sub.js"></script>
|
||||
<script src="../../../../generic/test-case.sub.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
TestCase(
|
||||
{
|
||||
"expectation": "blocked",
|
||||
"origin": "cross-http",
|
||||
"redirection": "swap-scheme",
|
||||
"source_context_list": [],
|
||||
"source_scheme": "https",
|
||||
"subresource": "sharedworker-classic",
|
||||
"subresource_policy_deliveries": []
|
||||
},
|
||||
document.querySelector("meta[name=assert]").content,
|
||||
new SanityChecker()
|
||||
).start();
|
||||
</script>
|
||||
<div id="log"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1 +0,0 @@
|
|||
Content-Security-Policy: block-all-mixed-content
|
|
@ -1,34 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Mixed-Content: Blockable content</title>
|
||||
<meta charset='utf-8'>
|
||||
<meta name="description" content="Test behavior of blockable content.">
|
||||
<link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
|
||||
<link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
|
||||
<meta name="assert" content="Mixed-Content: Expects blocked for sharedworker-classic to cross-https origin and swap-scheme redirection from https context.">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/common/security-features/resources/common.sub.js"></script>
|
||||
<script src="../../../../generic/test-case.sub.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
TestCase(
|
||||
{
|
||||
"expectation": "blocked",
|
||||
"origin": "cross-https",
|
||||
"redirection": "swap-scheme",
|
||||
"source_context_list": [],
|
||||
"source_scheme": "https",
|
||||
"subresource": "sharedworker-classic",
|
||||
"subresource_policy_deliveries": []
|
||||
},
|
||||
document.querySelector("meta[name=assert]").content,
|
||||
new SanityChecker()
|
||||
).start();
|
||||
</script>
|
||||
<div id="log"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1 +0,0 @@
|
|||
Content-Security-Policy: block-all-mixed-content
|
|
@ -1,34 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Mixed-Content: Blockable content</title>
|
||||
<meta charset='utf-8'>
|
||||
<meta name="description" content="Test behavior of blockable content.">
|
||||
<link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
|
||||
<link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
|
||||
<meta name="assert" content="Mixed-Content: Expects blocked for sharedworker-classic to same-http origin and swap-scheme redirection from https context.">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/common/security-features/resources/common.sub.js"></script>
|
||||
<script src="../../../../generic/test-case.sub.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
TestCase(
|
||||
{
|
||||
"expectation": "blocked",
|
||||
"origin": "same-http",
|
||||
"redirection": "swap-scheme",
|
||||
"source_context_list": [],
|
||||
"source_scheme": "https",
|
||||
"subresource": "sharedworker-classic",
|
||||
"subresource_policy_deliveries": []
|
||||
},
|
||||
document.querySelector("meta[name=assert]").content,
|
||||
new SanityChecker()
|
||||
).start();
|
||||
</script>
|
||||
<div id="log"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1 +0,0 @@
|
|||
Content-Security-Policy: block-all-mixed-content
|
|
@ -1,34 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Mixed-Content: Blockable content</title>
|
||||
<meta charset='utf-8'>
|
||||
<meta name="description" content="Test behavior of blockable content.">
|
||||
<link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
|
||||
<link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
|
||||
<meta name="assert" content="Mixed-Content: Expects blocked for sharedworker-classic to same-https origin and swap-scheme redirection from https context.">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/common/security-features/resources/common.sub.js"></script>
|
||||
<script src="../../../../generic/test-case.sub.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
TestCase(
|
||||
{
|
||||
"expectation": "blocked",
|
||||
"origin": "same-https",
|
||||
"redirection": "swap-scheme",
|
||||
"source_context_list": [],
|
||||
"source_scheme": "https",
|
||||
"subresource": "sharedworker-classic",
|
||||
"subresource_policy_deliveries": []
|
||||
},
|
||||
document.querySelector("meta[name=assert]").content,
|
||||
new SanityChecker()
|
||||
).start();
|
||||
</script>
|
||||
<div id="log"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1 +0,0 @@
|
|||
Content-Security-Policy: block-all-mixed-content
|
|
@ -1,34 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Mixed-Content: Blockable content</title>
|
||||
<meta charset='utf-8'>
|
||||
<meta name="description" content="Test behavior of blockable content.">
|
||||
<link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
|
||||
<link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
|
||||
<meta name="assert" content="Mixed-Content: Expects blocked for sharedworker-module to cross-http origin and keep-scheme redirection from https context.">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/common/security-features/resources/common.sub.js"></script>
|
||||
<script src="../../../../generic/test-case.sub.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
TestCase(
|
||||
{
|
||||
"expectation": "blocked",
|
||||
"origin": "cross-http",
|
||||
"redirection": "keep-scheme",
|
||||
"source_context_list": [],
|
||||
"source_scheme": "https",
|
||||
"subresource": "sharedworker-module",
|
||||
"subresource_policy_deliveries": []
|
||||
},
|
||||
document.querySelector("meta[name=assert]").content,
|
||||
new SanityChecker()
|
||||
).start();
|
||||
</script>
|
||||
<div id="log"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1 +0,0 @@
|
|||
Content-Security-Policy: block-all-mixed-content
|
|
@ -1,34 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Mixed-Content: Blockable content</title>
|
||||
<meta charset='utf-8'>
|
||||
<meta name="description" content="Test behavior of blockable content.">
|
||||
<link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
|
||||
<link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
|
||||
<meta name="assert" content="Mixed-Content: Expects blocked for sharedworker-module to cross-http origin and no-redirect redirection from https context.">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/common/security-features/resources/common.sub.js"></script>
|
||||
<script src="../../../../generic/test-case.sub.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
TestCase(
|
||||
{
|
||||
"expectation": "blocked",
|
||||
"origin": "cross-http",
|
||||
"redirection": "no-redirect",
|
||||
"source_context_list": [],
|
||||
"source_scheme": "https",
|
||||
"subresource": "sharedworker-module",
|
||||
"subresource_policy_deliveries": []
|
||||
},
|
||||
document.querySelector("meta[name=assert]").content,
|
||||
new SanityChecker()
|
||||
).start();
|
||||
</script>
|
||||
<div id="log"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1 +0,0 @@
|
|||
Content-Security-Policy: block-all-mixed-content
|
|
@ -1,34 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Mixed-Content: Blockable content</title>
|
||||
<meta charset='utf-8'>
|
||||
<meta name="description" content="Test behavior of blockable content.">
|
||||
<link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
|
||||
<link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
|
||||
<meta name="assert" content="Mixed-Content: Expects blocked for sharedworker-module to cross-http origin and swap-scheme redirection from https context.">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/common/security-features/resources/common.sub.js"></script>
|
||||
<script src="../../../../generic/test-case.sub.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
TestCase(
|
||||
{
|
||||
"expectation": "blocked",
|
||||
"origin": "cross-http",
|
||||
"redirection": "swap-scheme",
|
||||
"source_context_list": [],
|
||||
"source_scheme": "https",
|
||||
"subresource": "sharedworker-module",
|
||||
"subresource_policy_deliveries": []
|
||||
},
|
||||
document.querySelector("meta[name=assert]").content,
|
||||
new SanityChecker()
|
||||
).start();
|
||||
</script>
|
||||
<div id="log"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1 +0,0 @@
|
|||
Content-Security-Policy: block-all-mixed-content
|
|
@ -1,34 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- DO NOT EDIT! Generated by `common/security-features/tools/generate.py --spec mixed-content/` -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Mixed-Content: Blockable content</title>
|
||||
<meta charset='utf-8'>
|
||||
<meta name="description" content="Test behavior of blockable content.">
|
||||
<link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
|
||||
<link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
|
||||
<meta name="assert" content="Mixed-Content: Expects blocked for sharedworker-module to cross-https origin and swap-scheme redirection from https context.">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/common/security-features/resources/common.sub.js"></script>
|
||||
<script src="../../../../generic/test-case.sub.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
TestCase(
|
||||
{
|
||||
"expectation": "blocked",
|
||||
"origin": "cross-https",
|
||||
"redirection": "swap-scheme",
|
||||
"source_context_list": [],
|
||||
"source_scheme": "https",
|
||||
"subresource": "sharedworker-module",
|
||||
"subresource_policy_deliveries": []
|
||||
},
|
||||
document.querySelector("meta[name=assert]").content,
|
||||
new SanityChecker()
|
||||
).start();
|
||||
</script>
|
||||
<div id="log"></div>
|
||||
</body>
|
||||
</html>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue